【问题标题】:Curiously behaving IF block in Perl run on WindowsPerl 中奇怪的 IF 块在 Windows 上运行
【发布时间】:2014-06-13 16:42:04
【问题描述】:

背景:我编写了一个 Perl 脚本,用于遍历两个文件。该脚本的基本点是识别一个坐标列表之间的重叠,定义随机选择的染色体片段的开始和结束,以及第二个坐标列表,定义实际基因转录的开始和结束。

第一个输入文件包含三列。第一个是染色体编号,第二个和第三个是随机选择区域的近端和远端坐标,以碱基对表示。例如,

chr1    1100349    2035647
chr1    47837656   736474584
.       .          .
.       .          .
.       .          .

第二个输入文件包含四列:染色体编号、近端坐标、远端坐标和基因名称。例如,

chr1    1588354    2283765    geneA
chr1    55943837   787653743    geneB

这是我开始使用的一组测试文件。 第一组。

chr1    1   10
chr1    5   10
chr1    5   15
chr1    14  15
chr1    100 101
chr1    11  17

第二组。

chr1    1   5   geneA
chr1    7   10  geneB
chr1    12  16  geneC
chr1    18  21  geneD
chr10   126602211   126609396   B4galnt1

脚本从第一个列表中读取第一行,然后读取第二个列表的所有行,并为我打印第一个坐标对是否以及如何与第二个坐标对重叠(第一个坐标对是否在外面第二对?第一对在里面还是与第二对重叠?)然后,脚本返回并从第一个列表中读取第二行,并重复该过程。第一个文件有 200,000 行。第二个几千。它现在在一夜之间运行。

问题:当脚本确定第一和第二坐标对之间的关​​系时,它会在输出文件中打印一行。并非所有这些打印语句需要发送到输出,所以我尝试将它们注释掉。但是,当我这样做时,没有打印向输出文件发送信息的打印语句。但是,语句会打印到屏幕上,而不是输出文件。脚本正在运行,但所有的打印到输出语句都在使用,因此输出文件变得越来越大。如果脚本只打印输出那些重叠的坐标,那么输出文件会非常非常小。目前,输出文件现在为 2,131,294 KB!这仅到 11 号染色体。还有 8 个要检查,尽管较小,但文件大小仍将大大扩展。

更新信息:这是在我最初发布之后编辑的。更准确地说,只有当我注释掉循环内的第一个 print $output "..."; 语句(第一个语句是打印标题,这是在循环之前)时,脚本才能打印任何内容,甚至当所有其他人都独自一人时(未评论)。

以防万一:我在我的 Mac 上使用 Fraise 编写了脚本,但我在 PC 上运行它,该脚本包含在记事本文本文件中。

脚本如下: 注意:文件中有很多打印语句,很多都被注释掉了。感兴趣的打印语句是那些打印到输出文件的语句。这些是那些,当一个或多个被注释掉时,最终不会将信息发送到输出文件。这些语句看起来像:

print $output  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tinside\n";

实际脚本:

#!/bin/usr/perl
use strict; use warnings;

#############
## findGenes_after_ASboot_v5.pl
#############

#############
#  After making a big list of randomly placed intervals,
#  this script uses RefGene.txt file and identifies the 
#  the gene symbols encompassed or overlapped by each random interval 
#############

unless(scalar @ARGV == 2) {
    # $0 name of the program being executed;
    print "\n usage: $0 filename containig your list of positions and a RefGene-type file \n\n"; 
    exit;
}

#for ( my $i = 0; $i < 25; $i++ ){
#     print "#########################################\n";
#}

open( my $positions, "<", $ARGV[0] ) or die;
open( my $RefGene,   "<", $ARGV[1] ) or die;

open( my $output, ">>", "output.txt") or die;

# print header
print $output "chr\tpos count\tpos1\tpos2\tchr\tref count\tref1\tref2\tname2\trelationship\n";

my $pos_count = 1;
my $ref_count = 1;

for my $position_line (<$positions>) {
    #print "$position_line";
    my @posline = split('\t', $position_line);
    #print "$posline[0]\t$posline[1]\t$posline[2]";
    open( my $RefGene,   "<", $ARGV[1] ) or die;

    for my $ref (<$RefGene>){
        #print "\t$ref";    
        my @refline = split('\t', $ref);
        # print "\t$refline[0]\t$refline[1]\t$refline[2]\t$refline[3]";
        chomp $posline[2];
        chomp $refline[3];     
        if ( $posline[0] eq $refline[0] ){
            #print "\tchr match\n";

            # am i entirely prox to a gene?
            if ( $posline[2] < $refline[1] ){
                #print "too proximal\n";
                print "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\ttoo proximal\n";

                #the following print statement is one I'd like to be able to comment out
                print $output "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\ttoo proximal\n";
                $ref_count++; 
                next; 
            }

            # am i entirely distal to a gene?
            elsif ( $posline[1] > $refline[2] ){
                #print "too distal\n";
                print  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\ttoo distal\n";
                #the following print statement is one I'd like to be able to comment out
                print $output  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\ttoo distal\n";
                $ref_count++; 
                next; 
            }

            # am i completely inside a gene?
            elsif ( $posline[1] >= $refline[1] &&
                $posline[2] <= $refline[2]    ){
                #print "inside\n";
                print  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tinside\n";
                print $output  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tinside\n";
                $ref_count++; 
                next; 
            }

            # am i proximally overlapping?
            elsif ( $posline[1] < $refline[1] &&
                $posline[2] <= $refline[2]    ){
                #print "proximal overlap\n";
                print  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tproximal overlap\n";
                print $output  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tproximal overlap\n";
                $ref_count++; 
                next; 
            }
            # am i distally overlapping?
            elsif ( $posline[1] >= $refline[1] &&
                $posline[2] > $refline[2]    ){
                #print "distal overlap\n";
                print  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tdistal overlap\n";
                print $output  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tdistal overlap\n";
                $ref_count++; 
                next; 
            }

            else {
                #print "encompassing\n";
                print  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tencompassing\n";
                print $output  "$posline[0]\t$pos_count\t$posline[1]\t$posline[2]\t$refline[0]\t$ref_count\t$refline[1]\t$refline[2]\t$refline[3]\tencompassing\n";
                $ref_count++; 
                next;
            }       

        } # if a match with chr

        else {
            next;
        }

    } # for each reference
    $pos_count++;    
} # for each position

数据文件:

【问题讨论】:

  • 有趣的问题!关于评论它们有什么不同? 1 个想法您是否尝试过使用 print $output "..." if UltraVerbose; 并查看标志是否像您期望的那样“工作”?快速阅读它没有发现任何错误
  • 感谢您的想法。我会试试看。
  • 使用 Ultraverbose 不起作用。在使用严格的潜艇时出现错误提示(查看这意味着什么......)
  • 此外,即使我删除了 print $output 行(第 54 行,for 循环中的第一个 print $output 语句),我也遇到了同样的问题——没有任何内容可以输出。
  • 我感觉我们正在查看您正在使用的 perl 版本中的错误,但如果您还没有发现问题,我会继续与您​​一起查看.但有一些问题:(1) SO 很快就会要求我们将此对话转移到他们的私人聊天室之一。那里没有问题,只是抬头。 (2) 您发布的文件之一是 xlsx 文件。这是故意的吗?如何使用? (3) 你的脚本有两个参数;哪个文件应该是第一个,哪个是第二个? (4) 发布一些我可以比较的输出。也许你想要的输出和你看到的输出。

标签: perl debugging if-statement nested-loops bioinformatics


【解决方案1】:

我发现您的代码中有两个潜在缺陷:

  1. 在处理文件时始终使用while 而不是for

    每当您使用后者时,您实际上是将整个文件加载到内存中,而不是仅进行逐行处理。如果您确实能够支持这样做,您应该继续并完全加载较小的文件并在行上进行迭代。

  2. "\t" 上拆分,而不是在'\t' 上拆分。

    后者几乎可以肯定是一个错误,除非您确实为数据使用了 2 个字符的分隔符。

无论如何,我已经对您的代码进行了相当大的清理。删除重复的行等。很可能很多这些更改可能不起作用(因为它未经测试)或者不是您想要的。但是,如果您仔细阅读代码,也许它至少会给您一些想法:

#!/bin/usr/perl
use strict;
use warnings;
use autodie;

#############
## findGenes_after_ASboot_v5.pl
#############

#############
#  After making a big list of randomly placed intervals,
#  this script uses RefGene.txt file and identifies the 
#  the gene symbols encompassed or overlapped by each random interval 
#############

die "\n usage: $0 filename containig your list of positions and a RefGene-type file \n\n"
    if @ARGV != 2;

open my $positions, "<", $ARGV[0];

# Cache file by key
my %refgenes;
open my $RefGene,   "<", $ARGV[1];
while (<$RefGene>) {
    chomp;
    my @cols = split "\t";
    push @{$refgenes{$cols[0]}}, \@cols;
}

open my $output, ">>", "output.txt";

# print header
print $output "chr\tpos count\tpos1\tpos2\tchr\tref count\tref1\tref2\tname2\trelationship\n";

my $pos_count = 1;
my $ref_count = 1;

while (my $position_line = <$positions>) {
    chomp $position_line;
    my @posline = split "\t", $position_line;

    # Only iterate on matching refs
    for my $ref (@{ $refgenes{$posline[0]} }) {
        my @refline = @$ref;

        my $desc = join "\t", ($posline[0], $pos_count, @posline[1,2], $refline[0], $ref_count, @refline[1,2,3]);
        my $message = '';

        # am i entirely prox to a gene?
        if ( $posline[2] < $refline[1] ){
            $message = 'too proximal';

        # am i entirely distal to a gene?
        } elsif ( $posline[1] > $refline[2] ) {
            $message = 'too distal';

        # am i completely inside a gene?
        } elsif ( $posline[1] >= $refline[1] && $posline[2] <= $refline[2] ) {
            $message = 'inside';

        # am i proximally overlapping?
        } elsif ( $posline[1] < $refline[1] && $posline[2] <= $refline[2] ) {
            $message = 'proximal overlap';

        # am i distally overlapping?
        } elsif ( $posline[1] >= $refline[1] && $posline[2] > $refline[2] ) {
            $message = 'distal overlap';

        } else {
            $message = 'encompassing';
        }

        print "$desc\t$message\n";
        print $output "$desc\t$message\n";

        $ref_count++; 
    } # for each reference
    $pos_count++;
} # for each position

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 2014-01-11
    相关资源
    最近更新 更多