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/__init__.py +1 -1
- scmcp_shared/cli.py +96 -0
- scmcp_shared/schema/__init__.py +22 -1
- scmcp_shared/schema/io.py +4 -8
- scmcp_shared/schema/pl.py +2 -3
- scmcp_shared/schema/pp.py +15 -15
- scmcp_shared/schema/tl.py +18 -24
- scmcp_shared/schema/util.py +11 -11
- scmcp_shared/server/__init__.py +11 -49
- scmcp_shared/server/base.py +153 -0
- scmcp_shared/server/io.py +71 -61
- scmcp_shared/server/pl.py +288 -294
- scmcp_shared/server/pp.py +320 -358
- scmcp_shared/server/tl.py +393 -402
- scmcp_shared/server/util.py +241 -240
- scmcp_shared/util.py +110 -43
- {scmcp_shared-0.2.0.dist-info → scmcp_shared-0.3.0.dist-info}/METADATA +1 -1
- scmcp_shared-0.3.0.dist-info/RECORD +21 -0
- scmcp_shared/schema/base.py +0 -11
- scmcp_shared-0.2.0.dist-info/RECORD +0 -20
- {scmcp_shared-0.2.0.dist-info → scmcp_shared-0.3.0.dist-info}/WHEEL +0 -0
- {scmcp_shared-0.2.0.dist-info → scmcp_shared-0.3.0.dist-info}/licenses/LICENSE +0 -0
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
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
):
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
):
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
):
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
)
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
)
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
)
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
return
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
)
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
)
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
)
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
)
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
)
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
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
|