Perl-программа для имитации ферментов рестрикции с использованием ссылок, хеш-таблиц и подпрограмм - PullRequest
3 голосов
/ 28 ноября 2010

Я студент вводного класса Perl.Я ищу предложения о том, как подойти к заданию.Мой профессор поощряет форумы.Назначение:

Напишите программу на Perl, которая будет принимать два файла из командной строки, файл фермента и файл ДНК.Прочитайте файл с ферментами рестрикции и примените ферменты рестрикции к файлу ДНК.

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

Например, если фермент представляет собой EcoRI, а файл ДНК называется BC161026, выходной файл должен называться BC161026_EcoRI.

Мой подход заключается в создании основной программы и двух подпрограмм.следующим образом:

Main: Не знаете, как связать мои подводные лодки?

Подпрограмма $ DNA: Возьмите файл ДНК и удалите все новые строки, чтобы сделать одну строку

* 1016Подпрограмма «Ферменты»: считывание и сохранение строк из файла фермента, который находится в командной строке. Анализ файла таким образом, чтобы он отделял аббревиатуру фермента от позиции среза.Сохраните положение среза как регулярное выражение в хеш-таблице. Сохраните имя акронима в хеш-таблице

Примечание к формату файла фермента: Файл фермента соответствует формату, известному как Staden.Примеры:

AatI/AGG'CCT//
AatII/GACGT'C//
AbsI/CC'TCGAGG//

Аббревиатура фермента состоит из символов перед первой косой чертой (AatI, в первом примере. Распознавание).последовательность - это все, что находится между первым и вторым слешем (снова AGG'CCT, в первом примере). Точка отсечения обозначается апострофом в последовательности распознавания. Существуют стандартные сокращения для ДНК в ферментах следующим образом:

R = G или AB = не A (C или G или T) и т. Д. ...

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

Пример входного фермента: TryII/RRR'TTT//

Пример строки для чтения: CCCCCCGGGTTTCCCCCCCCCCCCAAATTTCCCCCCCCCCCCAGATTTCCCCCCCCCCGAGTTTCCCCC

Выходные данные должны быть:

CCCCCCGGG

TTTCCCCCCCCCCCCAAA

TTTCCCCCCCCCCCCAGA

TTTCCCCCCCCCCGAG

TTTCCCCC

Ответы [ 4 ]

3 голосов
/ 28 ноября 2010

Вот как я пытался решить проблему (код ниже).1) Имена файлов выбираются из аргументов и создаются соответствующие filehandles.2) Новый дескриптор файла создается для выходного файла, который в указанном формате3) «Точки разреза» извлекаются из первого файла4) Последовательности ДНК во втором файле зациклены на точках разреза, полученных на этапе 3 .

#!/usr/bin/perl
use strict;
use warnings;
my $file_enzyme=$ARGV[0];
my $file_dna=$ARGV[1];

open DNASEQ, ">$file_dna"."_"."$file_enzyme";
open ENZYME, "$file_enzyme";
open DNA, "$file_dna";
while (<ENZYME>) {
 chomp;
  if( /'(.*)\/\//) { # Extracts the cut point between ' & // in the enzyme file
    my $pattern=$1;
    while (<DNA>) {
     chomp;
     #print $pattern;
     my @output=split/$pattern/,;
     print DNASEQ shift @output,"\n"; #first recognized sequence being output
     foreach (@output) {
        print DNASEQ "$pattern$_\n"; #prefixing the remaining sequences with the cut point pattern
     }
   }
 }
}
close DNA;
close ENZYME;
close DNASEQ;
3 голосов
/ 28 ноября 2010

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

#!/usr/bin/env perl

use strict;
use warnings;

use Getopt::Long;

my ($enzyme_file, $dna_file);
my $write_output = 0;
my $verbose = 0;
my $help = 0;
GetOptions(
  'enzyme=s' => \$enzyme_file,
  'dna=s' => \$dna_file,
  'output' => \$write_output,
  'verbose' => \$verbose,
  'help' => \$help
);

$help = 1 unless ($dna_file && $enzyme_file);
help() if $help; # exits

# 'Main'
my $dna = getDNA($dna_file);
my %enzymes = %{ getEnzymes($enzyme_file) }; # A function cannot return a hash, so return a hashref and then store the referenced hash
foreach my $enzyme (keys %enzymes) {
  print "Applying enzyme " . $enzyme . " gives:\n";
  my $dna_holder = $dna;
  my ($precut, $postcut) = ($enzymes{$enzyme}{'precut'}, $enzymes{$enzyme}{'postcut'});

  my $R = qr/[GA]/;
  my $B = qr/[CGT]/;

  $precut =~ s/R/${R}/g;
  $precut =~ s/B/${B}/g;
  $postcut =~ s/R/${R}/g;
  $postcut =~ s/B/${B}/g;
  print "\tPre-Cut pattern: " . $precut . "\n" if $verbose;
  print "\tPost-Cut pattern: " . $postcut . "\n" if $verbose;

  #while(1){
  #  if ($dna_holder =~ s/(.*${precut})(${postcut}.*)/$1/ ) {
  #    print "\tFound section:" . $2 . "\n" if $verbose;
  #    print "\tRemaining DNA: " . $1 . "\n" if $verbose;
  #    unshift @{ $enzymes{$enzyme}{'cut_dna'} }, $2;
  #  } else {
  #    unshift @{ $enzymes{$enzyme}{'cut_dna'} }, $dna_holder;
  #    print "\tNo more cuts.\n" if $verbose;
  #    print "\t" . $_ . "\n" for @{ $enzymes{$enzyme}{'cut_dna'} };
  #    last;
  #  }
  #}
  unless ($dna_holder =~ s/(${precut})(${postcut})/$1'$2/g) {
    print "\tHas no effect on given strand\n" if $verbose;
  }
  @{ $enzymes{$enzyme}{'cut_dna'} } = split(/'/, $dna_holder);
  print "\t$_\n" for @{ $enzymes{$enzyme}{'cut_dna'} };

  writeOutput($dna_file, $enzyme, $enzymes{$enzyme}{'cut_dna'}) if $write_output; #Note that $enzymes{$enzyme}{'cut_dna'} is an arrayref already
  print "\n";
}

sub getDNA {
  my ($dna_file) = @_;

  open(my $dna_handle, '<', $dna_file) or die "Cannot open file $dna_file";
  my @dna_array = <$dna_handle>;
  chomp(@dna_array);

  my $dna = join('', @dna_array);

  print "Using DNA:\n" . $dna . "\n\n" if $verbose;
  return $dna;
}

sub getEnzymes {
  my ($enzyme_file) = @_;
  my %enzymes;

  open(my $enzyme_handle, '<', $enzyme_file) or die "Cannot open file $enzyme_file";
  while(<$enzyme_handle>) {
    chomp;
    if(m{([^/]*)/([^']*)'([^/]*)//}) {
      print "Found Enzyme " . $1 . ":\n\tPre-cut: " . $2 . "\n\tPost-cut: " . $3 . "\n" if $verbose;
      $enzymes{$1} = {
        precut => $2,
        postcut => $3,
        cut_dna => [] #Added to show the empty array that will hold the cut DNA sections
      };
    }
  }

  print "\n" if $verbose;
  return \%enzymes;
}

sub writeOutput {

  my ($dna_file, $enzyme, $cut_dna_ref) = @_;

  my $outfile = $dna_file . '_' . $enzyme;
  print "\tSaving data to $outfile\n" if $verbose; 
  open(my $outfile_handle, '>', $outfile) or die "Cannot open $outfile for writing";

  print $outfile_handle $_ . "\n" for @{ $cut_dna_ref };
}

sub help {

  my $filename = (split('/', $0))[-1];

  my $enzyme_text = <<'END';
AatI/AGG'CCT//
AatII/GACGT'C//
AbsI/CC'TCGAGG//
TryII/RRR'TTT//
Test/AAA'TTT//
END

  my $dna_text = <<'END';
CCCCCCGGGTTTCCCCCCC
CCCCCAAATTTCCCCCCCCCCCCAGATTTC
CCCCCCCCCGAGTTTCCCCC
END

  print <<END;
Usage: 
    $filename --enzyme (-e) <enzyme-filename> --dna (-d) <dna-filename> [options] (files may come in either order)
    $filename -h    (shows this help)

Options: 
    --verbose (-v)  print additional (debugging) information
    --output (-o)   output final data to files


Files:
The DNA file contains one DNA string which may be broken over many lines. E.G.:

$dna_text

The enzymes file constains enzyme definitions, one per line. E.G.:

$enzyme_text
END

exit;
}

Редактировать: Явно добавлена ​​инициализация cut_dna, потому что это конечный результат для каждого фермента, поэтому я подумал, что было бы хорошо увидеть его более четко.

Редактировать 2: добавлена ​​процедура вывода, вызов, флаг и соответствующая справка.

Редактировать 3: Изменена основная процедура для включения лучшего из метода канаванина при удалении петель. Теперь это глобальная замена, чтобы добавить временную метку ('), а затем разделить метку на массив. Оставленный старый метод в качестве комментария, новый метод - следующие 5 строк.

Редактировать 4: Дополнительный контрольный пример для записи в несколько файлов. (Ниже)

my @names = ('cat','dog','sheep'); 
foreach my $name (@names) { #$name is lexical, ie dies after each loop
  open(my $handle, '>', $name); #open a lexical handle for the file, also dies each loop
  print $handle $name; #write to the handle
  #$handles closes automatically when it "goes out of scope"
}
3 голосов
/ 28 ноября 2010

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

В подпрограмме Main вы можете перебирать хеш;для каждого фермента производят один выходной файл.Самый прямой способ - перевести сайт в регулярное выражение (с помощью других регулярных выражений) и применить его к последовательности ДНК, но есть и другие способы.(Вероятно, стоит разделить это по крайней мере на одну другую подпрограмму.)

2 голосов
/ 28 ноября 2010

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

#!/usr/bin/perl

use warnings;
use strict;
use Getopt::Long;

my ($enz_file, $dna_file);

GetOptions( "e=s" => \$enz_file,
            "d=s" => \$dna_file,
          );

if (! $enz_file || ! $dna_file) {
   # some help text 
   print STDERR<<EOF; 

   Usage: restriction.pl -e enzyme_file -d DNA_file

   The enzyme_file should contain one enzyme entry per line.
   The DNA_file may contain the sequence on one single or on
   several lines; all lines will be concatenated to yield a
   single string.
EOF      
   exit();
}

my %enz_and_patterns; # stores enzyme name and corresponding pattern

open ENZ, "<$enz_file" or die "Could not open file $enz_file: $!";
while (<ENZ>) {
   if (m#^(\w+)/([\w']+)//$#) {
      my $enzyme  = $1; # could also remove those two lines and use 
      my $pattern = $2; # the match variables directly, but this is clearer

      $enz_and_patterns{$enzyme} = $pattern;
   }
}
close ENZ;

my $dna_sequence;

open DNA, "<$dna_file" or die "Could not open file $dna_file: $!";
while (my $line = <DNA>) {
   chomp $line;
   $dna_sequence .= $line; # append the current bit to the sequence
                           # that has been read so far
}
close DNA;

foreach my $enzyme (keys %enz_and_patterns) {
   my $dna_seq_processed = $dna_sequence; # local copy so that we retain the original

   # now translate the restriction pattern to a regular expression pattern:
   my $pattern = $enz_and_patterns{$enzyme};
   $pattern    =~ s/R/[GA]/g; # use character classes
   $pattern    =~ s/B/[^A]/g;
   $pattern    =~ s/(.+)'(.+)/($1)($2)/; # remove the ', but due to the grouping
                                         # we "remember" its position

   $dna_seq_processed =~ s/$pattern/$1\n$2/g; # in effect we are simply replacing
                                              # each ' with a newline character
   my $outfile = "${dna_file}_$enzyme";
   open OUT, ">$outfile" or die "Could not open file $outfile: $!";
   print OUT $dna_seq_processed , "\n";
   close OUT;
}

Я проверил свой код на примере TryII, который работал нормально.

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

...