2

psiblastからの出力レポートを解析しています。COGアラインメントを使用して、遺伝子データベースで一致するもの(ホモログ)を検索しました。私がやりたいことの1つは、どの遺伝子が複数のCOGに一致するかを見つけることです。私の部分的なスクリプトは以下のとおりです。

特に、複数のCOGに割り当てられている遺伝子のすべてのCOGを保持する配列を作成する際に問題が発生しています。

parse_POG_reports.plの26行目、67行目で「strictrefs」を使用しているときに、「文字列( "COG0003")をARRAY参照として使用できません」というエラーが発生します。

要素を配列のハッシュにプッシュすることに関連する他の投稿を見てきました。しかし、1つの遺伝子が同じCOGに2つ一致し、同じCOGを配列(つまり、サンプル入力の最後の2行)にプッシュしようとすると、エラーが発生する可能性があると思います。これは意味がありますか?もしそうなら、どうすればこの問題を回避できますか?

use strict;
use warnings;

my %maxBits;my %COGhit_count;
my $Hohits={};my %COGhits;

my $COG_psi_report=$ARGV[0];
open (IN, $COG_psi_report) or die "cannot open $COG_psi_report\n";
while (my $line=<IN>){
    next if ($line =~/^#/);
    chomp $line;
    my @columns = split(/\t/,$line);
    my $bits=$columns[11];
    my $COG=$columns[0];
    my $hit=$columns[1];
    my $Eval=$columns[10];
    next if ($Eval > 0.00001); # threshold for significant hits set by DK
    $COGhit_count{$hit}++; # count how many COGs each gene is homologous to
    $COGhits{$hit}=$COG;
    if ($COGhit_count{$hit}>1) {
            push @{$COGhits{$hit}}, $COG; #
    }
    ## for those that there are multiple hits we need to select top hit ##
    if (!exists $maxBits{$hit}){
            $maxBits{$hit}=$bits;
    }
    elsif (exists $maxBits{$hit} && $bits > $maxBits{$hit}){
            $maxBits{$hit}=$bits;
    }
    $Hohits->{$hit}->{$bits}=$COG;
}
close (IN);

入力例:

POG0002 764184357-stool1_revised_scaffold22981_1_gene47608      23.90   159     112     3       1       156     1       153     2e-06   54.2
POG0002 764062976-stool2_revised_C999233_1_gene54902    23.63   182     121     5       3       169     2       180     2e-06   53.9
POG0002 763901136-stool1_revised_scaffold39447_1_gene145241     26.45   155     89      3       3       137     5       154     3e-06   53.9
POG0002 765701615-stool1_revised_C1349270_1_gene168522  23.53   187     115     5       3       169     2       180     5e-06   53.1
POG0002 158802708-stool2_revised_C1077267_1_gene26470   22.69   216     158     5       3       213     5       216     5e-06   52.7
POG0003 160502038-stool1_revised_scaffold47906_2_gene161164     33.00   297     154     6       169     424     334     626     6e-40    157
POG0003 160502038-stool1_revised_scaffold47906_2_gene161164     16.28   172     128     4       23      192     46      203     1e-06   56.6
POG0003 158337416-stool1_revised_C1254444_1_gene13533   30.06   346     184     7       133     424     57      398     6e-40    155
POG0003 158337416-stool1_revised_scaffold29713_1_gene153054     28.61   332     194     8       132     424     272     599     2e-38    152
POG0003 158337416-stool1_revised_scaffold29713_1_gene153054     24.00   200     131     5       1       193     5       190     9e-11   69.3
4

2 に答える 2

1

24行目を取り除く必要があります(逆算):

$COGhits{$hit}=$COG;

$COGhits{$hit}その中で、スカラー値(の値)に設定しています$COG$COGhits{$hit}後で、26行目で、配列として逆参照してプッシュしようとしています。そこにスカラーがあるので、それは機能しません。

を削除してif、これらの行をこれに変更するだけです。$hitこれらはすべて配列参照に格納されるため、これでうまくいくはずです。

$COGhit_count{$hit}++; # count how many COGs each gene is homologous to
push @{$COGhits{$hit}}, $COG;

の出力$COGhits

$VAR4 = {
      '158802708-stool2_revised_C1077267_1_gene26470' => [
                                                           'POG0002'
                                                         ],
      '764062976-stool2_revised_C999233_1_gene54902' => [
                                                          'POG0002'
                                                        ],
      '764184357-stool1_revised_scaffold22981_1_gene47608' => [
                                                                'POG0002'
                                                              ],
      '765701615-stool1_revised_C1349270_1_gene168522' => [
                                                            'POG0002'
                                                          ],
      '763901136-stool1_revised_scaffold39447_1_gene145241' => [
                                                                 'POG0002'
                                                               ],
      '160502038-stool1_revised_scaffold47906_2_gene161164' => [
                                                                 'POG0003',
                                                                 'POG0003'
                                                               ]
    };

ただし、スカラーと配列refの両方が必要な場合は、このコードを試してください。ただし、これはお勧めしません

$COGhit_count{$hit}++; # count how many COGs each gene is homologous to
if ($COGhit_count{$hit} == 1) {
  $COGhits{$hit}=$COG;             # Save as scalar
}
elsif ($COGhit_count{$hit} == 2) { # If we've just found the second hit,
  my $temp = $COGhits{$hit};       # save the first and convert $COGhits{$hit}
  $COGhits{$hit} = [];             # to an array ref, then push both the old and
  push @{$COGhits{$hit}}, $temp, $COG; # the new value in it.
} elsif ($COGhit_count{$hit} > 2) {
  push @{$COGhits{$hit}}, $COG;    # Just push the new value in
}

考え:おそらく$COGhits{$hit}=$COG最初に、複数の値が存在する場合があることに気付いたので、push行を追加しましたが、実際には古い行を置き換える必要があることに気づいていませんでした。

于 2012-07-26T14:48:39.603 に答える
0

それはあなたが間違っていることを正確に伝えています。

$COGhits{$hit}=$COG;  # <--- scalar
if ($COGhit_count{$hit}>1) {
        push @{$COGhits{$hit}}, $COG; # <--- array
}

値を非参照型として割り当ててから、参照型として自動有効化することはできません。Perl は後者を行いますが、競合するデータ型をその場所に既に保存している場合は行いません。

また、これが何らかの奇跡によって初めて機能し (機能しない)、これを複数回実行した場合、プッシュによって autoviv-ed された可能性のある配列は、スカラーの非参照代入によって破壊されます。

何を求めているのかわかりませんが、最初の行はおそらく削除する必要があります。


$COGその構造の代わりに、 の値に対してが複数指定されるかどうかを判断する必要があります$hit。可能であれば、それらの 4 行を に置き換えるだけpushです。

以前に多目的構造スロットを作成したことがありますが、それらは主に維持するのが面倒です。しかし、そのようなことをしたい場合は、これを行うことができます:

my $ref = \$hashref->{ $key }; # autovivifies slot as simple scalar.
                               # it starts out as undefined.
if ( ref $$ref ) {             # ref $ref will always be true
    push @$$ref, $value;
}
else { 
    $$ref = defined( $$ref ) ? [ $$ref, $value ] : $value;
}

ただし、混合ツリーに別の方法でアクセスするたびに、分岐ロジックを作成する必要があります。スカラーで得られるパフォーマンスの節約は、テストと分岐によっていくらか食い尽くされます。

だから私はもうこれをあまりしません。その関係が1-1なのか1-nなのかは事前に決めています。以下のようなルーチンを使用すると、この種のテーブルをある程度簡単に処理できます。

sub get_list_from_hash { 
    my ( $hash, $key ) = @_;
    my $ref = \$hash->{ $key };
    return unless defined( $$ref );
    return ref( $$ref ) ? @$$ref : $$ref;
}

sub store_in_hash { 
    $_[0] = {} unless ref $_[0];
    my ( $hash, $key, @values ) = @_;
    my @defined = grep {; defined } @values;
    unless ( @defined ) { 
        delete $hash->{ $key };
        return;
    }

    my $ref = \$hash->{ $key };
    if ( ref $$ref ) { 
        push @$$ref, @defined;
    }
    elsif ( defined $$ref ) { 
        $$ref = [ $$ref, @defined ];
    }
    elsif ( @values > 1 ) { 
        @$$ref = @defined;
    }
    else { 
        ( $$ref ) = @defined;
    }
}
于 2012-07-26T14:51:27.213 に答える