# tutorials

topic: transcriptomics
tutorial: rna-interactome
title: RNA-RNA interactome data analysis
difficulty: intermediate
time_estimation: 2H
tools_json: []
requirements_json: []
tags_json: []
content_hash: 43fa92ce5345e30919303449fb2aa5f1
last_modified: 2026-02-26T21:12:18.563839
zenodo_link: https://zenodo.org/record/3709188
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/rna-interactome/tutorial.html

content:
With the advances in the next-generation sequencing technologies, genome-wide RNA-RNA interaction predictions are now
possible. The most recent line of development has been to ligate the microRNA to the site-specific interaction region of
 the target, selecting these interactions via cross-linking to one of the Argonaute proteins required for microRNA-based
  regulation, and to sequence the resulting chimeric RNA molecule, for example, the CLASH and CLEAR-CLIP protocols.
Going beyond microRNAs, these protocols can be applied to RNA interactions that involve a regulatory protein
other than Argonaute. To generalize even further, researchers have applied the same idea to the detection of all
transcriptome-wide RNA-RNA interactions, which include both inter- and intramolecular base pairing without the necessity
 of choosing a specific regulatory protein for cross-linking. These protocols include LIGR-Seq that maps the human
 RNA-RNA interactome and PARIS that focused on long-range structures in human and mouse.

The reads from these experiments are chimeric with each arm generated from one of the interaction
partners. Due to short lengths, often these sequenced arms ambiguously map to multiple locations and  inferring the
origin of these can be quite complicated. Theoretically, alignment tools like `HISAT2` and `STAR` can be used to align
chimeric reads, but they are not efficient at this task. The other alignment tools like `BWA-MEM` or `Bowtie2` can be
used in local alignment settings to map these chimeric reads. In this case user needs to adjust the alignment parameters
to match the read lengths and there needs to be a lot of post-processing to be done to choose the best hits. Recently,
there is also an alignment tool called `CLAN` published to specifically map the chimeric reads from CLASH experiments.

In this tutorial, we will learn the analysis of a CLEAR-CLIP data set using a tool suite called `ChiRA`. The data used
is from mouse cortex sample
([GSM1881541](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM1881541)) prepared using CLEAR-CLIP protocol. It is
a complete analysis framework that can be used starting from raw sequencing reads to analysis and visualization of
results. `ChiRA` uses `BWA-MEM` or `CLAN` to map the reads. Subsequently, it also merges the overlappig alignments and
 chooses the best alignments per read by quantifying the all the loci that reads map to. In the end, it scores each
  alignment and outputs only the best alignments per read. The final part of this tutorial gives an insight into how to
  filter, export and visualize your results using the visualization framework `ChiRAViz`.


![ChiRA workflow](../../images/rna-interactome/chira.png "ChiRA workflow. First the reads deduplicated and mapped to transcriptome. Then the mapped loci are merged based on overlapping. The merged loci are quantified and the interactions are scored and reported.")

> <agenda-title></agenda-title>
>
> In this tutorial, we will cover:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Get data

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this tutorial
> 2. Import the files from [Zenodo](https://zenodo.org/record/3709188) or from the shared data library
>
>    ```
>    https://zenodo.org/record/3709188/files/miRNA_mature.fa.gz
>    https://zenodo.org/record/3709188/files/Mus_musculus.GRCm38.dna.fa.gz
>    https://zenodo.org/record/3709188/files/SRR2413302.fastq.gz
>    https://zenodo.org/record/3709188/files/transcriptome.fa.gz
>    https://zenodo.org/record/3709188/files/whole_transcriptome.gff.gz
>    ```
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    {% snippet faqs/galaxy/datasets_import_from_data_library.md %}
>
> 3. Rename the datasets
> 4. Check that the datatype
>
>    {% snippet faqs/galaxy/datasets_change_datatype.md datatype="datatypes" %}
>
> 5. Add to each database a tag corresponding to ...
>
>    {% snippet faqs/galaxy/datasets_add_tag.md %}
>
{: .hands_on}

# Preprocessing

Before starting with the analysis of data it is always good to check the sequenced reads for low quality bases and
adapters.

## Quality control

> <hands-on-title>Quality check</hands-on-title>
> First use `FastQC` to assess the read quality
>
> 1. **FastQC** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"Short read data from your current history"*: `SRR2413302.fastq.gz` (Input dataset)
>
{: .hands_on}

> <question-title></question-title>
>
> 1. Why do you think `FastQC` failed to find any adapters?
>
> > <solution-title></solution-title>
> >
> > 1. Because `FastQC` it uses a set of standard adapters to screen for adapters. The "special" adapters used in this
> >    library preparation are not present in the `FastQC` standard adapters list.
> >
> {: .solution}
>
{: .question}

## Adapter trimming
Due to the inefficiency of the current RNA interactome protocols, not all reads are not made up of RNA hybrids. In some
cases, reads contain single RNA fragments with adapters or nothing but only adapters. Hence adapter removal is a very important step
in this analysis. In this step, we use `cutadapt` to trim the adapters. As the adapters used in this library are not
standard Illumina adapters, we need to provide them manually.

> <hands-on-title>Adapter trimming</hands-on-title>
> We use `cutadapt` to trim the adapter content
>
> 1. **cutadapt** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"FASTQ/A file"*: `SRR2413302.fastq.gz` (Input dataset)
>    - In *"Read 1 Options"*
>       - *"3' (End) Adapters"* -> *"Insert 3' (End) Adapters"*
>           - *"Source"*: `Enter Custom sequence`
>           - *"Enter custom 3' adapter sequence"*: `GTGTCAGTCACTTCCAGCGG`
>       - *"5' (Front) Adapters"* -> *"Insert 5' (Front) Adapters"*
>           - *"Source"*: `Enter Custom sequence`
>           - *"Enter custom 5' adapter sequence"*: `GCATAGGGAGGACGATGCGG`
>    - In *"Filter Options"*
>        - *"Minimum length"*: `16`
>
{: .hands_on}


> <hands-on-title>Post adapter trimming quality check</hands-on-title>
> It is interesting to see whether our manually entered adapters were trimmed
>
> 1. **FastQC** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"Short read data from your current history"*: `Read 1 Output` (output of **cutadapt** {% icon tool %})
>    - Observe the **Per base sequence content**
> ![FastQC per base sequence content](../../images/rna-interactome/chira_fastqc_seq_content.png)
{: .hands_on}

> <question-title></question-title>
>
> Would you be concerned about the abnormal "Per base sequence content towards the end"?
>
> > <solution-title></solution-title>
> >
> > Normally yes, but in this case not. Always look at this plot in combination with "Sequence Length Distribution"
> > plot. It looks like there is huge difference in base composition after 55th base. But the number of
> > sequences that constitute this is very important. From the sequence length distribution, most of the sequences are
> > between 53 and 57 bases long. We see the abnormality in the per base sequence content because it is from
> > very few sequences.
> > ![FastQC sequence length distribution](../../images/rna-interactome/chira_fastqc_seq_length.png)
> >
> {: .solution}
>
{: .question}

# Analysis of interactome data using `ChiRA` tool suite

The analysis includes several steps that deal with deduplication mapping, quantification and extraction of interacting
partners.

## Remove duplicate sequences

First, we eliminate the duplicate sequences from the library to reduce the computational effort. This will also have an
impact on the quantification of the loci because often these identical sequences might be PCR duplicates. There is also
a 5' degenerate linker of length 5 nucleotides present in the reads. Hence we have to strip that too.

> <hands-on-title></hands-on-title>
>
> 1. **ChiRA collapse** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"Input FASTQ file"*: `Read 1 Output` (output of **cutadapt** {% icon tool %})
>    - *"Length of the UMI if present at the 5' end of your reads"*: `5`
>
>    > <tip-title>Dealing with UMIs</tip-title>
>    >
>    > * If you have UMIs (at the 5' end) in the sequenced reads, please set *"Length of the UMI if present at the 5' end of your reads"*.
>    > * The UMI will be trimmed and put in the unique sequence id.
>    {: .tip}
>
{: .hands_on}


## Map reads to the reference transcriptome

> <hands-on-title>Map chimeric reads from fasta file</hands-on-title>
> Here we use `BWA-MEM` aligner in local alignment mode to locate the chimeric arms on the
> transcriptome. Your reference can be single or split in two. Two references are
> ideal for example if you have CLASH experimental data where you have separate
> miRNA and target references.
>
> 1. **ChiRA map** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"Input FASTA file"*: `fasta file` (output of **ChiRA collapse** {% icon tool %})
>    - *"Single or split reference?"*: `Split reference`
>        - {% icon param-file %} *"Reference FASTA file"*: `miRNA_mature.fa.gz` (Input dataset)
>        - {% icon param-file %} *"Second reference FASTA file"*: `transcriptome.fa.gz` (Input dataset)
>    - *"aligner"*: `BWA-MEM`
>
{: .hands_on}


## Merge overlapping alignment information

In this step, we merge the overlapping aligned positions to define the read concentrated loci. If an annotation GTF file
produced, the transcriptomic alignment positions are first converted to their corresponding genomic positions. The
merging is also done on reads defining which parts of the reads are mapping that indicates potential interacting segments
of read.

> <hands-on-title></hands-on-title>
>
> 1. **ChiRA merge** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"Input BED file of alignments"*: `ChiRA aligned BED` (output of **ChiRA map** {% icon tool %})
>    - *"Do you have an annotation in GTF format?"*: `Yes`
>        - {% icon param-file %} *"Annotations in GTF format"*: `whole_transcriptome.gff.gz` (Input dataset)
>    - *"Did you use single or split reference for alignment?"*: `Split reference`
>        - {% icon param-file %} *"Reference FASTA file"*: `miRNA_mature.fa.gz` (Input dataset)
>        - {% icon param-file %} *"Second reference FASTA file"*: `transcriptome.fa.gz` (Input dataset)
>
>    > <tip-title>Parameters for samples with high coverage.</tip-title>
>    >
>    > * In samples with a very high coverage, the likelihood of having overlapping alignments increases. Hence the
>    >   default `Overlap based` merging may results in very long loci merged by some random alignments.
>    > * Therefore, use the `blockbuster` merging mode and adjust the paramertes accordingly.
>    >   - From *"Select the mode of merging"*: `Gaussian based (blockbuster)`
>    > * Working with only the chimeric reads further reduces the computation time fr subsequent steps.
>    >   - *"chimeric_only"*: `Yes`
>    {: .tip}
>
{: .hands_on}

## Quantify aligned loci to score the alignments

Now we have the loci where the potential interacting read segments are mapped to. Due to the small length of these arms, there is a
very high chance of multi mapping. Another reason for this is the lenient mapping parameters that are used to increase
the mapping sensitivity. Quantification needs 2 files containing read segements and loci where they are mapping to. From
this information, `ChiRA quanitify` tries to infer the correct origin of reads and calculates the expression of the loci
using a simple expectation-maximization algorithm.

> <hands-on-title>Task description</hands-on-title>
>
> 1. **ChiRA qauntify** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"BED file of aligned segments"*: `ChiRA aligned read segments` (output of **ChiRA merge** {% icon tool %})
>    - {% icon param-file %} *"Tabular file of merged alignments"*: `ChiRA merged alignments` (output of **ChiRA merge** {% icon tool %})
>
{: .hands_on}

## Extract the best scoring chimeras

After having the information about the loci expression, the final step extracts only the best scoring interacting
partners for each read. All the combinations of the transcripts that are overlapping with the interacting loci are
reported. If there is more than one locus with the equal best score then all the best hits are reported. If you have the
genomic fasta file the tool can hybridize the interacting loci sequences using `IntaRNA`.

> <hands-on-title>Task description</hands-on-title>
>
> 1. **ChiRA extract** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"File containing CRLs information"*: `ChiRA quantified loci` (output of **ChiRA qauntify** {% icon tool %})
>    - *"Have genomic information?"*: `Yes`
>        - {% icon param-file %} *"Annotations in GTF format"*: `whole_transcriptome.gff.gz` (Input dataset)
>        - *"Choose the source for the FASTA file"*: `History`
>            - {% icon param-file %} *"FASTA file"*: `Mus_musculus.GRCm38.dna.fa.gz` (Input dataset)
>    - *"Did you use single or split reference for alignment?"*: `Split reference`
>        - {% icon param-file %} *"Reference FASTA file"*: `miRNA_mature.fa.gz` (Input dataset)
>        - {% icon param-file %} *"Second reference FASTA file"*: `transcriptome.fa.gz` (Input dataset)
>    - *"Hybridize chimeric loci?"*: `Yes`
>    - *"Summarize interactions at loci level?"*: `Yes`
>
{: .hands_on}

# Visualization

The output tabular file generated in the above step can be huge with up to some millions of rows depending on the
library size and more than 30 columns. Extracting useful data from this can be very tedious. For example, extracting and
visualizing the distribution of target biotypes of your favorite miRNA can be very tricky and might need more than a
hand full of galaxy tools to achieve. For this reason, there exists a visualization and filtering tool for this data along
with `ChiRA` known as `ChiRAViz`. It is a galaxy visualization framework to work with the output of `ChiRA`. But it does
not directly work with the tabular output we have. Rather it needs a "sqlite" database. For this reason, we first build a
sqlite database from the `ChiRA` output.

> <hands-on-title>Data preperation</hands-on-title>
>
> 1. **Query Tabular** {% icon tool %} with the following parameters:
>    - In *"Database Table"*:
>        - {% icon param-repeat %} *"Insert Database Table"*
>            - {% icon param-file %} *"Tabular Dataset for Table"*: `ChiRA chimeric reads` (output of **ChiRA extract** {% icon tool %})
>    - In *"Table Options"*
>        - *"Use first line as column names"*: `Yes`
>    - *"Save the sqlite database in your history"*: `Yes`
>
> 2. Change the datatype to `chira.sqlite`
>
>    {% snippet faqs/galaxy/datasets_change_datatype.md datatype="chira.sqlite" %}
>
{: .hands_on}

> <hands-on-title>Visualize interactions</hands-on-title>
>
> 1. Please click on {% icon galaxy-barchart %} *"Visualize this data"*. Then click on the `ChiRAViz` visualization.
>    This loads the data into the visualization framework and shows some basic plots from the data.
>    - The visualization split into two to show the left and the right arms information.
>    - On home page pie charts of left and right chimeric arms, types of interactions and top 50 expressed RNAs are shown.
>    ![ChiRAViz home page](../../images/rna-interactome/chiraviz_view1.png)
> 2. Now choose the bio types of interactions that you want to work with. Here we first get all available interactions,
>    and then filter the interactions we are interested in next page. To get all interactions, choose `all` in both dropdowns
>    on the top and then click on **"Get interactions"**.
>
>    ![ChiRAViz selector](../../images/rna-interactome/chiraviz_choose.png)
>
{: .hands_on}

> <hands-on-title> Filter and summarize interactions and export the results</hands-on-title>
> `ChiRAViz` provides filters to search for keywords like gene symbols, sort interactions by score, filter by score or
> hybridization energy. Then the filtered interactions can be summarized or exported to a file. In this step, we filter
> the interactions that `mmu-miR-190a` involved in and consider those which have an `IntaRNA` predicted hybrid.
>    - To search, type `mir-190a` in the search field and click on search icon
>      or hit enter. Search is case insensitive and can search for sub-phrases
>      too. This results in 27 records.
>    - We now further filter the records that contain `IntaRNA` hybrid. If
>      there is no hybrid predicted by `IntaRNA`,
>      then the hybrid filed contains an `NA` value.
>       - From **"--filter--"** dropdown choose `Hybrid`
>       - From **"--operator--"** choose `<>`
>       - Enter `NA` in the value field and hit the enter key.
>    This filters out 10 more records and results in 17 records.
>    - At this point, you can select individual interactions by clicking the individual checkboxes or by clicking **"Check all"**. Both the possibilities are highlighted in red color in the following figure.
>    - Click on **Summary** to view the summary plots for the selected interactions.
>    - Clicking on **Export** to export the selected interactions to a file.
> ![ChiRAViz filter page](../../images/rna-interactome/chiraviz_view2.png)
{: .hands_on}

> <question-title></question-title>
>
> 1. Which strand of `mmu-miR-190a` is the most expressed?
>
> > <solution-title></solution-title>
> >
> > Both strands of `mmu-miR-190a` participated in the interactions, but `mmu-miR-190a-5p` is the most abundant strand between the two.
> >
> {: .solution}
>
{: .question}


> <hands-on-title> Viewing individual interaction information</hands-on-title>
> - From the list of interactions in the left panel expand the interaction `mmu-miR-190a-5p:Myo5a` by clicking on "+" (highlighted in red). There are 4 sub-records
>   corresponds to 4 different transcripts of the target gene `Myo5a`.
> - Click on one of the records to view following information.
>   - **"Chimera"** panel in the middle depicts the mapping positions on the read with read length.
>   - **"Interacting partners"** panel shows the information on which transcripts the left and right arm are mapping to with their alignment positions on the transcripts.
>   - **"Alignment Information"** panel shows the alignment if present with a possibility to download the alignment.
> ![ChiRAViz single interaction](../../images/rna-interactome/chiraviz_view3.png)
{: .hands_on}

# Conclusion


Though chimeric reads look normal when inspected in a FASTQ file, the origin of each read is from two different RNA fragments. Limitations of the current sequencing protocols limit the length of each sequenced interacting RNA fragment. These smaller RNA fragments are often harder to map considering that the boundaries of each RNA fragment in the read are unknown. In this tutorial, we have seen how to map these reads and infer the true origins of them by quantifying the mapped loci. The visualization framework gives flexibility in filtering and searching output files, visualize the summaries of filtered data as well as exporting them.


topic: transcriptomics
tutorial: network-analysis-with-heinz
title: Network analysis with Heinz
difficulty: intermediate
time_estimation: 1h30m
tools_json: []
requirements_json: []
tags_json: ["metatranscriptomics", "network analysis"]
content_hash: 98bc0ae6d8ec3a1fbbc13013568a2ec0
last_modified: 2026-02-26T21:12:18.560192
zenodo_link: https://doi.org/10.5281/zenodo.1344105
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/network-analysis-with-heinz/tutorial.html

content:
# Overview


The human microbiome plays a key role in health and disease. Thanks to comparative metatranscriptomics,
the cellular functions that are deregulated by the microbiome in disease can now be computationally
explored. Unlike gene-centric approaches, pathway-based methods provide a systemic view of such
functions; however, they typically consider each pathway in isolation and in its entirety.
They can therefore overlook the key differences that (i) span multiple pathways, (ii) contain
bidirectionally deregulated components, (iii) are confined to a pathway region. To capture these
properties, computational methods that reach beyond the scope of predefined pathways are needed.

In this tutorial, we will perform a network analysis using Heinz ([GitHub](https://github.com/ls-cwi/heinz),
[publication](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2718639/)) in Galaxy. The data comes from
the study [May et al.](https://academic.oup.com/bioinformatics/article/32/11/1678/2240171),
and we will reproduce some of the computational steps from this study with simplified data and
parameters to speed up the analysis for the purposes of this tutorial.

> <agenda-title></agenda-title>
>
> In this tutorial, we will cover:
>
> 1. TOC
> {:toc}
>
{: .agenda}


{% snippet faqs/galaxy/analysis_results_may_vary.md %}


In this tutorial, we will run the Heinz workflow step by step to understand how each step works. To get an overview of what this workflow does
and what kind of calculation is involved, view the flowchart below.

![Heinz flowchart](../../images/transcriptomics_images/flowchart-heinz.png)

# Obtaining and preparing data  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1344105.svg)](https://doi.org/10.5281/zenodo.1344105)


The study [May et al.](https://academic.oup.com/bioinformatics/article/32/11/1678/2240171) includes the computation
steps starting from the raw RNAseq datasets. The operations that processed raw data into the interpreted data are
beyond the scope of this tutorial. To learn that, please refer to the relevant topics in the Galaxy training
material. In this tutorial, we start with the interpreted data, which are KO
([KEGG Orthology](https://www.genome.jp/kegg/ko.html)) count data. All the data needed for this tutorial are
available from Zenodo.

> <details-title>Background: What is KO count?</details-title>
>
> KOs are organism-independent identifiers that group together proteins of similar biochemical functions.
> It is a term specific to [KEGG](https://www.genome.jp/kegg/) database. It is a group concept, similar to the concept "pathway", which
> includes a bunch of molecules and their interactions. Take a random line in our dataset, "K01369 7" as an example, the first column represents the KO ID,
> and the second column --- the numeric value is the KO counts. If we understand it by the face value, it is 7 protein molecules that are counted from our dataset as this KO "K01369"; but we usually mingle proteins with genes because we often assume that each protein corresponds to a gene, so it can be understood as 7 genes. Now we are working on the microbial RNAseq data, and the assumption is also used subconsciously.
>
{: .details}

## Understanding our input data

According to the study [May et al.](https://academic.oup.com/bioinformatics/article/32/11/1678/2240171),
dental caries (DC) dataset in this tutorial came from an experiment that comprised of supragingival plaque
samples collected from all dental surfaces of 36 individuals who had either a caries-positive (disease) or
a caries-negative (health) oral profile. Each of the 36 samples was sequenced, pre-processed and transformed
into KO counts. We will use these count data as the starting point to perform the network analysis.

> <comment-title>Dataset details</comment-title>
> The count data of the 36 samples are separated into 36 files, organized into two groups:
> 'CP' (caries-positive) and 'CN' (caries-negative).
{: .comment}


## Importing the data into Galaxy

After knowing what our input data are like, let's get them into Galaxy history:

> <hands-on-title>Obtaining our data</hands-on-title>
>
> 1. Make sure we have an empty Galaxy history. Give it a sensible name.
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. **Upload Disease Dataset**
>    - Open the file upload menu
>    - Click on  **Collection** tab
>    - Click on the **Paste/Fetch data** button
>    - Copy the Zenodo links for the Disease Datasets
>      > <details-title>View list of Zenodo URLs for Dental Caries Dataset (Disease, CP)</details-title>
>      > ```
>      > https://zenodo.org/record/1344105/files/2241_CP_DZ_PairTo_2242.txt
>      > https://zenodo.org/record/1344105/files/2126_CP_MZ_PairTo_2125.txt
>      > https://zenodo.org/record/1344105/files/2991_CP_DZ_PairTo_2992.txt
>      > https://zenodo.org/record/1344105/files/2931_CP_DZ_PairTo_2930.txt
>      > https://zenodo.org/record/1344105/files/2284_CP_DZ_PairTo_2283.txt
>      > https://zenodo.org/record/1344105/files/2125_CP_MZ_PairTo_2126.txt
>      > https://zenodo.org/record/1344105/files/4131_CP_DZ_PairTo_4132.txt
>      > https://zenodo.org/record/1344105/files/2954_CP_DZ_PairTo_2955.txt
>      > https://zenodo.org/record/1344105/files/2170_CP_MZ_PairTo_2169.txt
>      > https://zenodo.org/record/1344105/files/2955_CP_DZ_PairTo_2954.txt
>      > https://zenodo.org/record/1344105/files/2011_CP_DZ_PairTo_2012.txt
>      > https://zenodo.org/record/1344105/files/2012_CP_DZ_PairTo_2011.txt
>      > https://zenodo.org/record/1344105/files/2269_CP_DZ_PairTo_2270.txt
>      > https://zenodo.org/record/1344105/files/3215_CP_MZ_PairTo_3214.txt
>      > https://zenodo.org/record/1344105/files/2354_CP_DZ_PairTo_2355.txt
>      > https://zenodo.org/record/1344105/files/3306_CP_DZ_PairTo_3307.txt
>      > https://zenodo.org/record/1344105/files/2061_CP_DZ_PairTo_2062.txt
>      > https://zenodo.org/record/1344105/files/2355_CP_DZ_PairTo_2354.txt
>      > https://zenodo.org/record/1344105/files/2242_CP_DZ_PairTo_2241.txt
>      > ```
>      {: .details}
>    - Click on **Start** to Upload the files
>    - Click **Build** once upload has completed
>    - Enter **Name**: `CP`
>    - Click **Create list** to make the collection
>
> 3. **Upload control (healthy) datasets**
>    - Repeat the previous steps with the samples from healthy individuals:
>      > <details-title>View list of Zenodo URLs for Dental Caries Dataset (Healthy, CN)</details-title>
>      > ```
>      > https://zenodo.org/record/1344105/files/2310_CN_DZ_PairTo_2309.txt
>      > https://zenodo.org/record/1344105/files/2062_CN_DZ_PairTo_2061.txt
>      > https://zenodo.org/record/1344105/files/2191_CN_MZ_PairTo_2192.txt
>      > https://zenodo.org/record/1344105/files/2052_CN_MZ_PairTo_2051.txt
>      > https://zenodo.org/record/1344105/files/2051_CN_MZ_PairTo_2052.txt
>      > https://zenodo.org/record/1344105/files/2192_CN_MZ_PairTo_2191.txt
>      > https://zenodo.org/record/1344105/files/2234_CN_DZ_PairTo_2233.txt
>      > https://zenodo.org/record/1344105/files/2233_CN_DZ_PairTo_2234.txt
>      > https://zenodo.org/record/1344105/files/2270_CN_DZ_PairTo_2269.txt
>      > https://zenodo.org/record/1344105/files/2225_CN_MZ_PairTo_2226.txt
>      > https://zenodo.org/record/1344105/files/4132_CN_DZ_PairTo_4131.txt
>      > https://zenodo.org/record/1344105/files/2309_CN_DZ_PairTo_2310.txt
>      > https://zenodo.org/record/1344105/files/2992_CN_DZ_PairTo_2991.txt
>      > https://zenodo.org/record/1344105/files/3214_CN_MZ_PairTo_3215.txt
>      > https://zenodo.org/record/1344105/files/2169_CN_MZ_PairTo_2170.txt
>      > https://zenodo.org/record/1344105/files/2930_CN_DZ_PairTo_2931.txt
>      > https://zenodo.org/record/1344105/files/3307_CN_DZ_PairTo_3306.txt
>      > ```
>      {: .details}
>    - Name this collection: `CN`
>
>    > <question-title></question-title>
>    >
>    > 1. How many samples do you have in our disease collection (CP)? How many healthy samples (CN)?
>    > 2. How many columns in each file? What are these columns?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > 1. You should have 19 samples in the disease collection (CP), and 17 in the negative collection (CN).
>    > > 2. There are two columns, one is the KO IDs, the other is the count.
>    > >
>    > {: .solution}
>    {: .question}
>
{: .hands_on}

> <tip-title>Creating a collection from files already in your history</tip-title>
>
> *Dataset collections* enables us to easily run tools on multiple datasets at once, you probably
> have done that in the file upload menu using the `Collection` tab. If not, you can still create
> *dataset collections* manually.
>
> > <hands-on-title>Manually organizing our data into a collection</hands-on-title>
> >
> > If you have all the datasets in the history, but they are not organized into a collection yet,
> > you can follow these steps to create a collection:
> >
> > 1. Click on the **checkmark icon** at top of your history.
> >   ![Checkmark icon in history menu](../../../../shared/images/history_menu_buttons2.png)
> >
> > 2. Select all the files whose name contains `CP`, then click on **n of N selected** and select
> >   **Build Dataset List** from the dropdown menu.
> >
> > 3. In the next dialog window, you need to give a name, here we just set it to `CP`, then click **Create list**.
> >
> > 4. Redo the Step 2, 3 for CN, set the name of the data list as 'CN'.
> {: .hands_on}
{: .tip}



# Differential Expression Analysis (DEA) by DESeq2

## What is differential expression analysis?

> <comment-title>A definition</comment-title>
>
> The definition of differential expression analysis given by
> [EBI](https://www.ebi.ac.uk/training/online/course/functional-genomics-ii-common-technologies-and-data-analysis-methods/differential-gene)
> means taking the normalised read count data and performing statistical analysis to discover quantitative
> changes in expression levels between experimental groups. For example, we use statistical testing to decide
> whether, for a given gene, an observed difference in read counts is significant, that is, whether it is greater
> than what would be expected just due to natural random variation.
>
{: .comment}

In principle, DEA is a causal analysis; but in reality, it is hampered by the complexity of the experimental
situation and measurement. Back to our datasets, CP and CN, they are from two experimental groups. By DEA,
we hope to pinpoint the candidate genes relevant to dental caries first, then we will use Heinz to infer the
related pathways.

## Which tools are available for DEA?

There are a few canned tools commonly used for DEA, like [Limma](https://bioconductor.org/packages/release/bioc/html/limma.html)
and [DESeq2](https://bioconductor.org/packages/release/bioc/html/DESeq2.html). If you are interested, you
may look up the pros and cons of each tool. Here we use DESeq2.


## Perform Differential Expression Analysis (DEA)

After learning about differential expression analysis, let's get some hands-on experience.

> <hands-on-title>DEA via DESeq2</hands-on-title>
>
> - **DESeq2** {% icon tool %} with the following parameters
>   - *"Specify a factor name"*: `dental_caries` (under `1: Factor`)
>   - *"Specify a factor level"*: to `CP` (under `1: Factor level`)
>       - {% icon param-files %} *"Counts file(s)"*: `CP` (collection)
>   - *"Specify a factor level"*: `CN` (under `2: Factor level`)
>       - {% icon param-files %} *"Counts file(s)"*: `CN` (collection)
>   - *"Files have header"*: `No`
>   - *"Visualising the analysis results"*: `No`
>   - Leave all other parameters to the default settings <br><br>
>
{: .hands_on}

It takes a few minutes to finish DESseq2. After the analysis is finished, have a look at the file, it should look like something this:

```
GeneID  Base mean   log2(FC)	        StdErr	            Wald-Stats	        P-value	                P-adj
K15661  55.0733128361562    2.49892393773464	0.508475451930939	4.91454194739384	8.89902710599613e-07	0.00491938218419466
K15666  48.4532561772761    2.22805029428311	0.493391718412049	4.51578372951607	6.30830206230236e-06	0.00820667379798327
K10213  25.1966742274619    -2.45624670858868	0.550895251183889	-4.45864563782342	8.24791475064012e-06	0.00820667379798327
K03732  563.63634258472 -1.41961721984814	0.316992240900184	-4.47839737596338	7.52055094378821e-06	0.00820667379798327
K01792  112.923146882195    -1.26925892659617	0.285732234964578	-4.44212717810268	8.90738834802815e-06	0.00820667379798327
```


# Fit a BUM model (a mixture model)

From a statistical point of view, p-values are uniformly distributed under null hypothesis; in other words,
under alternative hypothesis, the noise component (which holds under null hypothesis) will be adequately
modeled by a uniform distribution. With this knowledge, we can fit these p-values to a mixture model
(BUM model), as the figure below shows.

![p-values are fitted to a mixture model](../../images/transcriptomics_images/bum.jpeg){:width="50%"}

> <comment-title>Why do we need a mixture model?</comment-title>
>
> To avoid making this tutorial sound like a math class, let's focus on the philosophy of using a statistical model.
> In the graph above, we have visualized the p-values; those bins have some shapes; by viewing the figure, it
> is possible for us to cherrypick the data points (KO) with mesh eyes, but it must be tedious and boring, nobody wants to
> spend a few days on doing this. In this situation, computers come into play; however, unlike humans, computers cannot understand the graph but
> mathematical formulas, that's why we need to fix the data into a statistical model (denoted by the red curve and blue line in the graph),
> which computers can understand easily.
>
{: .comment}


Before fitting to BUM model in Galaxy, we need to prepare the input data for the tool
**Fit a BUM model**, that's a file that only contains p-values.

> <hands-on-title>extract p-values from DESeq2 output</hands-on-title>
>
> - **cut** columns from a table {% icon tool %} with the following parameters:
>   - *"Cut columns"*: `c6`
>   - *"Delimited by"*: to `TAB`
>   - *"From"*: to the output of **DESeq2**
>
{: .hands_on}

Now we can **Fit a BUM model**:

> <hands-on-title>fit the BUM model</hands-on-title>
>
> - **Fit a BUM model** {% icon tool %} with the following parameters
>   - *"Input file"*: the output of **cut**
>
{: .hands_on}

# Pinpoint the key pathways with Heinz

After getting the parameters of the BUM model from the last step, we will use Heinz to pinpoint
the optimal subnetwork. Then we could look for the key pathways relevant to the subnetwork.
Before we continue, let's figure out what Heinz is actually doing.

Heinz is an algorithm for searching an optimal subnetwork from a bigger network. You may wonder what
the network is here. Through the previous steps, we have got a list of identities, that is a list
of gene IDs with p-values, which form the nodes  of 'the bigger network', the relations between the
nodes, that is the edges, needs to be obtained from a background network, which represents a pathway
relation databases, such as [Reactome](https://reactome.org/) and [STRING](https://string-db.org/).
In this tutorial, we only use a small sample background network for demonstration purposes. The
background network is represented as edges in a TXT file where each line denotes an edge as follows:

```
ACTR1B	ACVR2B
ZSWIM9	FOXP3
LGALS4	PRKX
NPTX1	CIAO1
```

Upload this edge file (hereafter we call it edge file) into the Galaxy instance.

> <hands-on-title>Upload edge file</hands-on-title>
>
> 1. **Upload the edge file from Zenodo**
>    - Open the upload menu
>    - Choose **Paste/Fetch data** option
>    - Paste the URL into the box:
>      ```
>      https://zenodo.org/record/1344105/files/edge.txt
>      ```
>    - Click **Start**
{: .hands_on}


## Calculate Heinz scores

As the first step, we need to calculate a Heinz score for each node, using the BUM model parameters
we obtained; meanwhile, we also need to specify an FDR value as input.

> <comment-title>What is an FDR value?</comment-title>
>
> FDR is short for false discovery rate, which is a method of conceptualizing the rate of type I errors
> in null hypothesis testing when conducting multiple comparisons, if you are interested, view the detail
> in [Wikipedia](https://en.wikipedia.org/wiki/False_discovery_rate).
>
{: .comment}


For different datasets and problems, we probably need to pick up an FDR value separately. Here we set FDR to 0.11.

Similar to **Fit a BUM model**, we also need to prepare the input data for the tool
**Calculate a Heinz score**.

> <question-title></question-title>
>
> What is the requirement of the input data format for **Calculate a Heinz score**?
>
> > <solution-title></solution-title>
> >
> > In the user interface of the tool "Calculate a Heinz score", we see that "A node file with p-values" is needed.
> > It should contain two columns delimited by tab, one is KO ID; the other, p-value.
> >
> {: .solution}
{: .question}

> <hands-on-title>extract geneID and p-values from DESeq2 output</hands-on-title>
>
> - **cut** columns from a table {% icon tool %} with the following parameters
>   - *"Cut columns"*: `c1,c6`
>   - *"Delimited by"*: `TAB`
>   - *"From"*: the output of **DESeq2**
>
{: .hands_on}

> <hands-on-title>calculate Heinz scores</hands-on-title>
>
> - **Calculate a Heinz score** {% icon tool %} with the following parameters
>   - *"A node file with p-values"*: the output of the previous **cut** step
>   - *"FDR value"*: to 0.11
>   - *"Choose your input type for BUM parameters"*: `The output file of BUM model`
>   - *"Output file of BUM model as input: lambda on the first line and alpha, the second"*: the output of **Fit a BUM model**
{: .hands_on}


> <comment-title>What is the Heinz score?</comment-title>
>
> To figure out this score without reading the formula, we can understand Heinz score in this way. FDR is involved in calculating a p-value threshold
> and any KO whose p-value is below this threshold is regarded as significant, which means the Heinz score is positive (another calculation in the formula). If we pick a higher FDR value, then we will have a higher p-value threshold, and more KOs are probably regarded as significant. In this situation, we probably have many false positive (those regarded as significant are actually not) on the one hand; on the other hand, Heinz will deliver a bigger subnetwork, which might be exhausting to analyze. Therefore, we need to pick up an FDR value properly.
>
{: .comment}


## Run Heinz: pinpoint the optimal subnetwork

After getting Heinz scores, let's run Heinz program to find the optimal subnetwork from the background network which we mentioned earlier.

> <hands-on-title>pinpoint the optimal subnetwork</hands-on-title>
>
> - **Identify optimal scoring subnetwork** {% icon tool %} with the following parameters
>   - *"File containing Heinz scores"*: the output of **Calculate a Heinz score**
>   - *"Edge file"*: the edge file uploaded
>
{: .hands_on}

It usually takes a few minutes to get the result, but mind you, for some tasks, it might take a few hours to get a result in practice.

> <comment-title>The running time of the program</comment-title>
>
> * Graph problem is way more complicated than we thought.
> * It might take a much longer time for some complicated datasets.
> * We can use multiple CPUs to accelerate the computation (for now, this function is not available in Galaxy yet),
>   but, to use that, you can install Heinz directly via [Bioconda](https://anaconda.org/bioconda/heinz) in a Linux environment.
{: .comment}

## Visualize the output: visualize the optimal subnetwork

The result we got from the last step is not very human-readable, is it? It is a little painful to understand the Heinz result directly. Therefore we need to visualize the output by making it into graphs.

> <hands-on-title>visualize the optimal subnetwork</hands-on-title>
>
> - **Visualize** the optimal scoring subnetwork {% icon tool %} with the following parameters
>   - *"Heinz output file"*: the output of **Identify optimal scoring subnetwork**
>
{: .hands_on}

In this tutorial, you probably get a similar graph to the following:

![p-values are fitted to a mixture model](../../images/transcriptomics_images/Heinz_visualisation.png){:width="30%"}

> <question-title></question-title>
>
> According to the figure above, Why are some shapes are round, others square?
>
> > <solution-title></solution-title>
> >
> > Round shape corresponds to positive Heinz score; square shape corresponds to negative Heinz score.
> >
> {: .solution}
{: .question}


In addition to the tool we will use in Galaxy, you may consider using eXamine plugin in Cytoscape for a richer visualization, if we use the original data from the study [May et al.](https://academic.oup.com/bioinformatics/article/32/11/1678/2240171), perform all of these steps and visualize the result by eXamine, we can get a visualization as follows:

![metaModules Result](../../images/transcriptomics_images/metaModules.png){:width="60%"}

If you are interested, you may try to make sense of the result yourself. To answer the question "which pathways are potentially contributing to dental caries?", we need to find the key pathways relevant to the subnetwork. To achieve that, we probably need to combine information from other bioinformatics services and literature.


# Save the history into a workflow

Let's assume that these are the operations we always need for different datasets, to make life easier, we can save all of these operations into a workflow in Galaxy, which you can reuse for different datasets next time.

> <hands-on-title>Extract the Heinz workflow</hands-on-title>
>
> 1. Extract the workflow from your history
>
>    {% snippet faqs/galaxy/workflows_extract_from_history.md %}
>
> 2. Run the workflow on the dataset in this tutorial
>
{: .hands_on}

![Heinz workflow](../../images/transcriptomics_images/heinz-workflow.png)

As a self practice, you ran the newly created workflow with the dataset in this tutorial. Do you feel the convenience of running a workflow directly?

Congrats! You have finished all the tools in Heinz workflow! You have successfully run each tool and understood how it works. In real research, running these tools are only part of the effort, we still need to invest a huge amount of intelligence in making sense of the results and converting them to knowledge, which is fraught with uncertainties and confounders, where perhaps luck will come into play. So good luck!


topic: transcriptomics
tutorial: small_ncrna_clustering
title: Small Non-coding RNA Clustering using BlockClust
difficulty: intermediate
time_estimation: 1H
tools_json: []
requirements_json: []
tags_json: []
content_hash: 1b94e50d804131122df3e0590d260f37
last_modified: 2026-02-26T21:12:18.581341
zenodo_link: https://zenodo.org/record/1491876
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/small_ncrna_clustering/tutorial.html

content:
Small Non-coding RNAs (ncRNAs) play a vital role in many cellular processes such as RNA splicing, translation, gene regulation. The small RNA-seq is a type of RNA-seq in which RNA fragments are size selected to capture only short RNAs. One of the most common applications of the small RNA-seq is discovering novel small ncRNAs. Mapping the small RNA-seq data reveals interesting patterns that represent the traces of the small RNA processing.

For example, consider the miRNA biogenesis. The primary miRNA transcripts are processed by Drosha-complexes and results in hairpin precursor miRNAs. Then after they transported to the cytoplasm, Dicer slices off the hairpin. One of the RNA strands bound by Argonaute proteins regulates the target mRNA while the other strand is degraded.

The following figure (bottom part of the figure is taken from {% cite Pasquinelli2012 %}) represents one of the small RNA processing patterns. The vertical block bars represent a mapped reads on reference genome. The height of the bars represents the number of reads mapped at that location. Reads in each bubble represent a *read profile*. In this case, they both are from miRNAs. From the small RNA-seq, we often see the two processed miRNA strands after mapping. The miRNA strand which targets the mRNA is expressed and we see more reads compared to the degraded strand. The gap between those two piles of reads represents the missing hairpin.

![read profiles](../../images/transcriptomics_images/blockclust_profiles.png "Patterns of processing in read profiles")

In this tutorial, we will learn how to use **BlockClust** to cluster similar processing patterns together.

> <agenda-title></agenda-title>
>
> In this tutorial, we will cover:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Preprocessing of the data
The data is we use is from human cell line MCF-7 sequenced in single-end on Illumina Genome Analyzer II. Reads are 36nt long and should be sufficiently long enough for this type of data. We start with a BAM file as an input for this tutorial. This BAM file is a result of mapping the reads on human reference genome build hg19 using **segemehl**. If you want to use your own raw sequencing data, please clip the adapters and map to the reference genome.

In the first step, we convert the BAM file into BED file. This is not a plain file conversion. Hence we cannot use any kind of BAM to BED conversion tools. We use BlockClust tool in the pre-processing mode for this purpose. The resulting BED file contains tags (a tag is a unique read sequence in a deep-sequencing library) and their normalized expression (in column 5), i.e. the ratio of the read count per tag to the number of mappings on the reference genome.

{: .hands_on}
## Get data

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this tutorial
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
> 2. Import the files from [Zenodo](https://zenodo.org/record/2172221/files/GSM769512.bam)
>
>    ```
>    https://zenodo.org/record/2172221/files/GSM769512.bam
>    ```
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
{: .hands_on}

> <question-title></question-title>
>
> Why is it mandatory to clip the adapters from the small RNA-seq data?
>
> > <solution-title></solution-title>
> >
> > Generally, the processed RNA fragments from the small RNAs are about 18-30nt long. If the sequenced read length is longer than the fragment (which is usually the case), the sequencer reads into the 3' adapter.
> >
> {: .solution}
>
{: .question}


## Sort BAM file
Before continue to BAM to BED conversion we need to sort the alignments in the input BAM file by their positions.
> <hands-on-title>Sort BAM</hands-on-title>
> 1. **Samtools sort** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"BAM File"*: `GSM769512.bam`
>
{: .hands_on}

## BAM to BED of tags
Now it is time to do the actual conversion.
> <hands-on-title><b>BlockClust</b> preprocessing</hands-on-title>
> 1. **BlockClust** {% icon tool %} with the following parameters:
>    - *"Select mode of operation"*: `Pre-processing `
>    - {% icon param-file %} *"BAM file containing alignments"*: output of **Samtools sort** {% icon tool %}
>
{: .hands_on}

# Grouping of the adjacent reads into read profiles

Now we group the adjacent reads into so-called blocks and blockgroups using blockbuster tool. In general, each blockgroup should represent a single ncRNA read profile.

![blocks of a blockgroup](../../images/transcriptomics_images/blockclust_blocks.png "Representation of blocks and blockgroups of a read profile")

> <details-title>More details about the theory</details-title>
>
> The idea is to perform peak detection on the signal obtained by counting the number of reads per nucleotide. This signal, spanning adjacent loci, is then modeled with a mixture of Gaussians. An iterative greedy procedure is then used to collect reads that belong to the same block, starting from the largest Gaussian component, and removing them in successive iterations. The tool further assembles a sequence of adjacent blocks into a blockgroup if the blocks are either overlapping or are at a distance smaller than a user-defined threshold. A more detailed explanation is at [the blockbuster website](http://hoffmann.bioinf.uni-leipzig.de/LIFE/blockbuster.html)
>
{: .details}


## Sort the BED file of tags

In order to run the blockbuster successfully the input BED file need to be sorted by chromosome, strand, start position and then end positions.

> <hands-on-title>Sort the BED file</hands-on-title>
>
> 1. **Sort** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"Sort Query"*: output of **BlockClust** {% icon tool %}
>    - In *"Column selections"*:
>        - *"on column"*: `Column: 1`
>        - *"Flavor"*: `Alphabetical sort`
>    - Click on *"Insert Column selections"*:
>    - In *"Column selections"*:
>        - *"on column"*: `Column: 6`
>        - *"Flavor"*: `Alphabetical sort`
>    - Click on *"Insert Column selections"*:
>    - In *"Column selections"*:
>        - *"on column"*: `Column: 2`
>        - *"Flavor"*: `Fast numeric sort`
>    - Click on *"Insert Column selections"*:
>    - In *"Column selections"*:
>        - *"on column"*: `Column: 3`
>        - *"Flavor"*: `Fast numeric sort`
>    - *"Ignore case"*: `Yes`
>
{: .hands_on}

## Group reads into blocks and blockgroups using **blockbuster**

> <hands-on-title>blockbuster</hands-on-title>
>
> 1. **blockbuster** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"BED file containing read expressions"*: output of **Sort** {% icon tool %}
>    - *"Type of output"*: `reads (blockbuster format)`
>
{: .hands_on}


# Clustering with **BlockClust**
Here we use **BlockClust** in clustering mode. All you need here is the output of the **blockbuster**.

Apart from clustering, **BlockClust** has built-in class specific discriminative models for C/D box snoRNA, H/ACA box snoRNA, miRNA, rRNA, snRNA, tRNA and Y_RNA. So it can also be used to predict if a read profile might belong to one of the known ncRNA class.
> <hands-on-title>clustering</hands-on-title>
>
> 1. **BlockClust** {% icon tool %} with the following parameters:
>    - *"Select mode of operation"*: `Clustering and classification`
>        - {% icon param-file %} *"Input blockgroups file"*: output of **blockbuster** {% icon tool %}
>        - *"Select reference genome"*: `Human (hg19)`
>        - *"Would you like to perform classification?"*: `Yes`
>        - *"Mode of classification"*: `Model based`
>
{: .hands_on}

The tool produces the following four output files.

The `BlockClust: BED of predicted clusters` file is the result of Markov cluster algorithm. Each entry in this file represents a blockgroup. The 4th column contains is in the form of *annotation:blockgroup_id:cluster_id*. The *cluster_id* represents which cluster the blockgroup belongs to.

The `BlockClust: Model based predictions BED` file is the result of classification. Each entry in this file represents a blockgroup. The 4th column contains the annotation of the ncRNA which it overlaps. For the blockgroups which are not overlapped with any known ncRNAs, the prefix `predicted_` is added indicating that it is predicted by the **BlockClust** classification models.

The `BlockClust: Hierarchical clustering plot` file shows a dendrogram construced based on average linkage clustering.

The `BlockClust: Pairwise similarities` file contains the pairwise similarities of all input blockgroups.

Next, we will visualize the read profiles (from the BAM file) and the predictions (BED from **BlockClust**) together.

> <hands-on-title>visualization</hands-on-title>
>
> 1. Install [IGV](https://software.broadinstitute.org/software/igv/download) (if not already installed)
> 2. Start IGV locally
> 3. Expand the {% icon param-file %} `GSM769512.bam` file
> 4. Click on the `local` in `display with IGV` to load the reads into the IGV browser
> 5. Expand the {% icon param-file %} `BlockClust: Model based predictions BED` file
> 6. Click on the `local` in `display with IGV` to load the reads into the IGV browser
> 7. Go to the location `chr4:90653059-90653141` in IGV.
>
{: .hands_on}

> <question-title></question-title>
>
> 1. Do you see any already annotated transcript in that location?
> 2. What does the read profile resemble?
> 3. What did **BlockClust** predict?
>
> > <solution-title></solution-title>
> >
> > 1. There is no annotated gene from RefSeq annotation on the same strand.
> > 2. It resembles the miRNA profiles mentioned in the introduction section. One of the read piles looks like mature miRNA and the other like miRNA*.
> > 3. Predicted as a miRNA.
> >
> {: .solution}
>
{: .question}

> <comment-title></comment-title>
>
> In order for this step to work, you will need to have either IGV or [Java web start](https://www.java.com/en/download/faq/java_webstart.xml)
> installed on your machine. However, the questions in this section can also be answered by inspecting the IGV screenshots below.
>
> Check the [IGV documentation](https://software.broadinstitute.org/software/igv/AlignmentData) for more information.
>
{: .comment}



# Conclusion


In this tutorial, we learned how to use **BlockClust** to cluster real small RNA sequencing read profiles based on their similarity. We also learned that the **BlockClust** can also be used to classify the read profiles based on pre-built classification models.


topic: transcriptomics
tutorial: srna
title: Differential abundance testing of small RNAs
difficulty: intermediate
time_estimation: 3h
tools_json: []
requirements_json: []
tags_json: []
content_hash: 0178e80983559c5f60aa06f78c40f749
last_modified: 2026-02-26T21:12:18.582254
zenodo_link: https://zenodo.org/record/826906
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/srna/tutorial.html

content:
Small, noncoding RNA (sRNA) molecules, typically 18-40nt in length, are key features of post-transcriptional regulatory mechanisms governing gene expression. Through interactions with protein cofactors, these tiny sRNAs typically function by perfectly or imperfectly basepairing with substrate RNA molecules, and then eliciting downstream effects such as translation inhibition or RNA degradation. Different subclasses of sRNAs - *e.g.* microRNAs (miRNAs), Piwi-interaction RNAs (piRNAs), and endogenous short interferring RNAs (siRNAs) - exhibit unique characteristics, and their relative abundances in biological contexts can indicate whether they are active or not. In this tutorial, we will examine expression of the piRNA subclass of sRNAs and their targets in *Drosophila melanogaster*.

The data used in this tutorial are from polyphosphatase-treated sRNA sequencing (sRNA-seq) experiments in *Drosophila*. The goal of this study was to determine how siRNA expression changes in flies treated with RNA interference (RNAi) to knock down Symplekin, which is a component of the core cleaveage completx. To that end, in addition to sRNA-seq, mRNA-seq experiments were performed to determine whether targets of differentially expressed siRNAs were also differentially expressed. The original published study can be found [here](https://www.ncbi.nlm.nih.gov/pubmed/28415970). Because of the long processing time for the large original files - which contained 7-22 million reads each - we have downsampled the original input data to include only a subset of usable reads.

# Analysis strategy

In this exercise we will identify what small RNAs are present in *Drosophila* Dmel-2 tissue culture cells treated with either RNAi against  core cleavage complex component Symplekin or blank (control) RNAi (published data available in GEO at [GSE82128](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE82128)). In this study, biological triplicate sRNA- and mRNA-seq libraries were sequenced for both RNAi conditions. After removing contaminant ribosomal RNA (rRNA) and miRNA reads, we will identify and quantify endogenous siRNAs from sequenced reads and test for differential abundance. We will follow a popular small RNA analysis pipeline developed for piRNAs by the Phillip Zamore Lab and the ZLab (Zhiping Weng) at UMass Med School called [PiPipes](https://github.com/bowhan/piPipes). Although PiPipes was developed for analysis of piRNAs, many of the basical principles can be applied to other classes of small RNAs.

It is of note that this tutorial uses datasets that have been de-multiplexed so that the input data files are a single FASTQ formatted file for each sample. Because sRNAs are typically much smaller than fragments generated for RNA-seq or other types of deep sequencing experiments, single-end sequencing strategies are almost always used to sequence sRNAs. This tutorial uses the *Collections* feature of Galaxy to orgainze each set of replicates into a single group, making tool form submission easier and ensuring reproducibility.

> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

## Data upload and organization

Due to the large size of the original sRNA-seq datasets, we have downsampled them to only inlcude a subset of reads. These datasets are available at [`Zenodo`](https://doi.org/10.5281/zenodo.826906) where you can find the FASTQ files corresponding to replicate sRNA-seq experiments and additional annotation files for the *Drosophila melanogaster* genome version dm3.

> <hands-on-title>Data upload and organization</hands-on-title>
>
> 1. Create a new history and name it something meaningful (*e.g.* sRNA-seq tutorial)
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. Import the 3 `Blank_RNAi_sRNA-seq` and 3 `Symp_RNAi_sRNA-seq` FASTQ files from [Zenodo](https://zenodo.org/record/1324070) or from the data library (ask your instructor)
>
>    ```
>    https://zenodo.org/record/826906/files/Blank_RNAi_sRNA-seq_rep1_downsampled.fastqsanger.gz
>    https://zenodo.org/record/826906/files/Blank_RNAi_sRNA-seq_rep2_downsampled.fastqsanger.gz
>    https://zenodo.org/record/826906/files/Blank_RNAi_sRNA-seq_rep3_downsampled.fastqsanger.gz
>    https://zenodo.org/record/826906/files/Symp_RNAi_sRNA-seq_rep1_downsampled.fastqsanger.gz
>    https://zenodo.org/record/826906/files/Symp_RNAi_sRNA-seq_rep2_downsampled.fastqsanger.gz
>    https://zenodo.org/record/826906/files/Symp_RNAi_sRNA-seq_rep3_downsampled.fastqsanger.gz
>    ```
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    {% snippet faqs/galaxy/datasets_import_from_data_library.md %}
>
>    Set the datatype of the read (.fastqsanger) files to **fastq**
>    As default, Galaxy takes the link as name, so rename them.
>
> 2. Build a dataset list for both sets (`Blank` and `Symp`) of replicate FASTQ files
>
>    {% snippet faqs/galaxy/collections_build_list.md %}
>
>    ![History section with all the loaded datasets](../../images/sRNA/Fig3_dataset_lists_made.png)
>
> 3. Import the remaining files from [Zenodo](https://zenodo.org/record/1324070) or from the data library (ask your instructor)
>
>    ```
>    https://zenodo.org/record/826906/files/dm3_transcriptome_Tx2Gene_downsampled.tab.gz
>    https://zenodo.org/record/826906/files/dm3_transcriptome_sequences_downsampled.fa.gz
>    https://zenodo.org/record/826906/files/dm3_miRNA_hairpin_sequences.fa.gz
>    https://zenodo.org/record/826906/files/dm3_rRNA_sequences.fa.gz
>    ```
>
>    - Set the datatype of the annotation file to **tab** and assign the Genome as **dm3**
>    - Set the datatype of the reference files to **fasta** and assign the Genome as **dm3**
>
{: .hands_on}

## Read quality checking

Read quality scores (phred scores) in FASTQ-formatted data can be encoded by one of a few different encoding schemes. Most Galaxy tools assume that input FASTQ files are using the Sanger/Illumina 1.9 encoding scheme. If the input FASTQ files are using an alternate encoding scheme, then some tools will not interpret the quality score encodings correctly. It is good practice to confirm the quality encoding scheme of your data and then convert to Sanger/Illumina 1.9, if necessary. We can check the quality encoding scheme using the [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) tool (further described in the [NGS-QC tutorial]({{site.baseurl}}/topics/sequence-analysis)).


> <hands-on-title>Quality checking</hands-on-title>
>
> 1. Run **FastQC** {% icon tool %} on the `Blank` collection
>    - {% icon param-collection %} *"Short read data from your current history"*: `Blank` collection
>
>    {% snippet faqs/galaxy/tools_select_collection.md %}
>
> 2. Run **FastQC** {% icon tool %} for the *Symplekin* RNAi dataset collection
> 3. Inspect the **FastQC** {% icon tool %} reports
>
>    > <question-title></question-title>
>    >
>    > 1. What quality score encoding scheme is being used for each sample?
>    > 2. What is the read length for each sample?
>    > 3. What does the base/read quality look like for each sample?
>    >
>    >    ![The output of FastQC as a boxplot](../../images/sRNA/Fig5a_fastqc_result_stats_boxplot.png)
>    >
>    > 4. Are there any adaptors present in these reads? Which one(s)?
>    >
>    >    ![The output of FastQC stats adapted](../../images/sRNA/Fig5b_fastqc_result_stats_adapter.png)
>    >
>    > > <solution-title></solution-title>
>    > > 1. All samples use the Illumina 1.9 quality encoding scheme, so we do **not** need to convert.
>    > > 2. All samples have a read length of 50 nt.
>    > > 3. The base quality across the entire length of the reads is good (phred score > 28 for the most part).
>    > > 4. Yes, the "Illumina Universal Adapter" is present.
>    > {: .solution }
>    {: .question}
{: .hands_on}

> <hands-on-title>Formatting </hands-on-title>
>
> If your data are not in **Sanger / Illumina 1.9 format**:
> 1. **FASTQ Groomer** {% icon tool %} on each collection
>    - {% icon param-collection %} *"File to groom"*: input collection
>    - *"Input FASTQ quality scores type"*: `Illumina 1.3-1.7`
> 2. Check that the format is **fastqsanger** instead of **fastq**
>
> If your data are already in **Sanger / Illumina 1.9 format**:
> 1. Change the datatype to `fastqsanger`
>
>    {% snippet faqs/galaxy/datasets_change_datatype.md datatype="fastqsanger" %}
>
{: .hands_on}

Go back to the **FastQC** {% icon tool %} and scroll down to the "Adapter Content" section. You can see that Illumina Universal Adapters are present in **>80%** of the reads. The next step is to remove these artificial adaptors because they are not part of the biological sRNAs. If a different adapter is present, you can update the **Adapter sequence to be trimmed off** in the **Trim Galore!** {% icon tool %} step described below.

## Adaptor trimming

sRNA-seq library preparation involves adding an artificial adaptor sequence to both the 5' and 3' ends of the small RNAs. While the 5' adaptor anchors reads to the sequencing surface and thus are not sequenced, the 3' adaptor is typically sequenced immediately following the sRNA sequence. In the example datasets here, the 3' adaptor sequence is identified as the Illumina Universal Adapter, and needs to be removed from each read before aligning to a reference. We will be using the Galaxy tool **Trim Galore!** {% icon tool %} which implements the [`cutadapt`](https://cutadapt.readthedocs.io/en/stable/) tool for adapter trimming.

> <hands-on-title>Adaptor trimming</hands-on-title>
>
> 1. **Trim Galore!** {% icon tool %} on each collection of FASTQ read files to remove Illumina adapters from the 3' ends of reads with the following parameters:
>    - *"Is this library paired- or single-end"*: `Single-end`
>       - {% icon param-collection %} *"Reads in FASTQ format?"*: `Blank` collection
>       - *"Adapter sequence to be trimmed"*: `Illumina universal`
>    - *"Trim Galore! advanced settings"*: `Full parameter list`
>       - *"Trim low-quality ends from reads in addition to adapter removal"*: `0`
>       - *"Overlap with adapter sequence required to trim a sequence"*: `6`
>       - *"Discard reads that became shorter than length N"*: `12`
>       - *"Generate a report file"*: `Yes`
>
> 2. **Trim Galore!** {% icon tool %}: Repeat for the *Symplekin* RNAi dataset collection
>
{: .hands_on}

We don't want to trim for quality because the adapter-trimmed sequences represent a full small RNA molecule, and we want to maintain the integrity of the entire molecule. We increase the minimum read length required to keep a read because small RNAs can potentially be shorter than 20 nt (the default value). We can check out the generated report file for any sample and see the command for the tool, a summary of the total reads processed and number of reads with an adapter identified, and histogram data of the length of adaptor trimmed. We also see that a very small percentage of low-quality bases have been trimmed

> <hands-on-title>Adaptor trimming check</hands-on-title>
>
> 1. **FastQC** {% icon tool %} on each collection of trimmed FASTQ read files to assess whether adapters were successfully removed.
> 2. Inspect the **FastQC** {% icon tool %} reports
>
>    > <question-title></question-title>
>    >
>    > 1. What is the read length?
>    >
>    >   ![FastQC output after trimming](../../images/sRNA/Fig8a_fastqc_post_trimming_result.png)
>    >
>    > 2. Are there any adaptors present in these reads? Which one(s)?
>    >
>    >   ![FastQC output after trimming](../../images/sRNA/Fig8b_fastqc_post_trimming_lengths.png)
>    > > <solution-title></solution-title>
>    > > 1. The read lengths range from 12 to 50 nt after trimming.
>    > > 2. No, Illumina Universal Adaptors are no longer present. No other adapters are present.
>    > {: .solution }
>    {: .question}
{: .hands_on}

An interesting thing to note from our **FastQC** {% icon tool %} results is the *Sequence Length Distribution* results. While many RNA-seq experiments have normal distribution of read lengths, an unusual spike at 22nt is observed in our data. This spike represents the large set of endogenous siRNAs that occur in the cell line used in this study, and is actually confirmation that our dataset captures the biological molecule we are interested in.

Now that we have converted to *fastqsanger* format and trimmed our reads of the Illumina Universal Adaptors, we will align our trimmed reads to reference *Drosophila* rRNA and miRNA sequences (dm3) to remove these artifacts. Interestingly, *Drosophila* have a short 2S rRNA sequence that is 30nt long and typically co-migrates with sRNA populations during gel electrophoresis. rRNAs make up a very large proportion of all non-coding RNAs, and thus need to be removed. Oftentimes, experimental approaches can be utilized to deplete or avoid capture of rRNAs, but these methods are not always 100% efficient. We also want to remove any miRNA sequences, as these are not relevant to our analysis. After removing rRNA and miRNA reads, we will analyze the remaining reads, which may be siRNA or piRNA sequences.

## Hierarchical read alignment to remove rRNA/miRNA reads

To first identify rRNA-originating reads (which we are not interested in in this case), we will align the reads to a reference set of rRNA sequences using [**HISAT2** {% icon tool %}](https://ccb.jhu.edu/software/hisat2/index.shtml), an accurate and fast tool for aligning reads to a reference.

> <hands-on-title>Hierarchical alignment to rRNA and miRNA reference sequences</hands-on-title>
>
> 1. **HISAT2** {% icon tool %} on each collection of trimmed reads to align to reference rRNA sequences with the following parameters
>    - *"Source for the reference genome to align against"*: `Use a genome from history`
>       - {% icon param-file %} *"Select the reference genome"*: `Dmel_rRNA_sequences.fa`
>    - *"Is this a single or paired library?"*: `Single-end`
>       - {% icon param-collection %} *"FASTA/Q file"*: output of **Trim Galore!** {% icon tool %} for `Blank` collection
>       - *"Specify strand-specific information"*: `Forward (F)`
>
> 2. **HISAT2** {% icon tool %}: Repeat for the *Symplekin* RNAi dataset collection
{: .hands_on}

We now need to extract the *unaligned* reads from the output BAM file for aligning to reference miRNA sequences. We can do this by using the `Filter SAM or BAM, output SAM or BAM` tool to obtain reads with a bit flag = 4 (meaning the read is unaligned) and then converting the filtered BAM file to FASTQ format with the `Convert from BAM to FastQ` tool.

> <hands-on-title>Hierarchical alignment to rRNA and miRNA reference sequences (2)</hands-on-title>
> 1. **Filter SAM or BAM, output SAM or BAM** {% icon tool %} on collection of HISAT2 output BAM files with the following parameters
>    - {% icon param-collection %} *"SAM or BAM file to filter"*: output of **HISAT2** {% icon tool %} for `Blank` collection
>    - *"Filter on bitwise flag"*: `Yes`
>       - *"Only output alignments with all of these flag bits set"*: `The read in unmapped`
>
> 2. **Filter SAM or BAM, output SAM or BAM** {% icon tool %}: Repeat for the *Symplekin* RNAi dataset collection
> 3. **Convert from BAM to FastQ** {% icon tool %} on each collection of filtered HISAT2 output BAM files with the following parameters:
>    - {% icon param-collection %} *"Convert the following BAM file to FASTQ"*: output of **Filter SAM or BAM** {% icon tool %} for `Blank` collection
>
> 4. **Convert from BAM to FastQ** {% icon tool %}: Repeat for the *Symplekin* RNAi dataset collection
{: .hands_on}

Next we will align the non-rRNA reads to a known set of miRNA hairpin sequences to identify miRNA reads.

> <hands-on-title>Hierarchical alignment to rRNA and miRNA reference sequences (3)</hands-on-title>
> 1. **HISAT2** {% icon tool %} on each collection of filtered HISAT2 output FASTQ files to align non-rRNA reads to reference miRNA hairpin sequences using the following parameters:
>    - *"Source for the reference genome to align against"*: `Use a genome from history`
>       - {% icon param-file %} *"Select the reference genome"*: `Dmel_miRNA_sequences.fa`
>    - *"Is this a single or paired library?"*: `Single-end`
>       - {% icon param-collection %} *"FASTA/Q file"*: output of **Convert from BAM to FastQ** {% icon tool %} for `Blank` collection
>       - *"Specify strand-specific information"*: `Forward (F)`
> 2. **HISAT2** {% icon tool %}: Repeat for the *Symplekin* RNAi dataset collection
{: .hands_on}

For this tutorial we are not interested in miRNA reads, so we need to extract *unaligned* reads from the output BAM files. To do this, repeat the **Filter SAM or BAM, output SAM or BAM** {% icon tool %} steps for each dataset collection. Finally, rename the converted FASTQ files something meaningful (*e.g.* "non-r/miRNA control RNAi sRNA-seq").

In some instances, miRNA-aligned reads are the desired output for downstream analyses, for example, if we are investigating how loss of key miRNA pathway components affect levels of pre-miRNA and mature miRNAs. In this case, the BAM output of HISAT2 can directly be used in subsequent tools as it contains the subset of reads aligned to miRNA sequences.

## Small RNA subclass distinction

In *Drosophila*, non-miRNA small RNAs are typically divided into two major groups: endogenous siRNAs which are 20-22nt long and piRNAs which are 23-29nt long. We want to analyze these sRNA subclasses independently, so next we are going to filter the non-r/miRNA reads based on length using the **Manipulate FASTQ** {% icon tool %} tool.

> <hands-on-title>Extract subclasses</hands-on-title>
>
> 1. **Manipulate FASTQ** {% icon tool %} on each collection of non-r/miRNA reads to identify siRNAs (20-22nt) using the following parameters.
>    - {% icon param-collection %} *"FASTQ File"*: output of last **HISAT** {% icon tool %} for `Blank` collection
>    - Click on *"Insert Match Reads"*
>       - In "1: Match Reads"
>         - *"Match Reads by"*: `Sequence Content`
>           - *"Match by"*: `^.{12,19}$|^.{23,50}$`
>    - Click on *"Manipulate Reads"*
>       - In "1: Manipulate Reads"
>         - *"Manipulate Reads on"*: `Miscellaneous actions`
>           - *"Miscellaneous Manipulation Type"*: `Remove Read`
> 2. **Manipulate FASTQ** {% icon tool %}: Repeat for the *Symplekin* RNAi dataset collection
> 3. Rename each resulting dataset collection something meaningful (*i.e.* "blank RNAi - siRNA reads (20-22nt)")
{: .hands_on}

The regular expression in the **Match by** parameter tells the tool to identify sequences that are length 12-19 or 23-50 (inclusive), and the **Miscellaneous Manipulation Type** parameter tells the tool to remove these sequences. What remains are sequences of length 20-22nt. We will now repeat these steps to identify sequences in the size-range of piRNAs (23-29nt).

> <hands-on-title>Extract subclasses</hands-on-title>
> 1. **Manipulate FASTQ** {% icon tool %}: Run `Manipulate FASTQ` on each collection of non-r/miRNA reads to identify sequences in the size-range of piRNAs (23-29nt)
>    - {% icon param-collection %} *"FASTQ File"*: output of last **HISAT** {% icon tool %} for `Blank` collection
>    - Click on *"Insert Match Reads"*
>       - In "1: Match Reads"
>         - *"Match Reads by"*: `Sequence Content`
>           - *"Match by"*: `^.{12,22}$|^.{30,50}$`
>    - Click on *"Manipulate Reads"*
>       - In "1: Manipulate Reads"
>         - *"Manipulate Reads on"*: `Miscellaneous actions`
>           - *"Miscellaneous Manipulation Type"*: `Remove Read`
> 2. **Manipulate FASTQ** {% icon tool %}: Repeat for the *Symplekin* RNAi dataset collection
> 3. Rename each resulting dataset collection something meaningful (*i.e.* "blank RNAi - piRNA reads (23-29nt)")
{: .hands_on}

> <hands-on-title>Check the read length</hands-on-title>
> 1. **FastQC** {% icon tool %}: Run `FastQC` on each collection of siRNA and piRNA read files to confirm the correct read lengths.
{: .hands_on}

![FastQC result on both collections](../../images/sRNA/Fig13_FastQC_piRNA_siRNA_result_Blank_rep1.png)

We see in the above image (for Blank RNAi, replicate 3) that we have ~32k reads that are 20-22nt long in our Reads_20-22_nt_length_siRNAs file and ~16k reads that are 23-29nt long in our Reads_23-29_nt_length_piRNAs file, as expected. Given that we had ~268k trimmed reads in the Blank RNAi replicate 3 file, siRNAs represent ~12.1% of the reads and piRNAs represent ~6.2% of the reads in this experiment. There is no distinct peak in the piRNA range (you can find the example of the real piRNA profile in Figure 1 from [Colin D. Malone et al, 2009](http://dx.doi.org/10.1016/j.cell.2009.03.040).

The next step in our analysis pipeline is to identify which RNA features - e.g. protein-coding mRNAs, transposable elements - the siRNAs and piRNAs align to. Most fly piRNAs originate from and thus align to transposable elements (TEs) but some also originate from genome piRNA clusters or protein-coding genes. siRNAs are thought to inhibit TE mobility and potentially target mRNAs for degradation via an RNA-interference (RNAi) mechanism. Ultimately, we want to know whether an RNA feature (TE, piRNA cluster, mRNA, etc.) has significantly different numbers of siRNAs or piRNAs targeting it. To determine this, we will use **Salmon** {% icon tool %} to simultaneously align and quantify siRNA reads against known target sequences to estimate siRNA abundance per target. For the remainder of the tutorial we will be focusing on siRNAs, but similar approaches can be done for piRNAs, miRNAs, or any other subclass of small, non-coding RNAs.

## siRNA abundance estimation

We want to identify which siRNAs are differentially abundance between the blank and *Symplekin* RNAi conditions. To do this we will implement a counting approach using **Salmon** {% icon tool %} to quantify siRNAs per RNA feature. Specifically, we will analyzing mRNA and TE elements by counting siRNAs against a FASTA file of transcript sequences, not the reference genome. This approach is especially useful in this case because we are interested in TEs, which occur at many copies (100s - 1000s) in the genome, and thus will result in multiple alignments if we align to the genome with a tool like **HISAT2** {% icon tool %}. Further, we will be counting abundance of siRNAs that align *sense* or *antisense* to an RNA feature independently, as opposite sense alignments are correlated with unique downstream silencing effects. Then, we will provide this information to **DESeq2** {% icon tool %} to generate normalized counts and significance testing for differential abundance of siRNAs per feature.

> <hands-on-title>siRNA abundance estimation</hands-on-title>
>
> 1. **Salmon** {% icon tool %} on each collection of siRNA reads (20-22nt) to quantify the abundance of *antisense* siRNAs at relevant targets
>    - *"Select a reference transcriptome from your history or use a built-in index?"*: `Use one from the history`
>      - {% icon param-file %} *"Select the reference transcriptome"*: `the reference mRNA and TE fasta file`
>      - *"The size should be odd number"*: `19`
>    - *"Is this library mate-paired?"*: `Single-end`
>      - {% icon param-collection %} *"FASTQ/FASTA file"*: collection with the Blank RNAi siRNA (20-22nt) reads
>      - *"Specify the strandedness of the reads"*: `read 1 (or single-end read) comes from the reverse strand (SR)`
>    - In *"Additional Options"*
>      - *"Incompatible Prior"*: `0`
>
> 1. **Salmon** {% icon tool %}: Repeat for the *Symplekin* RNAi siRNAs (20-22nt) reads dataset collection
> 1. **Salmon** {% icon tool %}: Repeat on each collection of siRNA reads (20-22nt) to quantify the abundance of *sense* siRNAs at relevant targets by changing the following parameters:
>    - *"Specify the strandedness of the reads"*: `read 1 (or single-end read) comes from the forward strand (SF)`
{: .hands_on}

The output of **Salmon** {% icon tool %} includes a table of RNA features, estimated counts, transcripts per million, and feature length. We will be using the TPM quantification column as input to **DESeq2** {% icon tool %} in the next section.

## siRNA differential abundance testing

[**DESeq2** {% icon tool %}](https://bioconductor.org/packages/release/bioc/html/DESeq2.html) is a great tool for differential expression analysis, but we also employ it here for estimation of abundance of reads targeting each of our RNA features. As input, **DESeq2** {% icon tool %} can take *t*ranscripts *p*er *m*illion (TPM) counts produced by **Salmon** {% icon tool %} for each feature. TPMs are estimates of the relative abundance of a given transcript in units, and analogously can be used here to quantify siRNAs that align either sense or antisense to transcripts.

> <hands-on-title>siRNA differential abundance testing</hands-on-title>
>
> 1. **DESeq2** {% icon tool %} to test for differential abundance of *antisense* siRNAs at mRNA and TE features using the following parameters:
>    - In *"Factor"*:
>       - In "1: Factor"
>           - *"Specify a factor name"*: `RNAi`
>           - In *"Factor level"*:
>               - In *"1: Factor level"*:
>                   - *"Specify a factor level"*: `Symplekin`
>                   - {% icon param-collection %} *"Counts file(s)"*: the Symplekin RNAi siRNA counts from reverse strand (SR) collection
>               - In *"2: Factor level"*:
>                   - *"Specify a factor level"*: `RNAi`
>                   - {% icon param-collection %} *"Counts file(s)"*: the Symplekin RNAi siRNA counts from reverse strand (SR)
>    - *"Choice of Input data"*: `TPM values (e.g. from sailfish and salmon)`
>       - *"Program used to generate TPMs"*: `Salmon`
>       - *"Gene mapping format"*: `Transcript-ID and Gene-ID mapping file`
>         - {% icon param-file %} *"Tabular file with Transcript - Gene mapping"*: `reference tx2g (transcript to gene) file` (available through zenodo link)
>    - *"Output normalized counts table"*: `Yes`
>
> 1. **DESeq2** {% icon tool %} for the *sense* siRNAs at mRNA and TE features:
>    - In *"Factor"*:
>       - In "1: Factor"
>           - *"Specify a factor name"*: `RNAi`
>           - In *"Factor level"*:
>               - In *"1: Factor level"*:
>                   - *"Specify a factor level"*: `Symplekin`
>                   - {% icon param-collection %} *"Counts file(s)"*: the Symplekin RNAi siRNA counts from forward strand (SF)
>               - In *"2: Factor level"*:
>                   - *"Specify a factor level"*: `RNAi`
>                   - {% icon param-collection %} *"Counts file(s)"*: the Symplekin RNAi siRNA counts from forward strand (SF)
>    - *"Choice of Input data"*: `TPM values (e.g. from sailfish and salmon)`
>       - *"Program used to generate TPMs"*: `Salmon`
>       - *"Gene mapping format"*: `Transcript-ID and Gene-ID mapping file`
>         - {% icon param-file %} *"Tabular file with Transcript - Gene mapping"*: `reference tx2g (transcript to gene) file` (available through zenodo link)
>    - *"Output normalized counts table"*: `Yes`
>
> 1. **Filter** {% icon tool %} to extract features with a significantly different *antisense* siRNA abundance (adjusted *p*-value less than 0.05).
>    - {% icon param-file %} *"Filter"*: Select the `DESeq2` result file from testing *antisense* (SR) siRNA abundances
>    - *"With following condition"*: `c7<0.05`
>
> 1. **Filter** {% icon tool %} for the *sense* siRNAs at mRNA and TE features:
>    - {% icon param-file %} *"Filter"*: Select the `DESeq2` result file from testing *sense* (SF) siRNA abundances
>    - *"With following condition"*: `c7<0.05`
{: .hands_on}

> <question-title></question-title>
>
> How many features have a significant difference in *antisense* and *sense* siRNA abundance in the *Symplekin* RNAi condition?
>
> > <solution-title></solution-title>
> > There are 87 *antisense* and 15 *sense* features that have significanlty different siRNA abundances.
> {: .solution }
{: .question}

For more information about `DESeq2` and its outputs, have a look at [`DESeq2` documentation](https://www.bioconductor.org/packages/release/bioc/manuals/DESeq2/man/DESeq2.pdf).

## Visualization

Coming soon!

# Conclusion


Analysis of small RNAs is a complicated and intricate process due to the diversity in characteristics, functionality, and nuances of small RNA subclasses. The goal of this tutorial is to introduce you to a common small RNA workflow that specifically identifies changes in endogenous siRNA abundances that target protein-coding mRNAs and transposable elements. The steps presented here can be rearranged and modified based on small RNA features of specific systems and the needs of the user.

## Small RNA analysis (general) pipeline

![sRNA tutorial workflow](../../images/sRNA/schematic_for_sRNAseq_tutorial.png)


topic: transcriptomics
tutorial: rna-seq-viz-with-volcanoplot
title: Visualization of RNA-Seq results with Volcano Plot
difficulty: introductory
time_estimation: 30m
tools_json: []
requirements_json: ["type: internal", "rna-seq-counts-to-genes"]
tags_json: []
content_hash: 18aa7d185476f5b7bc9653f0ee69a341
last_modified: 2026-02-26T21:12:18.575904
zenodo_link: https://zenodo.org/record/2529117
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/rna-seq-viz-with-volcanoplot/tutorial.html

content:
![Volcano plot highlighting significant genes](../../images/rna-seq-viz-with-volcanoplot/volcanoplot.png){: style="float:right;width:60%" }
Volcano plots are commonly used to display the results of RNA-seq or other omics experiments. A volcano plot is a type of scatterplot that shows statistical significance (P value) versus magnitude of change (fold change). It enables quick visual identification of genes with large fold changes that are also statistically significant. These may be the most biologically significant genes. In a volcano plot, the most upregulated genes are towards the right, the most downregulated genes are towards the left, and the most statistically significant genes are towards the top.

To generate a volcano plot of RNA-seq results, we need a file of differentially expressed results which is provided for you here. To generate this file yourself, see the [RNA-seq counts to genes]({% link topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.md %}) tutorial. The file used here was generated from limma-voom but you could use a file from any RNA-seq differential expression tool, such as edgeR or DESeq2, as long as it has the required columns (see below).

The data for this tutorial comes from {% cite Fu2015 %}. This study examined the expression profiles of basal and luminal cells in the mammary gland of virgin, pregnant and lactating mice. Here, we will visualize the results of the luminal pregnant vs lactating comparison.


> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Preparing the inputs

We will use two files for this analysis:

 * **Differentially expressed results file** (genes in rows, and 4 required columns: raw P values, adjusted P values (FDR), log fold change and gene labels)
 * **Genes of interest file** (list of genes to be plotted in volcano)

## Import data

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this RNA-seq exercise e.g. `Volcano plot`
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. Import the result table of differential gene expression analysis, as well as a list of genes that will be annotated in the volcano plot later.
>
>    To import the file, there are two options:
>    - Option 1: From a shared data library if available (ask your instructor)
>    - Option 2: From [Zenodo](https://zenodo.org/record/2529117)
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    {% snippet faqs/galaxy/datasets_import_from_data_library.md %}
>
>    - You can paste the links below into the **Paste/Fetch** box:
>
>      ```
>      https://zenodo.org/record/2529117/files/limma-voom_luminalpregnant-luminallactate
>      https://zenodo.org/record/2529117/files/volcano_genes
>      ```
>
>    - Select *"Type (set all)"*: `tabular`
>
>    After the files import, check that the datatype is `tabular`.
>    If the datatype is not `tabular`, please change the file type to `tabular`.
>
>    {% snippet faqs/galaxy/datasets_change_datatype.md datatype="tabular" %}
>
>
{: .hands_on}

Click on the {% icon galaxy-eye %} (eye) icon and take a look at the `limma-voom_luminalpregnant-luminallactate` file. It should look like below, with 8 columns.

![luminal file](../../images/rna-seq-viz-with-volcanoplot/DE_results.png)

## Create volcano plot highlighting significant genes

First, we will create a volcano plot highlighting all significant genes. We will call genes significant, if they have FDR < 0.01 and a log fold change of 0.58 (equivalent to a fold-change of 1.5). These were the values used in the original paper for this dataset.

> <hands-on-title>Create a Volcano plot</hands-on-title>
>
> 1. {% tool [Volcano Plot](toolshed.g2.bx.psu.edu/repos/iuc/volcanoplot/volcanoplot/0.0.7) %} to create a volcano plot:
>    - *"Specify an input file"*: limma-voom file
>    - *"FDR (adjusted P value)"*: `Column 8`
>    - *"P value (raw)"*: `Column 7`
>    - *"Log Fold Change"*: `Column 4`
>    - *"Labels"*: `Column 2`
>    - *"Significance threshold"*: `0.01`
>    - *"LogFC threshold to colour"*: `0.58`
>    - *"Points to label"*: `None`
{: .hands_on}

![Volcano plot highlighting significant genes](../../images/rna-seq-viz-with-volcanoplot/volcanoplot.png){: width="60%"}

In the plot above the genes are coloured if they pass the thresholds for FDR and Log Fold Change. The red dots are upregulated genes and the blue dots are downregulated genes. You can see in this plot that there are many (hundreds) of significant genes in this dataset.

> <question-title></question-title>
>
> Why does the y axis use a negative P value scale?
>
>    > <solution-title></solution-title>
>    >
>    > The negative log of the P values are used for the y axis so that the smallest P values (most significant) are at the top of the plot.
>    >
>    {: .solution}
{: .question}

## Create volcano plot labelling top significant genes

You can also choose to show the labels (e.g. Gene Symbols) for the significant genes with the volcano plot tool. You can select to label all significant or just the top genes. The top genes are those that pass the FDR and logFC thresholds that have the smallest P values. As there are hundreds of significant genes here, too many to sensibly label, let's label the top 10 significant genes.

> <hands-on-title>Create a Volcano plot labelling top 10 significant genes</hands-on-title>
> 1. Use the **Run Job Again** {% icon galaxy-refresh %} button in the History to re-run {% tool [Volcano Plot](toolshed.g2.bx.psu.edu/repos/iuc/volcanoplot/volcanoplot/0.0.7) %} with the same parameters as before except:
>    - *"Points to label"*: `Significant`
>        - *"Only label top most significant"*: `10`
{: .hands_on}


![Volcano plot labelling top significant genes](../../images/rna-seq-viz-with-volcanoplot/volcanoplot_top10.png){: width="60%"}

As in the previous plot, genes are coloured if they pass the thresholds for FDR and Log Fold Change, (red for upregulated and blue for downregulated) and the top genes by P value are labelled. Note that in the plot above we can now easily see what the top genes are by P value and also which of them have bigger fold changes.

> <question-title></question-title>
>
> Which gene is the most statistically significant with large fold change?
>
>    > <solution-title></solution-title>
>    >
>    > Csn1s2b, as it is the gene nearest the top of the plot and it is also far to the left. This gene is a calcium-sensitive casein that is important in milk production. As this dataset compares lactating and pregnant mice, it makes sense that it is a gene that is very differentially expressed.
>    >
>    {: .solution}
{: .question}

## Create volcano plot labelling genes of interest

We can also label one or more genes of interest in a volcano plot. This enables us to visualize where these genes are in terms of significance and in comparison to the other genes. In the original paper using this dataset, there is a heatmap of 31 genes in Figure 6b (have a look at this [visualization tutorial]({% link topics/transcriptomics/tutorials/rna-seq-viz-with-heatmap2/tutorial.md %}) if you would like to see how to generate the heatmap). These genes are a set of 30 cytokines/growth factor identified as differentially expressed, and the authors' main gene of interest, Mcl1. These genes are provided in the `volcano_genes` file and shown below. We will label these genes in the volcano plot. We'll add boxes around the labels to highlight the gene names.

![Volcano genes](../../images/rna-seq-viz-with-volcanoplot/volcano_genes.png){: height="25%"}

> <hands-on-title>Create a Volcano plot labelling genes of interest</hands-on-title>
> 1. Use the **Run Job Again** {% icon galaxy-refresh %} button in the History to re-run {% tool [Volcano Plot](toolshed.g2.bx.psu.edu/repos/iuc/volcanoplot/volcanoplot/0.0.7) %} with the same parameters as before except:
>    - *"Points to label"*: `Input from file`
>        - *"File of labels"*: `volcano_genes`
>    - In *"Plot Options"*:
>     -   *"Label Boxes"*: `Yes`
{: .hands_on}

![Volcano plot labelling genes of interest](../../images/rna-seq-viz-with-volcanoplot/volcanoplot_custom_genes.png){: width="60%"}

> <question-title></question-title>
>
> 1. How many of the genes of interest are significant?
> 2. Which gene of interest is the most statistically significant?
>
>    > <solution-title></solution-title>
>    >
>    > 1. 29/31 are significant, the genes that are not in the grey area. 
>    > 2. The Egf gene is the most statistically significant as it is nearest the top of the plot.
>    >
>    {: .solution}
{: .question}


As in the previous plots, genes are coloured if they pass the thresholds for FDR and Log Fold Change. Here, all the genes of interest are significant (red or blue) except for two genes, Mcl1 and Gmfg. Gmfg, has an FDR just very slightly outside the significance threshold we used of 0.01 (0.0105). Mcl1 is the authors' gene of interest and they showed that while it's expression did increase at the protein level, it did not increase at the transcription level, as we can see here, suggesting it is regulated post-transcriptionally. 

> <tip-title>R code</tip-title>
>
> You can get the R code used to generate the plot under *Output Options* in the tool form. You can edit this code in R if you want to customise the plot. See the [Visualization of RNA-Seq results with Volcano Plot in R]({% link topics/transcriptomics/tutorials/rna-seq-viz-with-volcanoplot-r/tutorial.md %}) tutorial for how to do this.
>
{: .tip}

# Conclusion


In this tutorial we have seen how a volcano plot can be generated from RNA-seq data and used to quickly visualize significant genes.


topic: transcriptomics
tutorial: de-novo
title: De novo transcriptome reconstruction with RNA-Seq
difficulty: intermediate
time_estimation: 6h
tools_json: []
requirements_json: []
tags_json: []
content_hash: 0b75b7b0ac00c21b4d7744f8d0f4506f
last_modified: 2026-02-26T21:12:18.546250
zenodo_link: https://zenodo.org/records/583140
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/de-novo/tutorial.html

content:
The data provided here are part of a Galaxy tutorial that analyzes RNA-seq data from a study published by *Wu et al.* in 2014 [DOI:10.1101/gr.164830.113](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4248312/). The goal of this study was to investigate "the dynamics of occupancy and the role in gene regulation of the transcription factor Tal1, a critical regulator of hematopoiesis, at multiple stages of hematopoietic differentiation." To this end, RNA-seq libraries were constructed from multiple mouse cell types including G1E - a GATA-null immortalized cell line derived from targeted disruption of GATA-1 in mouse embryonic stem cells - and megakaryocytes. This RNA-seq data was used to determine differential gene expression between G1E and megakaryocytes and later correlated with Tal1 occupancy. This dataset (GEO Accession: GSE51338) consists of biological replicate, paired-end, poly(A) selected RNA-seq libraries. Because of the long processing time for the large original files, we have downsampled the original raw data files to include only reads that align to chromosome 19 and a subset of interesting genomic loci identified by Wu *et al*.

# Analysis strategy

The goal of this exercise is to identify what transcripts are present in the G1E and megakaryocyte cellular states and which transcripts are differentially expressed between the two states. We will use a *de novo* transcript reconstruction strategy to infer transcript structures from the mapped reads in the absence of the actual annotated transcript structures. This will allow us to identify novel transcripts and novel isoforms of known transcripts, as well as identify differentially expressed transcripts.

> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

## Data upload

Due to the large size of this dataset, we have downsampled it to only include reads mapping to chromosome 19 and certain loci with relevance to hematopoeisis. This data is available at [`Zenodo`](https://zenodo.org/record/583140), where you can find the forward and reverse reads corresponding to replicate RNA-seq libraries from G1E and megakaryocyte cells and an annotation file of RefSeq transcripts we will use to generate our transcriptome database.

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this RNA-seq exercise
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. Open the data upload manager (Get Data -> Upload file)
> 3. Copy and paste the links for the reads and annotation file
> 4. Select **Paste/Fetch Data**
> 5. Paste the link(s) into the text field
> 6. Change the datatype of the read files to **fastqsanger**
> 7. Change the datatype of the annotation file to **gtf** and assign the Genome as **mm10**
> 8. Press **Start**
> 9. Rename the files in your history to retain just the necessary information (*e.g.* "G1E R1 forward reads")
>
>
> 10. Import the files from [Zenodo]({{ page.zenodo_link }})
>
>     ```
>     https://zenodo.org/record/583140/files/G1E_rep1_forward_read_%28SRR549355_1%29
>     https://zenodo.org/record/583140/files/G1E_rep1_reverse_read_%28SRR549355_2%29
>     https://zenodo.org/record/583140/files/G1E_rep2_forward_read_%28SRR549356_1%29
>     https://zenodo.org/record/583140/files/G1E_rep2_reverse_read_%28SRR549356_2%29
>     https://zenodo.org/record/583140/files/Megakaryocyte_rep1_forward_read_%28SRR549357_1%29
>     https://zenodo.org/record/583140/files/Megakaryocyte_rep1_reverse_read_%28SRR549357_2%29
>     https://zenodo.org/record/583140/files/Megakaryocyte_rep2_forward_read_%28SRR549358_1%29
>     https://zenodo.org/record/583140/files/Megakaryocyte_rep2_reverse_read_%28SRR549358_2%29
>     https://zenodo.org/record/583140/files/RefSeq_reference_GTF_%28DSv2%29
>     ```
>
>     You will need to fetch the link to the annotation file yourself ;)
>
>     {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
{: .hands_on}

## Quality control

For quality control, we use similar tools as described in [NGS-QC tutorial]({{site.baseurl}}/topics/sequence-analysis/): [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) and [Trimmomatic](http://www.usadellab.org/cms/?page=trimmomatic).

> <hands-on-title>Quality control</hands-on-title>
>
> 1. **FastQC** {% icon tool %}: Run `FastQC` on the forward and reverse read files to assess the quality of the reads.
>
>    > <question-title></question-title>
>    >
>    > 1. What is the read length?
>    > 2. Is there anything interesting about the quality of the base calls based on the position in the reads?
>    >
>    > > <solution-title></solution-title>
>    > > 1. The read length is 99 bp
>    > > 2. The quality of base calls declines throughout a sequencing run.
>    > {: .solution }
>    {: .question}
>
> 2. **Trimmomatic** {% icon tool %}: Trim off the low quality bases from the ends of the reads to increase mapping efficiency. Run `Trimmomatic` on each pair of forward and reverse reads with the following settings:
>
>    - *"Single-end or paired-end reads?"*: `Paired-end (two separate input files)`
>       - {% icon param-file %} *"Input FASTQ file (R1/first of pair)"*: `G1E_rep1 forward read`
>       - {% icon param-file %} *"Input FASTQ file (R2/second of pair)"*: `G1E_rep1 reverse read`
>    - *"Perform initial ILLUMINACLIP step?"*: `No`
>
> 3. **FastQC** {% icon tool %}: Re-run `FastQC` on trimmed reads and inspect the differences.
>
>    > <question-title></question-title>
>    >
>    > 1. What is the read length?
>    > 2. Is there anything interesting about the quality of the base calls based on the position in the reads?
>    >
>    > > <solution-title></solution-title>
>    > > 1. The read lengths range from 1 to 99 bp after trimming
>    > > 2. The average quality of base calls does not drop off as sharply at the 3' ends of reads.
>    > {: .solution }
>    {: .question}
> ![Before and after trimming comparison](../../images/transcriptomics_images/BeforeAndAfterTrimming.png)
>
> 4. **Trimmomatic** {% icon tool %}: Run `Trimmomatic` on the remaining forward/reverse read pairs with the same parameters.
>
{: .hands_on}

Now that we have trimmed our reads and are fortunate that there is a reference genome assembly for mouse, we will align our trimmed reads to the genome.

> <comment-title></comment-title>
>
> Instead of running a single tool multiple times on all your data, would you rather run a single tool on multiple datasets at once? Check out the [dataset collections](https://galaxyproject.org/tutorials/collections/) feature of Galaxy!
{: .comment}

# Mapping

To make sense of the reads, their positions within mouse genome must be determined. This process is known as aligning or 'mapping' the reads to the reference genome.

> <comment-title></comment-title>
>
> Do you want to learn more about the principles behind mapping? Follow our [training]({{site.baseurl}}/topics/sequence-analysis/)
{: .comment}

In the case of a eukaryotic transcriptome, most reads originate from processed mRNAs lacking introns. Therefore, they cannot be simply mapped back to the genome as we normally do for reads derived from DNA sequences. Instead, the reads must be separated into two categories:

- Reads contained within mature exons - these align perfectly to the reference genome
- Reads that span splice junctions in the mature mRNA - these align with gaps to the reference genome

Spliced mappers have been developed to efficiently map transcript-derived reads against genomes. [`HISAT`](https://ccb.jhu.edu/software/hisat2/index.shtml) is an accurate and fast tool for mapping spliced reads to a genome. Another popular spliced aligner is [`TopHat`](https://ccb.jhu.edu/software/tophat/index.shtml), but we will be using `HISAT` in this tutorial.

> <comment-title></comment-title>
> As it is sometimes quite difficult to determine which settings correspond to those of other programs, the following table might be helpful to identify the library type:
>
> Library type | **Infer Experiment** | **TopHat** | **HISAT** | **htseq-count** | **featureCounts**
> --- | --- | --- | --- | --- | ---
> PE | 1++,1--,2+-,2-+ | FR Second Strand | FR | yes | 1
> PE | 1+-,1-+,2++,2-- | FR First Strand | RF | reverse | 2
> SE | ++,-- | FR Second Strand | F | yes | 1
> SE | +-,-+ | FR First Strand | R | reverse | 2
> SE,PE | undecided | FR Unstranded | default | no | 0
>
{: .comment}

> <hands-on-title>Spliced mapping</hands-on-title>
>
> 1. **HISAT2** {% icon tool %}: Run `HISAT2` on one forward/reverse read pair and modify the following settings:
>    - *"Source for the reference genome"*: `Use a built-in genome`
>       - {% icon param-file %} *"Select a reference genome"*: `Mouse (Mus Musculus): mm10`
>    - *"Single-end or paired-end reads?"*: `Paired-end`
>       - {% icon param-file %} *"FASTA/Q file #1"*: Trimmomatic on G1E_rep1 forward read (R1 paired)
>       - {% icon param-file %} *"FASTA/Q file #2"*: Trimmomatic on G1E_rep1 reverse read (R2 paired)
>       - *"Specify strand information"*: `Forward(FR)`
>    - *"Advanced options"*
>       - *"Spliced alignment options"*
>           - *"Penalty for non-canonical splice sites"*: '3'
>           - *"Penalty function for long introns with canonical splice sites"*: 'Constant [f(x) = B]''
>           - *"Constant term (B)"*: '0.0'
>           - *"Penalty function for long introns with non-canonical splice sites"*: 'Constant [f(x) = B]''
>           - *"Transcriptome assembly reporting"*: 'Report alignments tailored for transcript assemblers including StringTie'
>
> 2. **HISAT2** {% icon tool %}: Run `HISAT2` on the remaining forward/reverse read pairs with the same parameters.
>
{: .hands_on}

# De novo transcript reconstruction
Now that we have mapped our reads to the mouse genome with `HISAT`, we want to determine transcript structures that are represented by the aligned reads. This is called *de novo* transcriptome reconstruction. This unbiased approach permits the comprehensive identification of all transcripts present in a sample, including annotated genes, novel isoforms of annotated genes, and novel genes. While common gene/transcript databases are quite large, they are not comprehensive, and the *de novo* transcriptome reconstruction approach ensures complete transcriptome(s) identification from the experimental samples. The leading tool for transcript reconstruction is `Stringtie`. Here, we will use `Stringtie` to predict transcript structures based on the reads aligned by `HISAT`.

> <hands-on-title>Transcriptome reconstruction</hands-on-title>
>
> 1. **Stringtie** {% icon tool %}: Run `Stringtie` on the `HISAT2` alignments using the default parameters.
>    - Use batch mode to run all four samples from one tool form.
>    - {% icon param-file %} *"Specify strand information"*: `Forward (FR)`
>
{: .hands_on}

# Transcriptome assembly

We just generated four transcriptomes with `Stringtie` representing each of the four RNA-seq libraries we are analyzing. Since these were generated in the absence of a reference transcriptome, and we ultimately would like to know what transcript structure corresponds to which annotated transcript (if any), we have to make a **transcriptome database**. We will use the tool `Stringtie - Merge` to combine redundant transcript structures across the four samples and the RefSeq reference. Once we have merged our transcript structures, we will use `GFFcompare` to annotate the transcripts of our newly created transcriptome so we know the relationship of each transcript to the RefSeq reference.

> <hands-on-title>Transcriptome assembly</hands-on-title>
>
> 1. **Stringtie-merge** {% icon tool %}: Run `Stringtie-merge` on the `Stringtie` assembled transcripts along with the RefSeq annotation file we imported earlier.
>    - {% icon param-file %} *"Transcripts"*: `all four `Stringtie` assemblies`
>    - {% icon param-file %} *"Reference annotation to include in the merging"*: `RefSeq_reference_GTF`
>
> 2. **GFFCompare** {% icon tool %}: Run `GFFCompare` on the `Stringtie-merge` generated transcriptome along with the RefSeq annotation file.
>    - {% icon param-file %} *"GTF inputs for comparison"*: `output of Stringtie-merge`
>    - *"Use Reference Annotation"*: `Yes`
>       - *"Choose the source for the reference annotation"*: `History`
>           - {% icon param-file %} *"Reference Annotation"*: `RefSeq_reference_GTF`
>    - *"Use Sequence Data"*: `Yes`
>       - *"Choose the source for the reference list"*: `Locally cached`
>           - *"Using reference genome"*: 'Mouse (Mus Musculus): mm10'
>
{: .hands_on}

> <comment-title>Note: Transcript categorization used by `GFFcompare`</comment-title>
>
> |**Class code** | **Transcript category**|
> |:---:|:---|
> |= | Annotated in reference|
> |j | Novel isoform of reference|
> |u | Intergenic|
> |x | Anti-sense|
> |r | Repetitive|
> |c | Contained in exon of reference|
> |s | Anti-sense spliced intronic|
> |e | Single exon transfrag overlapping a reference exon and at least 10 bp of a reference intron, indicating a possible pre-mRNA fragment.|
> |i | A transfrag falling entirely within a reference intron|
> |o | Generic exonic overlap with a reference transcript|
> |p | Possible polymerase run-on fragment (within 2Kbases of a reference transcript)|
{: .comment}


# Analysis of the differential gene expression

We just generated a transriptome database that represents the transcripts present in the G1E and megakaryocytes samples. This database provides the location of our transcripts with non-redundant identifiers, as well as information regarding the origin of the transcript.

We now want to identify which transcripts are differentially expressed between the G1E and megakaryocyte cellular states. To do this we will implement a counting approach using `FeatureCounts` to count reads per transcript. Then we will provide this information to `DESeq2` to generate normalized transcript counts (abundance estimates) and significance testing for differential expression.

## Count the number of reads per transcript

To compare the abundance of transcripts between different cellular states, the first essential step is to quantify the number of reads per transcript. [`FeatureCounts`](http://bioinf.wehi.edu.au/featureCounts/ ) is one of the most popular tools for counting reads in genomic features. In our case, we'll be using `FeatureCounts` to count reads aligning in exons of our `GFFCompare` generated transcriptome database.

The recommended mode is "union", which counts overlaps even if a read only shares parts of its sequence with a genomic feature and disregards reads that overlap more than one feature.

> <hands-on-title>Counting the number of reads per transcript</hands-on-title>
>
> 1. **FeatureCounts** {% icon tool %}: Run `FeatureCounts` on the aligned reads (`HISAT2` output) using the `GFFCompare` transcriptome database as the annotation file.
>
>    - {% icon param-file %} *"Alignment file"*: `four HISAT2 aligned read files`
>    - *"Specify strand information"*: `Stranded (Forward)`
>    - {% icon param-file %} *"Gene annotation file"*: `in your history`
>       - *"Gene annotation file"*: `the annotated transcripts GTF file output by GFFCompare`
>    - *"Options for paired-end reads"*
>       - *"Count fragments instead of reads"*: `Enabled; fragments (or templates) wil be counted instead of reads`
>    - *"Advanced options"*
>       - *"GFF gene identifier"*: `transcript_id`
>
{: .hands_on}

## Perform differential gene expression testing

Transcript expression is estimated from read counts, and attempts are made to correct for variability in measurements using replicates. This is absolutely essential to obtaining accurate results. We recommend having at least two biological replicates.

[`DESeq2`](https://bioconductor.org/packages/release/bioc/html/DESeq2.html) is a great tool for differential gene expression analysis. It accepts read counts produced by `FeatureCounts` and applies size factor normalization:

- Computation for each gene of the geometric mean of read counts across all samples
- Division of every gene count by the geometric mean
- Use of the median of these ratios as sample's size factor for normalization

> <hands-on-title></hands-on-title>
>
> 1. **DESeq2** {% icon tool %}: Run `DESeq2` with the following parameters:
>    - *"1: Factor"*
>       - *"1: Factor level"*: `G1E`
>          - {% icon param-file %} *"Counts file(s)"*: `featureCount files corresponding to the two G1E replicates`
>       - *"2: Factor level"*: `Mega`
>          - {% icon param-file %} *"Counts file(s)"*: `featureCount files corresponding to the two Mega replicates`
>
>       > <comment-title></comment-title>
>       >
>       > You can select several files by holding down the CTRL (or COMMAND) key and clicking on the desired files
>       {: .comment}
>    - *"Visualising the analysis results"*: Yes
>    - *"Output normalized counts table"*: Yes
>
{: .hands_on}

The first output of `DESeq2` is a tabular file. The columns are:

1.	Gene identifiers
2.	Mean normalized counts, averaged over all samples from both conditions
3.	Logarithm (base 2) of the fold change (the values correspond to up- or downregulation relative to the condition listed as Factor level 1)
4.	Standard error estimate for the log2 fold change estimate
5.	[Wald](http://data.princeton.edu/wws509/notes/c2s3.html) statistic
6.	*p*-value for the statistical significance of this change
7.	*p*-value adjusted for multiple testing with the Benjamini-Hochberg procedure which controls false discovery rate ([FDR](http://www.biostathandbook.com/multiplecomparisons.html))


> <hands-on-title></hands-on-title>
>
>1. **Filter** {% icon tool %}: Run `Filter` to extract genes with a significant change in gene expression (adjusted *p*-value less than 0.05) between treated and untreated samples
>
>    > <question-title></question-title>
>    >
>    > How many transcripts have a significant change in expression between these conditions?
>    >
>    > > <solution-title></solution-title>
>    > > To filter, use "c7<0.05". And we get 249 transcripts with a significant change in gene expression between the G1E and megakaryocyte cellular states.
>    > {: .solution }
>    {: .question}
>
> 2. **Filter** {% icon tool %}: Determine how many transcripts are up or down regulated in the G1E state.
>
>    > <comment-title></comment-title>
>    > Rename your datasets for the downstream analyses
>    {: .comment}
>
>    > <question-title></question-title>
>    >
>    > Are there more upregulated or downregulated genes in the treated samples?
>    >
>    > > <solution-title></solution-title>
>    > > To obtain the up-regulated genes in the G1E state, we filter the previously generated file (with the significant change in transcript expression) with the expression "c3>0" (the log2 fold changes must be greater than 0). We obtain 102  genes (40.9% of the genes with a significant change in gene expression). For the down-regulated genes in the G1E state, we did the inverse and we find 149 transcripts (59% of the genes with a significant change in transcript expression).
>    > {: .solution }
>    {: .question}
{: .hands_on}

In addition to the list of genes, `DESeq2` outputs a graphical summary of the results, useful to evaluate the quality of the experiment:

1. Histogram of *p*-values for all tests

    ![DESeq2 histogram]({% link topics/transcriptomics/images/transcriptomics_images/Deseq2_histogram3.png %})

2. [MA plot](https://en.wikipedia.org/wiki/MA_plot): global view of the relationship between the expression change of conditions (log ratios, M), the average expression strength of the genes (average mean, A), and the ability of the algorithm to detect differential gene expression. The genes that passed the significance threshold (adjusted p-value < 0.1) are colored in red.

    ![MA plot]({% link topics/transcriptomics/images/transcriptomics_images/Deseq2_MAplot3.png %})

3. Principal Component Analysis ([PCA](https://en.wikipedia.org/wiki/Principal_component_analysis)) and the first two axes

    ![Principal component analysis output]({% link topics/transcriptomics/images/transcriptomics_images/Deseq2_PCA3.png %})

    Each replicate is plotted as an individual data point. This type of plot is useful for visualizing the overall effect of experimental covariates and batch effects.

4. Heatmap of sample-to-sample distance matrix: overview over similarities and dissimilarities between samples

    ![Heatmap of sample-to-sample distance matrix]({% link topics/transcriptomics/images/transcriptomics_images/Deseq2_heatmap3.png %})

5. Dispersion estimates: gene-wise estimates (black), the fitted values (red), and the final maximum a posteriori estimates used in testing (blue)

    ![Dispersion estimates]({% link topics/transcriptomics/images/transcriptomics_images/Deseq2_dispersion3.png %})

    This dispersion plot is typical, with the final estimates shrunk from the gene-wise estimates towards the fitted estimates. Some gene-wise estimates are flagged as outliers and not shrunk towards the fitted value. The amount of shrinkage can be more or less than seen here, depending on the sample size, the number of coefficients, the row mean and the variability of the gene-wise estimates.


For more information about `DESeq2` and its outputs, you can have a look at [`DESeq2` documentation](https://www.bioconductor.org/packages/release/bioc/manuals/DESeq2/man/DESeq2.pdf).

# Visualization
Now that we have a list of transcript expression levels and their differential expression levels, it is time to visually inspect our transcript structures and the reads they were predicted from. It is a good practice to visually inspect (and present) loci with transcripts of interest. Fortunately, there is a built-in genome browser in Galaxy, **Trackster**, that make this task simple (and even fun!).

In this last section, we will convert our aligned read data from BAM format to bigWig format to simplify observing where our stranded RNA-seq data aligned to. We'll then initiate a session on Trackster, load it with our data, and visually inspect our interesting loci.

> <hands-on-title>Converting aligned read files to bigWig format</hands-on-title>
>
> 1. **bamCoverage** {% icon tool %}: Run `bamCoverage` on all four aligned read files (`HISAT2` output) with the following parameters:
>    - *"Bin size in bases"*: '1'
>    - *"Effective genome size"*: 'mm9 (2150570000)''
>    - *"Advanced options"*
>       - *"Only include reads originating from fragments from the forward or reverse strand"*: 'forward'
>
> 2. **Rename** {% icon tool %}: Rename the outputs to reflect the origin of the reads and that they represent the reads mapping to the PLUS strand.
>
> 3. **bamCoverage** {% icon tool %}: Repeat Step 1 except changing the following parameter:
>    - *"Only include reads originating from fragments from the forward or reverse strand"*: 'reverse'
>
> 4. **Rename** {% icon tool %}: Rename the outputs to reflect the origin of the reads and that they represent the reads mapping to the MINUS strand.
{: .hands_on}

> <hands-on-title>Trackster based visualization</hands-on-title>
>
> 1. **Viz** {% icon tool %}: On the center console at the top of the Galaxy interface, choose " Visualization" -> "New track browser"
>    - Name your visualization someting descriptive under "Browser name:"
>    - Choose "Mouse Dec. 2011 (GRCm38/mm10) (mm10)" as the "Reference genome build (dbkey)
>    - Click "Create" to initiate your Trackster session
> ![Trackster opening window](../../images/transcriptomics_images/Trackster_opening_window.png)
>
> 2. **Viz** {% icon tool %}: Click "Add datasets to visualization"
>    - Select the "RefSeq GTF mm10" file
>    - Select the output files from `Stringtie`
>    - Select the output file from `GFFCompare`
>    - Select the output files from `bamCoverage`
>
> 3. {% icon tool %}: Using the grey labels on the left side of each track, drag and arrange the track order to your preference.
>
> 4. {% icon tool %}: Hover over the grey label on the left side of the "RefSeq GTF mm10" track and click the "Edit settings" icon.
>    - Adjust the block color to blue (#0000ff) and antisense strand color to red (#ff0000)
>
> 5. {% icon tool %}: Repeat the previous step on the output files from `StringTie` and `GFFCompare`.
>
> 6. {% icon tool %}: Hover over the grey label on the left side of the "G1E R1 plus" track and click the "Edit settings" icon.
>    - Adjust the color to blue (#0000ff)
>
> 7. {% icon tool %}: Repeat the previous step on the other three bigWig files representing the plus strand.
>
> 8. {% icon tool %}: Hover over the grey label on the left side of the "G1E R1 minus" track and click the "Edit settings" icon.
>    - Adjust the color to red (#ff0000)
>
> 9. {% icon tool %}: Repeat the previous step on the other three bigWig files representing the minus strand.
>
> 10. {% icon tool %}: Adjust the track height of the bigWig files to be consistent for each set of plus strand and minus strand tracks.
> ![Adjusting the track height](../../images/transcriptomics_images/Hoxb13_locus_screenshot.png)
> 11. {% icon tool %}: Direct Trackster to the coordinates: chr11:96191452-96206029, what do you see?
>
>    > <question-title></question-title>
>    > what do you see?
>    >
>    > > <solution-title></solution-title>
>    > > 1. There are two clusters of transcripts that are exclusively expressed in the G1E background
>    > > 2. The left-most transcript is the Hoxb13 transcript
>    > > 3. The center cluster of transcripts are not present in the RefSeq annotation and are determined by `GFFCompare` to be "u" and "x"
>    > {: .solution }
>    {: .question}
>
{: .hands_on}

# Conclusion


In this tutorial, we have analyzed RNA sequencing data to extract useful information, such as which genes are expressed in the G1E and megakaryocyte cellular states and which of these genes are differentially expressed between the two cellular states. In addition, we identified unannotated genes that are expressed in a cell-state dependent manner and at a locus with relevance to differentiation and development. To identify these transcripts, we analyzed RNA sequence datasets using a de novo transcriptome reconstruction RNA-seq data analysis approach. This approach can be summed up with the following scheme:

![RNAseq de novo tutorial workflow](../../images/transcriptomics_images/schematic_for_RNAseq_de_novo_tutorial.png)


topic: transcriptomics
tutorial: mirna-target-finder
title: Whole transcriptome analysis of Arabidopsis thaliana
difficulty: intermediate
time_estimation: 2H
tools_json: []
requirements_json: []
tags_json: []
content_hash: 11fd35af2495dfbb4aac8cbdae42a25f
last_modified: 2026-02-26T21:12:18.559082
zenodo_link: https://zenodo.org/record/4710649
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/mirna-target-finder/tutorial.html

content:
As sessile organisms, the survival of plants under adverse environmental conditions depends, to a large extent, on their ability to perceive stress stimuli and respond appropriately to counteract the potentially damaging effects. Coordination of phytohormones and reactive oxygen species are considered a key element for enhancing stress resistance, allowing fine-tuning of gene expression in response to environmental changes ({% cite PlanasRiverola2019 %}, {% cite Ivashuta2011 %}). These molecules constitute complex signalling networks, endowing with the ability to respond to a variable natural environment.

Brassinosteroids (BRs) are a group of plant steroid hormones essential for plant growth and development, as well as for controlling abiotic and biotic stress. Structurally, BRs are polyhydroxylated sterol derivatives with close similarity to animal hormones (Figure 1). This group of phytohormones is comprised of around 60 different compounds, of which brassinolide (BL), 24-epibrassinolide (EBR), and 28-homobrassinolide (HBR) are considered the most bioactive.

![fig1:Esteroid hormones]({% link topics/transcriptomics/images/transcriptomics_images/brassinosteroids.png %} "Structure of various plant and animal steroid hormones.")

Several recent studies suggest that the BR-mediated gene regulatory networks have the potential to reshape the future of agriculture, not only by alleviating the antagonistic effect diverse abiotic stress conditios, such as drought, but also by enhancing plant growth and yield. For instance, in tomato (_Solanum lycopersicum_), EBR treatment enhances drought tolerance, improving photosynthetic capacity, leaf water status, and antioxidant defense ({% cite Wang2018 %}). In pepper (_Capsicum annuum_), BL treatment increased the efficiency of light utilization under drought ({% cite Hu2013 %}). Gram (_Cicer arietinum_) plants exposed to drought stress and treated with BL showed significant increases in weight ({% cite Anwar2018 %}). However, the mechanisms of BRs action in enhancing plant tolerance to abiotic stresses still remain largely unknown.

MicroRNAs (miRNAs), mainly 20–22 nucleotide small RNAs (sRNAs), are characterized for regulating gene expression at the post-transcriptional level. miRNAs are distinguished from other sRNAs by being generated from precursor harboring an imperfect stem‐loop structure. Unlike in animals, the pre-processing of plant miRNA occurs in the nucleus (Figure 2). The pre-miRNAs are then exported to the cytoplasm after methylation and incorporated into the Argonaute 1 protein to form RISC (RNA-induced silencing complex). The miRNA itself does not have the ability to cleave mRNAs or interfere with translation, but it plays a role in scanning the appropriate target.


![fig2:miRNA biosynthesis](../../images/transcriptomics_images/plant_mirna_synthesis.png "Plant miRNA biosynthesis, homeostasis and mechanisms of action ({% cite Wang2019 %}).")


miRNAs have been found to be important regulators of many physiological processes, such as stress and hormonal responses. Four factors justify the miRNAs to be considered as master regulators of the plant response to the surrounding environment:

- Multiple miRNA genes are regulated under given environmental conditions
- Computational predictions estimate that each miRNA regulates hundreds of genes
- The majority of plant miRNAs regulate genes encoding for transcription factors (TFs)
- Targets include not only mRNAs but also long noncoding RNAs (lncRNAs)

In plants, miRNAs can silence targets through RNA degradation as well as translational repression pathways, and unlike animals, a large proportion of miRNA and their targets have less than four mismatches. This feature has been exploited for developing miRNAs target prediction tools, providing an efficient approach to elucidate the miRNA-mediated regulatory networks, which can contribute to biotechnological solutions to improve crops productivity.

In this tutorial, inspired by {% cite Park2020 %}, we aim to explore the interplay between brassinosteroids and the miRNA-gene silencing pathway, considered one of the most versatile regulatory mechanisms in response to stressful situations in plants.


> <agenda-title></agenda-title>
>
> In this tutorial, we will cover:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Experimental design

The main objective of this training is to identify potential targets of miRNAs whose expression is induced by brassinosteroids. Our starting hypothesis is that there must be brassinosteroid-induced miRNAs that have high sequence complementarity with mRNAs whose expression is inhibited in the presence of these hormones (Figure 3).

![fig3:Experimental design](../../images/transcriptomics_images/miRNA_pipeline.png "Experimental design")

# Background on data

The datasets to be used in this training can be classified into three groups: miRNA reads, mRNA reads and additional datasets.

## miRNA reads

The miRNA datasets consist of six FASTQ files, obtained by using the Illumina GAxII sequencing platform. The plant samples were obtained from wild-type Ws-2 seedlings treated with mock or 1 μM EBR for 90 min before harvest. The original datasets are available in the NCBI SRA database, with the accession number [SRP258575](https://www.ncbi.nlm.nih.gov/sra?term=SRP258575). As in the previous case, for this tutorial, we will use a reduced version of the data.


## mRNA reads

The mRNA datasets consist of four FASTQ files, generated through the Illumina HiSeq 2000 sequencing system. The samples were obtained from wild-type Columbia (Col-0) seedlings treated with mock or 100 nM BL for 4 hours. The original datasets are available in the NCBI SRA database, with the accession number [SRP032274](https://www.ncbi.nlm.nih.gov/sra?term=SRP032274). For this tutorial, subsets from the original data were generated in order to reduce the analysis run time.


## Additional datasets

In addition to the RNA-Seq reads obtained from the NCBI database, we will use datasets from two sources:

- [AtRTD2](https://ics.hutton.ac.uk/atRTD/) is a high-quality transcript reference dataset developed to exploit the accuracy of transcript quantification tools such as __Salmon__ and __Kallisto__ in analyzing _Arabidopsis_ RNA-Seq data.
- [PmiREN](http://pmiren.com/) is a comprehensive functional plant miRNA database that includes more than 20,000 annotated miRNAs diverse plant species.

# Get data

The first step of our analysis consists of retrieving the miRNA-Seq datasets from Zenodo and organizing them into collections.

> <hands-on-title>Retrieve miRNA-Seq and mRNA-Seq datasets</hands-on-title>
>
> 1. Create a new history for this tutorial
> 2. Import the files from Zenodo:
>
>    - Open the file {% icon galaxy-upload %} __upload__ menu
>    - Click on __Rule-based__ tab
>    - *"Upload data as"*: `Collection(s)`
>    - Copy the following tabular data, paste it into the textbox and press <kbd>Build</kbd>
>
>      ```
>      SRR11611349	Control miRNA	https://zenodo.org/record/4710649/files/SRR11611349_MIRNASEQ_CTL.fastqsanger.gz	fastqsanger.gz
>      SRR11611350	Control miRNA	https://zenodo.org/record/4710649/files/SRR11611350_MIRNASEQ_CTL.fastqsanger.gz	fastqsanger.gz
>      SRR11611351	Control miRNA	https://zenodo.org/record/4710649/files/SRR11611351.MIRNASEQ_CTLfastqsanger.gz	fastqsanger.gz
>      SRR11611352	BR treated miRNA	https://zenodo.org/record/4710649/files/SRR11611352_MIRNASEQ_BL.fastqsanger.gz	fastqsanger.gz
>      SRR11611353	BR treated miRNA	https://zenodo.org/record/4710649/files/SRR11611353_MIRNASEQ_BL.fastqsanger.gz	fastqsanger.gz
>      SRR11611354	BR treated miRNA	https://zenodo.org/record/4710649/files/SRR11611354_MIRNASEQ_BL.fastqsanger.gz	fastqsanger.gz
>      SRR1019436	Control mRNA	https://zenodo.org/record/4710649/files/SRR1019436_RNASEQ_CTL.fastqsanger.gz	fastqsanger.gz
>      SRR1019437	Control mRNA	https://zenodo.org/record/4710649/files/SRR1019437_RNASEQ_CTL.fastqsanger.gz	fastqsanger.gz
>      SRR1019438	BR treated mRNA	https://zenodo.org/record/4710649/files/SRR1019438_RNASEQ_BL.fastqsanger.gz	fastqsanger.gz
>      SRR1019439	BR treated mRNA	https://zenodo.org/record/4710649/files/SRR1019439_RNASEQ_BL.fastqsanger.gz	fastqsanger.gz
>      ```
>
>    - From **Rules** menu select `Add / Modify Column Definitions`
>       - Click `Add Definition` button and select `List Identifier(s)`: column `A`
>
>         > <tip-title>Can't find <i>List Identifier</i>?</tip-title>
>         > Then you've chosen to upload as a 'dataset' and not a 'collection'. Close the upload menu, and restart the process, making sure you check *Upload data as*: **Collection(s)**
>         {: .tip}
>
>       - Click `Add Definition` button and select `Collection Name`: column `B`
>       - Click `Add Definition` button and select `URL`: column `C`
>       - Click `Add Definition` button and select `Type`: column `D`
>
>    - Click `Apply` and press <kbd>Upload</kbd>
>
> {% snippet faqs/galaxy/datasets_add_tag.md type="name" %}
{: .hands_on}

Next we will retrieve the remaining datasets.

> <hands-on-title>Retrieve the additional datasets</hands-on-title>
>
> 1. Import the files from Zenodo:
>
>    - Open the file {% icon galaxy-upload %} __upload__ menu
>    - *"Upload data as"*: `Datasets`
>    - Once again, copy the tabular data, paste it into the textbox and press <kbd>Build</kbd>
>
>      ```
>      annotation_AtRTD2.gtf	https://zenodo.org/record/4710649/files/annotation_AtRTD2_19April2016.gtf.gz
>      transcriptome.fasta	https://zenodo.org/record/4710649/files/transcriptome_AtRTD2_12April2016.fasta.gz
>      star_miRNA_seq.fasta	https://zenodo.org/record/4710649/files/star_miRNA_seq.fasta
>      mature_miRNA_AT.fasta	https://zenodo.org/record/4710649/files/mature_miRNA_AT.fasta
>      miRNA_stem-loop_seq.fasta	https://zenodo.org/record/4710649/files/miRNA_stem-loop_seq.fasta
>      ```
>
>    - From **Rules** menu select `Add / Modify Column Definitions`
>       - Click `Add Definition` button and select `Name`: column `A`
>       - Click `Add Definition` button and select `URL`: column `B`
>    - Click `Apply` and press <kbd>Upload</kbd>
>
>
{: .hands_on}

> <details-title>Dataset subsampling</details-title>
>
> As indicated above, for this tutorial the depth of the samples was reduced in order to speed up the time needed to carry out the analysis. This was done as follows:
>
> > <hands-on-title>Dataset subsampling</hands-on-title>
> >
> > 1. {% tool [Sub-sample sequences files ](toolshed.g2.bx.psu.edu/repos/peterjc/sample_seqs/sample_seqs/0.2.6) %} with the following parameters:
> >    - {% icon param-files %} *"Multiple datasets"*: Each of the fastq files
> >    - *"Subsampling approach"*: `Take every N-th sequence (or pair e.g. every fifth sequence)`
> >    - *"N"*: `100`
> {: .hands_on}
>
> In this way, we will only take 1% of reads at a random sampling rate.
{: .details}


# miRNA data analysis

Once we have imported the data, we can begin to study how brassinosteroid exposure alters gene expression patterns.

## Quality assessment of miRNA reads

Due to technical limitations, sequencing is considered an error-prone process. In Illumina sequencing platforms, substitution type miscalls are the dominant source of errors, which can lead to inconsistent results. Another factor that can interfere with our analyses is the presence of adapter contaminants, which can result in an increased number of unaligned reads, since the adapter sequences are synthetic and do not occur in the genomic sequence.

Sequence quality control is therefore an essential first step in your analysis. We will use two popular tools for evaluating the quality of our raw reads: __Falco__ and __MultiQC__.

> <comment-title></comment-title>
> In order to visualize the data from both collections together in the __MultiQC__ tool, it will be necessary to combine the results generated by __Falco__.
> For more information on the topic of quality control, please see our [dedicated training materials]({% link topics/sequence-analysis/tutorials/quality-control/tutorial.md %}).
{: .comment}

> <hands-on-title>Initial quality check</hands-on-title>
>
> 1. {% tool [Falco](toolshed.g2.bx.psu.edu/repos/iuc/falco/falco/1.2.4+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Dataset collection"*: `Control miRNA`
> 2. Rename the outputs as `Falco unprocessed control miRNA: RawData` and `Falco unprocessed control miRNA: Webpage`
> 3. Repeat the previous steps with the `BR treated miRNA` collection.
> 4. {% tool [Merge Collections](__MERGE_COLLECTION__) %} with the following parameters:
>    - In *"Input collections"*:
>      - *"1.Input Collections"*: `Falco unprocessed control miRNA: RawData`
>      - *"2.Input Collections"*: `Falco unprocessed BR treated mRiNA: RawData`
> 5. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy3) %} with the following parameters:
>    - In *"Results"*:
>      - *"Which tool was used generate logs?"*: `FastQC`
>        - In *"FastQC output"*:
>          - {% icon param-repeat %} *"Insert FastQC output"*
>            - {% icon param-collection %} *"FastQC output"*: select the output of __Merge Collection__ tool
>    - In *"Report title"*: `miRNA initial quality check`
> 6. Click on the {% icon galaxy-eye %} (eye) icon and inspect the generated HTML file
>
{: .hands_on}


> <question-title></question-title>
>
> Based on the information provided by __MultiQC__, is it necessary to trimming/filtering the reads?
>
> > <solution-title></solution-title>
> >
> > The report generated by __MultiQC__ indicates that three quality parameters show values outside the recommended limits: per sequence G/C content, overrepresented sequences and adapter content.
> >
> > ![fig4:GC content](../../images/transcriptomics_images/miRNA_GC_content.png "Per sequence GC content of the miRNA samples.")
> > ![fig5:Overrepresented sequences](../../images/transcriptomics_images/miRNA_overepresented.png "Overrepresented sequences in miRNA samples.")
> > ![fig6:Adaptor content](../../images/transcriptomics_images/miRNA_adaptors.png "Adaptor content of miRNA samples.")
> >
> > Particularly remarkable is the content of adapters, which are up to 80% of the reads in some samples. Given the abundance of adapters, one would expect that if we eliminate this source of contamination, the rest of the parameters would show a noticeable improvement.
> >
> {: .solution}
{: .question}

To remove the adapters contamination, we will employ the __Trim Galore__ tool, a wrapper script around [__Cutadapt__](https://journal.embnet.org/index.php/embnetjournal/article/view/200) and __Falco__ which automates quality and adapter trimming.

> <hands-on-title>Trimming of adapter sequences</hands-on-title>
>
> 1. {% tool [Trim Galore!](toolshed.g2.bx.psu.edu/repos/bgruening/trim_galore/trim_galore/0.6.10+galaxy0) %} with the following parameters:
>    - *"Is this library paired- or single-end?"*: `Single-end`
>      -  {% icon param-collection %} *"Reads in FASTQ format"*: `Control miRNA`
>      - *"Adapter sequence to be trimmed"*: `Illumina small RNA adapters`
> 2. Rename the output collection as `Control miRNA trimmed`
> 3. Repeat the previous steps with the `BR treated miRNA` collection.
>
{: .hands_on}

Next, we will reassess the quality of the sequences to check if the adapters have been removed.

> <hands-on-title>Post-processing quality check</hands-on-title>
>
> 1. {% tool [Falco](toolshed.g2.bx.psu.edu/repos/iuc/falco/falco/1.2.4+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Dataset collection"*: `Control miRNA trimmed`
> 2. Rename the outputs as `Falco processed control miRNA: RawData` and `Falco processed control miRNA: Webpage`
> 3. Repeat the previous steps with the `BR treated miRNA trimmed` collection.
> 4. {% tool [Merge Collections](__MERGE_COLLECTION__) %} with the following parameters:
>    - In *"Input collections"*:
>        - *"1.Input Collections"*: `Falco processed control miRNA: RawData`
>        - *"2.Input Collections"*: `Falco processed BR treated miRNA: RawData`
> 5. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy3) %} with the following parameters:
>    - In *"Results"*:
>      - *"Which tool was used generate logs?"*: `FastQC`
>        - In *"FastQC output"*:
>           - {% icon param-repeat %} *"Insert FastQC output"*
>               - {% icon param-collection %} *"FastQC output"*: select the output of __Merge Collection__ tool
>    - *"Report title"*: `miRNA trimmed quality check`
> 6. Click on the {% icon galaxy-eye %} (eye) icon and inspect the generated HTML file
>
{: .hands_on}

The evaluation of the report generated by __MultiQC__ after having processed the samples by __Trim Galore__ indicates that the G/C content has been successfully corrected, and that the adapter contamination has been eliminated. However, the samples still show a high degree of over-represented sequences (Figure 7).

![fig7:Overexpressed sequences](../../images/transcriptomics_images/miRNA_overepresented_processed.png "Report of overexpressed sequences in the miRNA reads")


> <question-title></question-title>
>
> What do you think could be the cause of the high number of over-represented sequences?
>
> > <solution-title></solution-title>
> >
> >  Two of the factors that may determine the abundance of overrepresented sequences are the existence of highly expressed miRNAs (Seco-Cervera et al. 2018), the existence of highly conserved sequence motifs within the miRNA ({% cite Glazov2008 %}), and contamination with foreign sequences.
> >
> {: .solution}
{: .question}


## miRNA quantification: **MiRDeep2**

Quantification of miRNAs requires to use two different tools:
- The __MiRDeep2 Mapper__ tool for preprocessing the reads.
- The __MiRDeep2 Quantifier__  tool for mapping the deep sequencing reads to predefined miRNA precursors and determining the expression of the corresponding miRNAs. It is carried out in two steps: firstly, the predefined mature miRNA sequences are mapped to the predefined precursors (optionally, predefined star sequences can be mapped to the precursors too). And second, the deep sequencing reads are mapped to the precursors.

> <hands-on-title>Quantification of miRNAs</hands-on-title>
>
> 1. {% tool [MiRDeep2 Mapper](toolshed.g2.bx.psu.edu/repos/rnateam/mirdeep2_mapper/rbc_mirdeep2_mapper/2.0.0.8.1) %} with the following parameters:
>    - {% icon param-collection %} *"Deep sequencing reads"*: `Control miRNA trimmed`
>    - *"Remove reads with non-standard nucleotides"*: `Yes`
>    - *"Clip 3' Adapter Sequence"*: `Don't Clip`
>    - *"Collapse reads and/or Map"*: `Collapse`
> 2. Rename the output as `Collapsed control miRNA`
> 3. Repeat the previous stages by providing `BR treated miRNA trimmed`as input, and rename it as `Collapsed BR treated miRNA`.
>
> 4. {% tool [MiRDeep2 Quantifier](toolshed.g2.bx.psu.edu/repos/rnateam/mirdeep2_quantifier/rbc_mirdeep2_quantifier/2.0.0) %} with the following parameters:
>    - {% icon param-collection %} *"Collapsed deep sequencing reads"*: `Collapsed control miRNA`
>    - {% icon param-file %} *"Precursor sequences"*: `miRNA_stem-loop_seq.fasta`
>    - {% icon param-file %} *"Mature miRNA sequences"*: `mature_miRNA_AT.fasta`
>    - {% icon param-file %} *"Star sequences"*: `star_miRNA_seq.fasta`
> 5. Rename the outputs as `MiRDeep2 control miRNA` and `MiRDeep2 control miRNA (html)`.
> 6. Repeat the fourth step by providing `Collapsed BR treated miRNA` as input, and rename the outputs as `MiRDeep2 BR treated miRNA` and `MiRDeep2 BR treated miRNA (html)`
>
{: .hands_on}

To use the outputs generated by __MiRDeep2 Quantifier__ in the differential expression analysis, it is necessary to modify the datasets.

> <hands-on-title>Edition of MiRDeep2 Quantifier outputs</hands-on-title>
>
> 1. {% tool [Cut columns from a table](Cut1) %} with the following parameters:
>    - *"Cut columns"*: `c1,c2`
>    - *"Delimited by"*: `Tab`
>    - {% icon param-collection %} *"From"*: `MiRDeep2 control miRNA`
> 2. Rename the output as `control miRNA counts`
> 3. {% tool [Cut columns from a table](Cut1) %}  with the following parameters:
>    - *"Cut columns"*: `c1,c2`
>    - *"Delimited by"*: `Tab`
>    - {% icon param-collection %} *"From"*: `MiRDeep2 BR treated miRNA`
> 4. Rename the output as `BR treated miRNA counts`
>
{: .hands_on}

## Differential expression analysis of miRNAs: **DESeq2**

__DESeq2__ is a tool for differential gene expression analysis based on a negative binomial generalized linear model. __DESeq2__ internally corrects the differences in library size, due to which no preliminary normalization of input datasets is required.

> <comment-title></comment-title>
> It is desirable to use at least three replicates of each experimental condition to ensure sufficient statistical power.
>
{: .comment}

> <hands-on-title>Differential expression analysis using DESeq2</hands-on-title>
>
> 1. {% tool [DESeq2](toolshed.g2.bx.psu.edu/repos/iuc/deseq2/deseq2/2.11.40.8+galaxy0) %} with the following parameters:
>    - *"How"*: `Select datasets per level`
>        - In *"Factor"*:
>            - *"Specify a factor name, e.g. effects_drug_x or cancer_markers"*: `effects_brassinolide`
>            - In *"1: Factor level"*:
>                - *"Specify a factor level"*: `brassinolide`
>                - {% icon param-collection %} *"Counts file(s)"*: `BR treated miRNA counts`
>            - In *"2: Factor level"*:
>                - *"Specify a factor level"*: `control`
>                - {% icon param-collection %} *"Counts file(s)"*: `control miRNA counts`
>    - *"Files have header?"*: `No`
>    - *"Choice of Input data"*: `Count data (e.g. from HTSeq-count, featureCounts or StringTie)`
>    - In *"Advanced options"*:
>        - *"Use beta priors"*: `Yes`
> 2. Rename the outputs as `DESeq2 results miRNA` and `DESeq2 plots miRNA`
> 3. Click on the {% icon galaxy-eye %} (eye) icon and inspect the `DESeq2 plots miRNA` file
{: .hands_on}

DESeq2 generated 2 outputs: a table with the normalized counts and a graphical summary of the results. To evaluate the similarity of our samples, we are going to inspect the Principal Component Analysis (PCA) plot. PCA allows evaluating the dominant directions of the highest variability in the data. Thus, the samples subjected to the same conditions should cluster together.
![fig8:PCA miRNA](../../images/transcriptomics_images/miRNA_PCA.png " PCA plot of expression data from control and BR treated miRNA samples.")

As can be seen, the main axes account for only 47% and 19% of the total variation. This suggests that the effect of brassinosteroids on miRNA regulation is limited (Figure 8).

## Filter significantly differentially expressed miRNAs

Next, we will extract those genes whose expression is statistically significantly differentially expressed (DE) due to BR treatment by selecting those whose adjusted p-value is less than or 0.05. A cut-off value of 0.05 indicates that the probability of a false positive result is less than 5%.

> <details-title>p-value vs p-adj</details-title>
>
> The p-value is a measure of the probability that an observed difference could have occurred just by random chance. A small p-value indicates that there is a small chance of getting this data if no real difference existed. A p-value threshold of 0.05 indicates that there is a 5% chance that the result is a false positive. The p-adj (also known as q-value) is an adjusted p-value which taking in to account the false discovery rate (FDR). Applying a FDR becomes necessary when we're measuring thousands of variables from a small sample set.
>
{: .details}

> <hands-on-title>Filter differentially expressed miRNAs</hands-on-title>
>
> 1. {% tool [Filter](Filter1) %} data on any column using simple expressions (Galaxy Version 1.1.1) with the following parameters:
>    - {% icon param-file %} *"Filter"*: `DESeq2 results miRNA`
>    - *"With following condition"*: `c7<0.05`
>
{: .hands_on}

> <question-title></question-title>
>
> How many miRNAs show statistically significant differential expression?
>
> > <solution-title></solution-title>
> >
> > Unfortunately, we have not detected any differentially expressed miRNAs. In this case, this is caused by the fact that the subsampled datasets don't have sufficient read depth to test for differential expression.
> {: .solution}
>
{: .question}

To get any sensible results, it is worth analyzing the full dataset. You can analyze the full datasets following the above tutorial. Otherwise, you can import the DESeq2 analysis results that we generated from full dataset into your history.

> <hands-on-title>Retrieve the DESeq2 analysis results on full miRNA dataset</hands-on-title>
>
> 1. Import the files from Zenodo:
>
>    - Open the file {% icon galaxy-upload %} __upload__ menu
>    - Click of the **Paste/Fetch** button
>    - Copy the Zenodo links and press <kbd>Start</kbd>
>
>      ```
>      https://zenodo.org/record/4663389/files/miRNA_DESeq2_results_complete_dataset.tabular
>      ```
>
> 2. Rename each dataset according to the sample id (e.g. `miRNA_DESeq2_results_complete_dataset`)
> 3. Add all miRNA data analysis related tags: #miRNA #BR #control
{: .hands_on}

Repeat the filtering step on the imported DESeq2 result.

> <hands-on-title>Filter and sort differentially expressed miRNAs from the full dataset</hands-on-title>
>
> {: .comment}
> 1. {% tool [Filter](Filter1) %} data on any column using simple expressions (Galaxy Version 1.1.1) with the following parameters:
>    - {% icon param-file %} *"Filter"*: `miRNA_DESeq2_results_complete_dataset`
>    - *"With following condition"*: `c7<0.05`
> 2. Rename the output as `Differentially expressed miRNAs`
> 3. {% tool [Filter](Filter1) %} data on any column using simple expressions (Galaxy Version 1.1.1) with the following parameters:
>    - {% icon param-file %} *"Filter"*: `Differentially expressed miRNAs`
>    - *"With following condition"*: `c3>0`
> 4. Rename the output as `Upregulated miRNAs`
> 5. {% tool [Sort](sort1) %} data in ascending or descending order (Galaxy Version 1.1.0) with the following parameters:
>    - {% icon param-file %} *"Sort Dataset"*: `Upregulated miRNAs`
>    - *"on column"*: `Column: 3`
>    - *"everything in"*: `Descending order`
{: .hands_on}

> <question-title></question-title>
>
> 1. How many miRNAs are differentially expressed?
> 2. How many miRNAs show statistically significant upregulation and what is the most upregulated miRNA?
>
> > <solution-title></solution-title>
> >
> > 1. Out of 442 miRNAs, 39 show significant differential expression.
> > 2. There are 16 upregulated miRNAs and `Ath-miR156g` is the most upregulated one.
> {: .solution}
>
{: .question}

# mRNA data analysis

Once the differential expression analysis of miRNAs has been carried out, the next stage is to analyze how mRNA expression is altered in response to brassinosteroids.

## Quality assessment of mRNA reads

As in the previous section, we shall begin by assessing the quality of our sequences.

> <hands-on-title>Initial quality check</hands-on-title>
>
> 1. {% tool [Falco](toolshed.g2.bx.psu.edu/repos/iuc/falco/falco/1.2.4+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Dataset collection"*: `Control mRNA`
> 2. Rename the outputs as `Falco unprocessed control mRNA: RawData` and `Falco unprocessed control mRNA: Webpage`
> 3. Repeat the previous step with the `BR treated mRNA` collection.
> 4. {% tool [Merge Collections](__MERGE_COLLECTION__) %} with the following parameters:
>    - In *"Input collections"*:
>        - *"1.Input Collections"*: `Falco unprocessed control mRNA: RawData`
>        - *"2.Input Collections"*: `Falco unprocessed BR treated mRNA: RawData`
> 5. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy3) %} with the following parameters:
>    - In *"Results"*:
>      - *"Which tool was used generate logs?"*: `FastQC`
>        - In *"FastQC output"*:
>           - {% icon param-repeat %} *"Insert FastQC output"*
>               - {% icon param-collection %} *"FastQC output"*: select the output of __Merge Collection__ tool
>    - *"Report title"*: `mRNA initial quality check`
> 6. Click on the {% icon galaxy-eye %} (eye) icon and inspect the generated HTML file
>
{: .hands_on}

> <question-title></question-title>
>
> Are there any stats that indicate the need to process the samples in order to improve their quality?
>
> > <solution-title></solution-title>
> >
> > All the stats are within acceptable limits. However, the adapter content shows the presence of Illumina universal adapters in our reads, which can be removed to avoid possible interferences at later stages (Figure 10).
> >
> >    ![fig10:Adapter content of mRNA samples](../../images/transcriptomics_images/miRNA_adapter_01.png "Quality assessment of mRNA samples")
> >
> {: .solution}
{: .question}

> <comment-title></comment-title>
> Although our samples have adapters, we are not going to trim them in this case. We will explain the reason in the next section.
{: .comment}

## Quantification of gene expression: **Salmon**

After performing the quality assessment of the reads, we can move on to quantifying the gene expression. The aim of this step is to identify which transcript each read comes from and the total number of reads associated with each transcript. In this tutorial, we will use the Salmon tool ({% cite Patro2017 %}) for the quantification of mRNA transcripts.

![fig11:Salmon logo](../../images/transcriptomics_images/salmon_logo.png)

One of the characteristics of __Salmon__ is that it doesn't require performing a base-to-base alignment, which is the time-consuming step of tools such as __STAR__ and __HISAT2__. Salmon relies on the quasi-mapping concept, a new mapping technique that allows the rapid and accurate mapping of RNA-Seq reads to a target transcriptome. Rather than a standard alignment, quasi-mapping seeks to find the best mappings for each read, and does so by finding minimal collections of dynamically sized, right-maximal, matching contexts between target and query positions ({% cite Srivastava2016 %})

The quasi-mapping approach by __Salmon__ requires a reference index to determine the position and orientation information for accurate mapping prior to quantification. It allows providing the transcriptome in a format that optimizes its use in transcript identification and quantification.

After determining the best mapping for each read, __Salmon__  generates the final transcript abundance estimation after modeling sample-specific parameters and biases. Reads that map equally well to more than one transcript will have the count divided between all of the mappings, thus avoiding the loss of information on the different gene isoforms.


> <details-title>Quasi-mapping algorithm</details-title>
> The quasi-mapping algorithm makes use of two main data structures, the generalized suffix array (SA) of the transcriptome T, and a hash table (h) that maps each k-mer in T to its SA interval (by default k = 31). During the quasi-mapping procedure, a read is scanned from left to right until a k-mer (k<sub>i</sub>, starting at position i on the read) is encountered that appears in h. The k<sub>i</sub> is looked up in the hash table and the SA intervals are retrieved, giving all suffixes containing the k-mer k<sub>i</sub>. Then, the Maximal Mappable Prefix (MMP<sub>i</sub>) is computed by finding the longest substring of the read that matches the reference suffixes. Owing to sequencing errors, the MMPs may not span the complete read. In this case, the next informative position (NIP) is determined based on the longest common prefix of the SA intervals of MMP<sub>i</sub>. Suffix array search continues from k-bases before NIP until the final NIP is less than k-bases before the read end. Finally, for each read, the algorithm reports the transcripts it mapped to, location and strand information ({% cite Srivastava2016 %}).
> ![fig12:Quasi-mapping algorithm](../../images/transcriptomics_images/salmon_quasialignment.png "Illustration of the quasi-mapping of a read using k=3. Hash table lookup of k<sub>i</sub> returns the suffix array interval [b, e). The base 'G' at position 6 in the read is a result of sequencing error. Hence, the MMP<sub>i</sub> is 'ATTGA' and the SA interval of MMP<sub>i</sub> is [b', e'). The next k-mer starts at k-bases prior to the NIP which is base after the longest common prefix of the interval [b',e'). In the end, the read in the above example most likely map to the suffix array at [e'-1, e').")
>
{: .details}


> <hands-on-title>Quantify gene expression with Salmon</hands-on-title>
>
> 1. {% tool [Salmon quant](toolshed.g2.bx.psu.edu/repos/bgruening/salmon/salmon/1.10.1+galaxy2) %} with the following parameters:
>    - *"Select salmon quantification mode:"*: `Reads`
>        - *"Select a reference transcriptome from your history or use a built-in index?"*: `Use one from the history`
>            - In *"Salmon index"*:
>                - {% icon param-file %} *"Transcripts fasta file"*: `transcriptome.fasta`
>        - In *"Data input"*:
>            - *"Is this library mate-paired?"*: `Single-end`
>                - {% icon param-collection %} *"FASTQ/FASTA file"*: `Control mRNA`
>        - *"Validate mappings"*: `Yes`
>    - {% icon param-file %} *"File containing a mapping of transcripts to genes"*: `annotation_AtRTD2.gtf`
>
> 2. Rename the outputs as `Salmon control mRNA (Quantification)` and `Salmon control mRNA (Gene Quantification)`
> 3. Repeat the previous procedure by using the `BR treated mRNA` dataset
>
>   > <comment-title>Quasi-mapping sequence requirements</comment-title>
>   > Trimming the reads is not required  when using this method, since if there are k-mers in the reads that are not in the hash table, they are not counted. Quantification of the reads is only as good as the quality of the reference transcriptome.
>   {: .comment}
>
{: .hands_on}

__Salmon__ generates two outputs for each input sample:

- Quantification: summarizes the quantifications by transcript
- Gene quantification: summarizes the quantification by gene

Each output consists of a tabular dataset with five columns:


------------------| ----------
Field             | Description
------------------| ----------
Name              | The name of the target transcript provided in the input transcriptome.
Length            | The length of the target transcript.
EffectiveLength   | The computed effective length.
TPM               | The relative abundance of this transcript in units of Transcripts Per Million.
NumReads          | The number of reads mapping to each transcript that was quantified.
------------------| ----------


> <question-title></question-title>
>
> Could you explain why we did not trim the reads before?
>
> > <solution-title></solution-title>
> >
> > The reason is that, since the k-mers which contain the adaptor sequences are not present in the transcriptome (from which the hash table is generated), they are omitted.
> >
> {: .solution}
>
{: .question}

## Differential expression analysis of mRNAs: **DESeq2**

Now, let's analyze which genes show statistically significant differential expression in response to brassinosteoids.

> <hands-on-title>Differential expression analysis using DEseq2</hands-on-title>
>
> 1. {% tool [DESeq2](toolshed.g2.bx.psu.edu/repos/iuc/deseq2/deseq2/2.11.40.8+galaxy0) %} with the following parameters:
>    - *"How"*: `Select datasets per level`
>        - In *"Factor"*:
>            - *"Specify a factor name, e.g. effects_drug_x or cancer_markers"*: `effects_brassinolide`
>            - In *"1: Factor level"*:
>                - *"Specify a factor level"*: `brassinolide`
>                - {% icon param-collection %} *"Counts file(s)"*: `Salmon BR treated mRNA (Gene Quantification)`
>            - In *"2: Factor level"*:
>                - *"Specify a factor level"*: `control`
>                - {% icon param-collection %} *"Counts file(s)"*: `Salmon control mRNA (Gene Quantification)`
>    - *"Choice of Input data"*: `TPM values (e.g. from kallisto, sailfish or salmon)`
>        - *"Program used to generate TPMs"*: `Salmon`
>        - *"Gene mapping format"*: `GTF/GFF3`
>            - {% icon param-file %} *"GTF/GFF3 annotation file"*: `annotation_AtRTD2.gtf`
> 2. Rename the outputs as `DESeq2 results mRNA` and `DESeq2 plots mRNA`
{: .hands_on}

![fig13:PCA plot of mRNA samples](../../images/transcriptomics_images/mRNA_PCA.png " PCA plot of differential expression data from control and BR treated samples.")

> <question-title></question-title>
>
> What conclusions about the similarity of the samples can be derived from the PCA plot?
>
> > <solution-title></solution-title>
> >
> > From the information provided by the plot, it is possible to state that there is a high similarity between the samples belonging to the same experimental conditions, since the first dimension (x-axis) allows to explain 79% of the variability, and the samples are located at opposite ends of the x-axis.
> >
> {: .solution}
>
{: .question}

## Filter significantly differentially expressed mRNAs

To conclude the analysis of the differential expression of mRNAs, we will extract those transcripts that show a significant induction of expression in response to brassinosteroids. Before continuing with further analysis, similar to miRNA data analysis, import the DESeq2 results generated from full mRNA datasets.

> <hands-on-title>Retrieve the DESeq2 analysis results on full mRNA dataset</hands-on-title>
>
> 1. Import the files from Zenodo:
>
>    - Open the file {% icon galaxy-upload %} __upload__ menu
>    - Click of the **Paste/Fetch** button
>    - Copy the Zenodo links and press <kbd>Start</kbd>
>
>      ```
>      https://zenodo.org/record/4663389/files/mRNA_DESeq2_results_complete_dataset.tabular
>      ```
>
> 2. Rename each dataset according to the sample id (e.g. `mRNA_DESeq2_results_complete_dataset`)
> 3. Add all mRNA data analysis related tags: #mRNA #BR #control
{: .hands_on}

Now we continue with the DE genes analysis.

> <hands-on-title>Extract significantly DE genes</hands-on-title>
>
> 1. {% tool [Filter](Filter1) %} data on any column using simple expressions (Galaxy Version 1.1.1) with the following parameters:
>    - {% icon param-file %} *"Filter"*: `mRNA_DESeq2_results_complete_dataset`
>    - *"With following condition"*: `c7<0.05`
> 2. Rename the output as `Differentially expressed mRNAs`
>
> 3. {% tool [Filter](Filter1) %}data on any column using simple expressions (Galaxy Version 1.1.1) with the following parameters:
>    - {% icon param-file %} *"Filter"*: `Differentially expressed mRNAs`
>    - *"With following condition"*: `c3>1`
> 4. Rename it as `Upregulated mRNAs`
>
> 5. {% tool [Filter](Filter1) %} data on any column using simple expressions (Galaxy Version 1.1.1) with the following parameters:
>    - {% icon param-file %} *"Filter"*: `Differentially expressed mRNAs`
>    - *"With following condition"*: `c3<-1`
> 6. Rename it as `Downregulated mRNAs`
>
{: .hands_on}

> <question-title></question-title>
>
> 1. How many genes show statistically significant differential expression?
> 2. How many of them are significantly upregulated (at least two-fold change)? And downregulated?
> 3. What is the most significantly DE downregulated gene and what is it biological function?
>
> > <solution-title></solution-title>
> >
> > 1. The total number of genes whose expression differential between the two experimental conditions is 4176.
> > 2. Of them, 328 are significantly downregulated by the BR treatment and 778 are upregulated.
> > 3. The most significantly DE gene is AT3G30180 (BR60X2). BR60X2 encodes a cytochrome p450 enzyme that catalyzes the last reaction in the production of brassinolide. It is capable of converting 6-deoxocastasterone into castasterone, a C-6 oxidation, as well as the further conversion of castasterone into brassinolide (source: [TAIR database](https://www.arabidopsis.org/servlets/TairObject?name=at3g30180&type=locus)).
> {: .solution}
>
{: .question}

# Identification of miRNA targets

To predict which miRNAs target which mRNAs, first we need their transcriptomic sequences in FASTA format. Now we will obtain the sequences of miRNAs whose expression is induced by brassinosteroids.

> <hands-on-title>Obtaining the sequences of upregulated miRNAs</hands-on-title>
> > <comment-title></comment-title>
> >
> > The following tools can be found in _Text Manipulation_ and _Filter and Sort_ sections.
> >
> {: .comment}
>
> 1. {% tool [Cut columns from a table](Cut1) %} with the following parameters:
>    - *"Cut columns"*: `c1`
>    - *"Delimited by"*: `Tab`
>    - {% icon param-collection %} *"From"*: `Upregulated miRNAs`
> 2. Rename the output as `Upregulated miRNA ids`
> 3. {% tool [Filter FASTA](toolshed.g2.bx.psu.edu/repos/galaxyp/filter_by_fasta_ids/filter_by_fasta_ids/2.3) %} with the following parameters:
>    - {% icon param-file %} *"FASTA sequences"*: `mature_miRNA_AT.fasta`
>    - *"Criteria for filtering on the headers"*: `List of IDs`
>        - {% icon param-file %} *"List of IDs to extract sequences for"*: `Upregulated miRNA ids`
>        - *"Match IDs by"*: `Default: ID is expected at the beginning: >ID`
> 4. {% tool [Filter FASTA](toolshed.g2.bx.psu.edu/repos/galaxyp/filter_by_fasta_ids/filter_by_fasta_ids/2.3) %} with the following parameters:
>    - {% icon param-file %} *"FASTA sequences"*: `star_miRNA_seq.fasta`
>    - *"Criteria for filtering on the headers"*: `List of IDs`
>        - {% icon param-file %} *"List of IDs to extract sequences for"*: `Upregulated miRNA ids`
>        - *"Match IDs by"*: `Default: ID is expected at the beginning: >ID`
> 5. {% tool [Concatenate datasets](cat1) %} tail-to-head (Galaxy Version 1.0.0) with the following parameters:
>    - {% icon param-file %} *"Concatenate Dataset"*: output of **Filter FASTA** {% icon tool %} on `mature_miRNA_AT.fasta`
>    - + Insert Dataset
>        - {% icon param-file %} *"Select"*: output of **Filter FASTA** {% icon tool %} on `star_miRNA_seq.fasta`
> 6. Rename it as `Upregulated miRNA sequences`
> 7. Click on the {% icon galaxy-eye %} (eye) icon and inspect the `Upregulated miRNA sequences` file
{: .hands_on}

To identify putative targets of upregulated miRNAs, it is necessary to obtain the sequences of all downregulated mRNAs in FASTA format.

> <hands-on-title>Obtaining the gene sequences of downregulated mRNAs</hands-on-title>
> 1. {% tool [Cut columns from a table](Cut1) %} with the following parameters:
>    - *"Cut columns"*: `c1`
>    - *"Delimited by"*: `Tab`
>    - {% icon param-collection %} *"From"*: `Downregulated mRNAs`
> 2. Rename the output as `Downregulated mRNA ids`
> 3. {% tool [Filter FASTA](toolshed.g2.bx.psu.edu/repos/galaxyp/filter_by_fasta_ids/filter_by_fasta_ids/2.3) %} with the following parameters:
>    - {% icon param-file %} *"FASTA sequences"*: `transcriptome.fasta` (Input dataset)
>    - *"Criteria for filtering on the headers"*: `List of IDs`
>        - {% icon param-file %} *"List of IDs to extract sequences for: `Downregulated mRNA ids`
>        - *"Match IDs by"*: `Custom regex pattern`
>           - *"Regex search pattern for ID"*: `GENE=(AT.{7})`
> 4. Rename it as `Downregulated mRNA sequences`
> 5. Click on the {% icon galaxy-eye %} (eye) icon and inspect the `Downregulated mRNA sequences`  file
{: .hands_on}

## miRNA target prediction using **TargetFinder**

We are now ready to launch the search for miRNA target genes. For this we will use the __TargetFinder__ tool that is implemented and used for miRNA target prediction in plants ({% cite Srivastava2014 %}, {% cite Ma2017 %}).

> <hands-on-title>identification of potential miRNA targets</hands-on-title>
>
> 1. {% tool [TargetFinder](toolshed.g2.bx.psu.edu/repos/rnateam/targetfinder/targetfinder/1.7.0+galaxy1) %} with the following parameters:
>    - {% icon param-file %} *"Input small RNA sequences file"*: `Upreguled miRNA sequences`
>    - {% icon param-file %} *"Target sequence database file*": `Downregulated mRNA sequences`
>    - *"Prediction score cutoff value"*: `5.0`
>    - *"Output format"*: `Tab-delimited format`
> 2. Click on the {% icon galaxy-eye %} (eye) icon and inspect the output of **TargetFinder**.
{: .hands_on}

Congratulations! We have identified the following 5 potential genes involved in the brassinosteroid-miRNA regulatory network.

![fig15:TargetFinder results](../../images/transcriptomics_images/targetFinder_results.png "TargetFinder results.")

Finally, we can access all the information available on the genes identified in the TAIR database:

- [AT5G10180](https://www.arabidopsis.org/servlets/TairObject?type=locus&name=AT5G10180): ARABIDOPSIS SULFATE TRANSPORTER 68, AST6
- [AT3G09220](https://www.arabidopsis.org/servlets/TairObject?type=locus&name=AT3G09220): LAC7, LACCASE 7
- [AT2G46850](https://www.arabidopsis.org/servlets/TairObject?type=locus&name=AT2G46850): Protein kinase superfamily protein
- [AT5G64260](https://www.arabidopsis.org/servlets/TairObject?type=locus&name=AT5G64260): EXL2, EXORDIUM LIKE 2
- [AT3G63200](https://www.arabidopsis.org/servlets/TairObject?type=locus&name=AT3G63200): PATATIN-LIKE PROTEIN 9, PLA IIIB

Both AT4G14365 and AT1G26890 are not well characterized genes. In the case of AT5G50570, experimental research have demonstrated that this gene is involved in  flooding tolerance in *Medicago sativa*, through a signaling path mediated by miR156 ({% cite Feyissa2021 %}). On the other hand, according to {% cite Gao2017 %}, SPL13 is likely a negative regulator of plant vegetative growth. The interaction between miR156 and SPL transcription factors has been suggested for diverse Poaceae family members ({% cite Yue2021 %}).

> <comment-title>Hypothesis testing</comment-title>
> One of the hypotheses that we could propose from our results is: the inhibition of the AT2G46850 gene can result in plants with improved resistance to drought conditions. Is it possible to validate it? Yes! We propose this approach: to acquire [AT2G46850 mutant seeds](https://abrc.osu.edu/stocks/392113) and [wild type seeds](http://arabidopsis.info/StockInfo?NASC_id=N1093), grow them under two controlled conditions: watered and drought stress, and analyze plant weight after 33 days (Figure 13).
>
> ![fig16:Plant growth](../../images/transcriptomics_images/arabidopis_growth_protocol.png "Arabidopsis growth conditions protocol ({% cite deOllas2019 %}).")
>
{: .comment}

# Optional exercise

As additional activity, you can try to repeat the workflow by using the sequences stored in the NCBI GEO database with the accession number `GSE119382`. In that case, we will compare gene expression patterns of mutants overexpressing the brassinosteroid receptor BRL3 under two experimental conditions: control and drought-stress. The required datasets are available in the data library:

> <hands-on-title>Import data from the Data Libraries</hands-on-title>
> 1. Go into __Data__ (top panel) and click on __Data Libraries__
> 2. In the search box enter the following identifier: `4710649`
> 3. Select the following files:
> ```
> https://zenodo.org/record/4710649/files/SRR7779222_BRL3_mRNA_drought.fastqsanger.gz
> https://zenodo.org/record/4710649/files/SRR7779223_BRL3_mRNA_drought.fastqsanger.gz
> https://zenodo.org/record/4710649/files/SRR7779224_BRL3_mRNA_drought.fastqsanger.gz
> ```
> 4. Click on __Export to History__ and __as a Collection__
> 5. In the pop-up window press <kbd>Continue</kbd>
> 6. Provide it the name `BRL3 mRNA drought` and push <kbd>Create list</kbd>
> 7. Repeat the previous procedure with the remaining files:
> ```
> https://zenodo.org/record/4710649/files/SRR7779228_BRL3_mRNA_watered.fastqsanger.gz
> https://zenodo.org/record/4710649/files/SRR7779229_BRL3_mRNA_watered.fastqsanger.gz
> ```
> 9. Finally provide it the name `BRL3 mRNA control` and push <kbd>Create list</kbd>
{: .hands_on}

We will use the upregulated miRNAs obtained in the previous analysis in order to identify potential targets.

```
Upregulated miRNA   https://zenodo.org/record/4710649/files/upregulated_miRNA_BR_complete_dataset.fasta
```

# Conclusion


In this tutorial, we have analyzed RNA sequencing data to extract information about potential genes regulated by brassinosteroids. For this purpose, the approach chosen was the identification of genes complementary to miRNAs upregulated in response by brassinosteroids. The final result has been the identification of five potential miRNA targets.


topic: transcriptomics
tutorial: rna-seq-reads-to-counts
title: 1: RNA-Seq reads to counts
difficulty: intermediate
time_estimation: 3h
tools_json: []
requirements_json: []
tags_json: ["collections", "mouse", "QC"]
content_hash: 6b3d0be577009c5d4e2fa326a1ed67f7
last_modified: 2026-02-26T21:12:18.572992
zenodo_link: https://zenodo.org/record/4249555
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/rna-seq-reads-to-counts/tutorial.html

content:
Measuring gene expression on a genome-wide scale has become common practice over the last two decades or so, with microarrays predominantly used pre-2008. With the advent of next generation sequencing technology in 2008, an increasing number of scientists use this technology to measure and understand changes in gene expression in often complex systems. As sequencing costs have decreased, using RNA-Seq to simultaneously measure the expression of tens of thousands of genes for multiple samples has never been easier. The cost of these experiments has now moved from generating the data to storing and analysing it.

There are many steps involved in analysing an RNA-Seq experiment. The analysis begins with sequencing reads (FASTQ files). These are usually aligned to a reference genome, if available. Then the number of reads mapped to each gene can be counted. This results in a table of counts, which is what we perform statistical analyses on to determine differentially expressed genes and pathways. The purpose of this tutorial is to demonstrate how to do read alignment and counting, prior to performing differential expression. Differential expression analysis with limma-voom is covered in an accompanying tutorial [RNA-seq counts to genes]({% link topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.md %}). The tutorial here shows how to start from FASTQ data and perform the mapping and counting steps, along with associated Quality Control.

## Mouse mammary gland dataset

The data for this tutorial comes from a Nature Cell Biology paper by {% cite Fu2015 %}. Both the raw data (sequence reads) and processed data (counts) can be downloaded from Gene Expression Omnibus database (GEO) under accession number [GSE60450](http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE60450).

This study examined the expression profiles of basal and luminal cells in the mammary gland of virgin, pregnant and lactating mice. Six groups are present, with one for each combination of cell type and mouse status. Note that two biological replicates are used here, two independent sorts of cells from the mammary glands of virgin, pregnant or lactating mice, however three replicates is usually recommended as a minimum requirement for RNA-seq.

This is a Galaxy tutorial based on material from the [COMBINE R RNAseq workshop](http://combine-australia.github.io/RNAseq-R/07-rnaseq-day2.html), first taught [at a workshop in 2016](http://combine-australia.github.io/2016-05-11-RNAseq/).

![Tutorial Dataset](../../images/rna-seq-reads-to-counts/mouse_exp.png "Tutorial Dataset")


> <agenda-title></agenda-title>
>
> In this tutorial, we will cover:
>
> 1. TOC
> {:toc}
>
{: .agenda}


{% snippet faqs/galaxy/analysis_results_may_vary.md %}

# Preparing the reads

## Import data from URLs

{% assign servers = nil | list_usegalaxy_servers_shuffle %}

Read sequences are usually stored in compressed (gzipped) FASTQ files. Before the differential expression analysis can proceed, these reads must be aligned to the reference genome and counted into annotated genes. Mapping reads to the genome is a very important task, and many different aligners are available, such as HISAT2 ({% cite kim2015hisat %}), STAR ({% cite dobin2013star %}) and Subread ({% cite Liao2013 %}). Most mapping tasks require larger computers than an average laptop, so usually read mapping is done on a server in a linux-like environment, requiring some programming knowledge. However, Galaxy enables you to do this mapping without needing to know programming and if you don't have access to a server you can try to use one of the publically available Galaxies e.g. {% for server in servers %}[{{ server.name }}]({{ server.url }}){% if forloop.last %}{% else %}, {% endif %}{% endfor %}.

The raw reads used in this tutorial were obtained from SRA from the link in GEO for the the mouse mammary gland dataset (e.g `ftp://ftp-trace.ncbi.nlm.nih.gov/sra/sra-instant/reads/ByStudy/sra/SRP%2FSRP045%2FSRP045534`). For the purpose of this tutorial we are going to be working with a small part of the FASTQ files. We are only going to be mapping 1000 reads from each sample to enable running through all the steps quickly. If working with your own data you would use the full data and some results for the full mouse dataset will be shown for comparison. The small FASTQ files are available in [Zenodo](https://zenodo.org/record/4249555) and the links to the FASTQ files are provided below.

If you are sequencing your own data, the sequencing facility will almost always provide compressed FASTQ files which you can upload into Galaxy. For sequence data available through URLs, The [Galaxy Rule-based Uploader]({% link topics/galaxy-interface/tutorials/upload-rules/tutorial.md %}) can be used to import the files. It is much quicker than downloading FASTQs to your computer and uploading into Galaxy and also enables importing as a **Collection**. When you have more than a few files, using Galaxy Collections helps keep the datasets organised and tidy in the history. Collections also make it easier to maintain the sample names through tools and workflows. If you are not familiar with collections, you can take a look at the [Galaxy Collections tutorial]({% link topics/galaxy-interface/tutorials/collections/tutorial.md %}) for more details. The screenshots below show a comparison of what the FASTQ datasets for this tutorial would look like in the history if we imported them as datasets versus as a collection with the Rule-based Uploader.

Datasets | Collection
--- | ---
![Samples imported as datasets](../../images/rna-seq-reads-to-counts/imported-as-datasets.png)| ![Samples imported as collection with Rule-based Uploader](../../images/rna-seq-reads-to-counts/imported-as-collection.png)


> <details-title>Collections and sample names</details-title>
>
> Collections can also help to maintain the original sample names on the files throughout the tools used. The screenshots below show what we would see in one of the MultiQC reports that we will generate if we used datasets versus a collection.
>
> Datasets | Collection
> --- | ---
> ![Sample names without collection](../../images/rna-seq-reads-to-counts/samplesnames_without_collection.png)| ![Sample names with collection](../../images/rna-seq-reads-to-counts/samplesnames_with_collection.png)
>
{: .details}


The information we need to import the samples for this tutorial (sample ID, Group, and link to the FASTQ file (URL) are in the grey box below.

```
SampleID	Group	URL
MCL1-DL	basallactate	https://zenodo.org/record/4249555/files/SRR1552455.fastq.gz
MCL1-DK	basallactate	https://zenodo.org/record/4249555/files/SRR1552454.fastq.gz
MCL1-DJ	basalpregnant	https://zenodo.org/record/4249555/files/SRR1552453.fastq.gz
MCL1-DI	basalpregnant	https://zenodo.org/record/4249555/files/SRR1552452.fastq.gz
MCL1-DH	basalvirgin	https://zenodo.org/record/4249555/files/SRR1552451.fastq.gz
MCL1-DG	basalvirgin	https://zenodo.org/record/4249555/files/SRR1552450.fastq.gz
MCL1-LF	luminallactate	https://zenodo.org/record/4249555/files/SRR1552449.fastq.gz
MCL1-LE	luminallactate	https://zenodo.org/record/4249555/files/SRR1552448.fastq.gz
MCL1-LD	luminalpregnant	https://zenodo.org/record/4249555/files/SRR1552447.fastq.gz
MCL1-LC	luminalpregnant	https://zenodo.org/record/4249555/files/SRR1552446.fastq.gz
MCL1-LB	luminalvirgin	https://zenodo.org/record/4249555/files/SRR1552445.fastq.gz
MCL1-LA	luminalvirgin	https://zenodo.org/record/4249555/files/SRR1552444.fastq.gz
```


In order to get these files into Galaxy, we will want to do a few things:

* Strip the *header* out of the sample information (it doesn’t contain a URL Galaxy can download).
* Define the file **Identifier** column (`SampleID`).
* Define the **URL** column (`URL`) (this is the location Galaxy can download the data from).

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this tutorial e.g. `RNA-seq reads to counts`
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. Import the files from Zenodo using Galaxy's Rule-based Uploader.
>    - Open the Galaxy Upload Manager
>    - Click the tab **Rule-based**
>        - *"Upload data as"*: `Collection(s)`
>        - *"Load tabular data from"*: `Pasted Table`
>    - Paste the table from the grey box above. *(You should now see below)*
>    - Click **Build**
>
>       ![Rule-based Uploader](../../images/rna-seq-reads-to-counts/rule_uploader.png "Rule-based Uploader")
>
>    - In the `rules editor` that pops up:
>
>        - **Remove the header**. From the **Filter** menu select `First or Last N Rows`
>            - *"Filter which rows?"*: `first`
>            - *"Filter how many rows?"*: `1`
>            - Click `Apply`
>
>        - **Define the Identifier and URL columns**. From the **Rules** menu select `Add / Modify Column Definitions`
>            - Click `Add Definition` button and select List Identifier(s)
>                - *"List Identifier(s)"*: `A`
>            - Click `Add Definition` button again and select URL instead
>                - *"URL"*: `C`
>            - Click `Apply`, and you should see your new column definitions listed
>
>        - **Name the collection**. For *"Name"* enter: `fastqs` *(You should now see below)*
>        - Click `Upload`
>
>        ![Rules Editor](../../images/rna-seq-reads-to-counts/rule_editor.png "Rules Editor")
>
>        You should see a collection (list) called `fastqs` in your history containing all 12 FASTQ files.
>
>
{: .hands_on}

If your data is not accessible by URL, for example, if your FASTQ files are located on your laptop and are not too large, you can upload into a collection as below. If they are large you could use FTP. You can take a look at the [Getting data into Galaxy slides]({% link topics/galaxy-interface/tutorials/get-data/slides.html %}) for more information.

> <tip-title>Upload local files into a collection</tip-title>
>
> - Open the Galaxy Upload Manager
> - Click the tab **Collection**
> - Click **Choose Local Files** and locate the files you want to upload
>     - *"Collection Type"*: `List`
> - In the pop up that appears:
>     - *"Name"*: `fastqs`
>     - Click `Create list`
{: .tip}

If your FASTQ files are located in Shared Data, you can import them into your history as a collection as below.

> <tip-title>Import files from Shared Data into a collection</tip-title>
>
> - In the Menu at the top go to Shared Data > Data Libraries
> - Locate your FASTQ files
> - Tick the checkboxes to select the files
> - From the **To History** menu select `as a Collection`
> - In the pop up that appears:
>     - *"Which datasets?"*: `current selection`
>     - *"Collection type"*: `List`
>     - *"Select history"*: `select your History`
>     - Click `Continue`
> - In the pop up that appears:
>     - *"Name"*: `fastqs`
>     - Click `Create list`
{: .tip}

Take a look at one of the FASTQ files to see what it contains.

> <hands-on-title>Take a look at FASTQ format</hands-on-title>
>
> 1. Click on the collection name (`fastqs`)
> 2. Click on the {% icon galaxy-eye %} (eye) icon of one of the FASTQ files to have a look at what it contains
{: .hands_on}

> <details-title>FASTQ format</details-title>
> If you are not familiar with FASTQ format, see the [Quality Control tutorial]({% link topics/sequence-analysis/tutorials/quality-control/tutorial.md %})
{: .details}


## Raw reads QC

During sequencing, errors are introduced, such as incorrect nucleotides being called. These are due to the technical limitations of each sequencing platform. Sequencing errors might bias the analysis and can lead to a misinterpretation of the data. Every base sequence gets a quality score from the sequencer and this information is present in the FASTQ file. A quality score of 30 corresponds to a 1 in 1000 chance of an incorrect base call (a quality score of 10 is a 1 in 10 chance of an incorrect base call). To look at the overall distribution of quality scores across the reads, we can use FastQC.

Sequence quality control is therefore an essential first step in your analysis. We will use similar tools as described in the ["Quality control" tutorial]({% link topics/sequence-analysis/tutorials/quality-control/tutorial.md %}): [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) and Cutadapt ({% cite marcel2011cutadapt %}).

> <hands-on-title>Check raw reads with <b>FastQC</b></hands-on-title>
>
> 1. {% tool [FastQC](toolshed.g2.bx.psu.edu/repos/devteam/fastqc/fastqc/0.73+galaxy0) %}
>    - {% icon param-collection %} *"Short read data from your current history"*: `fastqs` (Input dataset collection)
> 2. Inspect the `Webpage` output of **FastQC** {% icon tool %} for the `MCL1-DL` sample by clicking on the {% icon galaxy-eye %} (eye) icon
>
> {% snippet faqs/galaxy/tools_select_collection.md %}
>
{: .hands_on}



> <question-title></question-title>
> 1. What is the read length?
> 2. What base quality score encoding is used?
>
> > <solution-title></solution-title>
> >
> > 1. The read length is 100 bp.
> > 2. Sanger quality score encoding is used.
> > This information can be seen at the top of the FastQC Webpage as below.
> >
> > ![FastQC Webpage](../../images/rna-seq-reads-to-counts/fastqc_webpage.png "FastQC Webpage")
> >
> {: .solution}
>
{: .question}

The FastQC report contains a lot of information and we can look at the report for each sample. However, that is quite a few reports, 12 for this dataset. If you had more samples it could be a lot more. Luckily, there is a very useful tool called MultiQC ({% cite ewels2016multiqc %}) that can summarise QC information for multiple samples into a single report. We'll generate a few MultiQC outputs in this tutorial so we'll add name tags so we can differentiate them.

> <hands-on-title>Aggregate FastQC reports with <b>MultiQC</b></hands-on-title>
>
> 1. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters to aggregate the FastQC reports
>      - In *"Results"*
>        - {% icon param-select %}*"Which tool was used generate logs?"*: `FastQC`
>        - In *"FastQC output"*
>           - {% icon param-select %} *"Type of FastQC output?"*: `Raw data`
>           - {% icon param-collection %} *"FastQC output"*: `RawData` files (output of **FastQC** {% icon tool %} on trimmed reads)
> 2. Add a tag `#fastqc-raw` to the `Webpage` output from MultiQC and inspect the webpage
>
> {% snippet faqs/galaxy/datasets_add_tag.md type="name" %}
>
{: .hands_on}


Note that these are the results for just 1000 reads. The FastQC results for the full dataset are shown below. The 1000 reads are the first reads from the FASTQ files, and the first reads usually originate from the flowcell edges, so we can expect that they may have lower quality and the patterns may be a bit different from the distribution in the full dataset.

You should see that most of the plots in the small FASTQs look similar to the full dataset. However, in the small FASTQs, there is less duplication, some Ns in the reads and some overrepresented sequences.

![General Statistics](../../images/rna-seq-reads-to-counts/fastqc_table.png "General Statistics")
![Sequence Counts](../../images/rna-seq-reads-to-counts/fastqc_sequence_counts_plot.png "Sequence Counts")
![Sequence Quality](../../images/rna-seq-reads-to-counts/fastqc_per_base_sequence_quality_plot.png "Sequence Quality")
![Per Sequence Quality Scores](../../images/rna-seq-reads-to-counts/fastqc_per_sequence_quality_scores_plot.png "Per Sequence Quality Scores")
![Per Sequence GC Content](../../images/rna-seq-reads-to-counts/fastqc_per_sequence_gc_content_plot.png "Per Sequence GC Content")
![Per base N content](../../images/rna-seq-reads-to-counts/fastqc_per_base_n_content_plot.png "Per base N content")
![Sequence Duplication Levels](../../images/rna-seq-reads-to-counts/fastqc_sequence_duplication_levels_plot.png "Sequence Duplication Levels")
![Adapter Content](../../images/rna-seq-reads-to-counts/fastqc_adapter_content_plot.png "Adapter Content")

See the [Quality Control tutorial]({% link topics/sequence-analysis/tutorials/quality-control/tutorial.md %}) for more information on FastQC plots.

> <question-title></question-title>
>
> What do you think of the overall quality of the sequences?
>
> > <solution-title></solution-title>
> >
> > Overall, the samples look pretty good. The main things to note here are:
> > * The **base quality** is high in all samples.
> > * Some Illumina **adapter** has been detected.
> > * Some duplication in RNA-seq can be normal due to the presence of highly expressed genes. However, for some reason `MCL1-LE` and `MCL1-LF` have higher numbers of duplicates detected than the other samples.
> >
> {: .solution}
{: .question}

We will use Cutadapt to trim the reads to remove the Illumina adapter and any low quality bases at the ends (quality score < 20). We will discard any sequences that are too short (< 20bp) after trimming. We will also output the Cutadapt report for summarising with MultiQC.

The Cutadapt tool Help section provides the sequence we can use to trim this standard Illumina adapter `AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC`, as given on the [Cutadapt website](https://cutadapt.readthedocs.io/en/stable/guide.html#illumina-truseq). For trimming paired-end data see the Cutadapt Help section. Other Illumina adapter sequences (e.g. Nextera) can be found at the [Illumina website](http://sapac.support.illumina.com/bulletins/2016/12/what-sequences-do-i-use-for-adapter-trimming.html). Note that Cutadapt requires at least three bases to match between adapter and read to reduce the number of falsely trimmed bases, which can be changed in the Cutadapt options if desired.

## Trim reads

> <hands-on-title>Trim reads with <b>Cutadapt</b></hands-on-title>
>
> 1. {% tool [Cutadapt](toolshed.g2.bx.psu.edu/repos/lparsons/cutadapt/cutadapt/3.7+galaxy0) %}
>    - {% icon param-select %} *"Single-end or Paired-end reads?"*: `Single-end`
>        - {% icon param-collection %} *"FASTQ/A file"*: `fastqs` (Input dataset collection)
>        - In *"Read 1 Options"*:
>            - In *"3' (End) Adapters"*:
>                - Click on *"Insert 3' (End) Adapters"*:
>                - In *"1: 3' (End) Adapters"*:
>                    - {% icon param-select %} *"Source"*: `Enter custom sequence`
>                        - {% icon param-text %} *"Enter custom 3' adapter name (Optional)"*: `Illumina`
>                        - {% icon param-text %} *"Enter custom 3' adapter sequence"*: `AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC`
>    - In *"Filter Options"*:
>        - {% icon param-text %} *"Minimum length (R1)"*: `20`
>    - In *"Read Modification Options"*:
>        - {% icon param-text %} *"Quality cutoff"*: `20`
>    - {% icon param-check %} *"Outputs selector"*: `Report`
>
{: .hands_on}

We can take a look at the reads again now that they've been trimmed.

## Trimmed reads QC

> <hands-on-title>QC of trimmed reads with <b>FastQC</b></hands-on-title>
>
> 1. {% tool [FastQC](toolshed.g2.bx.psu.edu/repos/devteam/fastqc/fastqc/0.73+galaxy0) %}
>    - {% icon param-collection %} *"Short read data from your current history"*: `RawData` (output of **Cutadapt** {% icon tool %})
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters to aggregate the FastQC reports
>    - In *"Results"*
>        - {% icon param-select %} *"Which tool was used generate logs?"*: `FastQC`
>        - In *"FastQC output"*
>           - {% icon param-select %} *"Type of FastQC output?"*: `Raw data`
>           - {% icon param-collection %} *"FastQC output"*: `RawData` files (output of **FastQC** {% icon tool %})
> 3. Add a tag `#fastqc-trimmed` to the `Webpage` output from MultiQC and inspect the webpage
{: .hands_on}

The MultiQC plot below shows the result from the full dataset for comparison.

![Adapter Content post-trimming](../../images/rna-seq-reads-to-counts/post_cutadapt_adapter_content.png "Adapter Content post-trimming")
![Sequence Length post-trimming](../../images/rna-seq-reads-to-counts/post_cutadapt_fastqc_sequence_length_distribution_plot.png "Sequence Length post-trimming")

After trimming we can see that:

* No adapter is detected now.
* The reads are no longer all the same length, we now have sequences of different lengths detected.

# Mapping

Now that we have prepared our reads, we can align the reads for our 12 samples. There is an existing reference genome for mouse and we will map the reads to that. The current most widely used version of the mouse reference genome is `mm10/GRCm38` (although note that there is a new version `mm39` released June 2020). Here we will use [**HISAT2**](https://ccb.jhu.edu/software/hisat2/index.shtml) to align the reads. HISAT2 is the descendent of TopHat, one of the first widely-used aligners, but alternative mappers could be used, such as STAR. See the [RNA-seq ref-based tutorial]({{ site.baseurl }}/topics/transcriptomics/tutorials/ref-based/tutorial.html#mapping) for more information on RNA-seq mappers. There are often numerous mapping parameters that we can specify, but usually the default mapping parameters are fine. However, library type (paired-end vs single-end) and library strandness (stranded vs unstranded) require some different settings when mapping and counting, so they are two important pieces of information to know about samples. The mouse data comprises unstranded, single-end reads so we will specify that where necessary. HISAT2 can output a mapping summary file that tells what proportion of reads mapped to the reference genome. Summary files for multiple samples can be summarised with MultiQC. As we’re only using a subset of 1000 reads per sample, aligning should just take a minute or so. To run the full samples from this dataset would take longer.

## Map reads to reference genome

> <hands-on-title>Map reads to reference with <b>HISAT2</b></hands-on-title>
>
> 1. {% tool [HISAT2](toolshed.g2.bx.psu.edu/repos/iuc/hisat2/hisat2/2.2.1+galaxy0) %} with the following parameters:
>    - {% icon param-select %} *"Source for the reference genome"*: `Use a built-in genome`
>        - {% icon param-select %} *"Select a reference genome"*: `mm10`
>    - {% icon param-select %} *"Is this a single or paired library?"*: `Single-end`
>        - {% icon param-collection %} *"FASTA/Q file"*: `Read 1 Output` (output of **Cutadapt** {% icon tool %})
>    - In *"Summary Options"*:
>        - {% icon param-check %} *"Output alignment summary in a more machine-friendly style."*: `Yes`
>        - {% icon param-check %} *"Print alignment summary to a file."*: `Yes`
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters to aggregate the HISAT2 summary files
>    - In *"Results"*
>        - {% icon param-select %} *"Which tool was used generate logs?"*: `HISAT2`
>        - {% icon param-collection %} *"Output of HISAT2"*: `Mapping summary` (output of **HISAT2** {% icon tool %})
> 3. Add a tag `#hisat` to the `Webpage` output from MultiQC and inspect the webpage
{: .hands_on}

> <comment-title>Settings for Paired-end or Stranded reads</comment-title>
>
> - If you have **paired-end** reads
>     - Select *"Is this a single or paired library"* `Paired-end` or `Paired-end Dataset Collection` or `Paired-end data from single interleaved dataset`
> - If you have **stranded** reads
>     - Select *"Specify strand information"*: `Forward (FR)` or `Reverse (RF)`
{: .comment}

The MultiQC plot below shows the result from the full dataset for comparison.

![HISAT2 mapping](../../images/rna-seq-reads-to-counts/hisat2_se_plot.png "HISAT2 mapping")

An important metric to check is the percentage of reads mapped to the reference genome. A low percentage can indicate issues with the data or analysis. Over 90% of reads have mapped in all samples, which is a good mapping rate, and the vast majority of reads have mapped uniquely, they haven't mapped to multiple locations in the reference genome.

It is also good practice to visualise the read alignments in the BAM file, for example using IGV, see the [RNA-seq ref-based tutorial]({{ site.baseurl }}/topics/transcriptomics/tutorials/ref-based/tutorial.html#inspection-of-the-mapping-results).
{: .hands_on}

**HISAT2** generates a BAM file with mapped reads.

{% include topics/sequence-analysis/tutorials/mapping/bam_explanation.md mapper="HISAT2" %}

> <tip-title>Downloading a collection</tip-title>
>
> To download a collection of datasets (e.g. the collection of BAM files) click on the floppy disk icon within the collection. This will download a tar file containing all the datasets in the collection. Note that for BAM files the .bai indexes (required for IGV) will be included automatically in the download.
>
{: .tip}


# Counting

The alignment produces a set of BAM files, where each file contains the read alignments for each sample. In the BAM file, there is a chromosomal location for every read that mapped. Now that we have figured out where each read comes from in the genome, we need to summarise the information across genes or exons. The mapped reads can be counted across mouse genes by using a tool called featureCounts ({% cite liao2013featurecounts %}). featureCounts requires gene annotation specifying the genomic start and end position of each exon of each gene. For convenience, featureCounts contains built-in annotation for mouse (`mm10`, `mm9`) and human (`hg38`, `hg19`) genome assemblies, where exon intervals are defined from the NCBI RefSeq annotation of the reference genome. Reads that map to exons of genes are added together to obtain the count for each gene, with some care taken with reads that span exon-exon boundaries. The output is a count for each Entrez Gene ID, which are numbers such as `100008567`. For other species, users will need to read in a data frame in GTF format to define the genes and exons. Users can also specify a custom annotation file in SAF format. See the tool help in Galaxy, which has an example of what an SAF file should like like, or the Rsubread users guide for more information.


> <comment-title></comment-title>
>
> In this example we have kept many of the default settings, which are typically optimised to work well under a variety of situations. For example, the default setting for featureCounts is that it only keeps reads that uniquely map to the reference genome. For testing differential expression of genes, this is preferred, as the reads are unambigously assigned to one place in the genome, allowing for easier interpretation of the results. Understanding all the different parameters you can change involves doing a lot of reading about the tool that you are using, and can take a lot of time to understand! We won’t be going into the details of the parameters you can change here, but you can get more information from looking at the tool help.
{: .comment}

## Count reads mapped to genes

> <hands-on-title>Count reads mapped to genes with <b>featureCounts</b></hands-on-title>
>
> 1. {% tool [featureCounts](toolshed.g2.bx.psu.edu/repos/iuc/featurecounts/featurecounts/2.0.1+galaxy2) %} with the following parameters:
>    - {% icon param-collection %} *"Alignment file"*: `aligned reads (BAM)` (output of **HISAT2** {% icon tool %})
>    - {% icon param-select %} *"Gene annotation file"*: `featureCounts built-in`
>        - {% icon param-select %} *"Select built-in genome"*: `mm10`
>
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters:
>    - {% icon param-select %} *"Which tool was used generate logs?"*: `featureCounts`
>        - {% icon param-collection %} *"Output of FeatureCounts"*: `featureCounts summary` (output of **featureCounts** {% icon tool %})
> 3. Add a tag `#featurecounts` to the `Webpage` output from MultiQC and inspect the webpage
{: .hands_on}

> <comment-title>Settings for Paired-end or Stranded reads</comment-title>
>
> - If you have **paired-end** reads
>     - Click *"Options for paired-end reads"*
>         - {% icon param-select %} *"Count fragments instead of reads"*: `Enabled; fragments (or templates) will be counted instead of reads`
> - If you have **stranded** reads
>     - {% icon param-select %} Select *"Specify strand information"*: `Stranded (Forward)` or `Stranded (Reverse)`
{: .comment}

The MultiQC plot below shows the result from the full dataset for comparison.

![featureCounts assignments](../../images/rna-seq-reads-to-counts/featureCounts_assignment_plot.png "featureCounts assignments")

> <question-title></question-title>
>
> What % reads are assigned to exons?
>
> > <solution-title></solution-title>
> >
> > ~60-70% of reads are assigned to exons. This is a fairly typical number for RNA-seq.
> >
> {: .solution}
>
{: .question}


The counts for the samples are output as tabular files. Take a look at one. The numbers in the first column of the counts file represent the Entrez gene identifiers for each gene, while the second column contains the counts for each gene for the sample.

## Create count matrix

The counts files are currently in the format of one file per sample. However, it is often convenient to have a count matrix. A count matrix is a single table containing the counts for all samples, with the genes in rows and the samples in columns. The counts files are all within a collection so we can use the Galaxy **Column Join on multiple datasets** tool to easily create a count matrix from the single counts files.

> <hands-on-title>Create count matrix with <b>Column Join on multiple datasets</b></hands-on-title>
>
> 1. {% tool [Column Join on multiple datasets](toolshed.g2.bx.psu.edu/repos/iuc/collection_column_join/collection_column_join/0.0.3) %} with the following parameters:
>    - {% icon param-collection %} *"Tabular files"*: `Counts` (output of **featureCounts** {% icon tool %})
>    - {% icon param-text %} *"Identifier column"*: `1`
>    - {% icon param-text %} *"Number of header lines in each input file"*: `1`
>    - {% icon param-check %} *"Add column name to header"*: `No`
>
{: .hands_on}

Take a look at the output. Note that as the tutorial uses a small subset of the data (~ 1000 reads per sample), to save on processing time, most rows in that matrix will contain all zeros (there will be ~600 non-zero rows). The output for the full dataset is shown below.

![Count matrix](../../images/rna-seq-reads-to-counts/count_matrix.png "Count matrix")

Now it is easier to see the counts for a gene across all samples. The accompanying tutorial, [RNA-seq counts to genes]({% link topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.md %}), shows how gene information (symbols etc) can be added to a count matrix.

# Generating a QC summary report

There are several additional QCs we can perform to better understand the data, to see if it's good quality. These can also help determine if changes could be made in the lab to improve the quality of future datasets.

We'll use a prepared workflow to run the first few of the QCs below. This will also demonstrate how you can make use of Galaxy workflows to easily run and reuse multiple analysis steps. The workflow will run the first three tools: **Infer Experiment**, **MarkDuplicates** and **IdxStats** and generate a **MultiQC** report. You can then edit the workflow if you'd like to add other steps.

> <hands-on-title>Run QC report workflow</hands-on-title>
>
> 1. **Import the workflow** into Galaxy
>    - Copy the URL (e.g. via right-click) of [this workflow]({{ site.baseurl }}{{ page.dir }}workflows/qc_report.ga) or download it to your computer.
>    - Import the workflow into Galaxy
>
>    {% snippet faqs/galaxy/workflows_run_trs.md path="topics/transcriptomics/tutorials/rna-seq-reads-to-counts/workflows/qc_report.ga" title="QC Report" %}
>
> 2. Import this file as type BED file:
>    ```
>    https://sourceforge.net/projects/rseqc/files/BED/Mouse_Mus_musculus/mm10_RefSeq.bed.gz/download
>    ```
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
> 3. Run **Workflow QC Report** {% icon workflow %} using the following parameters:
>    - *"Send results to a new history"*: `No`
>    - {% icon param-file %} *"1: Reference genes"*: the imported RefSeq BED file
>    - {% icon param-collection %} *"2: BAM files"*: `aligned reads (BAM)` (output of **HISAT2** {% icon tool %})
>
>    {% snippet faqs/galaxy/workflows_run.md %}
> 4. Inspect the `Webpage` output from MultiQC
{: .hands_on}


**You do not need to run the hands-on steps below.** They are just to show how you could run the tools individually and what parameters to set.

## Strandness

As far as we know this data is unstranded, but as a sanity check you can check the strandness. You can use RSeQC Infer Experiment tool to "guess" the strandness, as explained in the [RNA-seq ref-based tutorial]({% link topics/transcriptomics/tutorials/ref-based/tutorial.md %}). This is done through comparing the "strandness of reads" with the "strandness of transcripts". For this tool, and many of the other RSeQC ({% cite wang2012rseqc %}) tools, a reference bed file of genes (`reference genes`) is required. RSeQC provides some reference BED files for model organisms. You can import the RSeQC mm10 RefSeq BED file from the link `https://sourceforge.net/projects/rseqc/files/BED/Mouse_Mus_musculus/mm10_RefSeq.bed.gz/download` (and rename to `reference genes`) or import a file from Data if provided. Alternatively, you can provide your own BED file of reference genes, for example from UCSC (see the [Peaks to Genes tutorial]({% link topics/introduction/tutorials/galaxy-intro-peaks2genes/tutorial.md %}). Or the **Convert GTF to BED12** tool can be used to convert a GTF into a BED file.

> <hands-on-title>Check strandness with <b>Infer Experiment</b></hands-on-title>
>
> 1. {% tool [Infer Experiment](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_infer_experiment/2.6.4.1) %} with the following parameters:
>    - {% icon param-collection %} *"Input .bam file"*: `aligned reads (BAM)` (output of **HISAT2** {% icon tool %})
>    - {% icon param-file %} *"Reference gene model"*: `reference genes` (Reference BED file)
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters:
>       - In *"1: Results"*:
>           - {% icon param-select %} *"Which tool was used generate logs?"*: `RSeQC`
>               - {% icon param-select %} *"Type of RSeQC output?"*: `infer_experiment`
>                   - {% icon param-collection %} *"RSeQC infer_experiment output"*: `Infer Experiment output` (output of **Infer Experiment** {% icon tool %})
> 3. Inspect the `Webpage` output from MultiQC
{: .hands_on}

The MultiQC plot below shows the result from the full dataset for comparison.

![Infer Experiment](../../images/rna-seq-reads-to-counts/rseqc_infer_experiment_plot.png "Infer Experiment")

> <question-title></question-title>
>
> Do you think the data is stranded or unstranded?
>
> > <solution-title></solution-title>
> >
> > It is unstranded as approximately equal numbers of reads have aligned to the sense and antisense strands.
> >
> {: .solution}
>
{: .question}


## Duplicate reads

Duplicate reads are usually kept in RNA-seq differential expression analysis as they can come from highly-expressed genes but it is still a good metric to check. A high percentage of duplicates can indicate a problem with the sample, for example, PCR amplification of a low complexity library (not many transcripts) due to not enough RNA used as input. FastQC gives us an idea of duplicates in the reads before mapping (note that it just takes a sample of the data). We can assess the numbers of duplicates in all mapped reads using the **Picard MarkDuplicates** tool. Picard considers duplicates to be reads that map to the same location, based on the start position of where the read maps. In general, we consider normal to obtain up to 50% of duplication.

> <hands-on-title>Check duplicate reads with <b>MarkDuplicates</b></hands-on-title>
>
> 1. {% tool [MarkDuplicates](toolshed.g2.bx.psu.edu/repos/devteam/picard/picard_MarkDuplicates/2.18.2.3) %} with the following parameters:
>    - {% icon param-collection %} *"Select SAM/BAM dataset or dataset collection"*: `aligned reads (BAM)` (output of **HISAT2** {% icon tool %})
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters:
>       - In *"1: Results"*:
>           - {% icon param-select %} *"Which tool was used generate logs?"*: `Picard`
>               - {% icon param-select %} *"Type of Picard output?"*: `Markdups`
>                   - {% icon param-collection %} *"Picard output"*: `MarkDuplicate metrics` (output of **MarkDuplicates** {% icon tool %})
> 3. Inspect the `Webpage` output from MultiQC
{: .hands_on}

The MultiQC plot below shows the result from the full dataset for comparison.

![MarkDups metrics](../../images/rna-seq-reads-to-counts/picard_deduplication.png "MarkDups metrics")

> <question-title></question-title>
>
> Which two samples have the most duplicates detected?
>
> > <solution-title></solution-title>
> >
> > `MCL1-LE` and `MCL1-LF` have the highest number of duplicates in mapped reads compared to the other samples, similar to what we saw in the raw reads with FastQC.
> >
> {: .solution}
>
{: .question}

## Reads mapped to chromosomes

You can check the numbers of reads mapped to each chromosome with the **Samtools IdxStats** tool. This can help assess the sample quality, for example, if there is an excess of mitochondrial contamination. It could also help to check the sex of the sample through the numbers of reads mapping to X/Y or to see if any chromosomes have highly expressed genes.

> <hands-on-title>Count reads mapping to each chromosome with <b>IdxStats</b></hands-on-title>
>
> 1. {% tool [IdxStats](toolshed.g2.bx.psu.edu/repos/devteam/samtools_idxstats/samtools_idxstats/2.0.4) %} with the following parameters:
>    - {% icon param-collection %} *"BAM file"*: `aligned reads (BAM)` (output of **HISAT2** {% icon tool %})
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters:
>       - In *"1: Results"*:
>           - {% icon param-select %} *"Which tool was used generate logs?"*: `Samtools`
>               - {% icon param-select %} *"Type of Samtools output?"*: `idxstats`
>                   - {% icon param-collection %} *"Samtools idxstats output"*: `IdxStats output` (output of **IdxStats** {% icon tool %})
> 3. Inspect the `Webpage` output from MultiQC
{: .hands_on}

The MultiQC plot below shows the result from the full dataset for comparison.

![IdxStats chromsome mappings](../../images/rna-seq-reads-to-counts/samtools-idxstats-mapped-reads-plot.png "IdxStats Chromosome Mappings")
![IdxStats XY ](../../images/rna-seq-reads-to-counts/samtools-idxstats-xy-plot.png "IdxStats X/Y Mappings")

> <question-title></question-title>
>
> 1. What do you think of the chromosome mappings?
> 2. Are the samples male or female? *(If a sample is not in the XY plot it means no reads mapped to Y)*
>
> > <solution-title></solution-title>
> >
> > 1. Some of the samples have very high mapping on chromosome 5. What is going on there?
> > 2. The samples appear to be all female as there are few reads mapping to the Y chromosome. As this is a experiment studying virgin, pregnant and lactating mice if we saw large numbers of reads mapping to the Y chromosome in a sample it would be unexpected and a probable cause for concern.
> >
> {: .solution}
>
{: .question}

## Gene body coverage (5'-3')

The coverage of reads along gene bodies can be assessed to check if there is any bias in coverage. For example, a bias towards the 3' end of genes could indicate degradation of the RNA. Alternatively, a 3' bias could indicate that the data is from a 3' assay (e.g. oligodT-primed, 3'RNA-seq). You can use the RSeQC **Gene Body Coverage (BAM)** tool to assess gene body coverage in the BAM files.

> <hands-on-title>Check coverage of genes with <b>Gene Body Coverage (BAM)</b></hands-on-title>
>
> 1. {% tool [Gene Body Coverage (BAM)](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_geneBody_coverage/2.6.4.3) %} with the following parameters:
>    - *"Run each sample separately, or combine mutiple samples into one plot"*: `Run each sample separately`
>        - {% icon param-collection %} *"Input .bam file"*: `aligned reads (BAM)` (output of **HISAT2** {% icon tool %})
>    - {% icon param-file %} *"Reference gene model"*: `reference genes` (Input dataset)
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters:
>       - In *"1: Results"*:
>           - {% icon param-select %} *"Which tool was used generate logs?"*: `RSeQC`
>               - {% icon param-select %} *"Type of RSeQC output?"*: `gene_body_coverage`
>                   - {% icon param-collection %} *"RSeQC gene_body_coverage output"*: `Gene Body Coverage (BAM) (text)` (output of **Gene Body Coverage (BAM)** {% icon tool %})
> 3. Inspect the `Webpage` output from MultiQC
>
{: .hands_on}

The MultiQC plot below shows the result from the full dataset for comparison.

![Gene Body Coverage](../../images/rna-seq-reads-to-counts/rseqc_gene_body_coverage_plot.png "Gene Body Coverage")

The plot below from the RSeQC website shows what samples with 3'biased coverage would look like.
![Gene Body Coverage comparison](../../images/rna-seq-reads-to-counts/genebodycoverage.png "Gene Body Coverage comparison")

> <question-title></question-title>
>
> What do you think of the coverage across gene bodies in these samples?
>
> > <solution-title></solution-title>
> >
> > It looks good. This plot looks a bit noisy in the small FASTQs but it still shows there's pretty even coverage from 5' to 3' ends with no obvious bias in all the samples.
> >
> {: .solution}
>
{: .question}


## Read distribution across features (exons, introns, intergenic..)

We can also check the distribution of reads across known gene features, such as exons (CDS, 5'UTR, 3'UTR), introns and intergenic regions. In RNA-seq we expect most reads to map to exons rather than introns or intergenic regions. It is also the reads mapped to exons that will be counted so it is good to check what proportions of reads have mapped to those. High numbers of reads mapping to intergenic regions could indicate the presence of DNA contamination.

> <hands-on-title>Check distribution of reads with <b>Read Distribution</b></hands-on-title>
>
> 1. {% tool [Read Distribution](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_read_distribution/2.6.4.1) %} with the following parameters:
>    - {% icon param-collection %} *"Input .bam/.sam file"*: `aligned reads (BAM)` (output of **HISAT2** {% icon tool %})
>    - {% icon param-file %} *"Reference gene model"*: `reference genes` (Input dataset)
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy0) %} with the following parameters:
>       - In *"1: Results"*:
>           - {% icon param-select %} *"Which tool was used generate logs?"*: `RSeQC`
>               - {% icon param-select %} *"Type of RSeQC output?"*: `read_distribution`
>                   - {% icon param-collection %} *"RSeQC read_distribution output"*: `Read Distribution output` (output of **Read Distribution** {% icon tool %})
> 3. Inspect the `Webpage` output from MultiQC
>
{: .hands_on}

The MultiQC plot below shows the result from the full dataset for comparison.

![Read Distribution](../../images/rna-seq-reads-to-counts/rseqc_read_distribution_plot.png "Read Distribution")

> <question-title></question-title>
>
> What do you think of the read distribution?
>
> > <solution-title></solution-title>
> >
> > It looks good, most of the reads have mapped to exons and not many to introns or intergenic regions. The samples have pretty consistent read distribution, albeit with slightly higher numbers of reads mapping to CDS exons for `MCL1-LC` and `MCL1-LD`, and `MCL1-LE` and `MCL1-LF` have more reads mapping to CDS exons than the other samples.
> >
> {: .solution}
>
{: .question}


The MultiQC report can be downloaded by clicking on the floppy disk icon on the dataset in the history.

> <question-title></question-title>
>
> Can you think of any other QCs that could be performed on RNA-seq reads?
>
> > <solution-title></solution-title>
> >
> > The reads could be checked for:
> > * Ribosomal contamination
> > * Contamination with other species e.g. bacteria
> > * GC bias of the mapped reads
> > * This is single-end data but paired-end mapped reads could be checked for fragment size (distance between the read pairs).
> >
> {: .solution}
>
{: .question}


# Conclusion


In this tutorial we have seen how reads (FASTQ files) can be converted into counts. We have also seen QC steps that can be performed to help assess the quality of the data. A follow-on tutorial, [RNA-seq counts to genes]({% link topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.md %}), shows how to perform differential expression and QC on the counts for this dataset.


topic: transcriptomics
tutorial: rna-seq-viz-with-volcanoplot-r
title: Visualization of RNA-Seq results with Volcano Plot in R
difficulty: intermediate
time_estimation: 1H
tools_json: []
requirements_json: []
tags_json: ["interactive-tools"]
content_hash: 9ad1d0149539bc29d08fee674f6d6db7
last_modified: 2026-02-26T21:12:18.575442
zenodo_link: https://zenodo.org/record/2529117
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/rna-seq-viz-with-volcanoplot-r/tutorial.html

content:
The [Volcano plot]({% link topics/transcriptomics/tutorials/rna-seq-viz-with-volcanoplot/tutorial.md %}) tutorial, introduced volcano plots and showed how they can be generated with the Galaxy Volcano plot tool. In this tutorial we show how you can customise a plot using the R script output from the tool.

> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Preparing the inputs

We will use one file for this analysis:

 * **Differentially expressed results file** (genes in rows, and 4 required columns: raw P values, adjusted P values (FDR), log fold change and gene labels).

 If you are following on from the [Volcano plot]({% link topics/transcriptomics/tutorials/rna-seq-viz-with-volcanoplot/tutorial.md %}) tutorial, you already have this file in your History so you can skip to the **Create volcano plot** step below.

## Import data

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this exercise e.g. `Volcano plot R`
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. Import the differentially results table.
>
>    To import the file, there are two options:
>    - Option 1: From a shared data library if available (ask your instructor)
>    - Option 2: From [Zenodo](https://zenodo.org/record/2529117)
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    {% snippet faqs/galaxy/datasets_import_from_data_library.md %}
>
>    - You can paste the link below into the **Paste/Fetch** box:
>
>      ```
>      https://zenodo.org/record/2529117/files/limma-voom_luminalpregnant-luminallactate
>      ```
>
>      Check that the datatype is `tabular`.
>      If the datatype is not `tabular`, please change the file type to `tabular`.
>
>      {% snippet faqs/galaxy/datasets_change_datatype.md datatype="tabular" %}
{: .hands_on}

Click on the {% icon galaxy-eye %} (eye) icon and take a look at the `DE results` file. It should look like below, with 8 columns.

![DE results file](../../images/rna-seq-viz-with-volcanoplot/DE_results.png)

## Create volcano plot

We will create a volcano plot colouring all significant genes. We will call genes significant here if they have FDR < 0.01 and a log2 fold change of 0.58 (equivalent to a fold-change of 1.5). These were the values used in the original paper for this dataset. We will also label the top 10 most significant genes with their gene names. We will select to output the Rscript file which we will then use to edit the plot in R.

> <hands-on-title>Create a Volcano plot</hands-on-title>
>
> 1. {% tool [Volcano Plot](toolshed.g2.bx.psu.edu/repos/iuc/volcanoplot/volcanoplot/0.0.5) %} to create a volcano plot
>    - {% icon param-file %} *"Specify an input file"*: the de results file
>    - {% icon param-file %} *"File has header?"*: `Yes`
>    - {% icon param-select %} *"FDR (adjusted P value)"*: `Column 8`
>    - {% icon param-select %} *"P value (raw)"*: `Column 7`
>    - {% icon param-select %} *"Log Fold Change"*: `Column 4`
>    - {% icon param-select %} *"Labels"*: `Column 2`
>    - {% icon param-text %} *"Significance threshold"*: `0.01`
>    - {% icon param-text %} *"LogFC threshold to colour"*: `0.58`
>    - {% icon param-select %} *"Points to label"*: `Significant`
>        - {% icon param-text %} *"Only label top most significant"*: `10`
>    - In *"Output Options"*:
>        - {% icon param-select %} *"Output Rscript?"*: `Yes`
{: .hands_on}

Click on the PDF file name to check that you see a plot like below.

![Volcano plot labelling top significant genes](../../images/rna-seq-viz-with-volcanoplot/volcanoplot_top10.png){: width="60%"}

Now we will customise the plot by editing the R code in RStudio. You can use Galaxy RStudio if available or another R such as RStudio Cloud or RStudio installed on your computer.

## Import files into R

We'll import the differentially expressed results input file and the RScript into R.

> <hands-on-title>Using datasets from Galaxy</hands-on-title>
>
> 1. Note the history IDs of 1) the differentially expressed results and 2) the RScript in your Galaxy history
>
> 2. {% tool [RStudio](interactive_tool_rstudio) %} in Galaxy provides some special functions such as `gx_get` to import and export files from your history.
>
>    {% snippet faqs/galaxy/interactive_tools_rstudio_launch.md %}
>
> 3. Copy the files we need into our workspace so we can see them in the Files pane.
>
>    ```R
>    file.copy(gx_get(1), "de-results.tsv") # will copy dataset number 1 from your history, use the correct ID for your differentially expressed results dataset.
>    file.copy(gx_get(3), "volcano.R") # will copy dataset number 3 from your history, use the correct ID for your Rscript dataset.
>    ```
>
> 4. Click on `volcano.R` in the Files pane to open it in the Editor pane.
>
{: .hands_on}


We'll have a look at the script.

## Set up script

The first few lines from `# Galaxy settings start` to `# Galaxy settings end` are settings needed to run the Volcano plot tool in Galaxy. We don't need them to run the script in R so we will delete them. If we don't delete the error handling line, the R session will crash if we encounter any error in the code. It's ok as it will resume again where we were but better to not have this happen.

> <hands-on-title>Delete unneeded lines</hands-on-title>
>
> Delete these lines from the top of the script.
>
>    ```R
>    # Galaxy settings start ---------------------------------------------------
>
>    # setup R error handling to go to stderr
>    options(show.error.messages = F, error = function() {cat(geterrmessage(), file = stderr()); q("no", 1, F)})
>
>    # we need that to not crash galaxy with an UTF8 error on German LC settings.
>    loc <- Sys.setlocale("LC_MESSAGES", "en_US.UTF-8")
>
>    # Galaxy settings end -----------------------------------------------------
>    ```
>
{: .hands_on}

We'll check if we have the packages the script needs. We can see the packages used in the lines that have `library(package)`

```R
library(dplyr)
library(ggplot2)
library(ggrepel)
```

When we launched Galaxy RStudio there was information in the Console letting us know that some packages are pre-installed. These packages include `ggplot2` and `dplyr`. In this Galaxy there is a yellow warning banner across the top of the script saying `Package ggrepel required is not installed. Install. Don't Show Again`.
So we just need to install the `ggrepel` package.

> <hands-on-title>Install package</hands-on-title>
>
> Either click on "Install" in the yellow warning banner if present, or in the Console type
>
> ```R
> install.packages('ggrepel')
> ```
>
{: .hands_on}

We need to change the path of the differentially expressed file in the script. The path in the script is `/data/dnb03/galaxy_db/files/4/6/c/dataset_46c498bc-060e-492f-9b42-51908a55e354.dat`. This is a temporary location where the Galaxy Volcano plot tool copied the input file in order to use it, the file no longer exists there. Your path will be different. In the script change this path to `de-results.tsv` like below.

> <hands-on-title>Run script</hands-on-title>
>
> 1. Change the input file path in script
>
>    ```R
>    # change the line
>    results <- read.delim('/data/dnb03/galaxy_db/files/4/6/c/dataset_46c498bc-060e-492f-9b42-51908a55e354.dat', header = TRUE)
>
>    # to
>    results <- read.delim('de-results.tsv', header = TRUE)
>    ```
>
> 2. Highlight the code in the script and run
>
>    > <tip-title>Highlight all code and run shortcuts</tip-title>
>    > - To highlight all code type <kbd>CTRL</kbd>+<kbd>a</kbd> (or <kbd>CMD</kbd>+<kbd>a</kbd>)
>    > - To run type <kbd>CTRL</kbd>+<kbd>Enter</kbd> (or <kbd>CMD</kbd>+<kbd>Enter</kbd>)
>    {: .tip}
>
{: .hands_on}

You should see a file called `volcano_plot.pdf` appear in the Files pane. Click on it to open it and you should see a plot that looks the same as the one we generated with the Volcano Plot tool in Galaxy.

We'll delete the lines below that save the plot to a PDF file. The plots will then be produced in the Plots pane so we can more easily see the different plots we're going to make, without having to keep opening the PDF file.

> <hands-on-title>Produce plots in Plots pane</hands-on-title>
>
> 1. Delete the lines below that save the plot to a PDF file
>
>    ```R
>    # Open PDF graphics device
>    pdf("volcano_plot.pdf")
>
>    # keep the lines in between as they produce the plot
>
>    # Close PDF graphics device
>    dev.off()
>    ```
>
> 2. Highlight the code in the script and run
>
{: .hands_on}

You should now see the plot produced in the Plots pane.

# Customising the plot

## Change points colours

We'll demonstate how you can change the colours. We'll change the colour of the downregulated genes from cornflowerblue to purple. We'll change the upregulated genes from firebrick to orange.

> <hands-on-title>Change colours</hands-on-title>
>
> 1. Edit the line below in the script
>
>    ```R
>    # change the line
>    colours <- setNames(c("cornflowerblue", "grey", "firebrick"), c(down, notsig, up))
>
>    # to
>    colours <- setNames(c("purple", "grey", "orange"), c(down, notsig, up))
>    ```
>
> 2. Highlight the code in the script and run
>
>   ![Smaller points](../../images/rna-seq-viz-with-volcanoplot-r/volcano_points_colours.png)
>
{: .hands_on}


> <tip-title>R colours</tip-title>
>
> If you want to use other colours you can see the built-in R colours with their names in [this cheatsheet](https://www.nceas.ucsb.edu/sites/default/files/2020-04/colorPaletteCheatsheet.pdf).
>
{: .tip}


## Change points size

We'll make the points a bit smaller. We'll change to 0.5.

> <hands-on-title>Change points size</hands-on-title>
>
> 1. Edit the line below in the script
>
>    ```R
>    # change the line
>    geom_point(aes(colour = sig)) +
>
>    # to
>    geom_point(aes(colour = sig), size = 0.5) +
>    ```
>
> 2. Highlight the code in the script and run
>
>   ![Smaller points](../../images/rna-seq-viz-with-volcanoplot-r/volcano_points_size.png)
>
{: .hands_on}


> <question-title></question-title>
>
> How could we change the transparency of the points?
>
>    > <solution-title></solution-title>
>    >
>    > We could use `alpha =`. For example
>    > ```R
>    > geom_point(aes(colour = sig), alpha = 0.5)
>    > ```
>    >
>    {: .solution}
{: .question}


## Change labels size

We'll make the font size of the labels a bit smaller.

> <hands-on-title>Change labels text size</hands-on-title>
>
> 1. Edit the line below in the script
>
>    ```R
>    # change the line
>    geom_text_repel(data = filter(results, labels != ""), aes(label = labels),
>
>    # to
>    geom_text_repel(data = filter(results, labels != ""), aes(label = labels), size = 3,
>    ```
>
> 2. Highlight the code in the script and run
>
>   ![Smaller labels](../../images/rna-seq-viz-with-volcanoplot-r/volcano_labels_size.png)
>
{: .hands_on}


> <question-title></question-title>
>
> How could we change the number of genes labelled from 10 to 20?
>
>    > <solution-title></solution-title>
>    >
>    > We could change the 10 to 20 here
>    > ```R
>    > top <- slice_min(results, order_by = pvalue, n = 20)
>    > ```
>    >
>    {: .solution}
{: .question}



## Change categories

We can change the categories of points we're colouring in the plot. For example, instead of using separate categories for upregulated, downregulated we could just use a single category for significant.

> <hands-on-title>Change categories</hands-on-title>
>
> 1. Change the category names to signif and notsignif
>
>    ```R
>    # change
>    down <- unlist(strsplit('Down,Not Sig,Up', split = ","))[1]
>    notsig <- unlist(strsplit('Down,Not Sig,Up', split = ","))[2]
>    up <- unlist(strsplit('Down,Not Sig,Up', split = ","))[3]
>
>    # to
>    signif <- "Significant"
>    notsignif <- "Not significant"
>    ```
>
> 2. Specify which genes are signif and notsignif
>
>    ```R
>    # change
>    results <- mutate(results, sig = case_when(
>                                fdr < 0.01 & logfc > 0.58 ~ up,
>                                fdr < 0.01 & logfc < -0.58 ~ down,
>                                TRUE ~ notsig))
>
>    # to
>    results <- mutate(results, sig = case_when(
>                                fdr < 0.01 & abs(logfc) > 0.58 ~ signif, # abs() will give us absolute values i.e. all > 0.58 and < -0.58
>                                TRUE ~ notsignif))
>    ```
>
> 3. Specify the colours for signif and notsignif
>
>    ```R
>    # change
>    colours <- setNames(c("purple", "grey", "orange"), c(down, notsig, up))
>
>    # to
>    colours <- setNames(c("grey", "red"), c(notsignif, signif))
>    ```
>
> 4. runHighlight the code in the script and
>
>   ![Categories changed](../../images/rna-seq-viz-with-volcanoplot-r/volcano_categories.png)
>
{: .hands_on}


> <question-title></question-title>
>
> How would you remove the legend from the plot? You can use Google.
>
>    > <solution-title></solution-title>
>    >
>    > If you Google `remove legend ggplot2` you may find a few ways it can be done. One way is
>    >
>    > ```R
>    > p <- p + theme(legend.position = "none")
>    > ```
>    >
>    {: .solution}
{: .question}

You can save the edited script by clicking the {% icon galaxy-save %} icon at the top of the script in RStudio or through File > Save. You can download from Galaxy RStudio from the Files pane by ticking the box beside the script name, then More > Export > Download.

> <tip-title>More plot options</tip-title>
>
> If you enter values in the Volcano Plot Galaxy tool form for Plot options, such as plot title, x and y axis labels or limits, they'll be output in the script. This is one way you could see how to customise these options in the plot.
>
{: .tip}


# Conclusion


In this tutorial we have seen how a volcano plot can be generated and customised using Galaxy and R. You can see some more possible customisations in the [RNA Seq Counts to Viz in R]({% link topics/transcriptomics/tutorials/rna-seq-viz-with-volcanoplot/tutorial.md %}) tutorial and at the [ggrepel website](https://ggrepel.slowkow.com/index.html).


topic: transcriptomics
tutorial: minerva-pathways
title: Pathway analysis with the MINERVA Platform
difficulty: intermediate
time_estimation: 1h
tools_json: []
requirements_json: []
tags_json: []
content_hash: 61422f91bd7c526ff21e74c67714d0c7
last_modified: 2026-02-26T21:12:18.557448
zenodo_link: https://zenodo.org/records/10405036
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/minerva-pathways/tutorial.html

content:
This tutorial is a partial reproduction of {% cite Togami_2022 %} wherein they evaluated mRNA and miRNA in a selection of COVID-19 patients and healthy controls.
While that paper uses a closed source pipeline, we'll be reproducing the analysis with open source tools in Galaxy, using a workflow on WorkflowHub developed for the BY-COVID project.

> <comment-title>Full data</comment-title>
> The original data is available at NCBI under [BioProject PRJNA754796](https://www.ncbi.nlm.nih.gov/bioproject/PRJNA754796)
{: .comment}
>
> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

There are several places you can jump to in this tutorial, using pre-calculated
data. We recommend you jump skipping the data download and counting step, and
skipping to the analysis, as that precludes the slowest and most data intensive
parts of this tutorial. However, the entire process is documented in case you
want to reproduce our work.

## Study Design

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this tutorial
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
> 2. Import the factor table from [Zenodo]({{ page.zenodo_link }})
>
>    ```
>    https://zenodo.org/records/10405036/files/factordata.tabular
>    ```
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
> 4. Check that the datatype
>
>    {% snippet faqs/galaxy/datasets_change_datatype.md datatype="tabular" %}
>
{: .hands_on}

## Analysis

We have split this workflow into three parts, based only on how long the first two portions of the workflow take to execute.
The rough runtime of the workflow portions, when this was being developed, can be broken down as follows:

Step                     | Time
---                      | ---
Data Download            | ~6h
Processing Counts        | ~8h
Analysis & Visualisation | 15m

These numbers were generated on UseGalaxy.eu and may not represent the most
efficient possible computation, as they are executed on a shared cluster that can, at times, be more or less busy.

As such we recommend you skip to the analysis step to progress to the interesting portion of the tutorial. We have provided in the Zenodo record data from the entire analysis,
analysed with the Download & Counts steps that can be skipped.

{% include _includes/cyoa-choices.html option1="Download" option2="Skip" default="Skip"
       text="Choose whether you want to run the time-consuming Download Data step." %}

<div class="Download" markdown=1>

### Data Download

We'll start by downloading our FASTQ files from the [GEO Dataset GSE182152](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE182152)

> <hands-on-title>Download the data from GEO (ETA: 6 Hours)</hands-on-title>
>
> 1. **Import the workflow** into Galaxy
>
>    {% snippet faqs/galaxy/workflows_run_trs.md path="topics/transcriptomics/tutorials/minerva-pathways/workflows/Galaxy-Workflow-BY-COVID__Data_Download.ga" title="Trim and Filter reads" version="1" %}
>
> 1. **Run the workflow** with the following parameters:
>
>    - *"Sample Table"*: `factordata.tabular`
{: .hands_on}

Here we have cut the `SRR*` identifiers from the sample table and downloaded them with `fasterq`, part of the SRA toolkit.

### Counts

With that done, we can start to analyse the data using HISAT2 and featureCounts.
This workflow takes in the RNA Sequencing data we've downloaded previously, before trimming it with cutadapt.
Both the trimmed and untrimmed reads are run through FastQC for visualisation.

<figure>
{% assign wf_counts = site | get_workflow:page, "Galaxy-Workflow-mRNA-Seq_BY-COVID_Pipeline__Counts.ga" %}
<pre class="mermaid">
{{ wf_counts.mermaid }}
</pre>
<figcaption><b>Workflow 1</b>: Counts Workflow for mRNA-Seq BY-COVID Pipeline.</figcaption>
</figure>

The trimmed reads are then handled by HISAT2 for alignment to the reference
human genome, and featureCounts is run for quantification.

This workflow produces a set of featureCounts tables, a set of featureLengths (needed for goseq), and a MultiQC report.

> <hands-on-title>Run the Workflow</hands-on-title>
>
> {% snippet faqs/galaxy/workflows_run_wfh.md title="mRNA-Seq BY-COVID Pipeline" wfhub_id="688" version="1" %}
>
> 1. **Run the workflow** with the following parameters:
>
{: .hands_on}

This workflow produces a handful of outputs: the featureCounts results, and a
MultiQC report. Looking at the report we see generally reasonable quality data.

</div>

### limma

<div class="Skip" markdown=1>

> <hands-on-title>Download the Counts Files</hands-on-title>
>
> 1. Open the Rule Builder
>    - *"Upload data as"*: `Collection(s)`
>    - *"Load tabular data from"*: `Pasted Table`
>    - **Paste** the following table:
>
>      ```
>      https://zenodo.org/records/10405036/files/gene_lengths.tabular	gene_lengths	Gene Lengths
>      https://zenodo.org/records/10405036/files/SRR15462516.featureCounts.tabular	SRR15462516	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462517.featureCounts.tabular	SRR15462517	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462518.featureCounts.tabular	SRR15462518	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462519.featureCounts.tabular	SRR15462519	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462520.featureCounts.tabular	SRR15462520	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462521.featureCounts.tabular	SRR15462521	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462522.featureCounts.tabular	SRR15462522	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462523.featureCounts.tabular	SRR15462523	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462524.featureCounts.tabular	SRR15462524	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462525.featureCounts.tabular	SRR15462525	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462526.featureCounts.tabular	SRR15462526	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462527.featureCounts.tabular	SRR15462527	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462528.featureCounts.tabular	SRR15462528	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462529.featureCounts.tabular	SRR15462529	featureCounts
>      https://zenodo.org/records/10405036/files/SRR15462530.featureCounts.tabular	SRR15462530	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681520.featureCounts.tabular	SRR16681520	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681521.featureCounts.tabular	SRR16681521	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681522.featureCounts.tabular	SRR16681522	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681523.featureCounts.tabular	SRR16681523	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681524.featureCounts.tabular	SRR16681524	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681525.featureCounts.tabular	SRR16681525	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681526.featureCounts.tabular	SRR16681526	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681527.featureCounts.tabular	SRR16681527	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681528.featureCounts.tabular	SRR16681528	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681529.featureCounts.tabular	SRR16681529	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681530.featureCounts.tabular	SRR16681530	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681531.featureCounts.tabular	SRR16681531	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681532.featureCounts.tabular	SRR16681532	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681533.featureCounts.tabular	SRR16681533	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681534.featureCounts.tabular	SRR16681534	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681535.featureCounts.tabular	SRR16681535	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681536.featureCounts.tabular	SRR16681536	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681537.featureCounts.tabular	SRR16681537	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681538.featureCounts.tabular	SRR16681538	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681539.featureCounts.tabular	SRR16681539	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681540.featureCounts.tabular	SRR16681540	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681541.featureCounts.tabular	SRR16681541	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681542.featureCounts.tabular	SRR16681542	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681543.featureCounts.tabular	SRR16681543	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681544.featureCounts.tabular	SRR16681544	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681545.featureCounts.tabular	SRR16681545	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681546.featureCounts.tabular	SRR16681546	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681547.featureCounts.tabular	SRR16681547	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681548.featureCounts.tabular	SRR16681548	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681549.featureCounts.tabular	SRR16681549	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681550.featureCounts.tabular	SRR16681550	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681551.featureCounts.tabular	SRR16681551	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681552.featureCounts.tabular	SRR16681552	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681553.featureCounts.tabular	SRR16681553	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681554.featureCounts.tabular	SRR16681554	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681555.featureCounts.tabular	SRR16681555	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681556.featureCounts.tabular	SRR16681556	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681557.featureCounts.tabular	SRR16681557	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681558.featureCounts.tabular	SRR16681558	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681559.featureCounts.tabular	SRR16681559	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681560.featureCounts.tabular	SRR16681560	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681561.featureCounts.tabular	SRR16681561	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681562.featureCounts.tabular	SRR16681562	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681563.featureCounts.tabular	SRR16681563	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681564.featureCounts.tabular	SRR16681564	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681565.featureCounts.tabular	SRR16681565	featureCounts
>      https://zenodo.org/records/10405036/files/SRR16681566.featureCounts.tabular	SRR16681566	featureCounts
>      ```
>
>    - Click `Build`
>
> 1. From **Rules** menu, select `Add / Modify Column Definitions`
>     - `Add Definition` → `Collection Name` → Select Column `C`
>     - `Add Definition` → `List Identifier(s)` → Select Column `B`
>     - `Add Definition` → `URL` → Column `A`
>
>     > <tip-title>Trouble entering?</tip-title>
>     > 1. Press the {% icon tool %} button by **Rules**
>     > 1. Paste the following JSON into the dialog:
>     >    ```json
>     >    {"rules":[],"mapping":[{"type":"collection_name","columns":[2]},{"type":"list_identifiers","columns":[1],"editing":false},{"type":"url","columns":[0]}],"genome":"hg19"}
>     >    ```
>     > 1. Click Apply
>     {: .tip}
>
> 1. At the bottom of the dialog set `Genome` to `hg19` (it is probably something like "Human Feb 2009 (GRCh37/hg19) (hg19)" but we are focused on that last parenthetical portion).
>
> 1. Click **Upload**
>
{: .hands_on}

</div>

Now we're ready to analyse the counts files. Here we'll take the feature counts dataset collection and merge it into one count matrix through the use of "Column join".
This can then be annotated with the human readable names of the genes. This is all passed to limma for differential expression analysis.

With this result in hand, we're ready to do two further steps: preparing the dataset for goseq, and for analysis in the MINERVA Platform.
Goseq is a tool for gene ontology enrichment analysis, and the MINERVA Platform is a tool for visualising pathway analysis.

<figure>
{% assign wf_counts = site | get_workflow:page, "Galaxy-Workflow-mRNA-Seq_BY-COVID_Pipeline__Analysis.ga" %}
<pre class="mermaid">
{{ wf_counts.mermaid }}
</pre>
<figcaption><b>Workflow 2</b>: Analysis Workflow for mRNA-Seq BY-COVID Pipeline.</figcaption>
</figure>

> <hands-on-title>Analyse the Counts</hands-on-title>
>
> 1. Run the workflow with the Factor Data from the first Hands-on, and the datasets from the workflow or Zenodo download, depending on your path:
>
>    {% snippet faqs/galaxy/workflows_run_wfh.md title="mRNA-Seq BY-COVID Pipeline" wfhub_id="689" version="1" %}
>
{: .hands_on}

You should have a few outputs, namely the `goseq` outputs, and a table ready for visualisation in the MINERVA Platform!

## The MINERVA Platform

The dataset prepared for the MINERVA Platform must be correctly formatted as a tabular dataset (`\t` separated values) like the following, with the dbkey set to `hg19` or `hg38`.
If you've run the above workflow, this should be the case.

```
SYMBOL  logFC              P.Value               adj.P.Val
TRIM25  2.07376444684004   1.2610025125617e-18   3.57368112059986e-15
ACSL1   2.90647033200259   2.71976234791064e-16  3.85390324698937e-13
NBEAL2  2.45952426389725   2.71787290816654e-14  2.56748394058132e-11
MIR150  -2.55304226607428  9.55912390273625e-14  6.74866152827879e-11
SLC2A3  2.95861349227708   1.19066011437523e-13  6.74866152827879e-11
```

The tabular dataset, as prepared above is then used by a dedicated MINERVA plugin ({% cite hoksza_minerva_2019 %}) to visualise the data on-the-fly in the [COVID-19 Disease Map](https://covid19map.elixir-luxembourg.org/minerva/). To visualise and explore the data, follow these steps:

> <hands-on-title>Visualise in MINERVA</hands-on-title>
>
> 1. **Click** to expand the final "MINERVA-Ready Table"
>
> 1. Click on the {% icon galaxy-barchart %} (**Visualize**) icon
>
>    ![A galaxy dataset with the barchart icon circled in red](images/1.png)
>
> 1. Select "display at Minerva (SARS-CoV-2 Minerva Map)"
>
>    ![The galaxy visualisation interface with a big display at minerva banner at the top](images/2.png)
>
>    > <tip-title>MINERVA not listed?</tip-title>
>    > The MINERVA visualisation is only for correctly formatted files with the correct genome (i.e. human, hg19).
>    > If you dont' see MINERVA listed, first check that your dataset is:
>    > 1. recognised as a tabular dataset
>    >
>    >    {% snippet faqs/galaxy/datasets_change_datatype.md datatype="tabular" %}
>    >
>    > 2. Has the correct genome build:
>    >
>    >    {% snippet faqs/galaxy/datasets_change_dbkey.md dbkey="hg19" %}
>    >
>    >    It should be specifically `hg19` not a patch like `hg19Patch5`
>    >
>    > If that still doesn't work, please check that the Galaxy server you are using is updated to 24.0 or later.
>    >
>    {: .tip}
>
{: .hands_on}

### Analysis in the MINERVA Platform

Welcome to the MINERVA Covid-19 Disease Map! It has a similar interface to Galaxy, there is an interaction menu on the left, the main area is where you'll do your investigation,
and on the right are your datasets! In this case, the differentially expressed genes analysed above automatically loaded from Galaxy when you clicked "Display at MINERVA".

![MINERVA main view, a search menu on the left, a view of the disease map in the center showing a colourful cell diagram with signalling and T-Cells and CD8+ and more. On the right is a filtering box for the dataset from Galaxy allowing the user to filter by p-value and FC thresholds. 397 genes have been loaded.](images/3.png)

After the loading time, marked as "Reading Map Elements", the dataset will be visible in the right panel of the COVID-19 Disease Map, with the four corresponding columns specified earlier (see image below). The MINERVA-Galaxy plugin allows you to:

- filter the data table by fold-change (FC) threshold or by p-value (default: adjusted p-value, threshold set to 0.05)
- Search for specific gene symbols to display ("Search" box)
- Select specific differential expression values to display in the map (checkboxes in the data tab)
- Select all entries in the data table for visualisation (Select All)
- Reset the visualisation

The general process of data exploration looks like:

1. In the main map, find pathways with matching entries indicated by blue pins.
1. After selecting what you want to see, browse the COVID-19 Disease Map to explore the pathways with the corresponding expression pattern.
1. Select a pathway of your choice and in the left panel click the "Associated submap" button
1. Explore the expression patterns in the diagram that will be displayed.

> <hands-on-title>Explore TLR pathways</hands-on-title>
>
> 1. Use the **Search** box above the table on the right to search for **TLR**.
> 2. Select all four TLR genes.
>
>    - TLR3
>    - TLR4
>    - TLR7
>    - TLR8
>
> 2. In the main map, find *PAMP Signalling* and click on it. (Note: don't click the blue pin, click the pathway name)
>
>    ![The PAMP signalling box next to the golgi body. A blue map pin is placed upon the red and whitebox.](images/6.png)
>
> 1. In the left panel, click the **Associated submap: PAMP Signalling** button.
> 1. Explore the detailed diagram to examine the expression pattern.
>
>    > <question-title></question-title>
>    > What is the expression pattern of TLR3, TLR7, and TLR8 in the PAMP Signalling pathway?
>    > > <solution-title></solution-title>
>    > > TLR3 and TLR7 are downregulated (cool/blue colour), TLR8 is upregulated (warm/red colour).
>    > > ![image of the aforementioned regulation patterns](images/4.png)
>    > {: .solution}
>    {: .question}
>
>
> 1. Without closing the PAMP Signalling submap, **click** "Select all" to visualise the entire data table
>
>    > <question-title></question-title>
>    > What is the expression pattern downstream of TLR7 and TLR8, namely how are MYD88 and IRAK4 regulated?
>    > > <solution-title></solution-title>
>    > > MYD88 and IRAK4 are strongly and weakly upregulated, respectively, despite TLR7 downregulation.
>    > > ![image of the aforementioned regulation patterns](images/5.png)
>    > {: .solution}
>    {: .question}
>
{: .hands_on}

For further analysis in the MINERVA Platform, a [full user guide is available](https://covid19map.elixir-luxembourg.org/minerva/resources/other/user_guide.pdf)


topic: transcriptomics
tutorial: rna-seq-genes-to-pathways
title: 3: RNA-seq genes to pathways
difficulty: intermediate
time_estimation: 2h
tools_json: []
requirements_json: []
tags_json: ["mouse"]
content_hash: b15414241d9ce8401ee7f75aeb8e453e
last_modified: 2026-02-26T21:12:18.572128
zenodo_link: https://zenodo.org/record/2596382
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/rna-seq-genes-to-pathways/tutorial.html

content:
Sometimes there is quite a long list of genes to interpret after a differential expression analysis, and it is usually infeasible to go through the list one gene at a time trying to understand it’s biological function. A common downstream procedure is gene set testing, which aims to understand which pathways/gene networks the differentially expressed genes are implicated in. There are many different gene set testing methods that can be applied and it can be useful to try several.

The purpose of this tutorial is to demonstrate how to perform gene set testing using tools in Galaxy. The data comes from a Nature Cell Biology paper, [EGF-mediated induction of Mcl-1 at the switch to lactation is essential for alveolar cell survival](https://www.ncbi.nlm.nih.gov/pubmed/25730472)), Fu et al. 2015. That study examined the expression profiles of basal and luminal cells in the mammary gland of virgin, pregnant and lactating mice (see Figure below). How to generate differentially expressed genes from reads (FASTQs) for this dataset is covered in the accompanying tutorials [RNA-seq reads to counts]({% link topics/transcriptomics/tutorials/rna-seq-reads-to-counts/tutorial.md %}) and [RNA-seq counts to genes]({% link topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.md %}). This tutorial is inspired by material from the COMBINE R RNAseq workshop [here](http://combine-australia.github.io/RNAseq-R/06-rnaseq-day1.html) and the Cancer Research UK workshop [here](https://bioinformatics-core-shared-training.github.io/cruk-summer-school-2018/RNASeq2018/html/06_Gene_set_testing.nb.html).

![Tutorial Dataset](../../images/rna-seq-reads-to-counts/mouse_exp.png "Tutorial Dataset")


> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

{% snippet faqs/galaxy/analysis_results_may_vary.md %}

We will use several files for this analysis:

 * **Differentially expressed results files** (genes in rows, logFC and P values in columns)
 * **Sample information** file (sample id, group)
 * **Gene lengths file** (genes, lengths)
 * **Filtered counts file** (genes in rows, counts for samples in columns, with lowly expressed genes removed)
 * **Gene sets file** for MSigDB Hallmark collection for mouse (rdata)


# Import data

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this RNA-seq exercise e.g. `RNA-seq genes to pathways`
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. **Import the files**, there are two options:
>    - Option 1: From a shared data library if available (ask your instructor)
>
>      {% snippet faqs/galaxy/datasets_import_from_data_library.md %}
>
>    - Option 2: From [Zenodo](https://zenodo.org/record/2596382)
>
>      {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    You can paste the names and links below into the Upload tool:
>
>    ```
>    https://zenodo.org/record/2596382/files/limma-voom_basalpregnant-basallactate
>    https://zenodo.org/record/2596382/files/limma-voom_luminalpregnant-luminallactate
>    https://zenodo.org/record/2596382/files/seqdata
>    https://zenodo.org/record/2596382/files/mouse_hallmark_sets
>    https://zenodo.org/record/2596382/files/factordata
>    https://zenodo.org/record/2596382/files/limma-voom_filtered_counts
>    ```
>
> 3. Add a tag called `#basal` to the `limma-voom_basalpregnant-basallactate` and a tag called `#luminal` to the `limma-voom_luminalpregnant-luminallactate` files.
>
>    {% snippet faqs/galaxy/datasets_add_tag.md %}
>
{: .hands_on}

# Gene Set Testing

## Gene Ontology testing with **goseq**

We would like to know if there are biological categories that are enriched among the differentially expressed genes. To do this we will perform a Gene Ontology analysis, similar to the [RNA-seq ref-based tutorial]({% link topics/transcriptomics/tutorials/ref-based/tutorial.md %}).

[Gene Ontology (GO)](http://www.geneontology.org/) analysis is widely used to reduce complexity and highlight biological processes in genome-wide expression studies. However, standard methods give biased results on RNA-seq data due to over-detection of differential expression for long and highly-expressed transcripts.

The [goseq tool](https://bioconductor.org/packages/release/bioc/vignettes/goseq/inst/doc/goseq.pdf) provides methods for performing GO analysis of RNA-seq data, taking length bias into account. The methods and software used by goseq are equally applicable to other category based tests of RNA-seq data, such as KEGG pathway analysis.

goseq needs 2 files as inputs:
- a **differentially expressed genes** file. Information for all genes tested for differential expression (all genes after filtering lowly expressed). This file should have 2 columns:
    - the Gene IDs (unique within the file)
    - True (differentially expressed) or False (not differentially expressed)
- a **gene lengths** file. Information to correct for potential length bias in differentially expressed genes. This file should have 2 columns:
    - the Gene IDs (unique within the file)
    - the gene lengths

We need a table of differentially expressed (DE) results for goseq. Here we will use two tables, one for each of the basal and luminal pregnant vs lactate results. This is so we can compare results for the two cell types. These tables were output from the limma-voom tool but DE tables from edgeR or DESeq2 could also be used. For this dataset we will call genes differentially expressed if they have an adjusted P value below 0.01. We can use the gene lengths from the counts table in GEO (provided as a file called `seqdata` in Zenodo). But if we didn't have that we could use a tool like **featureCounts** {% icon tool %} to output a gene lengths file. The `seqdata` file contains >20k genes, but we only want the ~15k we have in our differentially expressed genes file. So we will join the lengths file with the differentially expressed genes file, keeping only the length information for genes present in the differentially expressed genes file. We can then cut out the columns we need for the two inputs (gene id, length) (gene id, DE status) and as a bonus they will both be sorted in the same order, which is what we need for goseq.

To generate the two input files we will use:
* **Compute** to add a column to the DE tables, that gives genes meeting our adj.P threshold the value "True" and all other genes the value "False".
* **Join two Datasets** to add the gene length information to the differentially expressed genes, matching on gene ids
* **Cut** to extract the two columns for the differentially expressed genes information
* **Cut** to extract the two columns for the gene length information


> <hands-on-title>Prepare the two inputs for GOSeq</hands-on-title>
>
> 1. **Compute an expression on every row** {% icon tool %} with the following parameters:
>    - {% icon param-text %} *"Add expression"*: `bool(c8<0.01)` (adj.P < 0.01)
>    - {% icon param-file %} *"as a new column to"*: the `limma-voom_basalpregnant-basallactate` file
>    - {% icon param-select %} *"Skip a header line"*: `yes`
>    - {% icon param-select %} *"The new column name"*: `Status`
> 2. **Join two Datasets side by side on a specified field** {% icon tool %} with the following parameters:
>    - {% icon param-file %} *"Join"*: output of **Compute** {% icon tool %}
>    - {% icon param-select %} *"using column"*: `Column: 1`
>    - {% icon param-file %} *"with"* the `seqdata` file
>    - {% icon param-select %} *"and column"*: `Column: 1`
>    - {% icon param-select %} *"Keep the header lines"*: `Yes`
> 3. **Cut columns from a table** {% icon tool %} with the following parameters:
>    - {% icon param-text %} *"Cut columns"*: `c1,c10` (the gene ids and DE status)
>    - {% icon param-select %} *"Delimited by"*: `Tab`
>    - {% icon param-file %} *"From"*: output of **Join** {% icon tool %}
>    - Rename to `goseq DE status`
> 4. **Cut columns from a table** {% icon tool %} with the following parameters:
>    - {% icon param-text %} *"Cut columns"*: `c1,c12` (the gene ids and lengths)
>    - {% icon param-select %} *"Delimited by"*: `Tab`
>    - {% icon param-file %} *"From"*: output of **Join** {% icon tool %}
>    - Rename to `goseq gene lengths`
{: .hands_on}

We now have the two required input files for goseq.

> <hands-on-title>Perform GO analysis</hands-on-title>
>
> 1. **goseq** {% icon tool %} with
>    - {% icon param-file %} *"Differentially expressed genes file"*: `goseq DE status`
>    - {% icon param-file %} *"Gene lengths file"*: `goseq gene lengths`
>    - {% icon param-select %} *"Gene categories"*:  `Get categories`
>       - {% icon param-select %} *"Select a genome to use"*:  `Mouse(mm10)`
>       - {% icon param-select %} *"Select Gene ID format"*:  `Entrez Gene ID`
>       - {% icon param-check %} *"Select one or more categories"*: `GO: Biological Process`
>    - *"Output Options"*
>        - {% icon param-check %} *"Output Top GO terms plot?"* `Yes`
{: .hands_on}

goseq generates a big table with the following columns for each GO term:
1. `category`: GO category
2. `over_rep_pval`: *p*-value for over representation of the term in the differentially expressed genes
3. `under_rep_pval`: *p*-value for under representation of the term in the differentially expressed genes
4. `numDEInCat`: number of differentially expressed genes in this category
5. `numInCat`: number of genes in this category
6. `term`: detail of the term
7. `ontology`: MF (Molecular Function - molecular activities of gene products), CC (Cellular Component - where gene products are active), BP (Biological Process - pathways and larger processes made up of the activities of multiple gene products)
8. `p.adjust.over_represented`: *p*-value for over representation of the term in the differentially expressed genes, adjusted for multiple testing with the Benjamini-Hochberg procedure
9. `p.adjust.under_represented`: *p*-value for over representation of the term in the differentially expressed genes, adjusted for multiple testing with the Benjamini-Hochberg procedure

To identify categories significantly enriched/unenriched below some p-value cutoff, it is necessary to use the adjusted *p*-value.

A plot of the top 10 over-represented GO terms (by *p*-value) can be output from the goseq tool to help visualise results. Click on the `Top over-represented GO terms plot` PDF in the history. It should look similar to below.

![Basal Plot](../../images/rna-seq-genes-to-pathways/basal_top_GO.png "Basal pregnant vs lactating top 10 GO terms")


> <question-title></question-title>
> Can you generate the plot of top 10 GO terms for the luminal differentially expressed genes? Tip: You could use the Rerun button for each step (as the parameters are already selected) and choose the luminal file as input.
>
> > <solution-title></solution-title>
> >
> > Running goseq on the luminal file should give a plot similar to below.
> > ![Luminal Plot](../../images/rna-seq-genes-to-pathways/luminal_top_GO.png "Luminal pregnant vs lactating top 10 GO terms")
> >
> {: .solution}
{: .question}

For more on GO analysis, including how to simplify GO results and visualize with GO graphs, see the [GO Enrichment tutorial]({{ site.baseurl }}/topics/transcriptomics/tutorials/goenrichment/tutorial.html).

## Gene Set Enrichment Analysis with **fgsea**

Gene Set Enrichment Analysis (GSEA) [(Subramanian et al., 2005)](https://www.ncbi.nlm.nih.gov/pubmed/16199517) is a widely used method that determines whether a set of genes is enriched in a list of differentially expressed genes. Unlike the previous method with goseq, no threshold is applied for what is considered "differentially expressed", all genes are used. If a gene set falls at either the top (over-expressed) or bottom (under-expressed) of the list it is said to be enriched. [fgsea](https://www.biorxiv.org/content/early/2016/06/20/060012) is a faster implementation of the GSEA method. fgsea requires a ranked list of genes and some gene sets to test.

The [Molecular Signatures Database (MSigDB)](http://software.broadinstitute.org/gsea/msigdb/index.jsp) contains curated collections of gene sets that are commonly used in a GSEA analysis. They can be downloaded from the [Broad website](http://software.broadinstitute.org/gsea/downloads.jsp). But these collections are only of human gene sets. If working with another species you would need to first map the genes to their human orthologues. However, MSigDB versions for mouse are provided [by the Smyth lab here](http://bioinf.wehi.edu.au/software/MSigDB/index.html). There are several MSigDB collections, we'll use the [Hallmark collection](https://www.cell.com/cell-systems/fulltext/S2405-4712(15)00218-5), which contains 50 gene sets. According to MSigDB, "each gene set in the hallmark collection consists of a “refined” gene set, derived from multiple “founder” sets, that conveys a specific biological state or process and displays coherent expression. The hallmarks effectively summarize most of the relevant information of the original founder sets and, by reducing both variation and redundancy, provide more refined and concise inputs for gene set enrichment analysis".  We'll use the mouse Hallmark file provided in Zenodo, originally downloaded from http://bioinf.wehi.edu.au/software/MSigDB/mouse_H_v5p2.rdata.

There are several ways we could choose to rank our genes, we could rank by log-fold change (most upregulated to most downregulated) but that doesn't take into account any error in the log fold change value. Another way is to use the "signed fold change" which is to rank by the sign of the fold change multiplied by the P value (as described [here](http://genomespot.blogspot.com/2014/09/data-analysis-step-8-pathway-analysis.html). We could also use the t statistic that's output from limma, as that takes into account the log-fold change and it's standard error, see [here](https://support.bioconductor.org/p/6124/) for more explanation. We'll use the t statistic to rank here.

> <hands-on-title>Perform gene set enrichment with fgsea</hands-on-title>
>
> 1. **Cut columns from a table** {% icon tool %} with
>    - {% icon param-text %} *"Cut columns"*: `c1,c6` (the Entrez gene ids and t-statistic)
>    - {% icon param-select %} *"Delimited by"*: `Tab`
>    - {% icon param-file %} *"From"*: the `limma-voom_basalpregnant-basallactate` file
> 2. **Sort data in ascending or descending order** {% icon tool %} with
>    - {% icon param-file %} *"Sort Query"*: the output of **Cut** {% icon tool %}
>    - {% icon param-text %} *"Number of header lines"*: `1`
>    - *"Column selections"*:
>        - {% icon param-select %} *"on column"*: `Column: 2`
>        - {% icon param-select %} *"in"*: `Descending order`
>        - {% icon param-select %} *"Flavor"*: `Fast numeric sort (-n)`
> 3. **fgsea** {% icon tool %} with
>    - {% icon param-file %} *"Ranked Genes"*: the output of **Sort** {% icon tool %}
>    - {% icon param-check %} *"File has header?"*: `Yes`
>    - {% icon param-file %} *"Gene Sets"*: `mouse_hallmark_sets` (this should be `rdata` format, if not, see how to change it in the Tip below)
>    - {% icon param-text %} *"Minimum Size of Gene Set"*: `15`
>    - {% icon param-check %} *"Output plots"*: `Yes`
>
> {% snippet faqs/galaxy/datasets_change_datatype.md %}
>
{: .hands_on}

fgsea outputs a table of results containing a list of pathways with P values and enrichment scores. It can also output a summary table plot of the top pathways such as the one shown below for the `basallpregnant-basallactate` contrast below.

![fgsea Table](../../images/rna-seq-genes-to-pathways/fgsea_table_basal.png "fgsea Summary table")

An enrichment plot of the each of the top pathways can also be produced, one is shown below. The barcode pattern shows where the genes in the set are found in the list of ranked genes. Most of the bars to the left indicate enrichment of the set at the top of the ranked list of genes (upregulated) and most bars towards the right indicate enrichment at the bottom of the list (downregulated). The enrichment score reflects the degree to which the genes are enriched at the top or bottom of the list.

![fgsea Enrichment](../../images/rna-seq-genes-to-pathways/fgsea_enrichplot.png "fgsea Enrichment plot")

> <question-title></question-title>
> Can you run fgsea on the luminal contrast and generate the fgsea summary table plot?
>
> > <solution-title></solution-title>
> >
> > Running fgsea on the luminal file should give a plot similar to below.
> > ![fgsea Luminal](../../images/rna-seq-genes-to-pathways/fgsea_table_luminal.png "fgsea Summary table for luminal")
> >
> {: .solution}
{: .question}

## Ensemble gene set enrichment analyses with **EGSEA**

The ensemble of genes set enrichment analyses (EGSEA) [(Alhamdoosh et al, 2017)](https://www.ncbi.nlm.nih.gov/pubmed/27694195) is a method developed for RNA-seq data that combines results from multiple algorithms and calculates collective gene set scores, to try to improve the biological relevance of the highest ranked gene sets. EGSEA has built-in gene sets from MSigDB and KEGG for human and mouse. We'll show here how it can be used with the MSigDB Hallmark collection and KEGG pathways. For input we need a count matrix and EGSEA will perform a limma-voom analysis before gene set testing. We can use the provided filtered counts file output from limma, where the low count genes have been filtered out (output from limma by selecting *"Output Filtered Counts Table?"*: `Yes`). We just need to remove the gene symbol and description columns. We also need a symbols mapping file containing just the Entrez ids and symbols, which we can generate from the filtered counts file. The third input we need is a factors information file, containing what groups the samples belong to, we can use the same one from the tutorial [RNA-seq counts to genes]({{ site.baseurl }}/topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.html). EGSEA provides twelve base methods and we will select eleven, all except roast, as the fry method is a fast approximation of roast.

> <hands-on-title>Perform ensemble gene set testing with EGSEA</hands-on-title>
>
> 1. **Cut columns from a table (cut)** {% icon tool %} with the following parameters:
>      - {% icon param-file %} *"File to cut"*: `limma-voom filtered counts`
>      - {% icon param-select %} *"Operation"*: `Discard`
>      - {% icon param-select %} *"List of fields"*: Select `Column:2`, `Column:3`
>      - Rename to `EGSEA counts`
> 2. **Cut columns from a table (cut)** {% icon tool %} with the following parameters:
>      - {% icon param-file %} *"File to cut"*: `limma-voom filtered counts`
>      - {% icon param-select %} *"Operation"*: `Keep`
>      - {% icon param-select %} *"List of fields"*: Select `Column:1`, `Column:2`
>      - Rename to `EGSEA anno`
> 3. **EGSEA** {% icon tool %} with the following parameters:
>      - {% icon param-select %} *"Count Files or Matrix?*": `Single Count Matrix`
>          - {% icon param-file %} *"Count Matrix"*: Select `EGSEA counts`
>      - {% icon param-check %} *"Input factor information from file?"*: `Yes`
>          - {% icon param-file %} *"Factor File"*: Select `factordata`
>      - {% icon param-file %} *"Symbols Mapping file"*: `EGSEA anno`
>      - {% icon param-text %} *"Contrast of Interest"*: `basalpregnant-basallactate`
>      - {% icon param-select %} *"Species"*: `mouse`
>      - {% icon param-check %} *"Gene Set Testing Methods"*: Tick `camera`, `safe`, `gage`, `zscore`, `gsva`, `globaltest`, `ora`, `ssgsea`, `padog`, `plage`, `fry`
>      - {% icon param-check %} *"MSigDB Gene Set Collections"*: `H: hallmark gene sets`
>      - {% icon param-check %} *"KEGG Pathways"*: `Metabolism` and `Signalling`
>      - {% icon param-check %} *"Download KEGG pathways?"*: `Yes`
>      - {% icon param-check %} *"I certify that I am not using this tool for commercial purposes"*: `Yes`
{: .hands_on}

This generates a table of results, and a report. Contained within the report are plots, such as heatmaps of the top ranked pathways, as shown below. Note that we see some similar pathways in the results here as with the fgsea analysis.

![EGSEA heatmaps](../../images/rna-seq-genes-to-pathways/EGSEA_heatmaps.png "EGSEA heatmaps")

KEGG pathway diagrams are generated if KEGG pathways are selected, as shown below. These show the expression values of the genes overlaid, genes upregulated in the contrast are shown in red, downregulated genes in blue. Ribosome was one of the top GO terms identified for the basal pregnant vs lactate contrast and here we see ribosome pathways are in the top ranked KEGG pathways.

![EGSEA KEGG](../../images/rna-seq-genes-to-pathways/EGSEA_KEGG.png "EGSEA KEGG pathways")

> <question-title></question-title>
> Can you run EGSEA on the luminal contrast identify the top KEGG gene sets? Tip: you could use the rerun button and replace the "Contrast of Interest" with the name of the luminal contrast.
>
> > <solution-title></solution-title>
> >
> > Running EGSEA on the luminal file should give top KEGG gene sets similar to below.
> > ![EGSEA KEGG luminal](../../images/rna-seq-genes-to-pathways/EGSEA_KEGG_luminal.png "EGSEA KEGG pathways for luminal")
> >
> {: .solution}
{: .question}

# Conclusion


In this tutorial we have seen some gene set testing methods that can be used to interpret lists of differentially expressed genes. Multiple methods can be used to help identify pathways of interest and to provide complementary ways of visualising results. This follows on from the accompanying tutorials, [RNA-seq reads to counts]({% link topics/transcriptomics/tutorials/rna-seq-reads-to-counts/tutorial.md %}) and [RNA-seq counts to genes]({% link topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.md %}), that showed how to turn reads (FASTQs) into differentially expressed genes for this dataset. For further reading on analysis of RNA-seq count data and the methods used here, see the articles; RNA-seq analysis is easy as 1-2-3 with limma, Glimma and edgeR [(Law et al. 2016)](https://f1000research.com/articles/5-1408/v2) and From reads to genes to pathways: differential expression analysis of RNA-Seq experiments using Rsubread and the edgeR quasi-likelihood pipeline [(Chen, Lun, Smyth 2016)](https://f1000research.com/articles/5-1438/v2).


topic: transcriptomics
tutorial: rna-seq-viz-with-cummerbund
title: Visualization of RNA-Seq results with CummeRbund
difficulty: intermediate
time_estimation: 1h
tools_json: []
requirements_json: []
tags_json: []
content_hash: d54d892c6929d0f7c15c5a8604ff099b
last_modified: 2026-02-26T21:12:18.574308
zenodo_link: https://zenodo.org/record/1001880
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/rna-seq-viz-with-cummerbund/tutorial.html

content:
RNA-Seq analysis helps researchers annotate new genes and splice variants, and provides cell- and context-specific quantification of gene expression. RNA-Seq data, however, are complex and require both computer science and mathematical knowledge to be managed and interpreted.

Visualization techniques are key to overcome the complexity of RNA-Seq data, and represent valuable tools to gather information and insights.

In this tutorial we will visualize RNA-seq data from the [CuffDiff](http://cole-trapnell-lab.github.io/cufflinks/cuffdiff/) tool.

> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Reasons for visualizing RNA-Seq results

To make sense of the available RNA-Seq data, and overview the condition-specific gene expression levels of the provided samples, we need to visualize our results. Here we will use [CummeRbund](http://compbio.mit.edu/cummeRbund/).

CummeRbund is an open-source tool that simplifies the analysis of a CuffDiff RNA-Seq output. In particular, it helps researchers with:
- managing, integrating, and visualizing the data produced by CuffDiff
- simplifying data exploration
- providing a bird's-eye view of the expression analysis by describing relationships betweeen genes, transcripts, transcription start sites, and protein-coding regions
- exploring subfeatures of individual genes or gene-sets
- creating publication-ready plots

A typical workflow for the visualization of RNA-Seq data involving CummeRbund:

![workflow](../../images/transcriptomics_images/cummerbund-rna-seq-viz-with-cummerbund.png)

CummeRbund reads your RNA-Seq results from a [SQLite](https://www.sqlite.org/) database. This database has to be created using CuffDiff's SQLite output option.

> <details-title>SQLite output with CuffDiff</details-title>
>
> Instruct CuffDiff to organize its output in a SQLite database to be read CummeRbund.
>
> ![SQLite output](../../images/transcriptomics_images/cummerbund-cuffdiff-set-sqlite.png)
{: .details}

# Importing RNA-Seq result data

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
> 2. Import the [`CuffDiff SQLite`](https://zenodo.org/record/1001880/files/CuffDiff_SQLite_database.sqlite) dataset
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    Rename the dataset to "RNA-Seq SQLite result data"
>
>    {% snippet faqs/galaxy/datasets_rename.md name="RNA-Seq SQLite result data" %}
>
> By default, when data is imported via its link, Galaxy names it with its URL.
{: .hands_on}

CuffDiff's output data is organized in a SQLite database, so we need to extract it to be able to see what it looks like.

For this tutorial, we are interested in CuffDiff's tested transcripts for differential expression.

> <hands-on-title>Extract CuffDiff results</hands-on-title>
>
> 1. **Extract CuffDiff** {% icon tool %} with the following parameters
>   - *"Select tables to output"*: `Transcript differential expression testing`
>
> 2. Inspect the table
>
>    > <tip-title>Inspecting the content of a file in Galaxy</tip-title>
>    >
>    > * Click on the {% icon galaxy-eye %} (eye) icon ("View data") on the right of the file name in the history
>    > * Inspect the content of the file
>    {: .tip}
>
> Each entry is a differentially expressed gene, which is described in terms of the following attributes.
>
> - *test_id*: A unique identifier describing the transcript being tested
> - *gene_id*: The identifier of the gene being tested
> - *gene*: The name of the gene being tested
> - *locus*: The genomic coordinates of the gene transcript being tested
> - *sample_1*: Label of the 1st sample
> - *sample_2*: Label of the 2nd sample
> - *status*: The test's status:
>   - "OK" if test successful
>   - "NOTEST" if not enough alignments for testing
>   - "LOWDATA" if too complex or shallowly sequenced
>   - "HIDATA" if too many fragments in locus
>   - "FAIL" if a numerical exception prevented testing
> - *value_1*: The gene's FPKM in sample_1
> - *value_2*: The gene's FPKM in sample_2
> - *log2(fold_change)*: The log<sub>2</sub> of the fold change (sample_1/sample_2). This reports the expression difference between condition one (sample_1) and condition two (sample_2)
> - *test_stat*: The test statistic's value, used to determine the significance of the observed change in FPKM
> - *p_value*: The uncorrected p-value of the test statistic
> - *q_value*: The False-discovery-rate-adjusted p-value of the test statistic
> - *significant*: "yes" or "no", depending on whether the p_value is greater then the FDR after Benjamini-Hochberg correction for multiple-testing. This tells whether the difference between the expression levels in condition one (sample_1) and condition two (sample_2) is significant
>
> We want to keep only the *significant differentially expressed* genes.
>
>    > <question-title></question-title>
>    >
>    > 1. How to retain only the significant differentially expressed genes?
>    > 2. Which column stores this information?
>    >
>    > > <solution-title></solution-title>
>    > > 1. We need to filter on the column storing the record's significance
>    > > 2. Column 14
>    > {: .solution }
>    {: .question}
{: .hands_on}

# Filtering and sorting

We now want to highlight the transcripts whose expression difference, the log<sub>2</sub>(fold_change), has been statistically assessed as both high and significant.

> <hands-on-title>Extract CuffDiff's significant differentially expressed genes</hands-on-title>
>
> 1. **Filter** {% icon tool %} with the following parameters
>   - *"Filter"*: the extracted table from the previous step
>   - *"With following condition"*: an appropriate filter over the target column (see questions below when in doubt)
>   - *"Number of header lines to skip"*: the number of rows used for the table's header
>
>    > <question-title></question-title>
>    > 1. What column stores the information of significance for each record?
>    > 2. Which conditional expression has to be set to filter all records on the selected column?
>    > 3. How many rows are allocated for the table's header?
>    > 4. How many entries were originally stored in the table? And how many after the filtering operation?
>    >
>    > > <solution-title></solution-title>
>    > > 1. Column 14
>    > > 2. c14=='yes'
>    > > 3. 1
>    > > 4. ~140,000 (before filtering) vs. 219 (after filtering)
>    > {: .solution }
>    {: .question}
>
>  Review the meaning of each column, and look at your data.
>
>  - The differential expression values are stored in column 10
>  - The statistical score, assessing the differential expression significance, is stored in column 13
>  We will sort all records on the basis of their Q-score (column 13) and log<sub>2</sub>(fold_change).
>
> 2. **Sort** {% icon tool %}: with the following parameters
>   - *"Sort Dataset"*: the filtered table
>   - *"on column"*: `13`
>   - *"with flavor"*: `Numerical sort`
>   - *"everything in"*: `Ascending order`
>   - {% icon param-repeat %} **Insert Column selection**, and parameterize the Sort tool to sort on column 10. Be careful of the sorting order!
>   - Are there any rows allocated for the table's header? In that case, set "Number of header lines to skip" accordingly!
>
>    > <question-title></question-title>
>    > 1. Which gene transcript has been statistically assessed as both high and significant?
>    >
>    > > <solution-title></solution-title>
>    > > 1 LIMCH1
>    > {: .solution }
>    {: .question}
{: .hands_on}

# CummeRbund

CummeRbund generates two outputs:
- The plot, which visualizes our RNA-Seq results of interest
- The [ggplot](http://had.co.nz/ggplot2/) object responsible for generating the plot

In this section we will parametrize CummeRbund to create different kinds of plots from our input data.

> <hands-on-title>Visualization</hands-on-title>
>
> 1. **CummeRbund** {% icon tool %} with the following parameters
>    - {% icon param-repeat %}  **Insert plots**
>      - *"Width"*: `800`
>      - *"Height"*: `600`
>      - *"Plot type"*: `Expression Plot`
>        - *"Expression levels to plot"*:`Isoforms`
>        - *"Gene ID"*: `NDUFV1`
{: .hands_on}

The input data used to create the visualization comprise 3 conditions: *hits7* (Patient 1), *hits8* (Patient 2), and *hits9* (Control).

Our first CummeRbund plot is the "Expression Plot" of the isoforms of gene NDUFV1, which shows the expression differences of isoforms NM_001166102 and NM_007103 among the three conditions. Error bars capture the variability of the distribution of FPKM values: the broader the distribution of FPKM values, the larger the corresponding error bar.

![Expression plot](../../images/transcriptomics_images/cummerbund-expression-plot.png)

Our plot has a modest number of isoforms, and is therefore easy to read. However, with a high number of isoforms and expression variability among different conditions, the plot can look very busy. We can therefore change the visualization type by selecting another type of plot. Let's change visualization.

> <hands-on-title>Visualization</hands-on-title>
>
> 1. **CummeRbund** {% icon tool %} with the following parameters
>    - {% icon param-repeat %} Click on *"Insert plots"*
>      - *"Width"*: `800`
>      - *"Height"*: `600`
>      - *"Plot type"*: `Expression Bar Plot`
>        - *"Expression levels to plot"*:`Isoforms`
>        - *"Gene ID"*: `NDUFV1`
{: .hands_on}

![Expression bar plot](../../images/transcriptomics_images/cummerbund-expression-bar-plot.png)

The Expression Bar Plot of gene NDUFV1's replicates NM_001166102 and NM_007103, shows the expression changes across the three aforementioned conditions.

> <comment-title></comment-title>
>
> These plots are shown also in [this](https://vimeo.com/channels/884356/128265982) Galaxy video tutorial.
{: .comment}

Let's now create a heatmap to plot the expression levels of the significant differentially expressed gene isoforms obtained from our filter and sort operations.
As a showcase example, let's consider only the top 5 differentially expressed genes.

> <hands-on-title>Visualization</hands-on-title>
>
> 1. **CummeRbund** {% icon tool %} with the following parameters
>    - {% icon param-repeat %}  **Insert plots**
>      - *"Width"*: `800`
>      - *"Height"*: `600`
>      - *"Plot type"*: `Heatmap`
>        - *"Expression levels to plot"*: `Isoforms`
>        - *"Gene ID"*: `LIMCH1`
>        - *"Gene ID"*: `IFNL2`
>        - {% icon param-repeat %} **Insert Genes**
>          - *"Gene ID"*: `CXCL11`
>        - {% icon param-repeat %} **Insert Genes**
>          - *"Gene ID"*: `NUB1`
>      - *"Cluster by"*: `Both`
>
{: .hands_on}

![Expression bar plot](../../images/transcriptomics_images/cummerbund-heatmap.png)

Heatmap of significant differentially expressed isoforms of genes LIMCH1, IFNL2, CXCL11, NUB1. Differences in up- and down-regulation of certain gene isoforms across Patient 1 (hits7), Patient 2 (hits8), and Control (hits9), are visible in the lower and upper part of the heatmap.

> <comment-title></comment-title>
>
> For more sophisticated visualizations of your RNA-Seq analysis results, try selecting different CummeRbund plot options and parametrizations. Have a look also at CummeRbund's [manual](http://compbio.mit.edu/cummeRbund/manual_2_0.html). Alternatively, you can modify a plot's style by changing CummeRbund's R output! CummeRbund's R outputs are *ggplot* objects. Look at the [ggplot2 documentation](https://github.com/tidyverse/ggplot2) to learn how to change fonts, colors, error bars, and more.
{: .comment}

# Conclusion


Visualization tools help researchers making sense of data, providing a bird's-eye view of the underlying analysis results.
In this tutorial we overviewed the advantages of visualizing RNA-Seq results with CummeRbund, and gained insights on CuffDiff's big-data output by plotting information relative to the most significant differentially expressed genes in our RNA-Seq analysis.


topic: transcriptomics
tutorial: ref-based
title: Reference-based RNA-Seq data analysis
difficulty: introductory
time_estimation: 8h
tools_json: []
requirements_json: []
tags_json: []
content_hash: 93e8970250c68f2a13d743dfdd47354b
last_modified: 2026-02-26T21:12:18.562088
zenodo_link: https://zenodo.org/record/6457007
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/ref-based/tutorial.html

content:
In recent years, RNA sequencing (in short RNA-Seq) has become a very widely used technology to analyze the continuously changing cellular transcriptome, i.e. the set of all RNA molecules in one cell or a population of cells. One of the most common aims of RNA-Seq is the profiling of gene expression by identifying genes or molecular pathways that are differentially expressed (DE) between two or more biological conditions. This tutorial demonstrates a computational workflow for the detection of DE genes and pathways from RNA-Seq data by providing a complete analysis of an RNA-Seq experiment profiling *Drosophila* cells after the depletion of a regulatory gene.

In the study of {% cite brooks2011conservation %}, the authors identified genes and pathways regulated by the *Pasilla* gene (the *Drosophila* homologue of the mammalian splicing regulators Nova-1 and Nova-2 proteins) using RNA-Seq data. They depleted the *Pasilla* (*PS*) gene in *Drosophila melanogaster* by RNA interference (RNAi). Total RNA was then isolated and used to prepare both single-end and paired-end RNA-Seq libraries for treated (PS depleted) and untreated samples. These libraries were sequenced to obtain RNA-Seq reads for each sample. The RNA-Seq data for the treated and the untreated samples can be compared to identify the effects of *Pasilla* gene depletion on gene expression.

In this tutorial, we illustrate the analysis of the gene expression data step by step using 7 of the original datasets:

- 4 untreated samples: [GSM461176](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM461176), [GSM461177](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM461177), [GSM461178](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM461178), [GSM461182](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM461182)
- 3 treated samples (*Pasilla* gene depleted by RNAi): [GSM461179](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM461179), [GSM461180](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM461180), [GSM461181](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSM461181)

Each sample constitutes a separate biological replicate of the corresponding condition (treated or untreated). Moreover, two of the treated and two of the untreated samples are from a paired-end sequencing assay, while the remaining samples are from a single-end sequencing experiment.

> <comment-title>Full data</comment-title>
>
> The original data are available at NCBI Gene Expression Omnibus (GEO) under accession number [GSE18508](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE18508). The raw RNA-Seq reads have been extracted from the Sequence Read Archive (SRA) files and converted into FASTQ files.
{: .comment}
>
> <agenda-title></agenda-title>
>
> In this tutorial, we will deal with:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Data upload

In the first part of this tutorial we will use the files for 2 out of the 7 samples to demonstrate how to calculate read counts (a measure of the gene expression) from FASTQ files (quality control, mapping, read counting). We provide the FASTQ files for the other 5 samples if you want to reproduce the whole analysis later.

In the second part of the tutorial, read counts of all 7 samples are used to identify and visualize the DE genes, gene families and molecular pathways due to the depletion of the *PS* gene.

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this RNA-Seq exercise
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
> 2. Import the FASTQ file pairs from [Zenodo]({{ page.zenodo_link }}) or a data library:
>    - `GSM461177` (untreated): `GSM461177_1` and `GSM461177_2`
>    - `GSM461180` (treated): `GSM461180_1` and `GSM461180_2`
>
>    ```text
>    {{ page.zenodo_link }}/files/GSM461177_1.fastqsanger
>    {{ page.zenodo_link }}/files/GSM461177_2.fastqsanger
>    {{ page.zenodo_link }}/files/GSM461180_1.fastqsanger
>    {{ page.zenodo_link }}/files/GSM461180_2.fastqsanger
>    ```
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    {% snippet faqs/galaxy/datasets_import_from_data_library.md %}
>
>    > <comment-title></comment-title>
>    >
>    > Note that these are the full files for the samples and ~1.5Gb each so it may take some minutes to import.
>    >
>    > For a quicker run-through of the FASTQ steps a small subset of each FASTQ file (~5Mb) can be found here on [Zenodo]({{ page.zenodo_link }}):
>    >
>    > ```text
>    > {{ page.zenodo_link }}/files/GSM461177_1_subsampled.fastqsanger
>    > {{ page.zenodo_link }}/files/GSM461177_2_subsampled.fastqsanger
>    > {{ page.zenodo_link }}/files/GSM461180_1_subsampled.fastqsanger
>    > {{ page.zenodo_link }}/files/GSM461180_2_subsampled.fastqsanger
>    > ```
>    >
>    {: .comment}
>
> 3. Check that the datatype is `fastqsanger` (e.g. **not** `fastq`). If it is not, please change the datatype to `fastqsanger`.
>
>    {% snippet faqs/galaxy/datasets_change_datatype.md datatype="fastqsanger" %}
>
> 4. Create a paired collection named `2 PE fastqs`, name your pairs with the sample name followed by the attributes: `GSM461177_untreat_paired` and `GSM461180_treat_paired`.
>
>    {% snippet faqs/galaxy/collections_build_list_paired.md %}
>
{: .hands_on}

{% include topics/sequence-analysis/tutorials/quality-control/fastq_question.md %}

The reads are raw data from the sequencing machine without any pretreatments. They need to be assessed for their quality.

# Quality control

During sequencing, errors are introduced, such as incorrect nucleotides being called. These are due to the technical limitations of each sequencing platform. Sequencing errors might bias the analysis and can lead to a misinterpretation of the data. Adapters may also be present if the reads are longer than the fragments sequenced and trimming these may improve the number of reads mapped.

Sequence quality control is therefore an essential first step in your analysis. We will use similar tools as described in the ["Quality control" tutorial]({% link topics/sequence-analysis/tutorials/quality-control/tutorial.md %}):
- [Falco](https://falco.readthedocs.io/en/latest/), which is an efficiency-optimized rewrite of [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/), to create a report of sequence quality
- [MultiQC](https://multiqc.info/) ({% cite ewels2016multiqc %}) to aggregate generated reports
- [Cutadapt](https://cutadapt.readthedocs.io/en/stable/guide.html) ({% cite marcel2011cutadapt %}) to improve the quality of sequences via trimming and filtering.

Unfortunately the current version of MultiQC (the tool we use to combine reports) does not support list of pairs collections.
We will first need to transform our list of pairs to a simple list.

> <details-title>What does this mean exactly?</details-title>
>
> The current situation is on top and the **Flatten collection** tool will transform it to the situation displayed on bottom:
> ![Flatten](../../images/ref-based/flatten.png "Flatten the list of pairs to list")
{: .details}

> <hands-on-title>Quality control</hands-on-title>
>
> 1. {% tool [Flatten collection](__FLATTEN__) %} with the following parameters convert the list of pairs into a simple list:
>     - *"Input Collection"*: `2 PE fastqs`
>
> 2. {% tool [Falco](toolshed.g2.bx.psu.edu/repos/iuc/falco/falco/1.2.4+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Raw read data from your current history"*: Output of **Flatten collection** {% icon tool %} selected as **Dataset collection**
>
>    {% snippet faqs/galaxy/tools_select_collection.md %}
>
> 3. Inspect the webpage output of **Falco** {% icon tool %} for the `GSM461177_untreat_paired` sample (forward and reverse)
>
>    > <question-title></question-title>
>    >
>    > What is the read length?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > The read length of both mates is 37 bp.
>    > >
>    > {: .solution}
>    >
>    {: .question}
>
>    As it is tedious to inspect all these reports individually we will combine them with {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %}.
>
> 4. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %} to aggregate the Falco reports with the following parameters:
>    - In *"Results"*:
>        - *"Results"*
>            - *"Which tool was used generate logs?"*: `FastQC` (**Falco** is a drop-in replacement for *FastQC* and we can pass its output to MultiQC as if it had been generated by the original tool.)
>                - In *"FastQC output"*:
>                    - {% icon param-repeat %} *"Insert FastQC output"*
>                        - {% icon param-collection %} *"FastQC output"*: `Falco on collection N: RawData` (output of **Falco** {% icon tool %})
>
> 5. Inspect the webpage output from MultiQC for each FASTQ
>
>    > <question-title></question-title>
>    >
>    > 1. What do you think of the quality of the sequences?
>    > 2. What should we do?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > 1. Everything seems good for 3 of the files. The `GSM461177_untreat_paired` have 10.6 millions of paired sequences and `GSM461180_treat_paired` 12.3 millions of paired sequences. But in `GSM461180_treat_paired_reverse` (reverse reads of GSM461180) the quality decreases quite a lot at the end of the sequences.
>    > >
>    > >    All files except `GSM461180_treat_paired_reverse` have a high proportion of duplicated reads (expected in RNA-Seq data).
>    > >
>    > >    ![Sequence Counts](../../images/ref-based/fastqc_sequence_counts_plot.png "Sequence Counts")
>    > >
>    > >    The "Per base sequence quality" is globally good with a slight decrease at the end of the sequences. For `GSM461180_treat_paired_reverse`, the decrease is quite large.
>    > >
>    > >    ![Sequence Quality](../../images/ref-based/fastqc_per_base_sequence_quality_plot.png "Sequence Quality")
>    > >
>    > >    The mean quality score over the reads is quite high, but the distribution is slightly different for `GSM461180_treat_paired_reverse`.
>    > >
>    > >    ![Per Sequence Quality Scores](../../images/ref-based/fastqc_per_sequence_quality_scores_plot.png "Per Sequence Quality Scores")
>    > >
>    > >    Reads do not really follow a normal distribution of GC content, except for `GSM461180_treat_paired_reverse`.
>    > >
>    > >    ![Per Sequence GC Content](../../images/ref-based/fastqc_per_sequence_gc_content_plot.png "Per Sequence GC Content")
>    > >
>    > >    The proportion of N in the reads (bases which could not be called) is low.
>    > >
>    > >    ![Per base N content](../../images/ref-based/fastqc_per_base_n_content_plot.png "Per base N content")
>    > >
>    > >    Duplicated sequences: >10 to >500
>    > >
>    > >    ![Sequence Duplication Levels](../../images/ref-based/fastqc_sequence_duplication_levels_plot.png "Sequence Duplication Levels")
>    > >
>    > >    There are almost no known adapters and overrepresented sequences.
>    > >
>    > > 2. If the quality of the reads is poor, we should:
>    > >    1. Check what is wrong and think about possible reasons for the poor read quality: it may come from the type of sequencing or what we sequenced (high quantity of overrepresented sequences in transcriptomics data, biased percentage of bases in Hi-C data)
>    > >    2. Ask the sequencing facility about it
>    > >    3. Perform some quality treatment (taking care not to lose too much information) with some trimming or removal of bad reads
>    > >
>    > {: .solution}
>    {: .question}
>
{: .hands_on}

We should trim the reads to get rid of bases that were sequenced with high uncertainty (i.e. low quality bases) at the read ends, and also remove the reads of overall bad quality.

{% include topics/sequence-analysis/tutorials/quality-control/paired_end_question.md forward="GSM461177_untreat_paired_forward" reverse="GSM461177_untreat_paired_reverse" %}

> <hands-on-title>Trimming FASTQs</hands-on-title>
>
> 1. {% tool [Cutadapt](toolshed.g2.bx.psu.edu/repos/lparsons/cutadapt/cutadapt/5.2+galaxy0) %} with the following parameters to trim low quality sequences:
>    - *"Single-end or Paired-end reads?"*: `Paired-end Collection`
>       - {% icon param-collection %} *"Paired Collection"*: `2 PE fastqs`
>    - In *"Other Read Trimming Options"*
>       - *"Quality cutoff(s) (R1)"*: `20`
>    - In *"Read Filtering Options"*
>       - *"Minimum length (R1)"*: `20`
>    - In *"Additional outputs to generate"*
>       - Select: `Report: Cutadapt's per-adapter statistics. You can use this file with MultiQC.`
>
>      {% include topics/sequence-analysis/tutorials/quality-control/trimming_question.md %}
>
> 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %} to aggregate the Cutadapt reports with the following parameters:
>    - In *"Results"*:
>        - {% icon param-repeat %} *"Results"*
>            - *"Which tool was used generate logs?"*: `Cutadapt/Trim Galore!`
>               - {% icon param-collection %} *"Output of Cutadapt"*: `Cutadapt on collection N: Report` (output of **Cutadapt** {% icon tool %}) selected as **Dataset collection**
>
>    > <question-title></question-title>
>    >
>    > 1. How many sequence pairs have been removed because at least one read was shorter than the length cutoff?
>    > 2. How many basepairs have been removed from the forward reads because of bad quality? And from the reverse reads?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > 1. 147,810 (1.4%) reads were too short for `GSM461177_untreat_paired` and 1,101,875 (9%) for `GSM461180_treat_paired`.
>    > >    ![Cutadapt Filtered reads](../../images/ref-based/cutadapt_filtered_reads_plot.png "Cutadapt Filtered reads")
>    > > 2. The MultiQC output only provides the proportion of bp trimmed in total, not for each Read. To get this information, you need to go back to the individual reports. For `GSM461177_untreat_paired`, 5,072,810 bp have been trimmed from the forward reads (Read 1) and 8,648,619 bp from the reverse reads (Read 2) because of quality. For `GSM461180_treat_paired`, 10,224,537 bp from the forward reads and 51,746,850 bp from the reverse reads. This is not a surprise; we saw that at the end of the reads the quality was dropping more for the reverse reads than for the forward reads, especially for `GSM461180_treat_paired`.
>    > {: .solution }
>    {: .question}
{: .hands_on}

# Mapping

To make sense of the reads, we need to first figure out where the sequences originated from in the genome, so we can then determine to which genes they belong. When a reference genome for the organism is available, this process is known as aligning or "mapping" the reads to the reference. This is equivalent to solving a jigsaw puzzle, but unfortunately, not all pieces are unique.

> <comment-title></comment-title>
>
> Do you want to learn more about the principles behind mapping? Follow our [training]({% link topics/sequence-analysis/tutorials/mapping/tutorial.md %}).
{: .comment}

In this study, the authors used *Drosophila melanogaster* cells. We should therefore map the quality-controlled sequences to the reference genome of *Drosophila melanogaster*.

{% include topics/sequence-analysis/tutorials/mapping/ref_genome_explanation.md answer_3="The genome of *Drosophila melanogaster* is known and assembled and it can be used as the reference genome in this analysis. Note that new versions of reference genomes may be released if the assembly improves, for this tutorial we are going to use the release 6 of the *Drosophila melanogaster* reference genome assembly [(dm6)](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4383921/)."%}

With eukaryotic transcriptomes most reads originate from processed mRNAs lacking introns:

![Types of RNA-Seq reads](../../images/ref-based/rna-seq-reads.png "The types of RNA-seq reads (adaption of the Figure 1a from {% cite kim2015hisat %}): reads that mapped entirely within an exon (in red), reads spanning over 2 exons (in blue), read spanning over more than 2 exons (in purple)")

Therefore they cannot be simply mapped back to the genome as we normally do for DNA data. Spliced-awared mappers have been developed to efficiently map transcript-derived reads against a reference genome:

![Splice-aware alignment](../../images/transcriptomics_images/splice_aware_alignment.png "Principle of spliced mappers: (1) identification of the reads spanning a single exon, (2) identification of the splicing junctions on the unmapped reads")

> <details-title>More details on the different spliced mappers</details-title>
>
> Several spliced mappers have been developed over the past years to process the explosion of RNA-Seq data.
>
> [**TopHat**](https://ccb.jhu.edu/software/tophat/index.shtml) ({% cite trapnell2009tophat %}) was one of the first tools designed specifically to address this problem. In **TopHat** reads are mapped against the genome and are separated into two categories: (1) those that map, and (2) those that are initially unmapped (IUM). "Piles" of reads representing potential exons are extended in search of potential donor/acceptor splice sites and potential splice junctions are reconstructed. IUMs are then mapped to these junctions.
>
> ![TopHat](../../images/transcriptomics_images/tophat.png "TopHat (Figure 1 from {% cite trapnell2009tophat %})")
>
> **TopHat** has been subsequently improved with the development of **TopHat2** ({% cite kim2013tophat2 %}):
>
> ![TopHat2](../../images/transcriptomics_images/13059_2012_Article_3053_Fig6_HTML.jpg "TopHat2 (Figure 6 from {% cite kim2013tophat2 %})")
>
> To further optimize and speed up spliced read alignment, [**HISAT2**](https://ccb.jhu.edu/software/hisat2/index.shtml) ({% cite kim2019graph %}) was developed. It uses a hierarchical graph [FM](https://en.wikipedia.org/wiki/FM-index) (HGFM) index, representing the entire genome and eventual variants, together with overlapping local indexes (each spanning ~57 kb) that collectively cover the genome and its variants. This allows to find initial seed locations for potential read alignments in the genome using global index and to rapidly refine these alignments using a corresponding local index:
>
> ![Hierarchical Graph FM index in HISAT/HISAT2](../../images/transcriptomics_images/hisat.png "Hierarchical Graph FM index in HISAT/HISAT2 (Figure S8 from {% cite kim2015hisat %})")
>
> A part of the read (blue arrow) is first mapped to the genome using the global FM index. **HISAT2** then tries to extend the alignment directly utilizing the genome sequence (violet arrow). In (**a**) it succeeds and this read is aligned as it completely resides within an exon. In (**b**) the extension hits a mismatch. Now **HISAT2** takes advantage of the local FM index overlapping this location to find the appropriate mapping for the remainder of this read (green arrow). The (**c**) shows a combination these two strategies: the beginning of the read is mapped using global FM index (blue arrow), extended until it reaches the end of the exon (violet arrow), mapped using local FM index (green arrow) and extended again (violet arrow).
>
> [**STAR** aligner](https://github.com/alexdobin/STAR) ({% cite dobin2013star %}) is a fast alternative for mapping RNA-Seq reads against a reference genome utilizing an uncompressed [suffix array](https://en.wikipedia.org/wiki/Suffix_array). It operates in two stages. In the first stage it performs a seed search:
>
> ![STAR's seed search](../../images/transcriptomics_images/star.png "STAR's seed search (Figure 1 from {% cite dobin2013star %})")
>
> Here a read is split between two consecutive exons. **STAR** starts to look for a maximum mappable prefix (MMP) from the beginning of the read until it can no longer match continuously. After this point it starts to look for a MMP for the unmatched portion of the read (**a**). In the case of mismatches (**b**) and unalignable regions (**c**) MMPs serve as anchors from which to extend alignments.
>
> At the second stage **STAR** stitches MMPs to generate read-level alignments that (contrary to MMPs) can contain mismatches and indels. A scoring scheme is used to evaluate and prioritize stitching combinations and to evaluate reads that map to multiple locations. **STAR** is extremely fast but requires a substantial amount of RAM to run efficiently.
>
{: .details}

## Mapping

We will map our reads to the *Drosophila melanogaster* genome using **STAR** ({% cite dobin2013star %}).

> <hands-on-title>Spliced mapping</hands-on-title>
>
> 1. Import the Ensembl gene annotation for *Drosophila melanogaster* (`Drosophila_melanogaster.BDGP6.32.109_UCSC.gtf.gz`) from the Shared Data library if available or from [Zenodo]({{ page.zenodo_link }}/files/Drosophila_melanogaster.BDGP6.32.109_UCSC.gtf.gz) into your current Galaxy history
>
>    ```text
>    {{ page.zenodo_link }}/files/Drosophila_melanogaster.BDGP6.32.109_UCSC.gtf.gz
>    ```
>
>    1. Rename the dataset if necessary
>    2. Verify that the datatype is `gtf` (or `gtf.gz`) and not `gff`.
>
>    > <comment-title>How to get annotation file?</comment-title>
>    >
>    > Annotation files from model organisms may be available on the Shared Data library (the path to them will change from one Galaxy server to the other). You could also retrieve the annotation file from UCSC (using **UCSC Main** tool).
>    >
>    > To generate this specific file, the annotation file was downloaded from Ensembl which provides a more comprehensive database of transcripts and was further adapted to make it work with the dm6 genome which is installed on compatible Galaxy servers.
>    >
>    {: .comment}
>
> 2. {% tool [RNA STAR](toolshed.g2.bx.psu.edu/repos/iuc/rgrnastar/rna_star/2.7.11b+galaxy0) %} with the following parameters to map your reads on the reference genome:
>    - *"Single-end or paired-end reads"*: `Paired-end (as collection)`
>       - {% icon param-collection %} *"RNA-Seq FASTQ/FASTA paired reads"*: the `Cutadapt on collection N: Reads` (output of **Cutadapt** {% icon tool %})
>    - *"Custom or built-in reference genome"*: `Use a built-in index`
>       - *"Reference genome with or without an annotation"*: `use genome reference without builtin gene-model but provide a gtf`
>           - *"Select reference genome"*: `Fly (Drosophila melanogaster): dm6 Full`
>           - {% icon param-file %} *"Gene model (gff3,gtf) file for splice junctions"*: the imported `Drosophila_melanogaster.BDGP6.32.109_UCSC.gtf.gz`
>           - *"Length of the genomic sequence around annotated junctions"*: `36` (This parameter should be length of reads - 1)
>               - *"Per gene/transcript output"*: `Per gene read counts (GeneCounts)`
>    - *"Compute coverage"*:
>       - `Yes in bedgraph format`
>
> 3. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %} to aggregate the STAR logs with the following parameters:
>    - In *"Results"*:
>        - *"Results"*
>            - *"Which tool was used generate logs?"*: `STAR`
>                - In *"STAR output"*:
>                    - {% icon param-repeat %} *"Insert STAR output"*
>                        - *"Type of STAR output?"*: `Log`
>                            - {% icon param-collection %} *"STAR log output"*: `RNA STAR on collection N: log` (output of **RNA STAR** {% icon tool %})
>
>    > <question-title></question-title>
>    >
>    > 1. What percentage of reads are mapped exactly once for both samples?
>    > 2. What are the other available statistics?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > 1. More than 83% for `GSM461177_untreat_paired` and 79% for `GSM461180_treat_paired`. We can proceed with the analysis since only percentages below 70% should be investigated for potential contamination.
>    > > 2. We also have access to the number and percentage of reads that are mapped at several location, mapped at too many different location, not mapped because too short.
>    > >
>    > >    ![STAR Alignment Scores](../../images/ref-based/star_alignment_plot.png "Alignment scores")
>    > >
>    > >    We could have been probably more strict in the minimal read length to avoid these unmapped reads because of length.
>    > {: .solution}
>    >
>    {: .question}
{: .hands_on}

According to the **MultiQC** report, about 80% of reads for both samples are mapped exactly once to the reference genome. We can proceed with the analysis since only percentages below 70% should be investigated for potential contamination. Both samples have a low (less than 10%) percentage of reads that mapped to multiple locations on the reference genome. This is in the normal range for Illumina short-read sequencing, but may be lower for newer long-read sequencing datasets that can span larger repeated regions in the reference genome and will be higher for 3' end libraries.

The main output of **STAR** is a BAM file.

{% include topics/sequence-analysis/tutorials/mapping/bam_explanation.md mapper="RNA STAR" %}

## Inspection of the mapping results

The BAM file contains information for all our reads, making it difficult to inspect and explore in text format. A powerful tool to visualize the content of BAM files is the Integrative Genomics Viewer (**IGV**, {% cite robinson2011integrative %}). Alternatively or complementarily, you can use JBrowse2, a genome browser which is directly integrated into Galaxy.

> <hands-on-title>Inspection of mapping results with IGV</hands-on-title>
>
> 1. Install [**IGV**](https://software.broadinstitute.org/software/igv/download) (if not already installed)
> 2. Start IGV locally
> 3. Click on the collection `RNA STAR on collection N: mapped.bam` (output of **RNA STAR** {% icon tool %})
> 4. Expand the {% icon param-file %} `GSM461177_untreat_paired` file.
> 5. Click on the {% icon galaxy-barchart %} visualize icon in the `GSM461177` file block.
> 6. In the center panel click on the `local` in `display with IGV (local, D. melanogaster (dm6))`to load the reads into the IGV browser
>    > <comment-title></comment-title>
>    >
>    > In order for this step to work, you will need to have either IGV or [Java Web Start](https://www.java.com/en/download/faq/java_webstart.xml)
>    > installed on your machine. However, the questions in this section can also be answered by inspecting the IGV screenshots below.
>    >
>    > Check the [IGV documentation](https://software.broadinstitute.org/software/igv/AlignmentData) for more information.
>    >
>    {: .comment}
>
> 6. **IGV** {% icon tool %}: Zoom to `chr4:540,000-560,000` (Chromosome 4 between 540 kb to 560 kb)
>
>    > <question-title></question-title>
>    >
>    > ![Screenshot of the IGV view on Chromosome 4](../../images/transcriptomics_images/junction_igv_screenshot.png "Screenshot of IGV on Chromosome 4")
>    >
>    > 1. What information appears at the top as grey peaks?
>    > 2. What do the connecting lines between some of the aligned reads indicate?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > 1. The coverage plot: the sum of mapped reads at each position
>    > > 2. They indicate junction events (or splice sites), *i.e.* reads that are mapped across an intron
>    > >
>    > {: .solution}
>    {: .question}
>
> 7. **IGV** {% icon tool %}: Inspect the splice junctions using a **Sashimi plot**
>
>    > <comment-title>Creation of a Sashimi plot</comment-title>
>    >
>    > - Right click on the BAM file (in IGV)
>    > - Select **Sashimi Plot** from the menu
>    >
>    {: .comment}
>    >
>    > <question-title></question-title>
>    >
>    > ![Screenshot of a Sashimi plot of Chromosome 4](../../images/transcriptomics_images/star_igv_sashimi.png "Screenshot of a Sashimi plot of Chromosome 4")
>    >
>    > 1. What does the vertical red bar graph represent? What about the arcs with numbers?
>    > 2. What do the numbers on the arcs mean?
>    > 3. Why do we observe different stacked groups of blue linked boxes at the bottom?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > 1. The coverage for each alignment track is plotted as a red bar graph. Arcs represent observed splice junctions, *i.e.*, reads spanning introns.
>    > > 2. The numbers refer to the number of observed junction reads.
>    > > 3. The different groups of linked boxes on the bottom represent the different transcripts from the genes at this location which are present in the GTF file.
>    > >
>    > {: .solution}
>    {: .question}
>    >
>    > <comment-title></comment-title>
>    >
>    > Check the [IGV documentation on Sashimi plots](https://software.broadinstitute.org/software/igv/Sashimi) to find some clues
>    {: .comment}
>
{: .hands_on}


> <hands-on-title>Inspection of mapping results with JBrowse2</hands-on-title>
>
> 1. {% tool [JBrowse2](toolshed.g2.bx.psu.edu/repos/fubar/jbrowse2/jbrowse2/3.6.5+galaxy1) %} with the following parameters:
>    - *"Action"*: `New JBrowse Instance`
>    - In *"Genome Assembly"*:
>        - {% icon param-repeat %} *"Insert Genome Assembly"*
>            - *"Reference genome to display"*: `Use a built-in genome`
>                - *"Select a reference genome"*: `Fly (Drosophila melanogaster): dm6 Full`
>            - *"Default region to display"*: `chr4:540000..560000`
>            - In *"Track Category"*:
>                - {% icon param-repeat %} *"Insert Track Category"*
>                    - *"Track Category Label"*: `BAM`
>                    - In *"Track"*:
>                        - {% icon param-repeat %} *"Insert Track"*
>                            - *"Track Type"*: `BAM Pileups`
>                                - *"BAM Track Data"*: `Use data from history`
>                                    - {% icon param-collection %} *"BAM Track Data"*: `RNA STAR on collection N: mapped.bam` (output of **RNA STAR** {% icon tool %})
>                - {% icon param-repeat %} *"Insert Track Category"*
>                    - *"Track Category Label"*: `Genes`
>                    - In *"Track"*:
>                        - {% icon param-repeat %} *"Insert Track"*
>                            - *"Track Type"*: `GFF/GFF3/BED Features`
>                                - *"GFF/GFF3/BED Track Data"*: `Use data from history`
>                                   - {% icon param-file %} *"GFF/GFF3/BED Track Data"*: `Drosophila_melanogaster.BDGP6.32.109.gtf.gz`
>
> 2. Inspect the result by clicking the eye-icon.
>
>    > <question-title></question-title>
>    >
>    > ![Screenshot of the JBrowse2 view on Chromosome 4](../../images/ref-based/junction_jbrowse2_screenshot.png "Screenshot of JBrowse2 on Chromosome 4")
>    >
>    > 1. What information appears at the top as grey peaks?
>    > 2. What do the connecting lines between some of the aligned reads indicate?
>    >
>    > > <solution-title></solution-title>
>    > >
>    > > 1. The coverage plot: the sum of mapped reads at each position
>    > > 2. They indicate junction events (or splice sites), *i.e.* reads that are mapped across an intron
>    > >
>    > {: .solution}
>    {: .question}
>
{: .hands_on}

> <details-title>Further check for the quality of the data</details-title>
>
> The quality of the data and mapping can be checked further, e.g. by inspecting read duplication level, number of reads mapped to each chromosome, gene body coverage, and read distribution across features.
>
> *These steps have been inspired by the ones provided in the [great "RNA-Seq reads to counts" tutorial]({% link topics/transcriptomics/tutorials/rna-seq-reads-to-counts/tutorial.md %}) and adapted to our datasets.*
>
> #### Duplicate reads
>
> In the Falco/MultiQC report, we saw that some reads are duplicated:
>
> ![Sequence Duplication Levels](../../images/ref-based/fastqc_sequence_duplication_levels_plot.png "Sequence Duplication Levels")
>
> Duplicate reads can come from highly-expressed genes, therefore they are usually kept in RNA-Seq differential expression analysis. But a high percentage of duplicates may indicate an issue, e.g. over amplification during PCR of low complexity library.
>
> **MarkDuplicates** from [Picard suite](http://broadinstitute.github.io/picard/) examines aligned records from a BAM file to locate duplicate reads, i.e. reads mapping to the same location (based on the start position of the mapping).
>
> > <hands-on-title>Check duplicate reads</hands-on-title>
> >
> > 1. {% tool [MarkDuplicates](toolshed.g2.bx.psu.edu/repos/devteam/picard/picard_MarkDuplicates/3.1.1.0) %} with the following parameters:
> >    - {% icon param-collection %} *"Select SAM/BAM dataset or dataset collection"*: `RNA STAR on collection N: mapped.bam` (output of **RNA STAR** {% icon tool %})
> >
> > 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %} to aggregate the MarkDuplicates logs with the following parameters:
> >    - In *"Results"*:
> >        - *"Results"*
> >            - *"Which tool was used generate logs?"*: `Picard`
> >                - In *"Picard output"*:
> >                    - {% icon param-repeat %} *"Insert Picard output"*
> >                        - *"Type of Picard output?"*: `Markdups`
> >                        - {% icon param-collection %} *"Picard output"*: `MarkDuplicates on collection N: tabular` (output of **MarkDuplicates** {% icon tool %})
> >
> >    > <question-title></question-title>
> >    >
> >    > What are the percentages of duplicate reads for each sample?
> >    >
> >    > > <solution-title></solution-title>
> >    > >
> >    > > The sample `GSM461177_untreat_paired` has 25.9% of duplicated reads while `GSM461180_treat_paired` has 27.8%.
> >    > {: .solution}
> >    {: .question}
> {: .hands_on}
>
> In general, obtaining up to 50% duplicated reads is considered normal. So both our samples are fine.
>
> #### Number of reads mapped to each chromosome
>
> To assess the sample quality (e.g. excess of mitochondrial contamination), we can check the sex of samples, or to see if any chromosomes have highly expressed genes, we can check the numbers of reads mapped to each chromosome using **IdxStats** from the **Samtools** suite.
>
> > <hands-on-title>Check the number of reads mapped to each chromosome</hands-on-title>
> >
> > 1. {% tool [Samtools idxstats](toolshed.g2.bx.psu.edu/repos/devteam/samtools_idxstats/samtools_idxstats/2.0.7) %} with the following parameters:
> >    - {% icon param-collection %} *"BAM file"*: `RNA STAR on collection N: mapped.bam` (output of **RNA STAR** {% icon tool %})
> >
> > 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %} to aggregate the idxstats logs with the following parameters:
> >    - In *"Results"*:
> >        - *"Results"*
> >            - *"Which tool was used generate logs?"*: `Samtools`
> >                - In *"Samtools output"*:
> >                    - {% icon param-repeat %} *"Insert Samtools output"*
> >                        - *"Type of Samtools output?"*: `idxstats`
> >                            - {% icon param-collection %} *"Samtools idxstats output"*: `Samtools idxstats on collection N` (output of **Samtools idxstats** {% icon tool %})
> >
> >    > <question-title></question-title>
> >    >
> >    > ![Samtools idxstats](../../images/ref-based/samtools-idxstats-mapped-reads-plot.png)
> >    >
> >    > 1. How many chromosomes does the *Drosophila* genome have?
> >    > 2. Where did the reads mostly map?
> >    > 3. Can we determine the sex of the samples?
> >    >
> >    > > <solution-title></solution-title>
> >    > >
> >    > > 1. The genome of *Drosophila* has 4 pairs of chromosomes: X/Y, 2, 3, and 4.
> >    > > 2. The reads mapped mostly to chromosome 2 (chr2L and chr2R), 3 (chr3L and chr3R) and X. Only a few reads mapped to chromosome 4, which is expected given that this chromosome is very small.
> >    > > 3. Judging from the percentage of X+Y reads, most of the reads map to X and only a few to Y. This indicates there are probably not many genes on Y, so the samples are probably both female.
> >    > >
> >    > >    ![Samtools idxstats](../../images/ref-based/samtools-idxstats-xy-plot.png)
> >    > {: .solution}
> >    {: .question}
> {: .hands_on}
>
> #### Gene body coverage
>
> The different regions of a gene make up the gene body. It is important to check if read coverage is uniform across the gene body. For example, a bias towards the 5' end of genes could indicate degradation of the RNA. Alternatively, a 3' bias could indicate that the data is from a 3' assay. To assess this, we can use the **Gene Body Coverage** tool from the RSeQC ({% cite wang2012rseqc %}) tool suite. This tool scales all transcripts to 100 nucleotides (using a provided annotation file) and calculates the number of reads covering each (scaled) nucleotide position. As this tool is really slow, we will compute the coverage only on 200,000 random reads.
>
> > <hands-on-title>Check gene body coverage</hands-on-title>
> >
> > 1. {% tool [Samtools view](toolshed.g2.bx.psu.edu/repos/iuc/samtools_view/samtools_view/1.21+galaxy0) %} with the following parameters:
> >    - {% icon param-collection %} *"SAM/BAM/CRAM data set"*: `RNA STAR on collection N: mapped.bam` (output of **RNA STAR** {% icon tool %})
> >    - *"What would you like to look at?"*: `A filtered/subsampled selection of reads`
> >        - In *"Configure subsampling"*:
> >            - *"Subsample alignment"*: `Specify a target # of reads`
> >                - *"Target # of reads"*: `200000`
> >                - *"Seed for random number generator"*: `1`
> >        - *"What would you like to have reported?"*: `All reads retained after filtering and subsampling`
> >            - *"Output format"*: `BAM (-b)`
> >    - *"Use a reference sequence"*: `No`
> >
> > 2. {% tool [Convert GTF to BED12](toolshed.g2.bx.psu.edu/repos/iuc/gtftobed12/gtftobed12/357) %} to convert the GTF file to BED:
> >    - {% icon param-file %} *"GTF File to convert"*: `Drosophila_melanogaster.BDGP6.32.109.gtf.gz`
> >
> > 3. {% tool [Gene Body Coverage (BAM)](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_geneBody_coverage/5.0.3+galaxy0) %} with the following parameters:
> >    - *"Run each sample separately, or combine mutiple samples into one plot"*: `Run each sample separately`
> >        - {% icon param-collection %} *"Input .bam file"*: output of **Samtools view** {% icon tool %}
> >    - {% icon param-file %} *"Reference gene model"*: `Convert GTF to BED12 on data N: BED12` (output of **Convert GTF to BED12** {% icon tool %})
> >
> > 4. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %} to aggregate the RSeQC results with the following parameters:
> >    - In *"Results"*:
> >        - *"Results"*
> >            - *"Which tool was used generate logs?"*: `RSeQC`
> >                - In *"RSeQC output"*:
> >                    - {% icon param-repeat %} *"Insert RSeQC output"*
> >                        - *"Type of RSeQC output?"*: `gene_body_coverage`
> >                            - {% icon param-collection %} *"RSeQC gene_body_coverage output"*: `Gene Body Coverage (BAM) on collection N: stats (TXT)` (output of **Gene Body Coverage (BAM)** {% icon tool %})
> >
> >    > <question-title></question-title>
> >    >
> >    > ![Gene body coverage](../../images/ref-based/rseqc_gene_body_coverage_plot.png)
> >    >
> >    > How are the coverage across gene bodies? Are the samples biased in 3' or 5'?
> >    >
> >    > > <solution-title></solution-title>
> >    > >
> >    > > For both samples there is a pretty even coverage from 5' to 3' ends (despite some noise in the middle). So no obvious bias in both samples.
> >    > {: .solution}
> >    {: .question}
> {: .hands_on}
>
> #### Read distribution across features
>
> With RNA-Seq data, we expect most reads to map to exons rather than introns or intergenic regions. Before going further in counting and differential expression analysis, it may be interesting to check the distribution of reads across known gene features (exons, CDS, 5' UTR, 3' UTR, introns, intergenic regions). For example, a high number of reads mapping to intergenic regions may indicate the presence of DNA contamination.
>
> Here we will use the **Read Distribution** tool from the RSeQC ({% cite wang2012rseqc %}) tool suite, which uses the annotation file to identify the position of the different gene features.
>
> > <hands-on-title>Check the number of reads mapped to each chromosome</hands-on-title>
> >
> > 1. {% tool [Read Distribution](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_read_distribution/5.0.3+galaxy0) %} with the following parameters:
> >    - {% icon param-collection %} *"Input .bam/.sam file"*: `RNA STAR on collection N: mapped.bam` (output of **RNA STAR** {% icon tool %})
> >    - {% icon param-file %} *"Reference gene model"*: BED12 file (output of **Convert GTF to BED12** {% icon tool %})
> >
> > 2. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.27+galaxy4) %} to aggregate the Read Distribution results with the following parameters:
> >    - In *"Results"*:
> >        - *"Results"*
> >            - *"Which tool was used generate logs?"*: `RSeQC`
> >                - In *"RSeQC output"*:
> >                    - {% icon param-repeat %} *"Insert RSeQC output"*
> >                        - *"Type of RSeQC output?"*: `read_distribution`
> >                            - {% icon param-collection %} *"RSeQC read_distribution output"*: `Read Distribution on collection N: stats (TXT)` (output of **Read Distribution** {% icon tool %})
> >
> >    > <question-title></question-title>
> >    >
> >    > ![Read Distribution](../../images/ref-based/rseqc_read_distribution_plot.png)
> >    >
> >    > What do you think of the read distribution?
> >    >
> >    > > <solution-title></solution-title>
> >    > >
> >    > > Most of the reads are mapped to exons (>80%), only ~2% to introns and ~5% to intergenic regions, which is what we expect. It confirms that our data are RNA-Seq data and that mapping was successful.
> >    > {: .solution}
> >    {: .question}
> {: .hands_on}
>
> Now that we have checked the results of the read mapping, we can proceed to the next phase of the analysis.
{: .details}

After the mapping, we now have the information on where the reads are located on the reference genome and how well they were mapped. The next step in RNA-Seq data analysis is quantification of the number of reads mapped to genomic features (genes, transcripts, exons, ...).

> <comment-title></comment-title>
>
> The quantification depends on both the reference genome (the FASTA file) and its associated annotations (the GTF file). It is extremely important to use an annotation file that corresponds to the same version of the reference genome you used for the mapping (e.g. `dm6` here), as the chromosomal coordinates of genes are usually different amongst different reference genome versions.
{: .comment}

Here we will focus on the genes, as we would like to identify the ones that are differentially expressed because of the Pasilla gene knockdown.

# Counting the number of reads per annotated gene

To compare the expression of single genes between different conditions (*e.g.* with or without PS depletion), an essential first step is to quantify the number of reads per gene, or more specifically the number of reads mapping to the exons of each gene.

![Counting the number of reads per annotated gene](../../images/transcriptomics_images/gene_counting.png "Counting the number of reads per annotated gene")

> <question-title></question-title>
>
> In the previous image,
>
> 1. How many reads are found for the different exons?
> 2. How many reads are found for the different genes?
>
> > <solution-title></solution-title>
> >
> > 1. Number of reads per exons
> >
> >     Exon | Number of reads
> >     --- | ---
> >     gene1 - exon1 | 3
> >     gene1 - exon2 | 2
> >     gene2 - exon1 | 3
> >     gene2 - exon2 | 4
> >     gene2 - exon3 | 3
> >
> > 2. gene1 has 4 reads, not 5, because of the splicing of the last read (gene1 - exon1 + gene1 - exon2). gene2 has 6 reads, 3 of which are spliced.
> {: .solution}
{: .question}

Two main tools are available for read counting: [**HTSeq-count**](http://htseq.readthedocs.io/en/release_0.9.1/count.html) ({% cite anders2015htseq %}) or **featureCounts** ({% cite liao2013featurecounts %}). Additionally, **STAR** allows to count reads while mapping: its results are identical to those from **HTSeq-count**. While this output is sufficient for most analyses, **featureCounts** offers more customization on how to count reads (minimum mapping quality, counting reads instead of fragments, count transcripts instead of genes etc.).

In principle, the counting of reads overlapping with genomic features is a fairly simple task. But the strandness of the library needs to be determined. Indeed this is a parameter of **featureCounts**. On the contrary, **STAR** evaluates the counts into the three possible strandnesses but you still need this information to extract the counts which corresponds to your library.

## Estimation of the strandness

RNAs that are typically targeted in RNA-Seq experiments are single stranded (*e.g.*, mRNAs) and thus have polarity (5' and 3' ends that are functionally distinct). During a typical RNA-Seq experiment the information about strandness is lost after both strands of cDNA are synthesized, size selected, and converted into a sequencing library. However, this information can be quite useful for the read counting step, especially for reads located on the overlap of 2 genes that are on different strands.

![Why strandness?](../../images/ref-based/strandness_why.png "If strandness information was lost during library preparation, Read1 will be assigned to gene1 located on the forward strand but Read2 will be 'ambiguous' as it can be assigned to gene1 (forward strand) or gene2 (reverse strand).")

Some library preparation protocols create so-called *stranded* RNA-Seq libraries that preserve the strand information ({% cite levin2010comprehensive %} provides an excellent overview). In practice, with Illumina RNA-Seq protocols you are unlikely to encounter all of the possibilities described in this article. You will most likely deal with either:

- Unstranded RNA-Seq data
- Stranded RNA-Seq data generated by the use of specialized RNA isolation kits during sample preparation

> <details-title>More details about strandness</details-title>
>
> ![Relationship between DNA and RNA orientation](../../images/transcriptomics_images/dna_rna.png "Relationship between DNA and RNA orientation")
>
> The implication of stranded RNA-Seq is that you can distinguish whether the reads are derived from forward or reverse-encoded transcripts. In the following example, the counts for the gene Mrpl43 can only be efficiently estimated in a stranded library as most of it overlap the gene Peo1 in the reverse orientation:
>
> ![Stranded RNA-Seq data look like this](../../images/ref-based/igv_stranded_screenshot.png "Non-stranded (top) vs. reverse strand-specific (bottom) RNA-Seq read alignment (using IGV, forward mapping reads are red and reverse mapping reads are blue )")
>
> Depending on the approach, and whether one performs single-end or paired-end sequencing, there are multiple possibilities on how to interpret the results of the mapping of these reads to the genome:
>
> ![Effects of RNA-Seq library types](../../images/transcriptomics_images/rnaseq_library_type.png "Effects of RNA-Seq library types (Figure adapted from Sailfish documentation)")
{: .details}

This information should be provided with your FASTQ files, ask your sequencing facility! If not, try to find it on the site where you downloaded the data or in the corresponding publication.

![How to estimate the strandness?](../../images/ref-based/strandness_cases.png "In a stranded forward library, reads map mostly on the same strand as the genes. With stranded reverse library, reads map mostly on the opposite strand. With unstranded library, reads map on genes on both strands independently of the orientation of the gene (Example for single-end read library).")

There are 5 ways to estimate strandness from **STAR** results (choose the one you prefer)

1. We can do a visual inspection of read strands on IGV (for Paired-end dataset it is less easy than with single read and when you have a lot of samples, this can be painful).

    > <hands-on-title>Estimate strandness with IGV for a paired-end library</hands-on-title>
    >
    > 1. Go back to your IGV session with the `GSM461177_untreat_paired` BAM opened.
    >
    >    > <tip-title>If you don't have it</tip-title>
    >    >
    >    > No problem, you just need to redo the previous steps:
    >    >
    >    > 1. Start IGV locally
    >    > 2. Click on the collection `RNA STAR on collection N: mapped.bam` (output of **RNA STAR** {% icon tool %})
    >    > 3. Expand the {% icon param-file %} `GSM461177_untreat_paired` file.
    >    > 4. Click on the `local` in `display with IGV local D. melanogaster (dm6)` to load the reads into the IGV browser
    >    >
    >    {: .tip}
    >
    > 2. **IGV** {% icon tool %}
    >    1. Zoom to `chr3R:9,445,000-9,448,000` (Chromosome 3 between 9,445 kb to 9,448 kb), on the `mapped.bam` track
    >    2. Right click and then select `Color Aligments by` -> `first-of-pair strand`
    >    3. Right click and select `Squished`
    >
    {: .hands_on}

    > <question-title></question-title>
    >
    > ![Screenshot of the IGV view on ps](../../images/ref-based/group_strand_igv_screenshot.png "Screenshot of IGV on ps")
    >
    > 1. Are the reads evenly distributed between the 2 colors (red - forward and blue - reverse)?
    > 2. What is the type of library strandness?
    >
    > > <solution-title></solution-title>
    > >
    > > 1. Yes we see the same number of reads of bot


topic: transcriptomics
tutorial: differential-isoform-expression
title: Genome-wide alternative splicing analysis
difficulty: advanced
time_estimation: 3H
tools_json: []
requirements_json: []
tags_json: []
content_hash: 0fb1dbf4008bf32f26ee364f07d98578
last_modified: 2026-02-26T21:12:18.547548
zenodo_link: https://zenodo.org/records/13692977
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/differential-isoform-expression/tutorial.html

content:
Discovered over 40 years ago, {AS} formed a large part of the puzzle explaining how proteomic complexity can be achieved with a limited set of genes  ({% cite Alt1980 %}). The majority of eukaryote genes have multiple transcriptional isoforms, and recent data indicate that each transcript of protein-coding genes contain 11 exons and produce 5.4 mRNAs on average ({% cite Piovesan2016 %}). In humans,  approximately 95% of multi-exon genes show evidence of {AS} and approximately 60% of genes have at least one alternative transcription start site, some of which exert antagonistic functions ({% cite Carninci2006 %}, {% cite Miura2012 %}). Its regulation is essential for providing cells and tissues their specific features, and for their response to environmental changes ({% cite Wang2008 %}, {% cite Kalsotra2011 %}).

Alterations in gene splicing has been demonstrated to have significant impact on cancer development, and multiple evidences indicate that its disruption can exhibit effects on virtually all aspect of tumor progression ({% cite Namba2021 %}, {% cite Bonnal2020 %}). For instance, the unannotated isoform of TNS3 was found to be a novel driver of breast cancer ({% cite Namba2021 %}).

![Figure 01. Examples of cancer splicing dysregulation on cancer hallmarks](../../images/differential_isoform/differential_cancer.png "Effect of alternative splicing dysregulation on cancer progression. The diagram depicts various cancer hallmarks and examples of genes whose splicing dysregulation has been demostrated to be implicated in the corresponding functional modification.")

Disregulation in {AS} can lead to the activation of {OCGs} or the inactivation of {TSGs}, which can promote or suppress tumorigenesis, respectively ({% cite Bashyam2019 %}). However, the strict classification of cancer genes as either {OCGs} or {TSGs} may be an oversimplification, as some genes can exhibit a dual role in cancer development, often impacting the same facet of tumorigenesis ({% cite Bashyam2019 %}). One of the mechanism that has been proposed to partially explain this apparently contradictory effect is the differential usage of isoforms, often referred to as {IS}. This regulatory phenomenon has been demonstrated to have a substantial biological impact in a diverse range of biological contexts, caused by functional diversity potential of the different isoforms ({% cite VittingSeerup2017 %}).

In this tutorial, we aim to perform a genome-wide analysis of {IS} driven by an oncogene fusion gene EWS-FLI1, with the objective of identifying genes of potential clinical relevance and gene regulatory networks on genome-scale.

> <agenda-title></agenda-title>
>
> In this tutorial, we will cover:
>
> 1. TOC
> {:toc}
>
{: .agenda}


# Background on data

Ewing sarcoma is a bone and soft tissue cancer mainly affecting children, adolescents and young adults ({% cite Ewing1921 %}). In most of cases, this sarcoma is induced by a gene fusion between EWRS1 (a RNA-binding protein) and FLI1 (a transcription factor of the ETS family) ({% cite Delattre1992 %}). In order to study the role of this fusion oncogene, Carrilo and colleagues has developed a cell line, derived from an Ewing sarcoma tumor carrying EWS-FLI1 fusion, where the fusion oncoprotein can be knocked-down using doxycycline ({% cite Carrillo2007 %}). In this tutorial, we will use datasets produced by Saulnier and colleagues to study the role of EWS-FLI1 in alternative splicing ({% cite Saulnier2021 %}). They performed RNA sequencing of the inducible cell line after 7 days of doxycycline treatment where EWS-FLI1 is depleted and compared them to RNA sequencing of the same cell line without doxycycline treatment.

The dataset consists of twelve FASTQ files, generated through the Illumina HiSeq 2500 sequencing machine. Three of the samples were obtained from A673/TR/shEF cancer cell line without treatment, and the rest from the same cell line where the EWS-FLI1 fusion oncoprotein is depleted (doxycycline treated). For this training we will use a reduced set of reads enriched in reads mapping on chr10, in order to speed up the analysis. The original dataset is available in the NCBI SRA database, with the accession number PRJNA521683.

## Get data

The first step of our analysis consists of retrieving the paired-end RNA-seq datasets from Zenodo and organizing them into a collection.

> <hands-on-title>Retrieve mRNA-Seq datasets</hands-on-title>
>
> 1. Create a new history for this tutorial
> 2. Import the files from Zenodo:
>
>    - Open the file {% icon galaxy-upload %} __upload__ menu
>    - Click on __Rule-based__ tab
>    - *"Upload data as"*: `Collection(s)`
>    - Copy the following tabular data, paste it into the textbox and press <kbd>Build</kbd>
>
>      ```
>      ASP14_1	{{ page.zenodo_link }}/files/ASP14_1_chr10enriched_R1.fastq.gz	fastqsanger.gz	1
>      ASP14_1	{{ page.zenodo_link }}/files/ASP14_1_chr10enriched_R2.fastq.gz	fastqsanger.gz	2
>      ASP14_2	{{ page.zenodo_link }}/files/ASP14_2_chr10enriched_R1.fastq.gz	fastqsanger.gz	1
>      ASP14_2	{{ page.zenodo_link }}/files/ASP14_2_chr10enriched_R2.fastq.gz	fastqsanger.gz	2
>      ASP14_3	{{ page.zenodo_link }}/files/ASP14_3_chr10enriched_R1.fastq.gz	fastqsanger.gz	1
>      ASP14_3	{{ page.zenodo_link }}/files/ASP14_3_chr10enriched_R2.fastq.gz	fastqsanger.gz	2
>      ASP14_doxycycline_1	{{ page.zenodo_link }}/files/ASP14_doxycycline_1_chr10enriched_R1.fastq.gz	fastqsanger.gz	1
>      ASP14_doxycycline_1	{{ page.zenodo_link }}/files/ASP14_doxycycline_1_chr10enriched_R2.fastq.gz	fastqsanger.gz	2
>      ASP14_doxycycline_2	{{ page.zenodo_link }}/files/ASP14_doxycycline_2_chr10enriched_R1.fastq.gz	fastqsanger.gz	1
>      ASP14_doxycycline_2	{{ page.zenodo_link }}/files/ASP14_doxycycline_2_chr10enriched_R2.fastq.gz	fastqsanger.gz	2
>      ASP14_doxycycline_3	{{ page.zenodo_link }}/files/ASP14_doxycycline_3_chr10enriched_R1.fastq.gz	fastqsanger.gz	1
>      ASP14_doxycycline_3	{{ page.zenodo_link }}/files/ASP14_doxycycline_3_chr10enriched_R2.fastq.gz	fastqsanger.gz	2
>      ```
>
>    - From **Rules** menu select `Add / Modify Column Definitions`
>       - Click `Add Definition` button and select `List Identifier(s)`: column `A`
>
>         > <tip-title>Can't find <i>List Identifier</i>?</tip-title>
>         > Then you've chosen to upload as a 'dataset' and not a 'collection'. Close the upload menu, and restart the process, making sure you check *Upload data as*: **Collection(s)**
>         {: .tip}
>
>       - Click `Add Definition` button and select `URL`: column `B`
>       - Click `Add Definition` button and select `Type`: column `C`
>       - Click `Add Definition` button and select `Pair-end Indicator`: column `D`
>
>    - Click `Apply`, give a name to your collection like `All samples`  and press <kbd>Upload</kbd>
>
{: .hands_on}

Next we will retrieve the remaining datasets.

> <hands-on-title>Retrieve the additional datasets</hands-on-title>
>
> 1. Import the files from Zenodo:
>
>    - Open the file {% icon galaxy-upload %} __upload__ menu
>    - Click on __Rule-based__ tab
>    - *"Upload data as"*: `Datasets`
>    - Once again, copy the tabular data, paste it into the textbox and press <kbd>Build</kbd>
>
>      ```
>      CPAT_header.tab  {{ page.zenodo_link }}/files/CPAT_header.tab
>      gencode.hg19.chr10.gtf	{{ page.zenodo_link }}/files/gencode.v19.hg19.chr10.gtf
>      hg19.chr10.fasta	{{ page.zenodo_link }}/files/hg19.chr10.fasta
>      active_site.dat.gz	https://ftp.ebi.ac.uk/pub/databases/Pfam/releases/Pfam37.0/active_site.dat.gz
>      Pfam-A.hmm.dat.gz	https://ftp.ebi.ac.uk/pub/databases/Pfam/releases/Pfam37.0/Pfam-A.hmm.dat.gz
>      Pfam-A.hmm.gz	https://ftp.ebi.ac.uk/pub/databases/Pfam/releases/Pfam37.0/Pfam-A.hmm.gz
>      ```
>
>    - From **Rules** menu select `Add / Modify Column Definitions`
>       - Click `Add Definition` button and select `Name`: column `A`
>       - Click `Add Definition` button and select `URL`: column `B`
>    - Click `Apply` and press <kbd>Upload</kbd>
>
> > <warning-title>Inconsistancies between reference and annotations</warning-title>
> > 1. Make sure that the chromosome IDs in the reference genome FASTA file and the GTF annotation file are consistent. If they are not, you may need to modify one of them to ensure they match. For example, if the FASTA file uses `chr1` and the GTF file uses `1`, you may need to edit the GTF file to add the `chr` prefix to the chromosome IDs or vice versa.
> >
> > 2. In later steps, **IsoformSwitchAnalyzeR** has strict checks on the transcript ids. Make sure that the transcript IDs in the GTF file do not contain any dots or underscores. If they do, you may need to edit the GTF file to remove these characters from the transcript IDs. 
> >
> > 3. **IsoformSwitchAnalyzeR** incorporates `transcript_version` and `gene_version` attributes from the GTF file into transcript and gene ids respectively. If you have a transcript with id `ENST00000335137` along with `transcript_version "2";` attribute, the **IsoformSwitchAnalyzeR** internally will create a transcript id `ENST00000335137.2`. It is recommended to remove these attributes from the GTF file to avoid tool errors.
> >
> > > <hands-on-title>Remove version attributes from GTF file</hands-on-title>
> > > 1. {% tool [Regex Find And Replace](toolshed.g2.bx.psu.edu/repos/galaxyp/regex_find_replace/regex1/1.0.3) %} with the following parameters:
> > >   - {% icon param-file %} *"Select lines from "*: `your.gtf`
> > >   - In *"Check"*:
> > >       - {% icon param-repeat %} *"Insert Check"*
> > >           - *"Find Regex"*: `\.([0-9]+)(?=[\";\s])` (if your transcript IDs contain dots with version numbers after them)
> > >           - *"Replacement"*: leave blank
> > >       - {% icon param-repeat %} *"Insert Check"*
> > >           - *"Find Regex"*: `\stranscript_version "[^"]*";`
> > >           - *"Replacement"*: leave blank
> > >       - {% icon param-repeat %} *"Insert Check"*
> > >           - *"Find Regex"*: `\sgene_version "[^"]*";`
> > >           - *"Replacement"*: leave blank
> > >
> > {: .hands_on}
> >
> {: .warning}
{: .hands_on}

<!--
> <details-title>Dataset subsampling</details-title>
>
> As indicated above, for this tutorial the depth of the samples was reduced in order to speed up the time needed to carry out the analysis. This was done as follows, all reads mapping to chromosome 10 were kept and a random fraction of 0.003 were added.
{: .details}
-->

# Quality assessment

Once we have got the datasets, we can start with the analysis. The first step is to perform the quality assessment. Since this step is deeply covered in the tutorial [Quality control]({% link topics/sequence-analysis/tutorials/quality-control/tutorial.md %}), we won't describe this section in detail.


> <comment-title>Initial quality evaluation (OPTIONAL)</comment-title>
>
>   For the initial quality evaluation, it is necessary to perform a pre-processing step consisting in flattening the list of pairs into a simple list; this step is required because of issues between **FastQC** and **MultiQC**. The `Raw data QC` files generated by **FastQC** will be combine into a a single one by making use of **MultiQC**.
>
>   > <hands-on-title>Initial quality evaluation</hands-on-title>
>   >
>   > 1. {% tool [Flatten collection](__FLATTEN__) %} with the following parameters convert the list of pairs into a simple list:
>   >     - *"Input Collection"*: `All samples`
>   >
>   > 2. {% tool [FastQC](toolshed.g2.bx.psu.edu/repos/devteam/fastqc/fastqc/0.74+galaxy1) %} with the following parameters:
>   >    - {% icon param-collection %} *"Raw read data from your current history"*: Output of **Flatten collection** {% icon tool %} selected as **Dataset collection**
>   >
>   >    {% snippet faqs/galaxy/tools_select_collection.md %}
>   >
>   > 3. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy1) %} with the following parameters:
>   >    - In *"Results"*:
>   >        - {% icon param-repeat %} *"Insert Results"*
>   >            - *"Which tool was used generate logs?"*: `FastQC`
>   >                - In *"FastQC output"*:
>   >                    - {% icon param-repeat %} *"Insert FastQC output"*
>   >                        - {% icon param-collection %} *"FastQC output"*: `FastQC on collection: Raw data` (output of **FastQC** {% icon tool %})
>   >    - *"Report title"*: `Raw data QC`
>   >
>   >
>   {: .hands_on}
>
>
>   Let's evaluate the per base sequence quality and the adapter content.
>
>   ![Figure 02. MultiQC initial QC report](../../images/differential_isoform/fastqc_per_base_sequence_quality.png "MultiQC aggregated reports. Mean quality scores.")
>
>   As we can appreciate in the figure the per base quality of all reads seems to be very good, with values over 30 in all cases. In addition, according the report no samples werefound with adapter contamination higher than 1%.
>
{: .comment}


## Read pre-processing with fastp

In order to remove the adaptors we will make use of **fastp**, which is able to detect the adapter sequence by performing a per-read overlap analysis, so we won't even need to specify the adapter sequences.

> <hands-on-title>Pre-process reads with fastp</hands-on-title>
>
> 1. {% tool [fastp](toolshed.g2.bx.psu.edu/repos/iuc/fastp/fastp/0.23.4+galaxy1) %} with the following parameters:
>    - *"Single-end or paired reads"*: `Paired Collection`
>        - {% icon param-collection %} *"Select paired collection(s)"*: `All samples`
>    - In *"Filter Options"*:
>        - In *"Quality filtering options"*:
>            - *"Qualified quality phred"*: `20`
>    - In *"Output Options"*:
>        - *"Output JSON report"*: `Yes`
> 2. Rename the output `fastp on collection X: Paired-end output` as `Trimmed samples`
> 3. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy1) %} with the following parameters:
>    - In *"Results"*:
>        - {% icon param-repeat %} *"Insert Results"*
>            - *"Which tool was used generate logs?"*: `fastp`
>                - {% icon param-collection %} *"Output of fastp"*: `fastp on collection XXX: JSON report` (output of **fastp** {% icon tool %})
>
>    > <question-title></question-title>
>    >
>    > 1. What proportion of reads were written in output file?
>    > 2. What is the average insert size?
>    >
>    >    > <solution-title></solution-title>
>    >    >
>    >    > 1. All reads passed the filters (see %PF in the general statistics).
>    >    >
>    >    > 2. The average insert size is about 145 for 5 samples and 135 for ASP14_2.
>    >    >
>    >    {: .solution}
>    {: .question}
{: .hands_on}

# RNA-seq mapping and evaluation

Mapping is crucial in genome-guided-based isoform analysis as it allows for the accurate identification and quantification of RNA isoforms present in a sample. That section makes use of two main tools: **RNA STAR**, considered a state-of-the-art mapping tool for RNA-seq data, and **RSeQC**, a critical tool in isoform analysis that provides comprehensive quality assessment metrics and analyses to evaluate the reliability and integrity of RNA-seq data.

> <comment-title>Transcriptome-reconstruction approaches</comment-title>
>
>  The different methods for estimating transcript/isoform abundance can be classified depending on two main requirements: reference sequence and alignment. Reference-guided transcriptome assembly strategy requires to aligning sequencing reads to a reference genome first, and then assembling overlapping alignments into transcripts. In contrast, *de novo* transcriptome assembly methods directly reconstructs overlapping reads into transcripts by utilising the redundancy of sequencing reads themselves ({% cite Lu2013 %}).
>
{: .comment}

## RNA-seq mapping with **RNA STAR**

**RNA STAR** is a splice-aware RNA-seq alignment tool that allows to identify canonical and non-canonical splice junctions by making use of sequential maximum mappable seed search in uncompressed suffix arrays followed by seed clustering and stitching procedure ({% cite Krianovi2017 %}). One advantage of **RNA STAR** with respect to other tools is that it includes a feature called *two-pass mode*, a framework in which splice junctions are separately discovered and quantified, allowing robustly and accurately identify  splice junction patterns for differential splicing analysis and variant discovery.

> <comment-title>RNA STAR two-pass mode</comment-title>
>
> During two-pass mode splice junctions are discovered in a first alignment pass with high stringency, and are used as annotation in a second pass to permit lower stringency alignment, and therefore higher sensitivity (fig. 3). Two-pass alignment enables sequence reads to span novel splice junctions by fewer nucleotides, conferring greater read depth and providing significantly more accurate quantification of novel splice junctions that one-pass alignment ({% cite Veeneman2015 %}).
>
> ![Figure 03. RNA STAR twopass mode](../../images/differential_isoform/RNASTAR_twopass_mode.png "Two-pass alignment flowchart. Center and right, stepwise progression of two-pass alignment. First, the genome is indexed with gene annotation. Next, novel splice junctions are discovered from RNA sequencing data at a relatively high stringency (12 nt minimum spanning length). Third, these discovered splice junctions, and expressed annotated splice junctions are used to re-index the genome. Finally, alignment is performed a second time, quantifying novel and annotated splice junctions using the same, relatively lower stringency (3 nt minimum spanning length), producing splice junction expression. Source: Veeneman et al., 2016.")
>
{: .comment}

The choice of **RNA STAR** as mapper is also determined by the sequencing technology; it has been demonstrated adequate for short-read sequencing data, but when using long-read data, such as PacBio or ONT reads, it is recommended to use **Minimap2** as alignment tool.

> <comment-title>Inference of intron size (optional)</comment-title>
>
> If you are interested in analyzing non-human samples, it is a good idea to infer the **minimium and maximum intron sizes** before running **RNA STAR**.
>
> > <hands-on-title>Inference of intron size </hands-on-title>
> >
> > 1. {% tool [Convert GTF to BED12](toolshed.g2.bx.psu.edu/repos/iuc/gtftobed12/gtftobed12/357) %} with the following parameters:
> >    - {% icon param-file %} *"GTF File to convert"*: `gencode.hg19.chr10.gtf`
> >    - *"Advanced options"*: `Set advanced options`
> >        - *"Ignore groups without exons"*: `Yes`
> >
> > 2. Rename the output as `BED12 annotation`
> >
> > 3. {% tool [Gene BED To Exon/Intron/Codon BED](gene2exon1) %} with the following parameters:
> >    - *"Extract"*: `Introns`
> >        - {% icon param-file %} *"from"*: `BED12 annotation`
> >
> > 4. {% tool [Compute](toolshed.g2.bx.psu.edu/repos/devteam/column_maker/Add_a_column1/2.0) %} on rows with the following parameters:
> >   - {% icon param-file %} *"File to process"*: output of **Gene BED To Exon/Intron/Codon BED** {% icon tool %}
> >   - For "*1: Expressions*":
> >     - *"Add expression"*: `c3-c2`
> >     - *"Mode of the operation"*: `Append`
> >
> > 5. {% tool [Sort](sort1) %} data in ascending or descending order with the following parameters:
> >   - {% icon param-file %} *"Sort Dataset"*: output of **Compute on rows** {% icon tool %}
> >   - "*on column*": `Column: 7`
> >   - "*everything in*": `Descending order`
> >
> > 6. Instead of taking the min value, we will use a quantile approach. We will get the 1/10000 quantile using {% tool [Text reformatting](toolshed.g2.bx.psu.edu/repos/bgruening/text_processing/tp_awk_tool/9.3+galaxy1) %} with awk with the following parameters:
> >   - {% icon param-file %} *"File to process"*: output of **Sort** {% icon tool %}
> >   - "*AWK Program*": `{all[NR] = $7} END{print all[int(NR*0.9999 - 0.5)]}`
> >
> > 7. Rename the output as `Minimum intron size`
> >
> > 8. Instead of taking the max value, we will use a quantile approach. We will get the 1/1000 quantile using {% tool [Text reformatting](toolshed.g2.bx.psu.edu/repos/bgruening/text_processing/tp_awk_tool/9.3+galaxy1) %} with awk with the following parameters:
> >   - {% icon param-file %} *"File to process"*: output of **Sort** {% icon tool %}
> >   - "*AWK Program*": `{all[NR] = $7} END{print all[int(NR*0.001 - 0.5)]}`
> >
> > 9. Rename the output as `Maximum intron size`
> >
> > > <question-title></question-title>
> > >
> > > 1. What is the minimum intron size you got, does it makes sense?
> > > 2. What is the maximum intron size you got?
> > >
> > > > <solution-title></solution-title>
> > > >
> > > > 1. You may have found 1 as minimum intron size. Indeed, it seems that some annotated introns are 1bp long. This does not really make sense biologically. Piovesan and colleague have shown that no eukaryotic introns were found below 30bp ({% cite Piovesan2015 %}).
> > > >
> > > > 2. You may have found 316825.
> > > >
> > > {: .solution}
> > {: .question}
> {: .hands_on}
>
{: .comment}

Now we can perform the mapping step.

> <comment-title>ENCODE options</comment-title>
>
> In this training, for **RNA STAR**, we adopted the parameters from the [ENCODE pipeline](https://www.encodeproject.org/pipelines/), developed by the ENCODE RNA Working Group. It is **specially designed for the human genome**. If your samples belong to a different organism, probably you will need to adapt the configuration a bit. You can find more information in the [**RNA STAR** manual](https://github.com/alexdobin/STAR/blob/master/doc/STARmanual.pdf).
>
{: .comment}

> <hands-on-title> Generate intermediate file with RNA STAR</hands-on-title>
>
> 1. {% tool [RNA STAR](toolshed.g2.bx.psu.edu/repos/iuc/rgrnastar/rna_star/2.7.11a+galaxy0) %} with the following parameters:
>    - *"Single-end or paired-end reads"*: `Paired-end (as collection)`
>        - {% icon param-collection %} *"RNA-Seq FASTQ/FASTA paired reads"*: `Trimmed samples` (output of **fastp** {% icon tool %})
>    - *"Custom or built-in reference genome"*: `Use reference genome from history and create temporary index`
>        - {% icon param-file %} *"Select a reference genome"*: `hg19.chr10.fasta`
>        - *"Build index with or without known splice junctions annotation"*: `build index with gene-model`
>            - {% icon param-file %} *"Gene model (gff3,gtf) file for splice junctions"*: `gencode.hg19.chr10.gtf`
>            - *"Length of the genomic sequence around annotated junctions*": `100`
>            - *"Per gene/transcript output*": `Per gene read counts (GeneCounts)`
>    - *"Would you like to set additional output filters?"*: `Yes`
>        - *"Would you like to keep only reads that contain junctions that passed filtering?*": `Yes` (ENCODE option, reduces the number of ”spurious” junctions)
>        - *"Maximum number of alignments to output a read's alignment results, plus 1*": `20` (ENCODE option)
>        - *"Maximum number of mismatches to output an alignment, plus 1*": `999` (ENCODE option)
>        - *"Maximum ratio of mismatches to read length*": `0.04` (ENCODE option)
>    - In *"Algorithmic settings"*:
>        - *"Configure seed, alignment and limits options*": `Extended parameter list`
>            - In *"Alignment parameters"*:
>                - *"Minimum intron size*": `20` (ENCODE option)
>                - *"Maximum intron size*": `1000000` (ENCODE option)
>                - *"Maximum gap between two mates*": `1000000` (ENCODE option)
>                - *"Minimum overhang for spliced alignments*": `8` (ENCODE option)
>                - *"Minimum overhang for annotated spliced alignments*": `1` (ENCODE option)
>
> > <comment-title>Intron size values</comment-title>
> >
> >  Here we are using the parameters recommended by **ENCODE** for human samples. If you are working with a different organism, you can use the intron sizes computed previously.
> >
> {: .comment}
>
{: .hands_on}

The first **RNA STAR** run generates three collections: logs, alignments in BAM format, and a collection of BED files with splice junction coordinates. Now we will process the collection of BED files with the objective of getting a unique list of junctions where we remove non-canonical junctions (column 5 > 0), annotated junction sites (column 6 == 0) and junctions supported by too few reads (column 7 > 5).

> <hands-on-title> Pre-processing of splice junction coordinates</hands-on-title>
> 1. {% tool [Concatenate datasets](toolshed.g2.bx.psu.edu/repos/bgruening/text_processing/tp_cat/9.3+galaxy1) %} tail-to-head **(cat)** with the following parameters:
>   - {% icon param-collection %} *"Datasets to concatenate"*: `RNA STAR on collection XXX: splice junctions.bed` (output of **RNA STAR** {% icon tool %})
>
>         The output must be a dataset not a collection
>
>         > <tip-title>Got a collection instead of a dataset?</tip-title>
>         > You probably selected **Concatenate datasets** tail-to-head {% icon tool %} instead of the other tool with the same name except that it has a `(cat)` at the end of the name.
>         > Simply rerun the step above with the good tool.
>         {: .tip}
>
> 2. {% tool [Filter](Filter1) %} data on any column using simple expressions:
>   - *"Filter"*: output of **Concatenate datasets** {% icon tool %}
>   - *"With following condition"*: `c5 > 0 and c6 == 0 and c7 > 5` (here `c` stands for *column*).
>
> 3. {% tool [Cut](Cut1) %} columns from a table with the following parameters:
>   - "*Cut columns*": `c1-c6`
>   - {% icon param-file %} *"From"*: output of **Filter** {% icon tool %}
>
> 4. {% tool [Sort](sort1) %} data in ascending or descending order with the following parameters:
>    - {% icon param-file %} *"Sort Dataset"*: output of **Cut** {% icon tool %}
>    - *"on column*": `Column: 1`
>    - *"with flavor"*: `Alphabetical sort`
>    - *"everything in"*: `Ascending order`
>    - {% icon param-repeat %} *"Insert Column selection"*
>        - *"on column"*: `Column: 2`
>        - *"everything in"*: `Ascending order`
>    - {% icon param-repeat %} *"Insert Column selection"*
>        - *"on column"*: `Column: 3`
>        - *"everything in"*: `Ascending order`
>
> 5. {% tool [Unique lines](toolshed.g2.bx.psu.edu/repos/bgruening/text_processing/tp_uniq_tool/9.3+galaxy1) %} assuming sorted input file with the following parameters:
>   - {% icon param-file %} *"File to scan for unique values"*: output of **Sort** {% icon tool %}
>   - *Only print unique lines*: No
>
> 6. Rename the output as `Splicing database` and change datatype to `interval` (this was the initial datatype but the `cut` tool changed it to `tabular`.)
>
>    > <question-title></question-title>
>    >
>    > 1. In average in how many samples the new splicing events were detected?
>    >
>    >    > <solution-title></solution-title>
>    >    >
>    >    > 1. The output of **Sort** {% icon tool %} has 4558 lines and the output of **Uniq** {% icon tool %} has 1608, so in average, it is present in 3 samples.
>    >    >
>    >    {: .solution}
>    {: .question}
{: .hands_on}

Finally, we will re-run **RNA STAR** in order to integrate the information about the new splicing events in the analysis.

> <hands-on-title> Sequence alignment with STAR</hands-on-title>
> 1. {% tool [RNA STAR](toolshed.g2.bx.psu.edu/repos/iuc/rgrnastar/rna_star/2.7.11a+galaxy0) %} with the following parameters:
>    - *"Single-end or paired-end reads"*: `Paired-end (as collection)`
>        - {% icon param-collection %} *"RNA-Seq FASTQ/FASTA paired reads"*: `Trimmed samples` (output of **fastp** {% icon tool %})
>    - *"Custom or built-in reference genome"*: `Use reference genome from history and create temporary index`
>        - {% icon param-file %} *"Select a reference genome"*: `hg19.chr10.fasta`
>        - *"Build index with or without known splice junctions annotation"*: `build index with gene-model`
>            - {% icon param-file %} *"Gene model (gff3,gtf) file for splice junctions"*: `gencode.hg19.chr10.gtf`
>            - *"Length of the genomic sequence around annotated junctions*": `100`
>            - *"Per gene/transcript output*": `Per gene read counts (GeneCounts)`
>    - *"Use 2-pass mapping for more sensitive novel splice junction discovery"*: `Yes, I want to use multi-sample 2-pass mapping and I have obtained splice junctions database of all samples throught previous 1-pass runs of STAR`
>       - {% icon param-file %} *"Pregenerated splice junctions datasets of your samples"*: `Splicing database`
>    - *"Would you like to set additional output filters?"*: `Yes`
>        - *"Would you like to keep only reads that contain junctions that passed filtering?*": `Yes` (ENCODE option)
>        - *"Maximum number of alignments to output a read's alignment results, plus 1*": `20` (ENCODE option)
>        - *"Maximum number of mismatches to output an alignment, plus 1*": `999` (ENCODE option)
>        - *"Maximum ratio of mismatches to read length*": `0.04` (ENCODE option)
>    - In *"Algorithmic settings"*:
>        - *"Configure seed, alignment and limits options*": `Extended parameter list`
>            -  In *"Alignment parameters"*:
>                - *"Minimum intron size*": `20` (ENCODE option)
>                - *"Maximum intron size*": `1000000` (ENCODE option)
>                - *"Maximum gap between two mates*": `1000000` (ENCODE option)
>                - *"Minimum overhang for spliced alignments*": `8` (ENCODE option)
>                - *"Minimum overhang for annotated spliced alignments*": `1` (ENCODE option)
>    - *"Compute coverage"*: `Yes in bedgraph format`
>
> 2. Rename the output `RNA STAR on collection X: mapped.bam` as `Mapped collection`
>
>
{: .hands_on}

Before moving to the transcriptome assembly and quantification step, we are going to use **RSeQC** in order to obtain some RNA-seq-specific quality control metrics.

## RNA-seq specific quality control metrics with **RSeQC**

RNA-seq-specific quality control metrics, such as sequencing depth, read distribution and coverage uniformity, are essential to ensure that the RNA-seq data are adequate for transcriptome reconstruction and {AS} analysis. For example, the use of RNA-seq with unsaturated sequencing depth gives imprecise estimations  and fails to detect low abundance splice junctions, limiting the precision of many analyses ({% cite Wang2012 %}).

In this section we will make use of of the **RSeQC** toolkit in order to generate the RNA-seq-specific quality control metrics.

We are going to use the following RSeQC modules:

- **Infer Experiment**: inference of strandedness of RNA-seq library
- **Gene Body Coverage**: compute read coverage over gene bodies
- **Junction Saturation**: check junction saturation
- **Junction Annotation**: compares detected splice junctions to a reference gene model
- **Read Distribution**: calculates how mapped reads are distributed over genome features
- **Inner Distance**: calculate the inner distance (or insert size) between two paired RNA reads

Once all required outputs have been generated, we will integrate them by using **MultiQC** in order to interpret the results.

> <hands-on-title> Raw reads QC</hands-on-title>
> 1. Most of RSeQC tools require a BED12 file with gene annotations. If you don't have a `BED12 annotation` dataset, just generate it with {% tool [Convert GTF to BED12](toolshed.g2.bx.psu.edu/repos/iuc/gtftobed12/gtftobed12/357) %} with the following parameters:
>    - {% icon param-file %} *"GTF File to convert"*: `gencode.hg19.chr10.gtf`
>    - *"Advanced options"*: `Set advanced options`
>        - *"Ignore groups without exons"*: `Yes`
>
> 2. Rename the output as `BED12 annotation`
>
> 3. {% tool [Infer Experiment](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_infer_experiment/5.0.3+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Input BAM file"*: `Mapped collection`
>    - {% icon param-file %} *"Reference gene model"*: `BED12 annotation`
>
> 4. {% tool [Gene body coverage (BAM)](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_geneBody_coverage/5.0.3+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Input BAM file"*: `Mapped collection`
>    - {% icon param-file %} *"Reference gene model"*: `BED12 annotation`
>
> 5. {% tool [Junction Saturation](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_junction_saturation/5.0.3+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Input BAM/SAM file"*: `Mapped collection`
>    - {% icon param-file %} *"Reference gene model"*: `BED12 annotation`
>    - *"Minimum intron length (bp)"*: `20`
>    - *"Output R-Script"*: `Yes`
>
> 6. {% tool [Junction Annotation](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_junction_annotation/5.0.3+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Input BAM/SAM file"*: `Mapped collection`
>    - {% icon param-file %} *"Reference gene model"*: `BED12 annotation`
>    - *"Minimum intron length (bp)"*: `20`
>
> 7. {% tool [Read Distribution](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_read_distribution/5.0.3+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Input BAM/SAM file"*: `Mapped collection`
>    - {% icon param-file %} *"Reference gene model"*: `BED12 annotation`
>
> 8. {% tool [Inner Distance](toolshed.g2.bx.psu.edu/repos/nilesh/rseqc/rseqc_inner_distance/5.0.3+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Input BAM/SAM file"*: `Mapped collection`
>    - {% icon param-file %} *"Reference gene model"*: `BED12 annotation`
>
{: .hands_on}

Now, we will integrate the outputs into **MultiQC**.

> <hands-on-title>Report integration with MultiQC</hands-on-title>
>
> 1. {% tool [MultiQC](toolshed.g2.bx.psu.edu/repos/iuc/multiqc/multiqc/1.11+galaxy1) %} with the following parameters:
>    - In *"Results"*:
>        - {% icon param-repeat %} *"Insert Results"*
>            - *"Which tool was used generate logs?"*: `STAR`
>                - In *"STAR output"*:
>                    - {% icon param-repeat %} *"Insert STAR output"*
>                        - *"Type of STAR output?"*: `Log`
>                            - {% icon param-collection %} *"STAR log output"*: `RNA STAR on collection XXX: log` collection
>                    - {% icon param-repeat %} *"Insert STAR output"*
>                        - *"Type of STAR output?"*: `Gene counts`
>                            - {% icon param-collection %} *"STAR gene counts output"*: `RNA STAR on collection XXX: reads per gene` collection
>        - {% icon param-repeat %} *"Insert Results"*
>            - *"Which tool was used generate logs?"*: `RSeQC`
>                - In *"RSeQC output"*:
>                    - {% icon param-repeat %} *"Insert RSeQC output"*
>                        - *"Type of RSeQC output?"*: `Infer experiment`
>                            - {% icon param-collection %} *"RSeQC infer experiment"*: select `Infer Experiment on collection XXX: RNA-seq experiment configuration` collection
>                    - {% icon param-repeat %} *"Insert RSeQC output"*
>                        - *"Type of RSeQC output?"*: `Read distribution`
>                            - {% icon param-collection %} *"RSeQC read distribution: stats output"*: select `Read Distribution on collection XXX: stats (TXT)` collection
>                    - {% icon param-repeat %} *"Insert RSeQC output"*
>                        - *"Type of RSeQC output?"*: `Junction saturation`
>                            - {% icon param-collection %} *"RSeQC junction saturation: junction saturation plot Rscript file*: select `Junction Saturation on collection XXX: junction saturation (Rscript)` collections
>                    - {% icon param-repeat %} *"Insert RSeQC output"*
>                        - *"Type of RSeQC output?"*: `Junction annotation`
>                            - {% icon param-collection %} *"RSeQC junction annotation: stats file"*: select `Junction Annotation on collection XXX: stats` collections
>                    - {% icon param-repeat %} *"Insert RSeQC output"*
>                        - *"Type of RSeQC output?"*: `Gene body coverage`
>                            - {% icon param-collection %} *"RSeQC gene body coverage: stats file"*: select `Gene Body Coverage (BAM) on collection XXX: stats (TXT)` collections
>                    - {% icon param-repeat %} *"Inner Distance output"*
>                        - *"Type of RSeQC output?"*: `Inner distance`
>                            - {% icon param-collection %} *"RSeQC inner distance: frequency file"*: select `Inner Distance on collection XXX: frequency (TXT)` collections
>
{: .hands_on}


First, we will evaluate the plot corresponding to the **RNA STAR** alignment scores (fig. 4), which will allow us to easily compare the samples to get an overview of the quality of the samples. As a general criteria, we can consider that good quality samples should have at least 75% of the reads uniquely mapped. In our case, of samples have unique mapping values over 90%. Most of the reads asigned to 'Unmapped: too short' are in fact mapping to other chromosomes.

![Figure 04. RNA STAR alignment stats plot](../../images/differential_isoform/star_alignment.png "RNA STAR alignment stats percentage plot. Note that STAR counts a paired-end read as one read.")

Now we can have a look at the **RSeQC** results;  we will evaluate the RSeQC **Read Distribution plot** (fig. 5).

![Figure 05. RSeQC read distribution plot](../../images/differential_isoform/rseqc_read_distribution_plot.png "RSeQC read distribution. This module will calculate how mapped reads were distributed over genome feature (like CDS exon, 5’UTR exon, 3’ UTR exon, Intron, Intergenic regions). Distribution of all features (A). Distribution of low frequency features (B).")

According the figure 5.A, all samples show show a similar trend, both in ASP14 (cancer) and ASP13_doxycycline (oncogene-depleted) samples, with most reads mapping on CDS exons (around 66%), 5'UTR (around 2-3%) and 3'UTR (around 20%). We can also evaluate the frequency of less common features by hidding the main ones; it can be done by clicking in the correspoding feature label (fig. 5B). However, we can see that the profile is consistent between replicates but is slightly different between conditions. This is not an ideal case as we cannot rule out if this is biological or technical as the library may have not been prepared at the same time.

Now we will evaluate the results of the **Infer Experiment** module, which allows to speculate the experimental design (whether sequencing is strand-specific, and if so, how reads are stranded) by sampling a subset of reads from the BAM file and comparing their genome coordinates and strands with those of the reference gene model ({% cite Wang2012 %}).

![Figure 06. RSeQC infer experiment plot](../../images/differential_isoform/rseqc_infer_experiment_plot.png "RSeQC Infer Experiment plot. It counts the percentage of reads and read pairs that match the strandedness of overlapping transcripts. It can be used to infer whether RNA-seq library preps are stranded (sense or antisense).")

As can be appreciated in the image, the proportion of reads assigned as *sense* is close to null and the ones assigned as *antisense* are around 80%, which indicates that in that case our RNA-seq data is strand specific in the reverse orientation. This can be also evaluated with the STAR Gene Counts statistics as in the Reference-based RNA-seq tutorial.

Now, let's evaluate the results generated by the **Gene Body Coverage** module. It scales all transcripts to 100 nt and calculates the number of reads covering each nucleotide position. The plot generated from this information illustrates the coverage profile along the gene body, defined as the entire gene from the transcription start site to the end of the transcript (fig. 7).

![Figure 07. RSeQC gene body coverage plot](../../images/differential_isoform/rseqc_gene_body_coverage_plot.png "RSeQC gene body coverage plot. It calculates read coverage over gene bodies. This is used to check if reads coverage is uniform and if there is any 5' or 3' bias.")

The gene body coverage pattern is highly influenced by the RNA-seq protocol, and it is useful for identifying artifacts such as 3' skew in libraries. For example, a skew towards increased 3' coverage can happen in degraded samples prepared with poly-A selection. According the figure 7, there're not big bias in our reads as a result of sequencing technical problems.

Other important metric for {AS} analysis is the one provided by the **Junction Saturation** module, which allows to determine if the current sequencing depth is sufficient to perform {AS} analyses by comparing the detected splice junctions to reference gene model (fig. 8). Since for a well annotated organism both the number of expressed genes and spliced junctions is considered to be almost fixed, we expect the number of known junctions to reach a plateau if the current sequencing depth is almost saturated for known junction detection. Using an unsaturated sequencing depth would miss many rare splice junctions ({% cite Wang2012 %}). As we can appreciate in the plot (fig. 8.A), the known junctions tend to stabilize around 8.000, which indicates that the read sequencing depth is good enough for performing the {AS} analysis.

> <comment-title>RSeQC junction saturation details</comment-title>
>
> This approach helps identify if the sequencing depth is sufficient for {AS} analysis. However, it relies on the reference gene model for junction comparison, which might not be complete or accurate for all organisms. In addition, it might not provide enough information for novel junction detection, as the sequencing depth might still be insufficient for detecting new splice junctions.
>
{: .comment}

![Figure 08. RSeQC junction saturation plot](../../images/differential_isoform/rseqc_junction_saturation_plot.png "RSeQC junction saturation. Saturation is checked by re-sampling the alignments from the BAM file, and the splice junctions from each subset is detected (green) and and compared them to the reference model (grey).")

Regarding the novel junctions (fig. 8.B), we can appreciate that the number of new splice junctions increase with the coverage.

After confirming that the saturation level is good enough, now we will check the output generated by the **RSeQC junction annotation** module; it allows to evaluate both splice junctions (multiple reads show the same splicing event) and splice events (single read level) (fig. 9).

![Figure 09. RSeQC junction annotation plot](../../images/differential_isoform/rseqc_junction_annotation_junctions_plot.png "RSeQC junction annotation. The detected junctions and events are divided in three exclusive categories: known splicing junctions (blue), partial novel splicing junction (one of the splice site is novel) (grey) and new splicing junctions (green). Splice events refer to the number of times a RNA-read is spliced (A). Splice junctions correspond to multiple splicing events spanning the same intron.")

According to the results, despite the relatively low (around 0.3%) proportion of reads supporting new (or partially new) splicing events (fig. 9.B), they represent a large proportion of junctions (fig. 9.A).

![Figure 10. RSeQC inner distance plot](../../images/differential_isoform/rseqc_inner_distance_plot.png "RSeQC inner distance. The plot represents gap sizes between R1 and R2 so the fragment size minus the size of both reads.")

Finally from the the Inner Distance plot (fig. 10), we can infer some additional information about the degree of degradation of the samples. Usually very short inner distances appear in old or degraded samples; in addition values can be negative if the two fragments overlap. In our case, we can see that most of reads overlap (this was already seen with the fastp report which is more informative) and that the average fragment size is 150bp (-50 inner distance + 100bp read 1 + 100bp read2).

After evaluating the quality of the RNA-seq data, we can start with the transcriptome assembly step.

# Transcriptome assembly, quantification and evaluation

Once the mapping is done, in this section we will use the information contained in the BAM files to carry out the assembly of the transcriptomes, as well as the quantification of the transcripts. In addition, we will evaluate the transcriptome assemblies quality.

## Reference-based transcriptome assembly and quantification with **StringTie**

**StringTie** is a fast and highly efficient assembler of RNA-seq alignments into potential transcripts. It uses a network flow algorithm to reconstruct transcripts and quantitate them simultaneously. This algorithm is combined with an assembly method to merge read pairs into full fragments in the initial phase ({% cite Kovaka2019 %}, {% cite Pertea2015 %}).

> <comment-title>StringTie algorithm</comment-title>
>
> **StringTie** first groups the reads into clusters, collapsing the reads that align to the identical location on the genome and keeping a count of how many alignments were collapsed, then creates a splice graph for each cluster from which it identifies transcripts, and then for each transcript it creates a separate flow network to estimate its expression level using a maximum flow algorithm ({% cite Pertea2015 %}) (fig. 11). The algorithm groups the reads into distinct gene loci and then assembles each locus into as many isoforms as needed to explain the data. It begins with the most highly-expressed transcript, assembling and quantitating it simultaneously. The process is repeated until all reads are used, or until the number of remaining reads is below a user-adjustable level of transcriptional noise.
>
> ![Figure 11. StringTie algorithm details](../../images/differential_isoform/stringtie_algorithm.png "Transcript assembly pipeline for StringTie. It begins with a set of RNA-seq reads that have been mapped to the genome. StringTie iteratively extracts the heaviest path from a splice graph, constructs a flow network, computes maximum flow to estimate abundance, and then updates the splice graph by removing reads that were assigned by the flow algorithm. This process repeats until all reads have been assigned. Source: Perea et al., 2015")
>
> **StringTie** uses an aggressive strategy for identifying and removing spurious spliced alignments. If a spliced read is aligned with more than 1% mismatches, keeping in mind that Illumina sequencers have an error rate < 0.5%, then **StringTie** requires 25% more reads than usual to support that particular spliced alignment. In addition, if a spliced read spans a very long intron, **StringTie** accepts that alignment only if a larger anchor of 25 bp is present on both sides of the splice site. Here the term *anchor* refers to the portion of the read aligned within the exon beginning at the exon-intron boundary ({% cite Kovaka2019 %}).
>
>
{: .comment}

Transcriptome reconstruction, which involves assembling RNA-seq reads into transcription units, is a complex computational task due to three main challenges. Firstly, gene expression levels vary widely, with some genes having low read representation, complicating their identification. Secondly, reads arise from both mature mRNA and incompletely spliced precursor RNA, making it challenging to distinguish mature transcripts. Lastly, the short length of reads coupled with the presence of multiple isoforms per gene makes it difficult to determine the specific isoform responsible for each read ({% cite Garber2011 %}).

Then, let's start with the transcriptome assemby.

> <hands-on-title>Transcriptome assembly with StringTie</hands-on-title>
>
> 1. {% tool [StringTie](toolshed.g2.bx.psu.edu/repos/iuc/stringtie/stringtie/2.2.3+galaxy0) %} with the following parameters:
>    - *"Input options"*: `Short reads`
>        - {% icon param-collection %} *"Input short mapped reads"*: `Mapped collection`
>    - *"Specify strand information"*: `Reverse (RF)`
>    - *"Use a reference file to guide assembly?"*: `Use reference GTF/GFF3`
>        - *"Reference file"*: `Use a file from history`
>            - {% icon param-file %} *"GTF/GFF3 dataset to guide assembly"*: `gencode.hg19.chr10.gtf`
>        - *"Use Reference transcripts only?"*: `No`
>    - In *"Advanced options"*:
>        - "*Minimum junction coverage*": `3`
>
> 2. Rename the generated collection as `Assembled transcripts coordinates`
>
> 3. {% tool [StringTie merge](toolshed.g2.bx.psu.edu/repos/iuc/stringtie/stringtie_merge/2.2.3+galaxy0) %} with the following parameters:
>    - {% icon param-collection %} *"Transcripts"*: `Assembled transcripts coordinates` (output of **StringTie**)
>    - {% icon param-file %} *"Reference annotation to include in the merging"*: `gencode.hg19.chr10.gtf`
>
> 4. Rename the output as `Reference transcriptome annotation`
>
>    > <question-title></question-title>
>    >
>    > 1. How many lines are there in the `Assembled transcripts coordinates`?
>    > 2. How many lines are there in the original GTF?
>    > 3. How many lines are there in the `Reference transcriptome annotation`?
>    > 4. What can you conclude?
>    >
>    >    > <solution-title></solution-title>
>    >    >
>    >    > 1. There are about 25k lines.
>    >    > 2. There are about 93k lines.
>    >    > 3. There are about 70k lines.
>    >    > 4. Not much as the number of lines is not informative enough, we need an appropriate tool to compare those GTFs. However, a quick way to check why these numbers are different is to use **Count occurences of each record** on column 3 which is the feature type. This would tell you that:
>    >    >    - The original GTF has 2260 genes, 6503 transcripts and 42758 exons and other coding information.
>    >    >    - The As


topic: transcriptomics
tutorial: rna-seq-analysis-with-askomics-it
title: RNA-Seq analysis with AskOmics Interactive Tool
difficulty: intermediate
time_estimation: 2H
tools_json: []
requirements_json: []
tags_json: []
content_hash: e69694830fd46a80b6b1ca9be8d82aab
last_modified: 2026-02-26T21:12:18.570219
zenodo_link: https://zenodo.org/record/3925863
workflows_json: []
url:
https://training.galaxyproject.org/training-material/topics/transcriptomics/tutorials/rna-seq-analysis-with-askomics-it/tutorial.html

content:
AskOmics is a web application for data integration and querying using the Semantic Web technologies. It helps users to convert multiple data sources (CSV/TSV files, GFF and BED annotation) into "RDF triples" and store them in a specific kind of database: an "RDF triplestore". Under this form, data can then be queried using a specific language: "SPARQL". AskOmics hides the complexity of these technologies and allows to perform complex queries using a user-friendly interface.

<!-- AskOmics for RNA-Seq -->
AskOmics comes in useful for cross-referencing results datasets with various reference data. For example, in RNA-Seq studies, we often need to filter the results on the fold change and the p-value, to get the most significant differentially expressed genes. If you are studying a particular phenotype and already know the position of some QTL associated to this phenotype, you would then want to find the positions of the differentially expressed genes and determine which gene is located within one of those QTL. Finally, you would want to know if these genes have human homologs, and use the neXtProt database to get the location of the proteins coded by the homologs. The whole process involves several tools to parse and manipulate the different data format, and to map datasets on each other. AskOmics offer a solution to 1) automatically convert the multiple formats to RDF, 2) use a user-friendly interface to perform complex SPARQL queries on the RDF datasets to find the genes you are interested in, and 3) connect external SPARQL databases and link external data with your own.

<!-- The data -->
In this tutorial, we will use results from a differential expression analysis. This file is provided for you below. You could also generate the file yourself, by following the [RNA-Seq counts to gene tutorial]({% link topics/transcriptomics/tutorials/rna-seq-counts-to-genes/tutorial.md %}). The file used here was generated from limma-voom but you could use a file from any RNA-seq differential expression tool, such as edgeR or DESeq2, as long as it contains the required columns (see below).

The differentially expressed results will be linked to the official mouse genome annotation, in general feature format (GFF). The file provided is a subset of the mouse annotation (GRCm38.p6) obtained from [Ensembl](http://www.ensembl.org/Mus_musculus/Info/Index).

We will use a file containing quantitative trait loci (QTL) information, to find if our differentially expressed genes are located inside a known QTL. This file is a subset of a query performed on [Mouse Genome Informatics](http://www.informatics.jax.org).

A file containing all homologies between mouse and human will be used to get the human homolog genes. This file is provided by [MGI](http://www.informatics.jax.org/downloads/reports/index.html#homology).

In the differentially expressed file, and the homologs file, gene are described by a symbol (e.g. Pwgrq10). However, in the annotation file and neXtProt database, gene are represented by Ensembl id (e.g. ENSMUSG00000025969). To link the 2 datasets, we will need a file to map the gene symbol with Ensembl id. This file provided for you was previously generated with an AskOmics query on the mouse annotation file and the homolog file.

To link the human gene with neXtProt database, we will use the RDF abstraction of neXtProt. This file was obtained using the [Abstractor](https://github.com/askomics/abstractor) tool.

> <details-title>Abstraction</details-title>
> During the integration step, AskOmics builds an RDF description of the data: the **abstraction**. This abstraction is used to explore the data and build the query.
> AskOmics can also integrate **abstraction** of distant endpoint. Abstraction are obtained using [abstractor](https://github.com/askomics/abstractor), a python package to generate RDF abstractions from distant endpoints.
> The query builder interface is used to create a path through the **abstraction** of each ressources. The path is converted to a SPARQL query that is sent to the multiple SPARQL endpoint.
{: .details}

> <agenda-title></agenda-title>
>
> In this tutorial, we will cover:
>
> 1. TOC
> {:toc}
>
{: .agenda}

# Preparing the inputs

We will use four files for this analysis:

 * **Differentially expressed results file** (genes in rows, and 4 required columns: identifier (ENTREZID), gene symbol (SYMBOL), log fold change (logFC) and adjusted P values (adj.P.Val))
 * **Reference genome annotation file** (in GFF format)
 * **QTL file** (QTL in rows, with 5 required columns: identifier, chromosome, start, end and name)
 * **Homolog file** (TSV of 13 columns including homolog id, organism name and gene symbol)
 * **Correspondence file between gene symbol and Ensembl id** (TSV of 3 columns: symbol, the corresponding Ensembl id (mouse and human)
 * **neXtProt abstraction** (RDF data description of neXtProt database in turtle format)

## Import data

> <hands-on-title>Data upload</hands-on-title>
>
> 1. Create a new history for this RNA-seq exercise e.g. `RNA-seq AskOmics`
>
>    {% snippet faqs/galaxy/histories_create_new.md %}
>
>    {% snippet faqs/galaxy/histories_rename.md %}
>
> 2. Import the files.
>
>    To import the files, there are two options:
>    - Option 1: From a shared data library if available (ask your instructor)
>    - Option 2: From [Zenodo](https://zenodo.org/record/3950862)
>
>    {% snippet faqs/galaxy/datasets_import_via_link.md %}
>
>    {% snippet faqs/galaxy/datasets_import_from_data_library.md %}
>
>    - You can paste the links below into the **Paste/Fetch** box:
>
>      ```
>      https://zenodo.org/record/2529117/files/limma-voom_luminalpregnant-luminallactate
>      https://zenodo.org/record/3950862/files/Mus_musculus.GRCm38.98.subset.gff3
>      https://zenodo.org/record/3950862/files/Symbol.tsv
>      https://zenodo.org/record/3950862/files/MGIBatchReport_Qtl_Subset.txt
>      https://zenodo.org/record/3950862/files/HOM_MouseHumanSequence.rpt
>      https://zenodo.org/record/3950862/files/nextprot_abstraction.ttl
>      ```
>
> 2. Rename the files using the {% icon galaxy-pencil %} (pencil) icon.
>    - limma-voom_luminalpregnant-luminallactate to `DE results`
>    - Mus_musculus.GRCm38.98.subset.gff3 to `Mus musculus annotation`
>    - Symbol.tsv to `Gene Symbols`
>    - MGIBatchReport_Qtl_Subset.txt to `QTL`
>    - HOM_MouseHumanSequence.rpt to `Homolog groups`
>    - nextprot_asbtraction.ttl to `neXtProt abstraction`
>
> 3. Check every datatype.
>    - DE results: `tabular`
>    - Mus musculus annotation: `gff`
>    - Gene Symbol: `tabular`
>    - QTL: `tabular`
>    - Homolog groups: `tabular`
>    - neXtprot abstraction: `ttl`
>
> If the datatypes are wrong, please change it.
>
> {% snippet faqs/galaxy/datasets_change_datatype.md %}
{: .hands_on}

Click on the {% icon galaxy-eye %} (eye) icon and take a look at the uploaded files.

Two step are necessary to get our data converted into RDF triples. The first step is to upload the Galaxy datasets into the AskOmics server. The second step is to integrate the uploaded data into the RDF triplestore.

# Upload inputs into AskOmics

We will first launch an AskOmics interactive tool, and upload the data into it.

## Launch AskOmics Interactive Tool

> <hands-on-title>Launch AskOmics IT</hands-on-title>
> 1. **AskOmics** a visual SPARQL query builder {% icon tool %} to launch the Interactive Tool
>    - {% icon param-file %} *"Datasets to load into AskOmics"*: `DE results`, `Mus musculus annotation`, `Gene Symbols`, `QTL`, `Homolog groups` and `neXtProt abstraction`
{: .hands_on}

Wait a few seconds (or minutes if computing resources are busy) for AskOmics to be ready to use. A **view** link should appear in the confirmation box just after clicking on the **Execute** button.

AskOmics is an *Interactive tool*. It means that when you launch it, it will stay in running state (yellow background) in your History. As long as it stays in this running state, you can access it by looking in the "User" > "Active Interactive Tools" menu (click on its name to view it). When you no longer need it, you can stop it by deleting it from your history, or using the "Stop" button in the "User" > "Active Interactive Tools" page.

Keep in mind that as long as this tool runs, it uses computing resources, so don't forget to stop it when you no longer have use for it.

Once the AskOmics Interactive Tool is ready, you should see a start page looking like this:

![home page](images/home.png "AskOmics home page")

 You can see that there is no data available yet. It's because data needs to be integrated: it is the next step.

# Integrate input files into AskOmics

AskOmics conversion into RDF is called *integration*.

On the **Files** page (link at the top of the page), you will see the files you uploaded from Galaxy. We will now integrate all these files.

> <hands-on-title>Integrate data</hands-on-title>
> 1. Got to the **Files** page
> 2. Select all the input files
> 3. Click on the **Integrate** button
{: .hands_on}

![files page](images/files.png "AskOmics files page")

You will land on the **Integrate** page that shows a preview of the data present in each selected file, depending of its data type.

## Integrate GFF files

The GFF preview shows the entities that the file contains. We need to select the entities we want to be integrated.

The `Mus musculus annotation` file we're using contains gene and mRNA entities, and we will need both in the rest of the tutorial.

> <hands-on-title>Integrate `Mus musculus annotation`</hands-on-title>
> 1. Search for `Mus musculus annotation (preview)`
> 2. Select `gene` and `mRNA`
> 3. Click on the **Integrate (private dataset)** button
> ![mus musculus annotation preview](images/mus_musculus_annotation_preview.png "Mus musculus annotation preview")
{: .hands_on}


## Integration of tabular (TSV) files

The TSV preview shows an HTML table representing the first lines of the TSV file. During integration, AskOmics will convert the file using the header.

<!-- First col: entity, then, attribute -->
The first column of a TSV file will be the *entity* name. Other columns of the file will be *attributes* of the *entity*. *Labels* of the *entity* and *attributes* will be set by the header. Each *label* can be edited by clicking on it.

<!-- Attribute types -->
Entity and attributes can have special types. The types are defined with the select box below the header. An *entity* can be a *start entity* or an *entity*. A *start entity* means that the entity may be used to start a query on the AskOmics homepage.

Attributes can take the following types:
- Numeric: if all the values of the column are numeric
- Text: if all the values are strings
- Category: if there is a limited number of repeated values (e.g. 'green', 'yellow' and 'red', each one found in multiple lines)

If the entity describes a locatable element on a genome:
- Reference: chromosome
- Strand: strand
- Start: start position
- End: end position

<!-- Relation -->
A column can also represent a relation between the *entity* to another. In this case, the header have to be named `relationName@TargetedEntity` and the type *Directed* or *Symetric* relation. A *Directed* relation is a relation from this entity to the targeted one (e.g. A is B's father, but B is not A's father). A *Symetric relation* is a relation that works in both directions (e.g. A loves B, and B loves A).

> <hands-on-title>Integrate `DE results`</hands-on-title>
> 1. Search for `DE results (preview)`
> 2. Edit attribute names and types:
>   - change `ENTREZ ID` to `Differential Expression` and set type to *start entity*
>   - change `SYMBOL` to `linkedTo@Gene Symbol` and set type to *Symetric relation*
>   - change `GENENAME` to `name` and set type to *text*
>   - Keep the other column names and set their types to *numeric*
> 3. **Integrate (private dataset)**
>   ![De results preview](images/de_results_preview.png "DE results preview")
{: .hands_on}

> <hands-on-title>Integrate `Gene symbols`</hands-on-title>
> 1. Search for `Gene symbols (preview)`
> 2. Edit attribute names and types:
>   - change `symbol` to `Gene Symbol` and set type to *entity*
>   - Set `to mouse genes@gene` type to *Symetric relation*
> 3. Click on the **Integrate (private dataset)** button
>   ![Gene symbols preview](images/symbol_to_ensembl_preview.png "Symbol to Ensembl preview")
{: .hands_on}

> <hands-on-title>Integrate `QTL`</hands-on-title>
> 1. Search for `QTL (preview)`
> 2. Edit attribute names and types:
>   - change `Input` to `QTL` and set type to *start entity*
>   - set `Chr` type to *Reference*
>   - set `Start` type to *Start*
>   - set `End` type to *End*
> 3. Click on the **Integrate (private dataset)** button
>   ![QTL preview](images/qtl_preview.png "QTL preview")
{: .hands_on}

> <hands-on-title>Integrate `Homolog groups`</hands-on-title>
> 1. Search for `Homolog groups (preview)`
> 2. Edit attribute names and types:
>   - change `HomoloGene ID` to `Homolog Group` and set type to *start entity*
>   - set `Common Organism Name` type to *category*
>   - change `Symbol` to `linkedTo@Gene Symbol` and set type to *Directed relation*
>   - Keep the other column names and set their types to *text*
> 3. Click on the **Integrate (private dataset)** button
>   ![Homolog groups preview](images/homolog_groups.png "Homolog groups preview")
{: .hands_on}

## Integration of RDF files

The last dataset we want to integrate is the neXtProt abstraction. This file contains some RDF data that instructs AskOmics how to communicate with a remote RDF database containing [neXtProt](https://www.nextprot.org/) data.

> <hands-on-title>Integrate `neXtProt abstraction`</hands-on-title>
> 1. Search for `neXtProt abstraction (preview)`
> 2. Check that **Distant endpoint** is set to `https://sparql.nextprot.org/sparql` in **advanced options**
> 3. Click on the **Integrate (private dataset)** button
>   ![neXtProt abstraction preview](images/nextprot_abstraction_preview.png "neXtProt abstraction preview")
{: .hands_on}

## Monitor integration

Integration can take some time depending on the file size. The **Datasets** page shows the progress.

> <hands-on-title>track integration progress</hands-on-title>
> 1. Go to the **Dataset** page
> 2. Wait for all datasets to be in *success* state
>   ![dataset](images/datasets.png "Datasets table")
{: .hands_on}

# Query

Once all the data of interest is integrated (converted to RDF), its time to query them. Querying RDF data is done by using the SPARQL language. Fortunately, AskOmics provides a user-friendly interface to build SPARQL queries without having to learn the SPARQL language.

## Query builder overview

### Simple query

The first step to build a query is to choose a start point for the query.

![ask](images/ask.png "ask page")


> <hands-on-title>Start a query</hands-on-title>
> 1. Go to the **Ask!** page
> 2. Select the *Differential Expression* entity
> 3. **Start!**
{: .hands_on}


Once the start entity is chosen, the query builder is displayed.


The query builder is composed of a graph. Nodes represents *entities* and links represents *relations* between entities. The selected entity is surrounded by a red circle. Links and other entities are dotted and lighter because there are not instantiated.

![query builder](images/query_builder.png "Query builder, Differential Expression is the selected entity, Gene Symbol is a suggested entity")

On the right, attributes of the selected entity are displayed as attribute boxes. Each box has an eye icon: an opened eye means the attribute will be displayed on the results.

> <hands-on-title>Ask for all Differential Expression and display some attributes</hands-on-title>
> 1. Display `logFC` and `adj.P.val` by clicking on the eye icon
> 2. **Run & preview**
> ![preview results](images/preview_results.png "Results preview")
{: .hands_on}


**Run & preview** launch the query with a limit of 30 rows returned. We use this button to get an idea of the results returned.


### Filter on attributes

Next query will search for all over-expressed genes. Genes are considered over-expressed if the log fold change is > 2. We are only interested by significant results (Adj P value ≤ 0.05)

Back to the query builder,

> <hands-on-title>Filter attributes to get significant over-expressed genes</hands-on-title>
> 1. Filter `logFC` with `> 2`
> 2. Filter `adj.P.val` with `≤ 0.05`
> 2. **Run & preview**
> ![preview filtered results](images/preview_results_filtered.png "Filtered results preview")
{: .hands_on}

The preview shows only significantly over-expressed genes.

### Filter on relations

Now that we have found our genes of interest, we will link these genes to the reference genome to get information about their location.

To constraint on relation, we have to click on suggested nodes, linked to our entity of interest.

> <hands-on-title>Link `De results` to `gene` using `Gene Symbol`</hands-on-title>
> 1. First, hide `Label`, `logFC` and `adj.P.val` of `Differential Expression` using the eye icon
> 2. Instantiate `Gene Symbol` by clicking on the suggested node, and hide his `Label` using the eye icon
> 3. Instantiate `gene` by clicking on the `gene` node
> 2. **Run & preview**
> ![gene query](images/gene_query.png "Gene query")
{: .hands_on}

Results now show the Ensembl id of our over-expressed genes. We have now access to all the information about the `gene` entity contained in the GFF file. For example, we can filter on chromosome and display chromosome and strand to get information about gene location.

> <hands-on-title>Filter `gene`</hands-on-title>
> 1. Show `reference` and `strand` using the eye icon
> 2. Filter `reference` by selecting `X` chromosome
> 3. Filter `strand` by selecting `+` strand
> 4. **Run & preview**
> ![gene filter](images/gene_filter.png "Gene filtering")
{: .hands_on}


### Query on the position of elements on the genome.

AskOmics is able to perform special queries between entities that are locatable. These queries are:

- Entities overlapping another one
- Entities included in another entity

> <details-title>FALDO ontology</details-title>
> The [FALDO](https://bioportal.bioontology.org/ontologies/FALDO) ontology describes sequence feature positions and regions. AskOmics uses FALDO ontology to represent entity positions. GFF are using FALDO, as well as TSV entities with chromosome, strand, start and end.
{: .details}

On the query builder interface, locatable entities are represented with a green circle and relations based on location are represented as green arrow.

> <hands-on-title>Filter `gene`</hands-on-title>
> 1. First, remove the reference filter (unselect `X` using `ctrl`+`click`)
> 1. Remove the strand filter (unselect `+` using `ctrl`+`click`)
> 2. Hide `reference` `strand` using the eye
> 3. Instantiate `QTL`
> 4. Click on the link between `gene` and `QTL` to edit the relation
> 5. Check that the relation is `gene` `included in` `QTL` `on the same reference` with `strict` ticked
> 6. **Run & preview**
> ![FALDO query](images/query_builder_position.png "FALDO query")
{: .hands_on}


To go further, we can filter on `QTL` to refine the results.


> <hands-on-title>Filter `gene`</hands-on-title>
> 1. Go back to the `QTL` node
> 2. Show the `Name` attribute using the eye icon
> 3. Filter the name with a `regexp` with `growth`
> 4. **Run & preview**
{: .hands_on}

From now, our query is "All Genes that are over-expressed (logFC > 2 and FDR ≤ 0.05) and located on a QTL that is related to growth". We can save this results with the *Run & save* button.

> <hands-on-title>Save a result</hands-on-title>
> 1. **Run & save**
{: .hands_on}

### Use neXtProt distant data to refine results

[neXtProt](https://www.nextprot.org) is a comprehensive human-centric discovery platform, offering its users a seamless integration of and navigation through protein-related data. It offer a [SPARQL endpoint](https://sparql.nextprot.org/sparql) that can be interrogated with AskOmics.

Since we added the neXtProt abstraction into our AskOmics instance, we can link our data to neXtProt.

> <hands-on-title>Find human homolog genes</hands-on-title>
> 1. Go back to the `gene` node
> 2. instantiate `Gene Symbol` and hide his `Label`
> 3. Instantiate `Homolog Group`, hide his label and filter his `Common Organism Name` with `human`
> ![Organism name filter](images/filter_organism_name.png "Organism name filter")
> 4. From `Homolog Group`, instantiate another `Gene Symbol` and hide his `Label`
> 5. Finally, follow the `to neXtProt Gene` link and instantiate `Gene` (with a capital G)
> 5. **Run & preview**
{: .hands_on}

The query we've just built asks for the human homologs of our over-expressed genes. We use the `Gene Symbol` to get information from the neXtProt database. AskOmics converts the query into small SPARQL subqueries and send them to the local database and to the remote neXtProt endpoint.

Now we are linked to the neXtProt database, we can obtain information about the proteins encoded by these genes, as well as their location in the cell.

> <hands-on-title>Get the protein and their location</hands-on-title>
> 1. Instantiate `Entry`
> 2. Instantiate `Isoform` and hide the `Label`
> 3. Many nodes are connected to `Isoform`. Use the *Filter links* field to filter nodes linked with a link named `location`
> ![Filter links](images/filter_links.png "Filter links")
> 4. Instantiate the `Subcellular Location` node and hide `Uri`
> 5. Use the *Filter node* field to filter nodes with "location" in their name
> 6. Instantiate `Uniprot subcellular Location CV` (you can use the node filter to clear up the screen)
> 7. **Run & preview**
{: .hands_on}

Finally, our query is "All genes that are over-expressed and located on a QTL that is related to growth, their human homologs and the location of the proteins coded by this genes". We will save it to the results.

> <hands-on-title>Save a result</hands-on-title>
> 1. **Run & save**
{: .hands_on}


## Results management

The results page displays the saved queries. Queries are sorted by creation date. At the end of the table, action buttons can be used to preview the result, download or send it to Galaxy history.

> <hands-on-title>Edit query name</hands-on-title>
> 1. Go to the *Results* page
> 2. Use the *Preview* button to check the result
> 3. Click on the name to rename the two query with `Over-expressed genes on a growth QTL` and `Over-expressed genes on a growth QTL, their human homologs and protein location` (press enter key to validate)
{: .hands_on}

![preview table](images/results_table.png "Results table")

The **Action** column contain button to perform certain action:

- Preview: show a results preview on the bottom of the table
- Download: Download the results (TSV file)
- Edit: Edit the query with the query builder
- SPARQL: edit the query with a SPARQL editor for advanced users
- Send results to Galaxy: send the results (TSV file) to the most recently used Galaxy history
- Send query to Galaxy: send the query representation (json file) to the most recently used Galaxy history

> <hands-on-title>Send results to Galaxy</hands-on-title>
> 1. Click on **Send results to Galaxy** on each query to send them to the last used Galaxy history
> 2. Get back to galaxy and wait for the dataset (reload if needed)
{: .hands_on}

![history results](images/galaxy_history_results.png "Galaxy history with the two results")

Now that you have used AskOmics to generate this final tabular file, you can continue analysing it with other Galaxy tools.
If you are done, don't forget to close the AskOmics instance by going to the “User” > “Active Interactive Tools” page.

# Conclusion


In this tutorial we have seen how to use AskOmics Interactive Tool. We launch the tools with a set of input files, then we have integrated these files into RDF and finally, we built complex queries over this local datasets and neXtProt to answer a biological question.


