oncoordinate 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oncoordinate/HallmarkPathGMT/HALLMARK_ADIPOGENESIS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_ALLOGRAFT_REJECTION.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_ANDROGEN_RESPONSE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_ANGIOGENESIS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_APICAL_JUNCTION.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_APICAL_SURFACE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_APOPTOSIS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_BILE_ACID_METABOLISM.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_CHOLESTEROL_HOMEOSTASIS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_COAGULATION.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_COMPLEMENT.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_DNA_REPAIR.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_E2F_TARGETS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_ESTROGEN_RESPONSE_EARLY.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_ESTROGEN_RESPONSE_LATE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_FATTY_ACID_METABOLISM.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_G2M_CHECKPOINT.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_GLYCOLYSIS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_HEDGEHOG_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_HEME_METABOLISM.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_HYPOXIA.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_IL2_STAT5_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_IL6_JAK_STAT3_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_INFLAMMATORY_RESPONSE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_INTERFERON_ALPHA_RESPONSE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_INTERFERON_GAMMA_RESPONSE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_KRAS_SIGNALING_DN.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_KRAS_SIGNALING_UP.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_MITOTIC_SPINDLE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_MTORC1_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_MYC_TARGETS_V1.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_MYC_TARGETS_V2.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_MYOGENESIS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_NOTCH_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_OXIDATIVE_PHOSPHORYLATION.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_P53_PATHWAY.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_PANCREAS_BETA_CELLS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_PEROXISOME.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_PI3K_AKT_MTOR_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_PROTEIN_SECRETION.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_REACTIVE_OXYGEN_SPECIES_PATHWAY.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_SPERMATOGENESIS.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_TGF_BETA_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_TNFA_SIGNALING_VIA_NFKB.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_UNFOLDED_PROTEIN_RESPONSE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_UV_RESPONSE_DN.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_UV_RESPONSE_UP.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_WNT_BETA_CATENIN_SIGNALING.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/HALLMARK_XENOBIOTIC_METABOLISM.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/REACTOME_CELL_CYCLE.v2023.2.Hs.gmt +1 -0
- oncoordinate/HallmarkPathGMT/REACTOME_SIGNALING_BY_EGFR_IN_CANCER.v2023.2.Hs.gmt +1 -0
- oncoordinate/__init__.py +0 -0
- oncoordinate/lt.py +472 -0
- oncoordinate/oncoordinate.joblib +0 -0
- oncoordinate/sc.py +729 -0
- oncoordinate/sp.py +513 -0
- oncoordinate-0.1.7.dist-info/METADATA +93 -0
- oncoordinate-0.1.7.dist-info/RECORD +62 -0
- oncoordinate-0.1.7.dist-info/WHEEL +5 -0
- oncoordinate-0.1.7.dist-info/licenses/LICENSE +21 -0
- oncoordinate-0.1.7.dist-info/top_level.txt +1 -0
oncoordinate/sp.py
ADDED
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
# sp.py (under oncoordinate)
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Optional, Union, Sequence, Dict, Any, List
|
|
7
|
+
|
|
8
|
+
import anndata as ad
|
|
9
|
+
import numpy as np
|
|
10
|
+
import pandas as pd
|
|
11
|
+
from scipy import sparse
|
|
12
|
+
from sklearn.neighbors import NearestNeighbors
|
|
13
|
+
from sklearn.cluster import KMeans
|
|
14
|
+
import scanpy.external as sce
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
import scanpy as sc
|
|
17
|
+
import imageio as iio
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
def _load_tissue_positions(sp_dir: Path, obs_index: pd.Index) -> pd.DataFrame:
|
|
22
|
+
pos_files = list(sp_dir.glob("*tissue_positions*.csv"))
|
|
23
|
+
if not pos_files:
|
|
24
|
+
raise FileNotFoundError(f"No tissue_positions file found in {sp_dir}")
|
|
25
|
+
|
|
26
|
+
pos_path = pos_files[0]
|
|
27
|
+
|
|
28
|
+
pos = pd.read_csv(pos_path, header=None)
|
|
29
|
+
if pos.shape[1] == 6:
|
|
30
|
+
pos.columns = ["barcode", "in_tissue",
|
|
31
|
+
"array_row", "array_col",
|
|
32
|
+
"pxl_row", "pxl_col"]
|
|
33
|
+
else:
|
|
34
|
+
pos = pd.read_csv(pos_path)
|
|
35
|
+
|
|
36
|
+
if "barcode" not in pos.columns:
|
|
37
|
+
raise ValueError(f"No 'barcode' column in {pos_path}")
|
|
38
|
+
|
|
39
|
+
pos["barcode"] = pos["barcode"].astype(str)
|
|
40
|
+
obs_index = obs_index.astype(str)
|
|
41
|
+
direct_match = pos["barcode"].isin(obs_index).sum()
|
|
42
|
+
|
|
43
|
+
if direct_match == 0:
|
|
44
|
+
pos["_barcode_alt"] = pos["barcode"] + "-1"
|
|
45
|
+
alt_match = pos["_barcode_alt"].isin(obs_index).sum()
|
|
46
|
+
if alt_match > direct_match:
|
|
47
|
+
pos["barcode"] = pos["_barcode_alt"]
|
|
48
|
+
pos = pos.drop(columns=["_barcode_alt"], errors="ignore")
|
|
49
|
+
|
|
50
|
+
pos = pos.set_index("barcode")
|
|
51
|
+
return pos
|
|
52
|
+
|
|
53
|
+
def _load_visium_images_and_scalefactors(sp_dir: Path) -> Dict[str, Any]:
|
|
54
|
+
images: Dict[str, np.ndarray] = {}
|
|
55
|
+
scalefactors: Dict[str, float] = {}
|
|
56
|
+
|
|
57
|
+
sf_path = sp_dir / "scalefactors_json.json"
|
|
58
|
+
if sf_path.exists():
|
|
59
|
+
with open(sf_path, "r") as f:
|
|
60
|
+
scalefactors = json.load(f)
|
|
61
|
+
|
|
62
|
+
hires_png = list(sp_dir.glob("*tissue_hires_image.png"))
|
|
63
|
+
lowres_png = list(sp_dir.glob("*tissue_lowres_image.png"))
|
|
64
|
+
tif_imgs = list(sp_dir.glob("*.tif"))
|
|
65
|
+
|
|
66
|
+
if hires_png:
|
|
67
|
+
images["hires"] = iio.imread(hires_png[0])
|
|
68
|
+
|
|
69
|
+
if lowres_png:
|
|
70
|
+
images["lowres"] = iio.imread(lowres_png[0])
|
|
71
|
+
|
|
72
|
+
if tif_imgs:
|
|
73
|
+
images["fullres"] = iio.imread(tif_imgs[0])
|
|
74
|
+
|
|
75
|
+
scalefactors.setdefault("spot_diameter_fullres", 65.0)
|
|
76
|
+
|
|
77
|
+
if "tissue_hires_scalef" not in scalefactors:
|
|
78
|
+
scalefactors["tissue_hires_scalef"] = 1.0
|
|
79
|
+
|
|
80
|
+
if "tissue_lowres_scalef" not in scalefactors:
|
|
81
|
+
scalefactors["tissue_lowres_scalef"] = 1.0
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
"images": images,
|
|
85
|
+
"scalefactors": scalefactors,
|
|
86
|
+
"metadata": {},
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
def _attach_visium_spatial(a: ad.AnnData, p: Path, sample_name: str) -> ad.AnnData:
|
|
90
|
+
sp_dir = p / "spatial"
|
|
91
|
+
if not sp_dir.is_dir():
|
|
92
|
+
return a
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
pos = _load_tissue_positions(sp_dir, a.obs.index)
|
|
96
|
+
except FileNotFoundError:
|
|
97
|
+
logger.warning("No tissue positions found in %s", sp_dir)
|
|
98
|
+
return a
|
|
99
|
+
|
|
100
|
+
a.obs = a.obs.join(pos, how="left")
|
|
101
|
+
|
|
102
|
+
if "in_tissue" in a.obs.columns:
|
|
103
|
+
a.obs["in_tissue"] = a.obs["in_tissue"].fillna(0).astype(int)
|
|
104
|
+
n_before = a.n_obs
|
|
105
|
+
mask_tissue = a.obs["in_tissue"] == 1
|
|
106
|
+
if mask_tissue.sum() > 0:
|
|
107
|
+
a = a[mask_tissue].copy()
|
|
108
|
+
logger.info(
|
|
109
|
+
"Subset sample '%s' to in_tissue==1: %d -> %d spots",
|
|
110
|
+
sample_name,
|
|
111
|
+
n_before,
|
|
112
|
+
a.n_obs,
|
|
113
|
+
)
|
|
114
|
+
else:
|
|
115
|
+
logger.warning(
|
|
116
|
+
"Sample '%s' has no barcodes with in_tissue==1; keeping all %d spots.",
|
|
117
|
+
sample_name,
|
|
118
|
+
n_before,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
if {"pxl_row", "pxl_col"}.issubset(a.obs.columns):
|
|
122
|
+
coords = a.obs[["pxl_col", "pxl_row"]].to_numpy()
|
|
123
|
+
elif {"array_row", "array_col"}.issubset(a.obs.columns):
|
|
124
|
+
coords = a.obs[["array_col", "array_row"]].to_numpy()
|
|
125
|
+
else:
|
|
126
|
+
logger.warning(
|
|
127
|
+
"No pixel/array coordinates found in tissue_positions for %s; "
|
|
128
|
+
"skipping spatial embedding.",
|
|
129
|
+
p,
|
|
130
|
+
)
|
|
131
|
+
return a
|
|
132
|
+
|
|
133
|
+
a.obsm["spatial"] = coords
|
|
134
|
+
|
|
135
|
+
spatial_meta = _load_visium_images_and_scalefactors(sp_dir)
|
|
136
|
+
a.uns.setdefault("spatial", {})
|
|
137
|
+
a.uns["spatial"][sample_name] = spatial_meta
|
|
138
|
+
|
|
139
|
+
return a
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _read_single_spatial(path_like: Union[str, Path]) -> ad.AnnData:
|
|
143
|
+
p = Path(path_like)
|
|
144
|
+
if p.is_dir():
|
|
145
|
+
sp_dir = p / "spatial"
|
|
146
|
+
has_spatial = sp_dir.is_dir() and any(sp_dir.glob("*tissue_positions*.csv"))
|
|
147
|
+
|
|
148
|
+
if has_spatial:
|
|
149
|
+
if (p / "filtered_feature_bc_matrix.h5").exists():
|
|
150
|
+
a = sc.read_10x_h5(p / "filtered_feature_bc_matrix.h5")
|
|
151
|
+
elif (p / "matrix.mtx.gz").exists() or (p / "matrix.mtx").exists():
|
|
152
|
+
a = sc.read_10x_mtx(p, var_names="gene_symbols")
|
|
153
|
+
else:
|
|
154
|
+
a = sc.read_visium(path=p)
|
|
155
|
+
|
|
156
|
+
sample_name = p.name
|
|
157
|
+
a = _attach_visium_spatial(a, p, sample_name)
|
|
158
|
+
|
|
159
|
+
elif (p / "filtered_feature_bc_matrix.h5").exists() or (p / "raw_feature_bc_matrix.h5").exists():
|
|
160
|
+
a = sc.read_visium(path=p)
|
|
161
|
+
sample_name = p.name
|
|
162
|
+
|
|
163
|
+
elif (p / "matrix.mtx.gz").exists() or (p / "matrix.mtx").exists():
|
|
164
|
+
a = sc.read_10x_mtx(p, var_names="gene_symbols")
|
|
165
|
+
sample_name = p.name
|
|
166
|
+
|
|
167
|
+
else:
|
|
168
|
+
raise ValueError(
|
|
169
|
+
f"Directory {p} does not look like a Visium or 10x mtx folder."
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
else:
|
|
173
|
+
suffix = p.suffix.lower()
|
|
174
|
+
if suffix == ".h5ad":
|
|
175
|
+
a = ad.read_h5ad(p)
|
|
176
|
+
sample_name = p.stem
|
|
177
|
+
elif suffix == ".h5":
|
|
178
|
+
try:
|
|
179
|
+
a = sc.read_10x_h5(p)
|
|
180
|
+
except Exception:
|
|
181
|
+
a = ad.read_h5ad(p)
|
|
182
|
+
sample_name = p.stem
|
|
183
|
+
else:
|
|
184
|
+
raise ValueError(f"Unsupported spatial input: {p}")
|
|
185
|
+
|
|
186
|
+
a.obs.index = a.obs.index.astype(str)
|
|
187
|
+
a.var.index = a.var.index.astype(str)
|
|
188
|
+
a.var_names = a.var_names.astype(str).str.upper()
|
|
189
|
+
a.var_names_make_unique()
|
|
190
|
+
|
|
191
|
+
if "sample" not in a.obs.columns:
|
|
192
|
+
a.obs["sample"] = sample_name
|
|
193
|
+
|
|
194
|
+
if "counts" not in a.layers:
|
|
195
|
+
a.layers["counts"] = a.X.copy()
|
|
196
|
+
|
|
197
|
+
return a
|
|
198
|
+
|
|
199
|
+
def load_spatial(
|
|
200
|
+
path: Union[str, Path],
|
|
201
|
+
*,
|
|
202
|
+
sample_key: str = "sample",
|
|
203
|
+
) -> ad.AnnData:
|
|
204
|
+
p = Path(path)
|
|
205
|
+
a = _read_single_spatial(p)
|
|
206
|
+
|
|
207
|
+
if sample_key != "sample":
|
|
208
|
+
if "sample" in a.obs.columns:
|
|
209
|
+
a.obs[sample_key] = a.obs["sample"].astype(str)
|
|
210
|
+
else:
|
|
211
|
+
label = p.stem
|
|
212
|
+
a.obs[sample_key] = label
|
|
213
|
+
|
|
214
|
+
return a
|
|
215
|
+
|
|
216
|
+
def preprocess_spatial(
|
|
217
|
+
adata: ad.AnnData,
|
|
218
|
+
*,
|
|
219
|
+
sample_key: str = "sample",
|
|
220
|
+
batch_key: Optional[str] = None,
|
|
221
|
+
n_hvg: int = 2000,
|
|
222
|
+
pca_n_comps: int = 50,
|
|
223
|
+
neighbors_n_pcs: int = 30,
|
|
224
|
+
neighbors_k: int = 15,
|
|
225
|
+
use_batch_correction: bool = True,
|
|
226
|
+
inplace: bool = True,
|
|
227
|
+
) -> ad.AnnData:
|
|
228
|
+
if not inplace:
|
|
229
|
+
adata = adata.copy()
|
|
230
|
+
|
|
231
|
+
adata.obs.index = adata.obs.index.astype(str)
|
|
232
|
+
adata.var.index = adata.var.index.astype(str)
|
|
233
|
+
adata.var_names = adata.var_names.astype(str)
|
|
234
|
+
|
|
235
|
+
if "counts" not in adata.layers:
|
|
236
|
+
adata.layers["counts"] = adata.X.copy()
|
|
237
|
+
|
|
238
|
+
layer = "counts"
|
|
239
|
+
hvg_batch_key = batch_key if batch_key is not None and batch_key in adata.obs.columns else None
|
|
240
|
+
|
|
241
|
+
sc.pp.highly_variable_genes(
|
|
242
|
+
adata,
|
|
243
|
+
layer=layer,
|
|
244
|
+
n_top_genes=n_hvg,
|
|
245
|
+
flavor="seurat_v3",
|
|
246
|
+
batch_key=hvg_batch_key,
|
|
247
|
+
inplace=True,
|
|
248
|
+
)
|
|
249
|
+
adata = adata[:, adata.var["highly_variable"].values].copy()
|
|
250
|
+
|
|
251
|
+
sc.pp.normalize_total(adata, target_sum=1e4)
|
|
252
|
+
sc.pp.log1p(adata)
|
|
253
|
+
max_rank = max(0, min(adata.n_obs, adata.n_vars) - 1)
|
|
254
|
+
n_comps = max(2, min(pca_n_comps, max_rank))
|
|
255
|
+
sc.tl.pca(adata, n_comps=n_comps, svd_solver="arpack")
|
|
256
|
+
|
|
257
|
+
n_pcs_avail = int(adata.obsm["X_pca"].shape[1])
|
|
258
|
+
n_pcs_use = min(neighbors_n_pcs, n_pcs_avail)
|
|
259
|
+
k = max(2, min(neighbors_k, max(2, adata.n_obs - 1)))
|
|
260
|
+
|
|
261
|
+
if batch_key is None:
|
|
262
|
+
batch_key = sample_key
|
|
263
|
+
|
|
264
|
+
use_bbknn = (
|
|
265
|
+
use_batch_correction
|
|
266
|
+
and sce is not None
|
|
267
|
+
and batch_key is not None
|
|
268
|
+
and batch_key in adata.obs.columns
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
if use_bbknn:
|
|
272
|
+
try:
|
|
273
|
+
sce.pp.bbknn(adata, batch_key=batch_key, n_pcs=n_pcs_use)
|
|
274
|
+
except Exception as e:
|
|
275
|
+
logger.warning(
|
|
276
|
+
"BBKNN batch correction failed (%s); falling back to standard neighbors.",
|
|
277
|
+
e,
|
|
278
|
+
)
|
|
279
|
+
sc.pp.neighbors(adata, n_neighbors=k, n_pcs=n_pcs_use)
|
|
280
|
+
else:
|
|
281
|
+
sc.pp.neighbors(adata, n_neighbors=k, n_pcs=n_pcs_use)
|
|
282
|
+
|
|
283
|
+
sc.tl.umap(adata)
|
|
284
|
+
|
|
285
|
+
adata.uns.setdefault("oncoordinate_spatial_params", {})
|
|
286
|
+
adata.uns["oncoordinate_spatial_params"].update(
|
|
287
|
+
dict(
|
|
288
|
+
sample_key=sample_key,
|
|
289
|
+
batch_key=batch_key,
|
|
290
|
+
n_hvg=int(n_hvg),
|
|
291
|
+
pca_n_comps=int(n_comps),
|
|
292
|
+
neighbors_n_pcs=int(n_pcs_use),
|
|
293
|
+
neighbors_k=int(k),
|
|
294
|
+
use_batch_correction=bool(use_batch_correction),
|
|
295
|
+
)
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
return adata
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class pp:
|
|
302
|
+
@staticmethod
|
|
303
|
+
def make_network(
|
|
304
|
+
adata: ad.AnnData,
|
|
305
|
+
*,
|
|
306
|
+
sample_key: Optional[str] = None,
|
|
307
|
+
method: str = "knn",
|
|
308
|
+
cutoff: Union[int, float] = 10,
|
|
309
|
+
spatial_key: str = "spatial",
|
|
310
|
+
key_added: str = "oncoordinate_network",
|
|
311
|
+
inplace: bool = True,
|
|
312
|
+
) -> ad.AnnData:
|
|
313
|
+
|
|
314
|
+
if not inplace:
|
|
315
|
+
adata = adata.copy()
|
|
316
|
+
|
|
317
|
+
if spatial_key not in adata.obsm:
|
|
318
|
+
raise KeyError(
|
|
319
|
+
f"Spatial coordinates '{spatial_key}' not found in adata.obsm"
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
coords = np.asarray(adata.obsm[spatial_key], dtype=float)
|
|
323
|
+
if coords.ndim != 2 or coords.shape[1] < 2:
|
|
324
|
+
raise ValueError(
|
|
325
|
+
f"Expected 2D coordinates in obsm['{spatial_key}'], got shape {coords.shape}"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
n = adata.n_obs
|
|
329
|
+
neighbors_indices: List[np.ndarray] = [np.empty(0, dtype=int) for _ in range(n)]
|
|
330
|
+
neighbors_distances: List[np.ndarray] = [np.empty(0, dtype=float) for _ in range(n)]
|
|
331
|
+
|
|
332
|
+
def _build_for_indices(idx: np.ndarray) -> None:
|
|
333
|
+
sub_coords = coords[idx]
|
|
334
|
+
if sub_coords.shape[0] < 2:
|
|
335
|
+
return
|
|
336
|
+
|
|
337
|
+
if method.lower() == "knn":
|
|
338
|
+
k = int(cutoff)
|
|
339
|
+
k_eff = min(k + 1, sub_coords.shape[0])
|
|
340
|
+
nn = NearestNeighbors(n_neighbors=k_eff, metric="euclidean")
|
|
341
|
+
nn.fit(sub_coords)
|
|
342
|
+
dist, ind = nn.kneighbors(sub_coords)
|
|
343
|
+
elif method.lower() == "radius":
|
|
344
|
+
radius = float(cutoff)
|
|
345
|
+
nn = NearestNeighbors(radius=radius, metric="euclidean")
|
|
346
|
+
nn.fit(sub_coords)
|
|
347
|
+
dist_list, ind_list = nn.radius_neighbors(sub_coords)
|
|
348
|
+
for local_i, (d_arr, i_arr) in enumerate(zip(dist_list, ind_list)):
|
|
349
|
+
global_i = idx[local_i]
|
|
350
|
+
if i_arr.size == 0:
|
|
351
|
+
continue
|
|
352
|
+
mask_self = i_arr != local_i
|
|
353
|
+
neighbors_indices[global_i] = idx[i_arr[mask_self]]
|
|
354
|
+
neighbors_distances[global_i] = d_arr[mask_self]
|
|
355
|
+
return
|
|
356
|
+
else:
|
|
357
|
+
raise ValueError(f"Unsupported method '{method}'. Use 'knn' or 'radius'.")
|
|
358
|
+
|
|
359
|
+
for local_i, (d_row, i_row) in enumerate(zip(dist, ind)):
|
|
360
|
+
global_i = idx[local_i]
|
|
361
|
+
mask = i_row != local_i
|
|
362
|
+
neighbors_indices[global_i] = idx[i_row[mask]]
|
|
363
|
+
neighbors_distances[global_i] = d_row[mask]
|
|
364
|
+
|
|
365
|
+
if sample_key is not None and sample_key in adata.obs.columns:
|
|
366
|
+
sample_labels = adata.obs[sample_key].astype(str).values
|
|
367
|
+
samples = pd.unique(sample_labels)
|
|
368
|
+
for s in samples:
|
|
369
|
+
idx = np.where(sample_labels == s)[0]
|
|
370
|
+
if idx.size == 0:
|
|
371
|
+
continue
|
|
372
|
+
_build_for_indices(idx)
|
|
373
|
+
else:
|
|
374
|
+
_build_for_indices(np.arange(n, dtype=int))
|
|
375
|
+
|
|
376
|
+
edge_dict: Dict[tuple[int, int], float] = {}
|
|
377
|
+
for i in range(n):
|
|
378
|
+
neigh = neighbors_indices[i]
|
|
379
|
+
dist = neighbors_distances[i]
|
|
380
|
+
for j, d in zip(neigh, dist):
|
|
381
|
+
if i == j:
|
|
382
|
+
continue
|
|
383
|
+
a, b = (i, j) if i < j else (j, i)
|
|
384
|
+
if (a, b) not in edge_dict or d < edge_dict[(a, b)]:
|
|
385
|
+
edge_dict[(a, b)] = float(d)
|
|
386
|
+
|
|
387
|
+
if edge_dict:
|
|
388
|
+
edges = np.array(list(edge_dict.keys()), dtype=int)
|
|
389
|
+
distances = np.array(list(edge_dict.values()), dtype=float)
|
|
390
|
+
else:
|
|
391
|
+
edges = np.zeros((0, 2), dtype=int)
|
|
392
|
+
distances = np.zeros(0, dtype=float)
|
|
393
|
+
|
|
394
|
+
net = {
|
|
395
|
+
"neighbors_indices": [np.asarray(v, dtype=int) for v in neighbors_indices],
|
|
396
|
+
"neighbors_distances": [np.asarray(v, dtype=float) for v in neighbors_distances],
|
|
397
|
+
"edges": edges,
|
|
398
|
+
"edge_distances": distances,
|
|
399
|
+
"params": {
|
|
400
|
+
"sample_key": sample_key,
|
|
401
|
+
"method": method,
|
|
402
|
+
"cutoff": cutoff,
|
|
403
|
+
"spatial_key": spatial_key,
|
|
404
|
+
},
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
adata.uns[key_added] = net
|
|
408
|
+
logger.info(
|
|
409
|
+
f"Built spatial network with {edges.shape[0]} edges "
|
|
410
|
+
f"(method={method}, cutoff={cutoff})."
|
|
411
|
+
)
|
|
412
|
+
return adata
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
class tl:
|
|
416
|
+
@staticmethod
|
|
417
|
+
def get_c_niche(
|
|
418
|
+
adata: ad.AnnData,
|
|
419
|
+
*,
|
|
420
|
+
k_max: int,
|
|
421
|
+
celltype_key: str,
|
|
422
|
+
sample_key: Optional[str] = None,
|
|
423
|
+
network_key: str = "oncoordinate_network",
|
|
424
|
+
niche_key: str = "oncoordinate_c_niche",
|
|
425
|
+
inplace: bool = True,
|
|
426
|
+
) -> ad.AnnData:
|
|
427
|
+
|
|
428
|
+
if not inplace:
|
|
429
|
+
adata = adata.copy()
|
|
430
|
+
|
|
431
|
+
if network_key not in adata.uns:
|
|
432
|
+
raise KeyError(
|
|
433
|
+
f"Network key '{network_key}' not found in adata.uns. "
|
|
434
|
+
"Run PP.make_network(...) first."
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
net = adata.uns[network_key]
|
|
438
|
+
neighbors_indices = net.get("neighbors_indices")
|
|
439
|
+
if neighbors_indices is None or len(neighbors_indices) != adata.n_obs:
|
|
440
|
+
raise ValueError(
|
|
441
|
+
f"Invalid neighbors_indices under uns['{network_key}']; "
|
|
442
|
+
"expected list of length n_obs."
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
if celltype_key not in adata.obs.columns:
|
|
446
|
+
raise KeyError(f"celltype_key '{celltype_key}' not found in adata.obs")
|
|
447
|
+
|
|
448
|
+
celltypes = adata.obs[celltype_key].astype(str).values
|
|
449
|
+
unique_ct = np.unique(celltypes)
|
|
450
|
+
n_cells = adata.n_obs
|
|
451
|
+
n_ct = unique_ct.size
|
|
452
|
+
ct_to_idx = {ct: i for i, ct in enumerate(unique_ct)}
|
|
453
|
+
|
|
454
|
+
feats = np.zeros((n_cells, n_ct), dtype=float)
|
|
455
|
+
for i in range(n_cells):
|
|
456
|
+
neigh = np.asarray(neighbors_indices[i], dtype=int)
|
|
457
|
+
if neigh.size == 0:
|
|
458
|
+
continue
|
|
459
|
+
neigh_ct = celltypes[neigh]
|
|
460
|
+
indices = [ct_to_idx[c] for c in neigh_ct]
|
|
461
|
+
counts = np.bincount(indices, minlength=n_ct)
|
|
462
|
+
total = counts.sum()
|
|
463
|
+
if total > 0:
|
|
464
|
+
feats[i, :] = counts / total
|
|
465
|
+
|
|
466
|
+
kmeans = KMeans(
|
|
467
|
+
n_clusters=int(k_max),
|
|
468
|
+
random_state=0,
|
|
469
|
+
n_init=10,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
labels = kmeans.fit_predict(feats)
|
|
473
|
+
adata.obs[niche_key] = pd.Categorical(labels.astype(str))
|
|
474
|
+
|
|
475
|
+
comp_ct = pd.DataFrame(
|
|
476
|
+
0.0,
|
|
477
|
+
index=np.arange(k_max),
|
|
478
|
+
columns=unique_ct,
|
|
479
|
+
)
|
|
480
|
+
for k in range(k_max):
|
|
481
|
+
mask = labels == k
|
|
482
|
+
if not np.any(mask):
|
|
483
|
+
continue
|
|
484
|
+
comp_ct.iloc[k, :] = feats[mask].mean(axis=0)
|
|
485
|
+
|
|
486
|
+
comp_sample = None
|
|
487
|
+
if sample_key is not None and sample_key in adata.obs.columns:
|
|
488
|
+
comp_sample = pd.crosstab(
|
|
489
|
+
adata.obs[sample_key],
|
|
490
|
+
adata.obs[niche_key],
|
|
491
|
+
normalize="index",
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
net["c_niche_centers"] = kmeans.cluster_centers_
|
|
495
|
+
net["c_niche_celltype_composition"] = comp_ct
|
|
496
|
+
if comp_sample is not None:
|
|
497
|
+
net["c_niche_sample_composition"] = comp_sample
|
|
498
|
+
net.setdefault("c_niche_params", {})
|
|
499
|
+
net["c_niche_params"].update(
|
|
500
|
+
{
|
|
501
|
+
"niche_key": niche_key,
|
|
502
|
+
"celltype_key": celltype_key,
|
|
503
|
+
"sample_key": sample_key,
|
|
504
|
+
"k_max": int(k_max),
|
|
505
|
+
}
|
|
506
|
+
)
|
|
507
|
+
adata.uns[network_key] = net
|
|
508
|
+
|
|
509
|
+
logger.info(
|
|
510
|
+
f"Computed C-niches ({k_max} clusters) into obs['{niche_key}'] "
|
|
511
|
+
f"using celltype_key='{celltype_key}'."
|
|
512
|
+
)
|
|
513
|
+
return adata
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oncoordinate
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: Oncoordinate is an interpretable deep learning framework for single-cell and spatial transcriptomic analysis of malignancy that learns malignant and malignancy-associated cell states across epithelial, stromal, and immune lineages while remaining tightly integrated with the scverse ecosystem.
|
|
5
|
+
Author-email: "Vignesh V. Venkat" <vvv11@scarletmail.rutgers.edu>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Vignesh Venkat
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/Viggyvenkat/Oncoordinate
|
|
29
|
+
Project-URL: Issues, https://github.com/Viggyvenkat/Oncoordinate/issues
|
|
30
|
+
Keywords: cancer,pathways,bioinformatics
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Operating System :: OS Independent
|
|
34
|
+
Classifier: Intended Audience :: Science/Research
|
|
35
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
36
|
+
Requires-Python: >=3.10
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
License-File: LICENSE
|
|
39
|
+
Requires-Dist: anndata
|
|
40
|
+
Requires-Dist: numpy
|
|
41
|
+
Requires-Dist: pandas
|
|
42
|
+
Requires-Dist: scipy
|
|
43
|
+
Requires-Dist: scanpy
|
|
44
|
+
Requires-Dist: scvi-tools
|
|
45
|
+
Requires-Dist: scikit-learn==1.7.2
|
|
46
|
+
Requires-Dist: joblib
|
|
47
|
+
Requires-Dist: umap-learn
|
|
48
|
+
Requires-Dist: gseapy
|
|
49
|
+
Requires-Dist: matplotlib
|
|
50
|
+
Requires-Dist: seaborn
|
|
51
|
+
Requires-Dist: python-igraph
|
|
52
|
+
Requires-Dist: pytorch-tabnet
|
|
53
|
+
Requires-Dist: ipywidgets
|
|
54
|
+
Requires-Dist: imageio
|
|
55
|
+
Requires-Dist: click
|
|
56
|
+
Dynamic: license-file
|
|
57
|
+
|
|
58
|
+
# Oncoordinate
|
|
59
|
+
|
|
60
|
+
### Contents
|
|
61
|
+
1. Introduction
|
|
62
|
+
2. Discovering single-cell states
|
|
63
|
+
3. Projecting to spatial transcriptomic cohorts
|
|
64
|
+
4. References
|
|
65
|
+
5. Acknowledgements
|
|
66
|
+
|
|
67
|
+
Note: we provide a demo notebook (```vignettes/tutorial.html```) and two spatial datasets (```demo-data/V10U24-037_A```, ```demo-data/V10U24-037_B```). We will be uploading the train set, the test set, and the reference_sc.h5ad on zenodo. We have also provided an `environment.yml` file so that you can run the command: `conda env create -f environment.yml` and get a working environment for Oncoordinate.
|
|
68
|
+
|
|
69
|
+
## 1. Introduction
|
|
70
|
+
Oncoordinate is an interpretable deep learning framework for single-cell and spatial transcriptomic analysis of malignancy that learns malignant and malignancy-associated cell states across epithelial, stromal, and immune lineages while remaining tightly integrated with the scverse ecosystem. Built on a sequential attention–based and trained on an integrated lung atlas (~3M cells spanning normal, chronic disease, and multiple lung carcinoma subtypes), Oncoordinate predicts a four-stage neoplastic continuum (normal, dysplastic, pre-malignant, malignant) with calibrated probabilities and sparse, step-wise feature selection that can be traced back to genes and pathways. Beyond single-cell analysis, it includes a de novo label transfer pipeline based on scVI and scANVI that projects these learned states into spatial transcriptomic datasets (e.g., 10x Visium) via pseudospots and joint latent embeddings, enabling the localization of aggressive niches, tumor–CAF neighborhoods, and other malignant ecosystems within intact tissue. Oncoordinate also works with niche detection methods such as SOAPy and works seamlessly with AnnData and Scanpy-based workflows, providing a GPU-accelerated, atlas-scale, and plug-and-play framework for malignancy modeling across molecular and spatial dimensions.
|
|
71
|
+
|
|
72
|
+
To install Oncoordinate, please run:
|
|
73
|
+
|
|
74
|
+
``` pip install oncoordinate ```
|
|
75
|
+
|
|
76
|
+

|
|
77
|
+
|
|
78
|
+
## 2. Discovering single-cell states
|
|
79
|
+
Oncoordinate discovers malignant and malignancy-associated cell states by modeling neoplastic progression as a continuous, lineage-aware process rather than a binary tumor versus non-tumor classification. Using atlas-scale single-cell RNA-seq data, the model integrates gene-level features and pathway scores to learn a four-stage neoplastic continuum spanning normal, dysplastic, pre-malignant, and malignant states. Its sequential attention mechanism performs sparse, step-wise feature selection, allowing the model to focus on distinct transcriptional programs at different stages of malignancy while preserving interpretability. This design enables Oncoordinate to recover coherent oncogenic trajectories within individual lineages, such as epithelial, fibroblast, immune, and endothelial compartments, and to quantify heterogeneity both within and across patients. The resulting per-cell malignancy probabilities and lineage-resolved scores provide an interpretable representation of tumor ecosystem remodeling that can be directly used for downstream analyses, including trajectory visualization, pathway interrogation, and patient-level stratification.
|
|
80
|
+
|
|
81
|
+

|
|
82
|
+
|
|
83
|
+
## 3. Projecting to spatial transcriptomic cohorts
|
|
84
|
+
To translate single-cell–derived malignancy states into intact tissue architecture, Oncoordinate implements a de novo label transfer framework tailored for spatial transcriptomics data. Single-cell profiles sharing the same lineage and malignancy state are aggregated into pseudospots to approximate the multicellular composition of spatial capture spots, and these pseudospots are jointly embedded with spatial transcriptomic data using scVI to learn a shared, batch-corrected latent space. scANVI is then applied in a semi-supervised manner to infer probabilistic malignancy and lineage labels for each spatial spot. This approach enables robust projection of malignant programs into spatial coordinates, revealing colocalized malignant neighborhoods such as tumor–fibroblast (CAF) niches, regions of stromal remodeling, and immune-associated malignant ecosystems. By combining probabilistic spatial labeling with downstream niche detection methods such as SOAPy, Oncoordinate allows users to identify and characterize aggressive, spatially confined microenvironments that are not apparent from dissociated single-cell data alone.
|
|
85
|
+
|
|
86
|
+

|
|
87
|
+
|
|
88
|
+
## 4. References
|
|
89
|
+
- Venkat V. et al. Disruptive changes in tissue microenvironment prime oncogenic processes at different stages of carcinogenesis in lung. bioRxiv (2024).
|
|
90
|
+
- Venkat VV, De S. Oncoordinate-derived single-cell states translate to malignant clusters in spatial transcriptomic cohorts. bioRxiv (2026).
|
|
91
|
+
|
|
92
|
+
## 5. Acknowledgements
|
|
93
|
+
We thank colleagues at the Rutgers Cancer Institute and members of the De Laboratory for their guidance and support.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
oncoordinate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
oncoordinate/lt.py,sha256=pmdF3TYundHe5qSY52VvnKpu-wOWGmaKMbYD4JnsOj0,15887
|
|
3
|
+
oncoordinate/oncoordinate.joblib,sha256=OwN7FmRyRCV-WtaH962vtGbq-jLI4vgcscqIGI6wa4M,1937271
|
|
4
|
+
oncoordinate/sc.py,sha256=5OHrHMx0FSugyI-BpjaPcmExXplArhtqWvIihnsDI2w,24754
|
|
5
|
+
oncoordinate/sp.py,sha256=YksjUB72TbLqwUm0A1fLYF3kqYWhu15sFCc6L0yGxY4,16672
|
|
6
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_ADIPOGENESIS.v2023.2.Hs.gmt,sha256=3wE_zDwqggGdvhvpCqzBEexTpSQnO6zyAf0iY2jc56Q,1283
|
|
7
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_ALLOGRAFT_REJECTION.v2023.2.Hs.gmt,sha256=tBGJPLLWCO01szrGUbfB-iupXWQqMcJqEQnWn5W0bnM,1222
|
|
8
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_ANDROGEN_RESPONSE.v2023.2.Hs.gmt,sha256=eWMP5touZLL2H0sp9TRc733X6XA04QBJONi5zQkN6os,727
|
|
9
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_ANGIOGENESIS.v2023.2.Hs.gmt,sha256=eF_lbvQKTbuhh_5Uq0_pO6utU18fjRqI9AV16_SV7_I,304
|
|
10
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_APICAL_JUNCTION.v2023.2.Hs.gmt,sha256=GgKGajGsLRwcwm8fZKWiehRGUQZbcg4zX8nuZBiuDKg,1285
|
|
11
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_APICAL_SURFACE.v2023.2.Hs.gmt,sha256=LQrrCiAf5goHbPrn9D0n0ccOUT35HQN7PGA6vM3qvr0,380
|
|
12
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_APOPTOSIS.v2023.2.Hs.gmt,sha256=yNTbYbpCFsY9vgIQQUM4Y2df_bBPxXC9zJKy0OsuS9g,1001
|
|
13
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_BILE_ACID_METABOLISM.v2023.2.Hs.gmt,sha256=ve5P3rZ89nhrn453L6SFJHEuWu552jbME_wnQX-b9s8,801
|
|
14
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_CHOLESTEROL_HOMEOSTASIS.v2023.2.Hs.gmt,sha256=hSnwHNVJFecAYE-u-KKIch9xrbulB6jFZrVaXh5tBW4,553
|
|
15
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_COAGULATION.v2023.2.Hs.gmt,sha256=t5yV_Nl-d9ddpeVJgKOyV1vCLgP8MY0SUBJSy0hNF-o,823
|
|
16
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_COMPLEMENT.v2023.2.Hs.gmt,sha256=Sd_ZGCrCX-46yC-2wAVH4Y36HA0fZnZ9wpivdfqeITQ,1212
|
|
17
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_DNA_REPAIR.v2023.2.Hs.gmt,sha256=qO-LwjlVR-j5evTCuDE-wSJuBzkGzPdYLgWqcp8GjuU,974
|
|
18
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_E2F_TARGETS.v2023.2.Hs.gmt,sha256=jtjrIQRqfisWWuztAYNAtJJHJRTbW3icsXUqRBkKeOY,1263
|
|
19
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_EPITHELIAL_MESENCHYMAL_TRANSITION.v2023.2.Hs.gmt,sha256=p1gmkTx8J8rHOLl2J_qwzY4FGPPiw4mSv09mdIcr8EQ,1306
|
|
20
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_ESTROGEN_RESPONSE_EARLY.v2023.2.Hs.gmt,sha256=FUR8Mu434I_fDdDmFwErYYF2oEYwMjRiSXTFitCND1U,1335
|
|
21
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_ESTROGEN_RESPONSE_LATE.v2023.2.Hs.gmt,sha256=lX9ptgQD_Jab1RXLYHJMpALNbbxmI_xImmq09gO87-U,1310
|
|
22
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_FATTY_ACID_METABOLISM.v2023.2.Hs.gmt,sha256=04JidJvr6YTv3nGuHik5VfvS-AuQnaCqlw3rK_w7S3U,1046
|
|
23
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_G2M_CHECKPOINT.v2023.2.Hs.gmt,sha256=-QgDI7jxLcgSIuvE-TpvjihxSgUbmFXNXyB2aiP0_rM,1266
|
|
24
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_GLYCOLYSIS.v2023.2.Hs.gmt,sha256=VYxq25EZzKWzNlTS1RWSVKsa4q7DV4Qbe3fYc_gD0C0,1241
|
|
25
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_HEDGEHOG_SIGNALING.v2023.2.Hs.gmt,sha256=-d5ChLz4-j-rYcIPNz6uhs6zR0cUT2Qr3ILFQVFoSYo,306
|
|
26
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_HEME_METABOLISM.v2023.2.Hs.gmt,sha256=Qtqp5sa5v6xmI6ZUjw3zNZR-N4jznvePrPGPaaIp130,1292
|
|
27
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_HYPOXIA.v2023.2.Hs.gmt,sha256=h47PZ24OueXoKazsrL73gvwV6ilbxzhBJ7n3wGOjHVY,1244
|
|
28
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_IL2_STAT5_SIGNALING.v2023.2.Hs.gmt,sha256=RQ4Gfv-v7rQIwvKUoTRJV9hH3RqenbcDu6v9wdaA22E,1313
|
|
29
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_IL6_JAK_STAT3_SIGNALING.v2023.2.Hs.gmt,sha256=SMDisUR_aj252IItNg38YGnw2gQ5x-3pEORN3eD37MQ,634
|
|
30
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_INFLAMMATORY_RESPONSE.v2023.2.Hs.gmt,sha256=DL2WB-uH6OBOx8oi0ZhROJYQ7acWexVrmZKN0JE03dA,1291
|
|
31
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_INTERFERON_ALPHA_RESPONSE.v2023.2.Hs.gmt,sha256=2D14ED_HPsI67ovxny9-KPcr56CVrY1JNFzRGehQwGs,697
|
|
32
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_INTERFERON_GAMMA_RESPONSE.v2023.2.Hs.gmt,sha256=h9fftiHUlB1vnuqe_rRWhy27cp7NzxP78s4-vzUDHjI,1318
|
|
33
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_KRAS_SIGNALING_DN.v2023.2.Hs.gmt,sha256=jJgWqogXXDPcB1xXZQ5m0RaQVUaM1yZNHdJq480o6xs,1326
|
|
34
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_KRAS_SIGNALING_UP.v2023.2.Hs.gmt,sha256=hqyOBFaRsCE1gxTVqQP6kOdlDciBTsnTo2znimgAB5o,1314
|
|
35
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_MITOTIC_SPINDLE.v2023.2.Hs.gmt,sha256=d7zosxuYcFlS26lQbG8W9j4P2qARchE7HgCDcxwOLgs,1350
|
|
36
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_MTORC1_SIGNALING.v2023.2.Hs.gmt,sha256=q9Yc2fxXWjWapGal6bNXdc7w_fv6e8xl0H3kmaRlAEk,1286
|
|
37
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_MYC_TARGETS_V1.v2023.2.Hs.gmt,sha256=8se5j-hWXstttTZr_dbHciOCKwchVxvTqFZ8SL2cxDw,1287
|
|
38
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_MYC_TARGETS_V2.v2023.2.Hs.gmt,sha256=Jh1sL1Xpa28bEh4leZE-Z4_4iYr2kBQSsok7Bfxo4eA,440
|
|
39
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_MYOGENESIS.v2023.2.Hs.gmt,sha256=hQsMkzX5GPu-GI63Pyf8asOrLEm00JUb-sCOLxP0vhU,1250
|
|
40
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_NOTCH_SIGNALING.v2023.2.Hs.gmt,sha256=xOf5dS4fdq8H3POw2UsXtY3-SZJm03p8gTCNLRPWCLs,288
|
|
41
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_OXIDATIVE_PHOSPHORYLATION.v2023.2.Hs.gmt,sha256=OssD_puZLztFcJ_7wbigrno9UOEO2PUFwWRVLUJZeqo,1406
|
|
42
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_P53_PATHWAY.v2023.2.Hs.gmt,sha256=KyDt3T5irP0ccO66y_FaRmyZGVYEMJ36FVEvkT7-m4U,1291
|
|
43
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_PANCREAS_BETA_CELLS.v2023.2.Hs.gmt,sha256=F91XHWhgKP_X6UFcPoV4vFV2o8JlkZTEty-XkdG_xBo,333
|
|
44
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_PEROXISOME.v2023.2.Hs.gmt,sha256=eHaOXJIkcQXTZCXkEDbX3LXWVpSgQqFRUcVJnEyNbWY,730
|
|
45
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_PI3K_AKT_MTOR_SIGNALING.v2023.2.Hs.gmt,sha256=KDE1SFIBWGrgAbt1hhO-1sAXXSxz2ZUYMFSW4_EJgms,750
|
|
46
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_PROTEIN_SECRETION.v2023.2.Hs.gmt,sha256=5fvCdcYGAPXqIKpyeaHzGrIaeG3nRwGAGclAHcIqu4g,677
|
|
47
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_REACTIVE_OXYGEN_SPECIES_PATHWAY.v2023.2.Hs.gmt,sha256=-OdEhAHiTkiVkuN2KAnJs6qc8ddM-zqIhuqzJ0Z4fsQ,411
|
|
48
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_SPERMATOGENESIS.v2023.2.Hs.gmt,sha256=n9Y0N2kZDUkPsG0YehKgHYV1aCaIDA6mv3wfMEIysQQ,891
|
|
49
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_TGF_BETA_SIGNALING.v2023.2.Hs.gmt,sha256=w2tNLtHZOlzhWlZ7AKeksnEtOxZ0SwxdDpKdUs8QI28,434
|
|
50
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_TNFA_SIGNALING_VIA_NFKB.v2023.2.Hs.gmt,sha256=obljegRl5_LtnUgilBgqAFW5_EouaF1LojvBYSFBMmc,1294
|
|
51
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_UNFOLDED_PROTEIN_RESPONSE.v2023.2.Hs.gmt,sha256=leYvr_WLTlgJoJoxB4VOnfKP3dmyE39WITs7Mbx4ga0,816
|
|
52
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_UV_RESPONSE_DN.v2023.2.Hs.gmt,sha256=D3_Tmkku4JzXBPgv2lquw03Ty7eWgXxDrqD2mXBiFi4,971
|
|
53
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_UV_RESPONSE_UP.v2023.2.Hs.gmt,sha256=8NGFUQ4UrdR_ep6FBSNM7jvT3xDHbGehZc0J0nEqJUA,1025
|
|
54
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_WNT_BETA_CATENIN_SIGNALING.v2023.2.Hs.gmt,sha256=B-U77KUw5P2NPjnNEbGU8Fur_pc1PY6p7IZtOtzL7tU,361
|
|
55
|
+
oncoordinate/HallmarkPathGMT/HALLMARK_XENOBIOTIC_METABOLISM.v2023.2.Hs.gmt,sha256=MNVFUjU7LLn-sja6U72I6va351gC_p-p_LbET2bGCgY,1282
|
|
56
|
+
oncoordinate/HallmarkPathGMT/REACTOME_CELL_CYCLE.v2023.2.Hs.gmt,sha256=gBVSh4U-W1tlQnCsS-t82gH6rvqULIGM9xPupNmMhIU,4282
|
|
57
|
+
oncoordinate/HallmarkPathGMT/REACTOME_SIGNALING_BY_EGFR_IN_CANCER.v2023.2.Hs.gmt,sha256=0zUC0sfyFOG72yuwQou-VicZXoCA5My0SsDzWZM1osA,261
|
|
58
|
+
oncoordinate-0.1.7.dist-info/licenses/LICENSE,sha256=wLtNslPiZu4XVG7WaL9Sw4cO9tkXWaOrXBH8kEp7YKU,1071
|
|
59
|
+
oncoordinate-0.1.7.dist-info/METADATA,sha256=Gg8CwTmNNOBhZ9ZEPqYFqdMB6ULOQU6sCwj1gIsrBTU,7570
|
|
60
|
+
oncoordinate-0.1.7.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
61
|
+
oncoordinate-0.1.7.dist-info/top_level.txt,sha256=f_sVgWqAiEbx12sQ1Lc8EbfXykZM9ANKVOMl8cUhOEI,13
|
|
62
|
+
oncoordinate-0.1.7.dist-info/RECORD,,
|