scmcp-shared 0.2.0__py3-none-any.whl → 0.3.0__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.
scmcp_shared/server/tl.py CHANGED
@@ -1,407 +1,398 @@
1
1
  from fastmcp import FastMCP, Context
2
2
  import os
3
+ import inspect
4
+ from fastmcp import FastMCP
3
5
  import scanpy as sc
6
+ from fastmcp.exceptions import ToolError
4
7
  from ..schema.tl import *
8
+ from ..schema import AdataInfo
5
9
  from scmcp_shared.util import filter_args, add_op_log, forward_request, get_ads, generate_msg
6
- from scmcp_shared.logging_config import setup_logger
7
- logger = setup_logger()
8
-
9
- tl_mcp = FastMCP("ScanpyMCP-TL-Server")
10
-
11
-
12
- @tl_mcp.tool()
13
- async def tsne(
14
- request: TSNEModel = TSNEModel()
15
- ):
16
- """t-distributed stochastic neighborhood embedding (t-SNE) for visualization"""
17
-
18
- try:
19
- result = await forward_request("tl_tsne", request)
20
- if result is not None:
21
- return result
22
- func_kwargs = filter_args(request, sc.tl.tsne)
23
- ads = get_ads()
24
- adata = ads.get_adata(request=request)
25
- sc.tl.tsne(adata, **func_kwargs)
26
- add_op_log(adata, sc.tl.tsne, func_kwargs)
27
- return generate_msg(request, adata, ads)
28
- except KeyError as e:
29
- raise e
30
- except Exception as e:
31
- if hasattr(e, '__context__') and e.__context__:
32
- raise Exception(f"{str(e.__context__)}")
33
- else:
34
- raise e
35
-
36
-
37
- @tl_mcp.tool()
38
- async def umap(
39
- request: UMAPModel = UMAPModel()
40
- ):
41
- """Uniform Manifold Approximation and Projection (UMAP) for visualization"""
42
-
43
- try:
44
- result = await forward_request("tl_umap", request)
45
- if result is not None:
46
- return result
47
- func_kwargs = filter_args(request, sc.tl.umap)
48
- ads = get_ads()
49
- adata = ads.get_adata(request=request)
50
- sc.tl.umap(adata, **func_kwargs)
51
- add_op_log(adata, sc.tl.umap, func_kwargs)
52
- return [generate_msg(request, adata, ads)]
53
- except KeyError as e:
54
- raise e
55
- except Exception as e:
56
- if hasattr(e, '__context__') and e.__context__:
57
- raise Exception(f"{str(e.__context__)}")
58
- else:
59
- raise e
60
-
61
- @tl_mcp.tool()
62
- async def draw_graph(
63
- request: DrawGraphModel = DrawGraphModel()
64
- ):
65
- """Force-directed graph drawing"""
66
-
67
- try:
68
- result = await forward_request("tl_draw_graph", request)
69
- if result is not None:
70
- return result
71
- func_kwargs = filter_args(request, sc.tl.draw_graph)
72
- ads = get_ads()
73
- adata = ads.get_adata(request=request)
74
- sc.tl.draw_graph(adata, **func_kwargs)
75
- add_op_log(adata, sc.tl.draw_graph, func_kwargs)
76
- return [generate_msg(request, adata, ads)]
77
- except KeyError as e:
78
- raise e
79
- except Exception as e:
80
- if hasattr(e, '__context__') and e.__context__:
81
- raise Exception(f"{str(e.__context__)}")
82
- else:
83
- raise e
84
-
85
- @tl_mcp.tool()
86
- async def diffmap(
87
- request: DiffMapModel = DiffMapModel()
88
- ):
89
- """Diffusion Maps for dimensionality reduction"""
90
-
91
- try:
92
- result = await forward_request("tl_diffmap", request)
93
- if result is not None:
94
- return result
95
- func_kwargs = filter_args(request, sc.tl.diffmap)
96
- ads = get_ads()
97
- adata = ads.get_adata(request=request)
98
- sc.tl.diffmap(adata, **func_kwargs)
99
- adata.obsm["X_diffmap"] = adata.obsm["X_diffmap"][:,1:]
100
- add_op_log(adata, sc.tl.diffmap, func_kwargs)
101
- return [generate_msg(request, adata, ads)]
102
- except Exception as e:
103
- if hasattr(e, '__context__') and e.__context__:
104
- raise Exception(f"{str(e.__context__)}")
105
- else:
106
- raise e
107
-
108
- @tl_mcp.tool()
109
- async def embedding_density(
110
- request: EmbeddingDensityModel = EmbeddingDensityModel()
111
- ):
112
- """Calculate the density of cells in an embedding"""
113
-
114
- try:
115
- result = await forward_request("tl_embedding_density", request)
116
- if result is not None:
117
- return result
118
- func_kwargs = filter_args(request, sc.tl.embedding_density)
119
- ads = get_ads()
120
- adata = ads.get_adata(request=request)
121
- sc.tl.embedding_density(adata, **func_kwargs)
122
- add_op_log(adata, sc.tl.embedding_density, func_kwargs)
123
- return [generate_msg(request, adata, ads)]
124
- except Exception as e:
125
- if hasattr(e, '__context__') and e.__context__:
126
- raise Exception(f"{str(e.__context__)}")
127
- else:
128
- raise e
129
-
130
-
131
- @tl_mcp.tool()
132
- async def leiden(
133
- request: LeidenModel = LeidenModel()
134
- ):
135
- """Leiden clustering algorithm for community detection"""
136
-
137
- try:
138
- result = await forward_request("tl_leiden", request)
139
- if result is not None:
140
- return result
141
- func_kwargs = filter_args(request, sc.tl.leiden)
142
- ads = get_ads()
143
- adata = ads.get_adata(request=request)
144
- sc.tl.leiden(adata, **func_kwargs)
145
- add_op_log(adata, sc.tl.leiden, func_kwargs)
146
- return [generate_msg(request, adata, ads)]
147
- except Exception as e:
148
- if hasattr(e, '__context__') and e.__context__:
149
- raise Exception(f"{str(e.__context__)}")
150
- else:
151
- raise e
152
-
153
-
154
- @tl_mcp.tool()
155
- async def louvain(
156
- request: LouvainModel = LouvainModel()
157
- ):
158
- """Louvain clustering algorithm for community detection"""
159
-
160
- try:
161
- result = await forward_request("tl_louvain", request)
162
- if result is not None:
163
- return result
164
- func_kwargs = filter_args(request, sc.tl.louvain)
165
- ads = get_ads()
166
- adata = ads.get_adata(request=request)
167
- sc.tl.louvain(adata, **func_kwargs)
168
- add_op_log(adata, sc.tl.louvain, func_kwargs)
169
- return [generate_msg(request, adata, ads)]
170
- except Exception as e:
171
- if hasattr(e, '__context__') and e.__context__:
172
- raise Exception(f"{str(e.__context__)}")
173
- else:
174
- raise e
175
-
176
-
177
- @tl_mcp.tool()
178
- async def dendrogram(
179
- request: DendrogramModel,
180
- ):
181
- """Hierarchical clustering dendrogram"""
182
-
183
- try:
184
- result = await forward_request("tl_dendrogram", request)
185
- if result is not None:
186
- return result
187
- func_kwargs = filter_args(request, sc.tl.dendrogram)
188
- ads = get_ads()
189
- adata = ads.get_adata(request=request)
190
- sc.tl.dendrogram(adata, **func_kwargs)
191
- add_op_log(adata, sc.tl.dendrogram, func_kwargs)
192
- return [generate_msg(request, adata, ads)]
193
- except Exception as e:
194
- if hasattr(e, '__context__') and e.__context__:
195
- raise Exception(f"{str(e.__context__)}")
196
- else:
197
- raise e
198
-
199
-
200
- @tl_mcp.tool()
201
- async def dpt(
202
- request: DPTModel = DPTModel()
203
- ):
204
- """Diffusion Pseudotime (DPT) analysis"""
205
-
206
- try:
207
- result = await forward_request("tl_dpt", request)
208
- if result is not None:
209
- return result
210
- func_kwargs = filter_args(request, sc.tl.dpt)
211
- ads = get_ads()
212
- adata = ads.get_adata(request=request)
213
- sc.tl.dpt(adata, **func_kwargs)
214
- add_op_log(adata, sc.tl.dpt, func_kwargs)
215
- return [generate_msg(request, adata, ads)]
216
- except Exception as e:
217
- if hasattr(e, '__context__') and e.__context__:
218
- raise Exception(f"{str(e.__context__)}")
219
- else:
220
- raise e
221
-
222
-
223
- @tl_mcp.tool()
224
- async def paga(
225
- request: PAGAModel = PAGAModel()
226
- ):
227
- """Partition-based graph abstraction"""
228
-
229
- try:
230
- result = await forward_request("tl_paga", request)
231
- if result is not None:
232
- return result
233
- func_kwargs = filter_args(request, sc.tl.paga)
234
- ads = get_ads()
235
- adata = ads.get_adata(request=request)
236
- sc.tl.paga(adata, **func_kwargs)
237
- add_op_log(adata, sc.tl.paga, func_kwargs)
238
- return [generate_msg(request, adata, ads)]
239
- except Exception as e:
240
- if hasattr(e, '__context__') and e.__context__:
241
- raise Exception(f"{str(e.__context__)}")
242
- else:
243
- raise e
244
-
245
-
246
- @tl_mcp.tool()
247
- async def ingest(
248
- request: IngestModel = IngestModel()
249
- ):
250
- """Map labels and embeddings from reference data to new data"""
251
-
252
- try:
253
- result = await forward_request("tl_ingest", request)
254
- if result is not None:
255
- return result
256
- func_kwargs = filter_args(request, sc.tl.ingest)
257
- ads = get_ads()
258
- adata = ads.get_adata(request=request)
259
- sc.tl.ingest(adata, **func_kwargs)
260
- add_op_log(adata, sc.tl.ingest, func_kwargs)
261
- return [generate_msg(request, adata, ads)]
262
- except Exception as e:
263
- if hasattr(e, '__context__') and e.__context__:
264
- raise Exception(f"{str(e.__context__)}")
265
- else:
266
- raise e
267
-
268
- @tl_mcp.tool()
269
- async def rank_genes_groups(
270
- request: RankGenesGroupsModel,
271
-
272
- ):
273
- """Rank genes for characterizing groups, for differentially expressison analysis"""
274
-
275
- try:
276
- result = await forward_request("tl_rank_genes_groups", request)
277
- if result is not None:
278
- return result
279
- func_kwargs = filter_args(request, sc.tl.rank_genes_groups)
280
- ads = get_ads()
281
- adata = ads.get_adata(request=request)
282
- sc.tl.rank_genes_groups(adata, **func_kwargs)
283
- add_op_log(adata, sc.tl.rank_genes_groups, func_kwargs)
284
- return [generate_msg(request, adata, ads)]
285
- except Exception as e:
286
- if hasattr(e, '__context__') and e.__context__:
287
- raise Exception(f"{str(e.__context__)}")
288
- else:
289
- raise e
290
-
291
-
292
- @tl_mcp.tool()
293
- async def filter_rank_genes_groups(
294
- request: FilterRankGenesGroupsModel = FilterRankGenesGroupsModel()
295
- ):
296
- """Filter out genes based on fold change and fraction of genes"""
297
-
298
- try:
299
- result = await forward_request("tl_filter_rank_genes_groups", request)
300
- if result is not None:
301
- return result
302
- func_kwargs = filter_args(request, sc.tl.filter_rank_genes_groups)
303
- ads = get_ads()
304
- adata = ads.get_adata(request=request)
305
- sc.tl.filter_rank_genes_groups(adata, **func_kwargs)
306
- add_op_log(adata, sc.tl.filter_rank_genes_groups, func_kwargs)
307
- return [generate_msg(request, adata, ads)]
308
- except Exception as e:
309
- if hasattr(e, '__context__') and e.__context__:
310
- raise Exception(f"{str(e.__context__)}")
311
- else:
312
- raise e
313
-
314
-
315
- @tl_mcp.tool()
316
- async def marker_gene_overlap(
317
- request: MarkerGeneOverlapModel = MarkerGeneOverlapModel()
318
- ):
319
- """Calculate overlap between data-derived marker genes and reference markers"""
320
-
321
- try:
322
- result = await forward_request("tl_marker_gene_overlap", request)
323
- if result is not None:
324
- return result
325
- func_kwargs = filter_args(request, sc.tl.marker_gene_overlap)
326
- ads = get_ads()
327
- adata = ads.get_adata(request=request)
328
- sc.tl.marker_gene_overlap(adata, **func_kwargs)
329
- add_op_log(adata, sc.tl.marker_gene_overlap, func_kwargs)
330
- return [generate_msg(request, adata, ads)]
331
- except Exception as e:
332
- if hasattr(e, '__context__') and e.__context__:
333
- raise Exception(f"{str(e.__context__)}")
334
- else:
335
- raise e
336
-
337
- @tl_mcp.tool()
338
- async def score_genes(
339
- request: ScoreGenesModel,
340
-
341
- ):
342
- """Score a set of genes based on their average expression"""
343
- try:
344
- result = await forward_request("tl_score_genes", request)
345
- if result is not None:
346
- return result
347
- func_kwargs = filter_args(request, sc.tl.score_genes)
348
- ads = get_ads()
349
- adata = ads.get_adata(request=request)
350
- sc.tl.score_genes(adata, **func_kwargs)
351
- add_op_log(adata, sc.tl.score_genes, func_kwargs)
352
- return [generate_msg(request, adata, ads)]
353
- except Exception as e:
354
- if hasattr(e, '__context__') and e.__context__:
355
- raise Exception(f"{str(e.__context__)}")
356
- else:
357
- raise e
358
-
359
- @tl_mcp.tool()
360
- async def score_genes_cell_cycle(
361
- request: ScoreGenesCellCycleModel,
362
-
363
- ):
364
- """Score cell cycle genes and assign cell cycle phases"""
365
-
366
- try:
367
- result = await forward_request("tl_score_genes_cell_cycle", request)
368
- if result is not None:
369
- return result
370
- func_kwargs = filter_args(request, sc.tl.score_genes_cell_cycle)
371
- ads = get_ads()
372
- adata = ads.get_adata(request=request)
373
- sc.tl.score_genes_cell_cycle(adata, **func_kwargs)
374
- add_op_log(adata, sc.tl.score_genes_cell_cycle, func_kwargs)
375
- return [generate_msg(request, adata, ads)]
376
- except Exception as e:
377
- if hasattr(e, '__context__') and e.__context__:
378
- raise Exception(f"{str(e.__context__)}")
379
- else:
380
- raise e
381
-
382
-
383
- @tl_mcp.tool()
384
- async def pca(
385
- request: PCAModel = PCAModel()
386
- ):
387
- """Principal component analysis"""
388
-
389
- try:
390
- result = await forward_request("tl_pca", request)
391
- if result is not None:
392
- return result
393
- func_kwargs = filter_args(request, sc.pp.pca)
394
- ads = get_ads()
395
- adata = ads.get_adata(request=request)
396
- sc.pp.pca(adata, **func_kwargs)
397
- add_op_log(adata, sc.pp.pca, func_kwargs)
398
- return [
399
- generate_msg(request, adata, ads)
400
- ]
401
- except KeyError as e:
402
- raise e
403
- except Exception as e:
404
- if hasattr(e, '__context__') and e.__context__:
405
- raise Exception(f"{str(e.__context__)}")
406
- else:
407
- raise e
10
+ from .base import BaseMCP
11
+
12
+
13
+ class ScanpyToolsMCP(BaseMCP):
14
+ def __init__(self, include_tools: list = None, exclude_tools: list = None, AdataInfo: AdataInfo = AdataInfo):
15
+ """
16
+ Initialize ScanpyMCP with optional tool filtering.
17
+
18
+ Args:
19
+ include_tools (list, optional): List of tool names to include. If None, all tools are included.
20
+ exclude_tools (list, optional): List of tool names to exclude. If None, no tools are excluded.
21
+ AdataInfo: The AdataInfo class to use for type annotations.
22
+ """
23
+ super().__init__("ScanpyMCP-TL-Server", include_tools, exclude_tools, AdataInfo)
24
+
25
+ def _tool_tsne(self):
26
+ def _tsne(request: TSNEModel, adinfo: self.AdataInfo=self.AdataInfo()):
27
+ """t-distributed stochastic neighborhood embedding (t-SNE) for visualization"""
28
+ try:
29
+ result = forward_request("tl_tsne", request, adinfo)
30
+ if result is not None:
31
+ return result
32
+ func_kwargs = filter_args(request, sc.tl.tsne)
33
+ ads = get_ads()
34
+ adata = ads.get_adata(adinfo=adinfo)
35
+ sc.tl.tsne(adata, **func_kwargs)
36
+ add_op_log(adata, sc.tl.tsne, func_kwargs, adinfo)
37
+ return [generate_msg(adinfo, adata, ads)]
38
+ except ToolError as e:
39
+ raise ToolError(e)
40
+ except Exception as e:
41
+ if hasattr(e, '__context__') and e.__context__:
42
+ raise ToolError(e.__context__)
43
+ else:
44
+ raise ToolError(e)
45
+ return _tsne
46
+
47
+ def _tool_umap(self):
48
+ def _umap(request: UMAPModel, adinfo: self.AdataInfo=self.AdataInfo()):
49
+ """Uniform Manifold Approximation and Projection (UMAP) for visualization"""
50
+ try:
51
+ result = forward_request("tl_umap", request, adinfo)
52
+ if result is not None:
53
+ return result
54
+ func_kwargs = filter_args(request, sc.tl.umap)
55
+ ads = get_ads()
56
+ adata = ads.get_adata(adinfo=adinfo)
57
+ sc.tl.umap(adata, **func_kwargs)
58
+ add_op_log(adata, sc.tl.umap, func_kwargs, adinfo)
59
+ return [generate_msg(adinfo, adata, ads)]
60
+ except ToolError as e:
61
+ raise ToolError(e)
62
+ except Exception as e:
63
+ if hasattr(e, '__context__') and e.__context__:
64
+ raise ToolError(e.__context__)
65
+ else:
66
+ raise ToolError(e)
67
+ return _umap
68
+
69
+ def _tool_draw_graph(self):
70
+ def _draw_graph(request: DrawGraphModel, adinfo: self.AdataInfo=self.AdataInfo()):
71
+ """Force-directed graph drawing"""
72
+ try:
73
+ result = forward_request("tl_draw_graph", request, adinfo)
74
+ if result is not None:
75
+ return result
76
+ func_kwargs = filter_args(request, sc.tl.draw_graph)
77
+ ads = get_ads()
78
+ adata = ads.get_adata(adinfo=adinfo)
79
+ sc.tl.draw_graph(adata, **func_kwargs)
80
+ add_op_log(adata, sc.tl.draw_graph, func_kwargs, adinfo)
81
+ return [generate_msg(adinfo, adata, ads)]
82
+ except ToolError as e:
83
+ raise ToolError(e)
84
+ except Exception as e:
85
+ if hasattr(e, '__context__') and e.__context__:
86
+ raise ToolError(e.__context__)
87
+ else:
88
+ raise ToolError(e)
89
+ return _draw_graph
90
+
91
+ def _tool_diffmap(self):
92
+ def _diffmap(request: DiffMapModel, adinfo: self.AdataInfo=self.AdataInfo()):
93
+ """Diffusion Maps for dimensionality reduction"""
94
+ try:
95
+ result = forward_request("tl_diffmap", request, adinfo)
96
+ if result is not None:
97
+ return result
98
+ func_kwargs = filter_args(request, sc.tl.diffmap)
99
+ ads = get_ads()
100
+ adata = ads.get_adata(adinfo=adinfo)
101
+ sc.tl.diffmap(adata, **func_kwargs)
102
+ adata.obsm["X_diffmap"] = adata.obsm["X_diffmap"][:,1:]
103
+ add_op_log(adata, sc.tl.diffmap, func_kwargs, adinfo)
104
+ return [generate_msg(adinfo, adata, ads)]
105
+ except ToolError as e:
106
+ raise ToolError(e)
107
+ except Exception as e:
108
+ if hasattr(e, '__context__') and e.__context__:
109
+ raise ToolError(e.__context__)
110
+ else:
111
+ raise ToolError(e)
112
+ return _diffmap
113
+
114
+ def _tool_embedding_density(self):
115
+ def _embedding_density(request: EmbeddingDensityModel, adinfo: self.AdataInfo=self.AdataInfo()):
116
+ """Calculate the density of cells in an embedding"""
117
+ try:
118
+ result = forward_request("tl_embedding_density", request, adinfo)
119
+ if result is not None:
120
+ return result
121
+ func_kwargs = filter_args(request, sc.tl.embedding_density)
122
+ ads = get_ads()
123
+ adata = ads.get_adata(adinfo=adinfo)
124
+ sc.tl.embedding_density(adata, **func_kwargs)
125
+ add_op_log(adata, sc.tl.embedding_density, func_kwargs, adinfo)
126
+ return [generate_msg(adinfo, adata, ads)]
127
+ except ToolError as e:
128
+ raise ToolError(e)
129
+ except Exception as e:
130
+ if hasattr(e, '__context__') and e.__context__:
131
+ raise ToolError(e.__context__)
132
+ else:
133
+ raise ToolError(e)
134
+ return _embedding_density
135
+
136
+ def _tool_leiden(self):
137
+ def _leiden(request: LeidenModel, adinfo: self.AdataInfo=self.AdataInfo()):
138
+ """Leiden clustering algorithm for community detection"""
139
+ try:
140
+ result = forward_request("tl_leiden", request, adinfo)
141
+ if result is not None:
142
+ return result
143
+ func_kwargs = filter_args(request, sc.tl.leiden)
144
+ ads = get_ads()
145
+ adata = ads.get_adata(adinfo=adinfo)
146
+ sc.tl.leiden(adata, **func_kwargs)
147
+ add_op_log(adata, sc.tl.leiden, func_kwargs, adinfo)
148
+ return [generate_msg(adinfo, adata, ads)]
149
+ except ToolError as e:
150
+ raise ToolError(e)
151
+ except Exception as e:
152
+ if hasattr(e, '__context__') and e.__context__:
153
+ raise ToolError(e.__context__)
154
+ else:
155
+ raise ToolError(e)
156
+ return _leiden
157
+
158
+ def _tool_louvain(self):
159
+ def _louvain(request: LouvainModel, adinfo: self.AdataInfo=self.AdataInfo()):
160
+ """Louvain clustering algorithm for community detection"""
161
+ try:
162
+ result = forward_request("tl_louvain", request, adinfo)
163
+ if result is not None:
164
+ return result
165
+ func_kwargs = filter_args(request, sc.tl.louvain)
166
+ ads = get_ads()
167
+ adata = ads.get_adata(adinfo=adinfo)
168
+ sc.tl.louvain(adata, **func_kwargs)
169
+ add_op_log(adata, sc.tl.louvain, func_kwargs, adinfo)
170
+ return [generate_msg(adinfo, adata, ads)]
171
+ except ToolError as e:
172
+ raise ToolError(e)
173
+ except Exception as e:
174
+ if hasattr(e, '__context__') and e.__context__:
175
+ raise ToolError(e.__context__)
176
+ else:
177
+ raise ToolError(e)
178
+ return _louvain
179
+
180
+ def _tool_dendrogram(self):
181
+ def _dendrogram(request: DendrogramModel, adinfo: self.AdataInfo=self.AdataInfo()):
182
+ """Hierarchical clustering dendrogram"""
183
+ try:
184
+ result = forward_request("tl_dendrogram", request, adinfo)
185
+ if result is not None:
186
+ return result
187
+ func_kwargs = filter_args(request, sc.tl.dendrogram)
188
+ ads = get_ads()
189
+ adata = ads.get_adata(adinfo=adinfo)
190
+ sc.tl.dendrogram(adata, **func_kwargs)
191
+ add_op_log(adata, sc.tl.dendrogram, func_kwargs, adinfo)
192
+ return [generate_msg(adinfo, adata, ads)]
193
+ except ToolError as e:
194
+ raise ToolError(e)
195
+ except Exception as e:
196
+ if hasattr(e, '__context__') and e.__context__:
197
+ raise ToolError(e.__context__)
198
+ else:
199
+ raise ToolError(e)
200
+ return _dendrogram
201
+
202
+ def _tool_dpt(self):
203
+ def _dpt(request: DPTModel, adinfo: self.AdataInfo=self.AdataInfo()):
204
+ """Diffusion Pseudotime (DPT) analysis"""
205
+ try:
206
+ result = forward_request("tl_dpt", request, adinfo)
207
+ if result is not None:
208
+ return result
209
+ func_kwargs = filter_args(request, sc.tl.dpt)
210
+ ads = get_ads()
211
+ adata = ads.get_adata(adinfo=adinfo)
212
+ sc.tl.dpt(adata, **func_kwargs)
213
+ add_op_log(adata, sc.tl.dpt, func_kwargs, adinfo)
214
+ return [generate_msg(adinfo, adata, ads)]
215
+ except ToolError as e:
216
+ raise ToolError(e)
217
+ except Exception as e:
218
+ if hasattr(e, '__context__') and e.__context__:
219
+ raise ToolError(e.__context__)
220
+ else:
221
+ raise ToolError(e)
222
+ return _dpt
223
+
224
+ def _tool_paga(self):
225
+ def _paga(request: PAGAModel, adinfo: self.AdataInfo=self.AdataInfo()):
226
+ """Partition-based graph abstraction"""
227
+ try:
228
+ result = forward_request("tl_paga", request, adinfo)
229
+ if result is not None:
230
+ return result
231
+ func_kwargs = filter_args(request, sc.tl.paga)
232
+ ads = get_ads()
233
+ adata = ads.get_adata(adinfo=adinfo)
234
+ sc.tl.paga(adata, **func_kwargs)
235
+ add_op_log(adata, sc.tl.paga, func_kwargs, adinfo)
236
+ return [generate_msg(adinfo, adata, ads)]
237
+ except ToolError as e:
238
+ raise ToolError(e)
239
+ except Exception as e:
240
+ if hasattr(e, '__context__') and e.__context__:
241
+ raise ToolError(e.__context__)
242
+ else:
243
+ raise ToolError(e)
244
+ return _paga
245
+
246
+ def _tool_ingest(self):
247
+ def _ingest(request: IngestModel, adinfo: self.AdataInfo=self.AdataInfo()):
248
+ """Map labels and embeddings from reference data to new data"""
249
+ try:
250
+ result = forward_request("tl_ingest", request, adinfo)
251
+ if result is not None:
252
+ return result
253
+ func_kwargs = filter_args(request, sc.tl.ingest)
254
+ ads = get_ads()
255
+ adata = ads.get_adata(adinfo=adinfo)
256
+ sc.tl.ingest(adata, **func_kwargs)
257
+ add_op_log(adata, sc.tl.ingest, func_kwargs, adinfo)
258
+ return [generate_msg(adinfo, adata, ads)]
259
+ except ToolError as e:
260
+ raise ToolError(e)
261
+ except Exception as e:
262
+ if hasattr(e, '__context__') and e.__context__:
263
+ raise ToolError(e.__context__)
264
+ else:
265
+ raise ToolError(e)
266
+ return _ingest
267
+
268
+ def _tool_rank_genes_groups(self):
269
+ def _rank_genes_groups(request: RankGenesGroupsModel, adinfo: self.AdataInfo=self.AdataInfo()):
270
+ """Rank genes for characterizing groups, for differentially expressison analysis"""
271
+ try:
272
+ result = forward_request("tl_rank_genes_groups", request, adinfo)
273
+ if result is not None:
274
+ return result
275
+ func_kwargs = filter_args(request, sc.tl.rank_genes_groups)
276
+ ads = get_ads()
277
+ adata = ads.get_adata(adinfo=adinfo)
278
+ sc.tl.rank_genes_groups(adata, **func_kwargs)
279
+ add_op_log(adata, sc.tl.rank_genes_groups, func_kwargs, adinfo)
280
+ return [generate_msg(adinfo, adata, ads)]
281
+ except ToolError as e:
282
+ raise ToolError(e)
283
+ except Exception as e:
284
+ if hasattr(e, '__context__') and e.__context__:
285
+ raise ToolError(e.__context__)
286
+ else:
287
+ raise ToolError(e)
288
+ return _rank_genes_groups
289
+
290
+ def _tool_filter_rank_genes_groups(self):
291
+ def _filter_rank_genes_groups(request: FilterRankGenesGroupsModel, adinfo: self.AdataInfo=self.AdataInfo()):
292
+ """Filter out genes based on fold change and fraction of genes"""
293
+ try:
294
+ result = forward_request("tl_filter_rank_genes_groups", request, adinfo)
295
+ if result is not None:
296
+ return result
297
+ func_kwargs = filter_args(request, sc.tl.filter_rank_genes_groups)
298
+ ads = get_ads()
299
+ adata = ads.get_adata(adinfo=adinfo)
300
+ sc.tl.filter_rank_genes_groups(adata, **func_kwargs)
301
+ add_op_log(adata, sc.tl.filter_rank_genes_groups, func_kwargs, adinfo)
302
+ return [generate_msg(adinfo, adata, ads)]
303
+ except ToolError as e:
304
+ raise ToolError(e)
305
+ except Exception as e:
306
+ if hasattr(e, '__context__') and e.__context__:
307
+ raise ToolError(e.__context__)
308
+ else:
309
+ raise ToolError(e)
310
+ return _filter_rank_genes_groups
311
+
312
+ def _tool_marker_gene_overlap(self):
313
+ def _marker_gene_overlap(request: MarkerGeneOverlapModel, adinfo: self.AdataInfo=self.AdataInfo()):
314
+ """Calculate overlap between data-derived marker genes and reference markers"""
315
+ try:
316
+ result = forward_request("tl_marker_gene_overlap", request, adinfo)
317
+ if result is not None:
318
+ return result
319
+ func_kwargs = filter_args(request, sc.tl.marker_gene_overlap)
320
+ ads = get_ads()
321
+ adata = ads.get_adata(adinfo=adinfo)
322
+ sc.tl.marker_gene_overlap(adata, **func_kwargs)
323
+ add_op_log(adata, sc.tl.marker_gene_overlap, func_kwargs, adinfo)
324
+ return [generate_msg(adinfo, adata, ads)]
325
+ except ToolError as e:
326
+ raise ToolError(e)
327
+ except Exception as e:
328
+ if hasattr(e, '__context__') and e.__context__:
329
+ raise ToolError(e.__context__)
330
+ else:
331
+ raise ToolError(e)
332
+ return _marker_gene_overlap
333
+
334
+ def _tool_score_genes(self):
335
+ def _score_genes(request: ScoreGenesModel, adinfo: self.AdataInfo=self.AdataInfo()):
336
+ """Score a set of genes based on their average expression"""
337
+ try:
338
+ result = forward_request("tl_score_genes", request, adinfo)
339
+ if result is not None:
340
+ return result
341
+ func_kwargs = filter_args(request, sc.tl.score_genes)
342
+ ads = get_ads()
343
+ adata = ads.get_adata(adinfo=adinfo)
344
+ sc.tl.score_genes(adata, **func_kwargs)
345
+ add_op_log(adata, sc.tl.score_genes, func_kwargs, adinfo)
346
+ return [generate_msg(adinfo, adata, ads)]
347
+ except ToolError as e:
348
+ raise ToolError(e)
349
+ except Exception as e:
350
+ if hasattr(e, '__context__') and e.__context__:
351
+ raise ToolError(e.__context__)
352
+ else:
353
+ raise ToolError(e)
354
+ return _score_genes
355
+
356
+ def _tool_score_genes_cell_cycle(self):
357
+ def _score_genes_cell_cycle(request: ScoreGenesCellCycleModel, adinfo: self.AdataInfo=self.AdataInfo()):
358
+ """Score cell cycle genes and assign cell cycle phases"""
359
+ try:
360
+ result = forward_request("tl_score_genes_cell_cycle", request, adinfo)
361
+ if result is not None:
362
+ return result
363
+ func_kwargs = filter_args(request, sc.tl.score_genes_cell_cycle)
364
+ ads = get_ads()
365
+ adata = ads.get_adata(adinfo=adinfo)
366
+ sc.tl.score_genes_cell_cycle(adata, **func_kwargs)
367
+ add_op_log(adata, sc.tl.score_genes_cell_cycle, func_kwargs, adinfo)
368
+ return [generate_msg(adinfo, adata, ads)]
369
+ except ToolError as e:
370
+ raise ToolError(e)
371
+ except Exception as e:
372
+ if hasattr(e, '__context__') and e.__context__:
373
+ raise ToolError(e.__context__)
374
+ else:
375
+ raise ToolError(e)
376
+ return _score_genes_cell_cycle
377
+
378
+ def _tool_pca(self):
379
+ def _pca(request: PCAModel, adinfo: self.AdataInfo=self.AdataInfo()):
380
+ """Compute PCA (Principal Component Analysis)."""
381
+ try:
382
+ result = forward_request("tl_pca", request, adinfo)
383
+ if result is not None:
384
+ return result
385
+ func_kwargs = filter_args(request, sc.tl.pca)
386
+ ads = get_ads()
387
+ adata = ads.get_adata(adinfo=adinfo)
388
+ sc.tl.pca(adata, **func_kwargs)
389
+ add_op_log(adata, sc.tl.pca, func_kwargs, adinfo)
390
+ return [generate_msg(adinfo, adata, ads)]
391
+ except ToolError as e:
392
+ raise ToolError(e)
393
+ except Exception as e:
394
+ if hasattr(e, '__context__') and e.__context__:
395
+ raise ToolError(e.__context__)
396
+ else:
397
+ raise ToolError(e)
398
+ return _pca