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