From e2bd3b5ec50b3f251e9cc9902b05d72dc134016b Mon Sep 17 00:00:00 2001 From: mjemons Date: Tue, 19 Aug 2025 14:46:23 +0200 Subject: [PATCH 1/6] first few 3D metrics --- docs/index.rst | 1 + docs/modules/theedimensional_metrics.rst | 9 ++++++ src/segtraq/tm/__init__.py | 7 +++++ src/segtraq/tm/threedimensional_metrics.py | 36 ++++++++++++++++++++++ tests/tm/test_shape_metrics.py | 11 +++++++ 5 files changed, 64 insertions(+) create mode 100644 docs/modules/theedimensional_metrics.rst create mode 100644 src/segtraq/tm/__init__.py create mode 100644 src/segtraq/tm/threedimensional_metrics.py create mode 100644 tests/tm/test_shape_metrics.py diff --git a/docs/index.rst b/docs/index.rst index a436b83..ea5d6cf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,6 +16,7 @@ SegTraQ documentation modules/clustering_stability modules/nuclear_correlation modules/spillover_metrics + modules/threedimensional_metrics .. toctree:: :maxdepth: 1 diff --git a/docs/modules/theedimensional_metrics.rst b/docs/modules/theedimensional_metrics.rst new file mode 100644 index 0000000..554a9fe --- /dev/null +++ b/docs/modules/theedimensional_metrics.rst @@ -0,0 +1,9 @@ +.. highlight:: shell + +=================================================== +The three-dimensional metrics (:code:`sp`) accessor +=================================================== + +The three-dimensional metrics accessor provides metrics to quantify the distribution of transcripts along the $z$-axis +.. automodule:: segtraq.tm.threedimensional_metrics + :members: \ No newline at end of file diff --git a/src/segtraq/tm/__init__.py b/src/segtraq/tm/__init__.py new file mode 100644 index 0000000..158da9e --- /dev/null +++ b/src/segtraq/tm/__init__.py @@ -0,0 +1,7 @@ +from .threedimensional_metrics import ( + shape_metrics, +) + +__all__ = [ + "shape_metrics", +] diff --git a/src/segtraq/tm/threedimensional_metrics.py b/src/segtraq/tm/threedimensional_metrics.py new file mode 100644 index 0000000..03e2520 --- /dev/null +++ b/src/segtraq/tm/threedimensional_metrics.py @@ -0,0 +1,36 @@ +import numpy as np +import pandas as pd +import spatialdata as sd +from scipy.stats import kurtosis, skew + +def shape_metrics( + sdata: sd.SpatialData, + transcript_key: str = "transcripts", + z_coordinate: str = "z" + ) -> pd.DataFrame: + + """ + Calculates shape statistics (mean, variance, skew, kurtosis) based on the first four moments of the distribution + + Parameters + ---------- + sdata : sd.SpatialData + The SpatialData object containing spatial transcriptomics data. + transcript_key : str, optional + The key in the transcript table indicating transcript identifiers. Default is "transcripts". + z_coordinate : str, optional + The coordinate name of the z coordinate + + + Returns + ------- + pd.DataFrame + A DataFrame with columns `["mean", "variance", "skew, "kurtosis"]` + """ + + + z = np.array(sdata.points[transcript_key][z_coordinate]) + + df_res = pd.DataFrame(mean = np.mean(z), variance = np.var(z), skew = skew(z), kurtosis = kurtosis(z)) + + return(df_res) \ No newline at end of file diff --git a/tests/tm/test_shape_metrics.py b/tests/tm/test_shape_metrics.py new file mode 100644 index 0000000..55c835b --- /dev/null +++ b/tests/tm/test_shape_metrics.py @@ -0,0 +1,11 @@ +import pandas as pd + +import segtraq as st + + +def test_shape_metrics_structure(sdata_new): + df = st.tm.shape_metrics(sdata_new) + + assert isinstance(df, pd.DataFrame), f"shape_metrics should return a DataFrame, got {type(df)}" + expected_cols = {"mean", "variance", "skew", "kurtosis"} + assert set(df.columns) == expected_cols, f"Expected columns {expected_cols}, but got {set(df.columns)}" From fd9094560fdfb6dcdbe9e6b0aedd32b8bb3439b0 Mon Sep 17 00:00:00 2001 From: mjemons Date: Tue, 19 Aug 2025 14:50:14 +0200 Subject: [PATCH 2/6] add tm module --- src/segtraq/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segtraq/__init__.py b/src/segtraq/__init__.py index a1f5728..c02c5b5 100644 --- a/src/segtraq/__init__.py +++ b/src/segtraq/__init__.py @@ -5,4 +5,4 @@ from . import bl, cs, nc, sp -__all__ = ["bl", "cs", "nc", "sp"] +__all__ = ["bl", "cs", "nc", "sp", "tm"] From d19663f432bc30cd79562ca7656f5f3d6c03c074 Mon Sep 17 00:00:00 2001 From: mjemons Date: Tue, 19 Aug 2025 14:52:55 +0200 Subject: [PATCH 3/6] add module tm --- src/segtraq/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segtraq/__init__.py b/src/segtraq/__init__.py index c02c5b5..f1702c6 100644 --- a/src/segtraq/__init__.py +++ b/src/segtraq/__init__.py @@ -3,6 +3,6 @@ __author__ = """Daria Lazic, Matthias Meyer-Bender, Martin Emons""" __email__ = "daria.lazic@embl.de, matthias.meyerbender@embl.de, martin.emons@uzh.ch" -from . import bl, cs, nc, sp +from . import bl, cs, nc, sp, tm __all__ = ["bl", "cs", "nc", "sp", "tm"] From 80c8e733e208660067e677e2772c8a5d79da9ab4 Mon Sep 17 00:00:00 2001 From: mjemons Date: Tue, 19 Aug 2025 15:52:42 +0200 Subject: [PATCH 4/6] changes to result storage --- src/segtraq/tm/threedimensional_metrics.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/segtraq/tm/threedimensional_metrics.py b/src/segtraq/tm/threedimensional_metrics.py index 03e2520..d074b88 100644 --- a/src/segtraq/tm/threedimensional_metrics.py +++ b/src/segtraq/tm/threedimensional_metrics.py @@ -25,12 +25,12 @@ def shape_metrics( Returns ------- pd.DataFrame - A DataFrame with columns `["mean", "variance", "skew, "kurtosis"]` + A DataFrame with keys `["mean", "variance", "skew, "kurtosis"]` """ z = np.array(sdata.points[transcript_key][z_coordinate]) - df_res = pd.DataFrame(mean = np.mean(z), variance = np.var(z), skew = skew(z), kurtosis = kurtosis(z)) - - return(df_res) \ No newline at end of file + d = {"mean" : np.mean(z), "variance" : np.var(z), "skew" : skew(z), "kurtosis" : kurtosis(z)} + df = pd.DataFrame(data = d) + return(df) \ No newline at end of file From 935e68f7e78c589c46906abe2ac338c38a246431 Mon Sep 17 00:00:00 2001 From: mjemons Date: Tue, 19 Aug 2025 15:56:06 +0200 Subject: [PATCH 5/6] pass index --- src/segtraq/tm/threedimensional_metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segtraq/tm/threedimensional_metrics.py b/src/segtraq/tm/threedimensional_metrics.py index d074b88..268e477 100644 --- a/src/segtraq/tm/threedimensional_metrics.py +++ b/src/segtraq/tm/threedimensional_metrics.py @@ -32,5 +32,5 @@ def shape_metrics( z = np.array(sdata.points[transcript_key][z_coordinate]) d = {"mean" : np.mean(z), "variance" : np.var(z), "skew" : skew(z), "kurtosis" : kurtosis(z)} - df = pd.DataFrame(data = d) + df = pd.DataFrame(data = d, index = 0) return(df) \ No newline at end of file From 3e04eaea6051c5a7402c9a616690b79ff34abf8e Mon Sep 17 00:00:00 2001 From: mjemons Date: Thu, 9 Oct 2025 10:40:16 +0200 Subject: [PATCH 6/6] fixing index issue --- src/segtraq/tm/threedimensional_metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segtraq/tm/threedimensional_metrics.py b/src/segtraq/tm/threedimensional_metrics.py index 268e477..3823122 100644 --- a/src/segtraq/tm/threedimensional_metrics.py +++ b/src/segtraq/tm/threedimensional_metrics.py @@ -32,5 +32,5 @@ def shape_metrics( z = np.array(sdata.points[transcript_key][z_coordinate]) d = {"mean" : np.mean(z), "variance" : np.var(z), "skew" : skew(z), "kurtosis" : kurtosis(z)} - df = pd.DataFrame(data = d, index = 0) + df = pd.DataFrame(data = d, index = [0]) return(df) \ No newline at end of file