# preprocess
#!/bin/bash
# É necessário passar um diretório de entrada de dados ao chamar o script para execução:
indir=$1
# ! Significa negação, no caso abaixo, se não foi passado diretório de entrada print a mensagem "Missing input directory"
if [ ! ${indir} ]; then
echo "Missing input directory."
exit
fi
# SE o que foi passado não é um diretório, print a mensagem: "Wrong input directory"
if [ !-d ${indir} ]; then
echo "Wrong input directory (${indir})."
exit
fi
# Também é necessário passar um diretório de saída, ou seja onde os arquivos gerados ficarão:
outdir=$2
# SE não foi passado o diretório de saída, print uma mensagem dizendo que o argumento está faltando:
if [ ! ${outdir} ]; then
echo "Missing output directory."
exit
fi
# SE o que foi passado não é um diretório, print uma mensagem dizendo que argumento está errado:
if [ ! -d ${outdir} ]; then
echo "Wrong output directory (${outdir})."
exit
fi
# A função mkdir serve para criação de diretórios,no caso dentro do diretório que foi passado como output será criada uma
# pasta chamada processed, e dentro da mesma, serão criadas outras 3 pastas: atropos, prinseq e fastqc.
# A última conterá outras duas pastas: pre e pos. Ou seja, antes do processamento as reads passarão por um controle de
# qualide(pre) e após o processamento, serão novamente submetidas ao controle de qualidade (pos), pondendo realizar uma
# comparação de ambos posteriormente:
mkdir -p ${outdir}/processed/fastqc/pre
mkdir -p ${outdir}/processed/atropos
mkdir -p ${outdir}/processed/prinseq
mkdir -p ${outdir}/processed/fastqc/pos
# A estrutura for é utilizada para facilitar o processo, com ela pode-se realizar o comando para todas as reads,
# não sendo necessário a execução para cada uma delas. Assim, no comando abaixo, para cada read no formato .fastq será
# executado o mesmo comando: Pegar a base de cada nome (o que difere) e realizar o controle de qualidade (comando fastqc),
# gerando 2 arquivos um de erro (log.err.txt), caso venha a ocorrer, e outro de saída que mostra o andamento do processo
# (log.out.txt).
for r1 in `ls ${indir}/*_R1.fastq`; do
r2=`echo ${r1} | sed 's/_R1.fastq/_R2.fastq/'`
if [ ! -e "${r2}" ]; then
echo "Read 2 (${r2}) paired with Read 1 ($r1) not found."
exit
fi
name=`basename ${r1} | sed 's/_R1.fastq//'`
echo -e "FastQC pre-evaluation using sample ${name}: ${r1} & ${r2} ...\n"
fastqc -t 2 \
${r1} \
-o ${outdir}/processed/fastqc/pre/ \
> ${outdir}/processed/fastqc/pre/${name}_R1.log.out.txt \
2> ${outdir}/processed/fastqc/pre/${name}_R1.log.err.txt
fastqc -t 2 \
${r2} \
-o ${outdir}/processed/fastqc/pre/ \
> ${outdir}/processed/fastqc/pre/${name}_R2.log.out.txt \
2> ${outdir}/processed/fastqc/pre/${name}_R2.log.err.txt
# A função echo é para printar na tela a mensagem que vem em seguida entre aspas. Isso contribui para saber em que etapa
# o processo se encontra.
echo -e "Running atropos (insert) for adapter trimming using sample ${name}: ${r1} & ${r2} ...\n"
# É necessário inicializar o ambiente pyenv dentro desta sessão, pois para a execução do atropos é necessário um
# ambiente Python, dado o seu desenvolvimento
eval "$(pyenv init -)"
# Para ativar o ambiente Python para execução do atropos:
pyenv activate atropos
# Execução do Atropos - trimagem das reads, eliminando os adaptadores e sequencias de baixa qualidade. O atropos funciona
# utilizando 2 algortimos de trimagem o "insert" e o "adapter". O insert realiza a trimagem após alinhamento das reads
# por match das reads, o que sobrar é adaptadore e então ocorre a trimagem. e as reads que não foram trimadas nessa etapa
# passa para o segundo algortimo o adapter, que realiza a trimagem baseando-se na correspondendia do alinhamento dos adaptadores.
# -e: Esse parâmetro fornece o valor máximo da taxa de erro permitida para matches de adaptadores para que o alinhamento
# seja considerado que obteve sucesso. É o número de erros dividido pelo comprimento da região de matching.
# -n: Nessa opção deve-se optar por até quantos adaptadores deve ser removidos de cada read.
# No caso do nosso comando, o parâmtro diz: remova até dois adaptadores de cada read.
# -m: Essa opção descarta reads trimadas que apresentem tamanho menor que X (valor que você opta).
# No comando abaixo, reads menores que 15 pb serão descartadas.
# Op-order: Esse parâmetro descreve a ordem que as operações de trimagem são aplicadas. As letras significam:
# -A: Trimagem do adaptador,C: Corte,G: Trimagem NextSeq,Q: Qualidade da trimagem,W: Sobrescrever leituras de baixa qualidade.
# O default é WCGQA entretanto no comando acima a ordem foi alterada para GAWCQ devido a experiências prévias.
# Match-read-wildcards: Modo de interpretação da IUPAC está habilitado, assim ele identifica caracteres coringas quando
# não se sabe qual base será inserida por exemplo.
# -O: Nesse parâmetro você fornece um valor minimo que indica que se a sobreposição entre a read e o adaptador for menor
# que esse valor, a read não será modificada.
# -q: Nesse parâmetro deve ser fornecido um valor de qualidade de bases, o qual abaixo desse as bases das extremidades
# serão removidas. Se quer que ambas as extremidades sejam trimadas, deve-se passar 2 valore, o primeiro para a extremidade
# 5’ e o segundo para a extremidade 3’. No comando acima apenas um valor foi passado: 25, assim apenas bases com score de
# qualidade abaixo de 25 da extreimidade 3’ serão trimadas.
# -T: Fornece o número de threads a ser utilizado para trimagem das reads.
# Correct-mismatches: Esse parâmetro indica como lidar com os mismatches durante o alinhamento.
# As opções são “Liberal, conservativa, e N”. O N significa substituir a base que deu mismatch por N.
# As opções de correção ‘Liberal e conservativa’ envolvem a susbtituição de bases por aquela que apresenta a maior
# qualidade. Elas diferem apenas quando os scores de qualidade são iguais. A correção liberal substitui de acordo com a
# melhor mediana das qualidades das bases, enquanto que a conservativa significa manter inalterada.
# Pair-filter: Nesse parâmetro deve-se escolher qual das reads (pair-end) deve corresponder ao critério de filtragem para
# que ocorra a filtragem. Você pode escolher que ambas as reads entrem no critério ou qualquer uma. No caso foi escolhido qualquer uma.
# -a: Nesse parametro deve-se fornecer a sequência do adaptador a ser removido na primeira read na região 3’.
# -A: Nesse parametro deve-se fornecer a sequência do adaptador a ser removido na segunda read na região 3’.
# -o: Local de saída da read 1 trimada.
# -p: Local de saída da read 2 trimada.
# -pe1: Primeiro arquivo de entrada
# -pe2: Segundo arquivo de entrada
# Untrimmed-output: Indica o local de saída das reads 1 que não foram trimadas.
# Untrimmed-paired-output: Indica o local de saída das reads 2 que não foram trimadas.
atropos trim --aligner insert \
-e 0.1 \
-n 2 \
-m 15 \
--op-order GAWCQ \
--match-read-wildcards \
-O 25 \
-q 28 \
-T 8 \
--correct-mismatches conservative \
--pair-filter any \
-a AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC \
-A AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGTAGATCTCGGTGGTCGCCGTATCATT \
-o ${outdir}/processed/atropos/${name}_R1.atropos_insert.fastq \
-p ${outdir}/processed/atropos/${name}_R2.atropos_insert.fastq \
-pe1 ${r1} \
-pe2 ${r2} \
--untrimmed-output ${outdir}/processed/atropos/${name}_R1.atropos_untrimmed.fastq \
--untrimmed-paired-output ${outdir}/processed/atropos/${name}_R2.atropos_untrimmed.fastq \
> ${outdir}/processed/atropos/${name}.atropos.log.out.txt \
2> ${outdir}/processed/atropos/${name}.atropos.log.err.txt
# As reads que não foram trimadas na etapa anterior são submetidas a esse outro algoritmo "adapter"
echo -e "Running atropos (adapter) for adapter trimming using sample ${name}: ${outdir}/processed/atropos/${name}_R1.atropos_untrimmed.fastq & ${outdir}/processed/atropos/${name}_R2.atropos_untrimmed.fastq ...\n"
# -pe1: É o arquivo de entrada da read 1 para a trimagem, entretanto são o arquivo de saída do comando anterior,
# que não foram trimadas pelo algoritmo ‘insert’.
# -pe2: É o arquivo de entrada da read 2 para a trimagem, entretanto são o arquivo de saída do comando anterior,
# que não foram trimadas pelo algoritmo ‘insert’.
# -g: Nesse parametro deve-se fornecer a sequência do adaptador a ser removido na primeira read na região 5’.
# -G: Nesse parametro deve-se fornecer a sequência do adaptador a ser removido na segunda read na região 5’.
atropos trim --aligner adapter \
-e 0.1 \
-n 2 \
-m 1 \
--match-read-wildcards \
-O 3 \
-q 28 \
--pair-filter both \
-pe1 ${outdir}/processed/atropos/${name}_R1.atropos_untrimmed.fastq \
-pe2 ${outdir}/processed/atropos/${name}_R2.atropos_untrimmed.fastq \
-a GATCGGAAGAGCACACGTCTGAACTCCAGTCACNNNNNNATCTCGTATGCCGTCTTCTGCTTG \
-g AATGATACGGCGACCACCGAGATCTACACTCTTTCCCTACACGACGCTCTTCCGATCT \
-A AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGTAGATCTCGGTGGTCGCCGTATCATT \
-G CAAGCAGAAGACGGCATACGAGATNNNNNNGTGACTGGAGTTCAGACGTGTGCTCTTCCGATCT \
-T 8 \
-o ${outdir}/processed/atropos/${name}_R1.atropos_adapter.fastq \
-p ${outdir}/processed/atropos/${name}_R2.atropos_adapter.fastq \
> ${outdir}/processed/atropos/${name}.atropos_adapter.log.out.txt \
2> ${outdir}/processed/atropos/${name}.atropos_adapter.log.err.txt
# Após esses comandos, ambas as saidas dos dois comandos são concatenadas em um só arquivo, utlizando o comando cat:
# -read1 trimada com algoritmo insert + read 1 trimada com algoritmo adapter.
# -read 2 trimada com algoritmo insert + read 2 trimada com algoritmo adapter.
echo -e "Merging atropos adapter trimming results using sample ${name}: ${outdir}/processed/atropos/${name}_R1.atropos_insert.fastq and ${outdir}/processed/atropos/${name}_R2.atropos_insert.fastq + ${outdir}/processed/atropos/${name}_R1.atropos_adapter.fastq and ${outdir}/processed/atropos/${name}_R2.atropos_adapter.fastq ...\n"
cat ${outdir}/processed/atropos/${name}_R1.atropos_insert.fastq \
${outdir}/processed/atropos/${name}_R1.atropos_adapter.fastq \
> ${outdir}/processed/atropos/${name}_R1.atropos_final.fastq
cat ${outdir}/processed/atropos/${name}_R2.atropos_insert.fastq \
${outdir}/processed/atropos/${name}_R2.atropos_adapter.fastq \
> ${outdir}/processed/atropos/${name}_R2.atropos_final.fastq
# Em seguida, os arquivos gerados antes da concantenação foram removidos pois não serão utilizados.
echo -e "Removing useless atropos results ...\n"
rm -f ${outdir}/processed/atropos/${name}_R1.atropos_insert.fastq \
${outdir}/processed/atropos/${name}_R1.atropos_adapter.fastq \
${outdir}/processed/atropos/${name}_R2.atropos_insert.fastq \
${outdir}/processed/atropos/${name}_R2.atropos_adapter.fastq
# Em seguida as reads são submetidas ao programa PrinSeq, que é uma ferramenta para garantir que os dados obtidos não estejam
# comprometidos por sequencias de baixa qualidade, artefatos ou contaminantes que podem levar a conclusões errôneas.
# Essa ferramenta, realiza tanto a trimagem, filtragem de sequencias de baixa qualidade, quanto gera um resumo estatistico
# das caracteristicas das sequencias, como um controle de qualidade, parecido com o fastqc.
echo -e "PrinSeq processing: ${outdir}/processed/atropos/${name}_R1.atropos_final.fastq & ${outdir}/processed/atropos/${name}_R2.atropos_final.fastq ...\n"
# Após as reads serem processadas pelo Atropos, servirão de entrada para o prinseq (paramentros:fastq e fastq2).
# -min_len: Filtrar as sequências menores que 25pb.
# -noniupac: Filtrar sequências que apresentem caracteres que não seja A,T,C,G ou N.
# -lc-method: Método a ser utilizado para filtragem de sequências de baixa complexidade, pode ser "dust" ou "entropy". No caso,
# foi selecionado o dust: Os scores são computados de acordo com a frequencia de diferentes trinucleotideos (0-100).
# Scores elevados implicam em baixa complexidade.
# -lc_threshold: Valor a ser usado para filtragem de sequencias de baixa complexidade, no caso, como escolhido o método
# "dust", é escolhido um valor máximo aceito. Acima desse score, as sequencias serão filtradas.
# -out_format: Utilizado para escolher o formato do output. No comando abaixo foi selecionado o formato fastq.
# -out_good: Por default a saida de dados é o diretorio em que se encontram as reads. Para alterar o diretório de
# saída e nome do arquivo de saída utiliza-se esse parametro. No comando abaixo o diretório prinseq como output e o nome
# dos arquivos de saída.
# -out_bad: Por default, a saída é o diretório input. Para alterar deve-se usar esse parametro. No caso foi utilizado o null
# para que esses arquivos bad não sejam gerados.
# -trim_qual_window: Tamnho da "janela" a ser usado para calcular o score de qualidade. No caso, está dizendo para parar na
# primeira base que falhar.
# -trim_qual_step: De quanto em quanto a janela desliza avaliando os scores de qualidade sem faltar nenhum.
# -trim_qual-right: Trima as sequências que apresentam score de qualidade menor que o threshold na extremidade 3'.
# -trim_qual_type: Tipo de calculo a ser usado para se obter o score de qualidade, foi selecionado a média.
# -trim_qual_rule: Regra a ser utilizada para comparação do score de qualidade gerado.Foi selecionado lt (less than).
prinseq-lite.pl -fastq ${outdir}/processed/atropos/${name}_R1.atropos_final.fastq \
-fastq2 ${outdir}/processed/atropos/${name}_R2.atropos_final.fastq \
-out_format 3 \
-trim_qual_window 1 \
-trim_qual_step 1 \
-trim_qual_right 30 \
-trim_qual_type mean \
-trim_qual_rule lt \
-out_good ${outdir}/processed/prinseq/${name}.atropos_final.prinseq \
-out_bad null \
-lc_method dust \
-lc_threshold 30 \
-min_len 25 \
-trim_tail_right 5 \
-trim_tail_left 5 \
-ns_max_p 80 \
-noniupac \
> ${outdir}/processed/prinseq/${name}.atropos_final.prinseq.out.log \
2> ${outdir}/processed/prinseq/${name}.atropos_final.prinseq.err.log
# Realização do controle de qualidade após ter sido realizado o pre-processamento dos dados
echo -e "FastQC pos-evaluation using sample ${name}: ${outdir}/processed/prinseq/${name}.atropos_final.prinseq_1.fastq & ${outdir}/processed/prinseq/${name}_2.atropos_final.prinseq.fastq ...\n"
fastqc -t 2 \
${outdir}/processed/prinseq/${name}.atropos_final.prinseq_1.fastq \
-o ${outdir}/processed/fastqc/pos/ \
> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_1.log.out.txt \
2> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_1.log.err.txt
fastqc -t 2 \
${outdir}/processed/prinseq/${name}_2.atropos_final.prinseq.fastq \
-o ${outdir}/processed/fastqc/pos/ \
> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_2.log.out.txt \
2> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_2.log.err.txt
# SE EXISTIR <SAMPLE_NAME>.atropos_final.prinseq_1_singletons.fastq
if [ -e "${outdir}/processed/prinseq/${name}.atropos_final.prinseq_1_singletons.fastq" ]; then
fastqc -t 2 \
${outdir}/processed/prinseq/${name}.atropos_final.prinseq_1_singletons.fastq \
-o ${outdir}/processed/fastqc/pos/ \
> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_1_singletons.log.out.txt \
2> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_1_singletons.log.err.txt
fi
# SE EXISTIR <SAMPLE_NAME>.atropos_final.prinseq_2_singletons.fastq
if [ -e "${outdir}/processed/prinseq/${name}.atropos_final.prinseq_2_singletons.fastq" ]; then
fastqc -t 2 \
${outdir}/processed/prinseq/${name}.atropos_final.prinseq_2_singletons.fastq \
-o ${outdir}/processed/fastqc/pos/ \
> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_2_singletons.log.out.txt \
2> ${outdir}/processed/fastqc/pos/${name}.atropos_final.prinseq_2_singletons.log.err.txt
fi
done