-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ac20712
Showing
72 changed files
with
5,721 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Sphinx build info version 1 | ||
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. | ||
config: 58d3e5e0f064e9761f845a9c541a4b0e | ||
tags: 645f666f9bcd5a90fca523b33c5a78b7 |
Binary file not shown.
Binary file not shown.
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
.. Genes2Genes documentation master file, created by | ||
sphinx-quickstart on Wed Aug 16 09:01:25 2023. | ||
You can adapt this file completely to your liking, but it should at least | ||
contain the root `toctree` directive. | ||
Genes2Genes | ||
======================================= | ||
|
||
**A framework for single-cell pseudotime trajectory alignment** | ||
|
||
.. contents:: Contents | ||
|
||
Genes2Genes (G2G) is a new Python framework for aligning single-cell pseudotime trajectories of gene expression between any reference and query for a pairwise comparison such as: | ||
|
||
* Organoid vs. Reference tissue | ||
* Control vs. Treatment | ||
* Healthy vs. Disease | ||
|
||
Trajectory alignment: What & Why? | ||
########### | ||
|
||
A single-cell trajectory describes the transcriptomic state of cells along some axis of progression (such as time), due to undergoing some dynamic process (e.g. cell differentiation, treatment response, or disease infection). Given an scRNA-seq profile, there are various tools available today to infer such trajectory by estimating a pseudo ordering of the cells along an axis, commonly referred to as 'pseudotime'. The pseudotime axis of a trajectory can be descritized to represent it as a sequence of discrete time points. Given two such discrete pseudotime sequences of two trajectories, a pairwise alignment between them defines a non-linear mapping between their time points. This mapping could have 1-to-1 matches as well as 1-to-many/many-to-1 matches (a.k.a warps) between the time points, while unmapping the time points which have significantly different transcriptomic states. Below is an example visualization of two cell differentiation trajectories. | ||
|
||
|
||
.. image:: images/DocFigs1.png | ||
:width: 600 | ||
:alt: What is trajectory alignment? | ||
:align: center | ||
|
||
For two trajectories representing single lineages as above, G2G generates an **optimal pairwise trajectory alignment** that captures the matches and mismatches between their time points in sequential order, allowing a user to quantify the degree of similarity between them. | ||
|
||
.. image:: images/DocFigs1-1.png | ||
:width: 600 | ||
:alt: Example mapping | ||
:align: center | ||
| | ||
G2G defines 5 different states of alignment between any two **R** and **Q** time points, corresponding to all possible match and mismatch states. They are: 1-to-1 match (``M``), 1-to-many match (``V``), many-to-1 match (``W``), insertion (``I``) and deletion (``D``). Here, ``I`` or ``D`` refer to a mismatched time point in Q or R, respectively. These states jointly cover the alignment states defined in classical dynamic time warping and biological sequence alignment. | ||
|
||
.. image:: images/DocFigs1-3.png | ||
:width: 600 | ||
:alt: 5 states of alignment | ||
:align: center | ||
| | ||
Accordingly, we can describe any trajectory alignment as a 5-state alignment string. For example, the 5-state alignment string of the above illustrated trajectory alignment is: | ||
|
||
.. code-block:: | ||
IIIMMMWWWIIIDDDMMMIIIIDDDD | ||
This G2G alignment string enables us to identify the time regions of match and mismatch along the trajectories. For instance, we can interpret the above illustrated alignment as follow -- *R and Q trajectories have mid and late mismatches, with the early stage of Q being mismatched, yet starting to match to the early stage of R at the middle of Q's trajectory. Overall, there are 9 R and Q pseudotime pairs getting matched (with 34.62% alignment similarity)*. | ||
|
||
|
||
Outputs from Genes2Genes | ||
########### | ||
|
||
Given an scRNA-seq dataset with their pseudotime estimates and a specified set of genes (e.g. all transcription factors, highly variable genes, biological/signaling pathway genes), G2G generates fully-descriptive alignments for each gene (i.e. **gene-level alignment**), as well as an average (aggregate) alignment (i.e. **cell-level alignment**) across all genes. | ||
|
||
Below is an example gene-level alignment of the gene *JUNB* in T cell differentiation between a pan-fetal reference and an artificial thymic organoid system: | ||
|
||
.. image:: images/DocFigs2.png | ||
:width: 600 | ||
:alt: Example gene-level alignment? | ||
:align: center | ||
| | ||
.. code-block:: | ||
IIIIIDMMMMMMMMIDDDDD | ||
Each gene-level alignment carries its 5-state string, an alignment similarity percentage statistic, and the optimal alignment cost (in *nits* -- the unit measure of information). For the above gene, the aligment similarity is 40%, and the total cost of alignment is 53.47 nits. When the degree of difference in gene expression between the reference and query is high, the alignment cost will also be high. | ||
|
||
G2G uses the inferred gene-level alignments to inform: | ||
|
||
#. **The degree of similarity between the two profiles** as an average percentage of alignment similarity across all the genes tested, | ||
#. **An aggregate cell-level alignment across all genes** to inform the average states of match and mismatch between the two profiles (again represented by a 5-state string), | ||
#. **A ranked list of genes across time (from the most distant to most similar)** based on their alignment similarity percentage statistic, | ||
#. **The diversity of different alignment patterns in genes**, by clustering gene-level alignments to identify different matching and mismatching patterns along time, | ||
|
||
between the two single-cell reference and query profiles in comparison. | ||
|
||
For further downstream analysis, G2G provides a wrapper function to check gene-set overrepresentation analysis of the identified gene-clusters and the list of the top distant (differentially-expressed) genes across time, using `GSEApy <https://github.com/zqfang/GSEApy>`_ Enrichr interface. The user is also able to compute an average alignment across any gene subset of their interest. | ||
|
||
**Note**: G2G has been developed only for single-lineage trajectory comparison. In the case of a trajectory with multiple branches, we recommend separating out the singe-lineage branches before any pairwise comparison. | ||
|
||
Our approach to trajectory alignment | ||
########### | ||
|
||
We employ a **dynamic programming** (DP) based algorithm that can capture both matches and mismatches in gene expression in a unified way. This combines the classical **Gotoh's algorithm** for biological sequence alignment with **dynamic time warping**. Our DP algorithm uses a **Bayesian information-theoretic scoring scheme** based on the **minimum message length** criterion to generate an optimal alignment between two gene trajectories. This scheme evaluates the distributional similarity of gene expression between R and Q for each pair of time points, in terms of both their mean and variance of expression modelled as Gaussian distributions. | ||
For more details on the methods, please see our `manuscript <https://doi.org/10.1101/2023.03.08.531713>`_. | ||
|
||
Getting started | ||
=========== | ||
|
||
For now, G2G needs to be installed from GitHub: | ||
|
||
.. code-block:: shell | ||
pip install git+https://github.com/Teichlab/Genes2Genes.git | ||
The package will be made available soon on PyPi. | ||
|
||
**Input to Gene2Genes** | ||
|
||
G2G takes reference and query input data as ``anndata`` objects, where each ``adata`` object has: | ||
|
||
* log1p normalised gene expression stored at ``adata.X`` | ||
* pseudotime estimates of the cells stored as ``adata.obs['time']`` | ||
|
||
The user can estimate pseudotime of the cells in their datasets using any suitable method available (such as `Diffusion pseudotime <https://scanpy.readthedocs.io/en/stable/generated/scanpy.tl.dpt.html>`_, `Palantir <https://github.com/dpeerlab/Palantir>`_, `GPLVM <https://pyro.ai/examples/gplvm.html>`_, `Monocle <http://cole-trapnell-lab.github.io/monocle-release/>`_ etc.). | ||
For better visualisation and interpretation of the alignment results, we recommend the data to be annotated with their cell types (manually and/or using an automatic annotation tool such as `CellTypist <https://www.celltypist.org>`_). | ||
|
||
Please refer to our `Tutorial <https://github.com/Teichlab/Genes2Genes/blob/main/notebooks/Tutorial.ipynb>`_ for an example analysis between a reference and query dataset from literature. | ||
|
||
Citing Genes2Genes | ||
=========== | ||
Our manuscript is currently available as a `preprint <https://doi.org/10.1101/2023.03.08.531713>`_ at bioRxiv: | ||
|
||
*Sumanaweera, D., Suo, C., Cujba, A.M., Muraro, D., Dann, E., Polanski, K., Steemers, A.S., Lee, W., Oliver, A.J., Park, J.E. and Meyer, K.B., 2023.* **Gene-level alignment of single cell trajectories**. *bioRxiv, pp.2023-03.* | ||
|
||
This publication is part of the `Human Cell Atlas <https://www.humancellatlas.org>`_ | ||
|
||
Funding Acknowledgement | ||
=========== | ||
Marie Skłodowska-Curie grant agreement No: 101026506 (Marie Curie Individual Fellowship) under the European Union’s Horizon 2020 research and innovation programme; Wellcome Trust Ph.D. Fellowship for Clinicians; Wellcome Trust (WT206194); ERC Consolidator Grant (646794); Wellcome Sanger Institute’s Translation Committee Fund. | ||
|
||
|
||
.. toctree:: | ||
:hidden: | ||
|
||
self |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* Compatability shim for jQuery and underscores.js. | ||
* | ||
* Copyright Sphinx contributors | ||
* Released under the two clause BSD licence | ||
*/ | ||
|
||
/** | ||
* small helper function to urldecode strings | ||
* | ||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL | ||
*/ | ||
jQuery.urldecode = function(x) { | ||
if (!x) { | ||
return x | ||
} | ||
return decodeURIComponent(x.replace(/\+/g, ' ')); | ||
}; | ||
|
||
/** | ||
* small helper function to urlencode strings | ||
*/ | ||
jQuery.urlencode = encodeURIComponent; | ||
|
||
/** | ||
* This function returns the parsed url parameters of the | ||
* current request. Multiple values per key are supported, | ||
* it will always return arrays of strings for the value parts. | ||
*/ | ||
jQuery.getQueryParameters = function(s) { | ||
if (typeof s === 'undefined') | ||
s = document.location.search; | ||
var parts = s.substr(s.indexOf('?') + 1).split('&'); | ||
var result = {}; | ||
for (var i = 0; i < parts.length; i++) { | ||
var tmp = parts[i].split('=', 2); | ||
var key = jQuery.urldecode(tmp[0]); | ||
var value = jQuery.urldecode(tmp[1]); | ||
if (key in result) | ||
result[key].push(value); | ||
else | ||
result[key] = [value]; | ||
} | ||
return result; | ||
}; | ||
|
||
/** | ||
* highlight a given string on a jquery object by wrapping it in | ||
* span elements with the given class name. | ||
*/ | ||
jQuery.fn.highlightText = function(text, className) { | ||
function highlight(node, addItems) { | ||
if (node.nodeType === 3) { | ||
var val = node.nodeValue; | ||
var pos = val.toLowerCase().indexOf(text); | ||
if (pos >= 0 && | ||
!jQuery(node.parentNode).hasClass(className) && | ||
!jQuery(node.parentNode).hasClass("nohighlight")) { | ||
var span; | ||
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); | ||
if (isInSVG) { | ||
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); | ||
} else { | ||
span = document.createElement("span"); | ||
span.className = className; | ||
} | ||
span.appendChild(document.createTextNode(val.substr(pos, text.length))); | ||
node.parentNode.insertBefore(span, node.parentNode.insertBefore( | ||
document.createTextNode(val.substr(pos + text.length)), | ||
node.nextSibling)); | ||
node.nodeValue = val.substr(0, pos); | ||
if (isInSVG) { | ||
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); | ||
var bbox = node.parentElement.getBBox(); | ||
rect.x.baseVal.value = bbox.x; | ||
rect.y.baseVal.value = bbox.y; | ||
rect.width.baseVal.value = bbox.width; | ||
rect.height.baseVal.value = bbox.height; | ||
rect.setAttribute('class', className); | ||
addItems.push({ | ||
"parent": node.parentNode, | ||
"target": rect}); | ||
} | ||
} | ||
} | ||
else if (!jQuery(node).is("button, select, textarea")) { | ||
jQuery.each(node.childNodes, function() { | ||
highlight(this, addItems); | ||
}); | ||
} | ||
} | ||
var addItems = []; | ||
var result = this.each(function() { | ||
highlight(this, addItems); | ||
}); | ||
for (var i = 0; i < addItems.length; ++i) { | ||
jQuery(addItems[i].parent).before(addItems[i].target); | ||
} | ||
return result; | ||
}; | ||
|
||
/* | ||
* backward compatibility for jQuery.browser | ||
* This will be supported until firefox bug is fixed. | ||
*/ | ||
if (!jQuery.browser) { | ||
jQuery.uaMatch = function(ua) { | ||
ua = ua.toLowerCase(); | ||
|
||
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || | ||
/(webkit)[ \/]([\w.]+)/.exec(ua) || | ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || | ||
/(msie) ([\w.]+)/.exec(ua) || | ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || | ||
[]; | ||
|
||
return { | ||
browser: match[ 1 ] || "", | ||
version: match[ 2 ] || "0" | ||
}; | ||
}; | ||
jQuery.browser = {}; | ||
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; | ||
} |
Oops, something went wrong.