diff --git a/Build.PL b/Build.PL index 40ed8a70..2a9b5f6a 100644 --- a/Build.PL +++ b/Build.PL @@ -91,12 +91,9 @@ my $builder = $class->new( 'build_requires' => { 'ExtUtils::CBuilder' => 0, - 'Archive::Tar' => 0, 'DateTime::Duration' => 0, 'DateTime::Format::SQLite' => 0, 'HTTP::Headers' => 0, - 'IO::File' => 0, - 'IPC::Open2' => 0, 'List::Util' => 0, 'Test::Compile' => 0, 'Test::Distribution' => 0, diff --git a/Changes b/Changes index 28e268b9..22f02f48 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,17 @@ LIST OF CHANGES + - npg_tracking::illumina::run::short_info + - Stopped parsing out run details from the run folder name. Deleted + attributes, which were populated this way: 'name', 'instrument_string', + 'slot', 'flowcell_id'. + - Deleted 'short_reference' method. + - npg_tracking::illumina::run::folder + - Removed dependency on 'short_reference' method, which used to be + provided by npg_tracking::illumina::run::short_info. + - Introduce a check to ensure that the run folder name on staging and + in the database, when both are available, are the same. + release 100.0.1 - For aggregation of lims objects by library in st::api::lims, do not consider the same library with different tag index in the same lane diff --git a/MANIFEST b/MANIFEST index 9cdfc37c..cacc1d62 100644 --- a/MANIFEST +++ b/MANIFEST @@ -418,7 +418,6 @@ t/80-npg_tracking-report-events.t t/80-npg_tracking-report-event2followers.t t/80-npg_tracking-report-event2subscribers.t t/data/schema.txt -t/data/090414_IL24_2726.tar.bz2 t/data/dbic_fixtures/000-Designation.yml t/data/dbic_fixtures/000-EntityType.yml t/data/dbic_fixtures/000-InstrumentModDict.yml diff --git a/lib/npg_tracking/illumina/run/folder.pm b/lib/npg_tracking/illumina/run/folder.pm index 84789492..73f4c772 100644 --- a/lib/npg_tracking/illumina/run/folder.pm +++ b/lib/npg_tracking/illumina/run/folder.pm @@ -101,19 +101,45 @@ sub _build_runfolder_path { my $path = $self->_get_path_from_given_path(); $path && return $path; - # get info form DB if there - could be better integrated.... - if ($self->npg_tracking_schema() and + my $db_runfolder_name; + my $runfolder_name; + if ( $self->can('run_folder') and $self->has_run_folder ) { + $runfolder_name = $self->run_folder; + } + + if ( $self->npg_tracking_schema() and $self->can(q(id_run)) and $self->id_run() ) { - if (! $self->tracking_run->is_tag_set(q(staging))) { - croak q{NPG tracking reports run }.$self->id_run().q{ no longer on staging} + if (not $self->tracking_run->is_tag_set(q(staging))) { + croak sprintf 'NPG tracking reports run %i no longer on staging', + $self->id_run; } - if (my $gpath = $self->tracking_run->folder_path_glob and - my $fname = $self->tracking_run->folder_name) { - return $self->_get_path_from_glob_pattern(catfile($gpath, $fname)); + $db_runfolder_name = $self->tracking_run->folder_name; + if ($db_runfolder_name) { + if (my $gpath = $self->tracking_run->folder_path_glob) { + $path = $self->_get_path_from_glob_pattern( + catfile($gpath, $db_runfolder_name) + ); + } } } - return $self->_get_path_from_short_reference(); + if ( (not $path) and $runfolder_name ) { + $path = $self->_get_path_from_glob_pattern( + $self->_folder_path_glob_pattern() . $runfolder_name + ); + } + + if ( $db_runfolder_name and $runfolder_name and + ($db_runfolder_name ne $runfolder_name) ) { + carp sprintf 'Inconsistent db and given run folder name: %s, %s', + $db_runfolder_name, $runfolder_name; + } + + if (not $path) { + croak 'Failed to infer runfolder_path'; + } + + return $path; } sub _build_analysis_path { @@ -230,6 +256,7 @@ sub _build_subpath { last; } } + return $path; } @@ -261,25 +288,6 @@ sub _infer_analysis_path { return catdir( @path_components ); } -sub _get_path_from_short_reference { - my ($self) = @_; - - if ( !$self->can(q(short_reference)) || !$self->short_reference() ) { - croak q{Not enough information to obtain the path}; - } - - # works out by 'glob'ing the filesystem, the path to the run_folder based on - # short_reference string - - my $sr = $self->short_reference(); - if ($sr =~ /\a(\d+)\z/xms) { - $sr = q{_{r,}} . $sr; - } - - return $self->_get_path_from_glob_pattern( - $self->_folder_path_glob_pattern() . q{*} . $sr . q[{,_*}]); -} - sub _get_path_from_glob_pattern { my ($self, $glob_pattern) = @_; @@ -368,14 +376,13 @@ npg_tracking::illumina::run::folder =head1 DESCRIPTION -This package might need to have something provide the short_reference method, +This package might need to have something provide the run_folder accessor either declared in your class or via inheritance from npg_tracking::illumina::run::short_info, which is the preferred option. -Failure to have provided a short_reference method might cause a run-time error +Failure to have provided the runfolder accessor might cause a run-time error if your class needs to obtain any paths where a path or subpath was not given and access to the tracking database is not available. -to glob for it). In addition to this, you can add an analysis_path, which is the path to the recalibrated directory, which will be used to construct other paths from. @@ -469,7 +476,7 @@ Might be undefined. =head1 LICENSE AND COPYRIGHT -Copyright (C) 2013,2014,2015,2018,2019,2020,2023 Genome Research Ltd. +Copyright (C) 2013,2014,2015,2018,2019,2020,2023,2024 Genome Research Ltd. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/npg_tracking/illumina/run/short_info.pm b/lib/npg_tracking/illumina/run/short_info.pm index 5e08a2a4..f40c5886 100644 --- a/lib/npg_tracking/illumina/run/short_info.pm +++ b/lib/npg_tracking/illumina/run/short_info.pm @@ -11,10 +11,6 @@ use npg_tracking::util::types; our $VERSION = '0'; -Readonly::Scalar my $INSTRUMENT_PATTERN => '(IL|HS|HX|HF|MS)'; -Readonly::Scalar my $NAME_PATTERN => $INSTRUMENT_PATTERN.'(\d+_)0*(\d+)'; -Readonly::Scalar my $LONG_FOLDER_NAME_SUFFIX_PATTERN => '_(A|B)_?([0-9A-Z]{9}(?:-\d{3}V\d)?)'; - has q{id_run} => ( isa => q{NpgTrackingRunId}, is => q{ro}, @@ -23,94 +19,36 @@ has q{id_run} => ( documentation => 'Integer identifier for a sequencing run', ); -has q{name} => ( - isa => q{Str}, - is => q{ro}, - required => 0, - lazy_build => 1, - documentation => join q[ ], - qw/String identifier for a sequencing run/, q[,], - qw/usually contains a sequencing instrument - identifer and the id_run attribute value/, -); - -has q{instrument_string} => ( - isa => q{Str}, - is => q{ro}, - lazy_build => 1, - documentation => q{Instrument name}, -); - -has q{slot} => ( - isa => q{Str}, - is => q{ro}, - lazy_build => 1, - writer => q{_set_slot}, - documentation => q{Instrument slot}, -); - -has q{flowcell_id} => ( - isa => q{Str}, - is => q{ro}, - lazy_build => 1, - writer => q{_set_flowcell_id}, - documentation => q{Flowcell identifier}, -); - -subtype __PACKAGE__.q(::folder) +my $run_folder_subtype_name = __PACKAGE__.q(::folder); +subtype $run_folder_subtype_name => as 'Str' - => where {splitdir($_)==1}; -coerce __PACKAGE__.q(::folder) - => from 'Str' - => via {first {$_ ne q()} reverse splitdir($_)}; + => where { splitdir($_)==1 }; + has q{run_folder} => ( - isa => __PACKAGE__.q(::folder), + isa => $run_folder_subtype_name, is => q{ro}, lazy_build => 1, documentation => 'Directory name of the run folder', ); -sub short_reference { - my ($self) = @_; - my $return_value = $self->has_run_folder() ? $self->run_folder() - : $self->has_id_run() ? $self->id_run() - : $self->name() - ; - return $return_value; -} - -############### -# private methods - -############### - sub _build_id_run { my ($self) = @_; - my $inst_t; - my $inst_i; my $id_run; - if ( !$self->has_run_folder() ) { - $self->run_folder(); - } - - # Try to read id_run from the folder name - ($inst_t, $inst_i, $id_run) = $self->run_folder() =~ /$NAME_PATTERN/gmsx; - - # Failing that try the tracking DB. - if ( !$id_run ) { - if ($self->can(q(npg_tracking_schema)) and $self->npg_tracking_schema()) { - my $rs = $self->npg_tracking_schema()->resultset('Run') - ->search({folder_name => $self->run_folder()}); - if ($rs->count == 1) { - $id_run = $rs->next()->id_run(); - } + if ($self->can(q(npg_tracking_schema)) and $self->npg_tracking_schema()) { + if (!$self->has_run_folder()) { + $self->run_folder(); # Force the build + } + my $rs = $self->npg_tracking_schema()->resultset('Run') + ->search({folder_name => $self->run_folder()}); + if ($rs->count == 1) { + $id_run = $rs->next()->id_run(); } } - # When no id_run is set (as in pick-up runs) attempt to parse an id_run from - # the experiment name recorded in the Illumina XML file. + # When no id_run is set, attempt to parse an id_run from the experiment name + # recorded in the Illumina XML file. # We embed additional information in NovaSeqX samplesheets which have no # meaning here. See L if ( !$id_run && $self->can('experiment_name') && $self->experiment_name() ) { @@ -130,55 +68,10 @@ sub _build_id_run { return $id_run; } -sub _build_name { - my ($self) = @_; - if( !( $self->has_id_run() || $self->has_run_folder() ) ) { - try { - $self->run_folder(); - } catch { - croak qq{Unable to obtain name from run_folder : $_}; - }; - } - my ($start, $middle, $end) = $self->run_folder() =~ /$NAME_PATTERN/xms; - croak q{Unrecognised format for run folder name: } . $self->run_folder() - if !( $start && $middle && $end ); - - return $start.$middle.$end; -} - -sub _build_instrument_string { - my ( $self ) = @_; - my ( $start, $end ) = $self->name() =~ /$INSTRUMENT_PATTERN(\d+)/xms; - return $start . $end; -} - -sub _build_slot { - my ( $self ) = @_; - $self->_hs_info(); - return $self->slot(); -} - -sub _build_flowcell_id { - my ( $self ) = @_; - $self->_hs_info(); - return $self->flowcell_id(); -} - -sub _hs_info { - my ( $self ) = @_; - - my @parts = $self->run_folder() =~ m/${NAME_PATTERN}$LONG_FOLDER_NAME_SUFFIX_PATTERN/xms; - my $flowcell_id = pop @parts; - $self->_set_flowcell_id( $flowcell_id || q{}); - my $slot = pop @parts; - $self->_set_slot( $slot || q{}); - - return 1; -} - no Moose::Role; 1; + __END__ =head1 NAME @@ -195,86 +88,37 @@ npg_tracking::illumina::run::short_info =head1 DESCRIPTION -This Moose role ties together three attributes, id_run, name and run_folder, -which are central to tracking Illumina sequencing runs at the institute and -processing sequencing data. - -The ability to infer two of these values given a third one relies on run folder -name following a certain string pattern. If access to a run tracking database -is available and the database contains relevant records, any non-empty string -can be used as a run folder name. Access to a run tracking database is made via -the npg_tracking_schema attribute, which can be provided by a class which -consumes this role. - -See npg_tracking::illumina::run::folder for an example implementation of the -npg_tracking_schema attribute. - -If your class consumes this role, you need either to provide the run_folder -attribute value on construction or implement a _build_run_folder method in your -class. Failure to do this WILL cause a run-time error along the lines of - - Mypackage does not support builder method '_build_run_folder' for attribute 'run_folder' - =head1 SUBROUTINES/METHODS =head2 id_run -An attribute, can be set in the constructor or lazy-built assuming that the -run_folder attribute value is available or can be built. - - my $oPackage = Mypackage->new(id_run => $id_run); - my $iIdRun = $oPackage->id_run(); +NPG run identifier. If the value is not supplied, an attempt to build it is +made. -=head2 name +If access to a run tracking database is available and the database contains +the run record and the run folder name is defined in the database record and +the run_folder attribute is defined or can be built, then its value is used +to retrieve the id_run value from the database. -An attribute, can be set in the constructor. It can also be lazy-built assuming -that id_run or run_folder was provided attribute value is available. -The ability to build this attribute without database support is not guaranteed. +Access to a run tracking database is made via the 'npg_tracking_schema' +attribute, which can be provided by a class which consumes this role. See +npg_tracking::illumina::run::folder for an example implementation of the +npg_tracking_schema attribute. - my $oPackage = Mypackage->new(name => $name); - my $sName = $oPackage->name(); +If 'experiment_name' accessor is provided by the class that inherits from +this role, then, in the absence of a database record, an attempt is made to parse +out run ID from the value returned by the 'experiment_name' accessor. See +npg_tracking::illumina::run::long_info for the implementation of this accessor. =head2 run_folder An attribute, can be set in the constructor or lazy-built. A class consuming -this role should provide a _build_run_folder method. Failure to provide a builder -will cause a run-time error. Constrained to not contain file-system path - -anything which looks like such a path will be coerced to the last component of the path. - - my $oPackage = Mypackage->new(run_folder => $run_folder); - my $sRunFolder = $oPackage->run_folder(); - -=head2 short_reference - -A method. Returns the first it finds from run_folder, id_run, name. - - my $ShortReference = $oPackage->short_reference(); - -No guarantee that this method is going to be supported in future releases. -Deriving classes should not use it. - -=head2 instrument_string - -An attribute, the name of the instrument, will be lazy-built, -usually no need to set it via a constructor. - - my $sInstrumentString = $oPackage->instrument_string(); - -=head2 slot - -An attribute, the name of the instrument slot, will be lazy-built, -usually no need to set it via a constructor. - - my $slot = $oPackage->slot(); - -=head2 flowcell_id - -An attribute, will be lazy-built, usually no need to set it -via a constructor. -If the machine is a HiSeq, the flowcell id that was used. -If the machine is a MiSeq, the reagent kit id that was used. +this role should provide a builder method '_build_run_folder'. Failure to +provide a builder might result in a run-time error. The attribute is constrained +to not contain a file-system path. - my $fid = $oPackage->flowcell_id(); +The implementation of the build method for this attribute should not try to +retrieve run record from the tracking database. =head1 DIAGNOSTICS @@ -314,7 +158,7 @@ If the machine is a MiSeq, the reagent kit id that was used. =head1 LICENSE AND COPYRIGHT -Copyright (C) 2018 GRL +Copyright (C) 2013,2014,2015,2016,2018,2023,2024 Genome Research Ltd. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/npg_tracking/illumina/runfolder.pm b/lib/npg_tracking/illumina/runfolder.pm index 5f108239..39e1939b 100644 --- a/lib/npg_tracking/illumina/runfolder.pm +++ b/lib/npg_tracking/illumina/runfolder.pm @@ -6,6 +6,7 @@ package npg_tracking::illumina::runfolder; # use Moose; +use MooseX::StrictConstructor; use namespace::autoclean; use Carp; use File::Spec; @@ -24,7 +25,6 @@ npg_tracking::illumina::runfolder my $oRunfolder = npg_tracking::illumina::runfolder->new( runfolder_path => '/staging/IL29/incoming/090721_IL29_3379/'); - my $name = $oRunfolder->name; # 090721_IL29_3379 my $id = $oRunfolder->id_run; # 3379 =head1 DESCRIPTION @@ -42,7 +42,7 @@ with 'npg_tracking::illumina::run::long_info'; sub _build_run_folder { my $self = shift; - ($self->subpath or $self->has_id_run or $self->has_name) + ($self->subpath or $self->has_id_run) or croak 'Need a path or id_run to work out a run_folder'; return first {$_ ne q()} reverse File::Spec->splitdir($self->runfolder_path); } @@ -61,6 +61,8 @@ __PACKAGE__->meta->make_immutable; =item Moose +=item MooseX::StrictConstructor + =item Carp =item File::Spec @@ -81,7 +83,7 @@ David K. Jackson, Edavid.jackson@sanger.ac.ukE =head1 LICENSE AND COPYRIGHT -Copyright (C) 2018 GRL +Copyright (C) 2018,2019,2024 Genome Research Ltd. This file is part of NPG. diff --git a/t/60-illumina-run-folder.t b/t/60-illumina-run-folder.t index 8e51910a..7279f6e2 100644 --- a/t/60-illumina-run-folder.t +++ b/t/60-illumina-run-folder.t @@ -1,12 +1,11 @@ use strict; use warnings; -use Test::More tests => 11; +use Test::More tests => 5; use Test::Exception; use Test::Warn; use File::Temp qw(tempdir); use File::Path qw(make_path remove_tree); use File::Spec::Functions qw(catfile); -use Test::MockObject::Extends; use Moose::Meta::Class; use Cwd; @@ -42,12 +41,11 @@ local $ENV{dev} = qw{non_existant_dev_enviroment}; #prevent pickup of user's con local $ENV{TEST_DIR} = $basedir; #so when npg_tracking::illumina::run::folder globs the test director subtest 'standard runfolder' => sub { - plan tests => 28; + plan tests => 25; my $instr = 'HS2'; - my $id_run = q{1234}; - my $name = $instr . q{_1234}; - my $run_folder = q{123456_} . $instr . q{_1234} . q{_B_205NNABXX}; + my $id_run = 1234; + my $run_folder = 'test_folder'; my $runfolder_path = qq{$basedir/nfs/sf44/} . $instr . q{/analysis/} . $run_folder; my $data_subpath = $runfolder_path . q{/Data}; @@ -70,27 +68,17 @@ subtest 'standard runfolder' => sub { make_path $config_path; }; - my $path_info; - - lives_ok { $path_info = Moose::Meta::Class->create_anon_class( - roles => [qw/npg_tracking::illumina::run::folder/] - )->new_object({id_run => $id_run}); } - q{no error creating object directly from a role without short reference}; - throws_ok { $path_info->runfolder_path(); } - qr{Not enough information to obtain the path}, - q{Error getting runfolder_path as no 'short_reference' method in class}; - $create_staging->(); - lives_ok { $path_info = test::run::folder->new(id_run => $id_run) } - q{created role_test object ok}; + my $path_info; + lives_ok { $path_info = test::run::folder->new( + id_run => $id_run, run_folder => $run_folder + ) } q{created role_test object ok}; my $p; warning_like { $p = $path_info->runfolder_path() } qr/Unable to connect to NPG tracking DB for faster globs/, 'expected warnings'; is($p, $runfolder_path, q{runfolder_path found}); - is($path_info->run_folder(), $run_folder, - q{run_folder worked out from runfolder_path}); warning_like { $p = $path_info->recalibrated_path() } qr/Latest_Summary does not exist or is not a link/, 'warning about lt absence'; @@ -110,7 +98,7 @@ subtest 'standard runfolder' => sub { is($path_info->runfolder_path(), $runfolder_path, q{runfolder_path found}); warning_like { $p = $path_info->recalibrated_path() } qr/Latest_Summary does not exist or is not a link/, - 'warning about lt absence'; + 'warning about Latest_Summary absence'; is($p, $pb_cal_subpath, q{recalibrated_path found}); is($path_info->analysis_path(), $bbcalls_subpath, 'analysis path'); @@ -120,17 +108,19 @@ subtest 'standard runfolder' => sub { my $other = qq{$intensities_subpath/BAM_basecalls_2019-10-01}; make_path $other; - $path_info = test::run::folder->new(id_run => $id_run); + $path_info = test::run::folder->new( + id_run => $id_run, run_folder => $run_folder); warning_like { $p = $path_info->runfolder_path() } qr/Unable to connect to NPG tracking DB for faster globs/, 'expected warnings'; is($p, $runfolder_path, q{runfolder_path found}); is($path_info->basecall_path(), $basecalls_subpath, - q{basecalls_subpath found when link present to recalibrated directory}); + q{basecalls_path found when Latest_Summary link is present}); unlink $ls; - $path_info = test::run::folder->new(id_run => $id_run); + $path_info = test::run::folder->new( + id_run => $id_run, run_folder => $run_folder); warning_like { $p = $path_info->runfolder_path() } qr/Unable to connect to NPG tracking DB for faster globs/, 'expected warnings'; @@ -267,158 +257,4 @@ subtest 'standard run folder No 2' => sub { 'link points to non-existing directory - error'; }; -{ - my $tdir = catfile(tempdir( CLEANUP => 1 ), q()); - my $testrundir = catfile($tdir, q(090414_IL24_2726)); - mkdir $testrundir; - my $pi = test::run::folder->new({_folder_path_glob_pattern=>$tdir, id_run => 2}); - throws_ok { $pi->runfolder_path } qr/No paths to run folder found/, - 'error when no run folders found for id_run'; -} - -local $ENV{TEST_DIR} = q(t/data/long_info); -my $incoming = join q[/], $ENV{TEST_DIR}, q[nfs/sf20/ILorHSany_sf20/incoming]; - -subtest 'tests for short_reference method' => sub { - plan tests => 10; - - my $test; - lives_ok { $test = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - )->new_object(npg_tracking_schema => undef); - } 'anon class with no short_reference method'; - throws_ok { $test->runfolder_path } qr/Not enough information/, - 'no short_reference method - error'; - - my $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - $testc->add_attribute(q[short_reference] => ( - q[is] => q[ro], q[default] => undef )); - - lives_ok { - $test = $testc->new_object(npg_tracking_schema => undef) - } 'anon class with short_reference undef'; - throws_ok { $test->runfolder_path } qr/Not enough information/, - 'short_reference undef - error'; - - # short_reference method, with no suitable folder - $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - $testc->add_attribute(q[short_reference] => ( - q[is] => q[ro], q[default] => undef )); - lives_ok { - $test = $testc->new_object( npg_tracking_schema => undef, - short_reference => q[does_not_exist]); - } 'anon class with short_reference for non existant folder'; - throws_ok { $test->runfolder_path } qr/No paths to run folder found/, - 'no run folder found'; - - # short_reference method, with suitable folder - $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - $testc->add_attribute(q[short_reference] => ( - q[is] => q[ro], q[default] => undef )); - lives_ok { - $test = $testc->new_object( npg_tracking_schema => undef, - short_reference => q[5636]); - } 'anon class with short_reference for folder'; - lives_and { is $test->runfolder_path, - qq($incoming/101217_HS11_05636_A_90061ACXX) } 'run folder found'; - - # short_reference method, with suitable folder - $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - $testc->add_attribute(q[short_reference] => - ( q[is] => q[ro], q[default] => undef )); - lives_ok { - $test = $testc->new_object(npg_tracking_schema => undef, - short_reference => q[100914_HS3_05281_A_205MBABXX]); - } 'anon class with short_reference for folder'; - lives_and { is $test->runfolder_path, - qq($incoming/100914_HS3_05281_A_205MBABXX) } 'run folder found'; -}; - -my $testschema = Test::MockObject::Extends->new( q(npg_tracking::Schema) ); -$testschema->mock(q(resultset), sub{return shift;}); -#diag $testschema->resultset; -my $testrun = Test::MockObject::Extends->new(q(npg_tracking::Schema::Result::Run)); -$testschema->mock(q(find), sub{ - my($self,$id_run) = @_; - return $id_run ? $testrun : undef; -}); -$testrun->mock(q(is_tag_set), sub{ return 0; }); - -subtest 'schema, no id_run, but with short ref and a folder' => sub { - plan tests => 2; - - my $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - $testc->add_attribute(q[short_reference] => ( q[is] => q[ro], q[default] => undef )); - my $test; - lives_ok { - $test = $testc->new_object( q[short_reference] => q[100914_HS3_05281_A_205MBABXX], q[npg_tracking_schema] => $testschema ); - } 'anon class, schema, no id_run, with short_reference for folder'; - lives_and { is $test->runfolder_path, qq($incoming/100914_HS3_05281_A_205MBABXX) } ' run folder found'; -}; - -subtest 'schema, id_run, no staging tag' => sub { - plan tests => 2; - - $testrun->mock(q(is_tag_set), sub{ return 0; }); - my $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - $testc->add_attribute(q[short_reference] => ( q[is] => q[ro], q[default] => undef )); - $testc->add_attribute(q[id_run] => ( q[is] => q[ro], q[default] => 0 )); - my $test; - lives_ok { - $test = $testc->new_object( q[id_run] => 5281, q[short_reference] => q[100914_HS3_05281_A_205MBABXX], q[npg_tracking_schema] => $testschema ); - } 'anon class, schema, id_run, with short_reference for folder - but no staging tag'; - throws_ok { $test->runfolder_path } qr/NPG tracking reports run \d* no longer on staging/, ' no run folder found'; -}; - -subtest 'schema, id_run, staging tag, no glob, no folder_name' => sub { - plan tests => 2; - - $testrun->mock(q(is_tag_set), sub{ return 1; }); - $testrun->mock(q(folder_path_glob), sub{ return; }); - $testrun->mock(q(folder_name), sub{ return; }); - my $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - - $testc->add_attribute(q[short_reference] => ( q[is] => q[ro], q[default] => undef )); - $testc->add_attribute(q[id_run] => ( q[is] => q[ro], q[default] => 0 )); - my $test; - lives_ok { - $test = $testc->new_object( q[id_run] => 5281, q[short_reference] => q[100914_HS3_05281_A_205MBABXX], q[npg_tracking_schema] => $testschema ); - } 'anon class, schema, id_run, with short_reference for folder - staging tag but no folder name or glob from DB'; - lives_and { is $test->runfolder_path, qq($incoming/100914_HS3_05281_A_205MBABXX) } ' run folder found'; -}; - -subtest 'schema, no short ref, id_run, staging tag, glob, folder_name' => sub { - plan tests => 3; - - $testrun->mock(q(folder_path_glob), sub{ return q[t/data/long_info/{export,nfs}/sf20/ILorHSany_sf20/*]; }); - $testrun->mock(q(folder_name), sub{ return q[100914_HS3_05281_A_205MBABXX]; }); - my $testc = Moose::Meta::Class->create_anon_class( - roles => [qw(npg_tracking::illumina::run::folder)], - ); - $testc->add_attribute(q[id_run] => ( q[is] => q[ro], q[default] => 0 )); - my $test; - lives_ok { - $test = $testc->new_object( q[id_run] => 5281, q[short_reference] => q[100914_HS3_05281_A_205MBABXX], q[npg_tracking_schema] => $testschema ); - } 'anon class, schema, id_run, no short_reference, staging tag and folder name and glob'; - lives_and { is $test->runfolder_path, qq($incoming/100914_HS3_05281_A_205MBABXX) } ' run folder found'; - - $testrun->mock(q(folder_path_glob), sub{ return q[t/data/long_info/{export,nfs}/sf20/ILorHSany_sf20/*/]; }); - $test = $testc->new_object( q[id_run] => 5281, q[short_reference] => q[100914_HS3_05281_A_205MBABXX], q[npg_tracking_schema] => $testschema ); - lives_and { is $test->runfolder_path, qq($incoming/100914_HS3_05281_A_205MBABXX) } ' run folder found and does not contain a double slash'; -}; - 1; diff --git a/t/60-illumina-run-long_info.t b/t/60-illumina-run-long_info.t index 7ae660c8..d313d7ed 100644 --- a/t/60-illumina-run-long_info.t +++ b/t/60-illumina-run-long_info.t @@ -1,30 +1,14 @@ use strict; use warnings; -use Test::More tests => 68; +use Test::More tests => 31; use Test::Exception; use Test::Deep; use File::Temp qw(tempdir); use Moose::Meta::Class; -use Cwd; -use Carp; use File::Copy; use File::Slurp qw(edit_file_lines); -BEGIN { - local $ENV{'HOME'} = getcwd() . '/t'; - use_ok(q{npg_tracking::illumina::run::long_info}); - - # package creation within BEGIN block to ensure after HOME is reset - package test::long_info; - use Moose; - with qw{npg_tracking::illumina::run::short_info - npg_tracking::illumina::run::folder}; - with qw{npg_tracking::illumina::run::long_info}; - no Moose; - 1; -} - -package main; +use_ok(q{npg_tracking::illumina::run::long_info}); my $basedir = tempdir( CLEANUP => 1 ); @@ -324,196 +308,67 @@ subtest 'getting experiment name from runParameters' => sub { } }; -local $ENV{'TEST_DIR'} = $basedir; #so when npg_tracking::illumina::run::folder globs the test directory -local $ENV{'dev'} = 'none'; - -my $id_run = q{1234}; -my $name = q{IL2_1234}; -my $run_folder = q{123456_IL2_1234}; -my $runfolder_path = qq{$basedir/nfs/sf44/IL2/analysis/123456_IL2_1234}; -my $data_subpath = $runfolder_path . q{/Data}; -my $intensities_subpath = $data_subpath . q{/Intensities}; -my $basecalls_subpath = $intensities_subpath . q{/BaseCalls}; -my $bustard_subpath = $intensities_subpath . q{/Bustard-2009-10-01}; -my $gerald_subpath = $bustard_subpath . q{/GERALD-2009-10-01}; -my $archive_subpath = $gerald_subpath . q{/archive}; -my $qc_subpath = $archive_subpath . q{/qc}; -my $config_path = $runfolder_path . q{/Config}; - -sub delete_staging { - `rm -rf $basedir/nfs`; - return 1; -} - -sub create_staging { - my ($id_run, $lanes, $cycles) = @_; - delete_staging(); - `mkdir -p $qc_subpath`; - `mkdir $basecalls_subpath`; - - $lanes = $lanes || 8; - if ( $cycles ) { - $cycles = qq[]; - } else { - $cycles = <<"ENDXML"; - - - -ENDXML - } - - my $runparamsfile = qq[$runfolder_path/runParameters.xml]; - open(my $fh, '>', $runparamsfile) or die "Could not open file '$runparamsfile' $!"; - print $fh <<"ENDXML"; - - - - HiSeq Control Software - $id_run - - -ENDXML - close $fh; - - my $runinfofile = qq[$runfolder_path/RunInfo.xml]; - open($fh, '>', $runinfofile) or die "Could not open file '$runinfofile' $!"; - print $fh <<"ENDXML"; - - - - -$cycles - - - - - -ENDXML - close $fh; - return 1; -} - -sub create_latest_summary_link { - create_staging(); - `ln -s $gerald_subpath $runfolder_path/Latest_Summary`; - return 1; -} - -my $orig_dir = getcwd(); - -{ - my $long_info; - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - - create_staging(1234, 8); - - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->is_paired_read(), 1, q{Read is paired}); - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->is_indexed(), 1, q{Read is indexed}); - - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->lane_count(), 8, q{correct number of lanes}); - - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->expected_cycle_count(), 160, q{correct number of expected cycles}); - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->cycle_count(), 160, q{cycle count returns the same as expected_cycle_count}); - - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->tilelayout_columns(), 2, q{correct number of tilelayout_columns}); - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->tilelayout_rows(), 60, q{correct number of tilelayout_rows}); - lives_ok { $long_info = test::long_info->new({id_run => 1234}); } q{created role_test object ok}; - is($long_info->tile_count(), 120, q{correct number of tiles}); -} - -chdir $orig_dir; #need to leave directories before you can delete them.... -eval { delete_staging(); } or do { carp 'unable to delete staging area'; }; - -#Now let's test a new HiSeq directory.... -$ENV{TEST_DIR} = 't/data/long_info'; { + my $rf = 't/data/long_info/nfs/sf20/ILorHSany_sf20/incoming/100914_HS3_05281_A_205MBABXX'; + my $class = Moose::Meta::Class->create_anon_class( + methods => {"runfolder_path" => sub {$rf}}, + roles => [qw/npg_tracking::illumina::run::long_info/]); my $long_info; - lives_ok { $long_info = test::long_info->new({id_run => 5281}); } q{created role_test (HiSeq run 5281, RunInfo.xml) object ok}; + lives_ok { $long_info = $class->new_object(id_run => 5281); } + q{created role_test (HiSeq run 5281, RunInfo.xml) object ok}; cmp_ok($long_info->tile_count, '==', 32, 'correct tile count'); - lives_ok { $long_info = test::long_info->new({id_run => 5281}); } q{created role_test (HiSeq run 5281, RunInfo.xml) object ok}; cmp_ok($long_info->lane_count, '==', 8, 'correct lane count'); - lives_ok { $long_info = test::long_info->new({id_run => 5281}); } q{created role_test (HiSeq run 5281, RunInfo.xml) object ok}; cmp_ok($long_info->cycle_count, '==', 200, 'correct cycle count'); - lives_ok { $long_info = test::long_info->new({id_run => 5281}); } q{created role_test (HiSeq run 5281, RunInfo.xml) object ok}; - my $test_lane_tile_clustercount = {}; - foreach my $i (1..8) { - foreach my $y (1..8) { - foreach my $add ( 0,20,40,60 ) { - $test_lane_tile_clustercount->{$i}->{$y + $add} = undef; - } - } - } - - $long_info=undef; - lives_ok { $long_info = test::long_info->new({id_run => 19395}); } q{created role_test (HiSeq run 19395, RunInfo.xml) object ok}; + $rf = 't/data/long_info/nfs/sf20/ILorHSany_sf20/incoming/160408_HS31_19395_B_H5MMFADXY'; + $class = Moose::Meta::Class->create_anon_class( + methods => {"runfolder_path" => sub {$rf}}, + roles => [qw/npg_tracking::illumina::run::long_info/]); + lives_ok { $long_info = $class->new_object(id_run => 19395); } q{created role_test (HiSeq run 19395, RunInfo.xml) object ok}; cmp_ok($long_info->lane_tilecount->{1}, '==', 64, 'correct lane 1 tile count'); - lives_ok { $long_info = test::long_info->new({id_run => 19395}); } q{created role_test (HiSeq run 19395, RunInfo.xml) object ok}; cmp_ok($long_info->lane_tilecount->{2}, '==', 63, 'correct lane 2 tile count'); - note($long_info->runfolder_path); } -#Now let's test a NovaSeq directory.... -$ENV{TEST_DIR} = 't/data/long_info'; { - my $long_info; - - lives_ok { $long_info = test::long_info->new({id_run => 25723}); } q{created role_test object ok}; + my $rf = 't/data/long_info/nfs/sf20/ILorHSany_sf20/incoming/180426_NV1_25723_A_H3W2VDSXX'; + my $long_info = Moose::Meta::Class->create_anon_class( + methods => {"runfolder_path" => sub {$rf}}, + roles => [qw/npg_tracking::illumina::run::long_info/] + )->new_object(id_run => 25723); is($long_info->tilelayout_columns(), 12, q{correct number of tilelayout_columns}); - lives_ok { $long_info = test::long_info->new({id_run => 25723}); } q{created role_test object ok}; is($long_info->tilelayout_rows(), 78, q{correct number of tilelayout_rows}); - lives_ok { $long_info = test::long_info->new({id_run => 25723}); } q{created role_test object ok}; is($long_info->tile_count(), 936, q{correct number of tiles}); - - $long_info=undef; - lives_ok { $long_info = test::long_info->new({id_run => 25723}); } q{created role_test (HiSeq run 19395, RunInfo.xml) object ok}; cmp_ok($long_info->lane_tilecount->{1}, '==', 936, 'correct lane 1 tile count'); - note($long_info->runfolder_path); } { - my $long_info; my $rfpath = q(t/data/long_info/nfs/sf20/ILorHSany_sf20/incoming/120110_M00119_0068_AMS0002022-00300); - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; + my $long_info = Moose::Meta::Class->create_anon_class( + methods => {"runfolder_path" => sub {$rfpath}}, + roles => [qw/npg_tracking::illumina::run::long_info/])->new_object(); cmp_ok( $long_info->expected_cycle_count, '==', 318, 'expected_cycle_count'); - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { cmp_deeply( [$long_info->read_cycle_counts], [151,8,8,151], 'read_cycle_counts match');} 'read_cycle_counts live and match'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { cmp_deeply( [$long_info->read1_cycle_range], [1,151], 'read1_cycle_range matches');} 'read1_cycle_range lives and matches'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { cmp_deeply( [$long_info->indexing_cycle_range], [152,167], 'indexing_cycle_range matches');} 'indexing_cycle_range lives and matches'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { cmp_ok( $long_info->index_length, '==', 16, 'index_length matches');} 'index_length lives and matches'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { cmp_deeply( [$long_info->read2_cycle_range], [168,318], 'read2_cycle_range matches');} 'read2_cycle_range lives and matches'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { ok( $long_info->is_indexed, 'is_indexed ok');} 'is_indexed lives and ok'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { ok( $long_info->is_paired_read, 'is_paired_read ok');} 'is_paired_read lives and ok'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { ok( $long_info->is_dual_index, 'is_dual_index ok');} 'is_paired_read lives and ok'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { cmp_deeply( [$long_info->index_read1_cycle_range], [152,159], 'index_read1_cycle_range matches');} 'index_read1_cycle_range lives and matches'; - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } q{create test role for dual index paired}; lives_and { cmp_deeply( [$long_info->index_read2_cycle_range], [160,167], 'index_read2_cycle_range matches');} 'index_read2_cycle_range lives and matches'; - is ($long_info->instrument_name, 'M00119', 'instrument name from RunInfo.xml'); } #and a SP flowcell { - my $long_info; my $rfpath = q(t/data/long_info/nfs/sf20/ILorHSany_sf20/incoming/200303_A00562_0352_AHKFVLDRXX); - lives_ok { $long_info = test::long_info->new({runfolder_path=>$rfpath}); } + my $long_info = Moose::Meta::Class->create_anon_class( + methods => {"runfolder_path" => sub {$rfpath}}, + roles => [qw/npg_tracking::illumina::run::long_info/])->new_object(); q{create test role for SP flowcell}; cmp_ok ( $long_info->surface_count, '==', 1, 'surface_count'); is ($long_info->instrument_name, 'A00562', 'instrument name from RunInfo.xml'); } + 1; diff --git a/t/60-illumina-run-short_info.t b/t/60-illumina-run-short_info.t index 9777e889..dc2cdbce 100644 --- a/t/60-illumina-run-short_info.t +++ b/t/60-illumina-run-short_info.t @@ -1,274 +1,92 @@ use strict; use warnings; -use Test::More tests => 46; +use Test::More tests => 5; use Test::Exception; -use File::Temp qw/ tempdir /; use Moose::Meta::Class; +use t::dbic_util; -BEGIN { - use_ok(q{npg_tracking::illumina::run::short_info}); -} +use_ok(q{npg_tracking::illumina::run::short_info}); -package test::short_info; -use Moose; -use Carp; -use Readonly; -use File::Spec::Functions qw(splitdir); -use List::Util qw(first); +my $schema = t::dbic_util->new->test_schema( + fixture_path => q[t/data/dbic_fixtures]); -Readonly::Scalar my $FOLDER_PATH_PREFIX_GLOB_PATTERN => '/{staging,nfs/sf{5,6,9,10,11,12,13,14,15,16,17}}/{IL,HS}*/*/'; +my $rfname = q[20231017_LH00210_0012_B22FCNFLT3]; +# Start of package test::short_info +package test::short_info; +use Moose; with qw{npg_tracking::illumina::run::short_info}; -sub _build_run_folder { - my ($self) = @_; - - if( !( $self->has_id_run() || $self->has_name() ) ) { - croak q{Need an id_run or name to generate the run_folder}; - } - - my $path = $self->_short_path(); - return first {$_ ne q()} reverse splitdir($path); - -} - - -has q{_short_path} => ( isa => q{Str}, is => q{ro}, lazy_build => 1, init_arg => undef ); +sub _build_run_folder { return $rfname; } +# End of package test::short_info -sub _build__short_path { - my ($self) = @_; - my @dir = $self->has_run_folder() ? glob $self->_folder_path_glob_pattern() . $self->run_folder() - : $self->has_id_run() ? glob $self->_folder_path_glob_pattern() . q(*_{r,}) . $self->id_run() . q{*} - : $self->has_name() ? glob $self->_folder_path_glob_pattern() . q{*} . $self->name() - : croak q{No run_folder, name or id_run provided} - ; - - @dir = grep {-d $_} @dir; - - if ( @dir == 0 ) { - croak 'No paths to run folder found.'; - } - - my %fs_inode_hash; #ignore multiple paths point to the same folder - @dir = grep {not $fs_inode_hash{join q(,),stat $_}++} @dir; - - if ( @dir > 1 ) { - croak 'Ambiguous paths for run folder found: '.join q{,},@dir; - } - return shift @dir; -} +# Start of package test::db_short_info +package test::db_short_info; +use Moose; +use npg_tracking::Schema; +with qw{npg_tracking::illumina::run::short_info}; -has 'pattern_prefix' => ( +has q{npg_tracking_schema} => ( + isa => 'npg_tracking::Schema', is => 'ro', - isa => 'Str', - default => q[/nonexisting], + default => sub { return $schema }, ); +# End of package test::db_short_info -sub _folder_path_glob_pattern { - my $self = shift; - return $self->pattern_prefix . $FOLDER_PATH_PREFIX_GLOB_PATTERN; -} - - +# Start of package test::nvx_short_info package test::nvx_short_info; use Moose; with 'npg_tracking::illumina::run::short_info'; has experiment_name => (is => 'rw'); +# End of package test::nvx_short_info package main; -sub create_staging { - - my ($idr, $hi_seq) = @_; - if (!$idr) { $idr = 1234; } - my $base = tempdir( CLEANUP => 1 ); +subtest 'object derived directly from the role' => sub { + plan tests => 6; - my $instr_prefix = $hi_seq ? q[HS] : q[IL]; + my $class = Moose::Meta::Class->create_anon_class( + roles => [qw/npg_tracking::illumina::run::short_info/] + ); - my $next = $base . q[/staging]; `mkdir $next`; - $next = $next . q[/] . $instr_prefix . q[2]; `mkdir $next`; - $next = $next . q[/analysis]; `mkdir $next`; - $next = $next . q[/123456_] . $instr_prefix . q[2_] . $idr; - - if ( $hi_seq ) { - $next .= q{_B_205NNABXX}; - } - - `mkdir $next`; - $next = $next . q[/Data]; `mkdir $next`; - $next = $next . q[/Intensities]; `mkdir $next`; - - my $base_calls = $next . q[/BaseCalls]; `mkdir $base_calls`; - my $gerald = $next . q[/Bustard-2009-10-01]; `mkdir $gerald`; - $gerald = $next . q[/GERALD-2009-10-01]; `mkdir $gerald`; - - return $base; -} - -my $id_run = q{1234}; -my $name = q{IL2_1234}; -my $run_folder = q{123456_IL2_1234}; - -{ - my $short_info; - lives_ok { $short_info = Moose::Meta::Class->create_anon_class( - roles => [qw/npg_tracking::illumina::run::short_info/] - )->new_object({id_run => 1234}); - } q{object directly from the role ok}; - - throws_ok { $short_info->run_folder(); } - qr{does not support builder method '_build_run_folder' for attribute 'run_folder'}, + throws_ok { $class->new_object(id_run => 1234)->run_folder() } + qr{does not support builder method '_build_run_folder'}, q{Error thrown as no _build_run_folder method in class}; -} - -{ - my $short_info; - lives_ok { $short_info = test::short_info->new({}); } q{no error creating no-arg test object}; - throws_ok { $short_info->id_run(); } - qr{Need an id_run or name to generate the run_folder}, - q{As run_folder, can't obtain id_run}; - throws_ok { $short_info->name(); } - qr{Unable to obtain name from run_folder}, - q{As no id_run or run_folder, can't obtain name}; - throws_ok { $short_info->run_folder(); } - qr{Need an id_run or name to generate the run_folder}, - q{As no name or id_run, can't obtain run_folder}; - throws_ok { $short_info->_short_path(); } - qr{No run_folder, name or id_run provided}, - q{As no attributes, cannot get short path}; - throws_ok { $short_info->short_reference(); } - qr{Unable to obtain name from run_folder}, - q{As no id_run or run_folder, can't obtain name}; -} - -#### test where run_folder is given in the constructor -{ - my $short_info = test::short_info->new({ - run_folder => $run_folder, - }); - is($short_info->id_run(), $id_run, q{id_run worked out correctly}); - is($short_info->name(), $name, q{name worked out correctly}); - is($short_info->short_reference(), $run_folder, q{short_reference returns run_folder first}); - my $hs_runfolder = q{123456_HS2_1236_B_205NNABXX}; - $short_info = test::short_info->new({ - run_folder => $hs_runfolder, - }); - is($short_info->name(), q{HS2_1236}, q{HS name worked out correctly}); - is($short_info->id_run(), '1236', q{HS id_run worked out correctly}); - is($short_info->short_reference(), $hs_runfolder, q{HS short_reference returns run_folder first}); - is( $short_info->instrument_string(), q{HS2}, q{HS instrument name correctly worked out} ); - is( $short_info->slot(), q{B}, q{HS slot returned ok} ); - is( $short_info->flowcell_id(), q{205NNABXX}, q{HS flowcell_id returned ok} ); -} + throws_ok { $class->new_object(run_folder => q[export/sv03/my_folder]) } + qr{Attribute \(run_folder\) does not pass the type constraint}, + 'error supplying a directory path as the run_folder attribute value'; -#### test where run_folder is given in the constructor -# where we can't find out the run_folder -{ - my $short_info = test::short_info->new({ - id_run => $id_run, - }); - is($short_info->id_run(), $id_run, q{id_run returned correctly}); - is($short_info->short_reference(), $id_run, q{short_reference returns id_run}); - throws_ok { my $name = $short_info->name(); } qr{No[ ]paths[ ]to[ ]run[ ]folder[ ]found}, q{no runfolder found with which to return the path, so name/runfolder cannot be worked out}; -} + throws_ok { $class->new_object(run_folder => q[]) } + qr{Attribute \(run_folder\) does not pass the type constraint}, + 'error supplying an empty atring as the run_folder attribute value'; -# where we can find the run_folder -{ - my $base = create_staging(); - my $short_info = test::short_info->new({ - id_run => $id_run, - pattern_prefix => $base, - }); - is($short_info->short_reference(), $id_run, q{short_reference returns id_run}); - is($short_info->name(),$name, q{name worked out correctly}); - is($short_info->short_reference(), $run_folder, q{short_reference returns run_folder}); - - $base = create_staging(undef, 1); - $short_info = test::short_info->new({ - id_run => $id_run, - pattern_prefix => $base, - }); - is($short_info->short_reference(), $id_run, q{HS short_reference returns id_run}); - is($short_info->name(),q{HS2_1234}, q{HS name worked out correctly}); - is($short_info->short_reference(), q{123456_HS2_1234_B_205NNABXX}, q{HS short_reference returns run_folder}); -} - -#### test where name is give in the constructor -{ - my $base = create_staging(); - my $short_info = test::short_info->new({ - name => $name, - pattern_prefix => $base, - }); - is($short_info->short_reference(), $name, q{short_reference returns name}); - is($short_info->id_run(), $id_run, q{id_run worked out correctly}); - is($short_info->short_reference(), $run_folder, q{short_reference returns run_folder}); - is($short_info->run_folder(), $run_folder, q{run_folder worked out correctly}); - is($short_info->short_reference(), $run_folder, q{short_reference returns run_folder}); -} - - -{ - my $id = q[01234]; - my $base = create_staging($id); - my $short_info = test::short_info->new({ - run_folder =>q{123456_IL2_01234}, - pattern_prefix => $base, - }); - is($short_info->id_run(), 1234, q{id_run worked out correctly, no leading zero}); - is($short_info->name(), q[IL2_1234], q{name does not contain leading zero for id run}); - is($short_info->run_folder(), q[123456_IL2_01234], q{run_folder as set}); - is($short_info->short_reference(), q[123456_IL2_01234], q{short_reference returns run_folder}); - is( $short_info->instrument_string(), q{IL2}, q{IL instrument name correctly worked out} ); - is( $short_info->flowcell_id(), q{}, q{IL flowcell_id returns empty string} ); - is( $short_info->slot(), q{}, q{IL slot returns empty string} ); -} - - -{ - my $id = q{fail}; - my $base = create_staging($id); - my $short_info = test::short_info->new({ - run_folder =>q{123456_IL2_} . $id, - pattern_prefix => $base, - }); - - throws_ok { $short_info->name() } - qr/Unrecognised format for run folder name: /ms, - q{croak if the run id doesn't start with an integer}; -} + my $obj = $class->new_object(run_folder => q[my_folder], id_run => 1234); + is ($obj->run_folder, 'my_folder', 'the run_folder value is as set'); + is ($obj->id_run, 1234, 'id_run value is as set'); + throws_ok { $class->new_object(run_folder => q[my_folder])->id_run } + qr{Unable to identify id_run with data provided}, + 'error building id_run'; +}; -{ - my $short_info = test::short_info->new({ - run_folder =>q{120113_MS1_7362_A_MS0002061-300V2}, - }); +subtest 'object with a bulder method for run_folder' => sub { + plan tests => 1; - my $name; - my $flowcell_id; - lives_ok { - $name = $short_info->name(); - $flowcell_id= $short_info->flowcell_id(); - } q{MiSeq runfolder - kit id in place of flowcell}; - is($short_info->run_folder, q(120113_MS1_7362_A_MS0002061-300V2), q(run folder okay)); - is($name, q(MS1_7362), q(name okay)); - is($flowcell_id, q(MS0002061-300V2), q(flowcell_id (kit id) okay)); -} + is (test::short_info->new(id_run => 47995)->run_folder, $rfname, + 'value of run_folder attribute is set by the builder method'); +}; -subtest 'process run_folder when no id_run present' => sub { +subtest 'object with access to tracking database' => sub { plan tests => 2; - my $run_folder = q{180517_A00512_0010_BH3WCVDSXX}; #NovaSeq folder pattern - my $short_info; - lives_ok { - $short_info = test::short_info->new({ run_folder => $run_folder }); - } q[Can create object]; - throws_ok { - $short_info->id_run(); - } qr[Unable to identify id_run], q[Throws when it obtain id_run]; + throws_ok { test::db_short_info->new(run_folder => 'xxxxxx')->id_run } + qr{Unable to identify id_run with data provided}, + 'error building id_run when no db record for the run folder exists'; + is (test::db_short_info->new(run_folder => $rfname)->id_run, 47995, + 'id_run value retrieved from the database recprd'); }; subtest 'Test id_run extraction from within experiment_name' => sub { diff --git a/t/60-illumina-runfolder.t b/t/60-illumina-runfolder.t index 07ea02c5..85ae3346 100644 --- a/t/60-illumina-runfolder.t +++ b/t/60-illumina-runfolder.t @@ -1,76 +1,84 @@ use strict; use warnings; -use Test::More tests => 29; +use Test::More tests => 26; use Test::Exception; -use Archive::Tar; -use IO::File; +use Test::Warn; +use File::Copy; use File::Temp qw(tempdir); -use File::Basename qw(dirname); -use File::Spec::Functions qw(catfile rel2abs catdir); -use Cwd; +use File::Spec::Functions qw(catfile catdir); use t::dbic_util; use_ok('npg_tracking::illumina::runfolder'); my $schema = t::dbic_util->new->test_schema(); +my $rf_name = q(240201_MS8_48385_A_MS3553611-300V2); +# We need a trailing slash after our directory for the globbing later. +my $testdir = catfile(tempdir( CLEANUP => 1 ), q()); +my $testrundir = catdir($testdir,$rf_name); +mkdir $testrundir; -my $testrundata = catfile(rel2abs(dirname(__FILE__)),q(data),q(090414_IL24_2726.tar.bz2)); +{ + my $rf = npg_tracking::illumina::runfolder->new( + runfolder_path => $testrundir, + npg_tracking_schema => undef + ); + is ($rf->run_folder, $rf_name, 'run folder name is correct'); + throws_ok { $rf->id_run } qr/File not found/, + 'id_run cannot be computed, RunParameters.xml file is not found'; -my $origdir = getcwd; -my $testdir = catfile(tempdir( CLEANUP => 1 ), q()); #we need a trailing slash after our directory for the globbing later -chdir $testdir or die "Cannot change to temporary directory $testdir"; -diag ("Extracting $testrundata to $testdir"); -system('tar','xjf',$testrundata) == 0 or Archive::Tar->extract_archive($testrundata, 1); -chdir $origdir; #so cleanup of testdir can go ahead -my $testrundir = catdir($testdir,q(090414_IL24_2726)); + $rf = npg_tracking::illumina::runfolder->new( + _folder_path_glob_pattern => $testdir, + id_run => 2, + npg_tracking_schema => undef + ); + throws_ok { $rf->run_folder } qr/Failed to infer runfolder_path/, + 'run folder name cannot be built'; -{ - my $rf; + $rf = npg_tracking::illumina::runfolder->new( + run_folder => $rf_name, + _folder_path_glob_pattern => $testdir, + npg_tracking_schema => undef + ); + is ($rf->runfolder_path, $testrundir, + 'runfolder path by globbing for a run folder directory'); - lives_ok { - $rf = npg_tracking::illumina::runfolder->new( runfolder_path => $testrundir); - } 'runfolder from valid runfolder_path'; - { my $id_run; - lives_ok { $id_run = $rf->id_run; } 'id_run parsed'; - is($id_run, 2726, 'id_run correct'); - } - { my $name; - lives_ok { $name = $rf->name; } 'name parsed'; - is($name, q(IL24_2726), 'name correct'); - } + my $id_run = 1; + my $run_row = $schema->resultset('Run')->find($id_run); + $run_row->update({folder_name => 'nomatch'}); - mkdir catdir($testrundir,qw(Data)); - mkdir catdir($testrundir,qw(Data Intensities)); - { my $name; - lives_ok { - $rf = npg_tracking::illumina::runfolder->new(_folder_path_glob_pattern=>$testdir, id_run=> 2726, npg_tracking_schema => undef); - $name = $rf->name; - } 'runfolder from valid id_run'; - is($name, q(IL24_2726), 'name parsed'); - } - my $rfpath = catdir($testdir,q(090414_IL99_2726)); - mkdir $rfpath; - throws_ok { - $rf = npg_tracking::illumina::runfolder->new(_folder_path_glob_pattern=>$testdir, id_run=> 2726, npg_tracking_schema => undef); - $rf->runfolder_path; - } qr/Ambiguous paths/, 'throws when ambiguous run folders found for id_run'; - rmdir catdir($testdir,q(090414_IL99_2726)); - symlink $testrundir, catdir($testdir,q(superfoo_r2726)); - lives_ok { - $rf = npg_tracking::illumina::runfolder->new(_folder_path_glob_pattern=>$testdir, id_run=> 2726, npg_tracking_schema => undef); - $rf->runfolder_path; - } 'lives when ambiguous run folders found for id_run but they correspond, via links or such, to the same folder'; - unlink catdir($testdir,q(superfoo_r2726)); - throws_ok { - $rf = npg_tracking::illumina::runfolder->new(_folder_path_glob_pattern=>$testdir, id_run=> 2, npg_tracking_schema => undef); - $rf->run_folder; - } qr/No path/, 'throws when no run folders found for id_run'; + $rf = npg_tracking::illumina::runfolder->new( + id_run => $id_run, + run_folder => $rf_name, + _folder_path_glob_pattern => $testdir, + npg_tracking_schema => $schema + ); + throws_ok { $rf->runfolder_path } + qr/NPG tracking reports run 1 no longer on staging/, + 'error when the run does not have a staging tag'; + $run_row->set_tag(1, 'staging'); my $path; - my $expected_cycle_count; - my (@read_cycle_counts, @indexing_cycle_range, @read1_cycle_range, @read2_cycle_range); - + warning_like { $path = $rf->runfolder_path } + qr/Inconsistent db and given run folder name: nomatch, $rf_name/, + 'warning about mismatching run folder names'; + is ($path, $testrundir, + 'runfolder path via globbing for a run folder directory'); + + $run_row->update({folder_name => $rf_name, folder_path_glob => $testdir}); + + $rf = npg_tracking::illumina::runfolder->new( + id_run => $id_run, + run_folder => 'mismatch', + npg_tracking_schema => $schema + ); + warning_like { $path = $rf->runfolder_path } + qr/Inconsistent db and given run folder name: $rf_name, mismatch/, + 'warning about mismatching run folder names'; + is ($path, $testrundir, + 'runfolder path via using the database record'); +} +{ my $fh; my $runinfofile = qq[$testrundir/RunInfo.xml]; open($fh, '>', $runinfofile) or die "Could not open file '$runinfofile' $!"; @@ -96,10 +104,14 @@ ENDXML ENDXML - close $fh; + close $fh; + my $rf = npg_tracking::illumina::runfolder->new( + _folder_path_glob_pattern => $testdir, + run_folder => $rf_name, + npg_tracking_schema => undef + ); my $lane_count; - $rf = npg_tracking::illumina::runfolder->new(_folder_path_glob_pattern=>$testdir, name=> q(090414_IL24_2726), npg_tracking_schema => undef); lives_ok { $lane_count = $rf->lane_count; } 'finds and parses recipe file'; @@ -111,16 +123,6 @@ ENDXML is($tile_count,120,'tile_count'); } -{ - my $test_runfolder_path; - lives_ok { - $test_runfolder_path = npg_tracking::illumina::runfolder->new( - runfolder_path=> $testrundir, npg_tracking_schema => undef); - } 'runfolder from valid runfolder_path'; - is($test_runfolder_path->run_folder(), '090414_IL24_2726', - q{run folder obtained ok when runfolder_path used in construction}); -} - { my $new_name = q(4567XXTT98); my $testrundir_new = catdir($testdir, $new_name); @@ -145,14 +147,12 @@ ENDXML my $run_row = $schema->resultset('Run')->create($data); $run_row->set_tag(1, 'staging'); - my $rf; - - $rf = npg_tracking::illumina::runfolder->new( + my $rf = npg_tracking::illumina::runfolder->new( id_run => 33333, npg_tracking_schema => undef); - throws_ok { $rf->run_folder } qr/No paths to run folder found/, + throws_ok { $rf->run_folder } qr/Failed to infer runfolder_path/, 'error - not able to find a runfolder without db help'; - throws_ok { $rf->runfolder_path } qr/No paths to run folder found/, + throws_ok { $rf->runfolder_path } qr/Failed to infer runfolder_path/, 'error - not able to find a runfolder without db help'; $rf = npg_tracking::illumina::runfolder->new( @@ -180,8 +180,6 @@ ENDXML npg_tracking_schema => $schema); is ($rf->id_run, 33333, 'id_run with db helper'); is ($rf->run_folder, $new_name, 'runfolder with db helper'); - - rename $testrundir_new, $testrundir; } subtest 'getting id_run from experiment name in run parameters' => sub { @@ -211,16 +209,14 @@ subtest 'getting id_run from experiment name in run parameters' => sub { my $param_prefix = $expname_data->{$file_name}->{'rpf'}; my $run_params_file_path = qq[$rf/$param_prefix.xml]; - use File::Copy; copy(join(q[/],$run_param_dir,$file_name), $run_params_file_path) or die 'Failed to copy file'; my $li = new npg_tracking::illumina::runfolder( runfolder_path => $rf, npg_tracking_schema => $schema ); - is($li->id_run(), $expected_experiment_name, q[Expected id_run parsed from experiment name in run params]); - `rm $run_params_file_path` + unlink $run_params_file_path; } }; diff --git a/t/data/090414_IL24_2726.tar.bz2 b/t/data/090414_IL24_2726.tar.bz2 deleted file mode 100644 index d03283b0..00000000 Binary files a/t/data/090414_IL24_2726.tar.bz2 and /dev/null differ