вырожденные позиции в мотивах -bash - PullRequest
0 голосов
/ 01 ноября 2018

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

Например, Мотив может быть (psi, psi, x, psi), где psi = (I, L или V) и x может быть любой из 20 аминокислот.

Я бы искал набор последовательностей для появления этого мотива. Однако мои белковые последовательности являются точными последовательностями, то есть они не имеют неоднозначности, например:

>
MSGIALSRLAQERKAWRKDHPFGFVAVPTKNPDGTMNLMNWECAIPGKKGTPWEGGL

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

#!/usr/bin/bash
x=(A C G H I L M P S T V D E F K N Q R W Y)
psi=(I L V)
alpha=(D E)
motif1=($psi,$psi,$x,$psi)

  for f in *.fasta ; do
    if grep -q "$motif1" <$f ; then   
         echo $f
         grep "^>" $f | tr -d ">"
         grep -v ">" $f | grep -aob "$motif1"
     fi
  done

Ценю любую помощь в поиске моего пути. Заранее спасибо!

1 Ответ

0 голосов
/ 01 ноября 2018

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

Распространенным условием является использование оболочки для запуска Awk над набором файлов и вместо этого выполнение логики обнаружения в Awk. (Другими популярными инструментами являются Python и Perl; возможно, я бы занялся этим на Python, если бы начал с нуля.)

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

scan () {
    local f
    for f in *.fasta; do
        # Inefficient: refactor to do the grep only once, then decide whether you want to show the output or not
        if grep -q "$1" "$f"; then
            # Always, always use double quotes around file names
            echo "$f"
            grep "^>" "$f" | tr -d ">"
            grep -v ">" "$f" | grep -aob "$1"
        fi
    done
}

case $motif in
    1)     scan "$SIM_Type_1";;   # Notice typo in variable name
    2)     scan "$SIM_Type_2";;   # Ditto
    3)     scan "$SIM_Type_3";;   # Ditto
    4)     scan "$SIM_Type_4";;   # Ditto
    5)     scan "$SIM_TYPE_5";;   # Notice inconsistent variable name
    alpha) scan "$SIM_Type_alpha";;
    beta)  scan "$SIM_Type_beta";;
esac

Вы объявляете переменные _*Type_* (или иногда *_TYPE_* - оболочка чувствительна к регистру, и вам, вероятно, следует использовать одинаковую заглавную букву для всех переменных, чтобы вам было проще) в качестве массивов, но затем Вы, очевидно, пытаетесь использовать их как обычные скаляры. Я могу только догадываться о том, что вы намерены для переменных на самом деле содержать; но я предполагаю, что вы хотите что-то вроде

# These are strings which contain regular expressions
x='[ACGHILMPSTVDEFKNQRWY]'
psi='[ILV]'
psi_1='[IV]'
alpha='[DE]'
# These are strings which contain sequences of the above regexes
# The ${variable} braces are not strictly necessary, but IMHO help legibility
SIM_Type_1="${psi}${psi}${x}${psi}"
SIM_Type_2="${psi}${x}${psi}${psi}"
SIM_Type_3="${psi}${psi}${psi}${psi}"
SIM_Type_4="${x}${psi}${x}${psi}"
SIM_TYPE_5="${psi}${alpha}${psi}${alpha}${psi}"
SIM_Type_alpha="${psi_1}${x}${psi_1}${psi}"
SIM_Type_beta="${psi_1}${psi_1}.${x}${psi}"
# You had an empty spot here   ^ I guessed you want to permit any character?

Если вы действительно хотите, чтобы это были массивы, способ доступа к содержимому массива - "${array[@]}", но тогда это не приведет к тому, что мы можем напрямую передать grep или Awk, поэтому я решил объявить их как строки содержащие регулярные выражения для мотивов.

Но, повторюсь, Awk, вероятно, является лучшим языком для этого, поэтому давайте изменим scan на сценарий Awk.

# This replaces the function definition above
scan () {
    awk -v re="$1" '{ if (/^>/) label=$0
        else if (idx = match($0, re, result) {
            if (! printed) { print FILENAME; printed = 1 }
            print len + idx ":" result[0]
        }
        len += 1+length($0)  # one for the newline
      }
      # Reset printed if we skip to a new file
      FNR == 1 { printed = 0 }' *.fasta
}

Основным осложнением здесь является переопределение вычисления смещения grep -b байтов. Если это не является строго необходимым (возможно, достаточно номера строки?), Тогда сценарий Awk можно сократить до несколько более тривиального.

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

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

Если вы хотите сделать сценарий более универсальным, это, вероятно, также лучшая отправная точка, чем решение grep | tr, которое вы использовали ранее. Но если сценарий делает то, что вам нужно, и совпадения часто находятся в начале входного файла, или входные файлы не большие, возможно, вам вообще не захочется переключаться на Awk.

Также обратите внимание, что, как и в вашей логике grep, это не будет работать, если последовательность разбита на несколько строк в файле FASTA, и совпадение окажется между одним из разрывов строк.

Наконец, запрос сценария для интерактивного ввода - это дизайн. Я бы посоветовал вам принять выбор пользователя в качестве аргумента командной строки.

motif=$1

Таким образом, вы использовали бы это как ./scriptname alpha для запуска регулярного выражения alpha против ваших файлов FASTA.

Другим возможным рефакторингом было бы прочитать все регулярные выражения мотива в несколько более сложный скрипт Awk и распечатать все совпадения для всех них в форме, которая затем позволит вам легко выбрать те, которые вы на самом деле хотите изучить, более подробно. Если у вас есть много данных для обработки, циклическое повторение всего один раз - огромный выигрыш.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...