Может ли хеш-ключ иметь несколько "подзначений" в perl?

У меня есть список генов и следующая информация:

  • Их зовут "XLOC_0000..."
  • Геномная эшафот, на которой они расположены: "Эшафот..."
  • Расположение каждой функции на ее скаффолде ("начало", "остановка")

Я написал фрагмент кода Perl, который находит каждый ген в геномных скаффолдах и сохраняет его в файл. Вкратце, сначала я поместил каждый ген в хэш массивов, например

 my %geneID = map { $xloc[$_] => [ $scaffold[$_], $start[$_], $stop[$_] ] } (0 .. $#xloc);

Затем я делаю хеш файла fasta, содержащего строительные леса:

open FASTA, '<', 'genome.fasta' || die "Can't open 'genome.fasta'\n"; #Read in 'fasta' file
my (@head, @sequence);
while (<FASTA>) { 
    chomp;
    push @head, $_ if /^>/;     
    push @sequence, $_ if /^[A-Z]/;
}

my %scaf;
@scaf{@head} = @sequence; # All scaffolds, as ordered in FH.

Затем я назначаю элементы первого HoA и, используя substr, нахожу начальную и конечную позиции гена в пределах одного и того же имени.

foreach my $xloc (sort keys %geneID) {
        print "gene sequence for $xloc is: ";
        my $chm = @{$geneID{$xloc}}[0];
        my $start = @{$geneID{$xloc}}[1];  
        my $end = @{$geneID{$xloc}}[2];
        my $seq = substr($scaf{$chm},$start-1,$end-($start-1));         
        print "$seq\n"; 
}

Проблема в том, что если у меня есть xloc с тем же именем, например, XLOC_00001, ключ хеша принимает только последнее значение. Я хочу иметь возможность добавлять несколько "подзначений" к каждому хешу, находить их местоположения с помощью substr и по существу объединять их вместе в конце.

Любые предложения о том, как это сделать?


ОБНОВИТЬ:

Это тестовый пример, показывающий результаты, которые я получаю:

"ГЕНОМ" ФАСТА ФАЙЛ

>Scaffold1
ONEATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold2
TWOATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold3
THREEATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold4
FOURATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold5
FIVEATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold6
SIXATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold7
SEVENATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold8
EIGHTATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold9
NINEATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA
>Scaffold10
TENATCGCGCTTAGTGCAGTACGTAGCTACGTGACTACTGA

КЛЮЧИ и значения для%geneID:

Key: XLOC_000027 contains the values: >Scaffold1 1 10 
Key: XLOC_000037 contains the values: >Scaffold2 1 15 
Key: XLOC_000038 contains the values: >Scaffold3 2 9 
Key: XLOC_000051 contains the values: >Scaffold4 6 8 
Key: XLOC_000077 contains the values: >Scaffold5 2 7 
Key: XLOC_000079 contains the values: >Scaffold6 4 16 
Key: XLOC_000096 contains the values: >Scaffold7 4 9 
Key: XLOC_000100 contains the values: >Scaffold8 3 20 
Key: XLOC_000117 contains the values: >Scaffold9 6 8 
Key: XLOC_000119 contains the values: >Scaffold10 7 14 

Результаты, показывающие "ген" в качестве подстроки каркаса, на котором он расположен для каждого XLOC:

gene sequence for XLOC_000027 is: ONEATCGCG
gene sequence for XLOC_000037 is: TWOATCGCGCTTAG
gene sequence for XLOC_000038 is: HREEATCG
gene sequence for XLOC_000051 is: TCGCGCT
gene sequence for XLOC_000077 is: IVEATC
gene sequence for XLOC_000079 is: ATCGCGCTTAGTGCA
gene sequence for XLOC_000096 is: ENATCGCG
gene sequence for XLOC_000100 is: GHTATCGCGCTTAGTGCAG
gene sequence for XLOC_000117 is: TCGCGCT
gene sequence for XLOC_000119 is: GCGCTTAGTGCAG

2 ответа

Решение

Похоже, вам нужно поместить каждый набор значений (scaffold, start, stop) в массив для каждого элемента %geneID хэш. Как это

my %geneID;
push @{ $geneID{ $xloc[$_] } }, [ $scaffold[$_], $start[$_], $stop[$_] ] for 0 .. $#xloc;

Затем, как только %scaf хэш был построен, вы можете создать конкатенацию подпоследовательностей в цикле по всем составляющим последовательности.

for my $xloc (sort keys %geneID) {

  my $sequence;
  for my $part (@{ $geneID{$xloc} }) {
    my ($chm, $start, $end) = @$part;
    my $off = $start - 1;
    my $len = $end - $off;
    $sequence .= substr $scaf{$chm}, $off, $len;
  }

  print "gene sequence for $xloc is: $sequence\n";
}

Надеюсь, это поможет.


Обновить

Кстати, у вас есть ошибка в вашем файле open заявление.

open FASTA, '<', 'genome.fasta' || die "Can't open 'genome.fasta'\n"

такой же как

open FASTA, '<', ('genome.fasta' || die "Can't open 'genome.fasta'\n")

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

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

open my $fasta, '<', 'genome.fasta' or die "Can't open 'genome.fasta'\n"

И, если это имеет значение для вас, положить \n на конце вашего die строка запрещает Perl отображать файл и номер строки, где произошла ошибка.

Весь этот цикл лучше написан

my $fasta_file = 'genome.fasta';
open my $fasta, '<', $fasta_file or die "Can't open '$fasta_file'";
my (%scaf, $scaffold);
while (<$fasta>) {
  chomp;
  $scaffold = $_ if /^>/;   
  $scaf{$scaffold} = $_ if /^[A-Z]/;
}

Если вы знаете, что у вас будут дубликаты, вы можете создать свои хэши в следующем формате:

use strict;
use warnings FATAL => 'all';

use Data::Dumper;

my %hash;
push @{$hash{key1}}, 'Value1';
push @{$hash{key2}}, 'Value2';
push @{$hash{key1}}, 'Value3';

print Dumper ( \%hash );

В Perl есть свойство autovivification, которое позволяет ему создавать хеш-значение, если оно не существует, и добавлять к нему, если оно существует. (при условии, что вы используете список-контекст)

$VAR1 = {
          'key2' => [
                      'Value2'
                    ],
          'key1' => [
                      'Value1',
                      'Value3'
                    ]
        };

Теперь вы можете получить arrayref из вашего хеш-ключа и изучить все Xloc (что бы это ни было).

Другие вопросы по тегам