Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced a textual listing of instruments. #832

Merged
merged 4 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions data/templates/instrument_list_textual.tt2
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<th>Current Status</th>
<th>Status Comment</th>
<th>Laboratory</th>
<th>Staging Volume</th>
</tr>
</thead>
<tbody>
Expand All @@ -26,6 +27,7 @@
<td>[% instrument.current_instrument_status.instrument_status_dict.description %]</td>
<td>[% instrument.current_instrument_status.comment %]</td>
<td>[% instrument.lab %]</td>
<td>[% instrument.recent_staging_volumes.join(', ') %]</td>
</tr>
[% END %]
</tbody>
Expand Down
97 changes: 59 additions & 38 deletions lib/npg/model/instrument.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ package npg::model::instrument;

use strict;
use warnings;
use base qw(npg::model);
use English qw(-no_match_vars);
use File::Spec;
use Carp;
use DateTime;
use DateTime::Duration;
use DateTime::Format::MySQL;
use List::MoreUtils qw(any uniq);
use base qw(npg::model);

use npg::model::user;
use npg::model::run;
use npg::model::instrument_format;
Expand All @@ -15,10 +21,6 @@ use npg::model::instrument_annotation;
use npg::model::annotation;
use npg::model::instrument_designation;
use npg::model::designation;
use DateTime;
use DateTime::Duration;
use DateTime::Format::MySQL;
use List::MoreUtils qw/any/;

our $VERSION = '0';

Expand Down Expand Up @@ -380,6 +382,42 @@ sub latest_annotation {
return $self->{latest_annotation};
}

sub recent_staging_volumes {
my $self = shift;

my $run_status = q[run in progress];
my $query = q[SELECT folder_path_glob FROM instrument
JOIN run USING(id_instrument)
JOIN run_status USING(id_run)
JOIN run_status_dict USING(id_run_status_dict)
WHERE folder_path_glob IS NOT NULL
AND LENGTH(folder_path_glob) != 0
AND id_instrument=? AND description=?
ORDER BY date DESC];
my $dbh = $self->util->dbh();
# Four rather than two latest runs since NovaSeq(X) instruments have
# two sides, which write to the same staging server.
my $rows = $dbh->selectall_arrayref($query, {RaiseError => 1, MaxRows => 4},
$self->id_instrument(), $run_status);
my @globs = uniq map { $_->[0] } @{$rows};
# We do not need more that two unique globs.
while (scalar @globs > 2) {
pop @globs
}
Copy link
Member

@dkj dkj Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ORDER BY date DESC];
my $dbh = $self->util->dbh();
# Four rather than two latest runs since NovaSeq(X) instruments have
# two sides, which write to the same staging server.
my $rows = $dbh->selectall_arrayref($query, {RaiseError => 1, MaxRows => 4},
$self->id_instrument(), $run_status);
my @globs = uniq map { $_->[0] } @{$rows};
# We do not need more that two unique globs.
while (scalar @globs > 2) {
pop @globs
}
ORDER BY date DESC
LIMIT 4 ];
my $dbh = $self->util->dbh();
# Four rather than two latest runs since NovaSeq(X) instruments have
# two sides, which write to the same staging server.
my $rows = $dbh->selectall_arrayref($query, {RaiseError => 1, MaxRows => 4},
$self->id_instrument(), $run_status);
my @globs = uniq map { $_->[0] } @{$rows};
# We do not need more that two unique globs.
while (scalar @globs > 2) {
pop @globs
}

Probably not worth it! (Thinking aloud...)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is to limit to 4 rows, then it is aleady done by MaxRows => 4


my @volumes = ();
foreach my $area (@globs) {
my @dirs = File::Spec->splitdir($area);
# Current (May 2024) folder path globs look like
# /{export,nfs}/esa-sv-20201215-03/IL_seq_data/*/
##no critic (ValuesAndExpressions::ProhibitMagicNumbers)
push @volumes, (@dirs >= 3 and $dirs[0] eq q[]) ? $dirs[2] : $area;
##use critic
}

return @volumes;
}

sub does_sequencing {
my $self = shift;
return ($self->instrument_format->model &&
Expand Down Expand Up @@ -595,9 +633,9 @@ npg::model::instrument

=head1 DESCRIPTION
Clearpress model for an instrument.
To be replaced by DBIx model. Contains duplicates of functions in
npg_tracking::Schema::Result::Instrument. When editing the code
of this module consider if any changes are meeded in the other module.
Contains duplicates of functions in npg_tracking::Schema::Result::Instrument.
When editing the code of this module consider if any changes are needed in
the other module.

=head1 SUBROUTINES/METHODS

Expand All @@ -621,11 +659,6 @@ npg::model::instrument

my $arAllInstruments = $oInstrument->instruments();

=head2 instrument_by_ipaddr - npg::model::instrument by its IP address

my $oInstrument = $oInstrument->instrument_by_ipaddr('127.0.0.1');
instrument_by_instrument_comp

=head2 instrument_by_instrument_comp - npg::model::instrument by its instrument_comp name

=head2 current_instruments - arrayref of all npg::model::instruments with iscurrent=1
Expand All @@ -637,16 +670,6 @@ instrument_by_instrument_comp
my $lab = 'Sulston';
my $arCurrentSulstonInstruments = $oInstrument->current_instruments_from_lab($lab);

=head2 last_wash_instrument_status - npg::model::instrument_status (or undef) corresponding to the last 'wash performed' state

my $oInstrumentStatus = $oInstrument->last_wash_instrument_status();

=head2 check_wash_status - boolean whether this instrument needs washing

Has a side-effect of updating an instrument's current instrument_status to 'wash required'

$bNeedAWash = $oInstrument->check_wash_status();

=head2 runs - arrayref of npg::model::runs for this instrument

my $arRuns = $oInstrument->runs();
Expand Down Expand Up @@ -719,6 +742,10 @@ Has a side-effect of updating an instrument's current instrument_status to 'wash

=head2 fc_slots2blocking_runs - a hash reference mapping instrument flowcell slots to blocking runs; tags for slots are used as keys

=head2 recent_staging_volumes - returns a list of names of staging volumes
this instrument most recently transferred data to, most recently used volume
first. The list might be empty and cannot have more than two volume names.

=head2 does_sequencing - returns true is the instrument does sequencing, false otherwise

=head2 is_two_slot_instrument - returns true if this instrument has two slots, false otherwise
Expand All @@ -729,7 +756,7 @@ returns true if the instrument is a MiSeq, false otherwise

=head2 is_cbot_instrument - returns true if this instrument is CBot, false otherwise

=head2 current_run_by_id - returns one of current runs with teh argument id or nothing if a list of current runs does not contain a run with this id
=head2 current_run_by_id - returns one of current runs with the argument id or nothing if a list of current runs does not contain a run with this id

my $id_run = 22;
my $run = $oInstrument->current_run_by_id($id_run);
Expand Down Expand Up @@ -761,27 +788,21 @@ returns true if the instrument is a MiSeq, false otherwise

=item base

=item npg::model
=item File::Spec

=item English

=item Carp

=item npg::model::user

=item npg::model::run

=item npg::model::instrument_format

=item npg::model::instrument_status
=item Readonly

=item npg::model::instrument_status_dict
=item DateTime

=item npg::model::instrument_mod
=item DateTime::Duration

=item DateTime
=item DateTime::Format::MySQL

=item Readonly
=item List::MoreUtils

=back

Expand All @@ -793,15 +814,15 @@ returns true if the instrument is a MiSeq, false otherwise

=over

=item Roger Pettett, E<lt>[email protected]<gt>
=item Roger Pettett

=item Marina Gourtovaia

=back

=head1 LICENSE AND COPYRIGHT

Copyright (C) 2006,2008,2013,2014,2016,2018,2021 Genome Research Ltd.
Copyright (C) 2006,2008,2013,2014,2016,2018,2021,2024 Genome Research Ltd.

This file is part of NPG.

Expand Down
85 changes: 81 additions & 4 deletions t/10-model-instrument.t
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use strict;
use warnings;
use t::util;
use Test::More tests => 141;
use Test::More tests => 142;
use Test::Deep;
use Test::Exception;

Expand Down Expand Up @@ -191,7 +191,6 @@ my $util = t::util->new({ fixtures => 1 });
qq[status changed automatically to "$auto_status"]);
}


{
my $instr = npg::model::instrument->new({
util => $util,
Expand Down Expand Up @@ -312,7 +311,6 @@ lives_ok {$util->fixtures_path(q[t/data/fixtures]); $util->load_fixtures;} 'a fr
ok (!$model->autochange_status_if_needed('analysis in progress'), 'no autochange status');
}


{
my $model = npg::model::instrument->new({util => $util, id_instrument => 36,});
ok($model->is_two_slot_instrument, 'is two_slot instrument');
Expand Down Expand Up @@ -351,7 +349,6 @@ lives_ok {$util->fixtures_path(q[t/data/fixtures]); $util->load_fixtures;} 'a fr
cmp_deeply($model->fc_slots2blocking_runs, {fc_slotA => [], fc_slotB => [],}, 'empty mapping of both slots to blocking runs');
}


{
my $run = npg::model::run->new({util => $util, id_run => 9950,});
$run->id_instrument(36);
Expand Down Expand Up @@ -421,4 +418,84 @@ lives_ok {$util->fixtures_path(q[t/data/fixtures]); $util->load_fixtures;} 'a fr
is (scalar @{$model->instrument_statuses()}, 3, 'number of statuses in total');
}

subtest 'recent staging volumes list' => sub {
plan tests => 14;

my $util4updates = t::util->new(); # need a new db handle
lives_ok {$util4updates->load_fixtures;} 'a fresh set of fixtures is loaded';
my $dbh = $util4updates->dbh;
$dbh->{AutoCommit} = 1;
$dbh->{RaiseError} = 1;

my $status = 'run in progress';

my $model = npg::model::instrument->new({
util => $util,
id_instrument => 3,
});
is (join(q[ ], $model->recent_staging_volumes()), q[esa-sv-20201215-03],
qq[volume name for a single run that is associated with the "$status" status]);

$model = npg::model::instrument->new({
util => $util,
id_instrument => 14,
});
is (scalar $model->recent_staging_volumes(), 0,
'empty list since no glob is available for a run that is associated with ' .
qq[the "$status" status]);

$model = npg::model::instrument->new({
util => $util,
id_instrument => 13,
});
is (join(q[,], $model->recent_staging_volumes()), 'esa-sv-20201215-02',
'a list with one volume name');

my $new_glob = q[{export,nfs}/esa-sv-20201215-02/IL_seq_data/*/];
my $update = qq[update run set folder_path_glob='$new_glob' where id_run=15];
ok($dbh->do($update), 'folder path glob is updated');
$model = npg::model::instrument->new({
util => $util,
id_instrument => 13,
});
is (join(q[,], $model->recent_staging_volumes()), $new_glob,
'a full glob is returned');

$new_glob = q[/{export,nfs}];
$update = qq[update run set folder_path_glob='$new_glob' where id_run=15];
ok($dbh->do($update), 'folder path glob is updated');
$model = npg::model::instrument->new({
util => $util,
id_instrument => 13,
});
is (join(q[,], $model->recent_staging_volumes()), $new_glob,
'a full glob is returned');

$update = qq[update run set folder_path_glob='' where id_run=15];
ok($dbh->do($update), 'folder path glob is updated');
$model = npg::model::instrument->new({
util => $util,
id_instrument => 13,
});
is (scalar $model->recent_staging_volumes(), 0,
'an empty list is returned for a zero length glob');

$update = q[update run_status set id_run_status_dict=2 where ] .
q[id_run in (3,4,5) and id_run_status_dict=4];
ok($dbh->do($update), 'run statuses are updated');
$update = qq[update run set folder_path_glob='volume5' where id_run=15];
ok($dbh->do($update), 'folder path glob is updated');
$update = qq[update run set id_instrument=3 where id_run=15];
ok($dbh->do($update), 'assign one more run to the instrument');

$model = npg::model::instrument->new({
util => $util,
id_instrument => 3,
});
is (join(q[, ], $model->recent_staging_volumes()), q[volume5, /{export,nfs}],
'latest volumes list');

$dbh->disconnect;
};

1;
Loading
Loading