Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Assigning multiple lines into first element of array

by shabird (Sexton)
on Feb 29, 2020 at 18:03 UTC ( [id://11113581]=perlquestion: print w/replies, xml ) Need Help??

shabird has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, I have a file in which there is a sequence of text just like this

>NM_030643.4 Homo sapiens apolipoprotein L4 (APOL4) GAGGTGCTGGGGAGCAGCGTGTTTGCTGTGCTTGATTGTGAGCTGCTGGGAAGTTGTGACTTTCATTTT +A CCTTTCGAATTCCTGGGTATATCTTGGGGGCTGGAGGACGTGTCTGGTTATTATATAGGTGCACAGCTG +G AGGTGAGATCCACACAGCTCAGACCAGCTGGATCTTGCTCAGTCTCTGTCAGAGGAAGATCCCTTGGAG +G AGGCCCCGCAGCGACATGGAGGGAGCTGCTTTGCTGAAAATCTTTGTCGTCTGCATCTGGAACCAAAAT +C >NM_001198855.1 Homo sapiens cytochrome P450 family 2 subfamily C mem +ber 8 (CYP2C8) ACATGTCAAAGAGACACACACTAAATTAGCAGGGAGTGTTATAAAAACTTTGGAGTGCAAGCTCACAGC +T GTCTTAATAAGAAGAGAAGGCTTCAATGGAACCTTTTGTGGTCCTGGTGCTGTGTCTCTCTTTTATGCT +T CTCTTTTCACTCTGGAGACAGAGCTGTAGGAGAAGGAAGCTCCCTCCTGGCCCCACTCCTCTTCCTATT +A >NR_029834.1 Homo sapiens microRNA 200a (MIR200A), microRNA CCGGGCCCCTGTGAGCATCTTACCGGACAGTGCTGGATTTCCCAGCTTGACTCTAACACTGTCTGGTAA +C GATGTTCAAAGGTGACCCGC >AC067940.1 Homo sapiens clone RP11-818E9, LOW-PASS SEQUENCE SAMPLING AAATACAACTTTAAATCAAAACGGTAAAAATTCCACTCTTTCATACTAACTTCAAAAGTATTTGCTTTA +A AAAAAAAGNNNNNNNNNNAAACTGAATTTCTATTAAGCATCTATTTATAGAAGAGAGTAAACACCCCGT +G AATAAAAGACAGAGAATTGTAGCAGCCCGAAGTCCCTTTTCTCTCCTCCCAAGCATTTGGCTCTGGTCC +A AATTCACATATCCTGCTCCGTAAAACAAAGTGCCTTGGTTAACCTAACGTTATTCCTTGAACAGTAGTT +T AGTGATCAACTAGTTTTTGTTGTTGTTGTTGTTTGAGACAGAGTCTCACTCTGTCGCCCAGGCTGGAGT +G CAGTGGCGAGATCTCAGCTCACTGCAACCTCTGCTGCCCAGGTTCAAGGGATTCTCCTGCCTCAGCCTC +C CAAGTAGCTGGTATTACAGGCACCTGCCACCGCGCCTGGCTAATTTTTTTTTTTTTTTTTTTTTGTATT +T

i have loaded the file into an array and now i want to assign lines starting from ">" and ending on another ">" to first element of an array

>NM_030643.4 Homo sapiens apolipoprotein L4 (APOL4) GAGGTGCTGGGGAGCAGCGTGTTTGCTGTGCTTGATTGTGAGCTGCTGGGAAGTTGTGACTTTCATTTT +A CCTTTCGAATTCCTGGGTATATCTTGGGGGCTGGAGGACGTGTCTGGTTATTATATAGGTGCACAGCTG +G AGGTGAGATCCACACAGCTCAGACCAGCTGGATCTTGCTCAGTCTCTGTCAGAGGAAGATCCCTTGGAG +G AGGCCCCGCAGCGACATGGAGGGAGCTGCTTTGCTGAAAATCTTTGTCGTCTGCATCTGGAACCAAAAT +C

Here is my code

my $filename = '/file.fasta'; if(!open(MY_HANDLE, $filename)){ die "Couldnt open file"; } my @chars = <MY_HANDLE>; print "@chars[0]\n";

It is just returning first line of the file as a first element

OUTPUT

>NM_030643.4 Homo sapiens apolipoprotein L4 (APOL4)

please help me how can i achieve my desired sequence

Replies are listed 'Best First'.
Re: Assigning multiple lines into first element of array
by tybalt89 (Monsignor) on Feb 29, 2020 at 22:42 UTC

    Read to the next "\n>" and then fix up the line ends.

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11113581 use warnings; my $filename = 'file.fasta'; open my $handle, '<', $filename or die "$! opening $filename"; my @array = map s/>\z//r =~ s/^(?!>)/>/r, do { local $/ ="\n>"; <$hand +le> }; use Data::Dumper; print Dumper \@array;

    Or read the whole thing and split with a look-ahead for >

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11113581 use warnings; my $filename = 'file.fasta'; open my $handle, '<', $filename or die "$! opening $filename"; my @array = split /(?=>)/, do { local $/; <$handle> }; use Data::Dumper; print Dumper \@array;

      Thank you so much! it worked like a charm :)

      Everything works good but one more thing how can i count number of characters in first element of the array? When it returns first element of array it has many characters e.g: GAGGTGCTGGGGAGCAGCGTGTTTGCTGTGCTTGATTGTGAGCTGCTGGGAAGTTGTGACTTTCATTTTA CCTTTCGAATTCCTGGGTATATCTTGGGGGCTGGAGGACGTGTCTGGTTATTATATAGGTGCACAGCTGG. how come i count these characters?

        See length:

        c:\@Work\Perl\monks>perl -wMstrict -le "my @ra = ('MANYCHARACTERS'); printf qq{1st element of array has %d characters \n}, length $ra[0]; " 1st element of array has 14 characters


        Give a man a fish:  <%-{-{-{-<

        ...

        my @counts = map s/.*\n//r =~ tr/A-Z//, @array; print "counts: @counts\n";
Re: Assigning multiple lines into first element of array
by BillKSmith (Monsignor) on Feb 29, 2020 at 20:13 UTC
    Here is an easy way to get very close to what you want. The '>' is removed from the start of every line and it is added to the end of every line (except the last).
    use strict; use warnings; use Data::Dumper; my $filename = 'file.fasta'; open( my $MY_HANDLE, '<', $filename ) or die "Couldn't open file"; (undef, my @chars) = do{local $/="\n>"; <$MY_HANDLE>}; print Dumper(\@chars);

    OUTPUT:

    $VAR1 = [ 'NM_001198855.1 Homo sapiens cytochrome P450 family 2 subfam +ily C memb er 8 (CYP2C8) ACATGTCAAAGAGACACACACTAAATTAGCAGGGAGTGTTATAAAAACTTTGGAGTGCAAGCTCACAGCT GTCTTAATAAGAAGAGAAGGCTTCAATGGAACCTTTTGTGGTCCTGGTGCTGTGTCTCTCTTTTATGCTT CTCTTTTCACTCTGGAGACAGAGCTGTAGGAGAAGGAAGCTCCCTCCTGGCCCCACTCCTCTTCCTATTA >', 'NR_029834.1 Homo sapiens microRNA 200a (MIR200A), microRNA CCGGGCCCCTGTGAGCATCTTACCGGACAGTGCTGGATTTCCCAGCTTGACTCTAACACTGTCTGGTAAC GATGTTCAAAGGTGACCCGC >', 'AC067940.1 Homo sapiens clone RP11-818E9, LOW-PASS SEQUENCE + SAMPLING AAATACAACTTTAAATCAAAACGGTAAAAATTCCACTCTTTCATACTAACTTCAAAAGTATTTGCTTTAA AAAAAAAGNNNNNNNNNNAAACTGAATTTCTATTAAGCATCTATTTATAGAAGAGAGTAAACACCCCGTG AATAAAAGACAGAGAATTGTAGCAGCCCGAAGTCCCTTTTCTCTCCTCCCAAGCATTTGGCTCTGGTCCA AATTCACATATCCTGCTCCGTAAAACAAAGTGCCTTGGTTAACCTAACGTTATTCCTTGAACAGTAGTTT AGTGATCAACTAGTTTTTGTTGTTGTTGTTGTTTGAGACAGAGTCTCACTCTGTCGCCCAGGCTGGAGTG CAGTGGCGAGATCTCAGCTCACTGCAACCTCTGCTGCCCAGGTTCAAGGGATTCTCCTGCCTCAGCCTCC CAAGTAGCTGGTATTACAGGCACCTGCCACCGCGCCTGGCTAATTTTTTTTTTTTTTTTTTTTTGTATTT ' ];

    I also recommend that you check CPAN for modules that help with parsing fasta files. Sorry, I cannot offer more specific help.

    Bill
Re: Assigning multiple lines into first element of array
by tybalt89 (Monsignor) on Mar 01, 2020 at 02:00 UTC

    Simple "line at a time" version.

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11113581 use warnings; my $filename = 'file.fasta'; open my $handle, '<', $filename or die "$! opening $filename"; my @array; while( <$handle> ) { /^>/ and push @array, ''; $array[-1] .= $_; } use Data::Dumper; print Dumper \@array;
Re: Assigning multiple lines into first element of array
by johngg (Canon) on Feb 29, 2020 at 18:30 UTC

    Does your input file really have a leading space on every line except the first? That seems a bit odd and I wonder if it could be an error in posting. Please clarify.

    Cheers,

    JohnGG

      No it doesn't have a leading space in any line it is an error while posting.
        ... an error while posting.

        Please correct the erroneous OPed example data. And if you do correct it (which I strongly encourage), please note that you have done so. Please see How do I change/delete my post?


        Give a man a fish:  <%-{-{-{-<

Re: Assigning multiple lines into first element of array
by johngg (Canon) on Mar 01, 2020 at 00:46 UTC

    Thank you for clearing up the file layout question. I don't know if the following approach will be helpful to you but I wonder if, rather than an array, a hash table might be something to explore. A hash (also sometimes called an associative array) is arranged as key and value pairs. Here I initialise scalars to hold the sequence name and the sequence characters and also the hash in which sequences will be stored. Then I read the file line by line using chomp to remove line endings then storing the ">......." line as the key and concatenating the following lines together to form the value. When I encounter the next ">......." line or when I reach the end of file I call the addSequence() subroutine to add the key/value pair to the hash. Note that when the first ">......." line is read addSequence() is called but nothing as added to the hash as the stored sequence title is empty.

    The output shows the sorted keys from the resultant hash then I use the Data::Dumper module to show the actual hash in the form 'key' => 'value', the output now wrapping because of the long, concatenated lines. If it was preferred to keep the sequence data lines separated in an array this could be easily accomplished.

    use 5.026; use warnings; use Data::Dumper; open my $inFH, q{<}, \ <<__EOD__ or die $!; >NM_030643.4 Homo sapiens apolipoprotein L4 (APOL4) GAGGTGCTGGGGAGCAGCGTGTTTGCTGTGCTTGATTGTGAGCTGCTGGGAAGTTGTGACTTTCATTTTA CCTTTCGAATTCCTGGGTATATCTTGGGGGCTGGAGGACGTGTCTGGTTATTATATAGGTGCACAGCTGG AGGTGAGATCCACACAGCTCAGACCAGCTGGATCTTGCTCAGTCTCTGTCAGAGGAAGATCCCTTGGAGG AGGCCCCGCAGCGACATGGAGGGAGCTGCTTTGCTGAAAATCTTTGTCGTCTGCATCTGGAACCAAAATC >NM_001198855.1 Homo sapiens cytochrome P450 family 2 subfamily C memb +er 8 (CYP2C8) ACATGTCAAAGAGACACACACTAAATTAGCAGGGAGTGTTATAAAAACTTTGGAGTGCAAGCTCACAGCT GTCTTAATAAGAAGAGAAGGCTTCAATGGAACCTTTTGTGGTCCTGGTGCTGTGTCTCTCTTTTATGCTT CTCTTTTCACTCTGGAGACAGAGCTGTAGGAGAAGGAAGCTCCCTCCTGGCCCCACTCCTCTTCCTATTA >NR_029834.1 Homo sapiens microRNA 200a (MIR200A), microRNA CCGGGCCCCTGTGAGCATCTTACCGGACAGTGCTGGATTTCCCAGCTTGACTCTAACACTGTCTGGTAAC GATGTTCAAAGGTGACCCGC >AC067940.1 Homo sapiens clone RP11-818E9, LOW-PASS SEQUENCE SAMPLING AAATACAACTTTAAATCAAAACGGTAAAAATTCCACTCTTTCATACTAACTTCAAAAGTATTTGCTTTAA AAAAAAAGNNNNNNNNNNAAACTGAATTTCTATTAAGCATCTATTTATAGAAGAGAGTAAACACCCCGTG AATAAAAGACAGAGAATTGTAGCAGCCCGAAGTCCCTTTTCTCTCCTCCCAAGCATTTGGCTCTGGTCCA AATTCACATATCCTGCTCCGTAAAACAAAGTGCCTTGGTTAACCTAACGTTATTCCTTGAACAGTAGTTT AGTGATCAACTAGTTTTTGTTGTTGTTGTTGTTTGAGACAGAGTCTCACTCTGTCGCCCAGGCTGGAGTG CAGTGGCGAGATCTCAGCTCACTGCAACCTCTGCTGCCCAGGTTCAAGGGATTCTCCTGCCTCAGCCTCC CAAGTAGCTGGTATTACAGGCACCTGCCACCGCGCCTGGCTAATTTTTTTTTTTTTTTTTTTTTGTATTT __EOD__ my $seqTitle = q{}; my $accumulator = q{}; my %sequences = (); while ( <$inFH> ) { chomp; if ( m{^>} ) { addSequence(); } else { $accumulator .= $_; } } addSequence(); close $inFH or die $!; say for sort keys %sequences; say q{-} x 50; print Data::Dumper ->new( [ \ %sequences ], [ qw{ *sequences } ] ) ->Sortkeys( 1 ) ->Dumpxs(); sub addSequence { $sequences{ $seqTitle } = $accumulator if $seqTitle; $seqTitle = $_; $accumulator = q{}; }

    The output.

    >AC067940.1 Homo sapiens clone RP11-818E9, LOW-PASS SEQUENCE SAMPLING >NM_001198855.1 Homo sapiens cytochrome P450 family 2 subfamily C memb +er 8 (CYP2C8) >NM_030643.4 Homo sapiens apolipoprotein L4 (APOL4) >NR_029834.1 Homo sapiens microRNA 200a (MIR200A), microRNA -------------------------------------------------- %sequences = ( '>AC067940.1 Homo sapiens clone RP11-818E9, LOW-PASS SE +QUENCE SAMPLING' => 'AAATACAACTTTAAATCAAAACGGTAAAAATTCCACTCTTTCATACTA +ACTTCAAAAGTATTTGCTTTAAAAAAAAAGNNNNNNNNNNAAACTGAATTTCTATTAAGCATCTATTTA +TAGAAGAGAGTAAACACCCCGTGAATAAAAGACAGAGAATTGTAGCAGCCCGAAGTCCCTTTTCTCTCC +TCCCAAGCATTTGGCTCTGGTCCAAATTCACATATCCTGCTCCGTAAAACAAAGTGCCTTGGTTAACCT +AACGTTATTCCTTGAACAGTAGTTTAGTGATCAACTAGTTTTTGTTGTTGTTGTTGTTTGAGACAGAGT +CTCACTCTGTCGCCCAGGCTGGAGTGCAGTGGCGAGATCTCAGCTCACTGCAACCTCTGCTGCCCAGGT +TCAAGGGATTCTCCTGCCTCAGCCTCCCAAGTAGCTGGTATTACAGGCACCTGCCACCGCGCCTGGCTA +ATTTTTTTTTTTTTTTTTTTTTGTATTT', '>NM_001198855.1 Homo sapiens cytochrome P450 family 2 +subfamily C member 8 (CYP2C8)' => 'ACATGTCAAAGAGACACACACTAAATTAGCAGGG +AGTGTTATAAAAACTTTGGAGTGCAAGCTCACAGCTGTCTTAATAAGAAGAGAAGGCTTCAATGGAACC +TTTTGTGGTCCTGGTGCTGTGTCTCTCTTTTATGCTTCTCTTTTCACTCTGGAGACAGAGCTGTAGGAG +AAGGAAGCTCCCTCCTGGCCCCACTCCTCTTCCTATTA', '>NM_030643.4 Homo sapiens apolipoprotein L4 (APOL4) ' +=> 'GAGGTGCTGGGGAGCAGCGTGTTTGCTGTGCTTGATTGTGAGCTGCTGGGAAGTTGTGACTTTCA +TTTTACCTTTCGAATTCCTGGGTATATCTTGGGGGCTGGAGGACGTGTCTGGTTATTATATAGGTGCAC +AGCTGGAGGTGAGATCCACACAGCTCAGACCAGCTGGATCTTGCTCAGTCTCTGTCAGAGGAAGATCCC +TTGGAGGAGGCCCCGCAGCGACATGGAGGGAGCTGCTTTGCTGAAAATCTTTGTCGTCTGCATCTGGAA +CCAAAATC', '>NR_029834.1 Homo sapiens microRNA 200a (MIR200A), mic +roRNA' => 'CCGGGCCCCTGTGAGCATCTTACCGGACAGTGCTGGATTTCCCAGCTTGACTCTAACA +CTGTCTGGTAACGATGTTCAAAGGTGACCCGC' );

    This is all speculative. You may have a very good reason to keep all of the lines together as one element of an array but if you need to access individual sequences by name I think that a hash table is the way to go.

    Cheers,

    JohnGG

Re: Assigning multiple lines into first element of array
by Veltro (Hermit) on Feb 29, 2020 at 23:21 UTC

    Or you could change the "input record separator" and use the diamond operator <>

    use strict ; use warnings ; my $filename = 'file.fasta'; open my $fh, '<', $filename or die "Could not open file" ; my @chars ; { # Calling local $/ sets the input record separator in this block local $/ = '>' ; while(<$fh>) { chomp ; push @chars, $_ ; } } for ( @chars ) { chomp ; print $_ . "\n" ; }

    Output not verified (because of the leading space)

    edit: One thing though, the first element in the array does not contain a result this way.

    edit 2: Changed the open statement

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11113581]
Approved by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-23 07:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found