From 62fe487010678c43b580d0d7e85d6fff7762e42f Mon Sep 17 00:00:00 2001 From: SarahOuologuem Date: Mon, 3 Jul 2023 15:15:47 +0200 Subject: [PATCH 001/134] Add st preprocessing --- .../python_scripts/run_preprocess_spatialT.py | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 panpipes/python_scripts/run_preprocess_spatialT.py diff --git a/panpipes/python_scripts/run_preprocess_spatialT.py b/panpipes/python_scripts/run_preprocess_spatialT.py new file mode 100644 index 00000000..2738c800 --- /dev/null +++ b/panpipes/python_scripts/run_preprocess_spatialT.py @@ -0,0 +1,157 @@ +''' +Preprocess spatial transcriptomics data +''' +import warnings +warnings.simplefilter(action='ignore', category=FutureWarning) + +import numpy as np +import scanpy as sc +import muon as mu +import scanpy.experimental as sce + +import os +import argparse +import sys +import logging + +L = logging.getLogger() +L.setLevel(logging.INFO) +log_handler = logging.StreamHandler(sys.stdout) +formatter = logging.Formatter('%(asctime)s: %(levelname)s - %(message)s') +log_handler.setFormatter(formatter) +L.addHandler(log_handler) +L.debug("testing logger works") + + +from panpipes.funcs.scmethods import X_is_raw + + +sc.settings.verbosity = 3 + +parser = argparse.ArgumentParser() + +parser.add_argument("--input_mudata", + default="mudata_unfilt.h5mu", + help="") +parser.add_argument("--output_mudata", + default="mudata_unfilt.h5mu", + help="") +parser.add_argument("--figdir", + default="./figures/", + help="path to save the figures to") + +parser.add_argument("--norm_hvg_flavour", + default=None, + help="how to normalize the data and perform HVG selection, either 'squidpy' or 'seurat'") +parser.add_argument("--n_top_genes", + default=2000, + help="how many variable genes to select") +parser.add_argument("--filter_by_hvg", + default=False, + help="if True, subset the data to highly-variable genes after finding them") +parser.add_argument("--hvg_batch_key", + default=None, + help="if specified, highly-variable genes are selected within each batch separately and merged") +parser.add_argument("--squidpy_hvg_flavour", + default='seurat', + help="flavor for identifying highly variable genes. 'seurat', 'cellranger' or 'seurat_v3'") +parser.add_argument("--min_mean", + default=0.05, + help="min mean expression for HVG selection") +parser.add_argument("--max_mean", + default=1.5, + help="max mean expression for HVG selection") +parser.add_argument("--min_disp", + default=0.5, + help="dispersion min for HVG selection") +parser.add_argument("--theta", + default=100, + help="the negative binomial overdispersion parameter theta for Pearson residuals") +parser.add_argument("--clip", + default=None, + help="determines if and how residuals are clipped. Further information: https://scanpy.readthedocs.io/en/stable/generated/scanpy.experimental.pp.normalize_pearson_residuals.html") +parser.add_argument("--n_pcs", + default=50, + help="how many PCs to compute") + + +args, opt = parser.parse_known_args() + +L.info("running with args:") +L.debug(args) + +figdir = args.figdir + +if not os.path.exists(figdir): + os.mkdir(figdir) + +sc.settings.figdir = figdir +sc.set_figure_params(scanpy=True, fontsize=14, dpi=300, facecolor='white', figsize=(5,5)) + +mdata = mu.read(args.input_mudata) +spatial = mdata.mod['spatial'] + + +# check if raw data is available +#maybe layer of raw data as parameter +if X_is_raw(spatial): + spatial.layers['raw_counts'] = spatial.X.copy() +elif "raw_counts" in spatial.layers : + L.info("raw_counts layer already exists") + spatial.X = spatial.layers['raw_counts'].copy() +else: + L.error("X is not raw data and 'raw_counts' layer not found") + sys.exit("X is not raw data and 'raw_counts' layer not found") + + + +# Normalization + HVG selection based on flavour +if args.norm_hvg_flavour == "squidpy": + if args.squidpy_hvg_flavour == "seurat_v3": + sc.pp.highly_variable_genes(spatial, flavor="seurat_v3", n_top_genes=int(args.n_top_genes), subset=args.filter_by_hvg, + batch_key=args.hvg_batch_key) + sc.pp.normalize_total(spatial) + sc.pp.log1p(spatial) + else: + sc.pp.normalize_total(spatial) + sc.pp.log1p(spatial) + sc.pp.highly_variable_genes(spatial, flavor=args.squidpy_hvg_flavor, + min_mean=float(args.min_mean), + max_mean=float(args.max_mean), + min_disp=float(args.min_disp), subset=args.filter_by_hvg, batch_key=args.hvg_batch_key) + spatial.layers["lognorm"] = spatial.X.copy() + # plot HVGs: + sc.pl.highly_variable_genes(spatial, show=False, save="_genes_highlyvar.png") + +elif args.norm_hvg_flavour == "seurat": + if args.clip is not None: + clip = float(args.clip) + else: + clip = args.clip + + sce.pp.highly_variable_genes(spatial, theta=float(args.theta), clip=clip, n_top_genes=int(args.n_top_genes), + batch_key=args.hvg_batch_key, flavor='pearson_residuals', + layer="raw_counts", subset=args.filter_by_hvg) + sce.pp.normalize_pearson_residuals(spatial, theta=float(args.theta), clip=clip, layer="raw_counts") + spatial.layers["norm_pearson_resid"] = spatial.X.copy() +else: + # error or warning? + L.warning("No normalization and HVG selection was performed! To perform, please specify the 'norm_hvg_flavour' as either 'squidpy' or 'seurat'") + + +if "highly_variable" in spatial.var: + L.warning( "You have %s Highly Variable Features", np.sum(spatial.var.highly_variable)) + + + +#PCA +sc.pp.pca(spatial, n_comps=int(args.n_pcs), svd_solver='arpack', random_state=0) +sc.pl.pca(spatial, save = "_vars.png") + + + +mdata.update() +mdata.write(args.output_mudata) + +L.info("Done") + From a5afa56788961b4abe473709bf51dbf0a707546e Mon Sep 17 00:00:00 2001 From: SarahOuologuem Date: Mon, 3 Jul 2023 15:16:50 +0200 Subject: [PATCH 002/134] Add st preprocess parameters --- .../panpipes/pipeline_preprocess/pipeline.yml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/panpipes/panpipes/pipeline_preprocess/pipeline.yml b/panpipes/panpipes/pipeline_preprocess/pipeline.yml index 43ac7f52..474af1cf 100644 --- a/panpipes/panpipes/pipeline_preprocess/pipeline.yml +++ b/panpipes/panpipes/pipeline_preprocess/pipeline.yml @@ -42,6 +42,7 @@ modalities: prot: False rep: False atac: False + spatialT: True # Filtering # -------------------------- @@ -276,3 +277,40 @@ atac: # which dimension to exclude from further processing (sometimes useful to remove PC/LSI_1 if it's associated to tech factors) # leave blank to retain all dim_remove: 1 + + + + +# Spatial transcriptomics preprocessing +# Normalization + HVG selection + PCA +# -------------------------- +spatialT: + # how to perform normalization and HVG selection: + norm_hvg_flavour: seurat # ['seurat', 'squidpy'] + # 'seurat': HVG selection and normalization by analytic Pearson residuals + # 'squidpy': HVG selection and normalization using the standard scanpy functions (sc.pp.normalize_total(),sc.pp.log1p(), sc.pp.highly_variable_genes()) + + # !the following parameters are only for the case norm_hvg_flavour == squidpy: + squidpy_hvg_flavour: seurat #['seurat','cellranger','seurat_v3'], leave blank to use default ('seurat'), flavour for the sc.pp.highly_variable_genes() function + min_mean: # leave blank to use default (0.05), parameter in sc.pp.highly_variable_genes() + max_mean: # leave blank to use default (1.5), parameter in sc.pp.highly_variable_genes() + min_disp: # leave blank to use default (0.5), parameter in sc.pp.highly_variable_genes() + + # !the following parameters are only for the case norm_hvg_flavour == seurat: + theta: #leave blank to use default (100), the negative binomial overdispersion parameter for Pearson residuals + clip: #leave blank to use default (None) + # 'clip' can be specified as: + # None: residuals are clipped to the interval [-sqrt(n_obs), sqrt(n_obs)] + # a float value: if float c specified: clipped to the interval [-c, c] + # np.Inf: no clipping + + #! parameters for both cases norm_hvg_flavour = "seurat" and "squidpy" + n_top_genes: 2000 # Default is 2000, Mandatory for norm_hvg_flavour = "seurat" and squidpy_hvg_flavor: "seurat_v3" + filter_by_hvg: False # leave blank to use default (False); if True, subset the data to highly-variable genes after finding them + hvg_batch_key: #leave blank to use default (None); if specified, highly-variable genes are selected within each batch separately and merged + + n_pcs: 50 #leave blank to use default (50); how many PCs to compute with sc.pp.PCA() + + + + From 7c248b37d9e850f47fb0b605ce1841a9a9e1b510 Mon Sep 17 00:00:00 2001 From: SarahOuologuem Date: Mon, 3 Jul 2023 15:17:49 +0200 Subject: [PATCH 003/134] Add st preprocess --- panpipes/panpipes/pipeline_preprocess.py | 49 +++++++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/panpipes/panpipes/pipeline_preprocess.py b/panpipes/panpipes/pipeline_preprocess.py index b7d747de..5517388b 100644 --- a/panpipes/panpipes/pipeline_preprocess.py +++ b/panpipes/panpipes/pipeline_preprocess.py @@ -237,13 +237,58 @@ def atac_preprocess(log_file, scaled_file): if PARAMS['atac_feature_selection_flavour'] is not None: cmd += " --feature_selection_flavour %(atac_feature_selection_flavour)s" - if PARAMS['min_cutoff'] is not None: + if PARAMS['atac_min_cutoff'] is not None: cmd += " --min_cutoff %(atac_min_cutoff)s" cmd += " > %(log_file)s" job_kwargs["job_threads"] = PARAMS['resources_threads_high'] P.run(cmd, **job_kwargs) + +@active_if(mode_dictionary['spatialT'] is True) +@follows(atac_preprocess) +@originate("logs/preprocess_spatialT.log", PARAMS['mudata_file']) +def spatialT_preprocess(log_file, scaled_file): + if os.path.exists("figures/spatialT") is False: + os.mkdir("figures/spatialT") + cmd = """ + python %(py_path)s/run_preprocess_spatialT.py + --input_mudata %(scaled_file)s + --output_mudata %(scaled_file)s + --figdir ./figures/spatialT + """ + if PARAMS['spatialT_norm_hvg_flavour'] is not None: + cmd += " --norm_hvg_flavour %(spatialT_norm_hvg_flavour)s" + if PARAMS['spatialT_n_top_genes'] is not None: + cmd += " --n_top_genes %(spatialT_n_top_genes)s" + if PARAMS['spatialT_filter_by_hvg'] is True: + cmd += " --filter_by_hvg True" + else: + cmd += " --filter_by_hvg False" + if PARAMS['spatialT_hvg_batch_key'] is not None: + cmd += " --hvg_batch_key %(spatialT_hvg_batch_key)s" + if PARAMS['spatialT_squidpy_hvg_flavour'] is not None: + cmd += " --squidpy_hvg_flavour %(spatialT_squidpy_hvg_flavour)s" + if PARAMS['spatialT_min_mean'] is not None: + cmd += " --min_mean %(spatialT_min_mean)s" + if PARAMS['spatialT_max_mean'] is not None: + cmd += " --max_mean %(spatialT_max_mean)s" + if PARAMS['spatialT_min_disp'] is not None: + cmd += " --min_disp %(spatialT_min_disp)s" + if PARAMS['spatialT_theta'] is not None: + cmd += " --theta %(spatialT_theta)s" + if PARAMS['spatialT_clip'] is not None: + cmd += " --clip %(spatialT_clip)s" + if PARAMS['spatialT_n_pcs'] is not None: + cmd += " --n_pcs %(spatialT_n_pcs)s" + + cmd += " > %(log_file)s" + job_kwargs["job_threads"] = PARAMS['resources_threads_high'] + P.run(cmd, **job_kwargs) + + + + # @active_if(mode_dictionary['rep'] is True) # @follows(atac_preprocess) # # @transform(rna_preprocess,formatter(),"logs/preprocess_rep.log") @@ -252,7 +297,7 @@ def atac_preprocess(log_file, scaled_file): # pass # ---- end stub -@follows(postfilterplot,rna_preprocess,atac_preprocess,prot_preprocess) +@follows(postfilterplot,rna_preprocess,atac_preprocess,prot_preprocess, spatialT_preprocess) def full(): """ All cgat pipelines should end with a full() function which updates, From 9fae46ac6f4c88d99571c47b4ae6e1058ad8503b Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 09:53:37 +0100 Subject: [PATCH 004/134] first attempt at rtd --- docs/source/api.rst | 7 +++ docs/source/conf.py | 35 +++++++++++ docs/source/index.rst | 132 ++++++++++++++++++++++++++++++++++++++++++ docs/source/usage.rst | 0 4 files changed, 174 insertions(+) create mode 100644 docs/source/api.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/usage.rst diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 00000000..1d91f4e5 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,7 @@ +API +=== + +.. autosummary:: + :toctree: generated + + panpipes \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..0315437b --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,35 @@ +# Configuration file for the Sphinx documentation builder. + +# -- Project information + +project = 'Panpipes' +copyright = '2023, Rich-Griffin & Curion' +author = 'Charlotte Rich-Griffin & Fabiola Curion' + +release = '0.1' +version = '0.1.0' + +# -- General configuration + +extensions = [ + 'sphinx.ext.duration', + 'sphinx.ext.doctest', + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.intersphinx', +] + +intersphinx_mapping = { + 'python': ('https://docs.python.org/3/', None), + 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), +} +intersphinx_disabled_domains = ['std'] + +templates_path = ['_templates'] + +# -- Options for HTML output + +html_theme = 'sphinx_rtd_theme' + +# -- Options for EPUB output +epub_show_urls = 'footnote' \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..a3fbea3f --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,132 @@ +# Panpipes - multimodal single cell pipelines + +Created and Maintained by Charlotte Rich-Griffin and Fabiola Curion +Additional contributors: Devika Agarwal and Tom Thomas + +See our [preprint](https://www.biorxiv.org/content/10.1101/2023.03.11.532085v1): +Panpipes: a pipeline for multiomic single-cell data analysis +Charlotte Rich-Griffin, Fabiola Curion, Tom Thomas, Devika Agarwal, Fabian J. Theis, Calliope A. Dendrou. +bioRxiv 2023.03.11.532085; +doi: https://doi.org/10.1101/2023.03.11.532085 + + +# Introduction +These pipelines use cgat-core pipeline software + +Available pipelines: +1. "qc_mm" : for the ingestion of data and computation of QC metrics' +2. "preprocess" : for filtering and normalising of each modality +3. "integration" : integrate and batch correction using single and multimodal methods +4. "clustering" : cell clustering on single modalities +5. "refmap" : transfer scvi-tools models from published data to your data +6. "vis" : visualise metrics from other pipelines in context of experiment metadata + + + +# Installation and configuration + + + +See [installation instrcutions here](https://github.com/DendrouLab/panpipes/blob/main/docs/install.md) + + +Oxford BMRC Rescomp users find additional advice in [docs/installation_rescomp](https://github.com/DendrouLab/panpipes/blob/main/docs/installation_rescomp.md) + +# General principles for running pipelines + +Run the pipeline from the login node on your server, it will use in built the job submission system to submit jobs. + +Navigate to the directory where you want to run your analysis (this should not be within the panpipes folder, or your virutal environment folder) + +``` +mkdir data_dir/ +cd data_dir/ +panpipes qc_mm config +``` +This will produce two files, `pipeline.log` and `pipeline.yml` + +Edit `pipeline.yml` as appropriate for your data, following the instructions within the yml file. + +Then check which jobs will run with the command +``` +panpipes qc_mm show full +``` +The output of this will show a list of tasks that will be run as part of the pipeline. + +To run use the command +``` +panpipes qc_mm make full +``` + + +Occasionally you might want to run tasks individually (e.g. to assess outputs before deciding the parameters for the next step) +In order to do this you can run any task in the `show full` list such as: + +``` +panpipes qc_mm make plot_tenx_metrics +``` + + +# Running the complete pipeline + +Run each of pipeline qc, integration and clustering in separate folders. +### QC + +1. Generate sample submission file + - [more details on creating the submission file](https://github.com/DendrouLab/panpipes/blob/main/docs/setup_for_qc_mm.md) +2. Generate qc genelists + - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) +3. For adt assay - generate the protein metadata file [example]((https://github.com/DendrouLab/panpipes/blob/main/resources/protein_metadata_w_iso.md)). This file is integrated into the mdata['prot'].var slot. +4. Generate config file (`panpipes qc_mm config`) +5. Edit the pipeline.yml file for your dataset + - this is explained step by step within the pipeline.yml file +6. Run complete qc pipeline with `panpipes qc_mm make full ` +7. Use outputs to decide filtering thresholds. + - **Note that the actual filtering occurs in the first step of Preprocess pipeline** + - TODO: create doc to explain the pipeline outputs + + +The h5mu file outputted from `qc_mm` contains concatenated raw counts from all samples in the submission file, plus qc metrics are computed, and these qc metrics are visualised in a variety of plots to aid the user to determine data quality and filtering thresholds. + +### Preprocess +1. In a new folder, generate config file for integration, `panpipes preprocess config` +2. edit the pipeline.yml file + - The filtering options are dynamic depending on your qc_mm inputs [more details here](https://github.com/DendrouLab/panpipes/blob/main/docs/filter_dict_instructions.md) + - There are lots of options for normalisation explained in the pipeline.yml +2. Run complete preprocess pipeline with `panpipes preprocess make full ` + +The h5mu outputted from `preprocess` is filtered and normalised, and for rna highly variable genes are computed. + + +### Integration +1. In a new folder, generate config file for integration, `panpipes integration config` and edit the pipeline.yml file. +2. Run `panpipes integration make plot_pcas` and assess the post filtering qc plots, and pca outputs +3. Run batch correction with `panpipes integration make batch_correction` (or run steps 2 and 3 in one go with `panpipes integration make full`) +4. Use pipeline outputs to decide on the best batch correction method +5. Edit the integration pipeline yml with your preferred batch correction +6. Run `panpipes integration make merge_batch_correction` + +### Refmap + +1. In a new folder, generate config file for integration, `panpipes refmap config` and edit the pipeline.yml file. +2. Run complete refmap pipeline with `panpipes refmap make full ` + +### Clustering + +1. In a new folder, generate config file for integration, `panpipes clustering config` and edit the pipeline.yml file. +2. Run the clustering pipeline `panpipes clustering make cluster_analysis`. This will do the initial nearest neighbours and clustering for the parameters you specify. +3. Decide on the best values for k nearest neighbours based on UMAPs and clustree results. Once decided delete the folders for the parameters you don't need and delete those from the pipeline.yml. +4. Find markers for each of your cluster resolutions with `panpipes clustering make marker_analysis` +(Again you could run all the clustering pipeline at once with `panpipes clustering make full` but by making decisions along the way you'll reduce the computation and file size burden of the pipeline) + +### Vis +1. In a new folder, generate config file for integration, `panpipes vis config` and edit the pipeline.yml file. +2. Prepare plotting gene list files + - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) +3. Run complete refmap pipeline with `panpipes vis make full ` + +To repeat the pipeline after editing the pipeline.yml, delete the files in log and repeat step 3. + + +# Running pipeline modules from different entry points. +[see details](https://github.com/DendrouLab/panpipes/blob/main/docs/different_entry_points.md) \ No newline at end of file diff --git a/docs/source/usage.rst b/docs/source/usage.rst new file mode 100644 index 00000000..e69de29b From 1e1128a3440d3d6a20b5a02ca04acbd9462054a7 Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:52:02 +0100 Subject: [PATCH 005/134] Update .readthedocs.yaml --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index aa209bb2..dad7a17e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -17,7 +17,7 @@ build: # Build documentation in the "docs/" directory with Sphinx sphinx: - configuration: docs/conf.py + configuration: docs/source/conf.py # Optionally build your docs in additional formats such as PDF and ePub # formats: From 3dd280e11e289de4af92ba04357ac367206ee18b Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:52:28 +0100 Subject: [PATCH 006/134] Update .readthedocs.yaml --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index dad7a17e..aa209bb2 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -17,7 +17,7 @@ build: # Build documentation in the "docs/" directory with Sphinx sphinx: - configuration: docs/source/conf.py + configuration: docs/conf.py # Optionally build your docs in additional formats such as PDF and ePub # formats: From 3d115bcadc8b1a3684149f7bb73bec918634a54d Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:07:03 +0100 Subject: [PATCH 007/134] move files --- docs/{source => }/api.rst | 0 docs/{source => }/conf.py | 0 docs/{source => }/index.rst | 0 docs/{source => }/usage.rst | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename docs/{source => }/api.rst (100%) rename docs/{source => }/conf.py (100%) rename docs/{source => }/index.rst (100%) rename docs/{source => }/usage.rst (100%) diff --git a/docs/source/api.rst b/docs/api.rst similarity index 100% rename from docs/source/api.rst rename to docs/api.rst diff --git a/docs/source/conf.py b/docs/conf.py similarity index 100% rename from docs/source/conf.py rename to docs/conf.py diff --git a/docs/source/index.rst b/docs/index.rst similarity index 100% rename from docs/source/index.rst rename to docs/index.rst diff --git a/docs/source/usage.rst b/docs/usage.rst similarity index 100% rename from docs/source/usage.rst rename to docs/usage.rst From a53527e87e3c570908bfd0d505a97a1cad07f534 Mon Sep 17 00:00:00 2001 From: SarahOuologuem Date: Thu, 6 Jul 2023 13:17:00 +0200 Subject: [PATCH 008/134] Bug fixes + add PCA plot --- .../python_scripts/run_preprocess_spatialT.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/panpipes/python_scripts/run_preprocess_spatialT.py b/panpipes/python_scripts/run_preprocess_spatialT.py index 2738c800..188aa537 100644 --- a/panpipes/python_scripts/run_preprocess_spatialT.py +++ b/panpipes/python_scripts/run_preprocess_spatialT.py @@ -115,7 +115,7 @@ else: sc.pp.normalize_total(spatial) sc.pp.log1p(spatial) - sc.pp.highly_variable_genes(spatial, flavor=args.squidpy_hvg_flavor, + sc.pp.highly_variable_genes(spatial, flavor=args.squidpy_hvg_flavour, min_mean=float(args.min_mean), max_mean=float(args.max_mean), min_disp=float(args.min_disp), subset=args.filter_by_hvg, batch_key=args.hvg_batch_key) @@ -124,12 +124,16 @@ sc.pl.highly_variable_genes(spatial, show=False, save="_genes_highlyvar.png") elif args.norm_hvg_flavour == "seurat": - if args.clip is not None: - clip = float(args.clip) - else: + if args.clip is None: clip = args.clip - - sce.pp.highly_variable_genes(spatial, theta=float(args.theta), clip=clip, n_top_genes=int(args.n_top_genes), + elif args.clip == "None": + clip = None + elif args.clip == "np.Inf": + clip = np.Inf + else: + clip = float(args.clip) + + sce.pp.highly_variable_genes(spatial, theta=float(args.theta), clip=clip, n_top_genes=int(args.n_top_genes), batch_key=args.hvg_batch_key, flavor='pearson_residuals', layer="raw_counts", subset=args.filter_by_hvg) sce.pp.normalize_pearson_residuals(spatial, theta=float(args.theta), clip=clip, layer="raw_counts") @@ -147,6 +151,7 @@ #PCA sc.pp.pca(spatial, n_comps=int(args.n_pcs), svd_solver='arpack', random_state=0) sc.pl.pca(spatial, save = "_vars.png") +sc.pl.pca_variance_ratio(spatial, log=True, n_pcs=int(args.n_pcs), save=".png") From 5c1bf4c65ed197d433b8c3d4c02b015dc2b143e2 Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:17:26 +0100 Subject: [PATCH 009/134] move docs about --- docs/index.rst | 117 +++---------------------------------------------- docs/usage.rst | 109 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 111 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index a3fbea3f..a9ce9a00 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,6 +1,8 @@ -# Panpipes - multimodal single cell pipelines + Panpipes - multimodal single cell pipelines +================================================== -Created and Maintained by Charlotte Rich-Griffin and Fabiola Curion + +**Panpipes** Created and Maintained by Charlotte Rich-Griffin and Fabiola Curion Additional contributors: Devika Agarwal and Tom Thomas See our [preprint](https://www.biorxiv.org/content/10.1101/2023.03.11.532085v1): @@ -21,112 +23,5 @@ Available pipelines: 5. "refmap" : transfer scvi-tools models from published data to your data 6. "vis" : visualise metrics from other pipelines in context of experiment metadata - - -# Installation and configuration - - - -See [installation instrcutions here](https://github.com/DendrouLab/panpipes/blob/main/docs/install.md) - - -Oxford BMRC Rescomp users find additional advice in [docs/installation_rescomp](https://github.com/DendrouLab/panpipes/blob/main/docs/installation_rescomp.md) - -# General principles for running pipelines - -Run the pipeline from the login node on your server, it will use in built the job submission system to submit jobs. - -Navigate to the directory where you want to run your analysis (this should not be within the panpipes folder, or your virutal environment folder) - -``` -mkdir data_dir/ -cd data_dir/ -panpipes qc_mm config -``` -This will produce two files, `pipeline.log` and `pipeline.yml` - -Edit `pipeline.yml` as appropriate for your data, following the instructions within the yml file. - -Then check which jobs will run with the command -``` -panpipes qc_mm show full -``` -The output of this will show a list of tasks that will be run as part of the pipeline. - -To run use the command -``` -panpipes qc_mm make full -``` - - -Occasionally you might want to run tasks individually (e.g. to assess outputs before deciding the parameters for the next step) -In order to do this you can run any task in the `show full` list such as: - -``` -panpipes qc_mm make plot_tenx_metrics -``` - - -# Running the complete pipeline - -Run each of pipeline qc, integration and clustering in separate folders. -### QC - -1. Generate sample submission file - - [more details on creating the submission file](https://github.com/DendrouLab/panpipes/blob/main/docs/setup_for_qc_mm.md) -2. Generate qc genelists - - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) -3. For adt assay - generate the protein metadata file [example]((https://github.com/DendrouLab/panpipes/blob/main/resources/protein_metadata_w_iso.md)). This file is integrated into the mdata['prot'].var slot. -4. Generate config file (`panpipes qc_mm config`) -5. Edit the pipeline.yml file for your dataset - - this is explained step by step within the pipeline.yml file -6. Run complete qc pipeline with `panpipes qc_mm make full ` -7. Use outputs to decide filtering thresholds. - - **Note that the actual filtering occurs in the first step of Preprocess pipeline** - - TODO: create doc to explain the pipeline outputs - - -The h5mu file outputted from `qc_mm` contains concatenated raw counts from all samples in the submission file, plus qc metrics are computed, and these qc metrics are visualised in a variety of plots to aid the user to determine data quality and filtering thresholds. - -### Preprocess -1. In a new folder, generate config file for integration, `panpipes preprocess config` -2. edit the pipeline.yml file - - The filtering options are dynamic depending on your qc_mm inputs [more details here](https://github.com/DendrouLab/panpipes/blob/main/docs/filter_dict_instructions.md) - - There are lots of options for normalisation explained in the pipeline.yml -2. Run complete preprocess pipeline with `panpipes preprocess make full ` - -The h5mu outputted from `preprocess` is filtered and normalised, and for rna highly variable genes are computed. - - -### Integration -1. In a new folder, generate config file for integration, `panpipes integration config` and edit the pipeline.yml file. -2. Run `panpipes integration make plot_pcas` and assess the post filtering qc plots, and pca outputs -3. Run batch correction with `panpipes integration make batch_correction` (or run steps 2 and 3 in one go with `panpipes integration make full`) -4. Use pipeline outputs to decide on the best batch correction method -5. Edit the integration pipeline yml with your preferred batch correction -6. Run `panpipes integration make merge_batch_correction` - -### Refmap - -1. In a new folder, generate config file for integration, `panpipes refmap config` and edit the pipeline.yml file. -2. Run complete refmap pipeline with `panpipes refmap make full ` - -### Clustering - -1. In a new folder, generate config file for integration, `panpipes clustering config` and edit the pipeline.yml file. -2. Run the clustering pipeline `panpipes clustering make cluster_analysis`. This will do the initial nearest neighbours and clustering for the parameters you specify. -3. Decide on the best values for k nearest neighbours based on UMAPs and clustree results. Once decided delete the folders for the parameters you don't need and delete those from the pipeline.yml. -4. Find markers for each of your cluster resolutions with `panpipes clustering make marker_analysis` -(Again you could run all the clustering pipeline at once with `panpipes clustering make full` but by making decisions along the way you'll reduce the computation and file size burden of the pipeline) - -### Vis -1. In a new folder, generate config file for integration, `panpipes vis config` and edit the pipeline.yml file. -2. Prepare plotting gene list files - - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) -3. Run complete refmap pipeline with `panpipes vis make full ` - -To repeat the pipeline after editing the pipeline.yml, delete the files in log and repeat step 3. - - -# Running pipeline modules from different entry points. -[see details](https://github.com/DendrouLab/panpipes/blob/main/docs/different_entry_points.md) \ No newline at end of file +Check out the :doc:`usage` section for further information, including +how to :ref:`installation` the project. diff --git a/docs/usage.rst b/docs/usage.rst index e69de29b..78677bdb 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -0,0 +1,109 @@ + + +# Installation and configuration + + + +See [installation instrcutions here](https://github.com/DendrouLab/panpipes/blob/main/docs/install.md) + + +Oxford BMRC Rescomp users find additional advice in [docs/installation_rescomp](https://github.com/DendrouLab/panpipes/blob/main/docs/installation_rescomp.md) + +# General principles for running pipelines + +Run the pipeline from the login node on your server, it will use in built the job submission system to submit jobs. + +Navigate to the directory where you want to run your analysis (this should not be within the panpipes folder, or your virutal environment folder) + +``` +mkdir data_dir/ +cd data_dir/ +panpipes qc_mm config +``` +This will produce two files, `pipeline.log` and `pipeline.yml` + +Edit `pipeline.yml` as appropriate for your data, following the instructions within the yml file. + +Then check which jobs will run with the command +``` +panpipes qc_mm show full +``` +The output of this will show a list of tasks that will be run as part of the pipeline. + +To run use the command +``` +panpipes qc_mm make full +``` + + +Occasionally you might want to run tasks individually (e.g. to assess outputs before deciding the parameters for the next step) +In order to do this you can run any task in the `show full` list such as: + +``` +panpipes qc_mm make plot_tenx_metrics +``` + + +# Running the complete pipeline + +Run each of pipeline qc, integration and clustering in separate folders. +### QC + +1. Generate sample submission file + - [more details on creating the submission file](https://github.com/DendrouLab/panpipes/blob/main/docs/setup_for_qc_mm.md) +2. Generate qc genelists + - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) +3. For adt assay - generate the protein metadata file [example]((https://github.com/DendrouLab/panpipes/blob/main/resources/protein_metadata_w_iso.md)). This file is integrated into the mdata['prot'].var slot. +4. Generate config file (`panpipes qc_mm config`) +5. Edit the pipeline.yml file for your dataset + - this is explained step by step within the pipeline.yml file +6. Run complete qc pipeline with `panpipes qc_mm make full ` +7. Use outputs to decide filtering thresholds. + - **Note that the actual filtering occurs in the first step of Preprocess pipeline** + - TODO: create doc to explain the pipeline outputs + + +The h5mu file outputted from `qc_mm` contains concatenated raw counts from all samples in the submission file, plus qc metrics are computed, and these qc metrics are visualised in a variety of plots to aid the user to determine data quality and filtering thresholds. + +### Preprocess +1. In a new folder, generate config file for integration, `panpipes preprocess config` +2. edit the pipeline.yml file + - The filtering options are dynamic depending on your qc_mm inputs [more details here](https://github.com/DendrouLab/panpipes/blob/main/docs/filter_dict_instructions.md) + - There are lots of options for normalisation explained in the pipeline.yml +2. Run complete preprocess pipeline with `panpipes preprocess make full ` + +The h5mu outputted from `preprocess` is filtered and normalised, and for rna highly variable genes are computed. + + +### Integration +1. In a new folder, generate config file for integration, `panpipes integration config` and edit the pipeline.yml file. +2. Run `panpipes integration make plot_pcas` and assess the post filtering qc plots, and pca outputs +3. Run batch correction with `panpipes integration make batch_correction` (or run steps 2 and 3 in one go with `panpipes integration make full`) +4. Use pipeline outputs to decide on the best batch correction method +5. Edit the integration pipeline yml with your preferred batch correction +6. Run `panpipes integration make merge_batch_correction` + +### Refmap + +1. In a new folder, generate config file for integration, `panpipes refmap config` and edit the pipeline.yml file. +2. Run complete refmap pipeline with `panpipes refmap make full ` + +### Clustering + +1. In a new folder, generate config file for integration, `panpipes clustering config` and edit the pipeline.yml file. +2. Run the clustering pipeline `panpipes clustering make cluster_analysis`. This will do the initial nearest neighbours and clustering for the parameters you specify. +3. Decide on the best values for k nearest neighbours based on UMAPs and clustree results. Once decided delete the folders for the parameters you don't need and delete those from the pipeline.yml. +4. Find markers for each of your cluster resolutions with `panpipes clustering make marker_analysis` +(Again you could run all the clustering pipeline at once with `panpipes clustering make full` but by making decisions along the way you'll reduce the computation and file size burden of the pipeline) + +### Vis +1. In a new folder, generate config file for integration, `panpipes vis config` and edit the pipeline.yml file. +2. Prepare plotting gene list files + - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) +3. Run complete refmap pipeline with `panpipes vis make full ` + +To repeat the pipeline after editing the pipeline.yml, delete the files in log and repeat step 3. + + +# Running pipeline modules from different entry points. +[see details](https://github.com/DendrouLab/panpipes/blob/main/docs/different_entry_points.md) \ No newline at end of file From f4982c6af02238860b30f9577ee7d0b06f0b97aa Mon Sep 17 00:00:00 2001 From: SarahOuologuem Date: Thu, 6 Jul 2023 13:17:52 +0200 Subject: [PATCH 010/134] Add spatialT filtering --- panpipes/panpipes/pipeline_preprocess/pipeline.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/panpipes/panpipes/pipeline_preprocess/pipeline.yml b/panpipes/panpipes/pipeline_preprocess/pipeline.yml index 474af1cf..9b076103 100644 --- a/panpipes/panpipes/pipeline_preprocess/pipeline.yml +++ b/panpipes/panpipes/pipeline_preprocess/pipeline.yml @@ -130,6 +130,14 @@ filtering: ## var filtering: (feature) fragment level filtering here var: nucleosome_signal: + #------------------------------------------------------ + spatial: + #------------------------------------------------------ + obs: + min: + n_genes_by_counts: + max: + total_counts: # Intersecting barcodes # ---------------------- From 58f3c27db1b7725bd7756d59dcbce294be1059f2 Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:56:39 +0100 Subject: [PATCH 011/134] Update index.rst --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index a9ce9a00..3d780126 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,4 +1,4 @@ - Panpipes - multimodal single cell pipelines +Panpipes - multimodal single cell pipelines ================================================== From d14fd0ab7b507a48bb57d7ce4c877d1345a3123c Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:42:05 +0100 Subject: [PATCH 012/134] usage to rst --- docs/generated/panpipes.rst | 23 ++++ docs/usage.md | 109 +++++++++++++++++++ docs/usage.rst | 206 +++++++++++++++++++++++------------- 3 files changed, 265 insertions(+), 73 deletions(-) create mode 100644 docs/generated/panpipes.rst create mode 100644 docs/usage.md diff --git a/docs/generated/panpipes.rst b/docs/generated/panpipes.rst new file mode 100644 index 00000000..426a3148 --- /dev/null +++ b/docs/generated/panpipes.rst @@ -0,0 +1,23 @@ +panpipes +======== + +.. automodule:: panpipes + + + + + + + + + + + + + + + + + + + diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 00000000..78677bdb --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,109 @@ + + +# Installation and configuration + + + +See [installation instrcutions here](https://github.com/DendrouLab/panpipes/blob/main/docs/install.md) + + +Oxford BMRC Rescomp users find additional advice in [docs/installation_rescomp](https://github.com/DendrouLab/panpipes/blob/main/docs/installation_rescomp.md) + +# General principles for running pipelines + +Run the pipeline from the login node on your server, it will use in built the job submission system to submit jobs. + +Navigate to the directory where you want to run your analysis (this should not be within the panpipes folder, or your virutal environment folder) + +``` +mkdir data_dir/ +cd data_dir/ +panpipes qc_mm config +``` +This will produce two files, `pipeline.log` and `pipeline.yml` + +Edit `pipeline.yml` as appropriate for your data, following the instructions within the yml file. + +Then check which jobs will run with the command +``` +panpipes qc_mm show full +``` +The output of this will show a list of tasks that will be run as part of the pipeline. + +To run use the command +``` +panpipes qc_mm make full +``` + + +Occasionally you might want to run tasks individually (e.g. to assess outputs before deciding the parameters for the next step) +In order to do this you can run any task in the `show full` list such as: + +``` +panpipes qc_mm make plot_tenx_metrics +``` + + +# Running the complete pipeline + +Run each of pipeline qc, integration and clustering in separate folders. +### QC + +1. Generate sample submission file + - [more details on creating the submission file](https://github.com/DendrouLab/panpipes/blob/main/docs/setup_for_qc_mm.md) +2. Generate qc genelists + - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) +3. For adt assay - generate the protein metadata file [example]((https://github.com/DendrouLab/panpipes/blob/main/resources/protein_metadata_w_iso.md)). This file is integrated into the mdata['prot'].var slot. +4. Generate config file (`panpipes qc_mm config`) +5. Edit the pipeline.yml file for your dataset + - this is explained step by step within the pipeline.yml file +6. Run complete qc pipeline with `panpipes qc_mm make full ` +7. Use outputs to decide filtering thresholds. + - **Note that the actual filtering occurs in the first step of Preprocess pipeline** + - TODO: create doc to explain the pipeline outputs + + +The h5mu file outputted from `qc_mm` contains concatenated raw counts from all samples in the submission file, plus qc metrics are computed, and these qc metrics are visualised in a variety of plots to aid the user to determine data quality and filtering thresholds. + +### Preprocess +1. In a new folder, generate config file for integration, `panpipes preprocess config` +2. edit the pipeline.yml file + - The filtering options are dynamic depending on your qc_mm inputs [more details here](https://github.com/DendrouLab/panpipes/blob/main/docs/filter_dict_instructions.md) + - There are lots of options for normalisation explained in the pipeline.yml +2. Run complete preprocess pipeline with `panpipes preprocess make full ` + +The h5mu outputted from `preprocess` is filtered and normalised, and for rna highly variable genes are computed. + + +### Integration +1. In a new folder, generate config file for integration, `panpipes integration config` and edit the pipeline.yml file. +2. Run `panpipes integration make plot_pcas` and assess the post filtering qc plots, and pca outputs +3. Run batch correction with `panpipes integration make batch_correction` (or run steps 2 and 3 in one go with `panpipes integration make full`) +4. Use pipeline outputs to decide on the best batch correction method +5. Edit the integration pipeline yml with your preferred batch correction +6. Run `panpipes integration make merge_batch_correction` + +### Refmap + +1. In a new folder, generate config file for integration, `panpipes refmap config` and edit the pipeline.yml file. +2. Run complete refmap pipeline with `panpipes refmap make full ` + +### Clustering + +1. In a new folder, generate config file for integration, `panpipes clustering config` and edit the pipeline.yml file. +2. Run the clustering pipeline `panpipes clustering make cluster_analysis`. This will do the initial nearest neighbours and clustering for the parameters you specify. +3. Decide on the best values for k nearest neighbours based on UMAPs and clustree results. Once decided delete the folders for the parameters you don't need and delete those from the pipeline.yml. +4. Find markers for each of your cluster resolutions with `panpipes clustering make marker_analysis` +(Again you could run all the clustering pipeline at once with `panpipes clustering make full` but by making decisions along the way you'll reduce the computation and file size burden of the pipeline) + +### Vis +1. In a new folder, generate config file for integration, `panpipes vis config` and edit the pipeline.yml file. +2. Prepare plotting gene list files + - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) +3. Run complete refmap pipeline with `panpipes vis make full ` + +To repeat the pipeline after editing the pipeline.yml, delete the files in log and repeat step 3. + + +# Running pipeline modules from different entry points. +[see details](https://github.com/DendrouLab/panpipes/blob/main/docs/different_entry_points.md) \ No newline at end of file diff --git a/docs/usage.rst b/docs/usage.rst index 78677bdb..29454924 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,109 +1,169 @@ +Installation and configuration +============================== +See `installation instrcutions +here `__ -# Installation and configuration +Oxford BMRC Rescomp users find additional advice in +`docs/installation_rescomp `__ +General principles for running pipelines +======================================== +Run the pipeline from the login node on your server, it will use in +built the job submission system to submit jobs. -See [installation instrcutions here](https://github.com/DendrouLab/panpipes/blob/main/docs/install.md) +Navigate to the directory where you want to run your analysis (this +should not be within the panpipes folder, or your virutal environment +folder) +:: -Oxford BMRC Rescomp users find additional advice in [docs/installation_rescomp](https://github.com/DendrouLab/panpipes/blob/main/docs/installation_rescomp.md) + mkdir data_dir/ + cd data_dir/ + panpipes qc_mm config -# General principles for running pipelines +This will produce two files, ``pipeline.log`` and ``pipeline.yml`` -Run the pipeline from the login node on your server, it will use in built the job submission system to submit jobs. +Edit ``pipeline.yml`` as appropriate for your data, following the +instructions within the yml file. -Navigate to the directory where you want to run your analysis (this should not be within the panpipes folder, or your virutal environment folder) +Then check which jobs will run with the command -``` -mkdir data_dir/ -cd data_dir/ -panpipes qc_mm config -``` -This will produce two files, `pipeline.log` and `pipeline.yml` +:: -Edit `pipeline.yml` as appropriate for your data, following the instructions within the yml file. + panpipes qc_mm show full -Then check which jobs will run with the command -``` -panpipes qc_mm show full -``` -The output of this will show a list of tasks that will be run as part of the pipeline. +The output of this will show a list of tasks that will be run as part of +the pipeline. To run use the command -``` -panpipes qc_mm make full -``` +:: + + panpipes qc_mm make full -Occasionally you might want to run tasks individually (e.g. to assess outputs before deciding the parameters for the next step) -In order to do this you can run any task in the `show full` list such as: +Occasionally you might want to run tasks individually (e.g. to assess +outputs before deciding the parameters for the next step) In order to do +this you can run any task in the ``show full`` list such as: -``` -panpipes qc_mm make plot_tenx_metrics -``` +:: + panpipes qc_mm make plot_tenx_metrics -# Running the complete pipeline +Running the complete pipeline +============================= Run each of pipeline qc, integration and clustering in separate folders. -### QC - -1. Generate sample submission file - - [more details on creating the submission file](https://github.com/DendrouLab/panpipes/blob/main/docs/setup_for_qc_mm.md) -2. Generate qc genelists - - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) -3. For adt assay - generate the protein metadata file [example]((https://github.com/DendrouLab/panpipes/blob/main/resources/protein_metadata_w_iso.md)). This file is integrated into the mdata['prot'].var slot. -4. Generate config file (`panpipes qc_mm config`) -5. Edit the pipeline.yml file for your dataset - - this is explained step by step within the pipeline.yml file -6. Run complete qc pipeline with `panpipes qc_mm make full ` -7. Use outputs to decide filtering thresholds. - - **Note that the actual filtering occurs in the first step of Preprocess pipeline** - - TODO: create doc to explain the pipeline outputs +### QC +1. Generate sample submission file -The h5mu file outputted from `qc_mm` contains concatenated raw counts from all samples in the submission file, plus qc metrics are computed, and these qc metrics are visualised in a variety of plots to aid the user to determine data quality and filtering thresholds. + - `more details on creating the submission + file `__ -### Preprocess -1. In a new folder, generate config file for integration, `panpipes preprocess config` -2. edit the pipeline.yml file - - The filtering options are dynamic depending on your qc_mm inputs [more details here](https://github.com/DendrouLab/panpipes/blob/main/docs/filter_dict_instructions.md) - - There are lots of options for normalisation explained in the pipeline.yml -2. Run complete preprocess pipeline with `panpipes preprocess make full ` +2. Generate qc genelists -The h5mu outputted from `preprocess` is filtered and normalised, and for rna highly variable genes are computed. + - `more + details `__ +3. For adt assay - generate the protein metadata file + `example <(https://github.com/DendrouLab/panpipes/blob/main/resources/protein_metadata_w_iso.md)>`__. + This file is integrated into the mdata[‘prot’].var slot. +4. Generate config file (``panpipes qc_mm config``) +5. Edit the pipeline.yml file for your dataset -### Integration -1. In a new folder, generate config file for integration, `panpipes integration config` and edit the pipeline.yml file. -2. Run `panpipes integration make plot_pcas` and assess the post filtering qc plots, and pca outputs -3. Run batch correction with `panpipes integration make batch_correction` (or run steps 2 and 3 in one go with `panpipes integration make full`) -4. Use pipeline outputs to decide on the best batch correction method -5. Edit the integration pipeline yml with your preferred batch correction -6. Run `panpipes integration make merge_batch_correction` + - this is explained step by step within the pipeline.yml file + +6. Run complete qc pipeline with ``panpipes qc_mm make full`` +7. Use outputs to decide filtering thresholds. -### Refmap + - **Note that the actual filtering occurs in the first step of + Preprocess pipeline** + - TODO: create doc to explain the pipeline outputs -1. In a new folder, generate config file for integration, `panpipes refmap config` and edit the pipeline.yml file. -2. Run complete refmap pipeline with `panpipes refmap make full ` +The h5mu file outputted from ``qc_mm`` contains concatenated raw counts +from all samples in the submission file, plus qc metrics are computed, +and these qc metrics are visualised in a variety of plots to aid the +user to determine data quality and filtering thresholds. -### Clustering +Preprocess +~~~~~~~~~~ -1. In a new folder, generate config file for integration, `panpipes clustering config` and edit the pipeline.yml file. -2. Run the clustering pipeline `panpipes clustering make cluster_analysis`. This will do the initial nearest neighbours and clustering for the parameters you specify. -3. Decide on the best values for k nearest neighbours based on UMAPs and clustree results. Once decided delete the folders for the parameters you don't need and delete those from the pipeline.yml. -4. Find markers for each of your cluster resolutions with `panpipes clustering make marker_analysis` -(Again you could run all the clustering pipeline at once with `panpipes clustering make full` but by making decisions along the way you'll reduce the computation and file size burden of the pipeline) +1. In a new folder, generate config file for integration, + ``panpipes preprocess config`` +2. edit the pipeline.yml file -### Vis -1. In a new folder, generate config file for integration, `panpipes vis config` and edit the pipeline.yml file. -2. Prepare plotting gene list files - - [more details](https://github.com/DendrouLab/panpipes/blob/main/docs/gene_list_format.md) -3. Run complete refmap pipeline with `panpipes vis make full ` + - The filtering options are dynamic depending on your qc_mm inputs + `more details + here `__ + - There are lots of options for normalisation explained in the + pipeline.yml -To repeat the pipeline after editing the pipeline.yml, delete the files in log and repeat step 3. +3. Run complete preprocess pipeline with + ``panpipes preprocess make full`` +The h5mu outputted from ``preprocess`` is filtered and normalised, and +for rna highly variable genes are computed. -# Running pipeline modules from different entry points. -[see details](https://github.com/DendrouLab/panpipes/blob/main/docs/different_entry_points.md) \ No newline at end of file +Integration +~~~~~~~~~~~ + +1. In a new folder, generate config file for integration, + ``panpipes integration config`` and edit the pipeline.yml file. +2. Run ``panpipes integration make plot_pcas`` and assess the post + filtering qc plots, and pca outputs +3. Run batch correction with + ``panpipes integration make batch_correction`` (or run steps 2 and 3 + in one go with ``panpipes integration make full``) +4. Use pipeline outputs to decide on the best batch correction method +5. Edit the integration pipeline yml with your preferred batch + correction +6. Run ``panpipes integration make merge_batch_correction`` + +Refmap +~~~~~~ + +1. In a new folder, generate config file for integration, + ``panpipes refmap config`` and edit the pipeline.yml file. +2. Run complete refmap pipeline with ``panpipes refmap make full`` + +Clustering +~~~~~~~~~~ + +1. In a new folder, generate config file for integration, + ``panpipes clustering config`` and edit the pipeline.yml file. +2. Run the clustering pipeline + ``panpipes clustering make cluster_analysis``. This will do the + initial nearest neighbours and clustering for the parameters you + specify. +3. Decide on the best values for k nearest neighbours based on UMAPs and + clustree results. Once decided delete the folders for the parameters + you don’t need and delete those from the pipeline.yml. +4. Find markers for each of your cluster resolutions with + ``panpipes clustering make marker_analysis`` (Again you could run all + the clustering pipeline at once with + ``panpipes clustering make full`` but by making decisions along the + way you’ll reduce the computation and file size burden of the + pipeline) + +Vis +~~~ + +1. In a new folder, generate config file for integration, + ``panpipes vis config`` and edit the pipeline.yml file. +2. Prepare plotting gene list files + + - `more + details `__ + +3. Run complete refmap pipeline with ``panpipes vis make full`` + +To repeat the pipeline after editing the pipeline.yml, delete the files +in log and repeat step 3. + +Running pipeline modules from different entry points. +===================================================== + +`see +details `__ From 82b76bbaf08dda59b6e511fa00e3c64171106257 Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:48:52 +0100 Subject: [PATCH 013/134] install docs to rst --- docs/index.rst | 22 +++++-- docs/install.rst | 163 +++++++++++++++++++++++++++++++++++++++++++++++ docs/usage.rst | 2 +- 3 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 docs/install.rst diff --git a/docs/index.rst b/docs/index.rst index 3d780126..ef2b1fb2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,12 +16,22 @@ doi: https://doi.org/10.1101/2023.03.11.532085 These pipelines use cgat-core pipeline software Available pipelines: -1. "qc_mm" : for the ingestion of data and computation of QC metrics' -2. "preprocess" : for filtering and normalising of each modality -3. "integration" : integrate and batch correction using single and multimodal methods -4. "clustering" : cell clustering on single modalities -5. "refmap" : transfer scvi-tools models from published data to your data -6. "vis" : visualise metrics from other pipelines in context of experiment metadata + +1. **qc_mm** : for the ingestion of data and computation of QC metrics' +2. **preprocess** : for filtering and normalising of each modality +3. **integration** : integrate and batch correction using single and multimodal methods +4. **clustering** : cell clustering on single modalities +5. **refmap** : transfer scvi-tools models from published data to your data +6. **vis** : visualise metrics from other pipelines in context of experiment metadata Check out the :doc:`usage` section for further information, including how to :ref:`installation` the project. + + +Contents +-------- + +.. toctree:: + + install + api \ No newline at end of file diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 00000000..865515bd --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,163 @@ +Insallation of panpipes +----------------------- + +Step 1 create virutal environment: +'''''''''''''''''''''''''''''''''' + +It is advisable to run everything in a virtual environment either pip or +conda. + +Using pip venv Navigate to where you want to create your virtual +environment and follow the steps below to create a pip virtual +environment + +:: + + + python3 -m venv --prompt=panpipes python3-venv-panpipes/ + # This will create a panpipes/venv folder + +activate the environment + +:: + + source python3-venv-panpipes/bin/activate + +**OR** using conda: + +:: + + conda create --name pipeline_env python=3.8.6 + conda activate pipeline_env + +we include an environment.yml for a conda environment tested on all the +pipelines packaged in this version of Panpipes. + +Step 2 Download and install this repo +''''''''''''''''''''''''''''''''''''' + +If you have not already set up SSH keys for github first follow these +`instructions `__: + +:: + + git clone https://github.com/DendrouLab/panpipes + cd panpipes + pip install . + +.. raw:: html + + + +The pipelines are now installed as a local python package. + +Step 3 installing R requirements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The pipelines use R (mostly for ggplot visualisations). + +If you are using a venv virtual environment, the pipeline will call a +local R installation, so make sure R is installed and install the +required packages with the following command + +From within the panpipes repo folder run: +``Rscript panpipes/R_scripts/install_R_libs.R`` + +.. raw:: html + + + +Step 4 pipeline configuration (for SGE or SLURM) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create a yml file for the cgat core pipeline software to read + +:: + + vim ~/.cgat.yml + +For SGE servers: + +:: + + cluster: + queue_manager: sge + queue: short + condaenv: + +For Slurm servers: + +:: + + cluster: + queue_manager: slurm + queue: short + +There are likely other options that relate to **your specific server**, +e.g.  These are added as + +:: + + cluster: + queue_manager: slurm + queue: short + options: --qos=xxx --exclude=compute-node-0[02-05,08-19],compute-node-010-0[05,07,35,37,51,64,68-71] + +See `cgat-core +documentation `__ +for cluster specific additional configuration instructions. + +Note that there is extra information on the .cgat.yml for Oxford BMRC +rescomp users in +`docs/installation_rescomp `__ + +DRMAA library path +~~~~~~~~~~~~~~~~~~ + +if ``echo $DRMAA_LIBRARY_PATH`` does not return anything, add +DRMAA_LIBRARY_PATH to your bash environment (the line below is specific +to the rescomp server) You need to find the path to this libdrmaa.so.1.0 +file on your server, ask your sys admin if you cannot find it! + +:: + + PATH_TO_DRMAA = "" + echo "export DRMAA_LIBRARY_PATH=$PATH_TO/libdrmaa.so.1.0" >> ~/.bashrc + +Conda environments +~~~~~~~~~~~~~~~~~~ + +If one or more conda environments are needed to run each of the +pipelines, (i.e. one pipeline = one environment) the environment (s) +should be specified in the .cgat.yml file or in the pipeline.yml +configuration file and it will be picked up by the pipeline as the +default environment. + +If no environment is specified, the default behaviour of the pipeline is +to inherit environment variables from the node where the pipeline is +run. However there have been reported issues on SLURM clusters where +this was not the default behaviour. In those instances we recommend to +add the conda environment param in the .cgat.yml file or in each of the +pipeline.yml independently. + +i.e. : + +:: + + + cluster: + queue_manager: slurm + queue: cpu_p + options: --qos=xxx --exclude=compute-node-0[02-05,08-19],compute-node-010-0[05,07,35,37,51,64,68-71] + condaenv: pipeline_env + +To check the installation was successful run the following line + +:: + + panpipes --help + +A list of available pipelines should appear! diff --git a/docs/usage.rst b/docs/usage.rst index 29454924..f23a8394 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,4 +1,4 @@ -Installation and configuration +Installation ============================== See `installation instrcutions From 1d84eccb7ef8f16dcf21e6140a6821b502738d56 Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Fri, 7 Jul 2023 12:57:33 +0100 Subject: [PATCH 014/134] updated structure --- docs/contributors.rst | 2 ++ docs/index.rst | 9 ++++++++- docs/install.rst | 2 +- docs/references.rst | 2 ++ docs/release_notes.rst | 2 ++ docs/tutorials.rst | 2 ++ docs/usage.rst | 10 +++++----- 7 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 docs/contributors.rst create mode 100644 docs/references.rst create mode 100644 docs/release_notes.rst create mode 100644 docs/tutorials.rst diff --git a/docs/contributors.rst b/docs/contributors.rst new file mode 100644 index 00000000..766bf83c --- /dev/null +++ b/docs/contributors.rst @@ -0,0 +1,2 @@ +Contributors +============= \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index ef2b1fb2..d0c81239 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -32,6 +32,13 @@ Contents -------- .. toctree:: + :maxdepth: 2 + :hidden: + usage + tutorials install - api \ No newline at end of file + api + release_notes + contributors + references diff --git a/docs/install.rst b/docs/install.rst index 865515bd..5afd9b6b 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -1,4 +1,4 @@ -Insallation of panpipes +Installation ----------------------- Step 1 create virutal environment: diff --git a/docs/references.rst b/docs/references.rst new file mode 100644 index 00000000..f97cb5b2 --- /dev/null +++ b/docs/references.rst @@ -0,0 +1,2 @@ +References +========== \ No newline at end of file diff --git a/docs/release_notes.rst b/docs/release_notes.rst new file mode 100644 index 00000000..f530ad24 --- /dev/null +++ b/docs/release_notes.rst @@ -0,0 +1,2 @@ +Release Notes +============== diff --git a/docs/tutorials.rst b/docs/tutorials.rst new file mode 100644 index 00000000..f08b66f9 --- /dev/null +++ b/docs/tutorials.rst @@ -0,0 +1,2 @@ +Tutorials +========= \ No newline at end of file diff --git a/docs/usage.rst b/docs/usage.rst index f23a8394..adb17553 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,4 +1,4 @@ -Installation +Usage guidelines ============================== See `installation instrcutions @@ -8,7 +8,7 @@ Oxford BMRC Rescomp users find additional advice in `docs/installation_rescomp `__ General principles for running pipelines -======================================== +'''''''''''''''''''''''''''''''''' Run the pipeline from the login node on your server, it will use in built the job submission system to submit jobs. @@ -51,8 +51,8 @@ this you can run any task in the ``show full`` list such as: panpipes qc_mm make plot_tenx_metrics -Running the complete pipeline -============================= +Pipeline components +'''''''''''''''''''''''''''''''''' Run each of pipeline qc, integration and clustering in separate folders. ### QC @@ -163,7 +163,7 @@ To repeat the pipeline after editing the pipeline.yml, delete the files in log and repeat step 3. Running pipeline modules from different entry points. -===================================================== +'''''''''''''''''''''''''''''''''' `see details `__ From 8ec964cd89a7e553ea8440c437ef91b8364ca387 Mon Sep 17 00:00:00 2001 From: Charlotte Rich-Griffin <25774602+crichgriffin@users.noreply.github.com> Date: Fri, 7 Jul 2023 13:35:36 +0100 Subject: [PATCH 015/134] structure and logo --- docs/components/clustering.rst | 21 +++++ docs/components/integration.rst | 15 +++ docs/components/preprocess.rst | 20 ++++ docs/components/qc.rst | 43 +++++++++ docs/components/refmap.rst | 6 ++ docs/components/vis.rst | 16 ++++ docs/conf.py | 7 ++ docs/img/figure1_simplified.drawio.png | Bin 0 -> 175473 bytes docs/img/panpipes_logo.png | Bin 0 -> 90683 bytes docs/img/panpipes_logo3.png | Bin 0 -> 112308 bytes docs/img/panpipes_logo_small.png | Bin 0 -> 13511 bytes docs/img/panpipeslogo2.png | Bin 0 -> 148376 bytes docs/index.rst | 3 +- docs/usage.rst | 125 +++---------------------- 14 files changed, 143 insertions(+), 113 deletions(-) create mode 100644 docs/components/clustering.rst create mode 100644 docs/components/integration.rst create mode 100644 docs/components/preprocess.rst create mode 100644 docs/components/qc.rst create mode 100644 docs/components/refmap.rst create mode 100644 docs/components/vis.rst create mode 100644 docs/img/figure1_simplified.drawio.png create mode 100644 docs/img/panpipes_logo.png create mode 100644 docs/img/panpipes_logo3.png create mode 100644 docs/img/panpipes_logo_small.png create mode 100644 docs/img/panpipeslogo2.png diff --git a/docs/components/clustering.rst b/docs/components/clustering.rst new file mode 100644 index 00000000..9ef7f4d9 --- /dev/null +++ b/docs/components/clustering.rst @@ -0,0 +1,21 @@ +Clustering +=========== + + + + +1. In a new folder, generate config file for integration, + ``panpipes clustering config`` and edit the pipeline.yml file. +2. Run the clustering pipeline + ``panpipes clustering make cluster_analysis``. This will do the + initial nearest neighbours and clustering for the parameters you + specify. +3. Decide on the best values for k nearest neighbours based on UMAPs and + clustree results. Once decided delete the folders for the parameters + you don’t need and delete those from the pipeline.yml. +4. Find markers for each of your cluster resolutions with + ``panpipes clustering make marker_analysis`` (Again you could run all + the clustering pipeline at once with + ``panpipes clustering make full`` but by making decisions along the + way you’ll reduce the computation and file size burden of the + pipeline) \ No newline at end of file diff --git a/docs/components/integration.rst b/docs/components/integration.rst new file mode 100644 index 00000000..94e1a2d7 --- /dev/null +++ b/docs/components/integration.rst @@ -0,0 +1,15 @@ +Integration +============ + + +1. In a new folder, generate config file for integration, + ``panpipes integration config`` and edit the pipeline.yml file. +2. Run ``panpipes integration make plot_pcas`` and assess the post + filtering qc plots, and pca outputs +3. Run batch correction with + ``panpipes integration make batch_correction`` (or run steps 2 and 3 + in one go with ``panpipes integration make full``) +4. Use pipeline outputs to decide on the best batch correction method +5. Edit the integration pipeline yml with your preferred batch + correction +6. Run ``panpipes integration make merge_batch_correction`` \ No newline at end of file diff --git a/docs/components/preprocess.rst b/docs/components/preprocess.rst new file mode 100644 index 00000000..9c135df6 --- /dev/null +++ b/docs/components/preprocess.rst @@ -0,0 +1,20 @@ +Preprocessing +============= + + + +1. In a new folder, generate config file for integration, + ``panpipes preprocess config`` +2. edit the pipeline.yml file + + - The filtering options are dynamic depending on your qc_mm inputs + `more details + here `__ + - There are lots of options for normalisation explained in the + pipeline.yml + +3. Run complete preprocess pipeline with + ``panpipes preprocess make full`` + +The h5mu outputted from ``preprocess`` is filtered and normalised, and +for rna highly variable genes are computed. \ No newline at end of file diff --git a/docs/components/qc.rst b/docs/components/qc.rst new file mode 100644 index 00000000..42c63be1 --- /dev/null +++ b/docs/components/qc.rst @@ -0,0 +1,43 @@ +QC +==== + + + +1. Generate sample submission file + + - `more details on creating the submission + file `__ + +2. Generate qc genelists + + - `more + details `__ + +3. For adt assay - generate the protein metadata file + `example <(https://github.com/DendrouLab/panpipes/blob/main/resources/protein_metadata_w_iso.md)>`__. + This file is integrated into the mdata[‘prot’].var slot. +4. Generate config file (``panpipes qc_mm config``) +5. Edit the pipeline.yml file for your dataset + + - this is explained step by step within the pipeline.yml file + +6. Run complete qc pipeline with ``panpipes qc_mm make full`` +7. Use outputs to decide filtering thresholds. + + - **Note that the actual filtering occurs in the first step of + Preprocess pipeline** + - TODO: create doc to explain the pipeline outputs + +The h5mu file outputted from ``qc_mm`` contains concatenated raw counts +from all samples in the submission file, plus qc metrics are computed, +and these qc metrics are visualised in a variety of plots to aid the +user to determine data quality and filtering thresholds. + + + + +Running pipeline modules from different entry points. +'''''''''''''''''''''''''''''''''' + +`see +details `__ diff --git a/docs/components/refmap.rst b/docs/components/refmap.rst new file mode 100644 index 00000000..4ca41b9c --- /dev/null +++ b/docs/components/refmap.rst @@ -0,0 +1,6 @@ +Refmap +======= + +1. In a new folder, generate config file for integration, + ``panpipes refmap config`` and edit the pipeline.yml file. +2. Run complete refmap pipeline with ``panpipes refmap make full`` diff --git a/docs/components/vis.rst b/docs/components/vis.rst new file mode 100644 index 00000000..af48a473 --- /dev/null +++ b/docs/components/vis.rst @@ -0,0 +1,16 @@ +visualisation +============= + + + +1. In a new folder, generate config file for integration, + ``panpipes vis config`` and edit the pipeline.yml file. +2. Prepare plotting gene list files + + - `more + details `__ + +3. Run complete refmap pipeline with ``panpipes vis make full`` + +To repeat the pipeline after editing the pipeline.yml, delete the files +in log and repeat step 3. \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 0315437b..2b94d5f8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,6 +30,13 @@ # -- Options for HTML output html_theme = 'sphinx_rtd_theme' +html_static_path = ['_static'] +html_logo = "img/panpipeslogo2.png" +html_theme_options = { + 'logo_only': True, + 'display_version': False +} + # -- Options for EPUB output epub_show_urls = 'footnote' \ No newline at end of file diff --git a/docs/img/figure1_simplified.drawio.png b/docs/img/figure1_simplified.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..9e62089e3530f8385a03ad15acd66515cbc94105 GIT binary patch literal 175473 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