2012-05-10 2 views
0

У меня возникли проблемы с манипулированием массивом данных последовательности ДНК, который находится в формате .fasta. То, что я хотел бы сделать, это взять файл с несколькими тысячами последовательностей и соседними данными последовательности для каждой последовательности в файле на одну строку в файле. [Формат Fasta такой: Идентификатор последовательности начинается с>, после которого все в этой строке является описанием. На следующей строке (-ях) присутствует последовательность, соответствующая этому идентификатору. И это может продолжаться бесконечно до следующей строки, которая начинается с>, которая является идентификатором следующей последовательности в файле. Итак, в моем конкретном файле большинство моих последовательностей находятся на нескольких строках, поэтому то, что я хотел бы сделать, по существу удалите новые строки, но только новые строки между данными последовательности, а не между данными последовательности и строками идентификатора последовательности (которые начинаются с>).Выборочное объединение элементов массива на меньшее количество элементов нового массива

Я делаю это, потому что хочу иметь возможность достигать длины последовательности каждой последовательности (по длине, я считаю, это самый простой способ), а затем получить среднюю длину последовательности всех последовательностей во всем файле.

Вот мой сценарий до сих пор, что не кажется, хотят работать:

#!/usr/bin/perl -w 


##Subroutine 
sub get_file_data1 { 
    my($filename) = $_[0]; 
    my @filedata =(); 
    unless(open(GET_FILE_DATA, $filename)) { 
    print STDERR "Cannot open file \"$filename\"\n\n"; 
    exit; 
    } 
    @filedata = <GET_FILE_DATA>; 
    close GET_FILE_DATA; 
    return @filedata; 
} 



##Opening files 
my $fsafile = $ARGV[0]; 
my @filedata = &get_file_data1($fsafile); 


##Procedure 
my @count; 
my @ids; 
my $seq; 

foreach $seq (@filedata){ 
     if ($seq =~ /^>/) {push @ids, $seq; 
           push @count, "\n"; 
    } 
     else {push @count, $seq; 
    } 
} 


foreach my $line (@count) { 
    if ($line =~ /^[AGTCagtc]/){ 
     $line =~ s/^([AGTCagtc]*)\n/$1/; 
    } 
} 

##Make a text file to have a look 
open FILE3, "> unbrokenseq.txt" or die "Cannot open output.txt: $!"; 

foreach (@count) 
{ 
    print FILE3 "$_\n"; # Print each entry in our array to the file 
} 
close FILE3; 


__END__ 
##Creating array of lengths 
my $number; 
my @numberarray; 
foreach $number (@count) { 
       push @numberarray, length($number); 
       } 
print @numberarray; 


__END__ 
use List::Util qw(sum); 

sub mean { 
    return sum(@numberarray)/@numberarray; 
} 

Там что-то случилось со вторым Еогеасп линии раздела Порядок и я не могу понять, что это является. Обратите внимание, что код после строк END я даже не пытался, потому что я не могу заставить код на шаге процедуры делать то, что я хочу. Любая идея, как я могу получить хороший массив с элементами непрерывной последовательности (я решил просто удалить строки идентификатора последовательности из нового массива ..)? Когда я могу получить массив длин, после чего я могу тогда усреднить?

Наконец-то я должен, к сожалению, признать, что я не могу заставить Bio :: Perl работать на моем компьютере, я пробовал несколько часов, но ошибки за пределами моего мастерства исправлены. Я буду говорить с кем-то, кто может с надеждой помочь мне с моими проблемами Bio :: perl. Но пока мне просто нужно нажимать без него.

Спасибо! Извините за длину этого сообщения, я ценю помощь.

Эндрю

ответ

0

Проблема с вашей второй петлей заключается в том, что вы ничего не меняете в @count, потому что $line содержит копию значений в @count.

Но если все, что вы хотите сделать во втором цикле, - это удалить символ новой строки в конце, используйте функцию chomp. с этим вам не понадобится ваш второй цикл.(И это также будет быстрее, чем с помощью регулярных выражений.)

# remove newlines for all array elements before doing anything else with it 
chomp @filedata; 

# .. or you can do it in your first loop 
foreach $seq (@filedata){ 
    chomp $seq; 
    if ($seq =~ /^>/) { 
    ... 
} 

Дополнительный совет: Использование get_file_data1 читать весь файл в массив может быть медленным, если файлы большого размера. В этом случае было бы лучше перебирать файл по мере того, как вы идете:

open my $FILE_DATA, $filename or die "Cannot open file \"$filename\"\n"; 
while (my $line = <$FILE_DATA>) { 
    chomp $line; 
    # process the record as in your Procedure section 
    ... 
} 
close $FILE_DATA; 
+0

Большое спасибо за ваш ответ, я думаю, что это, безусловно, путь. Хотя, подумав об этом, я думаю, что большая проблема, с которой я нахожусь здесь, заключается не в возможности выборочно конденсировать несколько элементов последовательности из массива только в один элемент. Я пытаюсь сконденсировать все элементы данных последовательности, соответствующие элементу идентификатора последовательности (которые начинаются с>) только одним элементом. Я наивно думал, что могу это сделать, просто удалив новые строки после элементов последовательности, но это не сработает. Поэтому я думаю, что мне нужно полностью восстановить это. – amrezans

-1

Ваше регулярное выражение захватывает специально для $ 1, но вы печатаете $ _ в файл. Результат, скорее всего, не то, что вы намеревались.

+0

Нет, эта часть кода верна. '$ _' присваивается каждому элементу' @ count'. – dolmen

-1

Будьте осторожны с модификатором '*' или 'greedy' для ваших групп символов в s ///. Вместо этого вы обычно хотите «+». '*' также будет соответствовать строкам, не содержащим ни одного из ваших символов.

Выражение поиска с помощью модификатора 'g' также может содержать символы. Например:

$perl -e '$a="aggaacaat"; $b = $a =~ s/[a]//g; print $b; ' 
5 

Pretty cool huh! В качестве альтернативы, в вашем коде вы можете просто вызвать length() против $ 1.

Я был поражен, чтобы увидеть escaped '/ n' в вашем регулярном выражении. Хотя он работает нормально, общий термин «конец линии» - «$». Это более портативно и не испортит ваш характер.

Смежные вопросы