UNPKG

@gmod/jbrowse

Version:

JBrowse - client-side genome browser

474 lines (394 loc) 16.5 kB
use strict; use warnings; use JBlibs; use Test::More; use Test::Warn; use JSON 2; use Bio::JBrowse::Cmd::FlatFileToJson; use File::Spec::Functions qw( catfile catdir ); use File::Temp (); use File::Copy::Recursive 'dircopy'; use lib 'tests/perl_tests/lib'; use FileSlurping 'slurp'; sub run_with(@) { #system $^X, 'bin/flatfile-to-json.pl', @_; #ok( ! $?, 'flatfile-to-json.pl ran ok' ); my @args = @_; #warnings_are { Bio::JBrowse::Cmd::FlatFileToJson->new( @args )->run; #} [], 'ran without warnings'; } sub tempdir { my $tempdir = File::Temp->newdir( CLEANUP => $ENV{KEEP_ALL} ? 0 : 1 ); #diag "using temp dir $tempdir"; return $tempdir; } { #diag "running on volvox"; my $tempdir = tempdir(); my $read_json = sub { slurp( $tempdir, @_ ) }; dircopy( 'tests/data/volvox_formatted_refseqs', $tempdir ); run_with ( '--out' => $tempdir, '--bed' => 'sample_data/raw/volvox/volvox-remark.bed', '--trackLabel' => 'ExampleFeatures', '--key' => 'Example Features', '--autocomplete' => 'all', '--cssClass' => 'feature2', '--metadata' => '{"description": "toasted barrel head"}', '--clientConfig' => '{"featureCss": "height: 8px;", "histScale": 2}', '--urltemplate' => 'http://example.com/{name}/{start}/{end}', ); #system "find $tempdir -type f"; #die 'break'; run_with ( '--out' => $tempdir, '--gff' => 'sample_data/raw/volvox/volvox.gff3', '--trackLabel' => 'CDS', '--key' => 'Predicted genes', '--type' => 'CDS:predicted,mRNA:exonerate,mRNA:predicted', '--metadata' => '{"fall_reason": "strain"}', '--autocomplete' => 'all', '--cssClass' => 'cds', '--compress', '--getPhase', '--getSubfeatures', ); my $hist_output = $read_json->(qw( tracks ExampleFeatures ctgA hist-10000-0.json )); is_deeply( $hist_output, [4,3,4,3,4,1], 'got right histogram output for ExampleFeatures' ) or diag explain( $hist_output ); my $names_output = [ map JSON::from_json($_), split "\n", $read_json->(qw( tracks ExampleFeatures ctgA names.txt )) ]; is_deeply( $names_output->[3], [ [ 'f05' ], 'ExampleFeatures', 'f05', 'ctgA', 4715, 5968 ], 'got the right names output' ) or diag explain $names_output; my $cds_trackdata = $read_json->(qw( tracks CDS ctgA trackData.jsonz )); is( $cds_trackdata->{featureCount}, 2, 'got right feature count for CDS track' ) or diag explain $cds_trackdata; is( scalar( @{$cds_trackdata->{histograms}{meta}}), scalar( @{$cds_trackdata->{histograms}{stats}}), 'have stats for each precalculated hist' ); my $class=$cds_trackdata->{intervals}{nclist}[1][0]; my $structure=$cds_trackdata->{intervals}{classes}[$class]; my @structure_attributes=$structure->{attributes}; my $index=0; for(my $i=0; $i < scalar @{$structure_attributes[0]}; $i++) { if( $structure_attributes[0][$i] eq 'Subfeatures' ) { $index=$i+1; } } is( ref $cds_trackdata->{intervals}{nclist}[1][$index], 'ARRAY', 'exonerate mRNA has its subfeatures' ) or diag explain $cds_trackdata; is( scalar @{$cds_trackdata->{intervals}{nclist}[1][$index]}, 5, 'exonerate mRNA has 5 subfeatures' ); my $tracklist = $read_json->('trackList.json'); is( $tracklist->{tracks}[1]{storeClass}, 'JBrowse/Store/SeqFeature/NCList' ); is_deeply( $tracklist->{tracks}[2]{metadata}, { fall_reason => 'strain' } ); is_deeply( $tracklist->{tracks}[1]{style}, { featureCss => 'height: 8px;', histScale => 2, className => 'feature2', linkTemplate => 'http://example.com/{name}/{start}/{end}' }, '--clientConfig and --urltemplate options seem to work' ) or diag explain $tracklist; #system "find $tempdir"; } {# diag "running on single_au9_gene.gff3, testing --type filtering"; my $tempdir = tempdir(); dircopy( 'tests/data/AU9', $tempdir ); run_with ( '--out' => $tempdir, '--gff' => "tests/data/AU9/single_au9_gene.gff3", '--trackLabel' => 'AU_mRNA', '--key' => 'AU mRNA', '--type' => 'mRNA', '--autocomplete' => 'all', '--cssClass' => 'transcript', '--getPhase', '--getSubfeatures', ); #system "find $tempdir"; my $read_json = sub { slurp( $tempdir, @_ ) }; my $cds_trackdata = $read_json->(qw( tracks AU_mRNA Group1.33 trackData.json )); is( $cds_trackdata->{featureCount}, 1, 'got right feature count' ) or diag explain $cds_trackdata; my $class=$cds_trackdata->{intervals}{nclist}[0][0]; my $structure=$cds_trackdata->{intervals}{classes}[$class]; my @structure_attributes=$structure->{attributes}; my $index=0; for(my $i=0; $i < scalar @{$structure_attributes[0]}; $i++) { if( $structure_attributes[0][$i] eq 'Subfeatures' ) { $index=$i+1; } } is( ref $cds_trackdata->{intervals}{nclist}[0][$index], 'ARRAY', 'mRNA has its subfeatures' ) or diag explain $cds_trackdata; is( scalar @{$cds_trackdata->{intervals}{nclist}[0][$index]}, 7, 'mRNA has 7 subfeatures' ); my $tracklist = $read_json->( 'trackList.json' ); is( $tracklist->{tracks}[0]{key}, 'AU mRNA', 'got a tracklist' ) or diag explain $tracklist; is_deeply( $tracklist->{tracks}[0]{style}, { className => 'transcript' }, 'got the right style' ) or diag explain $tracklist; # run it again with a different CSS class, check that it updated run_with ( '--out' => $tempdir, '--gff' => "tests/data/AU9/single_au9_gene.gff3", '--trackLabel' => 'AU_mRNA', '--key' => 'AU mRNA', '--type' => 'mRNA', '--autocomplete' => 'all', '--cssClass' => 'foo_fake_class', '--getPhase', '--getSubfeatures', ); $tracklist = $read_json->( 'trackList.json' ); is( $tracklist->{tracks}[0]{key}, 'AU mRNA', 'got a tracklist' ); is_deeply( $tracklist->{tracks}[0]{style}, { className => 'foo_fake_class'}, 'got the right style' ); # check that we got the same data as before $cds_trackdata = $read_json->(qw( tracks AU_mRNA Group1.33 trackData.json )); $class=$cds_trackdata->{intervals}{nclist}[0][0]; $structure=$cds_trackdata->{intervals}{classes}[$class]; @structure_attributes=$structure->{attributes}; $index=0; for(my $i=0; $i < scalar @{$structure_attributes[0]}; $i++) { if( $structure_attributes[0][$i] eq 'Subfeatures' ) { $index=$i+1; } } is( $cds_trackdata->{featureCount}, 1, 'got right feature count' ) or diag explain $cds_trackdata; is( ref $cds_trackdata->{intervals}{nclist}[0][$index], 'ARRAY', 'mRNA has its subfeatures' ) or diag explain $cds_trackdata; is( scalar @{$cds_trackdata->{intervals}{nclist}[0][$index]}, 7, 'mRNA has 7 subfeatures' ); } { #diag "running on single_au9_gene.gff3, testing that we emit 2 levels of subfeatures"; my $tempdir = tempdir(); dircopy( 'tests/data/AU9', $tempdir ); run_with ( '--out' => $tempdir, '--gff' => "tests/data/AU9/single_au9_gene.gff3", '--trackLabel' => 'AU_mRNA', '--key' => 'AU mRNA', '--type' => 'gene', '--autocomplete' => 'all', '--cssClass' => 'transcript', '--getPhase', '--getSubfeatures', ); #system "find $tempdir"; my $read_json = sub { slurp( $tempdir, @_ ) }; my $cds_trackdata = $read_json->(qw( tracks AU_mRNA Group1.33 trackData.json )); my $class=$cds_trackdata->{intervals}{nclist}[0][0]; my $structure=$cds_trackdata->{intervals}{classes}[$class]; my @structure_attributes=$structure->{attributes}; my $index=0; for(my $i=0; $i < scalar @{$structure_attributes[0]}; $i++) { if( $structure_attributes[0][$i] eq 'Subfeatures' ) { $index=$i+1; } } is( $cds_trackdata->{featureCount}, 1, 'got right feature count' ) or diag explain $cds_trackdata; is( ref $cds_trackdata->{intervals}{nclist}[0][$index], 'ARRAY', 'gene has its subfeatures' ) or diag explain $cds_trackdata; is( scalar @{$cds_trackdata->{intervals}{nclist}[0][$index]}, 1, 'gene has 1 subfeature' ); $class=$cds_trackdata->{intervals}{nclist}[0][$index][0][0]; $structure=$cds_trackdata->{intervals}{classes}[$class]; @structure_attributes=$structure->{attributes}; my $index_subfeature=0; for(my $i=0; $i < scalar @{$structure_attributes[0]}; $i++) { if( $structure_attributes[0][$i] eq 'Subfeatures' ) { $index_subfeature=$i+1; } } is( ref $cds_trackdata->{intervals}{nclist}[0][$index][0][$index_subfeature], 'ARRAY', 'mRNA has its subfeatures' ) or diag explain $cds_trackdata; is( scalar @{$cds_trackdata->{intervals}{nclist}[0][$index][0][$index_subfeature]}, 7, 'mRNA has 7 subfeatures' ); } { # diag "testing options to set class name in trackList.json"; my $tempdir = tempdir(); dircopy( 'tests/data/AU9', $tempdir ); # test default, should be 'feature' run_with ( '--out' => $tempdir, '--gff' => "tests/data/AU9/single_au9_gene.gff3", '--trackLabel' => 'AU_mRNA', ); my $read_json = sub { slurp( $tempdir, @_ ) }; my $trackList = $read_json->(qw( trackList.json ) ); ok( $trackList->{'tracks'}->[0]->{'style'}->{'className'} eq 'feature', "default cssClassName is feature"); run_with ( '--out' => $tempdir, '--gff' => "tests/data/AU9/single_au9_gene.gff3", '--trackLabel' => 'AU_mRNA', '--cssClass' => 'flingwibbit' ); $read_json = sub { slurp( $tempdir, @_ ) }; $trackList = $read_json->(qw( trackList.json ) ); ok( $trackList->{'tracks'}->[0]->{'style'}->{'className'} eq 'flingwibbit', "cssClassName set correctly"); } { # diag "testing options to set track type in trackList.json"; my $tempdir = tempdir(); dircopy( 'tests/data/AU9', $tempdir ); run_with ( '--out' => $tempdir, '--gff' => "tests/data/AU9/single_au9_gene.gff3", '--trackLabel' => 'AU_mRNA', ); my $read_json = sub { slurp( $tempdir, @_ ) }; my $trackList = $read_json->(qw( trackList.json ) ); ok( $trackList->{'tracks'}->[0]->{'type'} eq 'FeatureTrack', "default track type is FeatureTrack"); run_with ( '--out' => $tempdir, '--gff' => "tests/data/AU9/single_au9_gene.gff3", '--trackLabel' => 'AU_mRNA', '--trackType' => 'flingwibbit' ); $read_json = sub { slurp( $tempdir, @_ ) }; $trackList = $read_json->(qw( trackList.json ) ); ok( $trackList->{'tracks'}->[0]->{'type'} eq 'flingwibbit', "non-default track type set correctly"); } for my $testfile ( "tests/data/au9_scaffold_subset.gff3", "tests/data/au9_scaffold_subset_sync.gff3" ) { # add a test for duplicate lazyclasses bug found by Gregg my $tempdir = tempdir(); dircopy( 'tests/data/AU9', $tempdir ); run_with ( '--out' => $tempdir, '--gff' => $testfile, '--arrowheadClass' => 'transcript-arrowhead', '--getSubfeatures', '--subfeatureClasses' => '{"CDS": "transcript-CDS", "UTR": "transcript-UTR", "exon":"transcript-exon", "three_prime_UTR":"transcript-three_prime_UTR", "five_prime_UTR":"transcript-five_prime_UTR", "stop_codon":null, "start_codon":null}', '--cssClass' => 'transcript', '--type' => 'mRNA', '--trackLabel' => 'au9_full1', ); my $read_json = sub { slurp( $tempdir, @_ ) }; my $cds_trackdata = $read_json->(qw( tracks au9_full1 Group1.33 trackData.json )); is( $cds_trackdata->{featureCount}, 28, 'got right feature count' ) or diag explain $cds_trackdata; is( scalar @{$cds_trackdata->{intervals}{classes}}, 5, 'got the right number of classes' ) or diag explain $cds_trackdata->{intervals}{classes}; #system "find $tempdir"; } { # test for warnings my $tempdir = tempdir(); run_with ( '--out' => $tempdir, '--gff' => catfile('tests','data','SL2.40ch10_sample.gff3'), '--compress', '--key' => 'Assembly', '--trackLabel' => 'assembly', ); my $read_json = sub { slurp( $tempdir, @_ ) }; my $trackdata = FileSlurping::slurp_tree( catdir( $tempdir, qw( tracks assembly SL2.40ch10 ))); is( scalar( grep @{$trackdata->{$_}} == 0, grep /^lf/, sort keys %$trackdata ), 0, 'no empty chunks in trackdata' ) or diag explain $trackdata; } { # test BED import my $tempdir = tempdir(); run_with ( '--out' => $tempdir, '--bed' => catfile('tests','data','foo.bed'), '--compress', '--key' => 'Fooish Bar Data', '--trackLabel' => 'foo', ); my $read_json = sub { slurp( $tempdir, @_ ) }; my $trackdata = FileSlurping::slurp_tree( catdir( $tempdir, qw( tracks foo chr10 ))); is( scalar( grep @{$trackdata->{$_}} == 0, grep /^lf/, sort keys %$trackdata ), 0, 'no empty chunks in trackdata' ) or diag explain $trackdata; is_deeply( $trackdata->{'trackData.jsonz'}{intervals}{classes}[0], { 'attributes' => [ 'Start', 'End', 'Strand', 'Name', 'Score', 'Seq_id' ], 'isArrayAttr' => {} } ) or diag explain $trackdata->{'trackData.jsonz'}; } QUANTGFF3: { # test quantitative gff3 my $tempdir = tempdir(); run_with ( '--out' => $tempdir, '--gff' => catfile('tests','data','quantitative.gff3'), '--compress', '--key' => 'Quantitative GFF3 test', '--trackLabel' => 'quantgff3', ); my $read_json = sub { slurp( $tempdir, @_ ) }; my $trackdata = FileSlurping::slurp_tree( catdir( $tempdir, qw( tracks quantgff3 ctgA ))); is( scalar( grep @{$trackdata->{$_}} == 0, grep /^lf/, sort keys %$trackdata ), 0, 'no empty chunks in trackdata' ) or diag explain $trackdata; is_deeply( $trackdata->{'trackData.jsonz'}{intervals}{classes}[0], { 'attributes' => [ 'Start', 'End', 'Strand', 'Name', 'Score', 'Seq_id', 'Source', 'Type' ], 'isArrayAttr' => {} }) or diag explain $trackdata->{'trackData.jsonz'}; } { # test for whitespace trimming my $tempdir = tempdir(); run_with ( '--out' => $tempdir, '--gff' => catfile('tests','data','whitespace.gff3'), '--trackLabel' => 'whitespace', ); my $read_json = sub { slurp( $tempdir, @_ ) }; my $trackdata = FileSlurping::slurp_tree( catdir( $tempdir, qw( tracks whitespace ctgA )))->{'trackData.json'}; is( $trackdata->{featureCount}, 1, 'got right feature count' ) or diag explain $trackdata; is_deeply($trackdata->{intervals}->{nclist}[0][4], ['val1','val2','val3'], 'array whitespace trimmed'); is_deeply($trackdata->{intervals}->{nclist}[0][8], 'blah', 'normal whitespace trimmed'); is_deeply( $trackdata->{intervals}{classes}[0], { 'attributes' => [ 'Start', 'End', 'Strand', 'Multivalue', 'Name', 'Seq_id', 'Source', 'Testing', 'Type' ], 'isArrayAttr' => { 'Multivalue' => 1 } }) or diag explain $trackdata->{intervals}{classes}[0]; } done_testing;