diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f762b1..57a86dc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,11 +11,11 @@ repos: hooks: - id: prettier - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.5.0 + rev: v2.11.1 hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.2 + rev: v0.14.10 hooks: - id: ruff types_or: [python, pyi, jupyter] @@ -23,7 +23,7 @@ repos: - id: ruff-format types_or: [python, pyi, jupyter] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: detect-private-key - id: check-ast diff --git a/README.md b/README.md index 2268420..edc697b 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you don't have Python installed, we recommend installing [Mambaforge][]. There are several alternative options to install troutpy: -1) Install the latest release of `troutpy` from [PyPI][]: +1. Install the latest release of `troutpy` from [PyPI][]: ```bash pip install troutpy @@ -43,6 +43,7 @@ import troutpy as tp ``` ## Reproducibility + Code, notebooks, and instructions to reproduce the results from the paper are available at the [reproducibility repository](https://github.com/theislab/troutpy_reproducibility). This repository also include diverse tutorials and compementary functions that are not core to Troutpy, but are required to reproduce the figures from Marco Salas et al. 2025. ## Release notes diff --git a/docs/.ipynb_checkpoints/index-checkpoint.md b/docs/.ipynb_checkpoints/index-checkpoint.md index ee72575..e168f7c 100644 --- a/docs/.ipynb_checkpoints/index-checkpoint.md +++ b/docs/.ipynb_checkpoints/index-checkpoint.md @@ -11,6 +11,7 @@ Tools Plotting ``` + ```{toctree} :maxdepth: 3 :caption: Tutorials @@ -26,4 +27,4 @@ changelog.md contributing.md references.md -``` \ No newline at end of file +``` diff --git a/docs/.ipynb_checkpoints/references-checkpoint.bib b/docs/.ipynb_checkpoints/references-checkpoint.bib index 9415d33..a75dc79 100644 --- a/docs/.ipynb_checkpoints/references-checkpoint.bib +++ b/docs/.ipynb_checkpoints/references-checkpoint.bib @@ -38,4 +38,4 @@ @article{blampey2024sopa pages={4981}, year={2024}, publisher={Nature Publishing Group UK London} -} \ No newline at end of file +} diff --git a/docs/api/.ipynb_checkpoints/plotting-checkpoint.md b/docs/api/.ipynb_checkpoints/plotting-checkpoint.md index 5e4ea7c..e643e37 100644 --- a/docs/api/.ipynb_checkpoints/plotting-checkpoint.md +++ b/docs/api/.ipynb_checkpoints/plotting-checkpoint.md @@ -8,7 +8,7 @@ .. autosummary:: :toctree: generated/basic_plots - + crosstab histogram pie @@ -23,7 +23,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/quantification - + gene_metric_heatmap logfoldratio_over_noise metric_scatter @@ -33,18 +33,15 @@ moranI_histogram diffusion_results spatial_inout_expression - -``` - - +``` ## Source, target and communication ```{eval-rst} .. autosummary:: :toctree: generated/communication - + celltype_communication gene_communication global_distribution_from_source @@ -54,7 +51,7 @@ target_score_by_celltype interactions_with_arrows spatial_interactions - + ``` ## Factor analysis @@ -62,7 +59,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/factor_analysis - + factors_in_cells rank_factor_genes_loadings rank_factor_genes_loadings_matrixplot @@ -70,9 +67,8 @@ nmf_gene_contributions paired_nmf_factors apply_exrnaH_to_cellular_to_create_cellularW - -``` +``` ## Colormaps & palettes @@ -83,6 +79,3 @@ get_colormap get_palette ``` - - - diff --git a/docs/api/.ipynb_checkpoints/preprocessing-checkpoint.md b/docs/api/.ipynb_checkpoints/preprocessing-checkpoint.md index 9292295..d0f57fc 100644 --- a/docs/api/.ipynb_checkpoints/preprocessing-checkpoint.md +++ b/docs/api/.ipynb_checkpoints/preprocessing-checkpoint.md @@ -15,3 +15,4 @@ pp.define_urna pp.filter_urna pp.format_adata +``` diff --git a/docs/api/.ipynb_checkpoints/tools-checkpoint.md b/docs/api/.ipynb_checkpoints/tools-checkpoint.md index 5a64d75..cff9637 100644 --- a/docs/api/.ipynb_checkpoints/tools-checkpoint.md +++ b/docs/api/.ipynb_checkpoints/tools-checkpoint.md @@ -35,7 +35,7 @@ tl.calculate_target_cells tl.compute_target_score tl.define_target_by_celltype - tl.cluster_distribution_from_source + tl.cluster_distribution_from_source tl.get_gene_interaction_strength tl.communication_strength tl.gene_specific_interactions @@ -46,7 +46,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/cell_scores - + tl.compute_contribution_score ``` @@ -55,7 +55,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/factors - + tl.factors_to_cells tl.latent_factor ``` @@ -68,7 +68,7 @@ tl.assess_diffusion tl.compute_js_divergence - + ``` ## Multimodal quantication @@ -76,7 +76,6 @@ ```{eval-rst} .. autosummary:: :toctree: generated/multimodal - + tl.image_intensities_per_transcript ``` - diff --git a/docs/api/plotting.md b/docs/api/plotting.md index 5e4ea7c..e643e37 100644 --- a/docs/api/plotting.md +++ b/docs/api/plotting.md @@ -8,7 +8,7 @@ .. autosummary:: :toctree: generated/basic_plots - + crosstab histogram pie @@ -23,7 +23,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/quantification - + gene_metric_heatmap logfoldratio_over_noise metric_scatter @@ -33,18 +33,15 @@ moranI_histogram diffusion_results spatial_inout_expression - -``` - - +``` ## Source, target and communication ```{eval-rst} .. autosummary:: :toctree: generated/communication - + celltype_communication gene_communication global_distribution_from_source @@ -54,7 +51,7 @@ target_score_by_celltype interactions_with_arrows spatial_interactions - + ``` ## Factor analysis @@ -62,7 +59,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/factor_analysis - + factors_in_cells rank_factor_genes_loadings rank_factor_genes_loadings_matrixplot @@ -70,9 +67,8 @@ nmf_gene_contributions paired_nmf_factors apply_exrnaH_to_cellular_to_create_cellularW - -``` +``` ## Colormaps & palettes @@ -83,6 +79,3 @@ get_colormap get_palette ``` - - - diff --git a/docs/api/preprocessing.md b/docs/api/preprocessing.md index 9292295..d0f57fc 100644 --- a/docs/api/preprocessing.md +++ b/docs/api/preprocessing.md @@ -15,3 +15,4 @@ pp.define_urna pp.filter_urna pp.format_adata +``` diff --git a/docs/api/tools.md b/docs/api/tools.md index 5a64d75..cff9637 100644 --- a/docs/api/tools.md +++ b/docs/api/tools.md @@ -35,7 +35,7 @@ tl.calculate_target_cells tl.compute_target_score tl.define_target_by_celltype - tl.cluster_distribution_from_source + tl.cluster_distribution_from_source tl.get_gene_interaction_strength tl.communication_strength tl.gene_specific_interactions @@ -46,7 +46,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/cell_scores - + tl.compute_contribution_score ``` @@ -55,7 +55,7 @@ ```{eval-rst} .. autosummary:: :toctree: generated/factors - + tl.factors_to_cells tl.latent_factor ``` @@ -68,7 +68,7 @@ tl.assess_diffusion tl.compute_js_divergence - + ``` ## Multimodal quantication @@ -76,7 +76,6 @@ ```{eval-rst} .. autosummary:: :toctree: generated/multimodal - + tl.image_intensities_per_transcript ``` - diff --git a/docs/index.md b/docs/index.md index ee72575..e168f7c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,6 +11,7 @@ Tools Plotting ``` + ```{toctree} :maxdepth: 3 :caption: Tutorials @@ -26,4 +27,4 @@ changelog.md contributing.md references.md -``` \ No newline at end of file +``` diff --git a/docs/references.bib b/docs/references.bib index 9415d33..a75dc79 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -38,4 +38,4 @@ @article{blampey2024sopa pages={4981}, year={2024}, publisher={Nature Publishing Group UK London} -} \ No newline at end of file +} diff --git a/pyproject.toml b/pyproject.toml index 53f9c21..9b8f42a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] dependencies = [ @@ -34,7 +35,7 @@ dependencies = [ "sainsc", # Version not specified; verify if necessary "scikit-learn>=1.6.1", "seaborn", - "sopa[cellpose,baysor]", + "sopa[baysor,cellpose]", "spatialdata", "spatialdata-io", "spatialdata-plot", diff --git a/src/troutpy/pl/__init__.py b/src/troutpy/pl/__init__.py index 2bbf9c3..25a3300 100644 --- a/src/troutpy/pl/__init__.py +++ b/src/troutpy/pl/__init__.py @@ -1,6 +1,6 @@ from .basic import crosstab, histogram, pie from .colors import get_colormap, get_palette -from .communication import cell_type_contacts, gene_communication, target_score_by_celltype +from .communication import cell_type_contacts, gene_communication, target_score_by_celltype from .factor_analysis import factors_in_cells, rank_factor_genes_loadings, rank_factor_genes_loadings_matrixplot from .metric_analysis import gene_metric_heatmap, logfoldratio_over_noise, metric_scatter, top_bottom_probes from .plotting import ( diff --git a/src/troutpy/pl/communication.py b/src/troutpy/pl/communication.py index 0db8e41..ec6b818 100644 --- a/src/troutpy/pl/communication.py +++ b/src/troutpy/pl/communication.py @@ -6,15 +6,18 @@ from mpl_chord_diagram import chord_diagram from spatialdata import SpatialData + def cell_type_contacts( sdata, kind="heatmap", celltype_key="cell type", vmax=None, vmin=None, - cmap="BuPu",table_key='table', - dendrogram_ratio=0.1,key='cell_contact_combined', - **kwargs + cmap="BuPu", + table_key="table", + dendrogram_ratio=0.1, + key="cell_contact_combined", + **kwargs, ): """Plot cell type-cell type interaction strength as a heatmap or chord diagram.""" interaction_strength = sdata["table"].uns[key] @@ -27,10 +30,7 @@ def cell_type_contacts( # Assign colors to cell types try: - cols = dict(zip( - np.unique(sdata["table"].obs[celltype_key]), - sdata["table"].uns[celltype_key + "_colors"], strict=False - )) + cols = dict(zip(np.unique(sdata["table"].obs[celltype_key]), sdata["table"].uns[celltype_key + "_colors"], strict=False)) colors = [cols[c] for c in source_table.var.index] except KeyError: colpalette = plt.get_cmap("tab20") @@ -47,20 +47,13 @@ def cell_type_contacts( col_colors=colors, dendrogram_ratio=dendrogram_ratio, cbar_pos=(0.02, 0.8, 0.02, 0.15), # Adjust colorbar position: (x, y, width, height) - **kwargs + **kwargs, ) g.fig.suptitle(key, y=1.05) g.ax_heatmap.grid(False) # remove grid from heatmap elif kind == "chord": - chord_diagram( - celltype_ints, - source_table.var.index, - directed=True, - fontsize=6, - colors=colors, - **kwargs - ) + chord_diagram(celltype_ints, source_table.var.index, directed=True, fontsize=6, colors=colors, **kwargs) plt.title(key, fontweight="bold") plt.grid(False) diff --git a/src/troutpy/pl/plotting.py b/src/troutpy/pl/plotting.py index 06a1f46..b9d398b 100644 --- a/src/troutpy/pl/plotting.py +++ b/src/troutpy/pl/plotting.py @@ -290,7 +290,7 @@ def plot_crosstab( if kind == "barh": plt.figure() crosstab_data.plot(kind="barh", stacked=stacked, figsize=figsize, width=0.99, colormap=cmap) - plt.xlabel('Total number of transcripts') + plt.xlabel("Total number of transcripts") plt.title(f"{xvar}_vs_{yvar}") if save: plt.savefig(os.path.join(figures_path, plot_filename)) diff --git a/src/troutpy/tl/.ipynb_checkpoints/interactions-checkpoint.py b/src/troutpy/tl/.ipynb_checkpoints/interactions-checkpoint.py index 75c82e4..e40d853 100644 --- a/src/troutpy/tl/.ipynb_checkpoints/interactions-checkpoint.py +++ b/src/troutpy/tl/.ipynb_checkpoints/interactions-checkpoint.py @@ -200,10 +200,10 @@ def gene_specific_interactions(sdata, copy: bool = False, gene_key: str = "gene" return sdata.copy() if copy else None def cell_contacts_with_urna_sources( - sdata, - spatial_key: str = "spatial", - cell_type_key: str = "cell type", - distance: float = 50, + sdata, + spatial_key: str = "spatial", + cell_type_key: str = "cell type", + distance: float = 50, copy: bool = False, uns_prefix: str = "cell_contact" ): @@ -243,7 +243,7 @@ def cell_contacts_with_urna_sources( cell_ids = adata.obs_names.values cell_types = adata.obs[cell_type_key].values unique_cell_types = np.unique(cell_types) - + # Step 1: Compute spatial neighbors coords = np.asarray(adata.obsm[spatial_key]) tree = BallTree(coords) @@ -264,7 +264,7 @@ def keep_transcript(row): target = row['target_cell'] source = row['source_cell'] return (source != target) and (source not in neighbors_dict[target]) - + filtered_trans = trans_df[trans_df.apply(keep_transcript, axis=1)] # Step 4: Build extended neighborhoods (spatial + uRNA) @@ -277,7 +277,7 @@ def keep_transcript(row): # Step 5: Count matrices cell_type_map = dict(zip(cell_ids, cell_types)) - + def count_matrix_from_neighbors(neigh_dict): mat = pd.DataFrame(0, index=unique_cell_types, columns=unique_cell_types, dtype=int) for source_cell, neighbors in neigh_dict.items(): @@ -309,5 +309,3 @@ def count_matrix_from_neighbors(neigh_dict): "urna_specific": urna_specific_mat } return results if copy else None - - diff --git a/src/troutpy/tl/.ipynb_checkpoints/source_cell-checkpoint.py b/src/troutpy/tl/.ipynb_checkpoints/source_cell-checkpoint.py index a0c0d7e..0407dee 100644 --- a/src/troutpy/tl/.ipynb_checkpoints/source_cell-checkpoint.py +++ b/src/troutpy/tl/.ipynb_checkpoints/source_cell-checkpoint.py @@ -458,7 +458,7 @@ def store_results_in_sdata(sdata, prob_table, closest_table, extracellular_trans sdata["table"].obs['normalized_urna_source_score'] = adata.obs['urna_source_score'] / cell_expr_sum except KeyError: print('Normalized urna source score could not be computed') - + def compute_contribution_score(sdata): diff --git a/src/troutpy/tl/.ipynb_checkpoints/target_cell-checkpoint.py b/src/troutpy/tl/.ipynb_checkpoints/target_cell-checkpoint.py index cf96fe2..db5d8e3 100644 --- a/src/troutpy/tl/.ipynb_checkpoints/target_cell-checkpoint.py +++ b/src/troutpy/tl/.ipynb_checkpoints/target_cell-checkpoint.py @@ -239,4 +239,3 @@ def compute_target_score( sdata.tables["target_score"] = prob_table return sdata.copy() if copy else None - diff --git a/src/troutpy/tl/__init__.py b/src/troutpy/tl/__init__.py index fd1a0ff..f8f100e 100644 --- a/src/troutpy/tl/__init__.py +++ b/src/troutpy/tl/__init__.py @@ -1,7 +1,7 @@ from .estimate_density import colocalization_proportion from .factor_analysis import factors_to_cells, latent_factor from .image_quantification import image_intensities_per_transcript -from .interactions import communication_strength, gene_specific_interactions, get_gene_interaction_strength, cell_contacts_with_urna_sources +from .interactions import cell_contacts_with_urna_sources, communication_strength, gene_specific_interactions, get_gene_interaction_strength from .quantify_urna import ( assess_diffusion, cluster_distribution_from_source, diff --git a/src/troutpy/tl/factor_analysis.py b/src/troutpy/tl/factor_analysis.py index 1a53191..e1006b0 100644 --- a/src/troutpy/tl/factor_analysis.py +++ b/src/troutpy/tl/factor_analysis.py @@ -139,6 +139,7 @@ def latent_factor( sdata[layer] = adata return sdata if copy else None + def combine_loadings_arrays(gene_loadings_pos: np.ndarray, gene_loadings_neg: np.ndarray) -> np.ndarray: """Combines positive and negative gene loading arrays from DRVI analysis""" if gene_loadings_pos.shape != gene_loadings_neg.shape: @@ -152,8 +153,7 @@ def combine_loadings_arrays(gene_loadings_pos: np.ndarray, gene_loadings_neg: np # Raise warning if conflicts found if np.any(conflict_mask): conflict_indices = np.argwhere(conflict_mask) - warnings.warn(f"Conflicts found at {len(conflict_indices)} locations. " - f"Example: {conflict_indices[:5].tolist()}",stacklevel=2) + warnings.warn(f"Conflicts found at {len(conflict_indices)} locations. Example: {conflict_indices[:5].tolist()}", stacklevel=2) # Initialize combined output combined = np.zeros_like(gene_loadings_pos) @@ -163,7 +163,6 @@ def combine_loadings_arrays(gene_loadings_pos: np.ndarray, gene_loadings_neg: np return combined - def factors_to_cells( sdata: SpatialData, extracellular_layer: str = "segmentation_free_table", cellular_layer: str = "table", copy: bool | None = None ) -> SpatialData: diff --git a/src/troutpy/tl/interactions.py b/src/troutpy/tl/interactions.py index 75c82e4..cd10886 100644 --- a/src/troutpy/tl/interactions.py +++ b/src/troutpy/tl/interactions.py @@ -3,11 +3,9 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd +from sklearn.neighbors import BallTree from spatialdata import SpatialData from tqdm import tqdm -import pandas as pd -import numpy as np -from sklearn.neighbors import BallTree ####### LIKELY DEPRECATED######### @@ -199,13 +197,9 @@ def gene_specific_interactions(sdata, copy: bool = False, gene_key: str = "gene" return sdata.copy() if copy else None + def cell_contacts_with_urna_sources( - sdata, - spatial_key: str = "spatial", - cell_type_key: str = "cell type", - distance: float = 50, - copy: bool = False, - uns_prefix: str = "cell_contact" + sdata, spatial_key: str = "spatial", cell_type_key: str = "cell type", distance: float = 50, copy: bool = False, uns_prefix: str = "cell_contact" ): """ Compute neighbor count matrices: @@ -239,11 +233,11 @@ def cell_contacts_with_urna_sources( Dictionary with three DataFrames: {"cell_cell", "combined", "urna_specific"} if copy=True, otherwise None. """ - adata = sdata['table'] + adata = sdata["table"] cell_ids = adata.obs_names.values cell_types = adata.obs[cell_type_key].values unique_cell_types = np.unique(cell_types) - + # Step 1: Compute spatial neighbors coords = np.asarray(adata.obsm[spatial_key]) tree = BallTree(coords) @@ -251,33 +245,31 @@ def cell_contacts_with_urna_sources( neighbors_dict = {cell_id: cell_ids[neighbors] for cell_id, neighbors in zip(cell_ids, neighbors_idx)} # Step 2: Merge source and target transcript info - target_obs = sdata['target_score'].obs[['closest_cell', 'distance']].copy() - target_obs.rename(columns={'closest_cell': 'target_cell'}, inplace=True) - source_obs = sdata['source_score'].obs[['closest_cell']].copy() - source_obs.rename(columns={'closest_cell': 'source_cell'}, inplace=True) + target_obs = sdata["target_score"].obs[["closest_cell", "distance"]].copy() + target_obs.rename(columns={"closest_cell": "target_cell"}, inplace=True) + source_obs = sdata["source_score"].obs[["closest_cell"]].copy() + source_obs.rename(columns={"closest_cell": "source_cell"}, inplace=True) - trans_df = target_obs.join(source_obs, how='inner') - trans_df = trans_df[trans_df['distance'] <= distance] + trans_df = target_obs.join(source_obs, how="inner") + trans_df = trans_df[trans_df["distance"] <= distance] # Step 3: Filter out transcripts where source already in neighborhood or == target def keep_transcript(row): - target = row['target_cell'] - source = row['source_cell'] + target = row["target_cell"] + source = row["source_cell"] return (source != target) and (source not in neighbors_dict[target]) - + filtered_trans = trans_df[trans_df.apply(keep_transcript, axis=1)] # Step 4: Build extended neighborhoods (spatial + uRNA) extended_neighbors_dict = {cell_id: list(neighs) for cell_id, neighs in neighbors_dict.items()} - for target_cell, group in filtered_trans.groupby('target_cell'): - sources = group['source_cell'].values - extended_neighbors_dict[target_cell] = np.unique( - np.concatenate([extended_neighbors_dict[target_cell], sources]) - ) + for target_cell, group in filtered_trans.groupby("target_cell"): + sources = group["source_cell"].values + extended_neighbors_dict[target_cell] = np.unique(np.concatenate([extended_neighbors_dict[target_cell], sources])) # Step 5: Count matrices cell_type_map = dict(zip(cell_ids, cell_types)) - + def count_matrix_from_neighbors(neigh_dict): mat = pd.DataFrame(0, index=unique_cell_types, columns=unique_cell_types, dtype=int) for source_cell, neighbors in neigh_dict.items(): @@ -303,11 +295,5 @@ def count_matrix_from_neighbors(neigh_dict): adata.uns[f"{uns_prefix}_combined"] = combined_mat adata.uns[f"{uns_prefix}_urna_specific"] = urna_specific_mat - results = { - "cell_body": cell_cell_mat, - "combined": combined_mat, - "urna_specific": urna_specific_mat - } + results = {"cell_body": cell_cell_mat, "combined": combined_mat, "urna_specific": urna_specific_mat} return results if copy else None - - diff --git a/src/troutpy/tl/quantify_urna.py b/src/troutpy/tl/quantify_urna.py index c043717..d927ca7 100644 --- a/src/troutpy/tl/quantify_urna.py +++ b/src/troutpy/tl/quantify_urna.py @@ -208,7 +208,7 @@ def quantify_overexpression( try: sdata["xrna_metadata"] except KeyError: - create_urna_metadata(sdata, layer=layer,gene_key=gene_key) + create_urna_metadata(sdata, layer=layer, gene_key=gene_key) # select columns that will be overwritten existing_cols = sdata["xrna_metadata"].var.columns @@ -221,7 +221,7 @@ def quantify_overexpression( return sdata if copy else None -def extracellular_enrichment(sdata: SpatialData, gene_key: str = "gene", copy: bool = False,layer:str='transcripts'): +def extracellular_enrichment(sdata: SpatialData, gene_key: str = "gene", copy: bool = False, layer: str = "transcripts"): """ Computes the proportion of transcripts classified as extracellular or intracellular for each gene and calculates additional metrics, including log fold change of extracellular to intracellular proportions. The results are integrated into the `sdata` object under the 'xrna_metadata' layer. @@ -259,7 +259,7 @@ def extracellular_enrichment(sdata: SpatialData, gene_key: str = "gene", copy: b try: sdata["xrna_metadata"] except KeyError: - create_urna_metadata(sdata, layer=layer,gene_key=gene_key) + create_urna_metadata(sdata, layer=layer, gene_key=gene_key) # select columns that will be overwritten existing_cols = sdata["xrna_metadata"].var.columns @@ -451,7 +451,7 @@ def in_out_correlation( try: sdata["xrna_metadata"] except KeyError: - create_urna_metadata(sdata,gene_key=gene_key) + create_urna_metadata(sdata, gene_key=gene_key) sdata["xrna_metadata"].var["in_out_spearmanR"] = sdata["xrna_metadata"].var.index.map(gene2spearman) sdata["xrna_metadata"].var["in_out_pvalue"] = sdata["xrna_metadata"].var.index.map(gene2pval) diff --git a/src/troutpy/tl/source_cell.py b/src/troutpy/tl/source_cell.py index 0407dee..e654176 100644 --- a/src/troutpy/tl/source_cell.py +++ b/src/troutpy/tl/source_cell.py @@ -376,7 +376,7 @@ def process_gene(gene, extracellular_transcripts, cells, coord_cells, cell_types residual = 1e-6 # small stabilizing term row_sums = scores.sum(axis=1, keepdims=True) + residual scores = scores / row_sums - #scores=scores.div(scores.sum(axis=1),axis=0) + # scores=scores.div(scores.sum(axis=1),axis=0) gene_prob_df = compute_probability_table(scores, cell_indices, cell_types_filt, all_cell_types, gene_transcripts) gene_closest_df = build_closest_cell_table(distances_min, closest_cell_ids, closest_cell_types, gene_transcripts) @@ -452,13 +452,12 @@ def store_results_in_sdata(sdata, prob_table, closest_table, extracellular_trans sdata["table"].obs["urna_source_score"] = list(np.sum(cell_source_table, axis=1)) try: - adata=sdata['table'] - raw_expr=adata.layers['raw'] + adata = sdata["table"] + raw_expr = adata.layers["raw"] cell_expr_sum = np.array(np.sum(raw_expr.todense(), axis=1)).flatten() - sdata["table"].obs['normalized_urna_source_score'] = adata.obs['urna_source_score'] / cell_expr_sum + sdata["table"].obs["normalized_urna_source_score"] = adata.obs["urna_source_score"] / cell_expr_sum except KeyError: - print('Normalized urna source score could not be computed') - + print("Normalized urna source score could not be computed") def compute_contribution_score(sdata): @@ -509,4 +508,4 @@ def compute_contribution_score(sdata): score = contribution_matrix.sum(axis=1) adata.obs["urna_contribution_score"] = score - adata.obs["normalized_urna_contribution_score"]=score/np.sum(raw_expr,axis=1) + adata.obs["normalized_urna_contribution_score"] = score / np.sum(raw_expr, axis=1) diff --git a/src/troutpy/tl/target_cell.py b/src/troutpy/tl/target_cell.py index cf96fe2..dc6ecee 100644 --- a/src/troutpy/tl/target_cell.py +++ b/src/troutpy/tl/target_cell.py @@ -127,6 +127,7 @@ def define_target_by_celltype(sdata: SpatialData, layer="transcripts", closest_c return celltype_by_feature + def compute_target_score( sdata, layer: str = "transcripts", @@ -182,14 +183,8 @@ def compute_target_score( transcript_coords = extracellular_transcripts[[xcoord, ycoord]].to_numpy() # Output tables - target_scores_table = pd.DataFrame( - 0, index=extracellular_transcripts.index, columns=all_cell_types, dtype=float - ) - closest_cell_info = pd.DataFrame( - index=extracellular_transcripts.index, - columns=["distance", "closest_cell", "closest_cell_type"], - dtype=object - ) + target_scores_table = pd.DataFrame(0, index=extracellular_transcripts.index, columns=all_cell_types, dtype=float) + closest_cell_info = pd.DataFrame(index=extracellular_transcripts.index, columns=["distance", "closest_cell", "closest_cell_type"], dtype=object) # KDTree on cell centroids kdtree = KDTree(coord_cells) @@ -239,4 +234,3 @@ def compute_target_score( sdata.tables["target_score"] = prob_table return sdata.copy() if copy else None -