# rnaseq.sh #!/bin/bash # Número de processadores a ser utilizado durante o processo. Criando a variável, basta substituir nos comandos. num_threads=8 # É necessário passar um diretório input de onde vai estar contido os dados de entrada para o alinhamento, na linha de # comando ao chamar o script para ser executado. indir=$1 # SE(if) não (!) for passado um diretório de entrada, print na tela a mensagem "Missing input directory." if [ ! ${indir} ]; then echo "Missing input directory." exit fi # A função echo, mostra na tela a mensagem que etá entre aspas. # SE for passado um argumento na linha de comando, mais esse não for o diretório, print na tela a mensagem:"Wrong input directory (${indir})." if [ ! -d ${indir} ]; then echo "Wrong input directory (${indir})." exit fi # É necessário passar um diretório de saída, ou seja, que vai conter os dados gerados. outdir=$2 # SE não for passado o argumento 2, o diretório de saída na linha de comando, print a mensagem:"Missing output directory." if [ ! ${outdir} ]; then echo "Missing output directory." exit fi # SE o argumento passado não é um diretório, print na tela a mensagem dizendo:"Wrong output directory (${outdir})." if [ ! -d ${outdir} ]; then echo "Wrong output directory (${outdir})." exit fi # É necessário passar um terceiro argumento na linha de comando, o arquivo de anotação do genoma no formato gtf. refgtf=$3 # SE ${refgtf} NÃO EXISTE, SE NÃO FOI PASSADO ARGUMENTO 3 NA LINHA DE COMANDO if [ ! ${refgtf} ]; then echo "Missing GTF file." exit fi if [ ! -e "${refgtf}" ]; then echo "Not found GTF file (${refgtf})." exit fi # É necessário passar um quarto argumento na linha de comando: Arquivo FASTA referente ao genoma a ser utilizado como referência. refseq=$4 # SE ${refseq} NÃO EXISTE, SE NÃO FOI PASSADO ARGUMENTO 4 NA LINHA DE COMANDO if [ ! ${refseq} ]; then echo "Missing GENOME fasta file." exit fi if [ ! -e "${refseq}" ]; then echo "Not found GENOME fasta file (${refseq})." exit fi # Primeiramente é chamado para a execução o script preprocess.sh, que realizará o processamento dos dados e controle de # qualidade. O mesmo necessita de 2 argumentos na linha de comando: O diretório de entrada de dados (Arquivos fastq) e # um diretório para saída dos dados processados, que por sua vez serão o input do presente script. ./preprocess.sh "${indir}" "${outdir}" # O comando mkdir cria diretórios. Assim os diretórios abaixo serão criados dentro do diretório passado como saída de dados # na linha de comando ao chamar o script. mkdir -p ${outdir}/star_index mkdir -p ${outdir}/star_out_pe mkdir -p ${outdir}/star_out_se mkdir -p ${outdir}/star_out_final mkdir -p ${outdir}/cufflinks mkdir -p ${outdir}/cuffmerge mkdir -p ${outdir}/stringtie mkdir -p ${outdir}/stringmerge mkdir -p ${outdir}/cuffcompare mkdir -p ${outdir}/cuffquant # A estrutura "for" serve como um loop, facilitando o script, pois assim não é necessário fazer para cada amostra # separadamente. A estrutura abaixo diz: para todos os dados contidos no diretório prinseq que finalizam com # .atropos_final.prinseq_1.fastq, faça o alinhamento. # "ls" é pra procurar dentro do diretório todos os arquivos que terminam com .atropos_final.prinseq_1.fastq. # a função "sed" é utilizada para substituição. # a função "touch" cria arquivos vazios. for r1 in `ls ${outdir}/processed/prinseq/*.atropos_final.prinseq_1.fastq`; do r1_singletons=`echo ${r1} | sed 's/prinseq_1.fastq/prinseq_1_singletons.fastq/'` if [ ! -e "${r1_singletons}" ]; then touch ${r1_singletons} fi r2=`echo ${r1} | sed 's/prinseq_1.fastq/prinseq_2.fastq/'` if [ ! -e "${r2}" ]; then echo "Read 2 (${r2}) paired with Read 1 ($r1) not found." exit fi r2_singletons=`echo ${r2} | sed 's/prinseq_2.fastq/prinseq_2_singletons.fastq/'` if [ ! -e "${r2_singletons}" ]; then touch ${r2_singletons} fi name=`basename ${r1} | sed 's/.atropos_final.prinseq_1.fastq//'` # Se não exister o index do genoma, então faça o index. # Para a construção do index a ferramenta STAR será utilizada. # O index facilitará o mapeamento das reads contra o genoma de referência. if [ ! -e "${outdir}/star_index/SAindex" ]; then echo "Indexing genome (${refseq}) ..." STAR --runThreadN ${num_threads} \ --runMode genomeGenerate \ --genomeFastaFiles ${refseq} \ --genomeDir ${outdir}/star_index \ --sjdbGTFfile ${refgtf} \ # --genomeSAindexNbases 12 \ Apenas para genomas muito pequenos (escalonamento) --sjdbOverhang 149 \ > ${outdir}/star_index/STAR.index.log.out.txt \ 2> ${outdir}/star_index/STAR.index.log.err.txt fi # --runThreadN: Número de processadores a ser utilizado, foi criado uma variável no inicio do script. # --runMode: Direciona o STAR a construir o index do genoma. # --genomeFastaFiles: Arquivo FASTA referente ao genoma de referência. # --genomeDir: Diretório de saída que irá conter o index gerado. # --sjdbGTFfile: Arquivo gtf - anotação do genoma de referência. # --sjdbOverhang: Especifica o tamanho da sequencia genomica levando em consideração a anotação para ser usado na construção # do banco de dados de junções de splicing. Esse tamanho geralmente é igual ao tamanho das reads -1. Logo, 149. # > log.out.txt: saída que contém as etapas da criação do index. # 2> log.err.txt: segunda saída que contem erros que venham a ocorrer durante o processo. echo "STAR alignment PE with sample ${name}: ${r1} & ${r2} ..." mkdir -p ${outdir}/star_out_pe/${name} # Para o alinhamento das reads contra o genoma de referência também será utlizado a ferramenta STAR. STAR --runThreadN ${num_threads} \ --genomeDir ${outdir}/star_index \ --readFilesIn ${r1} ${r2} \ --outSAMstrandField intronMotif \ --outFilterIntronMotifs RemoveNoncanonical \ --sjdbGTFfile ${refgtf} \ --outFilterMultimapNmax 20 \ --outFileNamePrefix ${outdir}/star_out_pe/${name}/ \ --outSAMtype BAM Unsorted \ > ${outdir}/star_out_pe/${name}/STAR.alignment_pe.log.out.txt \ 2> ${outdir}/star_out_pe/${name}/STAR.alignment_pe.log.err.txt # --readFilesIn: Reads (no caso já processadas) a serem utilizadas no mapeamento. # --outSAMstrandField: Para dados unstranded,as ferramentas Cufflinks/Cuffdiff requerem alinhamento de splicing com o # o atributo de fita XS, que será gerado com esse parâmetro e a opção intronMotif. # --outFilterIntronMotifs: Remove introns não canônicos. # --outFilterMultimapNmax: Número máximo de alinhamentos multiplos permitido por read, se exceder esse valor, a read é # considerada não mapeada; Foi utilizado o valor default. # --outFileNamePrefix: prefixo a ser dado para o arquivo gerado. # --outSAMtype: arquivo de saída do tipo BAM sem estar ordenado por nome ou por coordenada. echo "STAR alignment SE with sample ${name}: ${r1_singletons} & ${r2_singletons} ..." mkdir -p ${outdir}/star_out_se/${name} # Para as reads que não foram encontradas seu par, denomindas singletons, realizar o alinhamento: STAR --runThreadN ${num_threads} \ --genomeDir ${outdir}/star_index \ --readFilesIn ${r1_singletons},${r2_singletons} \ --sjdbGTFfile ${refgtf} \ --outSAMtype BAM Unsorted \ --outFilterMultimapNmax 20 \ --outSAMstrandField intronMotif \ --outFileNamePrefix ./$outdir/star_out_se/${name}/ \ > ./${outdir}/star_out_se/${name}/STAR.alignment_se.log.out.txt \ 2> ./${outdir}/star_out_se/${name}/STAR.alignment_se.log.err.txt echo "Merging STAR alignment PE & SE (${name}) ..." # STAR_out é a junção do alinhamento das reads paired-end e das singletons mkdir -p ${outdir}/star_out_final/${name} # Combinar resultados do alinhamento com reads paired-end e alinhamento com reads single-end (singletons): # Utilizar a função samtools merge para junção de ambos os alinhamentos. # -f: caso tenha o arquivo, sobreescreva. # -n: ordena o alinhamento por nome. # @: número de processadores. samtools merge -@ ${num_threads} -f -n ${outdir}/star_out_final/${name}/Aligned.out.bam \ ${outdir}/star_out_pe/${name}/Aligned.out.bam \ ${outdir}/star_out_se/${name}/Aligned.out.bam \ > ${outdir}/star_out_final/${name}/samtools.merge.log.out.txt \ 2> ${outdir}/star_out_final/${name}/samtools.merge.log.err.txt echo "Sorting STAR alignment final (${name}) ..." # Ordenar o resultado do alinhamento por coordenadas genômicas, pois é uma exigência para executar o cufflinks posteriormente. # Para a ordenação utilzar a função samtools sort: samtools sort -@ ${num_threads} -o ${outdir}/star_out_final/${name}/Aligned.out.sorted.bam \ ${outdir}/star_out_final/${name}/Aligned.out.bam \ > ${outdir}/star_out_final/${name}/samtools.sort.log.out.txt \ 2> ${outdir}/star_out_final/${name}/samtools.sort.log.err.txt echo "Collecting alignment statistics (${name}) ..." # Gerando as estatisticas do alinhamento utilizando o script SAM_nameSorted_to_uniq_count_stats.pl. # É necessário passar o arquivo de entrada (BAM final, contendo todos os alinhamentos) e o nome para o arquivo de saída. SAM_nameSorted_to_uniq_count_stats.pl ${outdir}/star_out_final/${name}/Aligned.out.bam > ${outdir}/star_out_final/${name}/Aligned.stats.txt # Após o mapeamento das reads contra o genoma de referência, o transcriptoma será então montado utilizando o cufflinks: echo "Running Cufflinks (${name}) ..." mkdir -p ${outdir}/cufflinks/${name} cufflinks --output-dir ${outdir}/cufflinks/${name} \ --num-threads ${num_threads} \ --GTF-guide ${refgtf} \ --frag-bias-correct ${refseq} \ --multi-read-correct \ --library-type fr-unstranded \ --frag-len-mean 250 \ --frag-len-std-dev 40 \ --total-hits-norm \ --compatible-hits-norm \ --max-frag-multihits 20 \ --min-isoform-fraction 0.25 \ --max-intron-length 9000 \ --min-intron-length 80 \ --overhang-tolerance 10 \ --max-bundle-frags 999999 \ --max-multiread-fraction 0.65 \ --overlap-radius 20 \ --3-overhang-tolerance 300 \ ${outdir}/star_out_final/${name}/Aligned.out.sorted.bam \ > ${outdir}/star_out_final/${name}/cufflinks.log.out.txt \ 2> ${outdir}/star_out_final/${name}/cufflinks.log.err.txt # --output-dir: Diretório para a saída de dados. # --num-threads: Número de processadores a ser utilizado. # --GTF-guide: Arquivo de anotação referente ao genoma de referência no formato gtf. # --frag-bias-correct: Arquivo FASTA do genoma de referência. # --multi-read-correct: Esse parametro solicita uma estimaçao inicial das reads mapeadas em multiplas posições. # --library-type: Indica o tipo de biblioteca. # --frag-len-mean: Média do tamanho dos fragmentos. # --frag-len-std-dev: Desvio padrão referente ao tamnho dos fragmentos. # --overhang-tolerance: Número de pb permitidos a entrar em um intron, caso seja mapeado corretamente. # --total-hits-norm: Conta todos os fragmentos, incluindo aqueles não compativeis com nenhum transcrito de referência, # levando ao número de mapeamentos, utilizando o FPKM. # –compatible-hits-norm: Conta somente os fragmentos compativeis com algums transcrito de referência, levando ao número # de mapeamento, utilizando o FPKM. # --min-isoform-fraction: Após calcular a abundancia de isoformas para um gene, Cufflinks elimina transcritos que apresentem # baixa abundancia, pois esses transcritos podem não ser montados de maneira confiável, podendo ser artefatos.Também elimina # introns que apresentem poucos alinhamentos de splicing. # --max-intron-length: Tamanho máximo dos introns. # --min-intron-length: Tamanho minimo dos introns. # --max-bundle-frags: Número maximo de fragmentos que um locus deve apresentar para que então passe para o proximo. # --max-multiread-fraction: Porção de reads que podem ser mapeadas em multiplas posições. # --overlap-radius: Transcrito que estão separados por menos que essa distancia são unidos e o gap é preenchido. # --3-overhang-tolerance: Número de pares de bases que se excedem na porção 3', para ser permitido que se una ao transcrito ja montado. # Será também realizada uma montagem utilizando o software Stringtie: echo "Running StringTie (${name}) ..." mkdir -p ${outdir}/stringtie/${name} # Deve-se passar primeiramente o arquivo de alinhamento stringtie ${outdir}/star_out_final/${name}/Aligned.out.sorted.bam \ -G ${refgtf} \ -o ${outdir}/stringtie/${name}/transcripts.gtf \ -p ${num_threads} \ -f 0.25 \ -a 10 \ -j 5 \ -c 6 \ -g 20 \ -M 0.65 \ -A ${outdir}/stringtie/${name}/gene_abundance.txt # -G: Arquivo de anotação referente ao genoma de referência no formato gtf. # -o: Arquivo de saída - formato gtf. # -p: Número de processadores a serem utilizados no processo. # -f: Fração minima de abundância de isoformas. # -a: Junções que não apresentam reads que alinharam através delas em pelo menos essa quantidade de bases em ambos os lados são filtradas. # -c: Minimo de cobertura permitido para os transcritos preditos. # -g: Transcrito que estão separados por menos que essa distancia são unidos e o gap é preenchido. # -M: Porção de reads que podem ser mapeadas em multiplas posições. # -A: Saida do arquivo de abudancia dos genes - formato txt. done # Junção de todos os arquivos de saída "transcripts.gtf" do cufflinks em um só - assembly_GTF_list.txt, utilizando a # ferramenta cuffmerge. echo "Running cuffmerge ..." # O comando find encontra todos os arquivos com esse nome no diretório dado. find ${outdir}/cufflinks/ -name 'transcripts.gtf' > ${outdir}/cuffmerge/assembly_GTF_list.txt cuffmerge -o ${outdir}/cuffmerge/ \ --ref-gtf ${refgtf} \ --ref-sequence ${refseq} \ --min-isoform-fraction 0.20 \ --num-threads ${num_threads} \ ${outdir}/cuffmerge/assembly_GTF_list.txt \ > ${outdir}/cuffmerge/cuffmerge.log.out.txt \ 2> ${outdir}/cuffmerge/cuffmerge.log.err.txt # -o: Saída do arquivo gerado. # -ref-gtf: Arquivo de anotação referente ao genoma no formato gtf. # - ref-sequence: Arquivo no formato FASTA do genoma de referência. # -min-isoform-fraction: minimo de abundancia de isoformas, abaixo disso são eliminadas. # -num-threads: Número de processadores a serem utilizados. # Similarmente ao processo anterior, se realizará a junção dos arquivos gerados do StringTie em um só arquivo, utilizando a # ferramenta stringtie merge: echo "Running stringtie merge ..." find ${outdir}/stringtie/ -name 'transcripts.gtf' > ${outdir}/stringmerge/assembly_GTF_list.txt stringtie --merge \ -G ${refgtf} \ -o ${outdir}/stringmerge/merged.gtf \ -c 1 \ -T 1 \ -f 0.25 \ -g 20 \ -i \ ${outdir}/stringmerge/assembly_GTF_list.txt # -T: minimo de transcritos TPM a serem utilizados na junção. # -i: mantém os transcritos unidos com retenção dos introns. # Em seguida será realizada uma comparação das montagens obtida com a referência utilizando a ferramenta cuffcompare: cuffcompare -r ${refgtf} \ -s ${refseq} \ -o ${outdir}/cuffcompare/stringmerge \ ${outdir}/stringmerge/merged.gtf \ > ${outdir}/stringmerge/cuffcompare.log.out.txt \ 2> ${outdir}/stringmerge/cuffcompare.log.err.txt # Criação da variávek biogroup_label: biogroup_label=() for bamfile in `ls ${outdir}/star_out_final/*/Aligned.out.sorted.bam`; do name=`basename $(dirname ${bamfile})` # Quantificação dos transcritos utilizando a ferramenta cuffquant: echo "Running cuffquant using sample ${name} with ${outdir}/stringmerge/merged.gtf as reference ..." mkdir -p ${outdir}/cuffquant/${name} cuffquant --output-dir ${outdir}/cuffquant/${name} \ --frag-bias-correct ${refseq} \ --multi-read-correct \ --num-threads ${num_threads} \ --library-type fr-unstranded \ --frag-len-mean 250 \ --frag-len-std-dev 40 \ --max-bundle-frags 9999999 \ --max-frag-multihits 20 \ ${outdir}/stringmerge/merged.gtf \ ${bamfile} \ > ${outdir}/cuffquant/${name}/cuffquant.log.out.txt \ 2> ${outdir}/cuffquant/${name}/cuffquant.log.err.txt # Os parâmetros são similares ao cufflinks. groupname=`echo ${name} | sed 's/[0-9]\+$//'` biogroup_label=($(printf "%s\n" ${biogroup_label[@]} ${groupname} | sort -u )) done biogroup_files=() # Para realizar a análise de genes diferencialmente expressos,utilizaremos os arquivo de abundância gerados na etapa anterior. echo "Running Differential Expression Analysis ..." # Será utilizado novamente a estrutura for, para fazer com todas as amostras de uma só vez. # Preparo dos dados para cuffdiff for label in ${biogroup_label[@]}; do echo -e "\tCollecting .cxb files for ${label} ..." group=() for cxbfile in `ls ${outdir}/cuffquant/${label}*/abundances.cxb`; do echo -e "\t\tFound ${cxbfile}" group=(${group[@]} "${cxbfile}") done biogroup_files=(${biogroup_files[@]} $(IFS=, ; echo "${group[*]}") ) done echo -e "\tRunning cuffnorm & cuffdiff ..." echo -e "\t\tLabels.: " $(IFS=, ; echo "${biogroup_label[*]}") echo -e "\t\tFiles..: " ${biogroup_files[*]} echo -e "\t\t\tGenerating abundance matrices (cuffnorm) ..." # Normalização dos resultados utilizando o cuffnorm: mkdir -p ${outdir}/cuffnorm/ cuffnorm --output-dir ${outdir}/cuffnorm \ --labels $(IFS=, ; echo "${biogroup_label[*]}") \ --num-threads ${num_threads} \ --library-type fr-unstranded \ --library-norm-method geometric \ --output-format simple-table \ ${outdir}/stringmerge/merged.gtf \ ${biogroup_files[*]} \ > ${outdir}/cuffnorm/cuffdiff.log.out.txt \ 2> ${outdir}/cuffnorm/cuffdiff.log.err.txt # -output-format: formato da saída: Tabela simples # Restante dos parametros já foram citados no cufflinks. echo -e "\t\t\tAnalysing differential expression (cuffdiff) ..." # Análise de genes diferencialmente expressos utilizando o cuffdiff mkdir -p ${outdir}/cuffdiff/ cuffdiff --output-dir ${outdir}/cuffdiff \ --labels $(IFS=, ; echo "${biogroup_label[*]}") \ --frag-bias-correct ${refseq} \ --multi-read-correct \ --num-threads ${num_threads} \ --library-type fr-unstranded \ --frag-len-mean 250 \ --frag-len-std-dev 40 \ --max-bundle-frags 9999999 \ --max-frag-multihits 20 \ --total-hits-norm \ --min-reps-for-js-test 2 \ --library-norm-method geometric \ --dispersion-method per-condition \ --min-alignment-count 12 \ ${outdir}/stringmerge/merged.gtf \ ${biogroup_files[*]} \ > ${outdir}/cuffdiff/cuffdiff.log.out.txt \ 2> ${outdir}/cuffdiff/cuffdiff.log.err.txt # --min-reps-for-js-test: Não será testada a expressão genica diferencial se não houver esse número minimo de réplicas. # --library-norm-method: Normalização do método. Geométrica: FPKMs e contagem dos fragmentos são escalados com base na # mediana das médias geométricas da contagem de fragmentos em todas as bibliotecas. # --dispersion-method: Método de dispersão. Por condição: Cada réplica recebe seu próprio modelo, não é realizado um pool. # --min-alignment-count:Número minimo de alinhamentos em um loco para esse ser submetido ao teste. # Restante dos parametros já foram citados anteriormente