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/pl.py CHANGED
@@ -5,362 +5,311 @@ import scanpy as sc
5
5
  from fastmcp import FastMCP, Context
6
6
  from fastmcp.exceptions import ToolError
7
7
  from ..schema.pl import *
8
- from ..schema import AdataModel
8
+ from ..schema import AdataInfo
9
9
  from pathlib import Path
10
- from ..logging_config import setup_logger
11
10
  from ..util import forward_request, sc_like_plot, get_ads
11
+ from .base import BaseMCP
12
12
 
13
13
 
14
- logger = setup_logger()
14
+ class ScanpyPlottingMCP(BaseMCP):
15
+ def __init__(self, include_tools: list = None, exclude_tools: list = None, AdataInfo: AdataInfo = AdataInfo):
16
+ """
17
+ Initialize ScanpyPreprocessingMCP with optional tool filtering.
18
+
19
+ Args:
20
+ include_tools (list, optional): List of tool names to include. If None, all tools are included.
21
+ exclude_tools (list, optional): List of tool names to exclude. If None, no tools are excluded.
22
+ AdataInfo: The AdataInfo class to use for type annotations.
23
+ """
24
+ super().__init__("ScanpyMCP-PL-Server", include_tools, exclude_tools, AdataInfo)
15
25
 
16
- pl_mcp = FastMCP("ScanpyMCP-PL-Server")
26
+ def _tool_pca(self):
27
+ def _pca(request: PCAModel, adinfo: self.AdataInfo=self.AdataInfo()):
28
+ """Scatter plot in PCA coordinates. default figure for PCA plot"""
29
+ try:
30
+ if (res := forward_request("pl_pca", request, adinfo)) is not None:
31
+ return res
32
+ adata = get_ads().get_adata(adinfo=adinfo)
33
+ fig_path = sc_like_plot(sc.pl.pca, adata, request, adinfo)
34
+ return {"figpath": fig_path}
35
+ except ToolError as e:
36
+ raise ToolError(e)
37
+ except Exception as e:
38
+ if hasattr(e, '__context__') and e.__context__:
39
+ raise ToolError(e.__context__)
40
+ else:
41
+ raise ToolError(e)
42
+ return _pca
17
43
 
44
+ def _tool_diffmap(self):
45
+ def _diffmap(request: DiffusionMapModel, adinfo: self.AdataInfo=self.AdataInfo()):
46
+ """Plot diffusion map embedding of cells."""
47
+ try:
48
+ if (res := forward_request("pl_diffmap", request, adinfo)) is not None:
49
+ return res
50
+ adata = get_ads().get_adata(adinfo=adinfo)
51
+ fig_path = sc_like_plot(sc.pl.diffmap, adata, request, adinfo)
52
+ return {"figpath": fig_path}
53
+ except ToolError as e:
54
+ raise ToolError(e)
55
+ except Exception as e:
56
+ if hasattr(e, '__context__') and e.__context__:
57
+ raise ToolError(e.__context__)
58
+ else:
59
+ raise ToolError(e)
60
+ return _diffmap
18
61
 
62
+ def _tool_violin(self):
63
+ def _violin(request: ViolinModel, adinfo: self.AdataInfo=self.AdataInfo()):
64
+ """Plot violin plot of one or more variables."""
65
+ try:
66
+ if (res := forward_request("pl_violin", request, adinfo)) is not None:
67
+ return res
68
+ adata = get_ads().get_adata(adinfo=adinfo)
69
+ fig_path = sc_like_plot(sc.pl.violin, adata, request, adinfo)
70
+ return {"figpath": fig_path}
71
+ except KeyError as e:
72
+ raise ToolError(f"doest found {e} in current sampleid with adtype {adinfo.adtype}")
73
+ except ToolError as e:
74
+ raise ToolError(e)
75
+ except Exception as e:
76
+ if hasattr(e, '__context__') and e.__context__:
77
+ raise ToolError(e.__context__)
78
+ else:
79
+ raise ToolError(e)
80
+ return _violin
19
81
 
20
- @pl_mcp.tool()
21
- async def pca(
22
- request: PCAModel = PCAModel(),
23
- adinfo: AdataModel = AdataModel()
24
- ):
25
- """Scatter plot in PCA coordinates. default figure for PCA plot"""
26
- try:
27
- result = await forward_request("pl_pca", request, adinfo)
28
- if result is not None:
29
- return result
30
- adata = get_ads().get_adata(adinfo=adinfo)
31
- fig_path = sc_like_plot(sc.pl.pca, adata, request, adinfo)
32
- return {"figpath": fig_path}
33
- except ToolError as e:
34
- raise ToolError(e)
35
- except Exception as e:
36
- if hasattr(e, '__context__') and e.__context__:
37
- raise ToolError(e.__context__)
38
- else:
39
- raise ToolError(e)
82
+ def _tool_stacked_violin(self):
83
+ def _stacked_violin(request: StackedViolinModel, adinfo: self.AdataInfo=self.AdataInfo()):
84
+ """Plot stacked violin plots. Makes a compact image composed of individual violin plots stacked on top of each other."""
85
+ try:
86
+ if (res := forward_request("pl_stacked_violin", request, adinfo)) is not None:
87
+ return res
88
+ adata = get_ads().get_adata(adinfo=adinfo)
89
+ fig_path = sc_like_plot(sc.pl.stacked_violin, adata, request, adinfo)
90
+ return {"figpath": fig_path}
91
+ except ToolError as e:
92
+ raise ToolError(e)
93
+ except Exception as e:
94
+ if hasattr(e, '__context__') and e.__context__:
95
+ raise ToolError(e.__context__)
96
+ else:
97
+ raise ToolError(e)
98
+ return _stacked_violin
40
99
 
41
- @pl_mcp.tool()
42
- async def diffmap(
43
- request: DiffusionMapModel = DiffusionMapModel(),
44
- adinfo: AdataModel = AdataModel()
45
- ):
46
- """Plot diffusion map embedding of cells."""
47
- try:
48
- result = await forward_request("pl_diffmap", request, adinfo)
49
- if result is not None:
50
- return result
51
- adata = get_ads().get_adata(adinfo=adinfo)
52
- fig_path = sc_like_plot(sc.pl.diffmap, adata, request, adinfo)
53
- return {"figpath": fig_path}
54
- except ToolError as e:
55
- raise ToolError(e)
56
- except Exception as e:
57
- if hasattr(e, '__context__') and e.__context__:
58
- raise ToolError(e.__context__)
59
- else:
60
- raise ToolError(e)
100
+ def _tool_heatmap(self):
101
+ async def _heatmap(request: HeatmapModel, adinfo: self.AdataInfo=self.AdataInfo()):
102
+ """Heatmap of the expression values of genes."""
103
+ try:
104
+ if (res := forward_request("pl_heatmap", request, adinfo)) is not None:
105
+ return res
106
+ adata = get_ads().get_adata(adinfo=adinfo)
107
+ fig_path = sc_like_plot(sc.pl.heatmap, adata, request, adinfo)
108
+ return {"figpath": fig_path}
109
+ except ToolError as e:
110
+ raise ToolError(e)
111
+ except Exception as e:
112
+ if hasattr(e, '__context__') and e.__context__:
113
+ raise ToolError(e.__context__)
114
+ else:
115
+ raise ToolError(e)
116
+ return _heatmap
61
117
 
62
- @pl_mcp.tool()
63
- async def violin(
64
- request: ViolinModel,
65
- adinfo: AdataModel = AdataModel()
66
- ):
67
- """Plot violin plot of one or more variables."""
68
- try:
69
- result = await forward_request("pl_violin", request, adinfo)
70
- if result is not None:
71
- return result
72
- adata = get_ads().get_adata(adinfo=adinfo)
73
- fig_path = sc_like_plot(sc.pl.violin, adata, request, adinfo)
74
- return {"figpath": fig_path}
75
- except KeyError as e:
76
- raise ToolError(f"doest found {e} in current sampleid with adtype {adinfo.adtype}")
77
- except ToolError as e:
78
- raise ToolError(e)
79
- except Exception as e:
80
- if hasattr(e, '__context__') and e.__context__:
81
- raise ToolError(e.__context__)
82
- else:
83
- raise ToolError(e)
118
+ def _tool_dotplot(self):
119
+ def _dotplot(request: DotplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
120
+ """Plot dot plot of expression values per gene for each group."""
121
+ try:
122
+ if (res := forward_request("pl_dotplot", request, adinfo)) is not None:
123
+ return res
124
+ adata = get_ads().get_adata(adinfo=adinfo)
125
+ fig_path = sc_like_plot(sc.pl.dotplot, adata, request, adinfo)
126
+ return {"figpath": fig_path}
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 _dotplot
84
135
 
136
+ def _tool_matrixplot(self):
137
+ def _matrixplot(request: MatrixplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
138
+ """matrixplot, Create a heatmap of the mean expression values per group of each var_names."""
139
+ try:
140
+ if (res := forward_request("pl_matrixplot", request, adinfo)) is not None:
141
+ return res
142
+ adata = get_ads().get_adata(adinfo=adinfo)
143
+ fig_path = sc_like_plot(sc.pl.matrixplot, adata, request, adinfo)
144
+ return {"figpath": fig_path}
145
+ except ToolError as e:
146
+ raise ToolError(e)
147
+ except Exception as e:
148
+ if hasattr(e, '__context__') and e.__context__:
149
+ raise ToolError(e.__context__)
150
+ else:
151
+ raise ToolError(e)
152
+ return _matrixplot
85
153
 
86
- @pl_mcp.tool()
87
- async def stacked_violin(
88
- request: StackedViolinModel = StackedViolinModel(),
89
- adinfo: AdataModel = AdataModel()
90
- ):
91
- """Plot stacked violin plots. Makes a compact image composed of individual violin plots stacked on top of each other."""
92
- try:
93
- result = await forward_request("pl_stacked_violin", request, adinfo)
94
- if result is not None:
95
- return result
96
- adata = get_ads().get_adata(adinfo=adinfo)
97
- fig_path = sc_like_plot(sc.pl.stacked_violin, adata, request,adinfo)
98
- return {"figpath": fig_path}
99
- except ToolError as e:
100
- raise ToolError(e)
101
- except Exception as e:
102
- if hasattr(e, '__context__') and e.__context__:
103
- raise ToolError(e.__context__)
104
- else:
105
- raise ToolError(e)
154
+ def _tool_tracksplot(self):
155
+ def _tracksplot(request: TracksplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
156
+ """tracksplot, compact plot of expression of a list of genes."""
157
+ try:
158
+ if (res := forward_request("pl_tracksplot", request, adinfo)) is not None:
159
+ return res
160
+ adata = get_ads().get_adata(adinfo=adinfo)
161
+ fig_path = sc_like_plot(sc.pl.tracksplot, adata, request, adinfo)
162
+ return {"figpath": fig_path}
163
+ except ToolError as e:
164
+ raise ToolError(e)
165
+ except Exception as e:
166
+ if hasattr(e, '__context__') and e.__context__:
167
+ raise ToolError(e.__context__)
168
+ else:
169
+ raise ToolError(e)
170
+ return _tracksplot
106
171
 
172
+ def _tool_scatter(self):
173
+ def _scatter(request: EnhancedScatterModel, adinfo: self.AdataInfo=self.AdataInfo()):
174
+ """Plot a scatter plot of two variables, Scatter plot along observations or variables axes."""
175
+ try:
176
+ if (res := forward_request("pl_scatter", request, adinfo)) is not None:
177
+ return res
178
+ adata = get_ads().get_adata(adinfo=adinfo)
179
+ fig_path = sc_like_plot(sc.pl.scatter, adata, request, adinfo)
180
+ return {"figpath": fig_path}
181
+ except ToolError as e:
182
+ raise ToolError(e)
183
+ except Exception as e:
184
+ if hasattr(e, '__context__') and e.__context__:
185
+ raise ToolError(e.__context__)
186
+ else:
187
+ raise ToolError(e)
188
+ return _scatter
107
189
 
108
- @pl_mcp.tool()
109
- async def heatmap(
110
- request: HeatmapModel,
111
- adinfo: AdataModel = AdataModel()
112
- ):
113
- """Heatmap of the expression values of genes."""
114
- try:
115
- result = await forward_request("pl_heatmap", request, adinfo)
116
- if result is not None:
117
- return result
118
- adata = get_ads().get_adata(adinfo=adinfo)
119
- fig_path = sc_like_plot(sc.pl.heatmap, adata, request,adinfo)
120
- return {"figpath": fig_path}
121
- except ToolError as e:
122
- raise ToolError(e)
123
- except Exception as e:
124
- if hasattr(e, '__context__') and e.__context__:
125
- raise ToolError(e.__context__)
126
- else:
127
- raise ToolError(e)
190
+ def _tool_embedding(self):
191
+ def _embedding(request: EmbeddingModel, adinfo: self.AdataInfo=self.AdataInfo()):
192
+ """Scatter plot for user specified embedding basis (e.g. umap, tsne, etc)."""
193
+ try:
194
+ if (res := forward_request("pl_embedding", request, adinfo)) is not None:
195
+ return res
196
+ adata = get_ads().get_adata(adinfo=adinfo)
197
+ fig_path = sc_like_plot(sc.pl.embedding, adata, request, adinfo)
198
+ return {"figpath": fig_path}
199
+ except KeyError as e:
200
+ raise ToolError(f"doest found {e} in current sampleid with adtype {adinfo.adtype}")
201
+ except Exception as e:
202
+ if hasattr(e, '__context__') and e.__context__:
203
+ raise ToolError(e.__context__)
204
+ else:
205
+ raise ToolError(e)
206
+ return _embedding
128
207
 
208
+ def _tool_embedding_density(self):
209
+ def _embedding_density(request: EmbeddingDensityModel, adinfo: self.AdataInfo=self.AdataInfo()):
210
+ """Plot the density of cells in an embedding."""
211
+ try:
212
+ if (res := forward_request("pl_embedding_density", request, adinfo)) is not None:
213
+ return res
214
+ adata = get_ads().get_adata(adinfo=adinfo)
215
+ fig_path = sc_like_plot(sc.pl.embedding_density, adata, request, adinfo)
216
+ return {"figpath": fig_path}
217
+ except ToolError as e:
218
+ raise ToolError(e)
219
+ except Exception as e:
220
+ if hasattr(e, '__context__') and e.__context__:
221
+ raise ToolError(e.__context__)
222
+ else:
223
+ raise ToolError(e)
224
+ return _embedding_density
129
225
 
130
- @pl_mcp.tool()
131
- async def dotplot(
132
- request: DotplotModel,
133
- adinfo: AdataModel = AdataModel()
134
- ):
135
- """Plot dot plot of expression values per gene for each group."""
136
- try:
137
- result = await forward_request("pl_dotplot", request, adinfo)
138
- if result is not None:
139
- return result
140
- adata = get_ads().get_adata(adinfo=adinfo)
141
- fig_path = sc_like_plot(sc.pl.dotplot, adata, request,adinfo)
142
- return {"figpath": fig_path}
143
- except ToolError as e:
144
- raise ToolError(e)
145
- except Exception as e:
146
- if hasattr(e, '__context__') and e.__context__:
147
- raise ToolError(e.__context__)
148
- else:
149
- raise ToolError(e)
226
+ def _tool_rank_genes_groups(self):
227
+ def _rank_genes_groups(request: RankGenesGroupsModel, adinfo: self.AdataInfo=self.AdataInfo()):
228
+ """Plot ranking of genes based on differential expression."""
229
+ try:
230
+ if (res := forward_request("pl_rank_genes_groups", request, adinfo)) is not None:
231
+ return res
232
+ adata = get_ads().get_adata(adinfo=adinfo)
233
+ fig_path = sc_like_plot(sc.pl.rank_genes_groups, adata, request, adinfo)
234
+ return {"figpath": fig_path}
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
+ return _rank_genes_groups
150
243
 
151
- @pl_mcp.tool()
152
- async def matrixplot(
153
- request: MatrixplotModel,
154
- adinfo: AdataModel = AdataModel()
155
- ):
156
- """matrixplot, Create a heatmap of the mean expression values per group of each var_names."""
157
- try:
158
- result = await forward_request("pl_matrixplot", request, adinfo)
159
- if result is not None:
160
- return result
161
- adata = get_ads().get_adata(adinfo=adinfo)
162
- fig_path = sc_like_plot(sc.pl.matrixplot, adata, request,adinfo)
163
- return {"figpath": fig_path}
164
- except ToolError as e:
165
- raise ToolError(e)
166
- except Exception as e:
167
- if hasattr(e, '__context__') and e.__context__:
168
- raise ToolError(e.__context__)
169
- else:
170
- raise ToolError(e)
244
+ def _tool_rank_genes_groups_dotplot(self):
245
+ def _rank_genes_groups_dotplot(request: RankGenesGroupsDotplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
246
+ """Plot ranking of genes(DEGs) using dotplot visualization. Defualt plot DEGs for rank_genes_groups tool"""
247
+ try:
248
+ if (res := forward_request("pl_rank_genes_groups_dotplot", request, adinfo)) is not None:
249
+ return res
250
+ adata = get_ads().get_adata(adinfo=adinfo)
251
+ fig_path = sc_like_plot(sc.pl.rank_genes_groups_dotplot, adata, request, adinfo)
252
+ return {"figpath": fig_path}
253
+ except ToolError as e:
254
+ raise ToolError(e)
255
+ except Exception as e:
256
+ if hasattr(e, '__context__') and e.__context__:
257
+ raise ToolError(e.__context__)
258
+ else:
259
+ raise ToolError(e)
260
+ return _rank_genes_groups_dotplot
171
261
 
262
+ def _tool_clustermap(self):
263
+ def _clustermap(request: ClusterMapModel, adinfo: self.AdataInfo=self.AdataInfo()):
264
+ """Plot hierarchical clustering of cells and genes."""
265
+ try:
266
+ if (res := forward_request("pl_clustermap", request, adinfo)) is not None:
267
+ return res
268
+ adata = get_ads().get_adata(adinfo=adinfo)
269
+ fig_path = sc_like_plot(sc.pl.clustermap, adata, request, adinfo)
270
+ return {"figpath": fig_path}
271
+ except ToolError as e:
272
+ raise ToolError(e)
273
+ except Exception as e:
274
+ if hasattr(e, '__context__') and e.__context__:
275
+ raise ToolError(e.__context__)
276
+ else:
277
+ raise ToolError(e)
278
+ return _clustermap
172
279
 
173
- @pl_mcp.tool()
174
- async def tracksplot(
175
- request: TracksplotModel,
176
- adinfo: AdataModel = AdataModel()
177
- ):
178
- """tracksplot, compact plot of expression of a list of genes."""
179
- try:
180
- result = await forward_request("pl_tracksplot", request, adinfo)
181
- if result is not None:
182
- return result
183
- adata = get_ads().get_adata(adinfo=adinfo)
184
- fig_path = sc_like_plot(sc.pl.tracksplot, adata, request,adinfo)
185
- return {"figpath": fig_path}
186
- except ToolError as e:
187
- raise ToolError(e)
188
- except Exception as e:
189
- if hasattr(e, '__context__') and e.__context__:
190
- raise ToolError(e.__context__)
191
- else:
192
- raise ToolError(e)
280
+ def _tool_highly_variable_genes(self):
281
+ def _highly_variable_genes(request: HighlyVariableGenesModel, adinfo: self.AdataInfo=self.AdataInfo()):
282
+ """plot highly variable genes; Plot dispersions or normalized variance versus means for genes."""
283
+ try:
284
+ if (res := forward_request("pl_highly_variable_genes", request, adinfo)) is not None:
285
+ return res
286
+ adata = get_ads().get_adata(adinfo=adinfo)
287
+ fig_path = sc_like_plot(sc.pl.highly_variable_genes, adata, request, adinfo)
288
+ return {"figpath": fig_path}
289
+ except ToolError as e:
290
+ raise ToolError(e)
291
+ except Exception as e:
292
+ if hasattr(e, '__context__') and e.__context__:
293
+ raise ToolError(e.__context__)
294
+ else:
295
+ raise ToolError(e)
296
+ return _highly_variable_genes
193
297
 
194
- @pl_mcp.tool()
195
- async def scatter(
196
- request: EnhancedScatterModel = EnhancedScatterModel(),
197
- adinfo: AdataModel = AdataModel()
198
- ):
199
- """Plot a scatter plot of two variables, Scatter plot along observations or variables axes."""
200
- try:
201
- result = await forward_request("pl_scatter", request, adinfo)
202
- if result is not None:
203
- return result
204
- adata = get_ads().get_adata(adinfo=adinfo)
205
- fig_path = sc_like_plot(sc.pl.scatter, adata, request,adinfo)
206
- return {"figpath": fig_path}
207
- except ToolError as e:
208
- raise ToolError(e)
209
- except Exception as e:
210
- if hasattr(e, '__context__') and e.__context__:
211
- raise ToolError(e.__context__)
212
- else:
213
- raise ToolError(e)
298
+ def _tool_pca_variance_ratio(self):
299
+ def _pca_variance_ratio(request: PCAVarianceRatioModel, adinfo: self.AdataInfo=self.AdataInfo()):
300
+ """Plot the PCA variance ratio to visualize explained variance."""
301
+ try:
302
+ if (res := forward_request("pl_pca_variance_ratio", request, adinfo)) is not None:
303
+ return res
304
+ adata = get_ads().get_adata(adinfo=adinfo)
305
+ fig_path = sc_like_plot(sc.pl.pca_variance_ratio, adata, request, adinfo)
306
+ return {"figpath": fig_path}
307
+ except ToolError as e:
308
+ raise ToolError(e)
309
+ except Exception as e:
310
+ if hasattr(e, '__context__') and e.__context__:
311
+ raise ToolError(e.__context__)
312
+ else:
313
+ raise ToolError(e)
314
+ return _pca_variance_ratio
214
315
 
215
- @pl_mcp.tool()
216
- async def embedding(
217
- request: EmbeddingModel,
218
- adinfo: AdataModel = AdataModel()
219
- ):
220
- """Scatter plot for user specified embedding basis (e.g. umap, tsne, etc)."""
221
- try:
222
- result = await forward_request("pl_embedding", request, adinfo)
223
- if result is not None:
224
- return result
225
- adata = get_ads().get_adata(adinfo=adinfo)
226
- fig_path = sc_like_plot(sc.pl.embedding, adata, request,adinfo)
227
- return {"figpath": fig_path}
228
- except KeyError as e:
229
- raise ToolError(f"doest found {e} in current sampleid with adtype {adinfo.adtype}")
230
- except Exception as e:
231
- if hasattr(e, '__context__') and e.__context__:
232
- raise ToolError(e.__context__)
233
- else:
234
- raise ToolError(e)
235
-
236
-
237
- @pl_mcp.tool()
238
- async def embedding_density(
239
- request: EmbeddingDensityModel,
240
- adinfo: AdataModel = AdataModel()
241
- ):
242
- """Plot the density of cells in an embedding."""
243
- try:
244
- result = await forward_request("pl_embedding_density", request, adinfo)
245
- if result is not None:
246
- return result
247
- adata = get_ads().get_adata(adinfo=adinfo)
248
- fig_path = sc_like_plot(sc.pl.embedding_density, adata, request,adinfo)
249
- return {"figpath": fig_path}
250
- except ToolError as e:
251
- raise ToolError(e)
252
- except Exception as e:
253
- if hasattr(e, '__context__') and e.__context__:
254
- raise ToolError(e.__context__)
255
- else:
256
- raise ToolError(e)
257
-
258
- @pl_mcp.tool()
259
- async def rank_genes_groups(
260
- request: RankGenesGroupsModel,
261
- adinfo: AdataModel = AdataModel()
262
- ):
263
- """Plot ranking of genes based on differential expression."""
264
- try:
265
- result = await forward_request("pl_rank_genes_groups", request, adinfo)
266
- if result is not None:
267
- return result
268
- adata = get_ads().get_adata(adinfo=adinfo)
269
- fig_path = sc_like_plot(sc.pl.rank_genes_groups, adata, request,adinfo)
270
- return {"figpath": fig_path}
271
- except ToolError as e:
272
- raise ToolError(e)
273
- except Exception as e:
274
- if hasattr(e, '__context__') and e.__context__:
275
- raise ToolError(e.__context__)
276
- else:
277
- raise ToolError(e)
278
-
279
-
280
- @pl_mcp.tool()
281
- async def rank_genes_groups_dotplot(
282
- request: RankGenesGroupsDotplotModel,
283
- adinfo: AdataModel = AdataModel()
284
- ):
285
- """Plot ranking of genes(DEGs) using dotplot visualization. Defualt plot DEGs for rank_genes_groups tool"""
286
- from fastmcp.exceptions import ClientError
287
- try:
288
- result = await forward_request("pl_rank_genes_groups_dotplot", request, adinfo)
289
- if result is not None:
290
- return result
291
- adata = get_ads().get_adata(adinfo=adinfo)
292
- fig_path = sc_like_plot(sc.pl.rank_genes_groups_dotplot, adata, request,adinfo)
293
- return {"figpath": fig_path}
294
- except ToolError as e:
295
- raise ToolError(e)
296
- except Exception as e:
297
- if hasattr(e, '__context__') and e.__context__:
298
- raise ToolError(e.__context__)
299
- else:
300
- raise ToolError(e)
301
-
302
-
303
- @pl_mcp.tool()
304
- async def clustermap(
305
- request: ClusterMapModel = ClusterMapModel(),
306
- adinfo: AdataModel = AdataModel()
307
- ):
308
- """Plot hierarchical clustering of cells and genes."""
309
- try:
310
- result = await forward_request("pl_clustermap", request, adinfo)
311
- if result is not None:
312
- return result
313
- adata = get_ads().get_adata(adinfo=adinfo)
314
- fig_path = sc_like_plot(sc.pl.clustermap, adata, request,adinfo)
315
- return {"figpath": fig_path}
316
- except ToolError as e:
317
- raise ToolError(e)
318
- except Exception as e:
319
- if hasattr(e, '__context__') and e.__context__:
320
- raise ToolError(e.__context__)
321
- else:
322
- raise ToolError(e)
323
-
324
- @pl_mcp.tool()
325
- async def highly_variable_genes(
326
- request: HighlyVariableGenesModel = HighlyVariableGenesModel(),
327
- adinfo: AdataModel = AdataModel()
328
- ):
329
- """plot highly variable genes; Plot dispersions or normalized variance versus means for genes."""
330
- try:
331
- result = await forward_request("pl_highly_variable_genes", request, adinfo)
332
- if result is not None:
333
- return result
334
- adata = get_ads().get_adata(adinfo=adinfo)
335
- fig_path = sc_like_plot(sc.pl.highly_variable_genes, adata, request,adinfo)
336
- return {"figpath": fig_path}
337
- except ToolError as e:
338
- raise ToolError(e)
339
- except Exception as e:
340
- if hasattr(e, '__context__') and e.__context__:
341
- raise ToolError(e.__context__)
342
- else:
343
- raise ToolError(e)
344
-
345
-
346
- @pl_mcp.tool()
347
- async def pca_variance_ratio(
348
- request: PCAVarianceRatioModel = PCAVarianceRatioModel(),
349
- adinfo: AdataModel = AdataModel()
350
- ):
351
- """Plot the PCA variance ratio to visualize explained variance."""
352
- ### there is some bug, as scanpy.pl.pca_variance_ratio didn't return axis
353
- try:
354
- result = await forward_request("pl_pca_variance_ratio", request, adinfo)
355
- if result is not None:
356
- return result
357
- adata = get_ads().get_adata(adinfo=adinfo)
358
- fig_path = sc_like_plot(sc.pl.pca_variance_ratio, adata, request,adinfo)
359
- return {"figpath": fig_path}
360
- except ToolError as e:
361
- raise ToolError(e)
362
- except Exception as e:
363
- if hasattr(e, '__context__') and e.__context__:
364
- raise ToolError(e.__context__)
365
- else:
366
- raise ToolError(e)