diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..f9d98d3 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,9 @@ +[run] +branch = True +omit = + */src/* + imaging_transcriptomics/reporting.py + imaging_transcriptomics/pls.py + imaging_transcriptomics/corr.py + imaging_transcriptomics/genes.py + imaging_transcriptomics/script/* diff --git a/.gitignore b/.gitignore index 87edeb4..596488b 100644 --- a/.gitignore +++ b/.gitignore @@ -168,5 +168,7 @@ Network Trash Folder Temporary Items .apdisk +# Strange directories or locally installed packages to ignore .idea/ - +src/ +pyls/ diff --git a/README.md b/README.md index e1d1f37..982dd4c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Imaging Transcriptomics [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5726839.svg)](https://doi.org/10.5281/zenodo.5726839) -[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-red.svg)](https://www.gnu.org/licenses/gpl-3.0) -[![Maintainer](https://img.shields.io/badge/maintainer-alegiac95-orange)](https://github.com/alegiac95) -[![Generic badge](https://img.shields.io/badge/python->=3.6-yellow.svg)](https://www.python.org/doc/versions/) +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![Maintainer](https://img.shields.io/badge/maintainer-alegiac95-blue)](https://github.com/alegiac95) +[![Generic badge](https://img.shields.io/badge/python->=3.6-blue.svg)](https://www.python.org/doc/versions/) [![Documentation Status](https://readthedocs.org/projects/imaging-transcriptomics/badge/?version=latest)](https://imaging-transcriptomics.readthedocs.io/en/latest/?badge=latest) @@ -62,18 +62,23 @@ Once installed the software can be used in two ways: --- To run the standalone script from the terminal use the command: ```shell -imagingtranscriptomics options +imagingtranscriptomics options {corr, pls} ``` The `options` available are: - `-i (--input)`: Path to the imaging file to analise. The path should be given to the program as an absolute path (e.g., `/Users/myusername/Documents/my_scan.nii`, since a relative path could raise permission errors and crashes. The script only accepts imaging files in the NIfTI format (`.nii`, `.nii.gz`). -- `-v (--variance)`: Amount of variance that the PLS components must explain. This _MUST_ be in the range 0-100. - > *__NOTE__*: if the variance given as input is in the range 0-1 the script will treat this as 30% the same way as if the number was in the range 10-100 (e.g., the script treats the inputs `-v 30` and `-v 0.3` in the exact same way and the resulting components will explain 30% of the variance). -- `-n (--ncomp)`: Number of components to be used in the PLS regression. The number _MUST_ be in the range 1-15. -- `--corr`: Run the analysis using Spearman correlation instead of PLS. - > *__NOTE__*: if you run with the `--corr` command no other input is required, apart from the input scan (`-i`). - `-o (--output)` *(optional)*: Path where to save the results. If none is provided the results will be saved in the same directory as the input scan. -> *__WARNING__*: The `-i` flag is _MANDATORY_ to run the script, and so is one, and only one, of the `-n` or `-v` flags. These last two are mutually exclusive, meaning that _ONLY_ one of the two has to be given as input. +- `-r` *(optional)*: Regions of the brain to use for the estimation. Can be either "cort+sub" (or equivalently "all") to use all regions or "cort" to use only cortical regions. +- `--no-gsea` *(optional)*: If this option is provided the GSEA analysis will not be performed. +- `--geneset` *(optional)*: Name of the geneset to use to run GSEA. The + full list is available in the documentation or by running the `imt_gsea + avail` command. +Additionally to the above options two specific commands (required) are available: +- `corr`: To run the correlation analysis. +- `pls`: To run the PLS analysis. If you choose to run the pls analysis + there are two additional options available: + - `--ncomp`: number of components to use in the PLS analysis. + - `--var`: variance to estimate from the data. ### Part of Python script @@ -92,10 +97,12 @@ import imaging_transcriptomics as imt my_data = np.ones(41) # MUST be of size 41 # (corresponds to the regions in left hemisphere of the DK atlas) -analysis = imt.ImagingTranscriptomics(my_data, n_components=1) -analysis.run() +analysis = imt.ImagingTranscriptomics(my_data, method="pls", n_components=1, + regions="cort+sub") +analysis.run(gsea=False) # If instead of running PLS you want to analysze the data with correlation you can run the analysis with: -analysis.run(method="corr") +analysis = imt.ImagingTranscriptomics(my_data, method="corr", + regions="cort+sub") ``` Once completed the results will be part of the `analysis` object and can be accessed with `analysis.gene_results`. @@ -115,7 +122,12 @@ For any problems with the software you can [open an issue in GitHub](https://git If you publish work using `imaging-transcriptomics` as part of your analysis please cite: ->*Imaging transcriptomics: Convergent cellular, transcriptomic, and molecular neuroimaging signatures in the healthy adult human brain.* Daniel Martins, Alessio Giacomel, Steven CR Williams, Federico Turkheimer, Ottavia Dipasquale, Mattia Veronese, PET templates working group. bioRxiv 2021.06.18.448872; doi: [https://doi.org/10.1101/2021.06.18.448872](https://doi.org/10.1101/2021.06.18.448872) +>*Imaging transcriptomics: Convergent cellular, transcriptomic, and +> molecular neuroimaging signatures in the healthy adult human brain.* +> Daniel Martins, Alessio Giacomel, Steven CR Williams, Federico Turkheimer, +> Ottavia Dipasquale, Mattia Veronese, PET templates working group. Cell +> Reports; doi: [https://doi.org/10.1016/j.celrep.2021.110173] +> (https://doi.org/10.1016/j.celrep.2021.110173) >*Imaging-transcriptomics: Second release update (v1.0.2)*.Alessio Giacomel, & Daniel Martins. (2021). Zenodo. https://doi.org/10.5281/zenodo.5726839 diff --git a/docs/conf.py b/docs/conf.py index 568eec2..b3f5be8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,7 +22,7 @@ author = 'Alessio Giacomel, Daniel Martins' # The full version, including alpha/beta/rc tags -release = '1.0.0' +release = '1.1.0' # -- General configuration --------------------------------------------------- diff --git a/imaging_transcriptomics/__init__.py b/imaging_transcriptomics/__init__.py index 981c1b8..f2345b7 100644 --- a/imaging_transcriptomics/__init__.py +++ b/imaging_transcriptomics/__init__.py @@ -1,19 +1,14 @@ -__version__ = "1.0.3" -from . import errors -from . import bootstrap +__version__ = "1.1.0" + from . import inputs -from . import transcriptomics -from . import genes from . import reporting from .transcriptomics import ImagingTranscriptomics -from .bootstrap import bootstrap_pls, bootstrap_genes, bootstrap_correlation from .inputs import ( - load_gene_expression, - load_gene_labels, - get_components, read_scan, extract_average, ) from .genes import GeneResults +from .corr import CorrAnalysis +from .pls import PLSAnalysis diff --git a/imaging_transcriptomics/bootstrap.py b/imaging_transcriptomics/bootstrap.py deleted file mode 100644 index e571ada..0000000 --- a/imaging_transcriptomics/bootstrap.py +++ /dev/null @@ -1,188 +0,0 @@ -import logging -import logging.config -import yaml -from pathlib import Path -from itertools import product -from multiprocessing import Pool -from functools import partial - -from scipy.stats import spearmanr -import numpy -import numpy as np -from tqdm import tqdm -from pyls import pls_regression - -from .genes import GeneResults - -cfg_file_path = Path(__file__).parent / "log_config.yaml" -with open(cfg_file_path, "r") as config_file: - log_cfg = yaml.safe_load(config_file.read()) - -logging.config.dictConfig(log_cfg) -logger = logging.getLogger("bootstrapping") -logger.setLevel(logging.DEBUG) - - -def correlate(corr1, corr2): - """Return correlation similar to MATLAB corr function. - - :param corr1: first element to correlate. - :param corr2: second element to correlate. - """ - return np.corrcoef(np.hstack((corr1, corr2)), rowvar=False)[0, 1:] - - -def bootstrap_pls(x, y, y_perm, dim, iterations=1_000): - """Return a coefficient of determination (R^2) and a p value from the bootstrapping on the PLS regression. - - The function calculates for each of the N ``iterations`` the value of the coefficient of determination on the - permuted data and determines how many times this is at least equal to the coefficient of determination with the - original data. - - :param x: X data for the PLS regression (in our case the zscore of the gene expression data) - :param y: Y data for the PLS regression (in our case the zscore of the average of the ROIs) - :param y_perm: matrix with the permuted Y data. This should have a number of rows equal to the original data and - number of columns equal to the number of iterations. - :param int dim: number of PLS components to use for the analysis. - :param int iterations: number of bootstrap iterations. - - :return R_boot: array of dimension ``dim`` with the coefficient of determination for each PLS component. - :return p_boot: array of dimension ``dim`` with the p value for each PLS component. - """ - R_boot = np.zeros(dim) - p_boot = np.zeros(dim) - for component in range(1, dim + 1): - pls_results = pls_regression(x, y, n_components=component, n_perm=0, n_boot=0) - exp_var = pls_results.get("varexp") - temp = 100 * exp_var.cumsum(axis=0) - R_squared = temp[component - 1] - R_sq = np.zeros(iterations) - for i in tqdm( - range(1000), - desc=f"Bootstrapping on PLS component {component}", - unit=" iterations", - ): - y_data = y_perm[:, i].reshape(41, 1) - _result = pls_regression( - x, y_data, n_components=component, n_perm=0, n_boot=0 - ) - _exp_var = 100 * np.cumsum(_result.get("varexp")) - R_sq[i] = _exp_var[component - 1] - R_boot[component - 1] = R_squared - p_boot[component - 1] = ( - float(len(R_sq[numpy.nonzero(R_sq >= R_squared)])) / iterations - ) - logger.debug( - "Computed components p value(s) and coefficient(s) of determination: \n R: %s \n p: %s", - R_boot, - p_boot, - ) - return R_boot, p_boot - - -def bootstrap_genes(x_data, y, n_components, y_norm, genes, n_iterations=1000): - """Run a bootstrap permuting the genes as well as the data, to assess reliability of the results. - - - - :param x_data: data to regress, provided as z scores (e.g., gene expression data). - :param y: data to regress against, provided as z scores (e.g. average values from ROIs). - :param n_components: number of components to use for the PLS regression. - :param y_norm: original y data (before z scoring). - :param genes: labels of the genes regressed against (e.g., the labels of the y data rows). - :param n_iterations: number of iterations for the bootstrapping and permutations. - :return gene_results: GeneResults data structure with all the results of the bootstrapping and the original - results as well. - """ - n_genes = 15_633 - gene_index = np.array(list(range(1, n_genes + 1))) - results = pls_regression(x_data, y, n_components=n_components, n_boot=0, n_perm=0) - r1 = correlate( - results.get("x_scores").reshape(41, n_components), y_norm.reshape(41, 1) - ) - logger.debug("Correlation between original data and regression scores: %s", r1) - weights = results.get("x_weights") - gene_results = GeneResults( - n_components, dim1=weights.shape[0], dim2=weights.shape[1] - ) - scores = results.get("x_scores") - for i in range(r1.size): - if r1[i] < 0: - weights[:, i] *= -1 - scores[:, i] *= -1 - for idx in range(1, n_components + 1): - x = np.argsort(weights[:, idx - 1], kind="mergesort")[::-1] - gene_results.original_results.set_result_values( - idx, - np.sort(weights[:, idx - 1], kind="mergesort")[::-1], - x, - genes[x], - gene_index[x], - ) - - # Main genes bootstrap - for iteration in tqdm( - range(n_iterations), desc="Bootstrapping gene list", unit=" iterations" - ): - my_resample = np.random.choice(41, size=41) - x_perm = x_data[my_resample, :] - y_perm = y[my_resample].reshape(41, 1) - results = pls_regression( - x_perm, y_perm, n_components=n_components, n_perm=0, n_boot=0 - ) - _weights = results.get("x_weights") - for component in range(1, n_components + 1): - __temp = _weights[:, component - 1] - __new_weights = __temp[gene_results.original_results.index[component - 1]] - __t_genes = np.array( - gene_results.original_results.pls_weights[component - 1] - ) - __correlation = correlate( - __t_genes.reshape(15633, 1), __new_weights.reshape(15633, 1) - ) - if __correlation < 0: - __new_weights *= -1 - gene_results.boot_results.pls_weights_boot[component - 1][ - :, component - 1, iteration - ] = __new_weights - return gene_results - - -def spearman_op(idx, permuted, y_data): - return spearmanr(permuted[:, idx[0]], y_data[:, idx[1]])[0] - - -def bootstrap_correlation(x_data, y_data, permuted, labels, n_iterations=1000): - """ - Bootstrap the results using pearson correlation. - - :param x_data: imaging data - :param y_data: gene expression data - :param permuted: permuted matrix of imaging data - :param labels: labels of the genes (original order) - :return gene_results: GeneResults class with correlation results. - """ - gene_results = GeneResults(n_comp=1, dim1=1, dim2=y_data.shape[1]) - n_genes = 15633 - pool = Pool() - # original correlation - corr_ = np.zeros(y_data.shape[1]) - for gene in range(n_genes): - corr_[gene], _ = spearmanr(x_data, y_data[:, gene]) - # order results and set indexes in gene results - gene_results.original_results.pls_weights = np.sort(corr_, kind="mergesort")[::-1] - __idx = np.argsort(corr_, kind="mergesort")[::-1] - gene_results.original_results.pls_gene = labels[__idx] - gene_results.original_results.gene_id = __idx - # bootstrap - __res = np.zeros((15633, 1000)) - _iter = product(range(n_iterations), range(n_genes)) - for ind, result in tqdm(enumerate(pool.imap(partial( - spearman_op, permuted=permuted, y_data=y_data), - _iter, chunksize=25_000 - )), - desc="Bootstrapping correlation", - unit="iterations"): - __res.flat[ind] = result - gene_results.boot_results.pls_weights_boot = __res - return gene_results diff --git a/imaging_transcriptomics/corr.py b/imaging_transcriptomics/corr.py new file mode 100644 index 0000000..723a839 --- /dev/null +++ b/imaging_transcriptomics/corr.py @@ -0,0 +1,173 @@ +import numpy as np +from pathlib import Path +from scipy.stats import spearmanr +import pandas as pd +import logging +from statsmodels.stats.multitest import multipletests +from multiprocessing import Pool +from functools import partial +from itertools import product +from collections import OrderedDict +import gseapy +from gseapy.plot import gseaplot +from .genes import GeneResults, CorrGenes +from .inputs import get_geneset +import yaml +import logging +import logging.config + +np.random.seed(1234) + +cfg_file_path = Path(__file__).parent / "log_config.yaml" +with open(cfg_file_path, "r") as config_file: + log_cfg = yaml.safe_load(config_file.read()) + +logging.config.dictConfig(log_cfg) +logger = logging.getLogger("genes") +logger.setLevel(logging.DEBUG) + + +# --------- CORR ANALYSIS --------- # +def _spearman_op(idx, permuted, y): # pragma: no cover, used for multiprocess + """Wrapper for the spearman correlation function, to be used for + parallel computation.""" + return spearmanr(permuted[:, idx[0]], y[:, idx[1]])[0] + + +class CorrAnalysis: + """Class to store all the results of the correlation analysis. + The only field contained is the a GeneResults object, storing all + information about the correlation analysis. + """ + def __init__(self): + self.gene_results = GeneResults("corr") + self.gsea_res = None + + # --------- COMPUTE FUNCTIONS --------- # + def bootstrap_correlation(self, imaging_data, permuted_imaging, + gene_exp, gene_labels, n_cpu=4): + """Perform bootstrapping on the correlation. + + The function first calculates the correlation between the imaging + vector and each of the genes. Then, it performs 1000 bootstrapping + iterations of the same correaltion only using the permuted imaging + data. The function then calls the methods of the GeneResults class + to order the genes and calculate the p-values. + + :param np.ndarray imaging_data: the imaging data. This vector + represents the original data to be correlated, and can have either + length 41 or 34, depending on whether the subcortical regions want + to be included in the analysis. + :param np.ndarray permuted_imaging: the imaging data permuted. This + is a matrix with shape (n_imaging, 1000), where `n_imaging` + represents the length of the imaging vector. + :param np.ndarray gene_exp: the gene expression data. + :param list gene_labels: the labels of the genes. + :param int n_cpu: the number of CPUs to use for the parallelization + """ + assert isinstance(self.gene_results.results, CorrGenes) + logger.info("Calculating correlation on original data.") + for i in range(self.gene_results.n_genes): + self.gene_results.results.corr[0, i], _ = spearmanr( + imaging_data, gene_exp[:, i]) + pool = Pool(n_cpu) + _ind = product(range(1000), range(self.gene_results.n_genes)) + + logger.info("Calculating correlation on permuted data.") + for ind, res in enumerate(pool.imap(partial(_spearman_op, + permuted=permuted_imaging, + y=gene_exp), + _ind, chunksize=15633)): + self.gene_results.results.boot_corr.flat[ind] = res + self.gene_results.results.genes = gene_labels + self.gene_results.results.sort_genes() + self.gene_results.results.compute_pval() + return + + def gsea(self, gene_set="lake", outdir=None): # pragma: no cover, + # long to process (t > 1 h) - TESTED on run + """Perform GSEA on the correlation. + + The function runs a first gsea with the data and then runs the same + analysis using the permuted data. The analysis of the permuted data + is used ot calculate the p-values for the Enrichment scores (ES). + + :param str gene_set: the gene set to use for the analysis. + :param str outdir: the directory where to save the results. + """ + assert isinstance(self.gene_results.results, CorrGenes) + logger.info("Performing GSEA.") + gene_set = get_geneset(gene_set) + # prepare the gene_list as a list of strings + gene_list = [ + gene for gene in self.gene_results.results.genes[:, 0].tolist() + ] + # perform the GSEA on original results + rnk = pd.DataFrame( + zip(gene_list, self.gene_results.results.corr[0, :])) + gsea_results = gseapy.prerank(rnk, gene_set, + outdir=None, + permutation_num=1000, + seed=1234) + _origin_es = gsea_results.res2d.es.to_numpy() + _boot_es = np.zeros((_origin_es.shape[0], 1000)) + # perform the GSEA on the permutations + for i in range(1000): + rnk = pd.DataFrame( + zip(gene_list, self.gene_results.results.boot_corr[:, i]) + ) + _gsea_res = gseapy.prerank(rnk, gene_set, + permutation_num=1, + no_plot=True, + outdir=None, + seed=1234) + _boot_es[:, i] = _gsea_res.res2d.es.to_numpy() + # calculate the p-value + _p_val = np.zeros((_origin_es.shape[0],)) + for i in range(_origin_es.shape[0]): + _p_val[i] = np.sum(_boot_es[i, :] >= _origin_es[i]) / 1000 + # calculate the p-value corrected + _, _p_corr, _, _ = multipletests(_p_val, method='fdr_bh') + # Prepare data to save + _out_data = OrderedDict() + _out_data["Term"] = gsea_results.res2d.axes[0].to_list() + _out_data["es"] = gsea_results.res2d.values[:, 0] + _out_data["nes"] = gsea_results.res2d.values[:, 1] + _out_data["p_val"] = _p_val + _out_data["fdr"] = _p_corr + _out_data["genest_size"] = gsea_results.res2d.values[:, 4] + _out_data["matched_size"] = gsea_results.res2d.values[:, 5] + _out_data["matched_genes"] = gsea_results.res2d.values[:, 6] + _out_data["ledge_genes"] = gsea_results.res2d.values[:, 7] + out_df = pd.DataFrame.from_dict(_out_data) + if outdir is not None: + logger.info("Saving GSEA results.") + outdir = Path(outdir) + assert outdir.exists() + out_df.to_csv(outdir / "gsea_corr_results.tsv", index=False, + sep="\t") + for i in range(len(gsea_results.res2d.index)): + term = gsea_results.res2d.index[i] + gsea_results.results[term]["pval"] = _p_val[i] + gsea_results.results[term]["fdr"] = _p_corr[i] + gseaplot(rank_metric=gsea_results.ranking, + term=term, + **gsea_results.results[term], + ofname=f"{outdir}/{term}_corr_prerank.pdf") + + # --------- SAVE FUNCTIONS --------- # + def save_results(self, outdir): # pragma: no cover, simply saves stuff + """Save the results to a file.""" + outdir = Path(outdir) + assert outdir.exists() + # Create the data to save + logger.info("Saving results.") + data_to_save = zip(self.gene_results.results.genes[:, 0], + self.gene_results.results.corr[0, :], + self.gene_results.results.pval[0, :], + self.gene_results.results.pval_corr[0, :]) + # Save the data + pd.DataFrame( + data_to_save, columns=["Gene", "Corr", "Pval", "Pval_corr"] + ).to_csv(outdir / "corr_genes.tsv", index=False, sep='\t') + return diff --git a/imaging_transcriptomics/data/geneset_LAKE.gmt b/imaging_transcriptomics/data/geneset_LAKE.gmt new file mode 100644 index 0000000..7245df1 --- /dev/null +++ b/imaging_transcriptomics/data/geneset_LAKE.gmt @@ -0,0 +1,30 @@ +Ast NA SLC1A2 GPC5 ADGRV1 RNF219-AS1 ZNF98 SLC1A3 HPSE2 FGFR3 COL5A3 ATP1A2 CST3 NKAIN3 PITPNC1 RYR3 GLUL GJA1 SLC4A4 MMD2 PAMR1 MSI2 NHSL1 C1orf61 PREX2 RGS20 HIF3A NDRG2 SFXN5 MT3 ACSS1 BMPR1B TNIK AHCYL2 GPM6A NPAS3 FBXL7 CTNNA2 CDH20 ZNRF3 PARD3B NCAN GLIS3 ACOT11 ARHGAP24 CLU MACF1 NTM CAMK2G LRRC16A RP11-436D23.1 RP11-384F7.2 DTNA ITPR2 CSGALNACT1 CPE LSAMP SPARCL1 CACNB2 GABRB1 MIR99AHG ZBTB20 NEBL CTNND2 DST RORA SORBS1 ZHX3 MYO10 TRPS1 FMN2 CABLES1 PRKG1 SOX5 NRXN1 SGCD SHROOM3 CADM1 SASH1 PRKCA BAZ2B PTGDS NRG3 PPP2R2B NTRK2 NEAT1 LGI4 PTN APC PARD3 GRAMD3 DPP10 FAM184A PTPRZ1 FUT9 WWOX OPHN1 ERBB4 ITSN1 ADD3 LIFR MAML2 ASPH QKI MEIS2 MAPK10 ADCY2 DCLK2 GRM3 PCDH9 ARHGAP5 DOCK4 MAST4 AC074363.1 RPS6KA2 MKLN1 ABLIM1 NFIA LINC00461 PDE7B FHIT NCKAP5 NAV2 FYN DGKG LRP1B PSD3 MAP3K5 CEP85L PRKD1 MYO6 MGAT4C GPM6B EPHB1 PHLPP1 FNBP1 SOX6 ZSWIM6 TRPM3 SLC35F1 SRGAP3 PHACTR3 WDR60 NFIB +End NA ABCB1 FLT1 CLDN5 ATP10A EPAS1 HERC2P3 B2M MECOM ABCG2 HLA-B HLA-E A2M SLC2A1 IGFBP7 ITM2A DUSP1 SLC39A10 UTRN GPCPD1 COBLL1 PTPRB PTPRG EBF1 SYNE2 PPFIBP1 RBMS3 TMSB10 ST6GAL1 ESYT2 TACC1 ST6GALNAC3 NEAT1 ARL15 CALD1 SPTBN1 LHFP IGF1R DLC1 GALNT18 RUNDC3B TJP1 DOCK9 MYRIP HSP90AA1 NR3C2 PCCA PTPRM PLCB4 PTPRK SPARCL1 NFIA +Ex1 NA CBLN2 ENC1 AC011288.2 TESPA1 RP11-314P15.2 LRRTM4 LINC01378 PDZD2 FAM19A1 HS6ST3 LINC00507 LINC01250 DGKB RP11-191L9.4 HPCAL1 MLIP R3HDM1 RGS6 NGEF LDB2 CHRM3 SORBS2 NRGN ADGRL2 CUX2 CAMK2N1 KCNIP4 CAMK2A ARPP19 SERPINE2 CACNG3 CHN1 PCDH7 KCTD16 ST6GALNAC5 ATRNL1 KALRN PHACTR1 ERICH1-AS1 LINC01122 KCNQ5 ASIC2 ATP2B1 FLRT2 AC007563.5 PRKCB NDST3 MAST3 CAMKK1 MEG3 GPC6 HOMER1 DLGAP1-AS4 KIAA1211L LRFN5 CDH12 KCTD1 BAIAP2 NELL1 LY86-AS1 IQCJ-SCHIP1 CREG2 CAMKV TMEM178B SHISA9 PDE7B NECAB1 SYN3 DLGAP2 ITPR1 RFTN1 CELF2 NWD2 AQP4-AS1 SIPA1L1 FAM153B PLCB1 LINGO2 PVRL3 CDH22 VSNL1 CDH9 EPB41L2 GRIA2 RASGRF2 BICC1 MIR137HG TMEM132D FSTL4 MKL2 WASF1 TANC2 MIAT CABP1 DIAPH2 OLFM1 SLC6A7 GULP1 CACNA1E SATB2 MEIS2 NTRK3 PPFIA2 PDE8B NLK GRIA4 PLEKHA5 AGBL4 PPP3CA FAT3 PDE4D GABRB3 TMEM132B RBFOX1 CACNA2D3 SLIT3 KCNH1 PTK2B CSMD1 CACNA2D1 KCNMA1 RAPGEF5 GRM5 SV2B DAB1 STXBP5L MTUS2 KHDRBS2 LRRC7 KIRREL3 RGS7 CNTNAP5 TENM2 MGAT4C SLIT2 CDH13 ARPP21 DGCR5 DLG2 SLC8A1 GRM7 DLGAP1 GRIN2A FAM19A2 EML6 SCN3B PTPRO BTBD9 EPHA6 FBXW7 CACNA1B CSMD3 MAP3K5 MAN1A1 ROCK2 DCLK1 AK5 KCNH3 GRIN2B CHD5 GNAL GRIA3 SLC17A7 PPP2R2C TMEM108 KIAA1549L DOK6 SORBS1 PRICKLE1 RFX3 CHSY3 ARHGAP32 NPTN ACTN1 CNKSR2 LMO3 PAK3 SORCS1 SEZ6L GALNT18 CACNA1C SLC2A13 TMEM59L SLC35F3 NELL2 CAMK1D CAMK2B CSGALNACT1 SLC4A10 HECW1 CTDSPL PPFIBP1 BRINP2 GUCY1A2 GABBR2 KCNB1 PCSK2 CYP46A1 RTN4 PI4KA NIN NCDN PDE2A SLC22A10 SLF1 PHYHIP TRIM9 MED12L AHI1 CELF5 MPP6 LMO4 CAMKK2 NPTXR NIPAL2 LRRTM3 ARHGAP26 LRFN2 CHL1 MAP2 MAPK4 NFAT5 PTPRN2 PPM1L GRIN1 THY1 AC091878.1 CAP2 EPHA4 RP11-707M1.1 TSC22D1 ABI2 SNED1 RP11-123M6.2 CNTN3 PRKAR2B FRRS1L ARHGEF7 USP25 ADCY1 ZNF804B RASAL2 RAPGEF2 PAK1 RPS6KC1 RP5-1187M17.10 SYBU WDR17 SUSD4 THRB ANKRD30BL GABRA2 ABLIM2 HSPH1 PLXNA2 NEDD4L NDFIP2 SGCD LONRF2 RGS4 CDK5R1 CCDC30 MAPK1 NEK10 CIT DCAF6 DCLK2 TRERF1 EFNA5 ARNT2 LRRC8B ZNF365 BCL11A MYH10 DPY19L2P1 SCAI YWHAH SHANK2 GOLGA8A KSR2 KCNJ6 SUGP2 NPTX1 VGLL4 ST8SIA3 TSPYL1 KCNB2 TMEM232 TLK1 TARBP1 ST8SIA5 DYNC2H1 RAD9A PLEKHA6 DGKZ KIFC2 PKNOX2 NETO1 GOLGA8B RUNDC3A TOMM20 SHC3 RPL31 KCNT1 CACNG8 +Ex2 NA KCNIP4 CNTNAP2 PTPRD COL5A2 DPP10 IQCJ-SCHIP1 AJ006998.2 FAM19A1 PTPRT LRRTM4 LDB2 KHDRBS2 UNC5D ST6GALNAC5 SNTG1 RP11-420N3.3 GRM7 ADGRB3 DCC AGBL4 CSMD1 PTPRK AC011288.2 RGS7 LRRC4C DLG2 KCNB2 SYT1 TRHDE RALYL LAMA2 KCNH7 HS6ST3 NTNG1 LINGO2 KCNQ5 NRG3 MGAT4C R3HDM1 PDE4D ATRNL1 ANO3 CNTN3 KHDRBS3 NKAIN2 ZNF804B MEG3 STXBP5L POU6F2 MKL2 OPCML CA10 NRG1 RORB NEGR1 CDH8 CELF2 PHACTR1 CNTN5 NELL2 THRB CPNE4 AC067956.1 DGKB NDST3 TENM2 KCNH5 KALRN RGS6 RIMS2 CHSY3 LRRC7 01-Mar CHN1 KCNQ3 FRMD4A FLRT2 PLCB1 LINC01250 CHRM3 AC114765.1 ERICH1-AS1 GABRB1 GULP1 KCNH1 NECAB1 GABRG3 DSCAM TMEM132D MEF2C FAM155A RYR2 RFX3 CACNA2D3 GRIN2A GRM5 FTH1 CBLN2 RP11-384F7.2 CDH10 BRINP3 FMN1 SGCD RP11-191L9.4 CTC-340A15.2 MIR137HG LRFN5 HECW1 XYLT1 ERC2 DCLK1 SLC39A10 OXR1 SEMA6D LY86-AS1 AK5 RASAL2 MAPK10 GUCY1A2 CUX2 KCNT2 FBXL2 TMEM232 EPHA4 HOMER1 EFNA5 FAT3 NRCAM AQP4-AS1 PPFIA2 GABRB3 ARHGAP32 PDE10A TESPA1 SLC44A5 OLFM3 CERS6 MLIP SLC2A13 CHL1 DGKI ARL15 ZNF385B CACNA1B PRKG1 KCTD16 PEX5L LMO4 MAST4 CSMD3 CACNA1C ARHGAP26 PIK3R1 NEFM YWHAH TMEM178B TMSB10 SORBS2 GAP43 RP11-586K2.1 TMEM108 ASAP1 RUNDC3B CCSER1 GRIN2B KIAA1211L RAPGEF5 SYN2 MCF2L2 PAK3 PAK1 NIN STXBP5-AS1 SOX5 CLSTN2 SCN3A CAMK1D NBEA DLGAP2 NOL4 NR2F1-AS1 LARGE CREG2 CACNG3 CDK14 CDH2 LRRTM3 TMEM132B DPY19L2P1 MYH10 GDAP1 ADCY1 SERPINI1 MIAT PI4KA FAM153B BRINP2 MLLT3 CEP126 UCHL1 SLC35F3 MED12L ATXN1 MARK1 GOLGA8A GOLGA8B SATB2 NTRK3 NEFL FSTL4 HCN1 AEBP2 UNC80 KCTD1 PRICKLE2 UGGT2 CELF5 SCN8A CEP112 +Ex3a NA KCNIP4 PTPRD PLCB1 FAM19A1 IQCJ-SCHIP1 CSMD1 TENM2 ATRNL1 LDB2 LINGO2 COL5A2 PHACTR1 POU6F2 RP11-594C13.1 SLC38A11 LRFN5 GRM7 NRG3 FAM19A2 HS6ST3 KALRN KHDRBS2 LRRTM4 CUX2 RP11-191L9.4 DCC RORB R3HDM1 GLIS3 CNTNAP2 RGS7 STXBP5L NTNG1 SNHG14 RBFOX1 KCTD16 KCNQ5 SNTG1 FMN1 ASIC2 CNTN5 MEG3 AGBL4 TESPA1 TMEM132D ERICH1-AS1 RGS6 NRG1 OPCML CACNA2D3 CPNE4 GRIN2A FLRT2 SYT1 TMEM178B DCLK1 ARPP21 ST6GALNAC5 PTPRT HECW1 ANKS1B CADPS2 NELL1 MAGI2 CHN1 ARHGAP26 AC114765.1 SYN3 NECAB1 CAMK2A PTPRK CHRM3 CABP1 NRGN NEGR1 DGKB RYR2 FAM155A KHDRBS3 CDH12 FOCAD FAT3 SLC2A13 RAPGEF5 FSTL4 BRINP1 CELF2 PDE7B NCALD PLEKHA5 CNTNAP5 UNC5D SGCD PRKCB MKL2 KCNH1 CACNA1C MEF2C MAST4 TANC2 PDE4D HOMER1 DSCAM GRM5 HDAC9 ADGRL2 KCTD1 AQP4-AS1 SORCS1 GABRG3 ERC2 EPHA4 MIAT KCNB2 CERS6 AC011288.2 PDE10A SCAI NELL2 GAP43 NEFM KCNMA1 LINC01250 OLFM3 DLGAP2 PPM1L MAGI3 FRMD4A NLK MLIP SORBS2 TMEM132B GPC6 NIPAL2 MTUS2 LRRC7 ADGRB3 CUX1 ZNF385B LMO4 NGEF TENM4 KIAA1211L RIMS2 FRMPD4 SYTL2 ASAP1 ARHGAP32 PPP2R2C RASAL2 KCNQ3 EPB41L2 EFNA5 CSMD2 DLGAP1-AS4 PTPRN2 SPATS2 PDZRN3 TRHDE SLIT2 BRINP2 LINC-PINT PTPRG CACNG3 NR3C1 PTK2B LRRTM3 CNTN3 FAM13A PRR16 MICAL2 BRINP3 SV2B CNKSR2 MED12L MAPK10 PTPRO SEMA6D CACNA1B AHI1 EPHA6 LY86-AS1 SLC35F3 AC091878.1 CDK14 DCAF6 ADAM23 HCN1 GRIA3 SATB2 MEG8 PAK3 MYT1L CHL1 PPP3CA FBXW7 MAPK4 FGF12 CSMD3 PCDH7 NR3C2 SCN8A SLC6A7 GABRB3 SCN3A CACNB4 RP1-34H18.1 CHSY3 VPS13A PAK1 FOXP1 FAM81A KCNH7 RFX3 PLXNA4 FARS2 TRERF1 LINC01122 ROCK2 CIT AEBP2 LRRFIP1 RAPGEF2 PIK3R1 SLC4A10 FTX FMN2 SIPA1L1 ARL15 EML6 OXR1 RPS6KC1 WASF1 KCNB1 MIR137HG NUAK1 OSBPL6 MIPOL1 MCF2L2 ATP2B2 MAN1A2 GRIA2 THRB PKNOX2 SYBU GLS LINC00632 NWD2 FRY STRBP FAM153B TMEM108 NEFL DGKI PCNXL2 PPFIA2 PCDH11X ELAVL4 MIR124-2HG SAMD12 FRAS1 ABLIM2 PRKAR2B NOL4 UBA6-AS1 CAMK1D SCN1A SLC44A5 MLLT3 ZBTB16 LARP1B ATP8A2 ITPR1 UNC79 CCDC30 +Ex3b NA NRGN RORB OLFM1 CHN1 POU6F2 SNAP25 PTPRD RP11-767I20.1 NEFM PDP1 ATP2B2 NEFL TENM2 FAM19A2 LMO4 CNTN5 FAM19A1 CALM1 CHGA MEF2C NTNG1 CPNE4 CCK CAMK2A PTPRT CUX2 KALRN STMN1 NCDN PLCB1 LINGO2 TUBA1B CABP1 ATP1A1 SCN1B GRIN2A HTR2A BRINP1 EIF4A2 LINC00657 SPARCL1 YWHAG ARPP21 PEBP1 GABRA1 TSC22D1 SLC17A7 NPTN CUX1 PPP3CA MAST4 NDUFA4 CCNI HS6ST3 YWHAH PHYHIP PARM1 NUAK1 KHDRBS2 ATP1B1 DCLK1 GRM7 RIMS3 PRKAR1B SLC2A13 IQCJ-SCHIP1 NSF OIP5-AS1 TRHDE PCSK1 NRG1 TSPYL1 STMN2 BASP1 PHACTR1 CSMD1 GABRG3 NCALD SCN1A BRINP3 FMN1 THY1 SORCS1 CNTNAP5 NDRG4 CACNA2D3 PSAP GAPDH FBXW7 HECW1 PRKCB R3HDM1 NECAB1 C1orf115 KHDRBS3 SULT4A1 PCP4 NELL2 NAT8L FOXP1 GABRD EPHA4 HSPH1 TAGLN3 ATRNL1 ARPP19 VAV3 MAP1B SLC12A5 NRN1 ENC1 EGR1 RGS4 HIVEP2 SLC30A3 NGFRAP1 PREPL STXBP1 YWHAB CAMK2N1 LRRC4C CAMK2B CTC-535M15.2 ENO2 CAMTA1 CSMD2 NDFIP1 CNKSR2 RTN1 CALM3 KCNA2 MEF2A TMEM132D GABRB2 REEP5 HSP90AB1 ZNF385B GLS VSNL1 LRFN5 PJA2 ALDOA UCHL1 PTK2B SSX2IP BEX1 ERC2 TCEAL2 UNC5D KCNB1 SORL1 RAPGEF5 CKB C11orf87 SCAI KLC1 CDK14 SCG5 ACTB C16orf45 MTATP6P1 KCNH5 RTN3 CREG2 PPIA RHOBTB2 ADAM23 KIF5C SH3GL2 MORF4L1 SEPW1 ARHGAP10 KIF3A DCC MAP1A MICAL2 MOAP1 CAMKK2 RPH3A BNIP3 CACNB4 TRIM37 CLTC VPS41 PGK1 CHD5 TPI1 CAP2 STRBP LDB2 PRMT8 LRRK2 ZBTB18 CHL1 LINGO1 GABARAPL1 ACSL3 CTSB CEND1 FSTL4 TESPA1 GRIN1 SNCB TMOD2 INA FAT3 TUBA1A GABBR2 FAM217B CADM3 RNF187 ITM2C ARHGAP32 MIAT ATP2A2 TPPP PRNP CIT TSPAN7 GCC2 SNTG1 FAIM2 SYT4 NGEF STMN4 ZNF365 NAP1L2 PPP2R2C GNAS G3BP2 USP22 GDI1 NFIX SMARCA2 TSPAN13 WBP2 SLC44A5 HLF CPLX1 CA11 IDS CLSTN1 RAB3A UNC13A ELAVL4 RNF11 UBB KIF5A HNRNPK CTC-340A15.2 CSRNP3 TOMM20 SYNGR1 GAP43 SKP1 SATB2 ITM2B SCAMP5 DDX24 LDHB MDH1 DNM1 COX6C SYT13 FAM81A RAB6B TSPYL4 ERICH1-AS1 ELMOD1 USP11 PRR16 FLRT2 GLCCI1 PDZRN3 TUBA4A TERF2IP CFL1 TTC39C CCDC136 KIAA1107 RGS7 PTPRN FBXL16 RCAN2 CAMK2G RPS14 ATP5B EIF1 DGKZ EEF1A2 EID1 ZBTB16 08-Sep TMEM30A RAC1 MAGI3 GRINA TMEM178B SERINC1 ZFAND5 DKK3 PRKAR1A FAM168B TOLLIP LINC01322 UBC HOMER1 UQCRH DYNLL2 ACTG1 UBE2E3 NDFIP2 SPOCK2 SNU13 ABR ATP5A1 PPP2R1A YWHAZ PPP3CB OSBPL3 ATP6V1B2 OCIAD1 RP11-191L9.4 NAP1L1 ATP6V0B PNMA2 NEGR1 FAM189A1 FOCAD CLTA DSTN CDK5R1 GABRG2 CNTNAP1 DMTN CTNNB1 SLC25A3 KIAA0319 NR2F1-AS1 EFNA5 PKD1 RASGRF1 SUGP2 NLRP1 ST8SIA3 B4GAT1 KIFC2 EIF4G2 NUDT3 CDKL5 STMN3 SYTL2 PKM COX4I1 ATXN7L3B DCAF6 PCMT1 LIN7A NDUFA1 EFR3A ARF1 GNB1 NCEH1 NUDCD3 PRKAR2B NR2F1 DYNLL1 SLC6A17 C14orf2 ATP6V0A1 ATP6V1E1 ENSA YPEL3 C16orf52 GUK1 LMO7 SERINC3 GLRB REEP2 PAK1 KCNAB2 MAP9 MAST3 HMP19 RP5-1187M17.10 RAB11FIP4 TMEM160 SCN8A MORF4L2 MTPN RPLP1 BEX2 MPRIP TUBB2A NAPEPLD HSPA12A SYBU GOT1 KIF3C ETV5 RUNDC3A CAMKV GNB5 BEX4 KIF1A PLD3 KIAA1549L NDUFS2 NAPB ATP6AP2 KIAA1211L EPB41L1 MIR124-2HG PKNOX2 ATP6AP1 PLEKHB2 MTCH1 NRSN1 RANGAP1 MAP2K1 TPM1 KCNH3 LMTK2 CAMKK1 MAP7D2 FZD3 RNF145 SYT16 SLC6A7 RPL15 KIAA0513 RPS27A CLSTN3 HINT1 ARL6IP5 LPCAT4 PACSIN1 COX7C FHL1 PTPN5 SYT7 +Ex3c NA NEFM NRGN SNAP25 NEFL MAP1B YWHAG OLFM1 VSNL1 CHN1 NCDN CALM1 TUBA1B CALM3 LMO4 THY1 PEBP1 ATP1B1 ENC1 TSPAN7 RGS4 LINC00657 NPTN BASP1 TSPYL1 ENO2 CKB BEX1 ATP1A1 APP PDP1 HSP90AB1 SPARCL1 PRNP CCK CREG2 YWHAH CLSTN1 CHGA GAPDH TMSB10 NSF RTN4 STMN2 PSAP SLC17A7 YWHAB ARPP19 GNAS PGK1 EIF4A2 DMTN PHYHIP RTN3 TSC22D1 ALDOA CAMK2A ATP2B2 HSP90AA1 SULT4A1 RAB6B NGFRAP1 CABP1 KLC1 UCHL1 SCN1B SKP1 PRKAR1B SCG5 CFL1 PREPL RTN1 NUAK1 TCEAL2 CAP2 STXBP1 CAMK2N1 ATP2A2 WBP2 NAT8L MAP1A PPP3CA NDRG4 NDUFA4 MDH1 TUBB2A INA TPI1 NAPB SYNGR1 RAB3A NRN1 NDFIP1 UBC HSPH1 PNMA2 CAMK2B CPLX2 MOAP1 RNF11 HINT1 RPH3A SEPW1 TAGLN3 PKM DYNLL2 FAIM2 CTSB CLU IDS SERINC3 KCNA2 BEX2 PJA2 ATP5A1 DNM1 ACTB DKK3 NAP1L2 ATP5B USP11 TSPYL4 CCNI GDI1 ATP6V1B2 UQCRH COX4I1 KIF5A BEX4 CAMKV UBB TMEM30A GRIN1 TUBA1A NDUFA1 TMEM59L STMN1 GABRA1 SYT1 COX7C SERINC1 CAMKK2 TMSB4X NUCKS1 AES SLC12A5 ARF1 ELAVL4 YPEL3 NECAB1 DPYSL2 GAP43 ATP2B1 MAST3 OIP5-AS1 DGKZ MTCH1 SARAF TOMM20 CACNG8 PRKAR1A GCC2 NGEF SYT11 KIAA1107 SV2B PRDM2 TMEM130 CADM3 TRIM37 KIF3A MORF4L1 NAP1L1 DSTN REEP5 SYP RORB SCAMP5 SV2A KCNB1 GNB1 MAPK1 PPP3CB KIF1A RUNDC3A ABR FBXW7 NCALD PIK3R1 USP22 BLCAP C16orf45 ACSL3 MAP7D2 EIF1 ATP6V0A1 YWHAE SCN1A NUDCD3 SIRPA ATP6V1A PRKCB GABRG2 PRRC2B ITM2B APLP1 TPPP KIAA1549L DCLK1 CAMK2G SNCA GLS ACTG1 ELMOD1 ZNF483 ADAM23 OCIAD1 SORL1 KIF5C SPTBN1 APBB1 RPS14 MEF2C ITPR1 CLTC ROCK2 PAK1 CPE RAB2A NCKAP1 RTF1 RUFY3 RPL31 GAS7 DNAJC6 APLP2 LONRF2 SEC62 07-Sep HIVEP2 WASF1 VPS13A RCAN2 EPHA4 +Ex3d NA CNTN5 LRRC4C NTNG1 TENM2 RORB PTPRD GABRG3 SNTG1 POU6F2 PLEKHH2 CTC-340A15.2 PHACTR2 CPNE4 CNTNAP5 RORA CTC-535M15.2 KCNIP4 TRPC3 ADAMTS17 BRINP3 FAM19A2 CSMD2 CUX1 FAM189A1 VAV3 NLGN1 HS6ST2 RP11-420N3.3 HTR2A PRKG1 KCNIP1 PLAGL1 MAST4 EYA4 PTPRT IQCJ-SCHIP1 RYR3 SLC2A13 SPARCL1 NRGN ZNF385B SPON1 THSD7A CUX2 RAB3B RIMS2 BRINP1 RP11-32K4.1 ILDR2 FAM19A1 GRIN2A CHGA RP11-30J20.1 CLMN PDE3A UNC13C PARM1 KHDRBS2 MYO16 PRR16 KCNH8 CDH20 ALOX12P2 SLC8A1 GRM7 ATP2B2 MEF2C CCDC136 GRIK4 CTNND1 ERC2 MEF2A GABRB2 NEGR1 PLCB1 ANKS1B PCSK1 LINGO2 DCLK1 CDK14 SLC44A5 OLFM1 TRHDE NRG3 KHDRBS3 GABRA1 LRRK2 LRRC28 SYT1 MTUS2 RBMS1 EXTL2 CAMK2G CSMD1 PTCHD4 PRMT8 ARL4C KIAA0319 IL1RAPL2 ETS2 PLCH1 LMO7 PEBP1 CCNI VPS41 SLC38A1 RALYL LRRC7 SLC6A17 PAM SCN1B LIN7A FOXP2 SMPD3 NELL2 SORL1 CALM1 RGS7 EPHA4 SORCS1 NYAP2 FMN1 NEFL LMO4 C11orf87 HS6ST3 PTPRO CELF2 OSBP2 LMO3 SPOCK1 ITPR2 CEMIP ATP1B1 SCN1A CACNB4 PGK1 PDP1 FGF12 FBXW7 FSTL4 RCAN2 SNAP25 CACNA1A FAT3 NAP1L1 PTEN PBX1 KIAA1109 HIVEP2 ARPP21 PLCXD3 CNKSR2 GABRD KALRN KIF5C HSP90AB1 NTRK2 CLCN4 SRRM3 TTC39C MDGA2 NR2F1-AS1 KCNMB4 MAPK10 CAMK2B ARID1B PDE10A PPA2 SCAI TMOD2 SLIT2 SATB2 MED13L AC067956.1 SSBP2 EIF4A2 ATXN1 RAP1GDS1 MAP1A PREPL KCNA2 ADRBK2 HSPH1 AUTS2 RBFOX2 GLCCI1 C8orf34 SSX2IP ATP1B3 ELL2 PTPRN2 HDAC9 GAPDH C16orf45 ATP1A1 CLEC16A UBL3 CTTNBP2 INA GRAMD1B NEFM GABRG2 TCEAL2 HECW1 FOXP1 DAPK1 PTK2B NPTN STXBP1 FRY KIAA1456 BICD1 EIF1 RGS4 CABP1 TSC22D1 C16orf52 SYT7 AIG1 MGST3 BAALC NDUFA4 SPAG16 STOX2 WDFY3 ARHGAP44 HCN1 GRM5 NSF STMN4 PTPRR GABARAPL1 AC114765.1 NDUFS1 CSRNP3 NDRG4 SIK2 MARK1 MAP3K13 NUAK1 MYO5A SYP ZMAT4 OSBPL3 TENM4 ZNF91 FOCAD RAC1 YWHAB RASGRF1 ITM2B SNRPN SLC4A10 CTSB NRSN1 STMN1 MICAL2 SPOCK2 FAM13B SLC17A7 YWHAH VPS13D SKP1 TPI1 DGKI ELMOD1 FHOD3 CADM3 ARHGAP26 RPLP1 ST8SIA1 GLRB TAGLN3 RNF157 PDZRN3 MCF2L2 LMTK2 STRBP TMEM131 FZD3 CSMD3 SLC23A2 EPHA5 CDC14B SLC12A5 SULT4A1 YWHAG PRKAR1B MORF4L1 PRKAR1A ANKRD17 OIP5-AS1 KLHL32 ARHGAP32 PLXNA4 ATP5B ELAVL4 REEP5 KIFAP3 CACNA2D3 RPS14 AC005592.2 MYH10 KCNB1 GLS +Ex3e NA NRGN TUBA1B UCHL1 OLFM1 NEFL TMSB4X TMSB10 CHN1 ENC1 CCK CALM1 SLC17A7 ARPP19 RTN1 YWHAH MAP1B FTH1 SNAP25 CALM3 VSNL1 NEFM LMO4 BEX1 TUBB2A PRNP GAPDH TUBA1A STMN1 NGFRAP1 HSP90AA1 ALDOA SEPW1 RTN3 THY1 HSP90AB1 YWHAG RGS4 DYNLL1 SPARCL1 ENO2 ACTG1 CREG2 NDUFA4 MTCH1 PEBP1 HSPA8 UBB CLSTN1 EIF4A2 PPIA RAB6B SCN3B SYT1 BASP1 YWHAB NAPB CRYM YWHAZ TUBA4A TPI1 LINC00657 NDRG4 STMN2 KLC1 TAGLN3 MDH1 GNAS ATP6V1B2 REEP5 HINT1 SERPINI1 CLU RTN4 TCEB2 GDA CFL1 BEX2 TMEM59L CHGA UBC TSPYL1 ATP6V1E1 SLIT1 GAP43 PSAP GHITM GABARAPL1 ARF1 SNCA SARAF SRP14 SV2B IDS CAMKV TOLLIP TSPAN7 ACTB SKP1 GDI1 MOAP1 NSF PDP1 NECAB1 CKB PKM COX4I1 TSC22D1 SYN1 STXBP1 TMEM130 RUNDC3A RPL21 SERINC1 GABARAPL2 NDFIP1 SULT4A1 SYNGR1 CDK5R1 BEX4 ELAVL4 GUK1 NPTN ATPIF1 STX1A ITM2C NAP1L2 SOD1 RPS14 RIMS3 CAMK2A ATP1A1 USMG5 ST6GALNAC5 ATP5A1 FBXW7 CNRIP1 RPL15 RPS27 SLC25A3 COX6C MKL2 CABP1 LINGO1 SYT7 MAPK1 DSTN PCMT1 PJA2 APLP1 SIRPA RAC1 TPPP PNMA2 TMEM160 ATP2B2 ATP1B1 DIRAS2 COX5B NCDN WBP2 PACSIN1 C14orf2 TOMM20 NDUFB2 STMN3 PRKCB PEA15 HSPH1 NLRP1 BAALC KIF5A DKK3 EIF1 ATP6AP2 GUCY1B3 UQCRH COX7C PGM2L1 SYT4 DPYSL2 NAP1L1 DNM1 NELL2 ATP6V1A EIF4G2 BLCAP EPHA4 SCG5 KIF3C SLC39A10 MEF2C ENO1 WASF1 MAST3 NPTX1 SATB2 USP11 NUAK1 NDFIP2 LMO3 RPLP1 SYT11 SLC6A7 RAB3A MORF4L2 PREPL DNAJA1 NGEF CHL1 NDUFA1 RNF11 ATP5B DGKZ RPS27A ATP2B1 ATP2A2 RPS28 SYTL2 NDUFA10 DMTN RHBDD2 HNRNPDL CTSB GABRA1 NRCAM ATP9A RAP1GAP TCEAL2 EPHB6 NUDT3 RPL31 PTK2B RPL34 ST8SIA3 NDUFV1 FAIM2 PDE2A RPS15 INPP5F EID1 CAMK2B SYN2 CAMKK2 ATP6AP1 PHYHIP SLC12A5 RPL35 TSPYL4 MT3 APP CA11 PIK3R1 LDHB GABRG2 FHL1 PAK3 MFSD6 OCIAD1 PFDN5 FEZ1 RPL3 ATP6V0B CHGB HMP19 PLEKHB2 KIAA1549L PTPRN CNTN3 KIAA0930 KIF1A MAP1LC3A TESPA1 ZFAND5 MIR124-2HG G3BP2 RP5-1187M17.10 NISCH SLC22A17 NCALD SYNJ1 OPTN GPC1 PAK1 CDH8 CAMK2N1 ITM2B APBB1 TRIM37 SCRN1 NPTXR 06-Mar RPL32 GOLGA8A DCLK1 ENSA PLD3 SCG2 RPL38 ADCY1 PPP3CB ATP5I GLS CHD5 TERF2IP FZD3 HNRNPA2B1 ANO5 KIFAP3 CDKL5 HSPA12A APLP2 NCKAP1 KIFC2 CPNE4 YPEL3 MORF4L1 LONRF2 ATL1 AC011288.2 SRSF5 PKD1 ATP6V0A1 BSN RPL23 CAP2 CLTC GOLGA8B TMEM30A PRKAR1B KIAA1211L DYNLL2 YWHAE ZNF483 APBA2 C16orf45 ADD2 MAP7D2 SYP GRIN1 11-Sep SORL1 SYBU TARBP1 CELF5 KCNQ2 ELMOD1 SSX2IP MIR137HG FAM49A AKAP11 MAPRE2 AQP4-AS1 ACTR2 PRKAR1A PI4KA KIF3A VPS41 DYNC1H1 USP22 HSP90B1 SEZ6L2 MYH10 DCAF6 ACSL3 SCN8A UNC13A TSPYL2 KCNB1 SEC62 SCAMP5 CACNG8 SV2A +Ex4 NA TSHZ2 RORB IL1RAPL2 DCC SLC22A10 RP11-475O6.1 SCHLAP1 POU6F2 FOXP2 LMO4 TOX OLFM1 KHDRBS2 PTPRD IQCJ-SCHIP1 CNTN5 FAM19A2 NRGN SLC38A11 SYT1 TRHDE RALYL KHDRBS3 CTC-535M15.2 RARB FSTL4 LDB2 SNTG1 MSC-AS1 CTC-340A15.2 TENM2 UNC5D CHN1 SLC17A7 SORCS1 OPCML CPNE4 SLC44A5 KCNH5 MEF2C RP11-191L9.4 SPARCL1 GABRG3 GRM7 CCK NELL2 RHOBTB2 AGBL4 IPCEF1 SNAP25 KALRN EPHA4 NUAK1 PTPRT ATRNL1 AC114765.1 LINGO2 STMN1 RP11-32K4.1 STXBP1 CTNNA2 TUBA1B NRG1 LRFN5 ATP2B2 FOXP1 PRKCB TSHZ3 ARPP21 BASP1 HS3ST4 MAGI3 CREG2 PCLO PPP3CA CAMK2A ADGRL2 KCNQ5 INPP4B PDP1 PLCXD3 EFNA5 CHGA ITPK1 NRG3 GRIN2A NCDN KCNQ3 DCLK1 HECW1 AC067956.1 PPFIBP1 ANKS1B UBE2E3 NEGR1 FBXW7 RTN1 KIAA0319 SYTL2 SATB2 PIK3R1 BRINP1 CELF2 R3HDM1 SV2B ENO2 CAP2 SCN1B KCNH1 SORL1 YWHAB VSNL1 PARM1 BRINP3 NCALD TOLLIP CSMD3 CAMK1D RGS4 GCC2 NELL1 CCNI PDE10A SLC8A1 FMN1 CABP1 CALM1 NTNG1 SH3GL2 MICAL2 ZMAT4 CTNNB1 MLIP RIMS3 TSC22D1 CALM3 CHSY3 NEFL LINC01322 CDK14 SULT4A1 NGFRAP1 NDRG4 ZNF385B ZNF365 LINGO1 CA11 RGS7 PEBP1 KIAA1549L MKL2 ERICH1-AS1 UCHL1 CLSTN1 DGKI ELAVL4 YWHAG FLRT2 CNKSR2 KCNB1 TSPYL1 PREPL SLIT1 DPY19L2P1 EPHB6 HIVEP2 VPS41 EIF4A2 IDS MAN1A2 SCN3A THRB HERC1 BEX1 SEMA6D KCND3 GABBR2 MIR124-2HG OLFM3 SPATS2L PHYHIP PRNP CACNB4 ZNF804B CAMK2N1 CDH10 RTN3 KIF5C ZMYND8 SLC6A7 SCN1A SNCA ALDOA GABRA1 PJA2 PCDH11X REEP5 CSRNP3 SERPINI1 RAPGEF2 YWHAH TAGLN3 NPTXR HSPH1 GLCCI1 TSPAN7 SYN2 KLC1 APBA2 RPL34 SEPW1 NWD2 PTPN5 NPTN PRDM2 NPTX1 GNAS BSN MIAT ADAM23 SSBP3 KCNB2 EIF1 OIP5-AS1 STOX2 NR2F1-AS1 CHD5 ATP5B GABRG2 PKNOX2 MTURN OSBPL6 GABRB3 RASAL2 ARHGAP32 PTPRO ZBTB16 08-Sep TCEAL2 RPL31 SPAG16 MDH1 RPS14 DDX24 TPI1 BCL11A GAP43 ATP1A1 GLS TPPP LINC00657 CFL1 ATP6V1B2 PDZRN4 GRIN1 CDKL5 KIFC2 RP5-1187M17.10 PDZRN3 TMSB10 PRKAR1B BEX2 FAIM2 SCAI SIRPA UQCRH SLC12A5 CAMKV RUNDC3A NDUFA4 TRIM37 C16orf45 CACNG8 GUCY1A2 THY1 TSPYL4 PNMA2 PLXNA4 INPP5F ELMOD1 KCNQ2 AMPH DGKZ EPHA5 FAM189A1 SCG5 RAB6B NAPB KCNT1 RP11-586K2.1 GNB5 TOMM20 PRICKLE1 +Ex5a NA PCP4 TMSB10 SYT1 CLSTN2 CTC-340A15.2 SNAP25 CPNE4 CTC-535M15.2 LRRK1 HS3ST4 RORB PHACTR1 IPCEF1 CADPS2 RXFP1 CNTN5 VSNL1 KCNIP4 DPP10 OLFM1 HS3ST2 CHN1 KCNQ5 PTPRT NCALD NEFL FOXP2 SLC17A7 EPHA3 DIRAS2 PTPRD TUBA1B PCDH7 PDE1C BASP1 CDK14 CHGA KCNT2 KHDRBS3 STMN2 SV2B NRGN FMN1 NRG1 STMN1 STX1A ELAVL4 LDB2 BRINP3 IL1RAPL2 ARPP21 KCNC2 SORCS3 KALRN CALM1 TENM4 FSTL4 NREP AGBL4 RALYL CABP1 SLC8A1 IQCJ-SCHIP1 BCL11A CAMK2D YWHAG NRN1 MDGA2 CDH10 LMO4 SLC22A10 SORCS1 KCNH7 KCNQ3 BEX1 POU6F2 HECW1 MAP1B RTN1 HTR2A MGLL EIF4A2 HIVEP2 EPHB6 STXBP1 GRM8 FBXW7 ENO2 R3HDM1 GABRG3 COL11A1 YWHAB MEF2C NDRG4 TSPAN7 PRKCB CDH8 NGEF TOX RYR2 SNCA ZNF385B NGFRAP1 GRIN2A THRB DCLK1 NELL2 CELF4 SULT4A1 TOLLIP CELF2 GNAS LRFN5 NKAIN2 ATP1A1 PAK1 CCNI CCSER1 PNMA2 PEBP1 DCAF6 CALM3 PGM2L1 NRSN1 SPARCL1 C16orf45 MOAP1 ST6GALNAC5 GRM7 NUAK1 NRCAM NEFM ATP2B2 SEPW1 PCLO GABRA1 RP1-34H18.1 MAP2 SSBP3 EFNA5 PPP3CA MKL2 GCC2 RAPGEF4 TPI1 NAP1L3 RTN3 GABARAPL1 PART1 SYN2 ITPK1 NELL1 SORL1 DNM1 SH3GL2 FAM189A1 GAPDH THY1 FRMPD4 TPPP NEGR1 CLSTN1 SNTG1 ST8SIA1 SERPINI1 MAGI3 NDUFA4 EVL GABRG2 EML6 CEND1 BAALC NSF NPTN RGS4 ERC2 TSPYL1 DYNLL1 TRIM37 IDS TAGLN3 COX4I1 GDA MICAL2 SCG2 YPEL3 EPHA5 ZBTB16 HSP90AA1 CNTN3 LINC01322 CAMK2A EID1 RP11-191L9.4 RAB6B KIF5A KLC1 PRKAR1B FOXP1 SYT7 ATP2A2 GLS KIF21A ELAVL2 CPLX2 KIAA1456 PAK3 NAPB PIK3R1 NDFIP1 CFL1 PDE4D KIF5C EEF1A2 UCHL1 PDP1 ATXN7L3B ALDOA PRKCE GLRB DKK3 FAT3 SIRPA NIPAL2 TSC22D1 PCDH10 HSP90AB1 DGKZ WBSCR17 PJA2 PREPL VPS41 RGS6 CAP2 PRNP ADD2 CAMKV CLTC SATB1-AS1 RIMS3 SYP HCN1 UQCRH CAMK2G SYNGR1 EIF1 RPH3A KCNB2 SYT11 NPTX1 TRIM44 SATB2 RPL15 CHSY3 RNF11 SARAF NCDN BEX4 STXBP5-AS1 ZFAND5 HLF FAM49A TLN2 STRBP GRIN1 KIAA1549L ATP1B1 SCG5 EPHA4 SNCB MORF4L1 PPP2R2C TCEAL2 ACTG1 ARPP19 KIAA1211L TMEM160 WBP2 GNB1 SCN3A COX6C KCNA2 SLIT1 VPS13A CACNA1C MGST3 RTN4 PHYHIP RPL31 KCNB1 SV2A ATP6V1B2 ATP6V1A FAIM2 MTURN GAP43 CACNG8 PDZRN3 CAMK2B SOD1 PCDH11Y 08-Sep RAC1 GDI1 LINC00657 ETV5 FAM19A1 NAP1L2 OIP5-AS1 TUBB2A HINT1 BEX2 MORF4L2 HSPH1 PRKAR1A UBC DYNLL2 SCN1B RAB3A STMN3 SKP1 PGK1 BSN ATP5B PTPN5 USP22 CNRIP1 PCMT1 RPS6 NETO1 SYT4 TOMM20 NUDT3 YWHAH EIF4G2 PAFAH1B1 PKNOX2 MAPK9 YWHAE USP11 LINC01378 LINGO1 DMTN C14orf2 RANGAP1 ATCAY LDHB MAST3 STAU2 CDKL5 GOT1 G3BP2 AES SCAI AC091878.1 MDH1 CTSB COX7C SYNJ1 ANO5 REEP2 PRICKLE1 DPY19L2P1 RPS14 TSPYL4 MIR124-2HG +Ex5b NA LRP1B CTNNA2 KCNIP4 PTPRD RXFP1 DPP10 SYT1 PDZRN4 NRG1 AC114765.1 PDE4D CLSTN2 PHACTR1 KCNQ5 HS3ST2 IL1RAPL2 OPCML AC067956.1 RALYL MEG3 AGBL4 RYR2 KCNH7 LDB2 PEX5L POU6F2 STXBP5L KHDRBS3 CSMD1 KALRN KHDRBS2 TMSB10 FSTL4 ZNF804B CCSER1 NKAIN2 NRG3 ATRNL1 SLIT1 NELL2 CPNE4 RP1-34H18.1 MIR137HG DSCAM RBFOX1 RP11-586K2.1 PART1 FOXP2 SLC35F3 LRRC7 CHSY3 DNAH6 SV2B SLC35F1 TENM4 NELL1 SORCS1 CHN1 CELF2 SLC17A7 CDH12 IQCJ-SCHIP1 TMEM132D CABP1 KCNB2 ARPP21 PTPRK LY86-AS1 HS3ST5 LRFN5 NRCAM R3HDM1 EFNA5 DMD SYN2 NECAB1 CHRM3 PCDH7 ENC1 FAM155A ERC2 FRMD4A CCK FBXW7 THRB NCAM2 LARGE ADGRL2 NRGN NETO1 MKL2 MMP16 RGS6 GABRG3 GRIA1 FMN1 MCTP1 SLC39A11 PRKD1 KCNQ3 GAP43 PRKCB AQP4-AS1 RP11-191L9.4 GABRB3 SOX5 ST6GALNAC5 GRM5 OXR1 HECW1 KCNT2 PCSK2 DCLK1 KCNMB4 CSGALNACT1 MDGA2 RASAL2 ZNF385B LMO4 AK5 HS3ST4 HTR1E ANKS1B SNCA CELF4 RAPGEF4 GRIA3 CACNA2D3 SCN3B CCDC3 SATB2 KIAA1211L ATP2B1 VSNL1 CDH10 RP11-384F7.2 CDK14 PDE1A SNTG1 ERICH1-AS1 CSMD3 NAV3 FRMPD4 CREG2 CACNA1B FOXP1 EPHB6 UCHL1 AFF3 KCNMA1 NGEF EML6 BMPER PTPRT PPFIBP1 AC091878.1 PRICKLE1 CACNA1C CAMK1D KCNH1 SLC4A10 PPP3CA MAPK10 PID1 TRIM9 NCALD AC011288.2 CNTN3 BRINP3 NUAK1 DIRAS2 MAP2 UNC80 DGKI LINC01250 DOK6 EPHA5 SCN3A NPAS2 DLGAP2 SLC39A10 MAST3 APBA2 PI4KA ARHGAP26 PACRG PRKAG2 SLIT3 HOMER1 NPTX1 MAGI3 VPS13A SHISA9 NWD2 EXT1 ARL15 WASF1 PPP2R2C ITPR1 BCL11A CACNG3 CHD5 RASA2 11-Sep MLIP MICAL2 RAP1GAP2 FMN2 BASP1 GLS FAT3 RGS4 KCTD16 TUBA1B MEG8 DGKZ LMO3 NIN SERPINI1 PRICKLE2 KIAA1549L DCC NEFL VPS41 ADAM23 SHC3 FBXL2 KCTD1 TOX WDR17 FOCAD MIR124-2HG ELAVL4 MIAT ST8SIA5 BSN YWHAH GUCY1A2 TESPA1 AC007246.3 +Ex6a NA HTR2C IFNG-AS1 ASIC2 NPSR1-AS1 TSHZ2 RP11-420N3.3 ROBO3 DPP10 ITGA8 ZNF385D HS3ST4 PCP4 CRYM TMEM155 LRP1B LHFPL3 KCNT2 SEMA5B GRM8 DIRAS2 MDGA2 SORCS2 OLFM3 MEG3 PRR16 TLE4 GRIP1 TLL1 KCNIP1 FGFR1 TRHDE CHRM2 CPNE4 LUZP2 ANKRD20A5P BCL11B GHR KIAA1456 SEMA3E CNTNAP2 CDH8 DAB1 KCNB2 COL11A1 TOX SLC24A2 MYRIP RYR2 NLGN1 VWC2L MAPK10 DPY19L1 SNTG1 DSCAM NRG3 FOXP2 DCLK1 GRIN3A CLSTN2 ERC2 SPOCK1 KIAA1217 LDB2 PTPRD CDH13 ENPP7P4 ZNF385B KHDRBS2 RALGPS2 ALCAM ADAMTS19 NKAIN2 MGAT4C AGBL4 DLC1 ADCY2 OPCML PDZRN4 RANBP17 PCDH17 CSMD3 GALNT14 KCTD8 GRM5 SYT1 STXBP6 LMO7 GABRG3 GRM3 LRRTM3 CHSY3 CORO6 DCC FARP1 UST PTPN13 TRPM2 MEIS2 RP11-586K2.1 NYAP2 PLXNA4 DOCK4 SGCD EML6 SLC44A5 DIP2A KIAA0319 KLHL5 BACH2 MLLT4 SH3RF3 STRBP CAMK2D CTC-340A15.2 ITM2C TMEM232 DPY19L2P1 FRAS1 CELF2 ZNF704 MAP1B CHN1 HS6ST3 MAGI3 SDK1 SCN3B MYT1L CADPS AC074363.1 PCDH11Y PTPRR NELL2 SLC24A3 FRMD4A ASTN2 LINGO2 KCNH7 NELL1 SLC35F3 RP1-34H18.1 GRIN2B PAK7 PHACTR1 RPH3A HERC1 NBEA CERS6 KCNQ3 ARPP21 XKR6 DLGAP4 SLC35F1 PTPRN2 GRIN2A PAK3 SOX5 OXR1 ST6GALNAC5 EVL HIVEP2 SNCA GPR158 AC005592.2 LRRC4C TLN2 LRRC7 AEBP2 FMN2 ANKRD30BL ELAVL4 NEGR1 MACROD2 BCL11A PRICKLE1 CAP2 IDS RNF144A TANC2 CACNB4 SCN8A FRMPD4 EPHA5 RPS6KC1 CDK14 SV2B HDAC9 CHL1 BMPER MARK1 SORL1 PLEKHA5 PGM2L1 EFR3A SETBP1 FAM189A1 SORBS2 RP5-921G16.1 SLC8A1 TUBA1B TPST1 ARHGAP44 CACNA1B RAP1GAP2 HCN1 BRAF KCNJ6 BASP1 ZFYVE28 EXOC4 SPAG16 NDFIP1 ZBTB16 SUSD4 RAPGEF4 PTPRT FAM49A MICU1 IQSEC1 UCHL1 LINC00632 KIFAP3 MYO5A PLCL2 SRRM3 EPB41L3 GABRA1 FAM153B ASAP1 DANT2 RBM5 KHDRBS3 CACNG3 SHISA9 +Ex6b NA HS3ST4 SEMA3E ASIC2 KIAA1217 DPP10 LRP1B PTPRD MDGA2 EGFEM1P ROBO2 DLC1 SLC8A1 RALYL PDZRN4 TLE4 CSMD1 MEG3 CLSTN2 RYR3 FOXP2 RXFP1 MCTP1 RYR2 PHACTR1 RP11-586K2.1 LRRTM4 TMEFF2 SLC35F1 NRG3 SLIT1 TRPM3 CADPS SYNPO2 OLFM3 SYT1 PDE4D NRG1 ARPP21 CELF2 NKAIN2 LUZP2 FRMPD4 KALRN EPHA5 DLG2 GRIK3 GABRG3 AGBL4 KCNH5 KHDRBS3 FAM155A KCNH7 DMD COL24A1 PEX5L ATP2B1 SORBS2 SCN3B DSCAM RP1-34H18.1 PRKCB MIR137HG SV2B NPTX1 PDE1A OPCML XKR4 MEIS2 NELL2 LINC01122 CACNA2D3 PCDH11X ERC2 GRIA3 DIRAS2 PRKAG2 CHSY3 DCLK1 ANKS1B AQP4-AS1 LDB2 KCNMB4 AK5 MMP16 PCDH11Y LRRC7 SEZ6L DGKG PAK7 TANC2 AFF3 CHN1 RAP1GAP2 GRM5 PCLO LARGE DGKI ADCY1 ZFPM2 NFIB KHDRBS2 DPY19L2P1 NEGR1 KCNQ5 AC091878.1 C8orf34 RAP1GAP FRAS1 NRCAM GRM3 CACNA1E NDFIP2 CCSER1 DOCK4 CAMK2D DIP2A ADAM23 PRICKLE1 CNTNAP5 GARNL3 SLIT3 TMEM178A KIAA1456 POU6F2 BCL11A HECW1 PCDH7 DSCAML1 PTPRN2 RIMS2 PLEKHA5 MLLT4 NGEF SLC17A7 FBXW7 01-Mar MAP2 CHRM3 SOX5 KCNMA1 DOK6 GUCY1A2 OXR1 PCSK2 CAMK2G NAV3 AC011288.2 DKK3 MYT1L STXBP5 ARHGAP26 TENM3 DYNC1I1 KIAA1211L CABP1 BMPER ERICH1-AS1 PAK3 PRICKLE2 PTPRR KCTD1 CELF4 STXBP5-AS1 CACNG3 KIAA0930 SORCS3 CDH2 11-Sep ASAP1 SLC4A10 MKL2 AP001347.6 WDR17 GAS7 NIN MLIP PGM2L1 GABRB3 CACNA1B MIAT PPM1E GPR158 LRRTM3 PTPRG EFNA5 UCHL1 RAPGEF4 ZNF385B HIVEP3 CAP2 SOBP ANKRD36B HIVEP2 SCN3A STRBP TMEM232 ARHGAP44 CHD5 AEBP2 CELF5 PDE8B FAM153B ARHGAP32 RP11-166D19.1 NLGN4Y FUT9 HOMER1 LL22NC03-2H8.5 CSRNP3 KIFC2 PPM1L PDS5B KCNB2 AC007246.3 ATP2C1 THY1 DLGAP2 SUSD4 +Ex8 NA ZNF804B KCNIP4 POSTN RGS12 MCTP2 NRG1 SORBS2 KCTD16 ERC2 NTNG2 FRAS1 LSAMP RP11-384F7.2 HS3ST4 CADPS GALNT14 CLSTN2 THEMIS SYT1 PDZRN4 NWD2 TMEM132D HPSE2 NR4A2 EGFEM1P TENM4 GNG2 SOX5 ATP8B1 SEMA6D SYNPR IQCJ-SCHIP1 DLG2 RIMS2 RIT2 CDH12 SLIT1 PDE1A RBFOX1 RXFP1 CSMD1 MAGI3 PCDH9 PCSK2 TESC TRPC5 SATB2 AK5 SPOCK1 DACH1 CPNE5 PPFIBP1 RP11-586K2.1 ARNTL2 KALRN ITGB8 CCK LAMA4 TENM3 GSG1L RASGEF1C ZNF804A RPL31 RASGRP1 TMSB10 MEG3 CBLN2 CSGALNACT1 ARAP2 UNC5C PLD5 SETBP1 RALYL CUX1 GNAO1 RP11-739G5.1 MMP16 SUSD4 MAP2K1 CACNA1B CELF2 DSCAML1 MCHR2 CADPS2 KCNQ3 MGAT5 ADCY2 UNC5D INPP4B CACNA1E DGKI PLEKHA5 CPNE4 CACNA1C CACNA2D3 SGCD NELL2 FRMD4A RPL23 TRHDE KHDRBS2 KCNQ5 SYNJ2 CHSY3 LRFN2 CNTNAP5 RPS18 GABRG3 ADGRL2 NECAB1 DCLK1 CPLX2 FMN1 RPS4X SEZ6L NPTX1 SORCS3 MTUS2 GRIP1 DGKH CHRM3 SIPA1L1 RPL37A CDKL5 RP1-34H18.1 LMO4 SYT7 SORBS1 NELL1 ERICH1-AS1 TANC2 ADAM23 EFNA5 GNG7 PTPRN2 FAM134B PRICKLE2 KCNT2 ABCC8 ENOX1 C16orf45 RP11-191L9.4 SHC3 STXBP5-AS1 RPS12 PDZRN3 CDC14B BAIAP2 DGKZ RPL13A CTDSPL ATP5E CELF4 PRKCB PTPRT ZNF385B FBXL2 POU6F2 MCF2L2 RAP1GAP2 CNTN4 CDH2 CAMKK2 RPS27A VPS13D RPLP2 NRCAM NBEA NDFIP2 LRRN2 ADGRB3 RPL34 RPS6 ARPP19 CDK14 RPL35 SNCA SLC8A1 TMEM178A RPL27 MIR137HG RPL32 BMPER LINGO1 11-Sep LARGE HINT1 ST8SIA5 MBOAT2 GRIA1 RPS24 MAST3 CCDC3 ATP2B2 PDE2A OSBPL3 CTNNAL1 EPHA4 SV2B RPL21 MIAT MKL2 FOXP1 PTPRO TAGLN3 RPS15 GNPTAB NAV3 RPL37 RASA2 MAN1A2 CAMK1D RPLP1 LARP1B CREG2 GAP43 ATP2B1 SLC4A10 PTPRR TRIM9 RPL13 UNC13A KCTD1 CYTH1 TMEM178B GABRB3 MEF2A CCNI GUK1 SRGAP3 ITPR1 KCNH3 NPAS2 C11orf80 SLC17A7 UQCRB WSB1 MAGI1 SEPW1 ARHGAP21 MNAT1 UCHL1 ACTN1 ARHGAP44 RPS19 RPL38 DYNLL1 RPL3 RPS14 FMN2 GLS EXOC6 CHD5 RPS8 SCN3A PPP2R2C CABP1 HOMER1 PRICKLE1 PDE8B SOBP PRMT8 DLGAP2 BRINP2 STMN1 SLF1 TASP1 PACRG WASF1 NIN TTLL11 BDP1 PPFIA2 GUCY1A2 THY1 STXBP5 ROCK2 RABGAP1 OLFM3 AC091878.1 PPP2R5C GFOD1 ICA1L NETO1 DZIP3 TACC1 KIAA1211L TARBP1 ZNF365 CELF5 AQP4-AS1 FHOD3 PLXNA4 RPS6KC1 RSRP1 DOK6 KIF5A ABLIM2 KIFC2 +In1a NA CCK CNR1 CXCL14 ADARB2 CRH GALNTL6 CNTN5 ROBO2 RP11-123O10.4 CHRNA7 NPAS3 RGS12 RBMS3 WIF1 RELN NR2F2-AS1 IL1RAPL2 NECAB2 DLX6-AS1 GRIP1 GRIK2 SORCS3 ROBO1 PLCXD3 AP1S2 GRIK1 SHISA9 TIMP2 ARL4C ZNF385D NPAS1 ADRA1A MYO16 CNTNAP2 PLS3 IGF1 GABRA1 GAD1 SGOL1-AS1 KIAA1211 SYNPR PID1 SCG2 KCNIP1 AC074363.1 SEMA6D COL16A1 RAB3C NRXN3 DNER ENTPD3 KCNT2 GABRG3 KCNQ5 CHRM3 SPOCK3 WWP1 CHL1 MCC MIR325HG L3MBTL4 LINC00693 SLC6A1 INPP4B SEZ6L CACNA1B ATP1B1 CDH4 DOCK10 GAD2 FSTL5 MTSS1 KCNAB1 ENOX1 SGCD PLD5 ALK DAB1 NRXN1 PLPPR1 NRIP3 SHISA6 SLC35F4 GABRG2 KAZN HMBOX1 ELAVL2 VWC2 MAML3 ARNT2 FOXG1 APLP2 HS3ST5 LINGO2 KIF1A NFIB KCNQ3 GNAS FGF14 ZNF536 ASIC2 CACNA1D ANO4 DGKB NR3C2 PTPRM SYT1 LARGE U91319.1 KIF3A SARAF CAMK2D SGK1 TTC28 SPOCK2 NMNAT2 CDH8 CNTNAP4 CPLX2 BICD1 KCNQ1OT1 NHS PRKD1 DPP6 REV3L PHYHIPL GRIA1 REEP1 PLCB4 ANKRD30BL DKK3 SLC2A13 C8orf34 LINC00461 ABAT ZEB2 SV2A PRNP DOCK9 MYT1L CLVS2 KCND3 KCNC2 KCNJ3 PDE8B GRIN2B GPR137C APP EPHA6 RTN3 PNMA2 KIDINS220 DSCAM MGAT4C NDRG4 NXPH1 CSMD3 MGAT5 CHST11 CDH13 PRKCA PARM1 UCHL1 ARHGAP5 FRMD4A TCF4 SUSD4 PRR16 MBOAT2 HSD17B12 ATP6V1A ZBTB16 CANX LINC00657 ANKRD26 NPTXR MAN1A1 PCSK2 TUBB2A TUBA1A PHTF1 SERINC1 KIF21A NAP1L3 SNRPN RP5-921G16.1 ATCAY ATP1A3 NETO1 IDS PHF20L1 BACH2 DAAM1 PCLO PAIP2 SH3RF3 HMP19 AIG1 HSP90AA1 CNTN3 AES HSP90B1 PLPPR4 RIMBP2 ITPR1 CELF4 GPR155 CDH9 ACTG1 OSBPL8 SYT11 COX4I1 CELF5 FRRS1L RNF157 KLC1 LARP1 ALDOA ALCAM GABRB2 NETO2 GNB1 FRAS1 CLTC C16orf45 HDAC9 PDXK USP11 KCNB2 PREPL MAP7D2 PTPRS MARK1 SORCS1 GABBR1 SCAMP5 ZYG11B TSPAN7 GAPDH SEZ6L2 G3BP2 PLD3 NDFIP1 SLC22A17 SYN2 ATP6V0A1 MORF4L2 USP22 EPB41L1 RAB6B DOPEY1 SLC25A12 FAM189A1 TFDP2 ADRBK2 TERF2IP ZNF483 +In1b NA CXCL14 ADARB2 CNTN5 SGOL1-AS1 CNR1 RGS12 PRELID2 C8orf34 GALNTL6 GRIK2 THSD7B ERBB4 CNTNAP2 NR2F2-AS1 NR2F2 FSTL5 GRIK1 SCG2 PLD5 ADRA1A INPP4B SYNPR THSD7A SDK1 CHRNA7 NCAM2 CDH9 DAB1 DLX6-AS1 CTC-806A22.1 CCK EGFR CNTNAP4 RP11-58C22.1 NPAS3 L3MBTL4 COL21A1 GAD2 DOCK10 SHISA9 MIR4300HG GAD1 SORCS1 ADAMTS9-AS2 CHST11 DNER ZNF385D RERG CHSY3 BTBD11 NHS PTPRM ASIC2 SPOCK3 IL1RAPL2 NTN4 MIR325HG LINC01197 LINGO2 PCSK2 PLPPR1 SLC44A5 CNTN4 TCF4 RAB3C TIMP2 ZNF536 ARNT2 RP11-123O10.4 PEX5L PRR16 DSCAM ADCY2 EPHA6 SLC24A3 MTUS2 RP11-436D23.1 SNTG1 KAZN COL16A1 KCNIP1 ARL4C NBEA SNHG14 DPP10 TTC28 BICD1 CHRM3 ATP1B1 SNRPN GABRB1 ELAVL2 ROBO1 HS3ST5 LSAMP GRIP1 FRMD4A HDAC9 ANO4 SGK1 LRRN3 KCNC2 PTPRO ZMAT4 DCC GNAL MYT1L RBMS3 KCNT2 NYAP2 SLC6A1 HMP19 RIMBP2 DGKB PCDH10 PGM2L1 GRIN2B DOK6 EXT1 MIR99AHG CDR2 RPH3A LUZP2 PDE1C ZEB2 TMEM108 PLEKHA5 PRICKLE2 SCN3A CHL1 NRG3 KCNB2 SEMA6D CACNA1B PDE7B PID1 TENM4 ZBTB16 NAP1L3 GNAS CACNA1D HS6ST3 FRMPD4 01-Mar SHANK2 THRB TMTC2 KCNQ3 REEP1 ANKRD26 SHISA6 RP5-921G16.1 CACNA2D3 KIDINS220 NETO2 REV3L PTPRS RP11-384F7.2 CDH12 LARGE MAML3 PRKCA PDE8B CDH8 VWC2 GABBR2 DKK3 SORCS3 SCLT1 CEP112 PKNOX2 OXR1 GPHN SUSD4 MYRIP MAGI3 TUBB2A NPAS2 NMNAT2 CACNA1E NPTXR PLPPR4 TSPYL2 NALCN SLC35F1 EPHA5 SV2A RIMS2 CSMD3 SRRM4 PAK3 PTPRE GRIA1 TENM3 FAM189A1 CORO6 GPR137C GABRA1 SLCO3A1 XKR4 NAP1L1 KCNQ5 RANBP17 RPL37A GABRG3 PDS5B TSPAN7 SEZ6L2 NLGN4Y USP11 PNMA2 ABLIM2 AP001347.6 WNK2 RPS6KA3 ARL15 CELF4 PHYHIPL ZNF483 KCND3 RPL34 NCOA2 NDFIP1 PRKCE GABRB2 KLC1 SYN3 SERINC1 MACROD2 PLD3 TMEM130 SCAMP5 KIF1A DAAM1 PAM SARAF SGCZ CACNG8 GRIN1 ACTG1 +In1c NA TAC3 VIP ADARB2 SYNPR DLX6-AS1 GALNTL6 ROBO2 CXCL14 CALB2 RGS12 SCG2 ERBB4 CRH CNR1 C8orf34 EGFEM1P DLX1 SLC24A3 ARL4C CCK KCNT2 THSD7A GAD1 SNTG1 CNTNAP2 IGF1 LRP1B PWRN1 VWC2L PLD5 MIR325HG PCP4 GRM7 ROBO1 GNAS LINC01322 SOBP SNHG14 DSCAM GRIA1 GABRG3 PTPRE MEG3 TCF4 NPAS3 WBSCR17 SDK1 SORCS1 ZNF536 TIMP2 TENM3 CIT NRXN3 L3MBTL4 NKAIN3 ANO4 CNTN4 TMEM132D BTBD11 NR3C2 SEMA6D KIAA1211 CNTNAP4 SLC6A1 RGS6 ZEB2 CHRM3 CACNA1D MYRIP CSMD1 PITPNC1 LARGE TSPAN7 NETO2 HMP19 KCNIP1 SHISA6 ZNF292 RP11-384F7.2 ASIC2 DNER SOX2-OT RP11-436D23.1 GNAL CNTN5 CCNI CLVS1 NAP1L3 RBFOX2 LRRC7 LRRC4C RNF180 REV3L FRAS1 VWC2 RP11-123O10.4 NPTXR CACNA2D3 DAB1 KAZN FRMD4A PLXNA4 PCSK2 HSP90AB1 NELL1 ARNT2 SEZ6L NCAM1 ZNF804A TNIK MAP1B SERINC1 OLFM3 TTC28 GRIN2B GABRA1 TMEM132B SCAMP5 LINC00461 ATP1B1 ZNF804B MYT1L DCLK1 PPM1E SLC25A12 SRRM4 KCNB2 PAK3 CDH10 ANKRD12 SLC22A17 MAN1A2 SNRPN ALCAM INPP5F TSPYL2 KCNH7 OSBPL1A ANKRD26 SYT14 TMSB4X NDFIP1 CNTNAP5 KCNQ1OT1 ZBTB16 PNMA2 CACNA1E CTTNBP2 ATCAY SLC44A5 HDAC9 KIF1A CSMD3 NFIB SORCS3 CACNA1B IDS ACTG1 TERF2IP ADRBK2 USP11 CCDC91 NCALD ZNF483 SETBP1 SARAF CHSY3 MIAT SCN3A FRRS1L CPLX2 SHISA9 DKK3 GRIN1 GRIP1 THRB CLSTN2 TFDP2 ITM2B SV2A 06-Mar PARK2 TMEM130 NEDD4L HSP90B1 LINC00657 RTN3 C16orf45 PCDH11X ALDOA TMEM59L CDH13 MAGI3 TTTY14 +In2 NA GALNTL6 ADARB2 CXCL14 NR2F2-AS1 RGS12 KCNT2 DLX6-AS1 NR2F2 CNTNAP4 CNR1 ALCAM ROBO2 COL21A1 MIR325HG SYNPR CDH9 NPAS3 ZMAT4 KIT ROBO1 ADRA1A CALB2 LRRC39 NRXN3 LINC01197 RP11-58C22.1 IGF1 ERBB4 ENTPD3 PLD5 PCDH10 CSMD3 CHRNA7 KCNIP1 RP11-69I8.3 INPP4B CRH SHISA6 NEAT1 RP11-436D23.1 DPP6 LRP1B ARL4C AFAP1 CSMD1 CNTNAP2 GAD1 GAD2 TTN CADM2 OXR1 ZEB2 DNER NLGN1 ZNF385D EGFR C8orf34 CACNA1D CNTN5 SGOL1-AS1 HS6ST3 SGK1 TNIK NHS VWC2 GABRA1 OLFM3 KCNQ5 GRIN3A SPOCK3 RAB3C MCC ANO4 PALLD HDAC9 WWP1 SNHG14 CCSER1 MGAT4C ADAMTS9-AS2 DCC BTBD11 PRKD1 CLSTN2 B4GALT6 TIMP2 SLC44A5 VWC2L EDIL3 SHISA9 KCNJ3 ZNF608 KCND3 FRAS1 CAMK2D GABRG3 CDH8 ATP1B1 PLCXD3 SEZ6L ALK THSD7A AFF2 PARM1 SNRPN PLCB4 TENM2 PARK2 PTPRE MPP6 KIAA1211 PDE7B NFIB DAB1 NR3C2 BCL2 GNAS ARNT2 RBFOX2 RNF150 RNPC3 LARP1 L3MBTL4 PLPPR1 CCK MLLT3 RP11-123O10.4 SDK1 CNTN4 TTC28 CNTNAP5 RAB2A GABRB2 FRMPD4 SLC6A1 GRIP1 ADAMTS17 OIP5-AS1 PLXNA4 KCNQ1OT1 SPOCK1 MAN1A2 GPHN GRIA1 SAMD4A LARGE TRAF3IP2-AS1 ADCY8 ASIC2 UPP1 GALNT18 PPM1E GRIN2A CIT NALCN MYT1L GPR155 ZBTB16 KIAA1456 GALNT13 DOK6 RP5-921G16.1 REEP1 KIF3A OXCT1 PDE8B TCF4 GRIK2 LINC00461 PPM1K TENM3 MEF2C CNTN3 SUSD4 SPECC1 NCALD ANKRD26 CHRM3 CANX AKAP6 OSBPL3 FGF12 SPAG16 REV3L KLHL5 MARK1 NEDD4L ABAT TMEM178B DKK3 RIMBP2 SAMD12 SYT14 NMNAT2 EEA1 AC034220.3 PKN2 SCG2 PAM EXT1 PRKAR2A RNF24 HSP90AB1 TNRC6A SSBP2 PRKCE VWA8 MYCBP2 MACROD2 SV2A LINC01322 DENND5B SLC22A17 KCNJ6 METTL15 AUH ADCY2 AHI1 RASA1 OSBPL8 KIF1A RELN MAGI1 THY1 KCTD16 SRRM4 CORO6 RUNDC3B CDK8 AIG1 KIDINS220 GPR137C CCNI PKNOX2 PRR16 STXBP5-AS1 ELAVL2 CYFIP2 FAM19A5 HOOK3 GOT1 SLC2A13 NAP1L3 MPHOSPH8 FHOD3 +In3 NA THSD7A GALNTL6 ADARB2 ERBB4 CNTNAP2 CXCL14 DLX6-AS1 RGS12 SYNPR ROBO2 CSMD1 SLC24A3 ROBO1 SHISA8 PLD5 HTR1E SDK1 PLCE1 MIR325HG L3MBTL4 KCNT2 CDH13 NR2F2-AS1 GRM7 SNHG14 RERG PROX1 MIR4300HG MEG3 ZMAT4 FRMD4A SEZ6 LRRC4C COL21A1 ZNF804A EGFR ENTPD3 SLC6A1 C8orf34 CNTN4 RYR3 PLXNA4 ADRA1A ARL4C DSCAM MTUS2 GAD1 BTBD11 TSHZ2 MYRIP NLGN1 LINGO2 TCF4 RP11-384F7.2 SLC44A5 DAB1 KCNQ1OT1 ANO4 LSAMP NKAIN3 NRG3 CHRM3 LINC01322 NRXN3 GRIK2 CIT SEZ6L OLFM3 ANK1 SCG2 CLVS1 SNTG1 CALN1 KCNH7 DCC RARB CNTN3 B4GALT6 CACNA1D TTC28 CADM2 SOBP REV3L KAZN PTPRO AK5 GALNT13 OPCML STARD13 SOX2-OT RP11-436D23.1 KLF12 SNRPN DNER PTPRE PCDH7 ANKRD30BL WBSCR17 SRRM4 ATP1B1 TENM3 MYT1L GNAL SUSD4 FHOD3 SLC25A12 GABRG3 GNAS KCNAB1 RP11-123O10.4 NCALD MAN1A2 CSMD3 RBFOX2 OSBPL3 CACNA1C TMEM132B FRMPD4 KCNC2 LIMCH1 PPM1E HMP19 AC007563.5 CCSER1 SORCS3 RP5-921G16.1 GPHN GRIP1 ADCY2 NCAM1 MAPK4 NTRK3 PRICKLE2 SYT14 SMARCA2 EXT1 HDAC9 BICD1 KCNIP4 PDE7B ANKH ATP1A3 GABRB2 GRIN2B ZBTB16 MAP2 NEDD4L PLEKHA5 THRB AHI1 CORO6 ZEB1 TSPYL2 TSPAN7 CAMTA1 GABRA1 TMEM108 RPS6KA2 NR3C2 DCLK1 SCAMP5 SLC2A13 PAM TRAF3IP2-AS1 INPP5F PAK3 ATCAY RANBP17 TFDP2 ANKRD26 REEP5 NMNAT2 ANKRD12 CYFIP2 ARHGAP44 OSBPL1A FNDC3A GABBR2 USP11 RGS6 IDS CDH10 SV2A OIP5-AS1 LARGE PCDH11X ADRBK2 SPTBN4 PTPN4 DDX24 KIF1A CERS6 KIRREL3 SERINC1 GRIN1 +In4a NA RELN CXCL14 ADARB2 GAD2 INPP4B SGOL1-AS1 DLX6-AS1 ERBB4 CNTNAP2 FRAS1 SV2C SLC6A1 HS3ST5 DNER CNTN5 GALNTL6 FREM1 ROBO2 EGFR RP11-123O10.4 GRIK2 COL5A2 SGCZ MGAT4C PTPRM C8orf34 DOCK10 GRIK1 KCNC2 ADRA1A PTPRT FGF13 FSTL5 MYO16 FAT1 DAB1 NCAM2 GRIP1 TOX3 SCG2 KAZN ALK PCDH15 FGF14 SPOCK3 PLD5 GAD1 ANKRD55 XKR4 GRIN3A CNTNAP4 NYAP2 NXPH1 UNC5D KCNIP1 RAB3C ZMAT4 RGS12 RIMBP2 ROBO1 LAMP5 GRIN2A CACNA2D1 CHSY3 BCL11B MCTP1 PRR16 KCNAB1 CSMD3 CACNA1B PTCHD4 PRELID2 RBMS3 ARL4C PIP5K1B ZNF536 ADRBK2 GRM8 GRM5 SHISA9 SGK1 EPHA6 EXT1 LINGO2 PRKCB MAML3 NEBL GRIA2 PCDH17 CNR1 GABRB1 HDAC9 CDC5L RPH3A MTSS1 CHRM3 ZBTB16 NPTXR GABBR2 PTPRO ABI1 CACNA1E MPPED1 ALCAM BTBD11 NIPAL3 DGKB FGF12 ANKRD26 SLC35F1 KIAA1211 TMEM132D MPP6 SOX2-OT GRIA4 MACROD2 MAGI3 CHL1 RP11-384F7.2 PRNP ERC2 CDH9 KCNT2 NETO1 GABRB2 AC074363.1 SORCS3 FLRT2 CELF4 SERINC1 PKNOX2 ARNT2 NAP1L3 AP001347.6 MTUS2 DOCK3 ITM2B PID1 TMEM132B KIDINS220 SDK1 KCTD16 GABRA1 SYN3 PNMA2 MYRIP ANO4 KIF1A PTPRS FRY PLPPR4 LUZP2 APP REEP5 HSP90AB1 PHYHIPL CNTN4 CANX USP11 RP11-382A20.3 SHC3 SNRPN VWC2 ZCCHC11 PDE8B CAMKV THRB RAPGEF4 PHF14 HMP19 SARAF LINC00461 KCNQ1OT1 ZNF483 APLP2 FRRS1L GAS7 SEZ6L KIAA1109 RTN3 CACNB2 TMEM178B PCSK2 CACNG8 NDUFA4 SCG5 MICU1 GNAS GRIA1 RNF150 KCNB2 COG5 DAAM1 TTC28 ATP6V0A1 GPR137C SV2A SCAMP5 PAK3 HIVEP3 TUBB2A ELAVL4 SEMA6D ABR DKK3 CSRNP3 BICD1 ATP6V1A TMEM232 SCAI LINC01122 APBA1 BRINP2 LINC00657 ACTG1 +In4b NA FGF13 KIT PRELID2 ADARB2 GAD2 PTCHD4 SLC6A1 SGCZ RP11-123O10.4 CTC-806A22.1 GRIK1 PTPRT DNER EYA4 SV2C MYO16 MGAT4C DLX6-AS1 ALK GRIN3A LAMP5 CDH13 FBXL7 NXPH1 PKP2 TACR1 GRIN2A BCL11B NRIP3 GRIP1 SPHKAP KCNIP1 RAB3C NXPH2 KCNAB1 TMEM132D TRPC3 TOX2 NTNG1 RBMS3 KIAA1211 KCNC2 PTPRM GAD1 LUZP2 DGKD LINC01314 MTUS2 SOX2-OT KAZN SYT1 AP1S2 ERBB4 FGF14 CXCL14 GNG4 MACROD2 ZNF536 ARL4C NYAP2 ATP8A2 PDGFD UBASH3B FREM1 FSTL5 UNC13C NFIB HPCAL1 IL1RAPL1 ANKRD55 GOLIM4 ADAMTS9-AS2 EGFR DOCK10 HTR1E CNTN5 C8orf34 NKAIN3 PIP5K1B ADAMTSL3 LSAMP SGK1 MTSS1 MCTP1 RPH3A SYN2 GRM5 UNC5D GRIA4 SEMA6D ITM2C PID1 EGFEM1P CDK14 TMEM132B ADRBK2 WWP1 IGSF11 TOX GRIK2 ZEB2 EXT1 PDE8B CDHR3 CCK FAM110B VWC2 DAB1 GRIA1 LRRC7 RIMBP2 SNHG14 GABRD UNC5C AP001347.6 SLC35F1 EEPD1 CNTNAP4 XKR4 SPOCK2 CACNA2D1 KIRREL3 GABBR2 EPHA3 KCTD16 CHST11 KIAA1107 BRINP2 SCN1A CCSER1 NRG1 DPP6 SPOCK1 ABI1 CELF4 PRKCE RGS7 CSMD3 SARAF PLCXD3 KCNH5 SH3RF3 DOCK9 LCORL ATP1B1 SAT1 MPPED1 APLP2 GABRB2 DGKB WASF3 GPR155 TMSB4X KIAA1109 PLCB1 PRNP RNF150 SH3GL3 NDUFA4 KCNQ3 NAP1L3 PTPRB HECW2 SV2A DLGAP1 APP GALNT18 NETO1 ZMAT4 PHYHIPL ASTN2 GABRB1 ARNT2 FRY PAK3 RP11-384F7.2 ADGRL2 CANX CAMKV AMMECR1 GPR158 SERINC1 SNRPN DSCAML1 GABRG3 ABAT MAP3K5 RGS7BP MIR181A1HG ARID5B SLIT2 HSP90AA1 SCG2 GRIN2B ANKRD26 MPDZ NGFRAP1 SAMD12 SLC22A17 NPTXR KIF21A PNMA2 USP22 RASGRF2 WSB1 EFR3B ANKRD30BL ANKH AC074363.1 GNAS TENM4 SH3KBP1 BICD1 TERF2IP USP11 FAIM2 SHISA9 ITM2B IDS REV3L DOCK3 CYFIP2 KLC1 TLK1 LRRFIP2 NMNAT2 GRIA2 YWHAB SLC2A13 OSBPL6 TSPYL2 HSP90AB1 DOK6 BEX2 NAV2 PTPRO SDK1 CHSY3 PRKAR2B CACNA1B NAPB LINC00599 PEBP1 CACNG8 MAST4 RANBP17 LRRTM3 KIF3A ADAM22 ATP6V1A CAP2 REPS1 LINC00657 DKK3 KIF1A GRIN1 SMYD3 AMPH DAAM1 BEX1 ASTN1 SCAMP5 PKNOX2 PREPL SEZ6L2 LRRC8B RAPGEF4 FAM49A SUSD4 HMP19 RTF1 TUBB2A TCEAL2 CACNG3 PRICKLE2 ADK PDZRN3 EPHA5 ATP6V0A1 SLC25A12 MORF4L2 NSF PGM2L1 UCHL1 LONRF2 KIFAP3 MAP7D2 SLC12A5 EML6 +In6a NA CNTN5 DPP10 ZNF385D CA8 ALK SDK1 ERBB4 THSD7A CRH PVALB SLC9A9 CNTNAP2 TMEM132D RP11-420N3.3 LHFPL3 KCNAB1 ZNF804A HPSE2 LRRC4C SLC6A1 TRPS1 VWC2 PLCXD3 SPARCL1 MYO16 ANK1 RP11-123O10.4 RORA FRMPD4 ZNF536 TMEM132C DNER DLX6-AS1 DLGAP1 GRIA1 GABRG3 FGF13 FSTL5 MDGA2 TMTC1 GULP1 TENM4 ADAMTS17 KIAA1211 FAM19A2 SNHG14 CALN1 SGCD MEF2C KCNC2 TOX TENM1 ADCY8 SCG2 RASGRF2 SRGAP1 AC010127.3 COL11A1 GRIP1 RBMS3 CNTNAP5 GRIA4 RYR1 RASSF8 FGF12 PTCHD4 ATP1B1 SOX6 PLD5 TIAM1 TENM2 ZNF804B MEG3 SLIT2 HCN1 GABRD EDIL3 LINC00693 ANO4 CPLX1 ADGRB3 SYT1 DAB1 NHS FMN1 GALNTL6 CADPS NBEA DOK5 SLC4A10 SLC24A3 PARM1 PPM1E NRG3 AC074363.1 ASTN2 HS6ST3 OSBPL6 RP11-444D3.1 KCNQ5 SNRPN NCALD CSMD3 DLGAP2 PCLO SHANK2 OSBPL3 MTUS1 BTBD11 NYAP2 UNC5C SPOCK3 KCNC1 NEAT1 KLHL5 IQCJ-SCHIP1 MAST4 HMP19 ATP1A3 PTPN13 GRM5 CDH12 GNAL C8orf34 ADRBK2 KCNJ6 SYT14 SPOCK1 TMEM132B CNTN4 PLXNA4 MGAT4C FUT9 CSMD2 KCNMB4 GRIN2B CTTNBP2 GABRA1 SPOCK2 SNTG1 RP5-921G16.1 SCN1A ADCY1 KIAA1456 SLC2A13 SUPT3H RNF175 ATRNL1 GAD1 UNC5D LRRC8B PKNOX2 ELMOD1 DGKB ZEB2 SUSD4 NDRG4 SIPA1L1 AUTS2 SEZ6L SV2A CDR2 KIAA1107 LUZP2 OIP5-AS1 KCNH1 SLC35F1 RIMBP2 LANCL1 CAMTA1 GOT1 SLC38A1 GABRB2 NSF PAM SETBP1 GPR155 PRICKLE2 SPAG16 KIFAP3 ABLIM2 PTPRN2 SCAMP5 GRID1 SYP BLCAP NF1 CCDC91 RAB3C CACNG2 EPHA5 FAM168A MEG8 PNMA2 PLEKHA1 USP22 MAP2 SPTAN1 APLP2 ANKRD26 GAPDH TPST1 GABBR1 SLC25A12 ANKS1A AFF3 EPB41L3 DENND5B USP11 TENM3 KHDRBS3 KIF1A GRIA3 LINC00657 SCN8A ALDOA SHISA9 ATP1A1 CIT +In6b NA ERBB4 DPP10 BTBD11 NXPH1 GAD1 KCNC2 ZNF804A TAC1 SLIT2 KCNAB1 TMEM132C RP11-123O10.4 KIAA1217 PTPRM GAD2 CNTNAP2 SOX6 ZNF385D FGF12 DLGAP1 ADAMTS17 SDK1 SPARCL1 MYO16 PVALB SLC9A9 VWC2 GRIP1 TENM3 SPOCK3 SLC6A1 SNHG14 ANK1 SNRPN CNTN5 KLHL5 KAZN AC010127.3 RBMS3 RP11-444D3.1 TENM1 ZMAT4 NHS CPLX1 EPHA6 ELAVL2 CADPS RPS6KA2 ZNF536 KLF12 RASGRF2 TENM2 LRRTM4 PAM SERPINI1 MEF2C KIF26B ATRNL1 IL1RAPL1 ADAMTS9-AS2 CEMIP ALK GRIK3 DGKD LRP8 PPARGC1A SLC44A5 KCNC1 GABRG3 XKR4 PTCHD4 PLCXD3 SAT1 FAM19A2 ASTN2 ANO4 GNAL PLXNA4 HCN1 OXR1 NEAT1 PRKG1 LRRFIP1 SGCZ LANCL1 TMEM108 ATP1B1 DNER ENOX1 PPIP5K2 TRPC5 ADCY8 SLC4A10 RP11-766N7.3 RBFOX1 TIMP2 ADRBK2 HS6ST3 SHISA9 ABAT GRM5 ROBO2 RP5-921G16.1 LRRC4C GABRB2 OSBPL3 NRG3 SYN2 GRM8 CORO6 SUPT3H SV2A FAR2 MAGI1 ARHGAP20 KHDRBS2 GOT1 U91319.1 RAB3C UPP1 GRIN2B EFR3B SNTG1 FMN1 SH3RF3 FGF13 SLC35F1 ADCY1 FRAS1 SRRM4 CLIP4 MDGA2 SCN1A LUZP2 SPAG16 PTPRN2 CNTNAP5 ANKS1A ERC2 FHOD3 NDST3 ARNT2 NDRG4 GABRA1 NCOA2 TTBK2 ESRRG CACNB4 SETBP1 ARL4C PRKCE LPCAT4 CLEC16A PTPRS MAN1A2 UNC5D SLC38A1 CCDC136 CAMTA1 MAP2 MAP1A ITSN1 OSBPL6 NTRK2 UBA6-AS1 MMP16 LUZP1 FAM135B TMEM132B ATP1A3 RASA1 GNAS ST8SIA1 PTPRE ATP5B NCALD RASAL2 BEND6 SCAMP5 FAM189A1 MDH1 SLC6A17 MAST4 TRIO GAPDH BACH2 AEBP2 NMNAT2 DAAM1 OIP5-AS1 EVL RNF157 GPC6 AAK1 MAP7D2 OSBPL8 SLC4A8 NDUFA4 RAPGEF4 NSF SRRM3 DYNLL2 DNM1 PPM1E STXBP5-AS1 SPIN1 MGEA5 KCNT1 SHANK2 TSC22D1 SULT4A1 PRICKLE2 TTN-AS1 MAP9 PNMA2 LRRC8B CDH9 COX4I1 SLC22A17 ATP6V1B2 MEG8 ST6GALNAC5 CALM3 SCN8A DLGAP2 SLC25A12 MARK1 INPP5F BLCAP PACRG TMEM130 +In7 NA GRIK1 SGCZ ROBO2 SST CDH12 NPY NCAM2 CALB1 CBLN4 NXPH1 PENK DAB1 GRID2 KIRREL3 ZNF385D KIAA1217 TENM3 RP11-123O10.4 PTPRM XKR4 SOX6 GAD1 COL25A1 SLC24A3 SYNPR SPOCK3 VWC2 KCNIP1 KIF26B SNHG14 GRIK3 NETO2 TOX2 NRXN3 ANKRD55 DLGAP1 LRP8 FSTL5 COL19A1 PTPRT CADPS KLF3-AS1 GRIP1 BACH1 THSD7A RASGRF2 CDH9 TENM2 TMTC1 EPHA6 ELAVL2 PCLO CACNG8 TMEFF2 PCDH15 KCNAB1 SNRPN TIMP2 RBFOX1 SNED1 PIP5K1B SCG2 MYRIP MAN1A1 TIAM1 KIAA1211 ROBO1 SLC6A1 ALK MAP3K5 LARGE OXR1 CDH8 PDZRN4 AHI1 PDE4B KAZN ANO4 GRIA3 CNTN6 RBMS3 PTPRN2 KIAA1324 LRRFIP1 ADAMTS19 BCL11A SOX2-OT ADAMTS9-AS2 C8orf34 ADCY2 04-Mar RP11-444D3.1 MPPED1 KCNC1 LRRC7 HCN1 PTCHD4 PCDH7 CHRM3 DGKG LINC01122 HS3ST5 NTRK2 SPARCL1 AUTS2 PACRG KCTD16 CIT AAK1 LRFN5 FAM135B RPH3A MEF2C TCF4 ZNF385B KCNT1 ETV6 TMSB4X SH3PXD2A GPC6 GRM7 GRIN2A SLC8A1 SETBP1 LINGO2 ARHGEF3 CACNA1A RUNX1T1 KLF12 RPS6KA2 MIR181A1HG SORBS2 RIMS2 MAP2 KCNMA1 RALGAPA2 TSPYL2 GRIA1 CYP46A1 SMARCA2 SCG5 MPDZ EPHB6 RAPGEF4 PPM1E MAST4 TMEM108 GRM5 TAOK3 KCNQ3 ATP1B1 NEGR1 CCDC136 FARP1 DMD FNDC3A GARNL3 SLC25A12 CUX2 SV2A CAMK2N1 HECTD2 OSBPL3 ZNF804A ANKRD26 MAP7D2 CLVS1 INPP4A ANKRD30BL NCOA2 PTPRG AC074363.1 SLC22A17 PRNP RCAN2 PRKCE PDE7B GIT2 PDE8B GLG1 UBA6-AS1 CACNA1C RNF157 LRRTM3 PTPRJ CORO6 KCNH1 ABAT PAM PCDH11X ITSN1 SYN2 ITFG1 DANT2 GPR155 C16orf45 PTPRO EVL ANKRD36C KIF1A NGFRAP1 PHF20L1 RASAL2 GFOD1 TENM4 CACNG3 ATG7 SCAMP5 FAM19A5 RAB3C EML6 LIN7A NR2F1-AS1 NDUFA4 SLC44A5 CACNG2 TSPAN7 USP11 CHD5 SULT4A1 PNMA2 KIF21A CSRNP3 ODF2L PJA2 CALM3 NPTN MAGED1 FAM189A1 DLGAP2 MIAT CAP2 +In8 NA GRIK1 SST ROBO2 SYNPR NXPH1 KIAA1217 RP11-123O10.4 ROBO1 SPOCK3 CNTNAP2 PCDH15 XKR4 MAFB GRIN3A CDH13 GRIK3 SOX6 SHISA6 NRXN3 GAD1 COL25A1 TENM3 KIF26B GRIP1 GRIK2 MAF PCDH11X MGAT4C ELAVL2 RAB3B SPARCL1 PLCH1 DLGAP1 CDH9 ST6GALNAC5 PTPRM ASTN2 STXBP6 SNHG14 LRP8 RBFOX1 RBMS3 ADCY2 DAB1 EPHB6 TIMP2 RASGRF2 NETO2 TENM2 SLC24A3 WLS SNRPN KCNIP1 OXR1 TRHDE GRIA3 NPAS3 NRIP3 KLHL5 PCDH11Y RAB3C GAD2 CACNA2D3 SATB1-AS1 CADPS PITPNC1 BCL11A KCNC2 GNAS NETO1 GRIA1 TMSB4X FRMD4A TIAM1 RUNX1T1 SLC6A1 RPS6KA2 TENM1 MPPED1 CDH8 SYT1 TMTC1 PCLO DMD GRIN2B DAPK1 LIMCH1 AAK1 CTNNA2 LINC01322 PDE1C SLC44A5 PAM PHF20L1 NTRK2 L3MBTL4 PIP5K1B TCF4 RIMS2 PNMA2 CHRM3 TLN2 GPC6 ABAT CCDC136 ARL4C AC005592.2 PTPRN2 PPM1K OSBPL8 MYT1L CNTN4 FARP1 ATP1B1 MYRIP NAV2 CHD5 CELF4 SLC8A1 TSPAN7 TMEFF2 ENOX1 EPHA6 LRRFIP1 AUTS2 UCHL1 DPP6 FAM135B MAGI1 SMARCA2 CDH12 RPH3A HSP90AB1 ANKRD36C TUBB2A IDS PDE8B TMEM178B RYR2 TSPYL2 VSNL1 DNM1 NGFRAP1 THRB GRIN1 CCSER1 KCTD16 SCAMP5 PTPRO ANKRD36 ITFG1 SV2A MTUS2 PTPRG NCALD ADGRL2 CACNG3 KCNB2 LINC01122 SARAF THSD7A DAAM1 NCOA2 ANKRD26 BEX1 TMEM130 PRNP AHI1 LRRC8B CACNG8 GRM5 RCAN2 SPATS2L SERINC1 HCN1 SCG5 EVL ARNT2 PDS5B OIP5-AS1 KIF21A SETBP1 SLC25A12 APLP2 ANKRD12 NDRG4 ABR FAIM2 NDFIP1 RUNDC3B MPDZ GARNL3 DDX24 GALNTL6 WSB1 TMEM59L CALM3 +Mic NA APBB1IP DOCK8 C10orf11 ST6GAL1 PLXDC2 ADAM28 C3 ITPR2 DOCK4 P2RY12 INPP5D TBXAS1 SYNDIG1 FYB ARHGAP24 AOAH RASGEF1C SLCO2B1 CSF1R ARHGAP22 ATP8B4 RP11-480C22.1 SFMBT2 CH17-437K3.1 MEF2A FRMD4A NAV3 CYFIP1 SRGAP2 SORL1 HS3ST4 SLC9A9 KCNQ3 ST6GALNAC3 ANKRD44 DIAPH2 MEF2C TBC1D22A PRPF38B EPB41L2 LDLRAD4 FCHSD2 ELMO1 MAML3 MBNL1 ABR MAML2 FAM49B UBE2E2 CHST11 ATM ZSWIM6 PKN2 QKI PICALM ASH1L PCM1 DOCK10 TCF12 RBM25 DIP2B DLEU2 GRID2 PRRC2C EVL SPIDR MAP4K4 RASAL2 NEAT1 +Oli NA PLP1 MOBP ST18 RNF220 CTNNA3 MBP TF CLDN11 SLC44A1 SLC5A11 TMEM144 CERCAM FRMD4B LINC00609 DOCK5 ENPP2 CNDP1 PIP4K2A KCNH8 QKI LINC01608 PLEKHH1 CARNS1 SCD CNP DOCK10 MOG CNTN2 C10orf90 PDE8A SHTN1 AC012593.1 SHROOM4 TMTC2 PHLPP1 DPYD EDIL3 COL4A5 NCKAP5 CLMN BCAS1 PLCL1 PXK PTGDS MAN2A1 PLD1 PDE4B SLC24A2 TMEM165 TTLL7 PRUNE2 ABCA2 FRYL QDPR ELMO1 PDE1C PPP2R2B ERBB2IP HIP1 SLAIN1 CREB5 FRMD5 GAB1 MAP7 GPRC5B PSEN1 IL1RAPL1 ZEB2 TCF12 SIK3 CNTNAP4 MAP4K4 TRIM2 HIPK2 FMNL2 SLCO3A1 SPOCK3 ANO4 UNC5C LMCD1-AS1 SH3D19 PCDH9 ARAP2 SH3GL3 ALCAM SRCIN1 TMEFF2 ZNF536 JAM3 MYO1D DLG1 SLC22A15 01-Mar FBXL7 07-Sep GRM3 DLC1 SORT1 FUT8 ZDHHC20 APBB2 DIP2B ZFYVE16 KLHL32 TJP1 FNBP1 PTBP2 ANKIB1 PEX5L DSCAML1 SOX2-OT DST DNM3 PTPRK NEAT1 CDH20 ATP8A1 AK5 GPM6B SGK1 SECISBP2L MAP4K5 CCDC88A DNAJC6 BAZ2B COBL AGAP1 RNF130 MYO6 ZBTB20 PLXDC2 FHIT SCD5 ANK3 ARHGAP21 NCAM2 NKAIN2 PDE1A HSP90AA1 NPAS3 DLG2 RERE CDC42BPA APP TBC1D5 UBE2E2 FAF1 HECW2 AUTS2 WDPCP PRRC2C KIF1B RBM25 DDX17 ANKRD12 GOLGA4 SRPK2 DPYSL2 KMT2E NAALADL2 CACNA2D1 PPP1R9A TSPAN5 NLK PHIP DTNB BOD1L1 KIRREL3 +OPC NA LHFPL3 PCDH15 TNR PTPRZ1 RP4-668E10.4 VCAN SEMA5A LUZP2 XYLT1 EPN2 CHST11 SOX6 DSCAM BCAN COL9A1 SMOC1 LRRC4C KIF13A MMP16 SLC35F1 OPCML AGAP1 PLPPR1 SCD5 LINC00511 CA10 NAV1 MEGF11 SEZ6L OPHN1 OLIG1 LRP1B SOX2-OT NLGN1 ZEB1 MAML2 NTM KAZN DPP6 COL11A1 NOVA1 TAOK3 NKAIN3 CASK NXPH1 PDZD2 TMEM132C HIP1 NAV2 BRINP3 NRCAM GRID2 PID1 CSMD3 SPATA6 TNK2 REV3L DCC ADARB2 CHL1 MDGA2 ABHD2 BCAS1 KAT2B LSAMP C1orf61 FHIT ADGRL3 QKI PEAK1 C10orf11 PRKCA GRIK1 DGKG SCN1A ZBTB20 PDZRN4 PPP1R9A PDE4B NPAS3 ASTN2 ZNF462 NLGN4X ADAMTS17 SH3D19 KCND2 NCKAP5 NCAM1 LRRTM4 APBB2 ZSWIM6 CSMD1 SNTG1 NRXN1 MTSS1 ASAP1 SOX5 RP11-436D23.1 ALCAM FCHSD2 KIF26B CTTNBP2 FGF12 RP11-384F7.2 NCAM2 SGCD KCNQ1OT1 KLF12 CDH20 CSMD2 RPL13 XKR4 LINC01322 GALNT13 SHISA9 CHD7 01-Mar WWOX DSCAML1 ITPR2 GRM7 PHLPP1 GPC6 COBL SORCS3 NFIA SLC24A3 TCF12 DOCK10 SGK1 NAALADL2 ATRNL1 +Per NA ATP1A2 DLC1 ITIH5 SLC19A1 SLC6A12 LAMA2 COLEC12 RBMS3 DCN HIGD1B NOTCH3 EBF1 IGFBP7 EPAS1 PDGFRB COBLL1 SLC6A1 CALD1 EPS8 UTRN SLC20A2 NR2F2-AS1 MYO1B GRM8 SLC38A11 TXNIP CYTH3 PARD3 B2M ZEB1 LHFP PRKG1 PTN RP11-649A16.1 PDE7B ARHGAP29 PDE8B UACA GPC5 ADAMTS9-AS2 RORA TJP1 PTPRK GRM3 PTEN PTPRG PPFIBP1 TACC1 ZBTB20 SASH1 NEAT1 KIAA1109 HSP90AA1 PDZD2 PTGDS TTC17 NTRK3 SLC1A3 LPP DDX17 APBB2 INPP4B DLEU2 NFIA \ No newline at end of file diff --git a/imaging_transcriptomics/data/geneset_Pooled.gmt b/imaging_transcriptomics/data/geneset_Pooled.gmt new file mode 100644 index 0000000..354da97 --- /dev/null +++ b/imaging_transcriptomics/data/geneset_Pooled.gmt @@ -0,0 +1,7 @@ +Astro NA A2ML1 AADAT AASS ABCA7 ABCD2 ABLIM1 ACAA2 ACACB ACADVL ACBD7 ACKR3 ACO2 ACOT11 ACOX2 ACP6 ACSBG1 ACSF2 ACSL6 ACSS1 ACSS3 ADA ADAM20P1 ADAMTSL5 ADCY2 ADCY8 ADCYAP1R1 ADD3 ADGRV1 ADHFE1 ADI1 ADORA2B ADRB1 AEBP1 AGBL2 AGFG2 AGL AGT AHCYL1 AHCYL2 AHNAK AIFM3 AK4 AKR7A2 ALDH1L1 ALDH2 ALDH4A1 ALDH7A1 ALDOC AMOT AMT AMZ2 ANGPTL4 ANKDD1A ANKRD35 ANKRD45 ANO8 APC APEH APLNR APOE AQP1 AQP4 ARHGAP24 ARHGAP32 ARHGAP5 ARHGAP5-AS1 ARHGEF26 ARHGEF26-AS1 ARHGEF4 ARL6IP6 ARRB1 ARSJ ASAP2 ASAP3 ASPH ASRGL1 ASTN1 ATP13A4 ATP1A2 ATP1B2 ATP6AP1L BAZ2B BBOX1 BBS2 BBS4 BCAN BCKDHB BDH2 BHMT2 BMP7 BMPR1A BMPR1B BRINP2 C1orf61 C5 CA12 CABLES1 CACHD1 CACNB1 CACNB2 CADM1 CAMK2G CAPN2 CARMIL1 CASC10 CASC2 CAT CD38 CDH2 CDH20 CDH26 CDH4 CDHR3 CEP350 CEP85L CERS1 CGRRF1 CHDH CHI3L1 CHPT1 CHRDL1 CHRNB1 CKB CLDN10 CLDN12 CLEC16A CLPTM1 CLU CMBL CNTFR CNTNAP3 COL5A3 COLCA1 COLCA2 COPS7B COQ10A CPE CRB1 CRYAB CRYZ CSGALNACT1 CST3 CTH CTNNA2 CTNND2 CXCL3 CXCL5 CYB5B CYBRD1 CYP2J2 CYP4V2 CYP7B1 DAAM2 DAG1 DBI DBP DCLK2 DCT DCUN1D1 DCXR DDAH1 DECR1 DGKG DHODH DHRS4-AS1 DHTKD1 DIAPH3 DIO2 DKK3 DMGDH DNAAF5 DNAH7 DOCK4 DOCK7 DOK5 DOLK DPP10 DPP8 DPY19L3 DPYSL3 DST DTNA DTX1 ECHDC2 EDNRB EEF2K EFEMP1 EFHC1 EFHC2 EFNA5 EFR3B EGFR ELMO2 ELOVL2 EMID1 EMX2 EMX2OS ENHO ENKUR ENO1 ENTPD2 EPHB1 EPHX1 EPHX2 ERBB2 ERBB4 ERLIN2 ETAA1 ETNPPL EYA1 EYA2 EZR F3 F8 FADS2 FAM107A FAM118B FAM167A FAM168A FAM171A1 FAM171B FAM181B FAM184A FAM189A2 FAM198A FAM213A FAM71F2 FARP1 FAT1 FAT3 FBXL7 FBXO2 FERMT2 FEZF2 FGD6 FGF2 FGFR3 FGFRL1 FGGY FHIT FJX1 FKBP10 FKBP9 FMN2 FNBP1 FOS FOXRED2 FUT10 FUT9 FYN FZD8 GABBR1 GABRA2 GABRB1 GABRG1 GAPDH GAS2L1 GAS8 GBA GCDH GDPD2 GFAP GGACT GJA1 GJB6 GLI1 GLI3 GLIS3 GLUD1 GLUD2 GLUL GNA14 GOLGA2P5 GOLIM4 GPAM GPC4 GPC5 GPD2 GPM6A GPM6B GPR143 GPR171 GPR19 GPR37L1 GPR75 GPRC5B GPT2 GRAMD1C GREB1 GRIN2C GRM3 GSTM5 H3F3B HADHB HAP1 HEPACAM HEPH HERPUD2 HES1 HGF HHATL HHIPL1 HIF3A HOPX HPR HPS4 HPSE2 HRH1 HS2ST1 HSBP1L1 HSD17B6 HSDL2 HSPA1A HSPB1 HTRA1 ID2 ID3 ID4 IDH2 IFT27 IFT43 IGFN1 IGSF1 IL17D IL17RB IL33 INHBB INTS3 INTU IQCA1 IQCH IQCH-AS1 ITGA7 ITGB4 ITM2C ITPKB ITPR2 ITSN1 JUN JUNB KATNAL2 KCNA2 KCNJ10 KCNN3 KCTD15 KCTD21 KIAA0319 KIAA1671 KLF15 KLKB1 KNDC1 LAMA1 LANCL2 LCNL1 LCTL LDHB LDHD LETM1 LFNG LGI1 LGI4 LGR4 LGR6 LHX2 LIFR LINC00461 LINC00595 LINC00654 LINC00839 LINC00886 LINC00900 LINC00982 LINC01158 LINC01351 LIX1 LMO3 LPIN1 LRIG1 LRP1 LRP1B LRP4 LRRC3B LRRC75A LRRC8A LRTOMT LSAMP MACF1 MAML2 MAOB MAP3K5 MAPK10 MAPK4 MASP1 MAST4 MCCC2 ME1 MEIS2 METRN METTL7A MGAT4C MGC16275 MGST1 MICALL2 MINK1 MIR99AHG MKLN1 MLC1 MLYCD MOCS1 MOK MOXD1 MRAS MRO MROH7 MRVI1 MRVI1-AS1 MSI2 MST1 MT1G MT2A MT3 MTHFD1 MTM1 MTMR1 MTSS1L MUL1 MUT MUTYH MYBPC1 MYH15 MYO10 MYO6 MYOM1 NACC2 NADK2 NAT8L NAV2 NBPF1 NBPF10 NBPF11 NCAN NCKAP5 NDP NDRG2 NDUFAF6 NDUFS3 NEAT1 NEBL NEK1 NEK11 NEK6 NFATC4 NFIA NFIB NHS NHSL1 NINL NKAIN3 NKAIN4 NME9 NOTCH2 NPAS3 NQO1 NR2E1 NRG3 NRXN1 NT5E NTM NTNG2 NTRK2 NTSR2 NWD1 OAF OGFRL1 OLFM2 OPHN1 ORAI3 OSBPL2 OTX1 OXTR P2RY1 PALLD PAMR1 PAPLN PARD3 PARD3B PARP3 PAX6 PAXIP1-AS2 PBXIP1 PCDH9 PCDHB4 PCDHB5 PCDHGA12 PCDHGA3 PCDHGA7 PCDHGB7 PCDHGC3 PCSK5 PDE4DIP PDE7B PDLIM3 PEX11A PEX12 PFKFB2 PFKM PGM1 PHACTR3 PHF21B PHGDH PHKA1 PHLPP1 PHYHD1 PIK3C2A PIPOX PIR PITPNC1 PLA2G5 PLCD1 PLCD4 PLCG1 PLEKHA7 PLIN4 PLIN5 PLOD2 PLSCR4 PLTP PLXNB1 PMM1 PMP2 PNPLA7 POLL PON2 PON3 POU2F1 POU3F2 PPARA PPARGC1A PPFIA1 PPP1R1B PPP1R26 PPP1R3C PPP1R3D PPP1R3G PPP2R2B PPP2R5A PRDM16 PRDM5 PRDX6 PREX2 PRKCA PRKD1 PRKG1 PRODH PRSS35 PSD2 PSD3 PSMG3-AS1 PTAR1 PTCH1 PTCHD1 PTGDS PTN PTPN9 PTPRA PTPRF PTPRZ1 PYGB PYGM QKI RAB30 RAB34 RALGAPA2 RAMP1 RANBP3L RAPGEF3 RASSF4 RBM26-AS1 RFX2 RFX4 RGMA RGN RGR RGS20 RGS9 RHOB RHOBTB3 RHPN2 RLBP1 RND1 RNF170 RNF182 RNF43 ROBO3 RORA RORB RPS6KA2 RYR3 S100B SALL2 SARDH SASH1 SAT1 SCARA3 SCG3 SCRG1 SDC2 SDC3 SDC4 SDS SEC14L2 SELENBP1 SEMA3D SEMA4A SEMA4B SERPINE2 SESN3 SFXN5 SGCD SHROOM3 SIRPA SLC13A5 SLC14A1 SLC15A2 SLC16A9 SLC18B1 SLC1A2 SLC1A3 SLC1A4 SLC25A18 SLC25A20 SLC25A29 SLC25A33 SLC25A43 SLC25A48 SLC25A53 SLC27A1 SLC2A10 SLC2A12 SLC30A10 SLC35C2 SLC35F1 SLC38A1 SLC39A11 SLC39A12 SLC44A2 SLC44A3 SLC46A1 SLC4A4 SLC7A10 SLC7A11 SLC7A2 SLC9A3R1 SLC9A8 SLCO1C1 SLITRK2 SMO SMOX SNTA1 SON SORBS1 SORCS2 SOX2 SOX21 SOX5 SOX6 SOX9 SOX9-AS1 SPARC SPARCL1 SPON1 SRGAP3 SRI SRPX SSPN STK33 STON2 STOX1 STRIP2 SUGCT SUOX SYCP2 SYNE1 SYPL2 SYTL4 TCF7L2 TCTN1 TET1 TFAP2C TGFBR3 THBS3 THSD1 TKT TLCD1 TM9SF4 TMED8 TMEM132A TMEM136 TMEM150C TMEM164 TMEM220 TMEM229A TMEM241 TMEM47 TMEM56 TMEM72 TMEM9 TNC TNIK TNNT1 TNS3 TOB1 TOM1L2 TOX TP53BP2 TPCN1 TPD52L1 TPP1 TRAF3IP2 TRIL TRIM66 TRIM8 TRPM3 TRPS1 TSC22D4 TSHZ1 TST TTC30A TTLL4 TTPA TTYH1 TUBB2B TULP3 UBAC1 UBC UG0898H09 USP40 VANGL2 VAV3 VCAN VEGFB VWA3A WDFY3-AS2 WDR17 WDR49 WDR60 WFS1 WIF1 WNT7B WWC1 WWOX XYLT2 YAP1 ZBTB20 ZBTB7C ZFAND5 ZFHX2 ZFHX4 ZFP2 ZFP36L1 ZFYVE21 ZHX3 ZIC5 ZMAT1 ZMYND12 ZNF221 ZNF404 ZNF516 ZNF521 ZNF671 ZNF680 ZNF717 ZNF81 ZNF816 ZNF827 ZNRF3 ZSWIM6 +Endo NA A2M A4GALT ABCA9 ABCB1 ABCG2 ABHD14B ABLIM3 ACE ACER2 ACKR1 ACTA2 ACTG2 ACTN1 ACTN4 ACVR1 ACVRL1 ADAMTS8 ADAMTS9 ADAR ADCY4 ADD1 ADGRF5 ADIPOR2 ADIRF ADM ADPRM AFAP1L1 AGRN AGTRAP AHNAK AIF1L AKAP12 AKR1E2 ALPL ALS2CL ANGPT2 ANKS1A ANO2 ANP32B ANTXR2 ANXA1 ANXA2 ANXA3 ANXA5 APH1A APOL1 APOL3 APOL4 APOLD1 ARAP3 ARFGEF2 ARHGAP10 ARHGAP29 ARHGAP42 ARHGEF15 ARHGEF17 ARL13B ARL15 ARPC1B ARRDC2 ASAP1-IT2 ASS1 ATAD2 ATP10A ATP7B ATP8B1 ATP8B5P AXIN2 B2M B3GNT2 BACE2 BAMBI BATF2 BCL2L10 BCL6B BCL7B BGN BHLHE40 BIRC3 BLOC1S3 BMP2 BMP6 BMPR2 BRD2 BSG BST2 BTBD6 BTG2 BTN3A3 BTNL9 C12orf57 C1R C2CD2 C2CD4B C7 CA4 CA5B CALD1 CAP1 CAPN12 CAPNS1 CARD6 CAV1 CAV2 CAVIN1 CAVIN2 CBFA2T3 CCDC141 CCDC3 CCDC68 CCDC88C CCL19 CCM2L CCNL1 CCNY CD151 CD248 CD320 CD34 CD44 CD46 CD59 CD63 CDA CDC37 CDH6 CDYL2 CEBPD CEMIP CENPP CEP89 CES1 CFH CFL1 CFLAR CGNL1 CHST12 CKMT2 CLDN5 CLEC14A CLIC5 CMAHP CMPK2 CMTM8 CNKSR3 CNN2 CNOT6L CNTLN COBLL1 COL1A2 COL24A1 COL27A1 COL4A1 COL4A2 COL6A2 COLEC12 COX4I2 COX7A1 CPAMD8 CPD CRIM1 CRIP2 CSDE1 CSNK1G3 CSRNP1 CSRP2 CTBS CTGF CTNNB1 CTR9 CTSV CX3CL1 CXCL12 CXCL2 CYB5R3 CYP1B1 CYR61 CYYR1 DAB2IP DACH1 DACT2 DANCR DCBLD1 DCN DDIT3 DDN DDX11 DDX47 DDX51 DEAF1 DEGS2 DEK DENND2C DIO3 DIO3OS DLC1 DMBT1 DOCK9 DSP DSTN DUSP1 DUSP11 DYRK3 EBF1 ECE1 ECM1 ECM2 ECSCR EDN1 EDN3 EDNRA EEF1A1 EEF1D EEF2 EEFSEC EFNA1 EGFL7 EHD1 EHD2 EIF1 EIF2AK2 EIF3A EIF3I EIF4G2 ELOVL7 EMCN EML1 EMP1 EMP2 ENG EOGT EPAS1 EPB41L4A EPSTI1 ERG ERRFI1 ESAM ESM1 ESYT2 ETS1 ETS2 EVA1C FAM122C FAM129B FAM162B FAM213A FAM89A FBLN5 FBXO25 FES FGD5 FHL2 FHL3 FHL5 FKBP1A FLI1 FLNA FLNB FLT1 FLT4 FMO2 FMOD FN1 FOSB FOSL2 FOXC1 FOXC2 FOXF1 FOXF2 FOXL1 FOXL2 FOXP1 FOXQ1 FRMD3 FRMD6 FRZB FSTL1 FURIN FZD10 FZD6 GABRE GADD45B GALNT15 GALNT18 GATAD2A GBP4 GCNT1 GGT1 GGT5 GIMAP6 GIMAP7 GJA4 GJC1 GNAI2 GNG11 GPCPD1 GPER1 GPIHBP1 GPR108 GPR4 GPR85 GPX1 GPX3 GRB10 GRP GSK3A GSTO2 GSTP1 GUK1 H2AFZ HBB HEBP2 HEG1 HELZ2 HERC2 HERC2P2 HERC2P9 HERPUD1 HES4 HEXIM1 HIGD1B HIST1H1D HIST1H2BC HLA-A HLA-B HLA-C HLA-E HLA-F HMGB1 HPCAL1 HPGD HRC HSF1 HSP90AA1 HSP90B1 HSPA12B HTR1F HYAL2 ICAM2 ID1 ID3 IER2 IFI27 IFI35 IFI44 IFI44L IFI6 IFIH1 IFITM1 IFITM2 IFITM3 IFNGR1 IGF1R IGFBP3 IGFBP7 IGSF9 IL15RA IL32 IMPDH1 ING1 INSR INTS12 IQGAP1 ISG15 ISLR ISM1 ISYNA1 ITGA1 ITGA11 ITGA6 ITGB1 ITIH5 ITM2A ITM2B ITPR3 JAG2 JUN JUNB JUND KANK2 KANK3 KCNE4 KCTD12 KDR KIAA0355 KIF25 KIF5B KLF11 KLF2 KLF4 KLF6 KLF9 KRTCAP3 LAMA2 LAMA3 LAMA4 LAMA5 LAMB2 LAMC1 LAPTM4A LDLR LEF1 LEPR LGALS1 LGALS3 LIMS2 LIN9 LMCD1 LMNA LMO2 LNX2 LRRC17 LRRC32 LRRC70 LSMEM1 LSR LXN LY6E LZTS1 LZTS2 MANBAL MAST2 MATN3 MECOM MEGF6 MFAP4 MFSD2A MGLL MGP MIR22HG MLIP MLKL MMRN2 MRGPRF MRPL1 MRPS24 MSX1 MT1A MT1E MT1F MT1L MT1M MT1X MVP MX1 MX2 MXRA7 MYADM MYCT1 MYH11 MYH9 MYL12A MYL12B MYL6 MYL9 MYLK2 MYO1B MYO1C MYO5C MYRIP NAGS NAMPT NBEAL1 NCL NDUFA4L2 NDUFAF3 NEAT1 NEDD9 NES NET1 NEURL1B NFE2L1 NFIA NFKBIA NID2 NKD1 NKX6-1 NLRC5 NOC3L NOS3 NOSTRIN NOTCH4 NR3C2 NR4A1 NSUN6 NT5DC2 NTAN1 NUDT2 NXN NYNRIN OAZ1 OCLN OLFML2A OPA3 OPTN ORC5 OST4 P2RY14 P4HA2 PALMD PAPSS2 PARP14 PARP9 PARVB PAWR PCAT19 PCBP3 PCCA PCDH1 PCGF2 PCOLCE PDCD4 PDE4C PDK4 PEAR1 PECAM1 PERP PES1 PFN1 PHACTR2 PHF10 PHLDB2 PIBF1 PIK3C2A PKIG PLA1A PLAT PLCB4 PLEKHG1 PLEKHG2 PLOD1 PLOD3 PLXDC1 PMEPA1 PML PODXL POLR2L POLRMT POMP PPARD PPFIBP1 PPP1R10 PPP1R15A PRELP PROCR PROSER2 PRRX1 PRSS23 PRX PSMB8 PSMB9 PSMC3 PSME1 PSME2 PTEN PTGES PTH1R PTMS PTPN14 PTPRB PTPRG PTPRK PTPRM PTTG1IP PXDC1 PXN PYGO2 QRFPR RAB13 RAB37 RAC1 RAI2 RALB RAMP2 RAMP3 RARRES2 RASIP1 RASL12 RBCK1 RBM17 RBM43 RBMS2 RBMS3 RBPMS RBPMS2 RCSD1 RELA RERGL RGCC RGS5 RHOA RHOB RHOBTB1 RHOC RND3 RNF152 ROBO4 RPL11 RPL13A RPL18 RPL19 RPL23 RPL27A RPL28 RPL3 RPL34 RPL35 RPL35A RPL36 RPL37A RPL38 RPL4 RPL41 RPL8 RPLP1 RPS11 RPS12 RPS16 RPS20 RPS21 RPS23 RPS27A RPS28 RPS29 RPS3 RPS4X RPS5 RPS6 RPS8 RPS9 RRAS RSAD2 RSU1 RUNDC3B RUVBL2 S100A10 S100A16 S100A6 S1PR1 SAV1 SCARB1 SCN4A SDCBP SEC14L1 SEMA3G SERF2 SERPINB6 SERPING1 SERPINH1 SERTAD1 SFTA1P SGPP2 SH2D3C SHANK3 SHC2 SHISA5 SIK2 SKAP1 SLC10A3 SLC12A7 SLC16A1 SLC16A13 SLC16A2 SLC16A6 SLC19A1 SLC19A3 SLC20A2 SLC25A39 SLC2A1 SLC2A3 SLC30A1 SLC35A4 SLC38A11 SLC38A3 SLC38A5 SLC39A10 SLC39A13 SLC39A8 SLC3A2 SLC4A2 SLC52A3 SLC5A6 SLC6A12 SLC6A13 SLC6A6 SLC7A1 SLC7A5 SLC9A1 SLC9A3R2 SLCO2A1 SLCO2B1 SLCO4A1 SLFN11 SLFN12 SLFN5 SMIM10 SMIM3 SMOC2 SNAI1 SNAI2 SNED1 SNHG5 SNHG8 SNRK SNTB1 SNX33 SOCS2 SORBS2 SOS1 SOX13 SOX17 SOX18 SOX7 SPARC SPARCL1 SPINK8 SPSB2 SPTBN1 SRGN ST6GAL1 ST6GALNAC1 ST6GALNAC3 STARD8 STAT3 STC2 STOM STRA6 STX10 SUSD2 SUV39H1 SWAP70 SYDE1 SYNE2 SYNPO SYNPO2 SYT15 TACC1 TAF13 TAGLN TAGLN2 TAP1 TBC1D4 TBPL1 TBX2 TBX3 TCF7L1 TCN2 TES TESC TESK1 TFPI TFRC TGFBR2 TGM2 THAP3 THBS1 THSD4 TIE1 TIMP1 TIMP3 TIPARP TJP1 TLN1 TM4SF1 TM4SF18 TMEM179B TMEM204 TMEM45B TMOD3 TMSB10 TNFAIP1 TNFSF10 TNIP1 TNS1 TNS2 TNXB TOPORS TPI1 TPM1 TPM2 TPM3 TPM4 TPT1 TRAM2 TRAPPC2B TRIM28 TRIM56 TRIP10 TSC22D1 TSC22D3 TSKU TSPAN14 TSPAN9 TTLL1 TTN TUBB TUBB4B TUBD1 TUBG1 TWIST1 TXLNA TXNIP UACA UBE2L6 UBE2S ULBP2 USHBP1 UTRN VAMP5 VANGL1 VAT1 VCL VGLL3 VIM VIT VWF WARS WIPI1 WNT11 WWTR1 XAF1 YBX3 YES1 ZBTB10 ZBTB38 ZCCHC14 ZEB1 ZFP36 ZIC1 ZIC3 ZIC4 ZMYM1 ZNF257 ZNF274 ZNF366 ZNF394 ZNF407 ZNF442 ZNF823 +Microglia NA AAED1 ABL2 ABR ACSL1 ACTB ACTR2 ACY3 ADAM17 ADAM28 ADAM9 ADAP2 ADPGK AIF1 AKAP13 AKR1A1 ALOX15B ALOX5 ALOX5AP AMZ2P1 ANKRD44 ANXA5 AOAH APAF1 APBB1IP AREL1 ARHGAP22 ARHGAP24 ARHGAP25 ARHGAP9 ARHGDIB ARID3B ARID5A ARL5A ARPC1B ARPC2 ARPC3 ARRB2 ARRDC3 ASH1L ATF6 ATF7IP2 ATM ATP13A3 ATP6V0E1 ATP6V1B2 B2M B3GNT5 B3GNTL1 B4GALT1 BACH1 BATF3 BCAR3 BCAS2 BCL2A1 BHLHE41 BLNK BMS1P4 BRAP C1QA C1QB C1QC C3 C3AR1 C5AR2 CAP1 CAPG CAPNS2 CAPZA1 CAPZB CARS2 CASP1 CCL2 CCL22 CCR1 CCR5 CD14 CD163 CD164 CD226 CD274 CD276 CD300C CD300LB CD33 CD37 CD4 CD53 CD74 CD83 CD84 CD86 CDC42EP3 CDC42SE1 CDV3 CEP170 CH25H CHCHD7 CHD1 CHD2 CHD9 CHST11 CHST14 CHSY1 CITED2 CLEC4A CLEC9A CLINT1 CLPB CMTM6 CMTM7 CNOT1 CNOT6 CNPY3 COL8A2 CORO1A COTL1 CPVL CREB3 CREG1 CSF1R CSF2RA CSF3R CSNK2A2 CTSB CTSC CTSL CTSS CTTNBP2NL CX3CR1 CXCL16 CXCR4 CYB561A3 CYBB CYFIP1 CYP2R1 CYTH4 CYTL1 DAGLB DCTD DDX21 DDX39A DEF6 DENND1C DENND3 DGKA DHRS9 DIAPH2 DIP2B DKC1 DNAH1 DNAJC10 DNAJC2 DNMBP DOCK10 DOCK11 DOCK4 DOCK8 DR1 DUSP2 DUSP6 E2F3 EBI3 EDEM1 EEPD1 EGR2 EGR3 EIF2AK3 EIF3L EIF3M EIF4A3 EIF4E ELF1 ELF4 ELL2 ELMO1 EMB EML4 ENPP1 EPB41L2 ESCO1 ETF1 ETS2 EVI2B EVL F13A1 FAM105A FAM135A FAM149A FAM46A FAM49B FAM91A1 FCER1G FCGBP FCGR1B FCGR2A FCGR3A FCGRT FCHSD2 FGD2 FGD4 FGL2 FHOD1 FMN1 FMNL1 FOLR2 FPR1 FRMD4A FUT4 FYB1 G0S2 GABPB1 GAL3ST4 GBP2 GGA3 GGTA1P GHRLOS GLIPR1 GM2A GMEB1 GMFG GNA13 GNAI3 GNB4 GNL2 GNLY GPR132 GPR183 GPR34 GPX1 GRB2 GRID2 GRN GTF2E2 GTPBP4 GYPC H2AFY HAMP HAUS8 HAVCR2 HCCS HCK HCLS1 HCST HENMT1 HEXB HIF1A HIVEP3 HK2 HLA-DMA HLA-DMB HLA-DPA1 HLA-DPB1 HLA-DRA HLA-DRB1 HLA-E HPGDS HPS3 HS3ST1 HS3ST4 HS6ST1 IFI16 IFNGR2 IGSF6 IL10RA IL13RA1 IL1B IL1RAP IL4R IL6R IL6ST INHBA INPP5D IPCEF1 IRAK2 IRF5 ISG20L2 ITGAM ITGAX ITGB2 ITM2B ITPR2 JDP2 KBTBD8 KCNMB1 KCNQ3 KCTD12 KDM7A KYNU LAPTM5 LAT2 LCP1 LCP2 LDLRAD4 LGMN LHFPL2 LILRB4 LIMS1 LINC-PINT LINC00484 LINC01480 LPAR5 LPAR6 LPCAT2 LPL LPXN LRRFIP1 LRRK1 LST1 LUZP1 LY86 LY96 LYN LYPLA1 LYST M6PR MAF1 MAFB MALT1 MAML2 MAML3 MAN1A1 MAP2K3 MAP4K4 MAPKAPK2 MASTL MBD4 MBNL1 MCM9 MDM2 MED12L MEF2A MEF2C METAP1 MFSD1 MGAT1 MICAL1 MILR1 MIS18BP1 MKNK1 MLXIPL MNDA MOB1A MOB3A MPEG1 MPP1 MR1 MRC1 MS4A4A MS4A7 MTHFD1L MTHFD2 MYBPC3 MYC MYO1F MYO7A MYO9B NAA15 NAA20 NAB2 NABP1 NAV3 NCF4 NCOA3 NCOA4 NEAT1 NEDD9 NFAM1 NKX3-1 NLRP3 NPC2 NPL NR4A2 NRBF2 NRROS NUFIP2 NUP54 OGFRL1 OLR1 OR2B11 OS9 OTUD1 P2RX4 P2RY12 P2RY13 P4HA1 PABPC1 PAG1 PARN PARP4 PBDC1 PCM1 PDE3B PDGFB PDK4 PDPN PELI1 PGM2 PICALM PIK3AP1 PIK3R5 PILRA PKN2 PLAU PLAUR PLBD1 PLCB2 PLD4 PLEKHO1 PLIN2 PLVAP PLXDC2 POPDC2 POU2F2 PPARG PPIG PRKAB1 PRPF38B PRR13 PRRC2C PSMA1 PTAFR PTGER4 PTPRC PTPRE PYCARD QKI RAB32 RAB39A RAB7B RANBP2 RAP2B RAPGEF2 RASAL2 RASGEF1B RASGEF1C RASSF5 RBM25 RC3H1 RCBTB2 RCOR1 REL RGS1 RGS10 RGS18 RHBDF2 RHOG RILPL2 RIN2 RIN3 RNASE6 RNASET2 RNF122 RNF144B RNF149 RNF20 RNF213 RNPEP RPA2 RPS2 RPS6KA1 RRM2B RTTN RUNX2 S100A11 SAT1 SCAMP2 SCIN SDCBP SEC24C SELPLG SERPINA1 SERPINB9 SERPINB9P1 SERPINF1 SFMBT2 SGK1 SGPP1 SH2B3 SIGLEC14 SIPA1L2 SIRPB1 SKAP2 SLA SLC12A6 SLC15A4 SLC16A3 SLC1A5 SLC25A37 SLC26A2 SLC2A5 SLC35A3 SLC43A2 SLC50A1 SLC7A7 SLC9A9 SLCO2B1 SMAD3 SMAP2 SNX29 SNX9 SOAT1 SOCS6 SORL1 SP100 SP140 SP140L SP3 SPATA13 SPHK1 SPI1 SPIDR SPN SPP1 SPRED1 SPTLC2 SRGAP1 SRGAP2 SRGAP2B SRGN SRRM2 ST6GAL1 ST6GALNAC3 ST8SIA4 STAB1 STAMBPL1 STK10 STK17B STK38L STK4 SUSD3 SUSD6 SWAP70 SYAP1 SYK SYNDIG1 SYNE4 SYNPO2L SYTL3 TAB3 TAL1 TBC1D14 TBC1D22A TBXAS1 TCF12 TCOF1 TET2 TFEC TGFBI TGFBR1 THEMIS2 TLN2 TLR1 TLR2 TLR3 TLR4 TLR6 TM6SF1 TMC8 TMED5 TMEM106A TNF TNFAIP8L3 TNFRSF11A TNFRSF12A TNFRSF13C TPD52L2 TPM3P9 TRA2B TRAF6 TREM2 TREML1 TRIB1 TSPYL5 TSR1 TXLNB TYROBP UBAC2 UBE2E2 UBXN11 UCP2 UGCG USP15 USP53 USP6 UTP14A VAMP8 VASH1 VAV1 VHL VMO1 VMP1 VSIG4 WASF2 WDFY4 WDR1 WDR91 XAF1 XIRP1 YIPF1 ZBTB1 ZBTB21 ZCCHC6 ZCCHC8 ZFP36L2 ZMYND15 ZNF143 ZNF217 ZNF267 ZNF3 ZNF490 ZNF655 ZNF700 ZNF805 ZNRF2 ZSWIM6 +Neuro_Exc NA ABCC8 ABI2 ABLIM2 ABR ACSL3 ACTB ACTG1 ACTN1 ACTR2 ADAM23 ADAMTS19 ADCY1 ADCY2 ADD2 ADGRB3 ADGRL2 AEBP2 AES AFF3 AGBL4 AHI1 AIG1 AK5 AKAP11 ALCAM ALDOA ALOX12P2 AMPH ANKRD17 ANKRD20A5P ANKRD36B ANKS1B ANO3 ANO5 APBA2 APBB1 APLP1 APLP2 APP ARAP2 ARF1 ARHGAP10 ARHGAP21 ARHGAP26 ARHGAP32 ARHGAP44 ARHGEF7 ARID1B ARL15 ARL4C ARL6IP5 ARNT2 ARNTL2 ARPP19 ARPP21 ASAP1 ASIC2 ASTN2 ATCAY ATL1 ATP1A1 ATP1B1 ATP1B3 ATP2A2 ATP2B1 ATP2B2 ATP2C1 ATP6AP1 ATP6AP2 ATP6V0A1 ATP6V0B ATP6V1A ATP6V1B2 ATP6V1E1 ATP8A2 ATP8B1 ATP9A ATRNL1 ATXN1 ATXN7L3B AUTS2 B4GAT1 BAALC BACH2 BAIAP2 BASP1 BCL11A BCL11B BDP1 BEX1 BEX2 BEX4 BICC1 BICD1 BLCAP BMPER BNIP3 BRAF BRINP1 BRINP2 BRINP3 BSN BTBD9 C11orf80 C11orf87 C16orf45 C1orf115 C8orf34 CA10 CA11 CABP1 CACNA1A CACNA1B CACNA1C CACNA1E CACNA2D1 CACNA2D3 CACNB4 CACNG3 CACNG8 CADM3 CADPS CADPS2 CALM1 CALM3 CAMK1D CAMK2A CAMK2B CAMK2D CAMK2G CAMK2N1 CAMKK1 CAMKK2 CAMKV CAMTA1 CAP2 CBLN2 CCDC136 CCDC3 CCDC30 CCK CCNI CCSER1 CDC14B CDH10 CDH12 CDH13 CDH2 CDH20 CDH22 CDH8 CDH9 CDK14 CDK5R1 CDKL5 CELF2 CELF4 CELF5 CEMIP CEND1 CEP112 CEP126 CERS6 CFL1 CHD5 CHGA CHGB CHL1 CHN1 CHRM2 CHRM3 CHSY3 CIT CKB CKMT1B CLCN4 CLEC16A CLMN CLSTN1 CLSTN2 CLSTN3 CLTA CLTC CLU CNKSR2 CNRIP1 CNTN3 CNTN4 CNTN5 CNTNAP1 CNTNAP2 CNTNAP5 COL11A1 COL24A1 COL5A2 CORO6 COX4I1 COX5B COX6C COX7C CPE CPLX1 CPLX2 CPNE4 CPNE5 CREG2 CRYM CSGALNACT1 CSMD1 CSMD3 CSRNP3 CTDSPL CTNNA2 CTNNAL1 CTNNB1 CTSB CTTNBP2 CUX1 CUX2 CYP46A1 CYTH1 DAB1 DACH1 DAPK1 DCAF6 DCC DCLK1 DCLK2 DDX24 DGCR5 DGKB DGKG DGKH DGKI DGKZ DIAPH2 DIP2A DIRAS2 DKK3 DLC1 DLG2 DLGAP1 DLGAP1-AS4 DLGAP2 DLGAP4 DMD DMTN DNAJA1 DNAJC6 DNM1 DOCK4 DOK6 DPP10 DPY19L1 DPY19L2P1 DPYSL2 DSCAM DSCAML1 DSTN DYNC1H1 DYNC1I1 DYNC2H1 DYNLL1 DYNLL2 DZIP3 EEF1A2 EFNA5 EFR3A EGFEM1P EGR1 EID1 EIF1 EIF4A2 EIF4G2 ELAVL2 ELAVL4 ELL2 ELMOD1 EML6 ENC1 ENO1 ENO2 ENOX1 ENSA EPB41L1 EPB41L2 EPB41L3 EPHA3 EPHA4 EPHA5 EPHA6 EPHB6 ERC2 ETS2 ETV5 EVL EXOC4 EXOC6 EXT1 EXTL2 EYA4 FAIM2 FAM13A FAM13B FAM155A FAM168B FAM189A1 FAM19A1 FAM19A2 FAM217B FAM49A FAM81A FARP1 FARS2 FAT3 FBXL16 FBXL2 FBXW7 FEZ1 FGF12 FGFR1 FHL1 FHOD3 FLRT2 FMN1 FMN2 FOCAD FOXP1 FOXP2 FRAS1 FRMD4A FRMPD4 FRRS1L FRY FSTL4 FTH1 FUT9 FZD3 G3BP2 GABARAPL1 GABARAPL2 GABBR2 GABRA1 GABRA2 GABRB1 GABRB2 GABRB3 GABRD GABRG2 GABRG3 GALNT14 GALNT18 GAP43 GAPDH GARNL3 GAS7 GCC2 GDA GDAP1 GDI1 GFOD1 GHITM GHR GLCCI1 GLIS3 GLRB GLS GNAL GNAO1 GNAS GNB1 GNB5 GNG2 GNG7 GNPTAB GOLGA8A GOT1 GPC1 GPC6 GPR158 GRAMD1B GRIA1 GRIA2 GRIA3 GRIA4 GRIK3 GRIK4 GRIN1 GRIN2A GRIN2B GRIN3A GRINA GRIP1 GRM3 GRM5 GRM7 GRM8 GSG1L GUCY1A2 GUK1 GULP1 HCN1 HDAC9 HECW1 HERC1 HINT1 HIVEP2 HIVEP3 HLF HNRNPA2B1 HNRNPDL HNRNPK HOMER1 HPCAL1 HPSE2 HS3ST2 HS3ST4 HS3ST5 HS6ST2 HS6ST3 HSP90AA1 HSP90AB1 HSP90B1 HSPA12A HSPA8 HSPH1 HTR1E HTR2A HTR2C ICA1L IDS IL1RAPL2 ILDR2 INA INPP4B INPP5F IPCEF1 IQSEC1 ITGA8 ITGB8 ITM2B ITM2C ITPK1 ITPR1 ITPR2 KALRN KCNA2 KCNAB2 KCNB1 KCNB2 KCNC2 KCND3 KCNH1 KCNH3 KCNH5 KCNH7 KCNH8 KCNIP1 KCNIP4 KCNJ6 KCNMA1 KCNMB4 KCNQ2 KCNQ3 KCNQ5 KCNT1 KCNT2 KCTD1 KCTD16 KCTD8 KHDRBS2 KHDRBS3 KIAA0319 KIAA0513 KIAA0930 KIAA1107 KIAA1109 KIAA1211L KIAA1217 KIAA1549L KIF1A KIF21A KIF3A KIF3C KIF5A KIF5C KIFAP3 KIFC2 KIRREL3 KLC1 KLHL32 KLHL5 KSR2 LAMA2 LAMA4 LARP1B LDB2 LDHB LHFPL3 LIN7A LINC-PINT LINC00507 LINC00599 LINC00632 LINGO1 LINGO2 LMO3 LMO4 LMO7 LMTK2 LONRF2 LPCAT4 LRFN2 LRFN5 LRP1B LRRC28 LRRC4C LRRC7 LRRC8B LRRFIP1 LRRK1 LRRK2 LRRN2 LRRTM3 LRRTM4 LSAMP LUZP2 LY86-AS1 MACROD2 MAGI1 MAGI2 MAGI3 MAN1A1 MAN1A2 MAP1A MAP1B MAP1LC3A MAP2 MAP2K1 MAP3K13 MAP3K5 MAP7D2 MAP9 MAPK1 MAPK10 MAPK4 MAPK9 MAPRE2 MARK1 MAST3 MAST4 MBOAT2 MCF2L2 MCHR2 MCTP1 MDGA2 MDH1 MED12L MED13L MEF2A MEF2C MEG3 MEG8 MEIS2 MFSD6 MGAT4C MGAT5 MGLL MGST3 MIAT MICAL2 MICU1 MIPOL1 MIR124-2HG MKL2 MLIP MLLT3 MMP16 MNAT1 MOAP1 MORF4L1 MORF4L2 MPHOSPH8 MPP6 MPRIP MT3 MTCH1 MTURN MTUS2 MYH10 MYO16 MYO5A MYRIP MYT1L NAP1L1 NAP1L2 NAP1L3 NAPB NAPEPLD NAT8L NAV3 NBEA NCALD NCAM2 NCDN NCEH1 NCKAP1 NDFIP1 NDFIP2 NDRG4 NDST3 NDUFA1 NDUFA10 NDUFA4 NDUFB2 NDUFS1 NDUFS2 NDUFV1 NECAB1 NEDD4L NEFL NEFM NEGR1 NEK10 NELL1 NELL2 NETO1 NFAT5 NFIB NFIX NGEF NIN NIPAL2 NISCH NKAIN2 NLGN1 NLGN4Y NLK NOL4 NPAS2 NPTN NPTX1 NPTXR NR2F1 NR2F1-AS1 NR3C1 NR3C2 NR4A2 NRCAM NREP NRG1 NRG3 NRGN NRN1 NRSN1 NRXN1 NSF NTNG1 NTNG2 NTRK2 NTRK3 NUAK1 NUCKS1 NUDCD3 NWD2 NYAP2 OCIAD1 OIP5-AS1 OLFM1 OLFM3 OPCML OPTN OSBP2 OSBPL3 OSBPL6 OXR1 PACRG PACSIN1 PAFAH1B1 PAK1 PAK3 PAM PARM1 PART1 PBX1 PCDH10 PCDH11X PCDH11Y PCDH17 PCDH7 PCDH9 PCLO PCMT1 PCP4 PCSK1 PCSK2 PDE10A PDE1A PDE1C PDE2A PDE3A PDE4D PDE7B PDE8B PDP1 PDS5B PDZD2 PDZRN3 PDZRN4 PEA15 PEBP1 PEX5L PFDN5 PGK1 PGM2L1 PHACTR1 PHACTR2 PHYHIP PI4KA PID1 PIK3R1 PJA2 PKD1 PKM PKNOX2 PLAGL1 PLCB1 PLCH1 PLCL2 PLCXD3 PLD3 PLD5 PLEKHA1 PLEKHA5 PLEKHA6 PLEKHB2 PLEKHH2 PLXNA2 PLXNA4 PNMA2 POU6F2 PPA2 PPFIA2 PPFIBP1 PPIA PPM1E PPM1L PPP2R1A PPP2R2C PPP2R5C PPP3CA PPP3CB PRDM2 PREPL PRICKLE1 PRICKLE2 PRKAG2 PRKAR1A PRKAR1B PRKAR2B PRKCB PRKCE PRKD1 PRKG1 PRMT8 PRNP PRR16 PRRC2B PSAP PTCHD4 PTEN PTK2B PTPN13 PTPN5 PTPRD PTPRG PTPRK PTPRN PTPRN2 PTPRO PTPRR PTPRT PWAR6 R3HDM1 RAB11FIP4 RAB2A RAB3A RAB3B RAB6B RABGAP1 RAC1 RAD9A RALGPS2 RALYL RANBP17 RANGAP1 RAP1GAP RAP1GAP2 RAP1GDS1 RAPGEF2 RAPGEF4 RAPGEF5 RARB RASA2 RASAL2 RASGEF1C RASGRF1 RASGRF2 RASGRP1 RBFOX1 RBFOX2 RBM5 RBMS1 RCAN2 REEP2 REEP5 RFTN1 RFX3 RGS12 RGS4 RGS6 RGS7 RHBDD2 RHOBTB2 RIMS2 RIMS3 RIT2 RNF11 RNF144A RNF145 RNF157 RNF187 ROBO2 ROBO3 ROCK2 RORA RORB RPH3A RPL13 RPL13A RPL15 RPL21 RPL23 RPL27 RPL3 RPL31 RPL32 RPL34 RPL35 RPL37 RPL37A RPL38 RPLP1 RPS12 RPS14 RPS15 RPS18 RPS19 RPS24 RPS27 RPS27A RPS28 RPS4X RPS6 RPS6KC1 RPS8 RSRP1 RTF1 RTN1 RTN3 RTN4 RUFY3 RUNDC3A RUNDC3B RXFP1 RYR2 RYR3 SAMD12 SARAF SATB1 SATB2 SCAI SCAMP5 SCG2 SCG5 SCN1A SCN1B SCN2A SCN3A SCN3B SCN8A SCRN1 SDK1 SEC62 SEMA3E SEMA5B SEMA6D SERINC1 SERINC3 SERPINE2 SERPINI1 SETBP1 SEZ6L SEZ6L2 SGCD SH3GL2 SH3RF3 SHANK2 SHC3 SHISA9 SIK2 SIPA1L1 SIRPA SKP1 SLC12A5 SLC17A7 SLC22A10 SLC22A17 SLC23A2 SLC24A2 SLC24A3 SLC25A3 SLC2A13 SLC30A3 SLC35F1 SLC35F3 SLC38A1 SLC38A11 SLC39A10 SLC39A11 SLC44A5 SLC4A10 SLC6A17 SLC6A7 SLC8A1 SLF1 SLIT1 SLIT2 SLIT3 SMARCA2 SMPD3 SNAP25 SNCA SNCB SNED1 SNHG14 SNTG1 SNU13 SOBP SOD1 SORBS1 SORBS2 SORCS1 SORCS2 SORCS3 SORL1 SOX5 SPAG16 SPARCL1 SPATS2 SPATS2L SPOCK1 SPOCK2 SPON1 SPTBN1 SPTBN4 SRGAP3 SRP14 SRRM3 SRRM4 SRSF11 SRSF5 SSBP2 SSBP3 SSX2IP ST6GALNAC5 ST8SIA1 ST8SIA3 ST8SIA5 STAU2 STMN1 STMN2 STMN3 STMN4 STOX2 STRBP STX1A STXBP1 STXBP5 STXBP5L STXBP6 SUGP2 SULT4A1 SUSD4 SV2A SV2B SYBU SYN1 SYN2 SYN3 SYNGR1 SYNJ1 SYNJ2 SYNPO2 SYNPR SYP SYT1 SYT11 SYT13 SYT16 SYT4 SYT7 SYTL2 TACC1 TAGLN3 TANC2 TARBP1 TASP1 TCEAL2 TENM2 TENM3 TENM4 TERF2IP TESC TESPA1 THEMIS THRB THSD7A THY1 TLE4 TLK1 TLL1 TLN2 TMEFF2 TMEM108 TMEM130 TMEM131 TMEM132B TMEM132D TMEM155 TMEM160 TMEM178A TMEM178B TMEM232 TMEM30A TMEM59L TMOD2 TMSB10 TMSB4X TOLLIP TOMM20 TOX TPI1 TPM1 TPPP TPST1 TRERF1 TRHDE TRIM37 TRIM44 TRIM9 TRPC3 TRPC5 TRPM2 TRPM3 TSC22D1 TSHZ2 TSHZ3 TSPAN13 TSPAN7 TSPYL1 TSPYL2 TSPYL4 TTC3 TTC31 TTC39C TTLL11 TUBA1A TUBA1B TUBA4A TUBB2A UBB UBC UBL3 UCHL1 UGGT2 UNC13A UNC13C UNC5C UNC5D UNC79 UNC80 UQCRB UQCRH USP11 USP22 USP25 UST VAV3 VGLL4 VPS13A VPS13D VPS41 VSNL1 VWC2L WASF1 WBP2 WDFY3 WDR17 WSB1 XKR4 XKR6 XYLT1 YPEL3 YWHAB YWHAE YWHAG YWHAH YWHAZ ZBTB16 ZBTB18 ZFAND5 ZFPM2 ZFYVE28 ZMAT4 ZMYND8 ZNF365 ZNF385B ZNF385D ZNF483 ZNF704 ZNF91 +Neuro_Inb NA AAK1 ABAT ABI1 ABLIM2 ABR ACSL6 ACTG1 ADAM22 ADAMTS19 ADAMTSL3 ADARB2 ADCY1 ADCY2 ADCY8 ADGRB3 ADGRL2 ADK ADRA1A AEBP2 AES AFAP1 AFF2 AFF3 AHI1 AIG1 AK5 AKAP6 ALCAM ALDOA ALK AMMECR1 AMPH ANK1 ANKH ANKRD12 ANKRD26 ANKRD36C ANKS1A ANO4 AP1S2 APBA1 APLP2 APP ARHGAP20 ARHGAP44 ARHGAP5 ARHGEF3 ARID5B ARL15 ARL4C ARL6IP1 ARNT2 ASIC2 ASTN1 ASTN2 ATCAY ATG7 ATP1A1 ATP1A3 ATP1B1 ATP6V0A1 ATP6V1A ATP6V1B2 ATP8A2 ATRNL1 ATRX AUH AUTS2 B4GALT6 BACH1 BACH2 BCL11A BCL11B BCL2 BEND6 BEX1 BEX2 BICD1 BLCAP BRINP2 BTBD11 C16orf45 C8orf34 CA8 CACNA1A CACNA1B CACNA1C CACNA1D CACNA1E CACNA2D1 CACNA2D3 CACNB2 CACNB4 CACNG2 CACNG3 CACNG8 CADM2 CADPS CADPS2 CALB1 CALB2 CALM3 CALN1 CAMK2D CAMK2N1 CAMKV CAMTA1 CANX CAP2 CBLN4 CCDC136 CCDC91 CCK CCNI CCSER1 CDC5L CDH10 CDH12 CDH13 CDH4 CDH8 CDH9 CDHR3 CDK14 CDK8 CDR2 CELF4 CELF5 CEMIP CEP112 CERS6 CHD5 CHL1 CHRM3 CHRNA7 CHST11 CHSY3 CIT CLEC16A CLIP4 CLSTN2 CLSTN3 CLTC CLVS1 CLVS2 CNR1 CNTN3 CNTN4 CNTN5 CNTN6 CNTNAP2 CNTNAP4 CNTNAP5 COG5 COL11A1 COL16A1 COL19A1 COL21A1 COL25A1 COL5A2 CORO6 COX4I1 CPLX1 CPLX2 CRH CSMD1 CSMD3 CSRNP3 CTNNA2 CTTNBP2 CUX2 CXCL14 CYFIP2 CYP46A1 DAAM1 DAB1 DAPK1 DCC DCLK1 DDX24 DENND5B DGKB DGKD DGKG DKK3 DLGAP1 DLGAP2 DLX1 DMD DNER DNM1 DOCK10 DOCK3 DOCK9 DOK5 DOK6 DOPEY1 DPP10 DPP6 DSCAM DSCAML1 DYNLL2 EDIL3 EEA1 EEPD1 EFR3B EGFEM1P EGFR ELAVL2 ELAVL3 ELAVL4 ELMOD1 EML6 ENOX1 ENTPD3 EPB41L1 EPB41L3 EPHA3 EPHA5 EPHA6 EPHB6 ERBB4 ERC2 ESRRG ETV6 EVL EXT1 EYA4 FAIM2 FAM110B FAM135B FAM168A FAM189A1 FAM19A2 FAM19A5 FAM49A FAR2 FARP1 FAT1 FBXL7 FGF12 FGF13 FGF14 FHOD3 FLRT2 FMN1 FNDC3A FOXG1 FRAS1 FREM1 FRMD4A FRMPD4 FRRS1L FRY FSTL5 FUT9 FXYD6 G3BP2 GABBR1 GABBR2 GABRA1 GABRB1 GABRB2 GABRD GABRG2 GABRG3 GAD1 GAD2 GALNT13 GALNT18 GAPDH GARNL3 GAS7 GFOD1 GIT2 GLG1 GNAL GNAS GNB1 GNG4 GOLIM4 GOT1 GPC6 GPHN GPR137C GPR155 GPR158 GRIA1 GRIA2 GRIA3 GRIA4 GRID1 GRID2 GRIK1 GRIK2 GRIK3 GRIN1 GRIN2A GRIN2B GRIN3A GRIP1 GRIP2 GRM5 GRM7 GRM8 GULP1 HCN1 HDAC9 HECTD2 HECW2 HIVEP3 HMBOX1 HOOK3 HPCAL1 HPSE2 HS3ST5 HS6ST3 HSD17B12 HSP90AA1 HSP90AB1 HSP90B1 HTR1E IDS IGF1 IGSF11 IL1RAPL1 IL1RAPL2 INPP4A INPP4B INPP5F ITFG1 ITM2B ITM2C ITPR1 ITSN1 KAZN KCNAB1 KCNAB3 KCNB2 KCNC1 KCNC2 KCND3 KCNH1 KCNH5 KCNH7 KCNIP1 KCNIP4 KCNJ3 KCNJ6 KCNMA1 KCNMB4 KCNQ1OT1 KCNQ3 KCNQ5 KCNT1 KCNT2 KCTD16 KHDRBS2 KHDRBS3 KIAA1107 KIAA1109 KIAA1211 KIAA1217 KIAA1324 KIDINS220 KIF1A KIF21A KIF26B KIF3A KIFAP3 KIRREL3 KIT KLC1 KLF12 KLF3-AS1 KLHL5 KMT2A L3MBTL4 LAMP5 LANCL1 LARP1 LHFPL3 LIMCH1 LIN7A LINC00461 LINC00599 LINC01197 LINGO2 LONRF2 LPCAT4 LRFN5 LRP1B LRP8 LRRC39 LRRC4C LRRC7 LRRC8B LRRFIP1 LRRFIP2 LRRN3 LRRTM3 LRRTM4 LSAMP LUZP1 LUZP2 MACROD2 MAF MAFB MAGED1 MAGI1 MAGI3 MAML3 MAN1A1 MAN1A2 MAP1A MAP1B MAP2 MAP3K5 MAP7D2 MAP9 MAPK4 MARK1 MAST4 MBOAT2 MCC MCTP1 MDGA2 MDH1 MEF2C MEG3 MEG8 METTL15 MGAT4C MGAT5 MGEA5 MIAT MICU1 MIR99AHG MLLT3 MMP16 MORF4L2 MPDZ MPHOSPH8 MPP6 MPPED1 MTSS1 MTUS1 MTUS2 MYCBP2 MYO16 MYRIP MYT1L NALCN NAP1L1 NAP1L3 NAPB NAV2 NBEA NCALD NCAM1 NCAM2 NCOA2 NDFIP1 NDRG4 NDST3 NDUFA4 NEAT1 NEBL NECAB2 NEDD4L NEGR1 NELL1 NETO1 NETO2 NF1 NFIB NHS NIPAL3 NKAIN3 NLGN1 NLGN4Y NMNAT2 NPAS1 NPAS2 NPAS3 NPTN NPTXR NPY NR2F1-AS1 NR2F2 NR2F2-AS1 NR3C2 NRG1 NRG3 NRIP3 NRXN1 NRXN2 NRXN3 NSF NSG2 NTN4 NTNG1 NTRK2 NTRK3 NXPH1 NXPH2 NYAP2 ODF2L OIP5-AS1 OLFM3 OPCML OSBPL1A OSBPL3 OSBPL6 OSBPL8 OXCT1 OXR1 PACRG PAIP2 PAK3 PALLD PAM PARM1 PCDH10 PCDH11X PCDH11Y PCDH15 PCDH17 PCDH7 PCLO PCP4 PCSK2 PDE1C PDE4B PDE7B PDE8B PDGFD PDS5B PDXK PDZRN3 PDZRN4 PEBP1 PEG3 PENK PEX5L PGM2L1 PHF14 PHF20L1 PHTF1 PHYHIPL PID1 PIP5K1B PITPNC1 PJA2 PKN2 PKNOX2 PKP2 PLCB1 PLCB4 PLCE1 PLCH1 PLCXD3 PLD3 PLD5 PLEKHA1 PLEKHA5 PLPPR1 PLPPR4 PLS3 PLXNA4 PNMA2 PPARGC1A PPIP5K2 PPM1E PPM1K PRELID2 PREPL PRICKLE2 PRKAR2A PRKAR2B PRKCA PRKCB PRKCE PRKD1 PRKG1 PRNP PROX1 PRR16 PTCHD4 PTPN13 PTPN4 PTPRB PTPRE PTPRG PTPRJ PTPRM PTPRN2 PTPRO PTPRS PTPRT PVALB RAB2A RAB3B RAB3C RAB3IP RAB6B RALGAPA2 RANBP17 RAPGEF4 RARB RASA1 RASAL2 RASGRF2 RASSF8 RBFOX1 RBFOX2 RBMS3 RCAN2 REEP1 REEP5 RELN REPS1 RERG REV3L RGS12 RGS6 RGS7 RGS7BP RIMBP2 RIMS2 RNF150 RNF157 RNF175 RNF180 RNF24 RNPC3 ROBO1 ROBO2 RORA RPH3A RPL34 RPL37A RPS6KA2 RPS6KA3 RTF1 RTN3 RUNDC3B RUNX1T1 RYR1 RYR2 RYR3 SAMD12 SAMD4A SARAF SAT1 SCAI SCAMP5 SCG2 SCG5 SCLT1 SCN1A SCN3A SCN8A SDK1 SEMA6D SERINC1 SERPINI1 SETBP1 SEZ6 SEZ6L SEZ6L2 SGCD SGK1 SH3GL3 SH3KBP1 SH3PXD2A SH3RF3 SHANK2 SHC3 SHISA6 SHISA8 SHISA9 SIPA1L1 SLC12A5 SLC22A17 SLC24A3 SLC25A12 SLC2A13 SLC35F1 SLC38A1 SLC44A5 SLC4A10 SLC4A8 SLC6A1 SLC6A17 SLC8A1 SLC9A9 SLCO3A1 SLIT2 SMARCA2 SMYD3 SNED1 SNHG14 SNTG1 SOBP SORBS2 SORCS1 SORCS3 SOX2-OT SOX6 SPAG16 SPARCL1 SPATS2L SPECC1 SPHKAP SPIN1 SPOCK1 SPOCK2 SPOCK3 SPTAN1 SPTBN4 SRGAP1 SRRM3 SRRM4 SSBP2 SST ST6GALNAC5 ST8SIA1 STARD13 STXBP6 SULT4A1 SUPT3H SUSD4 SV2A SV2C SYN2 SYN3 SYNPR SYP SYT1 SYT11 SYT14 SYT15 TAC1 TAC3 TAOK3 TCEAL2 TCF4 TENM1 TENM2 TENM3 TENM4 TERF2IP TFDP2 THRB THSD7A THY1 TIAM1 TIMP2 TLK1 TLN2 TMEFF2 TMEM108 TMEM130 TMEM132B TMEM132C TMEM132D TMEM178B TMEM232 TMEM59L TMSB4X TMTC1 TMTC2 TNIK TNRC6A TOX TOX2 TOX3 TPST1 TRAF3IP2-AS1 TRANK1 TRHDE TRIO TRPC3 TRPC5 TRPS1 TSC22D1 TSHZ2 TSPAN7 TSPYL2 TTBK2 TTC28 TTN TTTY14 TUBA1A TUBB2A UCHL1 UNC13C UNC5C UNC5D UPP1 USP11 USP22 VIP VSNL1 VSTM2A VWA8 VWC2 VWC2L WASF3 WIF1 WLS WNK2 WSB1 WWP1 XKR4 YWHAB ZBTB16 ZCCHC11 ZEB1 ZEB2 ZMAT4 ZNF292 ZNF385B ZNF385D ZNF483 ZNF536 ZNF608 ZYG11B +Oligo NA AATK ABCA2 ABCA8 ABCG1 ABHD17B ABHD6 ACER3 ACTL6A ACVR1C ADCY5 ADIPOR2 ADSS AFG3L1P AFMID AGA AGAP1 AGPAT4 AGPAT4-IT1 AGTPBP1 AHR AIF1L AK5 AKAP9 AKTIP ALAD ALCAM AMD1 AMER2 AMPD3 ANAPC5 ANGPTL2 ANK3 ANKIB1 ANKRD12 ANKRD18A ANKRD28 ANKRD36C ANKRD40 ANKRD65 ANKS1B ANKS6 ANLN ANO4 ANP32C APBA3 APBB1 APBB2 APIP APLP1 APOD APP ARAP2 ARHGAP21 ARHGEF37 ARMC1 ASB13 ASPA ATE1 ATG3 ATG4C ATP10B ATP8A1 AUTS2 AZGP1 B3GNT7 BACE1 BAZ2B BBX BCAS1 BCHE BEST1 BEST3 BMP8B BNIP3L BOD1L1 BOK BRCA1 BTBD16 BTBD3 BVES C10orf90 C1GALT1 CA10 CA14 CA2 CACNA2D1 CACNG4 CALD1 CAPN13 CAPN3 CARNS1 CASP8AP2 CBR1 CCDC121 CCDC160 CCDC25 CCDC88A CCNE2 CCP110 CD22 CD2BP2 CD9 CDC42BPA CDC42EP1 CDC42EP2 CDC42SE2 CDH1 CDH19 CDH20 CDK17 CDK18 CDK19 CDR2L CENPB CEP97 CERCAM CFAP20 CFL2 CHADL CHCHD4 CHD1L CHN2 CHST6 CLASP2 CLCA4 CLCN3 CLCN4 CLDN11 CLDND1 CLIP2 CLK1 CLMN CMTM5 CNDP1 CNP CNTN2 CNTNAP4 COBL COL16A1 COL4A5 COL8A1 COL9A1 COL9A2 COL9A3 COLGALT2 COMMD3 CPNE2 CPOX CPPED1 CRADD CREB5 CRYAB CSE1L CSRP1 CTNNA3 CUEDC1 CUTC CYB5R2 DAAM2 DDX17 DHCR24 DICER1 DIMT1 DIP2B DIXDC1 DLC1 DLG1 DLG2 DLL1 DMRT2 DNAJB2 DNAJC21 DNAJC22 DNAJC6 DNM3 DOCK10 DOCK5 DPF2 DPYD DPYSL2 DSCAML1 DST DTD2 DTNB DUSP10 DUSP16 DUSP7 DYNC1I2 DYNC1LI2 DYSF EBAG9 ECHDC1 EDIL3 EFS ELMO1 ELOVL1 ELP5 EMC3-AS1 ENDOD1 ENOPH1 ENOSF1 ENOX2 ENPP2 ENPP4 ENPP6 EPN2 ERBB3 ERMN ERMP1 EVI2A EXOC5 EXOC6B FA2H FAF1 FAM107B FAM122B FAM124A FAM126A FAM131B FAM13C FAM177A1 FAM192A FAM218A FAM219A FAM221A FAM222A FAM229B FAM69A FAM84B FANCB FANCL FAR1 FBXL5 FBXL7 FBXO32 FBXO7 FCHO1 FEZ1 FGF1 FHIT FIS1 FKBP7 FLNC FMNL2 FNBP1 FOLH1 FOLH1B FOXN2 FOXO4 FRK FRMD4B FRMD5 FRYL FUT8 FXR1 GAB1 GAB2 GALNT5 GALNT6 GALR1 GAS7 GCA GDE1 GDNF GJB1 GJC2 GLTP GNAI1 GNAZ GOLGA4 GOLGA7 GPD1 GPM6B GPR17 GPR37 GPR62 GPRC5B GPSM2 GREB1L GRHPR GRM3 GSKIP GSN GZF1 HAGLR HAPLN2 HAUS2 HBS1L HDAC11 HEBP1 HECW2 HHIP HHIP-AS1 HIP1 HIPK2 HIST1H2AC HNRNPA2B1 HPN HS3ST5 HSD11B1 HSD17B3 HSD17B4 HSP90AA1 HSPA2 HTATIP2 ICK IGSF8 IKZF2 IKZF5 IL1RAPL1 INPP1 INSL3 IP6K3 IPO13 ITGA2 ITGAE ITGB8 JAM3 KAT2B KATNAL1 KBTBD2 KCNH8 KCNJ2 KCNK10 KCNMB4 KCTD4 KIAA1324L KIF13A KIF13B KIF1B KIF1C KIF2A KIF6 KIRREL3 KIZ KLHL2 KLHL32 KLHL4 KLK6 KLRC2 KLRC3 KMT2E KNOP1 LACC1 LACTB2 LAMP2 LANCL1 LARP6 LAYN LDB3 LDLRAD4 LDLRAP1 LGI3 LGR5 LHFPL3 LHPP LIMCH1 LIN54 LINC00320 LINC00844 LINC00909 LINC01105 LPAR1 LPGAT1 LRP2 LRP6 LRRC63 LRRC8D LTN1 MAG MAL MAN2A1 MAP4K4 MAP4K5 MAP6D1 MAP7 MAP7D1 MAPK8IP1 MARCKSL1 MATN2 MBNL2 MBP MCM7 MEGF11 MEX3A MEX3C MGA MIB1 MIF4GD MIPEP MMACHC MND1 MOB3B MOBP MOG MOSPD2 MRPL52 MTF1 MTFR1 MTMR2 MTRR MTURN MTUS1 MUSK MVB12B MXI1 MYO1D MYO6 MYOT MYRF NAALADL2 NACAD NAP1L6 NAPEPLD NBR1 NCAM2 NCAPD2 NCKAP5 NDE1 NDRG1 NDUFS7 NEAT1 NEK3 NEK7 NENF NFASC NFYA NFYB NIFK-AS1 NINJ2 NIPA1 NIPAL3 NKAIN1 NKAIN2 NKTR NKX2-2 NKX6-2 NLK NPAS3 NPC1 NR0B1 NSDHL NT5DC1 NUCKS1 NUDT16 NXPE3 OLIG1 OLIG2 OMG OPALIN OR2L13 OSBPL1A OTUD6B OTUD7B PAIP2B PALB2 PALM2 PAPSS1 PAQR6 PAXBP1 PAXBP1-AS1 PCBP4 PCDH15 PCDH9 PCGF6 PCNA PCSK6 PDE1A PDE1C PDE4B PDE6B PDE8A PDGFRA PDHB PDIK1L PEPD PEX16 PEX5L PGM3 PHACTR3 PHIP PHLDA3 PHLDB1 PHLPP1 PHYHIPL PIEZO2 PIGN PIK3C2B PIP4K2A PKP4 PLA2G16 PLCL1 PLD1 PLEKHB1 PLEKHG3 PLEKHH1 PLEKHH2 PLLP PLP1 PLXDC2 PMP22 PNPT1 POGK POLR1B POPDC3 POU2AF1 PPA1 PPM1B PPM1D PPP1R14A PPP1R16B PPP1R21 PPP1R8 PPP1R9A PPP2R2A PPP2R2B PPP2R3A PPP6C PRDM8 PRKCQ PRKCQ-AS1 PRR18 PRR5L PRRC2C PRRG1 PRUNE2 PSEN1 PTBP2 PTGDS PTK2 PTMA PTP4A2 PTPDC1 PTPN11 PTPRD PTPRD-AS1 PTPRK PWWP2A PXK PYROXD1 QDPR QKI RAB28 RAB33A RAB3IP RAB40B RALA RAP1GDS1 RAPGEF5 RASAL1 RASGRP3 RASSF2 RBM25 RBP7 RBPJ RDX REEP3 RERE RHBDL2 RHOU RICTOR RMND5A RNASE1 RNASEH2A RNF13 RNF130 RNF141 RNF144A RNF220 RPS6KC1 RTKN RTN4 S100B S1PR5 SAMD4B SAP18 SAPCD2 SBDS SCARB2 SCD SCD5 SEC14L5 SECISBP2L SEMA4D SEMA6A SENP2 SERAC1 SERINC5 SET SFRP1 SFT2D1 SFTPC SGK1 SGK2 SGPL1 SH3D19 SH3GL3 SH3PXD2A SH3TC2 SHB SHC4 SHROOM4 SHTN1 SIK3 SIRT2 SLAIN1 SLC12A2 SLC22A15 SLC24A2 SLC35A5 SLC35D2 SLC3A1 SLC44A1 SLC45A3 SLC5A11 SLCO1A2 SLCO3A1 SMIM6 SMOC1 SNHG18 SNRPF SNX1 SNX22 SNX27 SNX30 SNX6 SORT1 SOSTDC1 SOX2-OT SOX3 SOX8 SPATA7 SPDL1 SPECC1 SPG21 SPOCK3 SPP1 SPPL3 SPSB1 SRCIN1 SRD5A3 SRPK2 SRRM1 ST13 ST18 ST3GAL5 ST3GAL6-AS1 STEAP1B STK31 STK39 STMN4 STRN SUGT1 SUN2 SWT1 SYNJ2 TALDO1 TAOK1 TARSL2 TAS2R39 TBC1D15 TBC1D32 TBC1D5 TCF12 TCFL5 TCP11L2 TF TGFB3 THAP5 THBS2 THBS4 TJAP1 TJP1 TJP2 TMC7 TMCC2 TMCC3 TMED4 TMEFF2 TMEM125 TMEM144 TMEM151A TMEM165 TMEM189 TMEM206 TMEM230 TMEM235 TMEM258 TMEM63A TMEM64 TMEM87A TMEM98 TMTC2 TMTC4 TNR TP53INP2 TP53TG5 TPPP TPPP3 TPRN TPTEP1 TRAM1L1 TRIM2 TRIM21 TRIM59 TRIM62 TRMT13 TSEN15 TSPAN15 TSPAN5 TTC23L TTL TTLL7 TTYH2 TUBA1A TUBB4A TULP4 TXNL1 TYMS TYMSOS UBE2E2 UBE4B UGT8 UNC5C URI1 USH1C USP32 UTP15 VAMP3 VEZF1 VRK2 VSTM2B WDPCP WDR20 WDR44 WDR89 WIPF1 WNK1 WRB WSCD1 XYLT1 YBEY YPEL2 YWHAQ ZBTB20 ZBTB6 ZC3H13 ZCCHC24 ZDHHC11 ZDHHC20 ZDHHC9 ZEB2 ZFP3 ZFYVE16 ZGRF1 ZKSCAN1 ZNF146 ZNF175 ZNF24 ZNF268 ZNF271P ZNF281 ZNF415 ZNF488 ZNF536 ZNF559 ZNF565 ZNF572 ZNF576 ZNF577 ZNF585B ZNF607 ZNF652 ZNF664 ZNF682 ZNF708 ZNF728 ZNF738 ZNF826P ZNF841 ZNHIT6 ZSCAN29 ZZZ3 +OPC NA ABHD2 ADARB2 ADGRL3 AGAP1 ALCAM APBB2 ASAP1 ASIC4 ASTN2 ATRNL1 BCAN BCAS1 BRINP3 C1orf61 CA10 CASK CCDC50 CD81 CDH20 CHD7 CHL1 CHST11 CMYA5 COBL COL11A1 COL9A1 CSMD1 CSMD3 CSPG5 CTTNBP2 DCC DGKG DOCK10 DPP6 DSCAM DSCAML1 EPN2 FCHSD2 FERMT1 FGF12 FHIT GALNT13 GPC6 GPR17 GRID2 GRIK1 GRM7 HIP1 HTRA1 ITPR2 KAT2B KAZN KCND2 KCNQ1OT1 KIF13A KIF26B KLF12 LHFPL3 LRP1 LRP1B LRRC4C LRRTM4 LSAMP LUZP2 MAML2 MARCKS MDGA2 MEGF11 MMP16 MTSS1 NAALADL2 NAV1 NAV2 NCAM1 NCAM2 NCKAP5 NFIA NKAIN3 NLGN1 NLGN4X NOVA1 NPAS3 NRCAM NRXN1 NTM NXPH1 OLIG1 OLIG2 OPCML OPHN1 PCDH15 PDE4B PDGFRA PDZD2 PDZRN4 PEAK1 PHLPP1 PID1 PLPPR1 PPP1R9A PRKCA PSAP PTPRZ1 QKI REV3L RPL13 SCD5 SCN1A SDC3 SEMA5A SERPINE2 SETD5 SEZ6L SGCD SGK1 SH3D19 SHISA9 SLC24A3 SLC35F1 SMOC1 SNTG1 SNX22 SORCS3 SOX2-OT SOX5 SOX6 SPATA6 TAOK3 TCF12 TMBIM6 TMEM132C TNK2 TNR VCAN WWOX XKR4 XYLT1 ZBTB20 ZEB1 ZNF462 ZSWIM6 \ No newline at end of file diff --git a/imaging_transcriptomics/errors.py b/imaging_transcriptomics/errors.py index 932f7ea..48c56a4 100644 --- a/imaging_transcriptomics/errors.py +++ b/imaging_transcriptomics/errors.py @@ -9,19 +9,19 @@ class InvalidFormatError(Exception): errorFile -- file that is not in the correct format. message -- optional user overridden error message to display. """ - def __init__( self, error_file, - message="The provided file has an invalid format. Please use files in the .nii, " - ".nii.gz format.", + message="The provided file has an invalid format. Please use files " + "in the .nii, .nii.gz format.", ): self.error_file = error_file self.message = message super().__init__(self.message) def __str__(self): - return f"{self.message} The error was caused by the file {self.error_file}." + return f"{self.message}" \ + f" The error was caused by the file {self.error_file}." class InvalidSizeError(Exception): @@ -32,9 +32,9 @@ class InvalidSizeError(Exception): * size -- size of the input image * message -- optional user defined error message """ - def __init__( - self, shape=(182, 218, 182), message="The provided file has a wrong shape." + self, shape=(182, 218, 182), + message="The provided file has a wrong shape." ): self.message = message self.shape = shape @@ -48,12 +48,11 @@ def __str__(self): class CheckPath: """Decorator to check if a path exists. - In order to run the function decorated the path provided to the function has to exists, otehrwise an error is - raised. + In order to run the function decorated the path provided to the function + has to exists, otherwise an error is raised. :raises FileNotFoundError: """ - def __init__(self, function): self.function = function @@ -66,11 +65,11 @@ def __call__(self, path, *args, **kwargs): class CheckExtension: """Decorator to check the file extension of the input scan. - Extension of the imaging scan has to be in NIfTI format (compressed or not) in order to run the function. + Extension of the imaging scan has to be in NIfTI format (compressed or not) + in order to run the function. :raises InvalidFormatError: """ - def __init__(self, function): self.function = function @@ -84,11 +83,11 @@ def __call__(self, path, *args, **kwargs): class CheckShape: """Decorator to check the correct matrix shape of the imaging scan. - Shape of the matrix has to be 182x218x182 in order to run the function, otherwise raises and error. + Shape of the matrix has to be 182x218x182 in order to run the function, + otherwise raises and error. :raises InvalidSizeError: """ - def __init__(self, function): self.function = function @@ -101,11 +100,11 @@ def __call__(self, image, *args, **kwargs): class CheckVariance: """Decorator to check that the variance is in the correct range of values. - Target variance has to be in the range 0.0-1.0 (equivalent to 0-100%) in order to run the function. + Target variance has to be in the range 0.0-1.0 (equivalent to 0-100%) in + order to run the function. :raises ValueError: """ - def __init__(self, function): self.function = function diff --git a/imaging_transcriptomics/genes.py b/imaging_transcriptomics/genes.py index 5757af9..ade9de6 100644 --- a/imaging_transcriptomics/genes.py +++ b/imaging_transcriptomics/genes.py @@ -2,10 +2,15 @@ import logging.config import yaml from pathlib import Path - +from pyls import pls_regression from scipy.stats import zscore, norm from statsmodels.stats.multitest import multipletests import numpy as np +from collections import OrderedDict +import gseapy +from gseapy.plot import gseaplot +import pandas as pd +from .inputs import get_geneset cfg_file_path = Path(__file__).parent / "log_config.yaml" @@ -17,99 +22,370 @@ logger.setLevel(logging.DEBUG) -class OriginalResults(dict): - """Class to hold the result from gene analysis (non bootstrapped).""" +# --------- GENE ANALYSIS --------- # +class GeneResults: + def __init__(self, method, **kwargs): + """Initialize the results of the analysis. Depending on the method + used, the results will have underlying result classes, which account + for the different analysis methods. + + :param str method: the method used for the analysis. + :param kwargs: Additional parameters, for the initialisation. If the + method is "pls" among the kwargs you *MUST* specify the number of + components used, for the initialisation of the pls class. + """ + self.method = method + if self.method == "pls": + self.results = PLSGenes(kwargs.get("n_components")) + elif self.method == "corr": + self.results = CorrGenes() + else: + raise ValueError(f"The method {method} is not supported.") + + @property + def n_genes(self): + return self.results.n_genes + + @property + def genes(self): + if isinstance(self.results, PLSGenes): + return self.results.orig.genes + elif isinstance(self.results, CorrGenes): + return self.results.genes + + @property + def scores(self): + if isinstance(self.results, PLSGenes): + return self.results.orig.weights + elif isinstance(self.results, CorrGenes): + return self.results.corr + + @property + def boot(self): + if isinstance(self.results, PLSGenes): + return self.results.boot.weights + elif isinstance(self.results, CorrGenes): + return self.results.boot_corr + + @property + def pvals(self): + if isinstance(self.results, PLSGenes): + return self.results.boot.pval + elif isinstance(self.results, CorrGenes): + return self.results.pval + + @property + def pvals_corr(self): + if isinstance(self.results, PLSGenes): + return self.results.boot.pval_corr + elif isinstance(self.results, CorrGenes): + return self.results.pval_corr + + +# --------- PLS GENES --------- # +class PLSGenes: + def __init__(self, n_components): + """ Initialize the results of the PLS analysis. The result will + include both the permuted and the original results. The class + contains two subclasses, one for the original results and one for + the bootrapped results. + + :param int n_components: number of components used for the analysis. + """ + self.n_genes = 15633 + self.n_components = n_components + self.orig = OrigPLS(n_components, self.n_genes) + self.boot = BootPLS(n_components, self.n_genes) + + def boot_genes(self, imaging_data, permuted_imaging, + scan_data, gene_exp, gene_labels): + """Bootstrapping on the PLS components. + + :param imaging_data: imaging data. Allows the user to specify the + data to use (e.g., with only cortical regions this can be only the + cortical vector, other wise the whole data). + :param permuted_imaging: imaging data permuted. Allows the user to + specify the data to use (e.g., with only cortical regions this can be + only the cortical vector, other wise the whole data). + :param scan_data: Original scam data, not zscored. + :param gene_exp: gene expression data. + :param gene_labels: gene labels. + """ + logger.info("Performing bootstrapping of the genes.") + + def correlate(c1, c2): + """Return the MATLAB style correlation between two vectors.""" + return np.corrcoef(np.hstack((c1, c2)), rowvar=False)[0, 1:] + + _res = pls_regression(gene_exp, imaging_data.reshape( + imaging_data.shape[0], 1), + n_components=self.n_components, + n_boot=0, n_perm=0) + r1 = correlate(_res.get("x_scores"), scan_data.reshape( + scan_data.shape[0], 1)) + _weights = _res.get("x_weights") + _scores = _res.get("x_scores") + for i in range(r1.size): + if r1[i] < 0: + _weights[:, i] *= -1 + _scores[:, i] *= -1 + for _idx in range(self.n_components): + _sort_weights_indexes = np.argsort(_weights[:, _idx], + kind="mergesort")[::-1] + self.orig.index[_idx, :] = _sort_weights_indexes + self.orig.genes[_idx, :] = gene_labels[:, 0][_sort_weights_indexes] + self.orig.weights[_idx, :] = _weights[:, _idx][ + _sort_weights_indexes] + self.orig.zscored[_idx, :] = zscore(self.orig.weights[_idx, :], + axis=0, + ddof=1) + for _iter in range(1000): + _perm_imaging = permuted_imaging[:, _iter] + _i_results = pls_regression(gene_exp, _perm_imaging.reshape( + _perm_imaging.shape[0], 1), + n_components=self.n_components, + n_boot=0, n_perm=0) + _weights_i = _i_results.get("x_weights") + for _comp in range(self.n_components): + _temp_weights = _weights_i[:, _comp] + _new_weights = _temp_weights[self.orig.index[_comp, :]] + _temp_genes = self.orig.weights[_comp, :] + _corr = correlate( + _temp_genes.reshape(_temp_genes.size, 1), + _new_weights.reshape(_new_weights.shape[0], 1) + ) + if _corr < 0: + _new_weights *= -1 + self.boot.weights[_comp, :, _iter] = _new_weights + return + + def compute(self): + """ Compute the p-values of the z-scored weights. + The compute function calculates the zscores based on the original + weights, orders the weights in descending order and then calculates + the p-values and corrects for multiple comparisons using the + Benjamini-Hochberg method. + """ + logger.info("Calculating statistics.") + for component in range(self.n_components): + # Calculate the standard deviation of all the wights + self.boot.std[component, :] = self.boot.weights[component, :, + :].std(axis=1, ddof=1) + # Calculate the zscore and store it sorted in descending order + _z = self.orig.weights[component, :] / self.boot.std[component, :] + self.boot.z_score[component, :] = np.sort( + _z, axis=0, kind='mergesort')[::-1] + _index = np.argsort(_z, axis=0, kind='mergesort')[::-1] + # Reorder the genes according to the zscore + self.boot.genes[component, :] = self.orig.genes[component, _index] + # Calculate pvalue and pvalue corrected + _p_val = norm.sf(abs(self.boot.z_score[component, :])) + self.boot.pval[component, :] = _p_val + _, _p_corr, _, _ = multipletests(_p_val[::-1].reshape(1, + self.n_genes), + method='fdr_bh', + is_sorted=True) + self.boot.pval_corr[component, :] = _p_corr + return + + def gsea(self, gene_set="lake", outdir=None): + """Perform a GSEA analysis on the z-scored weights.""" + assert isinstance(self.orig, OrigPLS) + assert isinstance(self.boot, BootPLS) + logger.info("Performing GSEA.") + gene_set = get_geneset(gene_set) + for _component in range(self.n_components): + gene_list = [gene for gene in self.orig.genes[ + _component, :]] + rnk = pd.DataFrame(zip(gene_list, + self.orig.zscored[_component, :])) + gsea_results = gseapy.prerank(rnk, gene_set, + outdir=None, + seed=1234, + permutation_num=1000) + _origin_es = gsea_results.res2d.es.to_numpy() + _boot_es = np.zeros((_origin_es.shape[0], 1000)) + for i in range(1000): + rnk = pd.DataFrame(zip(gene_list, + zscore( + self.boot.weights[_component, :, i], + ddof=1) + ) + ) + gsea_res = gseapy.prerank(rnk, gene_set, + outdir=None, + seed=1234, + permutation_num=1) + _boot_es[:, i] = gsea_res.res2d.es.to_numpy() + _p_val = np.zeros((_origin_es.shape[0],)) + for i in range(_origin_es.shape[0]): + _p_val[i] = np.sum(_boot_es[i, :] >= _origin_es[i]) / 1000 + # calculate the p-value corrected + _, _p_corr, _, _ = multipletests(_p_val, method='fdr_bh', + is_sorted=False) + # Prepare data to save + _out_data = OrderedDict() + _out_data["Term"] = gsea_results.res2d.axes[0].to_list() + _out_data["es"] = gsea_results.res2d.values[:, 0] + _out_data["nes"] = gsea_results.res2d.values[:, 1] + _out_data["p_val"] = _p_val + _out_data["fdr"] = _p_corr + _out_data["genest_size"] = gsea_results.res2d.values[:, 4] + _out_data["matched_size"] = gsea_results.res2d.values[:, 5] + _out_data["matched_genes"] = gsea_results.res2d.values[:, 6] + _out_data["ledge_genes"] = gsea_results.res2d.values[:, 7] + out_df = pd.DataFrame.from_dict(_out_data) + if outdir is not None: + logger.info("Saving GSEA results.") + outdir = Path(outdir) + assert outdir.exists() + out_df.to_csv( + outdir / f"gsea_pls{_component + 1}_results.tsv", + index=False, + sep="\t") + for _i in range(len(gsea_results.res2d.index)): + term = gsea_results.res2d.index[_i] + gsea_results.results[term]["pval"] = _p_val[_i] + gsea_results.results[term]["fdr"] = _p_corr[_i] + gseaplot(rank_metric=gsea_results.ranking, + term=term, + **gsea_results.results[term], + ofname=f"{outdir}/{term}_pls" + f"{_component + 1}_prerank.pdf") + + +# --------- ORIG PLS --------- # +class OrigPLS: + def __init__(self, n_components, n_genes): + """ Initialize the original results of the PLS analysis. The class + contains the fields corresponding to the number of components used, + the weights of the pls for each gene ordered in descending order, + the index where the original genes and the zscore of the weights. - def __init__(self, n_comp): - super().__init__() - self.pls_weights = [None] * n_comp - self.pls_gene = [None] * n_comp - self.gene_id = [None] * n_comp - self.index = [None] * n_comp - self.pls_weights_z = [None] * n_comp - logger.debug("OriginalResults class initialized with %s components", n_comp) + :param int n_components: number of components used. + :param int n_genes: number of genes. + """ + self.n_components = n_components + self.weights = np.zeros((n_components, n_genes)) + self.genes = np.zeros((n_components, n_genes), dtype=object) + self.index = np.zeros((n_components, n_genes), dtype=np.int32) + self.zscored = np.zeros((n_components, n_genes)) + + +# --------- BOOT PLS --------- # +class BootPLS: + def __init__(self, n_components, n_genes, n_iter=1000): + """Initialise a class to store the results of the bootstrapping of + the genes. + + All the initialised fields are stored as numpy arrays with the + number of rows corresponding to the number of components and the + columns corresponding to the number of genes. The weights field has + an additional 3rd dimension corresponding to the number of + iterations (the default number is 1000). + The fields are: + + * weights (n_components, n_genes, n_iter): the weights of the genes + for each component, for each iteration. + + * genes (n_components, n_genes, n_iter): the genes that correspond + to the most contributing genes for each component. - def set_result_values(self, idx, pls_weights, x, pls_genes, gene_id): - """Set the values for all class attributes. + * index (n_components, n_genes, n_iter): the index of the genes + compared to the original list of gene labels. + + * std: the standard deviation of the weights for each component, + calculated from the bootstrapped weights. + + * zscored (n_components, n_genes, n_iter): the z-scored weights. + + * pval (n_components, n_genes): the p-value of the z-scored gene + wights. + + * pval_corr (n_components, n_genes): the p-value of the correlation + corrected for multiple comparisons using the Benjamini-Hochberg method. + + :param int n_components: number of components used for the analysis. + :param int n_genes: number of genes used for the analysis. + :param int n_iter: number of iterations used for the bootstrapping, + the default is 1000. + """ + self.n_components = n_components + self.weights = np.zeros((n_components, n_genes, n_iter)) + self.genes = np.zeros((n_components, n_genes), dtype=object) + self.std = np.zeros((n_components, n_genes)) + self._z_score = np.zeros((n_components, n_genes)) + self.pval = np.zeros((n_components, n_genes)) + self.pval_corr = np.zeros((n_components, n_genes)) - :param idx: index of the component to set the values in the array (must be in the range 0:n_components-1). - :param pls_weights: weights to pass to the array at the index idx. - :param pls_genes: genes to pass to the array at the index idx - :param gene_id: id of the genes to pass to the array at the index idx - :param x: index of the pls genes in the original gene list. - :return: + @property + def z_score(self): + """The z-scored weights. """ - self.pls_weights[idx - 1] = np.array(pls_weights) - logger.debug("Weights at index %s set as %s", idx - 1, pls_weights) - self.pls_gene[idx - 1] = np.array(pls_genes) - logger.debug("Genes at index %s set as %s", idx - 1, pls_genes) - self.gene_id[idx - 1] = gene_id - logger.debug("Genes ids at index %s set as %s", idx - 1, gene_id) - self.index[idx - 1] = np.array(x) - self.pls_weights_z[idx - 1] = np.array(zscore(pls_weights, axis=0, ddof=1)) - - -class BootResults(dict): - """Class to hold the results from the bootstrapping gene analysis.""" - - def __init__(self, n_comp, dim1, dim2, n_perm=1000): - super().__init__() - self.pls_weights_boot = [np.zeros((dim1, dim2, n_perm))] * n_comp - self.std = [None] * n_comp - self.z_scores = [None] * n_comp - self.pls_genes = [None] * n_comp - self.pval = [None] * n_comp - self.pval_corrected = [None] * n_comp - logger.debug("BootResult class initialised with %s components", n_comp) - - def compute_values(self, n_comp, original_weights, original_ids): - """Compute the values of the bootstrap for each of the components. - - :param n_comp: number of PLS components. - :param original_weights: weights obtained from the original analysis (not bootstrapped) - :param original_ids: original ids (labels) from the original analysis (not bootstrapped) - :return: + return self._z_score + + +# --------- CORRELATION GENES --------- # +class CorrGenes: + """Class that stores the gene results of the correlation analysis. It + has the following fields: + + * boot_corr: the bootstrapped results of the correlation analysis. + * corr: the original results of the correlation analysis. + * boot_corr: the bootstrapped results of the correlation analysis. + * genes: the gene list used for the analysis. + * pval: the p-value of the correlation. + * pval_corr: the p-value of the correlation corrected for multiple + comparisons using the Benjamini-Hochberg method. + """ + def __init__(self, n_iter=1000): + """Initialise the class. + + :param int n_iter: number of iterations used for the bootstrapping, + """ + self.n_genes = 15633 + self._n_iter = n_iter + self.boot_corr = np.zeros((self.n_genes, self._n_iter)) + self.corr = np.zeros((1, self.n_genes)) + self.genes = np.zeros((1, self.n_genes)) + self.pval = np.zeros((1, self.n_genes)) + self.pval_corr = np.zeros((1, self.n_genes)) + self._index = None + + def compute_pval(self): + """Compute the p-values, and its fdr correction, of the correlation, + from the list of bootstrapped correlations. + """ + # This calculation assumes that the order of the genes is the same + # in both the original and the bootstrapped list. IF one is ordered, + # make sure the order of the other is the same. + logger.info("Computing p values.") + for i in range(self.n_genes): + self.pval[0, i] = np.sum( + self.boot_corr[i, :] >= self.corr[0, i]) / self._n_iter + _, p_corr, _, _ = multipletests(self.pval[0, :], method='fdr_bh', + is_sorted=False) + self.pval_corr[0, :] = p_corr + return + + @property + def is_sorted(self): + """Check if the list of genes is sorted. + + :return: True if the list of genes is sorted, False otherwise. + """ + return False if self._index is None else True + + def sort_genes(self): + """Order the genes in the list of genes. Both the order of the + order of the bootstrapped genes are ordered. """ - logger.info("Computing bootstrap gene results.") - for component in range(1, n_comp + 1): - logger.debug("Computing results for component %s", component) - self.std[component - 1] = self.pls_weights_boot[component - 1][ - :, component - 1, : - ].std(ddof=1, axis=1) - __temp = original_weights[component - 1] / self.std[component - 1] - self.z_scores[component - 1] = np.sort(__temp, kind="mergesort")[::-1] - __idx = np.argsort(__temp, kind="mergesort")[::-1] - self.pls_genes[component - 1] = original_ids[component - 1][__idx] - __p = norm.sf(abs(self.z_scores[component - 1])) - self.pval[component - 1] = __p - _, __p_corr, _, _ = multipletests( - __p[::-1].reshape(1, 15633), method="fdr_bh", is_sorted=True - ) - self.pval_corrected[component - 1] = __p_corr - - def compute_correlation(self, original_corr, originals_ids, original_index): - """Compute the p value of the correlation after the permutation.""" - logger.info("Computing bootstrap correlation results") - n_iter = 1000 - for i in range(n_iter): - tmp = self.pls_weights_boot[:, i] - self.pls_weights_boot[:, i] = tmp[original_index] - p = np.zeros(15633) - for i in range(15633): - original = original_corr[i] - boot = self.pls_weights_boot[i, :] - p[i] = float(len(boot[np.nonzero(boot >= original)])) / n_iter - self.pval = p - _, p_corrected, _, _ = multipletests(p, method="fdr_bh", - is_sorted=False) - self.pval_corrected = p_corrected - self.pls_genes = np.array(originals_ids) - - -class GeneResults(dict): - """Class to save the gene results.""" - - def __init__(self, n_comp, dim1, dim2): - super().__init__() - self.original_results = OriginalResults(n_comp) - self.boot_results = BootResults(n_comp, dim1, dim2) + logger.info("Sorting genes in ascending order.") + self._index = np.argsort(self.corr, axis=1, kind='mergesort') + self.corr[0, :] = self.corr[0, self._index] + self.genes[:] = self.genes[self._index] + self.pval[0, :] = self.pval[0, self._index] + self.pval_corr[0, :] = self.pval_corr[0, self._index] + for i in range(self._n_iter): + self.boot_corr[:, i] = self.boot_corr[:, i][self._index] + return diff --git a/imaging_transcriptomics/inputs.py b/imaging_transcriptomics/inputs.py index 87ff7a6..7b7100c 100644 --- a/imaging_transcriptomics/inputs.py +++ b/imaging_transcriptomics/inputs.py @@ -26,10 +26,10 @@ def read_scan(path): """Return the imaging file associated to the input scan. - Uses the `Nibabel `_ to read the input imaging file and get the voxel data. + Uses the `Nibabel `_ + to read the input imaging file and get the voxel data. :param str path: path of the imaging file to analyze. - :return: Numpy matrix with the voxel of the input scan. """ logger.debug("Reading scan: %s", path) @@ -41,8 +41,9 @@ def read_scan(path): def extract_average(imaging_matrix): """Extract the average value of the ROIs from the imaging scan. - The values are extracted from the left hemisphere only, since the data of the Allen Human Brain Atlas are - available for that hemisphere only for all donors. + The values are extracted from the left hemisphere only, since the data of + the Allen Human Brain Atlas are available for that hemisphere only for + all donors. :param imaging_matrix: matrix with the voxels of the image. @@ -62,41 +63,29 @@ def extract_average(imaging_matrix): return np.array(data) -# Other parameters -@CheckVariance -def get_components(target_variance, explained_var): - """Return the optimal number of PLS components to explain a desired amount of the total variance. - - :param float target_variance: total explained variance - :param np.array explained_var: array with explained variance by each individual pls component. - - :return int dim: optimal number of components to extract the desired explained variance. - """ - dim = 1 - cumulative_var = np.cumsum(explained_var) - while cumulative_var[dim - 1] < target_variance: - dim += 1 - logger.debug( - "Extracted variance is %s with %s components", cumulative_var[dim - 1], dim - ) - return dim - - # Gene expression data -def load_gene_expression(): +def load_gene_expression(regions="cort+sub"): """Return matrix with gene expression data. The data have been previously normalised and are available in the ``data`` sub-folder. :return: numpy array with the gene expression data. """ + if regions not in ["cort+sub", "cort", "all"]: + raise ValueError("The regions must be either 'cort+sub', 'cort' or " + "'all'.") logger.debug("Loading gene_expression data.") expression_file_path = ( Path(__file__).resolve().parent / "data" / "gene_expression_data.csv" ) expression_data = pd.read_csv(expression_file_path, sep=",") my_data_x = expression_data.iloc[0:41, 2:].to_numpy() - return zscore(my_data_x, ddof=1) + my_data = zscore(my_data_x, ddof=1) + if regions == "cort+sub" or regions == "all": + my_data = my_data + elif regions == "cort": + my_data = my_data[:34, :] + return my_data def load_gene_labels(): @@ -110,3 +99,46 @@ def load_gene_labels(): Path(__file__).resolve().parent / "data" / "gene_expression_labels.txt" ) return pd.read_fwf(genes_labels_path, header=None).to_numpy() + + +def get_geneset(gene_set: str): + """Returns the path to the geneset file, if it is not one of those + defined in gseapy. + + :param str gene_set: the name of the geneset. If the geneset is "lake" + or "pooled", the genesets are provided with the package data, otherwise + the gene sets are from the gseapy package. + """ + if gene_set.lower() == "lake": + return str(Path(__file__).parent / "data" / "geneset_LAKE.gmt") + elif gene_set.lower() == "pooled": + return str(Path(__file__).parent / "data" / + "geneset_Pooled.gmt") + else: + return gene_set + + +def extract_average_all_regions(imaging_matrix): + """Extract the average value of the ROIs from the imaging scan. + + The values are extracted from the left hemisphere only, since the data of + the Allen Human Brain Atlas are available for that hemisphere only for + all donors. + + :param imaging_matrix: matrix with the voxels of the image. + + :return: numpy array with the average value from 41 brain regions. + """ + logger.debug("Extracting average from scan.") + atlas_data = nib.load( + Path(__file__).resolve().parent + / "data" + / "atlas-desikankilliany_1mm_MNI152.nii.gz" + ).get_fdata() + n_regions = int(max(atlas_data.flatten())) + print(n_regions) + data = np.zeros(n_regions) + for i in range(1, n_regions + 1): + data[i - 1] = np.mean(imaging_matrix[np.where(atlas_data == i)]) + logger.debug("Extracted values are: \n%s", data) + return np.array(data) diff --git a/imaging_transcriptomics/pls.py b/imaging_transcriptomics/pls.py new file mode 100644 index 0000000..b2664bc --- /dev/null +++ b/imaging_transcriptomics/pls.py @@ -0,0 +1,156 @@ +import numpy as np +from pyls import pls_regression +import pandas as pd + +from .genes import GeneResults, PLSGenes +from pathlib import Path +import yaml +import logging.config +import logging + +cfg_file_path = Path(__file__).parent / "log_config.yaml" +with open(cfg_file_path, "r") as config_file: + log_cfg = yaml.safe_load(config_file.read()) + +logging.config.dictConfig(log_cfg) +logger = logging.getLogger("genes") +logger.setLevel(logging.DEBUG) + +np.random.seed(1234) + + +# --------- PLS ANALYSIS --------- # +class PLSAnalysis: + """Class for performing PLS regression on the imaging data. + This class contains fields for + """ + def __init__(self, imaging_data, gene_exp, n_components: int, var: float): + self.var, self.n_components, self.components_var = self.set_coef( + imaging_data, gene_exp, n_components=n_components, var=var) + self._p_val = np.zeros(self.n_components) + self._r2 = np.zeros(self.n_components) + self.gene_results = GeneResults("pls", n_components=self.n_components) + + @staticmethod + def check_var(var: float): + """ Check if the variance is between 0 and 1. + + :param float var: variance. + """ + if var < 0: + raise ValueError("The variance must be a positive number.") + elif var > 1: + raise ValueError("The variance must be a number between 0 and 1.") + return var + + @staticmethod + def set_coef(data, gene_exp, var=None, n_components=None): + """Set the coefficients for the PLS regression. The function will + estimate the variance or the number of components depending on the + non missing parameter through a PLS regression with 15 components. + + :param data: imaging data. + :param gene_exp: gene expression data. + :param var: variance. + :param n_components: number of components. + """ + res = pls_regression(gene_exp, data.reshape(data.shape[0], 1), + n_components=15, + n_perm=0, + n_boot=0) + explained_var = res.get("varexp") + if var is None: + var = np.cumsum(explained_var)[n_components-1] + if n_components is None: + dim = 1 + cumulative_var = np.cumsum(explained_var) + while cumulative_var[dim - 1] < var: + dim += 1 + n_components = dim + return var, n_components, explained_var + + @property + def p_val(self): + """P-value of the pls regression given by the bootstrapping on the + PLS components.""" + return self._p_val + + @property + def r2(self): + """R2 of the pls regression given by the bootstrapping on the PLS + components""" + return self._r2 + + @p_val.setter + def p_val(self, p_val): + self._p_val = p_val + + @r2.setter + def r2(self, r2): + self._r2 = r2 + + def boot_pls(self, + imaging_data, + permuted_imaging, + gene_exp): # pragma: no cover + """Bootstrapping on the PLS components. + + :param imaging_data: imaging data. Allows the user to specify the + data to use (e.g., with only cortical regions this can be only the + cortical vector, other wise the whole data). + :param permuted_imaging: imaging data permuted. Allows the user to + specify the data to use (e.g., with only cortical regions this can be + only the cortical vector, other wise the whole data). + :param gene_exp: gene expression data. + """ + # Iterate over the components + logger.info(f"Calculating PLS with permuted data") + for component in range(1, self.n_components + 1): + _res = pls_regression(gene_exp, imaging_data.reshape( + imaging_data.shape[0], 1), + n_components=component, + n_perm=0, n_boot=0) + _exp_var = _res.get("varexp") + _temp = _exp_var.cumsum(axis=0) + _R = _temp[component - 1] + _R_sq = np.zeros(1000) + # Iterate over the permutations + for i in range(1000): + y_data = permuted_imaging[:, i].reshape( + imaging_data.shape[0], 1) + _res = pls_regression(gene_exp, y_data, n_components=component, + n_perm=0, n_boot=0) + _exp_var = _res.get("varexp") + _R_sq[i] = _exp_var.cumsum(axis=0)[component - 1] + # Set the results + self.r2[component - 1] = _R + self.p_val[component - 1] = np.sum(_R_sq >= _R) / 1000 + self.print_table() + return + + def print_table(self): + print("+-----------+----------------+-------+") + print("| Component | Cumulative var | p val |") + print("|-----------|----------------|-------|") + for i in range(self.p_val.shape[0]): + print("| {} | {:.3f} | {} |".format( + i + 1, self.r2[i], self.p_val[i])) + print("+-----------+----------------+-------+") + print("") + + def save_results(self, outdir=None): + """Save the results of the PLS regression. + + :param outdir: output directory. + """ + assert isinstance(self.gene_results.results, PLSGenes) + for i in range(self.n_components): + data = zip(self.gene_results.results.orig.genes[i, :], + self.gene_results.results.orig.zscored[i, :], + self.gene_results.results.boot.pval[i, :], + self.gene_results.results.boot.pval_corr[i, :]) + df = pd.DataFrame(data, columns=["Gene", "Z-score", "p-value", + "p-value (corrected)"]) + df.to_csv(f"{outdir}/pls_component_{i+1}.tsv", sep='\t', + index=False) + diff --git a/imaging_transcriptomics/reporting.py b/imaging_transcriptomics/reporting.py index 948fcf8..b40b2b7 100644 --- a/imaging_transcriptomics/reporting.py +++ b/imaging_transcriptomics/reporting.py @@ -5,55 +5,13 @@ import pandas as pd import matplotlib.pyplot as plt from fpdf import FPDF +from enigmatoolbox.utils.parcellation import parcel_to_surface +from enigmatoolbox.plotting.surface_plotting import plot_cortical, \ + plot_subcortical from .errors import CheckPath from .genes import GeneResults - - -class PDF(FPDF): - """Class to generate a PDF report for the imaging-transcriptomics script.""" - - def header(self): - """The header will contain always the title.""" - self.rect(10, 10, 190, 280) - self.line(10, 50, 200, 50) - self.set_font("Helvetica", "B", 14) - self.cell( - w=0, h=15, align="C", txt="Imaging Transcriptomics Analysis Report", ln=True - ) - - def analysis_info(self, filename, date, filepath): - """Info on the analysis performed. Information included are the name of - the scan of the input, date of the analysis and the original path of the scan. - - :param filename: name of the scan used for analysis. - :param date: date when the analysis was performed. - :param filepath: absolute path of the imaging scan used for analysis. - """ - self.set_font("Courier", "", 10) - self.cell(w=100, h=8, align="L", txt=f" Scan Name: {filename}") - self.cell(w=100, h=8, align="L", txt=f" Date: {date}", ln=True) - self.cell(w=100, h=10, align="L", txt=f" File Path: {filepath}") - - def pls_regression(self, path_plots): - """Include the plots of the pls components. - - :param path_plots: path where the .png plots are located. - """ - self.ln(20) - self.set_font("Helvetica", "BU", 12) - self.cell(w=0, h=10, align="L", txt="-PLS Regression") - self.ln(10) - self.image(Path(path_plots) / "individual_variance.png", x=15, w=120) - self.image(Path(path_plots) / "cumulative_variance.png", x=15, w=120) - - def reproducibility_line(self, cli_commands, version): - """Create a string with the command used from the command line to run the analysis. - - :param cli_commands: commands given in the cli to run the analysis. - :param version: version of the software used to run the analysis. - """ - pass +from .transcriptomics import ImagingTranscriptomics @CheckPath @@ -78,8 +36,9 @@ def make_folder(path, folder_name: str): @CheckPath def make_plots(path, limit_x, data_y): - """Generate the plots for the explained variance by each component, one with the cumulative sum and one with the - variance explained by each individual component. + """Generate the plots for the explained variance by each component, + one with the cumulative sum and one with the variance explained by each + individual component. :param path: path where the plots will be saved. :param limit_x: number of PLS components. @@ -100,7 +59,8 @@ def make_plots(path, limit_x, data_y): colors="lightgrey", linestyles="dashed", ) - plt.hlines(varexp[limit_x - 1], 0, limit_x, colors="lightgrey", linestyles="dashed") + plt.hlines(varexp[limit_x - 1], 0, limit_x, colors="lightgrey", + linestyles="dashed") plt.title("Cumulative variance explained by PLS components") plt.ylabel("Total explained variance (%)") plt.xlabel("Number of PLS components") @@ -114,75 +74,106 @@ def make_plots(path, limit_x, data_y): plt.bar(range(1, 16), 100 * data_y, color="sandybrown") for index, value in enumerate(data_y): plt.text(index + 0.5, 100 * value, "{:.1f}".format(100 * value)) - plt.xlabel("PLS components") + plt.title("Individual variance explained by PLS components") + plt.xlabel("PLS component") plt.ylabel("Variance (%)") plt.savefig(path / "individual_variance.png", dpi=1200) plt.close() + return + +""" +def reorder_data(data): + # Indexes to match the abagen (DK) order to the enigma + enigma_index = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 75, 71, 74, 73, + 69, 72, 70, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 82, 79, 81, 80, 76, 79, 77, 83], + np.int32) - 1 + if not isinstance(data, np.ndarray): + try: + data = np.array(data) + except TypeError: + raise TypeError("The data must be a numpy array.") + if data.shape == (83,) : + data = data[enigma_index] + elif data.shape == (41,): + pass -def create_pdf(filepath, save_dir): - """Create a PDF report. - - Creates a report for the imaging transcriptomics analysis with some plots and details of what was run by the user. - - :param filepath: path of the image used for analysis. - :param save_dir: path where to save the report (same as where the plots are located). - """ - if not isinstance(filepath, Path): - filepath = Path(filepath) - analysis_date = datetime.now().strftime("%d-%m-%Y") - - report = PDF(orientation="P", unit="mm", format="A4") +# PLOTTING +# TODO: add plots for the cortical and subcortical regions +def make_surface_plots(data, save_dir): + pass + save_dir = Path(save_dir) + filename_cort = save_dir / "cortical_surface.png" + # All regions are there, just reorder them + if data.shape == (83,): + data = data[enigma_index] + + + data_cortical = parcel_to_surface(data, "aparc_fsa5") + plot_cortical(array_name=data_cortical, surface_name="fsa5", + size=(800, 400), cmap="RdBu_r", color_bar=True, + color_range=(-0.5, 0.5), interactive=False, + screenshot=True, filename=str(filename_cort), + transparent_bg=True + ) + plot_subcortical(array_name=data_subcortical,) +""" + + +def pls_components(data): + """Return a string with the number of components, its cumulative + variance and its p value from the analysis.""" + if not isinstance(data, ImagingTranscriptomics): + raise TypeError("The data must be an ImagingTranscriptomics object.") + n_components = data.analysis.n_components + res_str = "PLS Component: R2 pval " + for i in range(n_components): + res_str += f"PLS {i+1}: " \ + f"{data.analysis.r2[i]:.3f}" \ + f" {data.analysis.p_val[i]:.4f}" + return res_str + + +def make_pdf(transcriptomics_data, save_dir, name="report", scanname="", ): + if not isinstance(transcriptomics_data, ImagingTranscriptomics): + raise TypeError("The data must be an ImagingTranscriptomics object.") + save_dir = Path(save_dir) + WIDTH = 210 # mm + HEIGHT = 297 # mm + MARGIN = 5 # mm + report = FPDF(orientation="P", unit="mm", format="A4") + report.set_font("Arial", size=11) report.add_page() - report.analysis_info(filename=filepath.name, date=analysis_date, filepath=filepath) - report.pls_regression(path_plots=save_dir) - report.output(save_dir / "Report.pdf", "F") - - -def create_csv(analysis_results, n_comp, save_dir): - """Create .csv files for the results of each component. - - The function creates a different csv file for each of the components used for PLS regression (if 2 components are - used the files 'PLS1.csv' and 'PLS2.csv' will be created. - - :param analysis_results: GeneResults data structure with the results of bootstrapping. - :param int n_comp: number of components used in the regression. - :param save_dir: path where the output will be saved. - :return: - """ - if not isinstance(analysis_results, GeneResults): - raise TypeError("The data are not of the GeneResults class.") - for i in range(n_comp): - data = np.vstack( - ( - np.array(analysis_results.boot_results.pls_genes[i].reshape(1, 15633)), - np.array(analysis_results.boot_results.z_scores[i]), - np.array(analysis_results.boot_results.pval[i]), - np.array(analysis_results.boot_results.pval_corrected[i]), - ) - ).T - data = pd.DataFrame(data, columns=["Gene ID", "Z", "p", "p corrected"]) - data.to_csv(save_dir / f"PLS{i+1}.csv", index=False) - - -def create_corr_csv(analysis_results, save_dir): - """Create a csv file for the correlation coefficients. - - :param analysis_results: GeneResults data structure with the results of bootstrapping. - :param save_dir: path where the output will be saved. - :return: - """ - if not isinstance(analysis_results, GeneResults): - raise TypeError("The data are not of the GeneResults class.") - if not isinstance(save_dir, Path): - save_dir = Path(save_dir) - data = np.vstack( - ( - np.array(analysis_results.boot_results.pls_genes.reshape(1, 15633)), - np.array(analysis_results.original_results.pls_weights), - np.array(analysis_results.boot_results.pval), - np.array(analysis_results.boot_results.pval_corrected), - ) - ).T - data = pd.DataFrame(data, columns=["Gene ID", "Correlation coefficient", "p", "p corrected"]) - data.to_csv(save_dir / "Correlation_coefficients.csv", index=False) + # Header + report.image(str(Path(__file__).parent / "resources" / "header.png"), + x=0, y=0, w=WIDTH) + # Info on the analysis + analysis_date = datetime.now().strftime("%d-%m-%Y") + report.ln(25) + report.cell(WIDTH/2, txt=f"Scan name: {scanname}") + report.cell(WIDTH/2, txt=f"Analysis date:{analysis_date}") + # PLS plots + if transcriptomics_data.method == "pls": + report.ln(10) + make_plots(save_dir, + transcriptomics_data.analysis.n_components, + transcriptomics_data.analysis.components_var) + report.cell(WIDTH, txt="PLS Analysis") + report.image(str(save_dir / "individual_variance.png"), + x=MARGIN, y=53, w=WIDTH/2) + report.image(str(save_dir / "cumulative_variance.png"), + x=WIDTH/2 + MARGIN, y=53, w=WIDTH/2) + report.ln(90) + report.cell(WIDTH, txt=pls_components(transcriptomics_data)) + # MAKE GENE RESULTS TABLE + report.ln(80) + report.cell(WIDTH, txt="For the gene results refer to the spreadsheet in " + "the report folder.") + report.output(str(save_dir / f"{name}.pdf"), "F") diff --git a/imaging_transcriptomics/resources/Header_final.pdf b/imaging_transcriptomics/resources/Header_final.pdf new file mode 100644 index 0000000..a55a6a5 Binary files /dev/null and b/imaging_transcriptomics/resources/Header_final.pdf differ diff --git a/imaging_transcriptomics/resources/header.png b/imaging_transcriptomics/resources/header.png new file mode 100644 index 0000000..4d3e356 Binary files /dev/null and b/imaging_transcriptomics/resources/header.png differ diff --git a/imaging_transcriptomics/resources/header.svg b/imaging_transcriptomics/resources/header.svg new file mode 100644 index 0000000..9ba35a7 --- /dev/null +++ b/imaging_transcriptomics/resources/header.svg @@ -0,0 +1 @@ +IMAGING TRANSCRIPTOMICS ANALYSIS REPORT \ No newline at end of file diff --git a/tests/__init__.py b/imaging_transcriptomics/script/__init__.py similarity index 100% rename from tests/__init__.py rename to imaging_transcriptomics/script/__init__.py diff --git a/imaging_transcriptomics/script/imagingtranscriptomics.py b/imaging_transcriptomics/script/imagingtranscriptomics.py new file mode 100644 index 0000000..9a55248 --- /dev/null +++ b/imaging_transcriptomics/script/imagingtranscriptomics.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 + +import argparse +import imaging_transcriptomics as imt +from pathlib import Path + + +def parse_cmdline(): + DESCRIPTION = """Perform imaging transcriptomics analysis of a + neuroimaging data.""" + EPILOG = """ + If you use this software in your work, please cite: + + * + """ + parser = argparse.ArgumentParser(description=DESCRIPTION, + epilog=EPILOG) + # IO arguments + parser.add_argument("-i", "--input", type=str, required=True, + help="Input file, can be a neuroimaging file (e.g., " + ".nii[.gz] or a text file (e.g, .txt, .tsv, " + ".csv) containing the values in a column") + parser.add_argument("-o", "--output", type=str, required=False, + help="Output directory, if not provided, the same of " + "the input file is used") + # Control arguments + parser.add_argument("-r", "--regions", type=str, required=False, + choices=["all", "cort+sub", "cort"], default="all", + help="Regions to be used for the analysis, can be " + "either 'all' (default), 'cort+sub' or 'cort'." + "The behaviour with 'all' is the same as " + "'cort+sub' and will use all regions to perform " + "the analysis, while with 'cort' will use only " + "the cortical regions.") + parser.add_argument("--no-gsea", action="store_false", required=False, + help="If True perform GSEA analysis, otherwise skip.") + parser.add_argument("--geneset", type=str, required=False, default="lake", + help="geneset to use for the GSEA analysis. Can be " + "either 'lake' (default), 'pooled' or any of " + "the genesets included in the gseapy package.") + subparser = parser.add_subparsers(title="method", dest="method") + parse_corr = subparser.add_parser("corr") + parse_corr.add_argument("--cpu", type=int, required=False, default=4, + help="Number of CPUs to use for the analysis.") + parse_pls = subparser.add_parser("pls") + pls_group = parse_pls.add_mutually_exclusive_group(required=True) + pls_group.add_argument("--ncomp", type=int, help="Number of " + "PLS components.") + pls_group.add_argument("--var", type=float, + help="Percentage of variance to extract form " + "the data.") + return parser.parse_args() + + +def main(): + parsed = parse_cmdline() + regions = parsed.regions + gsea = parsed.no_gsea + geneset = parsed.geneset + infile = Path(parsed.input) + input_name = infile.stem + outdir = Path(parsed.output) if parsed.output else infile.parent + if parsed.method == "corr": + if infile.suffix in [".txt", ".tsv", ".csv"]: + transcriptomics = imt.ImagingTranscriptomics.from_file( + infile, + method="corr", + regions=regions) + elif str().join(infile.suffixes) in [ + ".nii", ".nii.gz"]: + transcriptomics = imt.ImagingTranscriptomics.from_scan( + infile, + method="corr", + regions=regions) + n_cpu = parsed.cpu + elif parsed.method == "pls": + pls_arg = { + "n_components": parsed.ncomp, + "var": parsed.var + } + if infile.suffix in [".txt", ".tsv", ".csv"]: + transcriptomics = imt.ImagingTranscriptomics.from_file( + infile, + method="pls", + regions=regions, **pls_arg) + elif str().join(infile.suffixes) in [".nii", ".nii.gz"]: + transcriptomics = imt.ImagingTranscriptomics.from_scan( + infile, + method="pls", + regions=regions, **pls_arg) + n_cpu = 4 + else: + raise ValueError("Method not recognized") + transcriptomics.run(outdir, + scan_name=input_name, + gsea=gsea, + gene_set=geneset, + n_cpu=n_cpu) + # PLOTTING and PDF creation + imt.reporting.make_pdf(transcriptomics_data=transcriptomics, + save_dir=Path(outdir) / f"Imt_{input_name}_" + f"{transcriptomics.method}", + name=str(input_name), + scanname=str(infile.name)) + + +if __name__ == "__main__": + main() diff --git a/imaging_transcriptomics/script/imt_gsea.py b/imaging_transcriptomics/script/imt_gsea.py new file mode 100644 index 0000000..e581c9f --- /dev/null +++ b/imaging_transcriptomics/script/imt_gsea.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 + +import pickle +import argparse +from pathlib import Path +import gseapy +import nibabel.nifti1 + + +def parse_args(): + DESCRIPTION = "" + EPILOG = "" + parser = argparse.ArgumentParser(description=DESCRIPTION, + epilog=EPILOG) + parser.add_argument("-i", "--input", type=str, required=False, + help="Path to the input. This MUST be a pickle file, " + "(i.e. a file ending in .pkl), created by " + "running an imaging transcriptomics " + "analysis with the imagingtranscriptomics " + "script.") + parser.add_argument("-o", "--output", type=str, required=False, + help="Path where the results will be saved. If this " + "is not provided the same path as the input " + "will be used.") + parser.add_argument("-g", "--geneset", type=str, required=False, + default="lake", + help="Name of the gene set to use. Some of the " + "avilable gene sets are:\n" + "- 'lake': \n" + "- 'pooled' \n" + "- 'kegg' \n" + "The 'lake' and 'pooled' gene sets are inluded " + "in the imaging transcriptomics package while " + "all the other gene sets are available in the " + "gseapy package. If you want to see all the " + "available gene sets, please run the " + "'imt_gsea -g avail' command.") + + return parser.parse_args() + + +def main(): + parsed = parse_args() + if parsed.geneset == "avail": + avail_gene_sets = ["lake", "pooled"] + gseapy.get_library_name() + print("The following gene sets are available:") + for gene_set in avail_gene_sets: + print(f"- {gene_set}") + else: + geneset = parsed.geneset + if parsed.input is None: + raise ValueError("Please provide an input file.") + infile = Path(parsed.input) + if not infile.suffix == ".pkl": + raise ValueError("The input file must be a pickle file.") + outdir = Path(parsed.output) if parsed.output else infile.parent + with open(infile, "rb") as f: + transcriptomics = pickle.load(f) + transcriptomics.gsea(outdir=outdir, gene_set=geneset) + + +if __name__ == '__main__': + main() + diff --git a/script/log_config.yaml b/imaging_transcriptomics/script/log_config.yaml similarity index 100% rename from script/log_config.yaml rename to imaging_transcriptomics/script/log_config.yaml diff --git a/tests/bootstrap_test.py b/imaging_transcriptomics/tests/__init__.py similarity index 100% rename from tests/bootstrap_test.py rename to imaging_transcriptomics/tests/__init__.py diff --git a/tests/auto_test.py b/imaging_transcriptomics/tests/auto_test.py similarity index 68% rename from tests/auto_test.py rename to imaging_transcriptomics/tests/auto_test.py index 61473b4..ee750af 100644 --- a/tests/auto_test.py +++ b/imaging_transcriptomics/tests/auto_test.py @@ -12,23 +12,14 @@ def test_version(): def test_modules_import(): """Test that the submodules are all imported correctly.""" imported = dir(imt) - assert "bootstrap" in imported - assert "errors" in imported - assert "genes" in imported assert "inputs" in imported assert "reporting" in imported - assert "transcriptomics" in imported assert "oermutatiuons" not in imported def test_functions_import(): """Test that the functions are imported correctly.""" imported = dir(imt) - assert "bootstrap_pls" in imported - assert "bootstrap_genes" in imported - assert "load_gene_expression" in imported - assert "load_gene_labels" in imported - assert "get_components" in imported assert "read_scan" in imported assert "extract_average" in imported @@ -41,6 +32,7 @@ def test_classes_import(): def test_not_in_module(): - """Test that an error is raised when trying to import a non existing modeule""" + """Test that an error is raised when + trying to import a non existing module""" with pytest.raises(ImportError): from imaging_transcriptomics import outputs diff --git a/imaging_transcriptomics/tests/conftest.py b/imaging_transcriptomics/tests/conftest.py new file mode 100644 index 0000000..34719cd --- /dev/null +++ b/imaging_transcriptomics/tests/conftest.py @@ -0,0 +1,9 @@ +import pytest +import numpy as np +from pathlib import Path + + +@pytest.fixture(scope="session") +def tdata_dir(): + yield Path(__file__).parent / 'data' + diff --git a/imaging_transcriptomics/tests/data/MNI152_T1_1mm.nii.gz b/imaging_transcriptomics/tests/data/MNI152_T1_1mm.nii.gz new file mode 100644 index 0000000..d6ec45e Binary files /dev/null and b/imaging_transcriptomics/tests/data/MNI152_T1_1mm.nii.gz differ diff --git a/tests/data/anatomical.nii b/imaging_transcriptomics/tests/data/anatomical.nii similarity index 100% rename from tests/data/anatomical.nii rename to imaging_transcriptomics/tests/data/anatomical.nii diff --git a/tests/data/example_nifti2.nii.gz b/imaging_transcriptomics/tests/data/example_nifti2.nii.gz similarity index 100% rename from tests/data/example_nifti2.nii.gz rename to imaging_transcriptomics/tests/data/example_nifti2.nii.gz diff --git a/imaging_transcriptomics/tests/data/test_input.txt b/imaging_transcriptomics/tests/data/test_input.txt new file mode 100644 index 0000000..4152e79 --- /dev/null +++ b/imaging_transcriptomics/tests/data/test_input.txt @@ -0,0 +1,41 @@ +-1.635237754 +0.255716141 +-1.018681225 +-0.648232157 +1.972433013 +-0.913493909 +-3.391377792 +-1.354893436 +-0.209065125 +-2.026201134 +-1.619781072 +-1.042303914 +-1.180346914 +-1.983037632 +0.352800321 +-2.005634044 +-0.354617884 +-1.109127894 +-1.81329833 +-0.535985644 +0.390585161 +-0.472059549 +-1.060126275 +-0.513570565 +0.624203987 +-1.204124982 +-2.635143056 +-1.21217398 +-1.925115643 +-0.839038675 +-1.028532407 +0.080350238 +-1.149865812 +0.410996598 +-1.228776992 +0.451691495 +-1.51049856 +0.44416055 +-0.244479445 +-1.903263154 +-1.21203209 diff --git a/tests/data/wrong_format.txt b/imaging_transcriptomics/tests/data/wrong_format.txt similarity index 100% rename from tests/data/wrong_format.txt rename to imaging_transcriptomics/tests/data/wrong_format.txt diff --git a/tests/errors_test.py b/imaging_transcriptomics/tests/errors_test.py similarity index 90% rename from tests/errors_test.py rename to imaging_transcriptomics/tests/errors_test.py index b92a23a..23daa45 100644 --- a/tests/errors_test.py +++ b/imaging_transcriptomics/tests/errors_test.py @@ -29,7 +29,7 @@ def test_check_extension_error(): """Test that the CheckExtension decorator throws the correct error.""" @CheckExtension - def function(path): + def function(path): # pragma: no cover """Dummy function to test the decorator.""" return path @@ -39,8 +39,9 @@ def function(path): assert ( str(ex.value) - == f"The provided file has an invalid format. Please use files in the .nii, .nii.gz format. " - f"The error was caused by the file {test_path.absolute()}/wrong_format.txt." + == f"The provided file has an invalid format. Please use files in " + f"the .nii, .nii.gz format. The error was caused by the file" + f" {test_path.absolute()}/wrong_format.txt." ) @@ -61,7 +62,7 @@ def test_check_shape_error(): matrix = np.zeros((171, 230, 167)) @CheckShape - def function(in_matrix): + def function(in_matrix): # pragma: no cover """Dummy function to test the decorator.""" return in_matrix.shape @@ -89,7 +90,7 @@ def test_check_variance_error(): """Test that the CheckVariance decorator throws the correct error.""" @CheckVariance - def function(var): + def function(var): # pragma: no cover """Dummy function to test the decorator.""" return var + 1 diff --git a/imaging_transcriptomics/tests/inputs_test.py b/imaging_transcriptomics/tests/inputs_test.py new file mode 100644 index 0000000..4f0609b --- /dev/null +++ b/imaging_transcriptomics/tests/inputs_test.py @@ -0,0 +1,101 @@ +import numpy as np +import pytest +from pathlib import Path +import gseapy + +from imaging_transcriptomics.inputs import ( + extract_average, + load_gene_expression, + load_gene_labels, + read_scan, + get_geneset +) +from imaging_transcriptomics.errors import InvalidSizeError, InvalidFormatError + + +# READ SCAN FUNCTION TESTS +def test_read_scan(tdata_dir): + """Test the read scan function.""" + scan = read_scan(tdata_dir / "MNI152_T1_1mm.nii.gz") + assert scan.shape == (182, 218, 182) + assert scan.dtype == np.float64 + + +def test_read_scan_errors(tdata_dir): + """Test the errors given by the read scan function""" + with pytest.raises(FileNotFoundError): + read_scan(tdata_dir / "MNI152_T1_1mm.nii") + with pytest.raises(InvalidFormatError): + read_scan(tdata_dir / "wrong_format.txt") + + +# EXTRACT AVERAGE FUNCTION TESTS +def test_extract_average(): + """Test the extract average function.""" + scan = np.ones((182, 218, 182)) + average = extract_average(scan) + assert average.dtype == np.float64 + assert average.shape == (41,) + np.testing.assert_array_equal(average, np.ones(41)) + + +def test_extract_average_errors(): + """Test the errors given by the extract average function.""" + with pytest.raises(InvalidSizeError): + extract_average(np.ones((182, 218, 182, 1))) + with pytest.raises(InvalidSizeError): + extract_average(np.ones((91, 102, 91))) + + +# LOAD GENE EXPRESSION FUNCTION TESTS +def test_load_gene_expression(): + """Test the load gene expression function.""" + expression = load_gene_expression(regions="all") + assert expression.shape == (41, 15633) + assert expression.dtype == np.float64 + np.testing.assert_almost_equal(expression[0, 0], -.281, decimal=3) + np.testing.assert_almost_equal(expression[34, 18], 1.199, decimal=3) + np.testing.assert_almost_equal(expression[39, 13], -3.201, decimal=3) + + +def test_load_gene_expression_cort(): + expression = load_gene_expression(regions="cort") + assert expression.shape == (34, 15633) + assert expression.dtype == np.float64 + np.testing.assert_almost_equal(expression[0, 0], -.281, decimal=3) + np.testing.assert_almost_equal(expression[32, 18], .473, decimal=3) + + +def test_load_gene_expression_errors(): + """Test the errors given by the load gene expression function.""" + with pytest.raises(ValueError): + load_gene_expression(regions="wrong_region") + + +# LOAD GENE LABELS FUNCTION TESTS +def test_gene_labels_load(): + """Test that the genes labels are loaded correctly.""" + labels = load_gene_labels() + assert labels.shape == (15633, 1) + assert labels[78] == "ABHD6" + assert labels[1635] == "C6orf106" + assert "SLC7A10" in labels + assert "audhd49b" not in labels + + +# GENESET FUNCTION TESTS +def test_get_geneset(): + """Test the geneset function.""" + geneset = get_geneset("lake") + assert isinstance(geneset, str) + assert Path(geneset).exists() + geneset = get_geneset("pooled") + assert isinstance(geneset, str) + assert Path(geneset).exists() + geneset = get_geneset("POOLed") + assert isinstance(geneset, str) + assert Path(geneset).exists() + geneset = get_geneset("GO_Biological_Process_2017") + assert isinstance(geneset, str) + assert geneset in gseapy.get_library_name() + diff --git a/imaging_transcriptomics/tests/transcriptomics_test.py b/imaging_transcriptomics/tests/transcriptomics_test.py new file mode 100644 index 0000000..52a4158 --- /dev/null +++ b/imaging_transcriptomics/tests/transcriptomics_test.py @@ -0,0 +1,153 @@ +from pathlib import Path +import numpy as np +import pytest +import imaging_transcriptomics as imt +from scipy.stats import zscore + + +# INITIALIZATION TESTS +def test_init_transcriptomics_corr(): + """ + Test the initialization of a transcriptomics object. + """ + # Test with all regions (cort + sub) + data = np.random.rand(41) + imt_instance = imt.ImagingTranscriptomics(data, regions="all", + method="corr") + assert isinstance(imt_instance, imt.ImagingTranscriptomics) + assert imt_instance._regions == "all" + assert imt_instance._method == "corr" + assert imt_instance.scan_data.shape == (41,) + assert imt_instance.scan_data.dtype == np.float64 + np.testing.assert_array_almost_equal(imt_instance._cortical, zscore(data, + ddof=1)[:34]) + assert imt_instance.zscore_data.shape == (41,) + assert imt_instance._permutations is None + # Test with only cortical regions + data = np.random.rand(34) + imt_instance = imt.ImagingTranscriptomics(data, regions="cort", + method="corr") + assert isinstance(imt_instance, imt.ImagingTranscriptomics) + assert imt_instance._regions == "cort" + assert imt_instance._method == "corr" + assert imt_instance.scan_data.shape == (34,) + assert imt_instance.scan_data.dtype == np.float64 + assert imt_instance._subcortical is None + np.testing.assert_array_almost_equal(imt_instance._cortical, zscore( + data, ddof=1)) + assert imt_instance.zscore_data.shape == (34,) + assert imt_instance._permutations is None + + +def test_init_transcriptomics_pls(): + """ + Test the initialization of a transcriptomics object. + """ + # Test with a all regions (cort + sub) + data = np.random.rand(41) + imt_instance = imt.ImagingTranscriptomics(data, regions="all", + method="pls", n_components=1) + assert isinstance(imt_instance, imt.ImagingTranscriptomics) + assert imt_instance._regions == "all" + assert imt_instance._method == "pls" + assert imt_instance.scan_data.shape == (41,) + assert imt_instance.scan_data.dtype == np.float64 + np.testing.assert_array_almost_equal(imt_instance._cortical, zscore( + data, ddof=1)[:34]) + assert imt_instance.zscore_data.shape == (41,) + assert imt_instance._permutations is None + # Test with only cortical regions + data = np.random.rand(41) + imt_instance = imt.ImagingTranscriptomics(data, regions="cort", + method="pls", n_components=1) + assert isinstance(imt_instance, imt.ImagingTranscriptomics) + assert imt_instance._regions == "cort" + assert imt_instance._method == "pls" + assert imt_instance.scan_data.shape == (41,) + assert imt_instance.scan_data.dtype == np.float64 + assert imt_instance._subcortical is None + assert imt_instance.zscore_data.shape == (41,) + assert imt_instance._permutations is None + + +def test_wrong_method(): + """ + Test the initialization of a transcriptomics object with a wrong method. + """ + data = np.random.rand(41) + with pytest.raises(ValueError): + imt.ImagingTranscriptomics(data, regions="all", method="wrong") + + +def test_missing_pls_argument(): + """ + Test the initialization of a transcriptomics object with a wrong method. + """ + data = np.random.rand(41) + with pytest.raises(ValueError): + imt.ImagingTranscriptomics(data, regions="all", method="pls") + + +def test_from_scan_init(tdata_dir): + scan = tdata_dir / "MNI152_T1_1mm.nii.gz" + imt_instance = imt.ImagingTranscriptomics.from_scan(scan, regions="all", + method="corr") + assert isinstance(imt_instance, imt.ImagingTranscriptomics) + with pytest.raises(ValueError): + imt.ImagingTranscriptomics.from_scan(scan, regions="all", + method="pca") + with pytest.raises(ValueError): + imt.ImagingTranscriptomics.from_scan(scan, regions="none", + method="corr") + + +def test_from_scan_errors(tdata_dir): + scan = tdata_dir / "MNI152_T1_1mm_brain.nii.gz" + with pytest.raises(FileNotFoundError): + imt.ImagingTranscriptomics.from_scan(scan, regions="all", + method="corr") + + +def test_from_file_init(tdata_dir): + file = tdata_dir / "test_input.txt" + imt_instance = imt.ImagingTranscriptomics.from_file(file, regions="all", + method="corr") + assert isinstance(imt_instance, imt.ImagingTranscriptomics) + with pytest.raises(ValueError): + imt.ImagingTranscriptomics.from_file(tdata_dir, regions="all", + method="corr") + with pytest.raises(FileNotFoundError): + imt.ImagingTranscriptomics.from_file(tdata_dir / "new_file.txt", + regions="none", method="corr") + + +def test_permute_data(): + """Test the permutations method.""" + data = np.random.rand(41) + imt_instance = imt.ImagingTranscriptomics(data, regions="all", + method="pls", n_components=1) + assert imt_instance._permutations is None + imt_instance.permute_data() + assert imt_instance._permutations is not None + assert imt_instance._permutations.shape == (41, 1000) + assert imt_instance._permutations.dtype == np.float64 + + +def test_permute_data_with_cort(): + """Test the permutations method.""" + data = np.random.rand(34) + imt_instance = imt.ImagingTranscriptomics(data, regions="cort", + method="pls", n_components=1) + imt_instance.permute_data() + assert imt_instance._permutations.shape == (34, 1000) + assert imt_instance._permutations.dtype == np.float64 + + +def test_make_out_dir(tmpdir): + """Test the make_out_dir method.""" + out_dir = tmpdir / "Imt_test_pls" + imt_instance = imt.ImagingTranscriptomics(np.random.rand(41), + regions="all", method="pls", + n_components=1) + imt_instance._make_output_dir(tmpdir, "test") + assert out_dir.exists() diff --git a/imaging_transcriptomics/transcriptomics.py b/imaging_transcriptomics/transcriptomics.py index 244e433..2c1cf9c 100644 --- a/imaging_transcriptomics/transcriptomics.py +++ b/imaging_transcriptomics/transcriptomics.py @@ -2,19 +2,20 @@ import logging import warnings from pathlib import Path +import pickle import numpy as np -import pandas as pd import yaml -from pyls import pls_regression -from scipy.stats import zscore, spearmanr +from scipy.stats import zscore with warnings.catch_warnings(): warnings.filterwarnings("ignore") from netneurotools import freesurfer, stats -from .inputs import load_gene_expression, load_gene_labels, get_components -from .bootstrap import bootstrap_pls, bootstrap_genes, bootstrap_correlation +from .inputs import load_gene_expression, load_gene_labels, \ + extract_average, read_scan +from .pls import PLSAnalysis +from .corr import CorrAnalysis cfg_file_path = Path(__file__).parent / "log_config.yaml" with open(cfg_file_path, "r") as config_file: @@ -26,114 +27,165 @@ class ImagingTranscriptomics: - def __init__(self, scan_data, **kwargs): - """Initialise the imaging transcriptomics class with the input scan's data and number of components or variance - explained. + # --------- INITIALIZATION --------- # + def __init__(self, + scan_data, + regions="cort+sub", + method="pls", + **kwargs): + """ImagingTranscriptomics class for imaging transcriptomics analysis. - :param array-like scan_data: average values in the ROI defined by the Desikan-Killiany atlas. - :param int n_components: number of components to use for the PLS regression. - :param int variance: total explained variance by the PLS components. - """ - logger.debug("Initializing ImagingTranscriptomics class.") - self.scan_data = self.check_input_length(scan_data) - self.zscore_data = zscore(scan_data, ddof=1, axis=0) - self.n_components = self.check_in_components(kwargs.get("n_components")) - self.var = self.check_in_var(kwargs.get("variance")) - self.check_var_or_comp(self.var, self.n_components) - self._cortical = self.zscore_data[0:34].reshape(34, 1) - self._subcortical = self.zscore_data[34:].reshape(7, 1) - self._gene_expression = load_gene_expression() - self._gene_labels = load_gene_labels() - # Initialise with defaults for later - self.permuted = None - self.r_boot = None - self.p_boot = None - self.gene_results = None - self.var_components = None - logger.debug("ImagingTranscriptomics class successfully initialized.") - - @staticmethod - def check_input_length(data): - """Check that the length of the data given as input is correct in length (41). + :param np.array scan_data: imaging scan data. + :param str regions: regions to be used for analysis. These can be + "cort+sub" (or "all") which will perform the analysis on the + cortical and subcortical regions, or "cort" which will only perform + the analysis on the cortical regions. + :param str method: method to run the analysis, can be either "pls" + for pls regression or "corr" cor simple correlation analysis. + :param kwargs: additional arguments for the method. This include: + * "n_components": number of components for pls regression. + * "var": variance explained for pls regression. + * "n_permutations": number of permutations for permutation test. - :param data: array to check has the correct length. - :raises AttributeError: if the length of the data is not 41. - :return: data if it has correct length. """ - if not len(data) == 41: - raise AttributeError( - "The data must have a length of 41, corresponding to the number of regions in the " - "left brain hemisphere!" + if regions == "cort+sub" or regions == "all": + assert scan_data.shape == (41,) + self.zscore_data = zscore(scan_data, axis=0, ddof=1) + self._cortical = self.zscore_data[:34] + self._subcortical = self.zscore_data[34:] + elif regions == "cort": + assert scan_data.shape == (34,) or scan_data.shape == (41,) + self.zscore_data = zscore(scan_data, axis=0, ddof=1) + self._cortical = self.zscore_data if scan_data.shape == (34,) else\ + self.zscore_data[:34] + self._subcortical = None + self._regions = regions + self.scan_data = scan_data + self.gene_expression = load_gene_expression(self._regions) + self.gene_labels = load_gene_labels() + if method not in ["pls", "corr"]: + raise ValueError( + "The method must be either pls or corr." + "Please choose either pls or corr to run the analysis." ) - return data - - @staticmethod - def check_in_var(variance): - """Check if the variance given as input is in the correct range. + else: + self._method = method + if self._method == "pls": + if "n_components" not in kwargs and "var" not in kwargs: + raise ValueError("You must specify either the variance or " + "the number of components for pls regression") + else: + if self._regions == "all" or self._regions == "cort+sub": + self.analysis = PLSAnalysis(self.zscore_data, + self.gene_expression, + kwargs.get("n_components"), + kwargs.get("var")) + else: + self.analysis = PLSAnalysis(self._cortical, + self.gene_expression, + kwargs.get("n_components"), + kwargs.get("var")) + elif self._method == "corr": + self.analysis = CorrAnalysis() + self._permutations = None + self._permutation_ind = None - The variance can be in the range 0-100. If the variance is greater than 1 the value is divided by 100. - If the variance is None it will be kept as is. + @classmethod + def from_scan(cls, scan_path, method="pls", regions="cort+sub", **kwargs): + """Initialise an ImagingTranscriptomics object from a NIfTI scan. + The extracted data corresponds to the average of the ROIs in the DK + atlas. - :param variance: input variance to check. - :raises ValueError: if below 0 ir greater than 100. - :return: variance if correct. + :param str scan_path: path to the NIfTI scan. + :param str method: method to run the analysis, can be either "pls" + for pls regression or "corr" cor simple correlation analysis. + :param str regions: regions to be used for analysis. These can be + "cort+sub" (or "all") which will perform the analysis on the + cortical and subcortical regions, or "cort" which will only perform + the analysis on the cortical regions. + :param kwargs: additional arguments for the method. This include: + * "n_components": number of components for pls regression. + * "var": variance explained for pls regression. + * "n_permutations": number of permutations for permutation test. + :return: ImagingTranscriptomics object. """ - if variance is None: - return variance - elif 0.0 <= variance <= 1.0: - return variance - elif 1.0 < variance < 100: - logger.warning( - "The variance inputted was in the range 1-100. It has been converted to the range 0.0-1.0" + if not Path(scan_path).exists(): + raise FileNotFoundError("The specified scan file does not exist.") + if method not in ["pls", "corr"]: + raise ValueError( + "The method must be either pls or corr." + "Please choose either pls or corr to run the analysis." + ) + if regions not in ["cort+sub", "cort", "all"]: + raise ValueError( + "The regions must be either cort+sub, cort or all." + "Please choose one of these to run the analysis." ) - return variance / 100 - elif variance < 0.0: - raise ValueError("The input variance cannot be negative!") - elif variance > 100: - raise ValueError("The input variance is too big!") - elif isinstance(variance, str): - raise TypeError("Strings are not supported, please input a numeric value!") + scan_data = extract_average(read_scan(scan_path)) + return cls(scan_data, method=method, regions=regions, **kwargs) - @staticmethod - def check_in_components(components): - """Check if the number of components given as input is in the range 1-15 + @classmethod + def from_file(cls, file_path, method="pls", regions="cort+sub", **kwargs): + """Initialise an ImagingTranscriptomics object from a text file. + The file should contain a column with the data you want to use for + the analysis. - :param components: number of components given as input. - :raises ValueError: if the component is not in the range 1-15 or None. - :return: the number of components if correct. + :param str file_path: path to the text file. The text file should + contain a column with the data you want to use for the analysis. + :param str method: method to run the analysis, can be either "pls" + for pls regression or "corr" cor simple correlation analysis. + :param str regions: regions to be used for analysis. These can be + "cort+sub" (or "all") which will perform the analysis on the + cortical and subcortical regions, or "cort" which will only perform + the analysis on the cortical regions. + :param kwargs: additional arguments for the method. This include: + * "n_components": number of components for pls regression. + * "var": variance explained for pls regression. + * "n_permutations": number of permutations for permutation test. + :return: ImagingTranscriptomics object. """ - if components is None: - return components - elif 1 <= components <= 15: - return components - else: - raise ValueError("The number of components MUST be in the range 1-15.") + if not Path(file_path).exists(): + raise FileNotFoundError("The specified file does not exist.") + if not Path(file_path).is_file(): + raise ValueError(f"{file_path} is not a file.") + scan_data = np.loadtxt(file_path) + if scan_data.shape[0] > 41: + scan_data = scan_data[:41] + return cls(scan_data, method=method, regions=regions, **kwargs) - @staticmethod - def check_var_or_comp(variance, components): - if variance is None and components is None: - raise AttributeError( - "You must set either the variance or the number of components!" - ) + # --------- PROPERTIES --------- # + @property + def method(self): # pragma: no cover, simply returns stuff + return self._method + + @property + def gene_results(self): # pragma: no cover, simply returns stuff + return self.analysis.gene_results - def permute_data(self, iterations=1_000): - """Permute the scan data for the analysis. + # --------- METHODS --------- # + def permute_data(self, n_permutations=1000): + """Permute the imaging data maintaining spatial autocorrelation for + the cortical regions. The permutation is done using the + netneurotools Python package. - The permutations are computed into cortical and subcortical regions separately and then merged. This is done - to maintain the spatial autocorrelation in the cortical regions for more accuracy. - To compute the cortical permutations the library python package ``netneurotools`` developed by R. Markello is - used. For more information about the methods used you can refer to the official `documentation of the - package. _` + :param int n_permutations: number of permutations. - :param int iterations: number of iterations to perform in the permutations. """ - self.permuted = np.zeros((self.zscore_data.shape[0], iterations)) - # subcortical - logger.debug("Starting permutations.") - sub_permuted = np.array( - [np.random.permutation(self._subcortical) for _ in range(iterations)] - ).reshape(7, iterations) - self.permuted[34:, :] = sub_permuted + logger.info("Permuting data.") + _permuted = np.zeros((self.zscore_data.shape[0], n_permutations)) + _perm_indexes = np.zeros((self.zscore_data.shape[0], + n_permutations), dtype=np.int32) + # Calculate the permutations on the subcortical regions. + if self._subcortical is not None: + sub_permuted = np.zeros((self._subcortical.shape[0], + n_permutations)) + for i in range(n_permutations): + sub_resample = np.random.choice(7, size=7) + _perm_indexes[34:, i] = sub_resample + 34 # keep into + # account the shift of the subcortical given by the cortical + # regions. + sub_permuted[:, i] = self._subcortical[sub_resample] + _permuted[34:, :] = sub_permuted # Cortical # Annotation file for the Desikan-Killiany atlas in fs5 annot_lh = Path(__file__).resolve().parent / "data/fsa5_lh_aparc.annot" @@ -154,120 +206,122 @@ def permute_data(self, iterations=1_000): ) # Get the spin samples spins = stats.gen_spinsamples( - parcel_centroids, parcel_hemi, n_rotate=iterations, method="vasa", seed=1234 + parcel_centroids, parcel_hemi, + n_rotate=n_permutations, + method="vasa", + seed=1234 ) - cort_permuted = np.array(self._cortical[spins]).reshape(34, iterations) - self.permuted[0:34, :] = cort_permuted - logger.debug("End permutations.") + cort_permuted = np.array(self._cortical[spins]).reshape(34, + n_permutations) + _perm_indexes[:34, :] = spins + _permuted[0:34, :] = cort_permuted + self._permutations = _permuted + self._permutation_ind = _perm_indexes + return - def save_permutations(self, path): - """Save the permutations to a csv file at a specified path. + def _make_output_dir(self, output_dir, name=""): + """Create the output directory if it does not exist. - :param path: Path used to save the permutations, this *should* also include the name of the file, e.g., - "~/Documents/my_permuted.csv" + :param str output_dir: path to the output directory. + :param str name: name of the output directory, if not provided + disregard. """ - if self.permuted is None: - raise AttributeError( - "There are no permutations of the scan available to save. Before saving the " - "permutations you need to compute them." - ) - logger.info("Saving permutations to file %s", path) - pd.DataFrame(self.permuted).to_csv(Path(path), header=None, index=False) + outdir = Path(output_dir) / f"Imt_{name}_{self.method}" + outdir.mkdir(exist_ok=True) + return outdir - def correlation(self): - """Calculate the correlation between the imaging and genetic data. + def _save_object(self, outdir, name): + """Save the object as a pickle file. - :return corr_genes: pearson correlation coefficient ordered in - descending order. - :return corr_gene_labels: labels of the genes ordered by correlation coefficient. + :param str outdir: path to the output directory. + :param str name: name of the output file. """ - corr_ = np.zeros(self._gene_expression.shape[1]) - p_val = np.zeros(self._gene_expression.shape[1]) - for gene in range(15633): - corr_[gene], p_val[gene] = spearmanr( - self.zscore_data, self._gene_expression[:, gene] - ) - corr_genes = np.sort(corr_) - corr_gene_labels = self._gene_labels[np.argsort(corr_)] - return corr_genes, corr_gene_labels + outfile = Path(outdir) / f"{name}.pkl" + with open(outfile, "wb") as f: + pickle.dump(self, f) + return - def pls_all_components(self): - """Compute a PLS regression with all components. + # --------- RUN ANALYSIS --------- # + def gsea(self, outdir=None, gene_set="lake"): + if self.method == "corr": + self.analysis.gsea(gene_set=gene_set, outdir=outdir) + elif self.method == "pls": + self.gene_results.results.gsea(gene_set=gene_set, + outdir=outdir) - After the regression is estimated, either the number of components or the estimated percentage of variance - given by the components is estimated, depending on what is set by the user in the __init__() method. - """ - logger.debug("Performing PLS with all 15 components.") - results = pls_regression( - self._gene_expression, - self.zscore_data.reshape(41, 1), - n_components=15, - n_perm=0, - n_boot=0, - ) - var_exp = results.get("varexp") - if self.n_components is None and self.var != 0.0: - self.n_components = get_components(self.var, var_exp) - logger.debug("Number of components has been set to: %s", self.n_components) - elif self.var is None and self.n_components != 0: - self.var = np.cumsum(var_exp)[self.n_components - 1] - logger.debug( - "Variance has been set to: %s", self.var - ) # add number of variance set - self.var_components = var_exp + def run(self, outdir=None, scan_name="", gsea=True, + gene_set="lake", save_res=True, n_cpu=4): # pragma: no cover + """Method to run the imaging transcriptomics analysis. - def run(self, n_iter=1_000, method="pls"): - """Run the analysis of the imaging scan. - - :param int n_iter: number of permutations to make. - :param str method: method to run the analysis, can be either "pls" - for pls regression or "corr" cor simple correlation analysis. + :param str outdir: path to the output directory, if not provided the + results will be saved in the current directory. + :param str scan_name: name of the scan, if not provided the name will + be ignored. Is used only to create the output directory. + :param bool gsea: if True, run the GSEA analysis, if False the GSEA + analysis is skipped. + :param str gene_set: gene set to use for the GSEA analysis. + :param bool save_res: if True, save the results in a directory, + if False the results are not saved. + :param int n_cpu: number of CPUs to use for the analysis (only for + correlation analysis). """ - logger.info("Starting imaging transcriptomics analysis.") - if method is "pls": - logger.info("Running analysis with PLS regression") - self.pls_all_components() - self.permute_data(iterations=n_iter) - self.r_boot, self.p_boot = bootstrap_pls( - self._gene_expression, - self.zscore_data.reshape(41, 1), - self.permuted, - self.n_components, - iterations=n_iter, - ) - self.gene_results = bootstrap_genes( - self._gene_expression, - self.zscore_data.reshape(41, 1), - self.n_components, - self.scan_data, - self._gene_labels, - n_iter, - ) - self.gene_results.boot_results.compute_values( - self.n_components, - self.gene_results.original_results.pls_weights, - self.gene_results.original_results.pls_gene, - ) - elif method is "corr": - logger.info("Running analysis with correlation.") - # run first analysis - self.permute_data(iterations=n_iter) - # bootstrap analysis - self.gene_results = bootstrap_correlation( - self.zscore_data, - self._gene_expression, - self.permuted, - self._gene_labels, - ) - self.gene_results.boot_results.compute_correlation( - self.gene_results.original_results.pls_weights, - self.gene_results.original_results.pls_gene, - self.gene_results.original_results.gene_id, - ) - else: - raise NotImplementedError( - f"The method {method} does not exist. " - f"Please choose either pls or corr as " - f"method to run the analysis." - ) - logger.info("Imaging transcriptomics analysis completed.") + logger.info(f"Running the {self.method} analysis.") + # Create the permuted data matrix + self.permute_data() + # Check if the ouput directory is provided and create the output folder + if save_res: + if outdir is not None: + outdir = self._make_output_dir(outdir, name=scan_name) + else: + outdir = self._make_output_dir(Path.cwd(), name=scan_name) + # Run the analysis + # CORRELATION + if self._method == "corr": + # Select the data or slice of data + if self._regions == "cort": + _d = self._cortical + if self._permutations.shape[0] == 41: + _d_perm = self._permutations[0:34, :] + else: + _d_perm = self._permutations + elif self._regions == "cort+sub" or self._regions == "all": + _d = self.zscore_data + _d_perm = self._permutations + self.analysis.bootstrap_correlation(_d, _d_perm, + self.gene_expression, + self.gene_labels, + n_cpu=n_cpu) + if save_res: + self.analysis.save_results(outdir=outdir) + if gsea: + self.gsea(gene_set=gene_set, outdir=outdir) + # PLS + elif self._method == "pls": + # Select the data or slice of data + if self._regions == "cort": + _d = self._cortical + if self._permutations.shape[0] == 41: + _d_perm = self._permutations[0:34, :] + else: + _d_perm = self._permutations + elif self._regions == "cort+sub" or self._regions == "all": + _d = self.zscore_data + _d_perm = self._permutations + assert isinstance(self.analysis, PLSAnalysis) + self.analysis.boot_pls(_d, _d_perm, self.gene_expression) + if self._regions == "cort": + _orig = self.scan_data if self.scan_data.shape[0] == 34 else \ + self.scan_data[0:34, :] + elif self._regions == "cort+sub" or self._regions == "all": + _orig = self.scan_data + self.gene_results.results.boot_genes(_d, + _d_perm, + _orig, + self.gene_expression, + self.gene_labels) + self.gene_results.results.compute() + if save_res: + self._save_object(outdir, f"{self.method}_analysis") + self.analysis.save_results(outdir=outdir) + if gsea: + self.gsea(gene_set=gene_set, outdir=outdir) diff --git a/pytest.ini b/pytest.ini index 38c5da0..a99a03d 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,14 @@ [pytest] - +minversion = 3.0 testpaths = - tests + imaging_transcriptomics/tests + +[tool: pytest] +norecursedirs = + src/*pyls* + imaging_transcriptomics/reporting.py + imaging_transcriptomics/pls.py + imaging_transcriptomics/corr.py + imaging_transcriptomics/genes.py + imaging_transcriptomics/scripts/* + diff --git a/requirements.txt b/requirements.txt index 186aca9..14029b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,3 +13,4 @@ nibabel==3.2.1 matplotlib==3.4.2 netneurotools>=0.2.2 fpdf2>=2.0.0 +gseapy==0.10.7 diff --git a/script/imagingtranscriptomics b/script/imagingtranscriptomics deleted file mode 100644 index 4793160..0000000 --- a/script/imagingtranscriptomics +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 - -import logging -import logging.config -import argparse -from pathlib import Path - -import imaging_transcriptomics -from imaging_transcriptomics import reporting - - -def get_args(): - """Return the args parsed from the command line. - - Reads the command line and parses the possible inputs for a match. The available inputs are: - * input: path of the input file to analyze. - * output (optional): path where to save the results. - * ncomp: number of components to use for PLS regression. - * variance: percentage of variance to extract by the PLS components. - - :return: Data structure with all args parsed from the command line. - """ - DESCRIPTION = ( - """Perform imaging transcriptomics analysis on a neuroimaging scan. """ - ) - EPILOG = """Check your results in the specified folder or in the file path of the input scan, if you have not - specified an output path. If you used this software in your research please cite: - * Imaging transcriptomics: **Convergent cellular, transcriptomic, and molecular neuroimaging signatures in the - healthy adult human brain.** - *Daniel Martins, Alessio Giacomel, Steven CR Williams, Federico E Turkheimer, Ottavia Dipasquale, Mattia Veronese, - PET templates working group*; bioRxiv 2021.06.18.448872; doi: `https://doi.org/10.1101/2021.06.18.448872 - `_ """ - - parser = argparse.ArgumentParser(description=DESCRIPTION, epilog=EPILOG) - - parser.add_argument( - "-i", - "--input", - type=str, - help=( - "Input imaging file in NIfTI format (.nii, .nii.gz).\n" - "The input file is expected to have the same matrix size as the atlas used (182x218x182)," - "if the input image has different matrix size this can be resliced to match the" - "resolution of the MNI152 1mm template matrix size (e.g. the one provided with FSL)." - ), - required=True, - ) - parser.add_argument( - "-o", - "--out", - type=str, - help="Path where to save the output, if not specified the path of the path of the input scan " - "is used.", - required=False, - ) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument( - "-n", - "--ncomp", - type=int, - help="Number of PLS components to use. The number of components has to be between 1 and 15.", - ) - group.add_argument( - "-v", - "--variance", - help="""Variance explained by the components. The variance input should be between 10 and - 100, and the program will select the number of components that explain a variance closest to - the desired (with the explained variance used as a minimum). """, - ) - group.add_argument("--corr", action="store_true", help="run with the correlation " - "method") - verbosity = parser.add_mutually_exclusive_group(required=False) - verbosity.add_argument( - "--suppress", - action="store_true", - help="Suppress the log on console. Only shows WARNINGS if present.", - ) - verbosity.add_argument( - "--verbose", - action="store_true", - help="Show all logging messages from the script.", - ) - return parser.parse_args() - - -def set_log_level(inputs): - """Set the logging level based on the input form the user. - - :param inputs: Inputs read from the CLI (from argparse.parse_args()) - - :return logger: Logger to use for the script execution. - """ - if inputs.verbose: - logger_name = "verbose" - elif inputs.suppress: - logger_name = "suppress" - else: - logger_name = "info" - return logger_name - - -def main(): - - inputs = get_args() - logger_name = set_log_level(inputs) - logger = logging.getLogger(logger_name) - input_path = Path(inputs.input) - data_to_analyse = imaging_transcriptomics.inputs.extract_average( - imaging_transcriptomics.inputs.read_scan(input_path) - ) - # Don't check inputs as checks are in the initialization of the analysis! - n_comp = 1 if inputs.corr else inputs.ncomp - initial_dict = {"variance": inputs.variance, "n_components": n_comp} - - # Get IO paths to save files - if not inputs.out: - save_dir = input_path.absolute().parent - else: - save_dir = Path(inputs.out) - scan_name = input_path.name.split(".")[0] - - save_dir = reporting.make_folder(save_dir, f"Imt_{scan_name}") - file_handler = logging.FileHandler(save_dir / "logs.log", "a") - logger.addHandler(file_handler) - logger.info("Setting up analysis ...") - analysis = imaging_transcriptomics.ImagingTranscriptomics( - data_to_analyse, **initial_dict - ) - logger.info("Running analysis.") - _method = "corr" if inputs.corr else "pls" - analysis.run(method=_method) - - # Save the results - if not inputs.corr: - reporting.make_plots(save_dir, analysis.n_components, analysis.var_components) - reporting.create_pdf(input_path, save_dir) - reporting.create_csv(analysis.gene_results, analysis.n_components, save_dir) - - -if __name__ == "__main__": - main() diff --git a/setup.py b/setup.py index f16fdae..fc121ba 100644 --- a/setup.py +++ b/setup.py @@ -40,8 +40,9 @@ def get_requirements(): author="Alessio Giacomel, Daniel Martins", author_email="alessio.giacomel@kcl.ac.uk , daniel.martins@kcl.ac.uk", version=get_version_number(), - url="https://github.com/alegiac95/imt", - description="A package to perform imaging transcriptomics on a neuroimaging brain scan.", + url="https://github.com/alegiac95/Imaging-transcriptomics", + description="A package to perform imaging transcriptomics analysis on a " + "neuroimaging brain scan.", license="GPLv3", long_description=read_long_description(), long_description_content_type="text/markdown", @@ -53,12 +54,20 @@ def get_requirements(): "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", ], - keywords="Image analysis, Neuroimaging, Imaging Transcriptomics, Medical Imaging, Research, Multimodal Imaging", + keywords="Image analysis, Neuroimaging, Imaging Transcriptomics, " + "Medical Imaging, Research, Multimodal Imaging", install_requires=get_requirements(), packages=["imaging_transcriptomics"], include_package_data=True, - package_data={"imaging_transcriptomics": ["*.yaml", "*.nii.gz", "*.csv", "*.txt", "*.annot"]}, - scripts=glob("script/imagingtranscriptomics"), + package_data={"imaging_transcriptomics": ["*.yaml", "*.nii.gz", + "*.csv", "*.txt", "*.annot"]}, + entry_points={ + "console_scripts": [ + "imagingtranscriptomics=imaging_transcriptomics.script" + ".imagingtranscriptomics:main", + "imt_gsea=imaging_transcriptomics.script.imt_gsea:main", + ] + }, project_urls={ "Source": "https://github.com/alegiac95/Imaging-transcriptomics", "Bug Reports": "https://github.com/alegiac95/Imaging-transcriptomics/issues", diff --git a/tests/genes_test.py b/tests/genes_test.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/inputs_test.py b/tests/inputs_test.py deleted file mode 100644 index 575415c..0000000 --- a/tests/inputs_test.py +++ /dev/null @@ -1,61 +0,0 @@ -import numpy as np -import pytest - -from imaging_transcriptomics.inputs import ( - extract_average, - get_components, - load_gene_expression, - load_gene_labels, -) - - -# def test_read_scan(): -# """Test that an imaging scan is red correctly.""" -# pass - - -def test_get_components(): - """Test that the returned number of components is correct.""" - test_variance = np.array([0.5, 0.1, 0.18, 0.22]) - assert get_components(0.50, test_variance) == 1 - assert get_components(0.60, test_variance) == 2 - assert get_components(0.61, test_variance) == 3 - assert get_components(1.00, test_variance) == 4 - - -def test_get_components_error(): - """Test if the get_components() function raises the correct error.""" - test_variance = np.array([0, 0, 0]) - with pytest.raises(ValueError): - get_components(1.1, test_variance) - with pytest.raises(ValueError): - get_components(-0.1, test_variance) - - -def test_extract_average(): - """Test that the extracted average from a scan is correct.""" - test_matrix = np.ones((182, 218, 182)) - - np.testing.assert_equal(extract_average(test_matrix), np.ones(41)) - - -def test_extract_average_len(): - """Test that the length of the returned object has the correct length (41).""" - test_matrix = np.zeros((182, 218, 182)) - assert len(extract_average(test_matrix)) == 41 - - -def test_gene_expression_load(): - """Test that the genes expression data are loaded correctly.""" - genes = load_gene_expression() - assert genes.shape == (41, 15633) - - -def test_gene_labels_load(): - """Test that the genes labels are loaded correctly.""" - labels = load_gene_labels() - assert labels.shape == (15633, 1) - assert labels[78] == "ABHD6" - assert labels[1635] == "C6orf106" - assert "SLC7A10" in labels - assert "audhd49b" not in labels # just some randoms string to mimic a gene. diff --git a/tests/transcriptomics_test.py b/tests/transcriptomics_test.py deleted file mode 100644 index 0b17ad5..0000000 --- a/tests/transcriptomics_test.py +++ /dev/null @@ -1,120 +0,0 @@ -from pathlib import Path -import numpy as np -import pytest -import imaging_transcriptomics as imt - - -# INITIALIZATION TESTS -def test_init_basic(): - """Test basic initialisation method.""" - test_param = {"n_components": 3, "variance": None} - data = np.ones(41) - t = imt.ImagingTranscriptomics(data, **test_param) - t_z_scores = np.empty(41) - t_z_scores[:] = np.NaN - assert t.n_components == 3 - assert t.var is None - np.testing.assert_equal(t.zscore_data, t_z_scores) - - -def test_init_error_components(): - """Test that the initialisation with components in the wrong range raises a ValueError.""" - t_param_err = [16, 0] - for test in t_param_err: - with pytest.raises(ValueError): - imt.ImagingTranscriptomics(np.ones(41), n_components=test) - - -def test_init_error_variance(): - """Test that variance in the wrong range or with wrong type raises a ValueError.""" - t_param_err = [-1.0, 101] - for test in t_param_err: - with pytest.raises(ValueError): - imt.ImagingTranscriptomics(np.ones(41), variance=test) - test = "a" - with pytest.raises(TypeError): - imt.ImagingTranscriptomics(np.ones(41), variance=test) - - -def test_init_missing_attribute_error(): - """Test that an AttributeError is raised when both number of components and variance are missing.""" - with pytest.raises(AttributeError): - imt.ImagingTranscriptomics(np.ones(41)) - - -def test_init_length_error(): - """Test an AttributeError is raised when the length of input data is different from 41""" - test_param = {"n_components": 3, "variance": None} - with pytest.raises(AttributeError): - imt.ImagingTranscriptomics(np.ones(43), **test_param) - imt.ImagingTranscriptomics(np.ones(40), **test_param) - - -# METHODS TESTS -def test_permutations(): - """Test the permutations are computed correctly.""" - t_data = np.array( - [ - 2.49176123, - 2.12076098, - 1.88912675, - 2.29363057, - 2.17108429, - 2.44944779, - 1.9532944, - 2.13951822, - 1.81947959, - 1.58996705, - 1.91860982, - 2.30857561, - 2.39706742, - 2.03412347, - 2.0920649, - 1.89473161, - 2.05717326, - 1.20646305, - 1.72044527, - 2.0083166, - 1.66318842, - 2.06091217, - 1.72413881, - 2.33628019, - 2.61411213, - 1.807411, - 1.96163793, - 1.85169722, - 2.11455623, - 1.92936416, - 1.28974378, - 1.81579151, - 2.66449885, - 2.67599858, - 1.13808303, - 1.40784474, - 2.70367057, - 2.00515875, - 2.49107748, - 1.75756543, - 2.29094877, - ] - ) - test = imt.ImagingTranscriptomics(t_data, n_components=1) - assert test.permuted is None - test.permute_data(10) - assert test.permuted.shape == (41, 10) - assert np.unique(test.permuted, axis=0).shape[1] == 10 - - -def test_saving_error(): - """Test that the save_permutations() method raises an error if no permutations are available.""" - test = imt.ImagingTranscriptomics(np.zeros(41), n_components=1) - with pytest.raises(AttributeError): - test.save_permutations(Path().cwd()) - - -def test_correlation(): - """Test the correlation method is performing correctly.""" - test = imt.ImagingTranscriptomics(np.random.rand(41), n_components=1) - genes, labels = test.correlation() - assert genes.shape == (15633,) - assert labels.shape == (15633,1)