Skip to content

Commit

Permalink
update agat_sp_add_start_and_stop.pl (#429)
Browse files Browse the repository at this point in the history
* avoid disturbing AGAT message when codon table is not set by bioperl (Use of uninitialized value)

* deal with GTF stop out of CDS. Add option ni/na to avoid to interpret IUPAC code in codons. Add option to extend the sequence to find the next start/stop codon in the sequence if absent from the CDS

* update test to reflect add of option na/ni and -e/--extend

* OmniscientI: allow to parse omniscient (config sub-hash was not handled)

* OmniscientI: fix bug in check_exons where exon location was not necessarly updated if needed because the test @ was wrong because was not the number of location but the size of the location object. I took the opportunity to update that part of the code to be more concise and efficient

* avoid message [[ not found during CI

---------

Co-authored-by: Jacques Dainat <[email protected]>
  • Loading branch information
Juke34 and Juke34 authored Feb 22, 2024
1 parent 180374e commit b3b4c47
Show file tree
Hide file tree
Showing 9 changed files with 555 additions and 1,040 deletions.
329 changes: 287 additions & 42 deletions bin/agat_sp_add_start_and_stop.pl

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions docs/tools/agat_sp_add_start_and_stop.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ agat_sp_add_start_and_stop.pl.pl --help

Output gff file updated

- **-e** or **--extend**

Boolean - When no start/stop codon found, try to extend the CDS to meet the next start/stop codon in the sequence.

- **--ni** or **--na**

Boolean - no iupac / no ambiguous, avoid usage of IUPAC. By default IUPAC is used that means, NNN is seen as start and/or stop codon.

- **-v**

Verbose for debugging purpose.
Expand Down
94 changes: 46 additions & 48 deletions lib/AGAT/OmniscientI.pm
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,13 @@ sub slurp_gff3_file_JD {
}
next;
}
# save header if any
if ($level eq 'config'){
foreach my $thing( keys %{$file->{'other'} } ){
$omniscient{'config'}{$thing} = $file->{'config'}{$thing};
}
next;
}
if ( ref($file->{$level}) eq 'HASH'){ #Header,level1,level2,#level3
foreach my $tag (keys %{$file->{$level}}){
foreach my $id (keys %{$file->{$level}{$tag}}){
Expand Down Expand Up @@ -2194,69 +2201,60 @@ sub _check_exons{
"a next step) !!\n") if($debug);

my $location_cpt=0;
foreach my $location (sort {$a->[1] <=> $b->[1] } @{$list_location_NoExon}){
$location_cpt++;
foreach my $location (sort {$a->[1] <=> $b->[1] } @{$list_location_NoExon}){
$location_cpt++;

my $create_exon=1;
my $new_location;
my $overlap;
my $create_exon=1;
my $new_location;
my $overlap;

foreach my $exon_location (sort {$a->[1] <=> $b->[1] } @{$list_location_Exon}){
foreach my $exon_location (sort {$a->[1] <=> $b->[1] } @{$list_location_Exon}){

($new_location, $overlap) = _manage_location_lowLevel_adjacent($location, $exon_location); #there is an overlap if $new_location != $exon_location. If it's the same, we should check $overlap to be sure
#there is an overlap if $new_location != $exon_location. If it's the same, we should check $overlap to be sure
($new_location, $overlap) = _manage_location_lowLevel_adjacent($location, $exon_location);

#The exon_location has been modified by location... We have to remodelate the exon (only if fit some conditions) location to take the modification into account
if($new_location->[1] < $exon_location->[1] or $new_location->[2] > $exon_location->[2] ){
$create_exon=undef; # We must avoid to create exon because there is an overlap.

if($new_location->[1] < $exon_location->[1] or $new_location->[2] > $exon_location->[2] ){ #The exon_location has been modified by location... We have to remodelate the exon (only if fit some conditions) location to take the modification into account
$create_exon=undef; # We must avoid to create exon because there is an overlap.
my $redefine_left=undef;
my $redefine_right=undef;

my $redefine_left=undef;
my $redefine_right=undef;
#first location => check left
if($location_cpt == 1){
if($new_location->[1] < $exon_location->[1]){ $redefine_left = $new_location->[1];} # Modify only if it's more left
}
#=> check left and right
if($location_cpt != 1 and $location_cpt != @$location){
if($new_location->[1] < $exon_location->[1]){ $redefine_left = $new_location->[1];} # Modify only if it's more left
if($new_location->[2] > $exon_location->[2]){ $redefine_right = $new_location->[2];} # Modify only if it's more right
}
#last location => check right
if($location_cpt == @$location){
if($new_location->[2] > $exon_location->[2]){ $redefine_right = $new_location->[2];} # Modify only if it's more right
}
if($new_location->[1] < $exon_location->[1]){ $redefine_left = $new_location->[1];} # Modify only if it's more left
if($new_location->[2] > $exon_location->[2]){ $redefine_right = $new_location->[2];} # Modify only if it's more right

if ($redefine_left or $redefine_right){
foreach my $l3_feature (@{$hash_omniscient->{'level3'}{'exon'}{$id_l2} } ){
if($l3_feature->_tag_value('ID') eq $exon_location->[0][0]){

foreach my $l3_feature (@{$hash_omniscient->{'level3'}{'exon'}{$id_l2} } ){
if($l3_feature->_tag_value('ID') eq $exon_location->[0][0]){

if($redefine_left){
if($redefine_left){
dual_print($log, "Modify the left location for ".$l3_feature->_tag_value('ID')." from ".$l3_feature->start()." to ".$new_location->[1]."\n", 0); #print only in log
$l3_feature->start($new_location->[1]); $resume_case2++;
}
else{$redefine_left = $exon_location->[1];}
$l3_feature->start($new_location->[1]); $resume_case2++;
}

if($redefine_right){
if($redefine_right){
dual_print($log, "Modify the right location for ".$l3_feature->_tag_value('ID')." from ".$l3_feature->end()." to ".$new_location->[2]."\n", 0); #print only in log
$l3_feature->end($new_location->[2]); $resume_case2++;
}
else{$redefine_right = $exon_location->[2];}

last;
}
}
}
elsif($overlap){ #location not modified but no overlap, so it means the exon is not defined ! <= ?? Not sure this comment is good 27th Nov 2018
$create_exon=undef;
}
}
$l3_feature->end($new_location->[2]); $resume_case2++;
}
last;
}
}
}
}
elsif($overlap){ #location not modified but no overlap, so it means the exon is not defined ! <= ?? Not sure this comment is good 27th Nov 2018
$create_exon=undef;
}
}

if($create_exon){
push @{$createIT{'exon'}}, $location;
}
if($create_exon){
push @{$createIT{'exon'}}, $location;
}
}
}
}
else{ dual_print($log, "No other feature to check the exon locations (e.g CDS, UTR, etc...). We can trust them then.\n") if ($debug)}
}
else{ $createIT{'exon'}=$list_location_NoExon;} # no exon exists, we have to create all of them
else{ $createIT{'exon'}=$list_location_NoExon;} # no exon exists, we have to create all of them

# NOW CREATE EXON IF NECESSARY
if(keys %createIT){
Expand Down
4 changes: 4 additions & 0 deletions lib/AGAT/Utilities.pm
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ sub get_proper_codon_table {
my ($codon_table_id_original) = @_;
my $codonTable = Bio::Tools::CodonTable->new( -id => $codon_table_id_original);
my $codon_table_id_bioperl = $codonTable->id;
if (!$codon_table_id_bioperl){
$codon_table_id_bioperl = 1 ;
$codonTable = Bio::Tools::CodonTable->new( -id => $codon_table_id_original);
}

if ($codon_table_id_original == 0 and $codon_table_id_original != $codon_table_id_bioperl){
$codonTable->warn("Your version of bioperl do not handle codon table 0\n".
Expand Down
2 changes: 1 addition & 1 deletion t/config.t
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ my $new_config_name = "agat_config_renamed.yml";
system("$script config -e --output $new_config_name --locus_tag Name");

#run test
ok( system("if [[ -e $new_config_name ]];then exit 0;fi") == 0, "rename agat config file check");
ok( system("if [ -e $new_config_name ];then exit 0;fi") == 0, "rename agat config file check");

# ----- Test use a renamed config file ----

Expand Down
9 changes: 8 additions & 1 deletion t/scripts_output.t
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,14 @@ unlink $outtmp;

$script = $script_prefix."bin/agat_sp_add_start_and_stop.pl";
$result = "$output_folder/agat_sp_add_start_and_stop_1.gff";
system(" $script --gff $input_folder/1.gff --fasta $input_folder/1.fa -o $outtmp 2>&1 1>/dev/null");
system(" $script --gff $input_folder/agat_sp_add_start_and_stop.gff --fasta $input_folder/1.fa --ni -o $outtmp 2>&1 1>/dev/null");
#run test
ok( system("diff $result $outtmp") == 0, "output $script");
unlink $outtmp;

$script = $script_prefix."bin/agat_sp_add_start_and_stop.pl";
$result = "$output_folder/agat_sp_add_start_and_stop_2.gff";
system(" $script --gff $input_folder/agat_sp_add_start_and_stop.gff --fasta $input_folder/1.fa -e --ni -o $outtmp 2>&1 1>/dev/null");
#run test
ok( system("diff $result $outtmp") == 0, "output $script");
unlink $outtmp;
Expand Down
86 changes: 86 additions & 0 deletions t/scripts_output/in/agat_sp_add_start_and_stop.gff
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
##gff-version 3
1 irgsp gene 303233 306736 . + . ID=gene:Os01g0105700;Name=basic helix-loop-helix protein 071;biotype=protein_coding;description=Basic helix-loop-helix dimerisation region bHLH domain containing protein. (Os01t0105700-01);gene_id=Os01g0105700;logic_name=irgspv1.0-20170804-genes
1 irgsp mRNA 303233 306736 . + . ID=transcript:Os01t0105700-01;Parent=gene:Os01g0105700;biotype=protein_coding;transcript_id=Os01t0105700-01
1 irgsp five_prime_UTR 303233 303328 . + . Parent=transcript:Os01t0105700-01
1 irgsp exon 303233 303471 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0105700-01.exon1;rank=1
1 irgsp CDS 303329 303471 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01
1 irgsp exon 303981 304509 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0105700-01.exon2;rank=2
1 irgsp CDS 303981 304509 . + 1 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01
1 irgsp exon 305572 305718 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon3;rank=3
1 irgsp CDS 305572 305718 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01
1 irgsp exon 305834 305899 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon4;rank=4
1 irgsp CDS 305834 305899 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01
1 irgsp exon 305993 306058 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon5;rank=5
1 irgsp CDS 305993 306058 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01
1 irgsp exon 306171 306245 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon6;rank=6
1 irgsp CDS 306171 306245 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01
1 irgsp CDS 306353 306490 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01
1 irgsp exon 306353 306736 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon7;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0105700-01.exon7;rank=7
1 irgsp three_prime_UTR 306494 306736 . + . Parent=transcript:Os01t0105700-01
###
1 irgsp gene 306871 308842 . - . ID=gene:Os01g0105800;Name=IRON-SULFUR CLUSTER PROTEIN 9;biotype=protein_coding;description=Similar to Iron sulfur assembly protein 1. (Os01t0105800-01);gene_id=Os01g0105800;logic_name=irgspv1.0-20170804-genes
1 irgsp mRNA 306871 308842 . - . ID=transcript:Os01t0105800-01;Parent=gene:Os01g0105800;biotype=protein_coding;transcript_id=Os01t0105800-01
1 irgsp three_prime_UTR 306871 307123 . - . Parent=transcript:Os01t0105800-01
1 irgsp exon 306871 307217 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0105800-01.exon4;rank=4
1 irgsp CDS 307127 307217 . - 1 ID=CDS:Os01t0105800-01;Parent=transcript:Os01t0105800-01;protein_id=Os01t0105800-01
1 irgsp exon 307296 307413 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon3;constitutive=1;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0105800-01.exon3;rank=3
1 irgsp CDS 307296 307413 . - 2 ID=CDS:Os01t0105800-01;Parent=transcript:Os01t0105800-01;protein_id=Os01t0105800-01
1 irgsp CDS 308397 308601 . - 0 ID=CDS:Os01t0105800-01;Parent=transcript:Os01t0105800-01;protein_id=Os01t0105800-01
1 irgsp exon 308397 308626 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0105800-01.exon2;rank=2
1 irgsp five_prime_UTR 308602 308626 . - . Parent=transcript:Os01t0105800-01
1 irgsp exon 308703 308842 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105800-01.exon1;rank=1
1 irgsp five_prime_UTR 308703 308842 . - . Parent=transcript:Os01t0105800-01
###
1 irgsp gene 309520 313170 . - . ID=gene:Os01g0105900;biotype=protein_coding;description=Carbohydrate/purine kinase domain containing protein. (Os01t0105900-01);gene_id=Os01g0105900;logic_name=irgspv1.0-20170804-genes
1 irgsp mRNA 309520 313170 . - . ID=transcript:Os01t0105900-01;Parent=gene:Os01g0105900;biotype=protein_coding;transcript_id=Os01t0105900-01
1 irgsp three_prime_UTR 309520 309821 . - . Parent=transcript:Os01t0105900-01
1 irgsp exon 309520 310070 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon8;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0105900-01.exon8;rank=8
1 irgsp CDS 309825 310070 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp exon 310256 310367 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0105900-01.exon7;rank=7
1 irgsp CDS 310256 310367 . - 1 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp exon 310455 310552 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon6;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0105900-01.exon6;rank=6
1 irgsp CDS 310455 310552 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp exon 310632 310739 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon5;rank=5
1 irgsp CDS 310632 310739 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp exon 310880 310918 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon4;rank=4
1 irgsp CDS 310880 310918 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp exon 311002 311073 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon3;rank=3
1 irgsp CDS 311002 311073 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp exon 311163 311426 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon2;rank=2
1 irgsp CDS 311163 311426 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp CDS 312867 313064 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01
1 irgsp exon 312867 313170 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0105900-01.exon1;rank=1
1 irgsp five_prime_UTR 313065 313170 . - . Parent=transcript:Os01t0105900-01
###
1 irgsp gene 319754 322205 . + . ID=gene:Os01g0106200;biotype=protein_coding;description=Similar to RER1A protein (AtRER1A). (Os01t0106200-01);gene_id=Os01g0106200;logic_name=irgspv1.0-20170804-genes
1 irgsp mRNA 319754 322205 . + . ID=transcript:Os01t0106200-01;Parent=gene:Os01g0106200;biotype=protein_coding;transcript_id=Os01t0106200-01
1 irgsp five_prime_UTR 319754 319874 . + . Parent=transcript:Os01t0106200-01
1 irgsp exon 319754 320236 . + . Parent=transcript:Os01t0106200-01;Name=Os01t0106200-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0106200-01.exon1;rank=1
1 irgsp CDS 319875 320236 . + 0 ID=CDS:Os01t0106200-01;Parent=transcript:Os01t0106200-01;protein_id=Os01t0106200-01
1 irgsp exon 321468 321648 . + . Parent=transcript:Os01t0106200-01;Name=Os01t0106200-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0106200-01.exon2;rank=2
1 irgsp CDS 321468 321648 . + 1 ID=CDS:Os01t0106200-01;Parent=transcript:Os01t0106200-01;protein_id=Os01t0106200-01
1 irgsp CDS 321928 321972 . + 0 ID=CDS:Os01t0106200-01;Parent=transcript:Os01t0106200-01;protein_id=Os01t0106200-01
1 irgsp exon 321928 322205 . + . Parent=transcript:Os01t0106200-01;Name=Os01t0106200-01.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0106200-01.exon3;rank=3
1 irgsp three_prime_UTR 321976 322205 . + . Parent=transcript:Os01t0106200-01
### No start no end
1 irgsp gene 25861 26424 . - . ID=gene:Os01g0100650;biotype=protein_coding;description=Hypothetical gene. (Os01t0100650-00);gene_id=Os01g0100650;logic_name=irgspv1.0-20170804-genes
1 irgsp mRNA 25861 26424 . - . ID=transcript:Os01t0100650-00;Parent=gene:Os01g0100650;biotype=protein_coding;transcript_id=Os01t0100650-00
1 irgsp three_prime_UTR 25861 26039 . - . Parent=transcript:Os01t0100650-00
1 irgsp exon 25861 26424 . - . Parent=transcript:Os01t0100650-00;Name=Os01t0100650-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0100650-00.exon1;rank=1
1 irgsp CDS 26058 26423 . - 0 ID=CDS:Os01t0100650-00;Parent=transcript:Os01t0100650-00;protein_id=Os01t0100650-00
1 irgsp five_prime_UTR 26424 26424 . - . Parent=transcript:Os01t0100650-00
### Sould extend to find start but avoid out of sequence (<0)
#1 irgsp gene 58658 61090 . + . ID=gene:Os01g0101150;biotype=protein_coding;description=Hypothetical conserved gene. (Os01t0101150-00);gene_id=Os01g0101150;logic_name=irgspv1.0-20170804-genes
#1 irgsp mRNA 58658 61090 . + . ID=transcript:Os01t0101150-00;Parent=gene:Os01g0101150;biotype=protein_coding;transcript_id=Os01t0101150-00
#1 irgsp exon 58658 61090 . + . Parent=transcript:Os01t0101150-00;Name=Os01t0101150-00.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0101150-00.exon1;rank=1
#1 irgsp CDS 58661 61000 . + 0 ID=CDS:Os01t0101150-00;Parent=transcript:Os01t0101150-00;protein_id=Os01t0101150-00
### Sequence length = 43270923. No start, No Stop . Extension to find stop should stop because reach end of sequence
1 irgsp gene 43270900 43270919 . + . ID=geneA
1 irgsp mRNA 43270900 43270919 . + . ID=transcriptA;Parent=geneA
1 irgsp exon 43270900 43270919 . + . Parent=transcriptA
1 irgsp CDS 43270900 43270919 . + 0 Parent=transcriptA
### Sequence length = 43270923. No start, No Stop . Extension to find start should stop because reach beginning of sequence
1 irgsp gene 34 123 . + . ID=geneX
1 irgsp mRNA 34 123 . + . ID=transcriptX;Parent=geneX
1 irgsp exon 34 123 . + . Parent=transcriptX
1 irgsp CDS 34 123 . + 0 Parent=transcriptX
Loading

0 comments on commit b3b4c47

Please sign in to comment.