---
# System prepended metadata

title: Applied Bioinformatics

---

# Applied Bioinformatics

This is a collaborative document that was used on day 4 and day 5 of the Applied Bioinformatics Course 2024. 

The developed and shared code from day 5 is on top, the one for day 4 at the bottom of the page. 

# Day 5 bracken results into db

## How should the format look like?

Article "How to Share Data for Collaboration"
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7518408/

What are the general guidelines outlined in the paper?

- send raw data
- tidy, not messy
- documentation
    - codes for the variables
    - how was the data generated?

How should our table look like?

- we need to add sample identifier to the existing table
    - we will use the accession number for that




## Our batch script(s)

Not necesserily in this order we need to: 

1:  add the sample identifier to the bracken output.
use accession number 

### Day 5: Group with 4
```
#!/bin/bash
#SBATCH --ntasks=1                  
#SBATCH --nodes=1                    
#SBATCH --cpus-per-task=1     
#SBATCH -A naiss2024-22-540
#SBATCH --mem=1GB       
#SBATCH --time=0-00:15   
#SBATCH -o slurm.%A.%a.out  
#SBATCH -e slurm.%A.%a.err   
#SBATCH --job-name=combine_bracken_report  


bracken_out_dir="/path/to/bracken_output" ## path to directory with bracken output files
accnum_file="/path/to/accnum_file" ## path to file with the list of accessions 

# add header
echo -e "accession_number\tname\ttaxonomy_id\ttaxonomy_lvl\tkraken_assigned_reads\tadded_reads\tnew_est_reads\tfraction_total_reads" > ${bracken_out_dir}/combined_bracken.out
# append all files with column accession number (Out files should be: {accession_number}.braken.out)
srun xargs -I{} -a $accnum_file awk -v id={} 'NR > 1 {print id "\t" $0}' ${bracken_out_dir}/{}.bracken.out >> ${bracken_out_dir}/combined_bracken.out
```


2:  gather the samples from everyone. 

We will do that by individually uploading our data sets into the database

3:  make a table in the sqlite data base. 



```
SQL_STATEMENT="
CREATE TABLE IF NOT EXISTS bracken_abundances_long (
    accession_number TEXT NOT NULL,
    name TEXT NOT NULL,
    taxonomy_id TEXT NOT NULL,
    taxonomy_lvl TEXT NOT NULL,
    kraken_assigned_reads INTEGER NOT NULL,
    added_reads INTEGER NOT NULL,
    new_est_reads INTEGER NOT NULL,
    fraction_total_reads REAL NOT NULL
    
);
"
DB_PATH="/proj/applied_bioinformatics/common_data/sample_collab.db"
sqlite3 "$DB_PATH" "$SQL_STATEMENT"
```

4:  fill the data base table with our data. 
```
#sqlite3 -batch -separator "$(printf '\t')"
sqlite3 -batch /proj/applied_bioinformatics/common_data/sample_collab.db ".separator \t" ".import path/to/your/combined_bracken.out bracken_abundances_long"
```

## Questions to answer with the data base: 

Please add the code you used to get the answers. 

1) can you check that the fraction_total_reads proportions add to one per sample ?
```
SELECT accession_number, SUM(fraction_total_reads) AS total_fraction
FROM bracken_abundances_long
GROUP BY accession_number
HAVING total_fraction != 1.0;
```

2) can you list the first 20 samples with highest SARS-CoV-2 abundance ?

```
SELECT accession_number, name, fraction_total_reads AS total_coronavirus_abundance
FROM bracken_abundances_long
WHERE name LIKE '%Severe acute respiratory%'
GROUP BY accession_number
ORDER BY total_coronavirus_abundance DESC
LIMIT 20;
```

```
sqlite3 -batch /proj/applied_bioinformatics/common_data/sample_collab.db "SELECT * 
FROM bracken_abundances_long 
WHERE name = 'Severe acute respiratory syndrome-related coronavirus' 
ORDER BY fraction_total_reads DESC 
LIMIT 20;"
```

3) can you see a relationship between SARS-CoV-2 abundance and Rt values ?
 

In Python:
```
df_sars = df[df["name"].str.contains("Severe acute respiratory")].sort_values("fraction_total_reads", ascending=False)

combined = df_sars.merge(sample_annot, left_on="accession_number", right_on="run_accession")

print(combined.columns)

plt.figure()

sns.scatterplot(combined, x="fraction_total_reads", y="Ct")
```

On command line:
```
sqlite3  -batch /proj/applied_bioinformatics/common_data/sample_collab.db "
SELECT *
FROM sample_annot
JOIN bracken_abundances_long ON sample_annot.run_accession = bracken_abundances_long.accession_number
WHERE name = 'Severe acute respiratory syndrome-related coronavirus' 
ORDER BY fraction_total_reads DESC"
```

Or in a nice box:

```
sqlite3 -box -batch /proj/applied_bioinformatics/common_data/sample_collab.db "SELECT run_accession, name, fraction_total_reads, Ct FROM sample_annot INNER JOIN bracken_abundances_long ON sample_annot.run_accession = bracken_abundances_long.accession_number WHERE name LIKE '%Severe acute respiratory%' ORDER BY fraction_total_reads DESC LIMIT 20"
```

4) can you check if SARS-CoV-2 is present in rtPCR negative patients ?
```
sqlite3 -box -batch /proj/applied_bioinformatics/common_data/sample_collab.db \
    "SELECT run_accession, name, fraction_total_reads, Ct 
    FROM sample_annot 
    INNER JOIN bracken_abundances_long 
    ON sample_annot.run_accession = bracken_abundances_long.accession_number 
    WHERE name LIKE '%Severe acute respiratory%' AND Ct = '0.0';"
```

Also on command line
```
sqlite3 -box -batch /proj/applied_bioinformatics/common_data/sample_collab.db "SELECT run_accession, name, fraction_total_reads, Ct, host_disease_status FROM sample_annot INNER JOIN bracken_abundances_long ON sample_annot.run_accession = bracken_abundances_long.accession_number WHERE name LIKE '%Severe acute respiratory%' AND host_disease_status = 'SARS-CoV-2 negative' ORDER BY fraction_total_reads DESC LIMIT 20"
```

5) is SARS-CoV-2 only ever seen in RNA samples (ie not in DNA samples) ?
```
sqlite3 -box -batch /proj/applied_bioinformatics/common_data/sample_collab.db 
"SELECT run_accession, name, fraction_total_reads AS total_coronavirus_abundance, nuc, host_disease_status
FROM sample_annot sa
INNER JOIN bracken_abundances_long bal ON sa.run_accession = bal.accession_number
WHERE nuc='RNA' AND name LIKE '%Severe acute respiratory%'
ORDER BY  total_coronavirus_abundance DESC
LIMIT 20"
```
6) what are the 10 most ubiquitous human pathogens found in the 125 patients ? Below is list known to be associated with upper airways and oral/nasal cavities of the study's supp tables 3 & 4:

'Dolosigranulum pigrum','Haemophilus influenzae', 'Haemophilus parainfluenzae',
'Klebsiella pneumoniae','Streptococcus pneumoniae','Staphylococcus aureus','Influenza A virus',
'Severe acute respiratory syndrome-related coronavirus','Chlamydia pneumoniae',
'Haemophilus parainfluenzae','Serratia marcescens','Enterobacter hormaechei',
'Enterobacter cloacae', 'Enterobacter asburiae','Burkholderia multivorans',
'Human coronavirus HKU1','Human coronavirus NL63','Rhinovirus A'


* to view the top 10
```
SELECT name, COUNT(name) as prevalence
FROM sample_annot sa
INNER JOIN bracken_abundances_long bal ON sa.run_accession = bal.accession_number
GROUP BY name
ORDER BY  prevalence DESC
LIMIT 10;
```
* to compare the top 10 against the list of known pathogens

```
SELECT name, COUNT(name) as prevalence
FROM sample_annot sa
INNER JOIN bracken_abundances_long bal ON sa.run_accession = bal.accession_number
WHERE name IN ('Dolosigranulum pigrum',
'Haemophilus influenzae', 
'Haemophilus parainfluenzae',
'Klebsiella pneumoniae',
'Streptococcus pneumoniae',
'Staphylococcus aureus',
'Influenza A virus',
'Severe acute respiratory syndrome-related coronavirus',
'Chlamydia pneumoniae',
'Haemophilus parainfluenzae',
'Serratia marcescens',
'Enterobacter hormaechei',
'Enterobacter cloacae', 
'Enterobacter asburiae',
'Burkholderia multivorans',
'Human coronavirus HKU1',
'Human coronavirus NL63',
'Rhinovirus A')
GROUP BY name
ORDER BY  prevalence DESC
LIMIT 10;
```
### Scripts from other groups:

#### some group
to add accession number in each file.

In your MedBioInfo folder:
```
# first add accession numbers as the last column of each bracken.out files 
# and concatenate all in one (called #bracken_sql.out).

#Dont forget to change the username and file pattern.

srun \
cat analyses/username_run_accessions.txt \
| xargs -I % sh -c \
"sed  '1d;s/$/\t%/' analyses/kraken2/%_bracken.out" \
> analyses/kraken2/bracken_sql.out
-- % 

# then add headers to the created file
srun \
sed -i 1i"name\ttaxonomy_id\ttaxonomy_lvl\tkraken_assigned_reads\tadded_reads\tnew_est_reads\tfraction_total_reads\taccession_number" analyses/kraken2/bracken_sql.out
```

#### group x
```
# usage: bash your_bash_script_filename_here.sh
# run only once

srun -A naiss2024-22-540 bash -c '
directory_to_search="/proj/applied_bioinformatics/users/x_ronod/MedBioinfo/data/bracken_out/"  # Change this to your directory
# Find all files matching ERR*result
find "$directory_to_search" -type f -name "ERR*result" | while read -r file_path; do
    # Split the basename using "_" and take the first field
    basename=$(basename "$file_path")
    accession_number=$(echo "$basename" | cut -d"_" -f1)
    
    # Create a temporary file
    tmp_file=$(mktemp)
    
    # Add the accession number column to the start of the file
    awk -v acc="$accession_number" "BEGIN {FS=OFS=\"\t\"} NR==1 {\$0=\"accession_number\" OFS \$0} NR>1 {\$0=acc OFS \$0} 1" "$file_path" > "$tmp_file"
    
    # Move the temporary file back to the original file
    mv "$tmp_file" "$file_path"
    
    echo "Processed $file_path"
done
'
```

#### Group: Fantastic four
Adding accession number or Sample ID to your Bracken output.

Step by step guide:
1) Make sure that you have the Bracken output files by first go to your output directory `cd /proj/applied_bioinformatics/user/"YOUR PATH HERE"/bracken_output_files`. Locate the files using `ls`. 
2) Create the bash script in your directory using `nano add_accession_number.sh`. Copy-paste the code below. 
3) Run the script and pray.
4) Make sure that the output is correct by examine your `.tsv` file by using the following bash command in your terminal: `head ERR******_bracken.tsv`. If you now can see your Accession number or Sample ID, you have completed the task. Good job!

```
#!/bin/bash

#SBATCH -A naiss2024-22-540
#SBATCH -n 1
#SBATCH -t 01:00:00
#SBATCH -J blastp
#SBATCH -o blastp.%j.out
#SBATCH -e blastp.%j.err
#SBATCH --mail-user ***********@ki.se
#SBATCH --mail-type=BEGIN,END,FAIL,TIME_LIMIT_80

# To run this script your bracken out file name should be as bracken.1.ERR****.out

# Define paths
bracken_dir="/path/to/bracken/files"

cd "$bracken_dir" || exit

# Initialize the output file and add a header
output_all="all_sample.tsv"
echo -e "Accession_Number\tColumn1\tColumn2" > "$output_all"

# Loop through each file in the directory
for file in *.out; do
  # Check if the file name matches the pattern we need
  if [[ $file =~ bracken\.[0-9]+\.(ERR[0-9]+)\.out ]]; then
    # Extract the sample name using the regex capture group
    sample="${BASH_REMATCH[1]}"
    
    # Create the output filename
    output="${sample}_bracken.tsv"
    
    # Run the awk command
    awk -F, -v sample="$sample" 'NR==1 {print "Accession_Number\t"$1"\t"$2} NR>1 {print sample "\t"$1"\t"$2}' "$file" > "$output"
    
    # Append the generated file content to the all_sample.tsv, excluding the header
    tail -n +2 "$output" >> "$output_all"
  else
    # Print a message if the file does not match the pattern
    echo "Skipping file: $file (does not match the required pattern)"
  fi
done
```

#### Group: At the End
The following piece of code has two main steps. Firstly, it adds the accession number of every file into the bracken report output, in a column titled 'sample_id'. Secondly, it collates all the now modified reports into a single file, to be loaded into SQL. 

The file has headers, corresponding to:
* name	
* taxonomy_id	
* taxonomy_lvl	
* kraken_assigned_reads	
* added_reads	new_est_reads	
* fraction_total_reads
* sample_id	

The script is intended to be loaded as part of the nextflow pipeline such that all produced bracken outputs will be processed.

This first part is to be appended to the BRACKEN process.
```
process BRACKEN...{

	input: 
    path(bracken_output) // is not collected
	tuple val(id), path(reads)

	// directives:
	container 'https://depot.galaxyproject.org/singularity/gawk:5.3.0'
	publishDir "$params.outdir/06_prepbracken"

	script:
	"""
	awk 'BEGIN {FS=OFS="\t"}{\$0 = \$0 OFS (NR == 1 ? "sample_id" : "${id}")} 1' ${bracken_output} | awk 'NR>1' > ${id}_sortedbrackenreport.txt;
	"""

	output:
	path "${id}_sortedbrackenreport.txt", emit: indiv_modified_bracken_report

}

```

This second part is a process of its own.
```
process PREPBRACKEN{

	input: 
    path(indiv_modified_bracken_report) // is collected
	tuple val(id), path(reads)

	// directives:
	container 'https://depot.galaxyproject.org/singularity/gawk:5.3.0'
	publishDir "$params.outdir/06_prepbracken"

	script:
	"""	
    cat ${indiv_modified_bracken_report} > sortedbrackenreport.txt
	"""	
    
    output:
	path "sortedbrackenreport.txt", emit: modified_bracken_report
}
```



------
# Day 4 Introduction to Nextflow

This document is a living document we can all work on in real time. We can ask questions and answer them, post code for everyone etc. 

The document is written in Markdown. Here is a link to some basic syntax: https://www.markdownguide.org/basic-syntax/

 > blockquote

    code (indented by one tab, or four spaces)

In line `code`by using backticks (`)


## Flash2: Merging paired end reads

Write your first own process:

```
process FLASH2 {
    input:
   
    // directives
    
    
    script:
    """
    
    """

    output:
}
```

#### Amrei 
```
process FLASH2 {

	input: 
	tuple val(id), path(reads)

	// directives
	container 'https://depot.galaxyproject.org/singularity/flash2:2.2.00--hed695b0_2'
	publishDir "$params.outdir/02_flash"

	script: 
	"""
	flash2 \\
	    $reads \\
	    --output-prefix="${id}.flash2" \\
	    --max-overlap=150 \\
	    | tee -a ${id}_flash2.log
	"""

	output: 
	tuple val(id), path ("${id}.flash2.extendedFrags.fastq"), 	emit: merged_reads
	path "${id}.flash2.notCombined*.fastq", 	emit: notCombined_fastq
	path "${id}.flash2.hist", 			emit: flash2_hist
	path "${id}.flash2.histogram", 			emit: flash2_his2togram
	path "${id}_flash2.log", 			emit: log
	
}
```
#### Group with 5
```
process FLASH2 {
    input: 
	tuple val(id), path(reads)
   
    // directives
	container "https://depot.galaxyproject.org/singularity/flash:1.2.11--h5bf99c6_6"
    publishDir "$params.outdir/02_flash2"

	script:
    """
    flash  \\
    -z -t 2 \\
    $reads 2>&1 \\
    | tee

    flash -t 2 \
	-o ${id}.flash \
	-d $params.outdir/02_flash \
	${reads[0]} ${reads[1]}


    """

    output:
    path "${id}*flash", emit: flash
    path "${id}*log", 	emit: log
}
```




#### Group 5
```
process FLASH2 {
    input:
    tuple val(id), path(reads)
   
    // directives
    container https://depot.galaxyproject.org/singularity/flash2%3A2.2.00--he4a0461_6
    publishDir '$params.outdir/flas2'
    
    script
    """
    flash \
    $reads
    """

    output:
    path "${id}",       emit: merged_reads

}
```

```
process BOWTIE2 {
    input:
    database
    tuple val(id), path(merged_reads)
    
   
    // directives
    container https://depot.galaxyproject.org/singularity/bowtie2%3A2.5.4--he20e202_0
    publishDir '$params.outdir/03_bowtie2'
    
    script
    """
    bowtie2 \
        -x $bowtie2_db \\
        -U $merged_reads \\
        -S ${id}.sam
    
    """

    output:
    path "${id}.sam", emit: sam_file

}
```


#### Group the best potato group
##### Flash2: Merging paired end reads


```
process FLASH2 {
    input:
    tuple val(id), path(reads)
   
    // directives
    container 'https://depot.galaxyproject.org/singularity/flash:1.2.11--h5bf99c6_6'
    publishDir "$params.outdir/02_merged" 

    script:
	"""

	flash \\
	    --threads 2
        --compress
        -o {}.flash
        ${id}_1.fastq.gz
        ${id}_2.fastq.gz
        

	"""

output:
path "${id}*extendedFrags.fasta.gz", 	emit: merged_reads
}
```

```

process BOWTIE2 {
    input:
    tuple val(id), path(merged_reads), path(bowtie_db)
   
    // directives
    container 'https://depot.galaxyproject.org/singularity/bowtie2:2.5.2--py39h6fed5c7_0'
    publishDir "$params.outdir/03_bowtie" 

    script:
	"""

	bowtie2 \\
        
		-x $bowtie_db \\
		--no-unal \\
		-U $merged_reads \\
		-S ${id}_merged2PhiX.sam \\
		| tee -a ${id}_merged2PhiX.log
	"""

output:
path "${id}_merged2PhiX.sam", 	emit: bowtie_sam
path "${id}_merged2PhiX.log", emit: bowtie_log
}
```


#### Group the best best group
##### Flash2: Mergigng paired end reads

```
process FLASH2 {
    input:
    tuple val(id), path(reads)
   
    // directives
    container 'https://depot.galaxyproject.org/singularity/flash:1.2.11--h5bf99c6_6'
    publishDir "$params.outdir/02_flash2"
    
    script:
    """
   flash \\
   --threads 2 \\
   --compress \\
   --output-prefix .flash \\
   $reads \\
   
   
    """

    output:
    path "${id}*fastqc.html",       emit: flash_
    "
}
```

```
process BOWTIE2{
   input: 
   path(bowtie2_db)
    tuple val(id), path(merged_reads)
   
   // directives
	container 'https://depot.galaxyproject.org/singularity/bioconductor-crisprbowtie:1.6.0--r43hdfd78af_0'
	publishDir "$params.outdir/03_bowtie2"

script:
        """
        bowtie2 -x $bowtie2_db -U $merged_reads --threads 8 --no-unal \\
        | tee ${id}_bowtie2.log
        """   
        
output:
 path "${id}.sam",                           emit: sam

}
```

## change workflow scope
Here is also the old workflow scope. How do we need to change that one to add the new process?

```
workflow{
	ch_input = Channel.fromFilePairs(params.input_read_pairs, checkIfExists: true )	

	// quality control
	FASTQC ( ch_input )

	// assembling reports
	MULTIQC ( FASTQC.out.qc_zip.collect())
}
```


## Where to find containers?
Here is a good resource on where to find containers:

https://depot.galaxyproject.org/singularity/


Alternatively, you can do an internet search for **nf-core modules** and the name of your tool - in this case flash2. Go to the github repository of that module and copy paste the link to the singularity container from the **main.nf** file.

Look up seqera containers - brand-new - which can make singularity containers for you on the fly. Choose which tools should be available in there, which environment they will be run in and it'll make a container for you. 

## Bowtie2: Map the reads to the data base

We need to: 

a) change the workflow scope

What do we need as an input for bowtie? 
Which channel factory/factories could be useful here?


b) add a new process called BOWTIE2

```
process BOWTIE2 {
    input:
   
    // directives

    script:
    """
    
    """

    output:
}
```

c) define the run time environment for this process

```
withName:'BOWTIE2'{

}	
```




### Flash2: Merging paired end reads


```
process FLASH2 {
        input:
        tuple val(id), path(reads)

        //directives
        container 'https://depot.galaxyproject.org/singularity/flash%3A1.2.11--h5bf99c6_6'
        publishDir "$params.outdir/02_flash"

        script:
        """

        flash $reads \
                

        """

        output:
        path "${id}.fastq.gz",     emit: merged_pairs
}
```

#### erik
```
    process FLASH2 {
        input:
        tuple val(id), path(reads)

        // directives

        container 'https://depot.galaxyproject.org/singularity/flash2:2.2.00--hed695b0_2'
        publishDir "$params.outdir/02_flash" 

        script:
        """
        flash2 \\
            $reads \\
            --output-prefix="${id}.flash2" \\
            --max-overlap=150 \\
            | tee -a ${id}_flash2.log
        """

        output:
        tuple val(id), path ("${id}.flash2.extendedFrags.fastq"),	emit: merged_reads
        path "${id}.flash2.notCombined*.fastq",	emit: notCombined_fastq
        path "${id}.flash2.hist",	emit: flash2_hist
        path "${id}.flash2.histogram",	emit: flash2_histogram
        path "${id}_flash2.log",	emit: flash2_log

    }
```

#### Amrei Bowtie2
```

process BOWTIE2 {

	input: 
	path(bowtie2_db)
	tuple val(id), path(merged_reads)

	// directives:
	container 'https://depot.galaxyproject.org/singularity/mulled-v2-ac74a7f02cebcfcc07d8e8d1d750af9c83b4d45a:f70b31a2db15c023d641c32f433fb02cd04df5a6-0'
	publishDir "$params.outdir/03_bowtie2"

	script:
	db_name = bowtie2_db.find{it.name.endsWith(".rev.1.bt2")}.name.minus(".rev.1.bt2")****
	"""

	bow****tie2 \\
	    -x $db_name \\
	    -U $merged_reads \\
	    -S ${id}_bowtie2_merged_${db_name}.sam \\
	    --no-unal \\
	    |& tee -a ${id}_bowtie2_merged_${db_name}.log

	"""

	output:
	path "${id}_bowtie2_merged_${db_name}.log", emit: logs
	path "${id}_bowtie2_merged_${db_name}.sam", emit: aligned_reads 
	
}

```

## Kraken

```
process KRAKEN2{

	input: 
	path(kraken2_db)
	tuple val(id), path(reads)

	// directives:
	container 'https://depot.galaxyproject.org/singularity/mulled-v2-8706a1dd73c6cc426e12dd4dd33a5e917b3989ae:c8cbdc8ff4101e6745f8ede6eb5261ef98bdaff4-0'
	publishDir "$params.outdir/04_kraken2"

	script:
	"""
	kraken2 \\
	    -db $kraken2_db \\
	    --paired \\
        --gzip-compressed \\
		--output ${id}_kraken2_taxonomy.txt \\
		--classified-out "${id}_kraken2_classified#.fq" \\
		--report ${id}_kraken2_report.txt \\
		$reads \\
	    |& tee -a ${id}_kraken2.log
	"""

    output:
	path "${id}_kraken2.log", emit: logs
	path "${id}_kraken2_classified*.fq" , emit: kraken2_classified_reads 
	path "${id}_kraken2_taxonomy.txt", emit: kraken2_taxonomy
	path "${id}_kraken2_report.txt", emit: kraken2_report
	
}

```

Command to make the output look nicer: 
sed -i -E 's/\b[scogfkp]\__//g' $krona_output




