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/pl.py CHANGED
@@ -3,319 +3,313 @@ import inspect
3
3
  from functools import partial
4
4
  import scanpy as sc
5
5
  from fastmcp import FastMCP, Context
6
+ from fastmcp.exceptions import ToolError
6
7
  from ..schema.pl import *
8
+ from ..schema import AdataInfo
7
9
  from pathlib import Path
8
- from ..logging_config import setup_logger
9
10
  from ..util import forward_request, sc_like_plot, get_ads
11
+ from .base import BaseMCP
10
12
 
11
13
 
12
- 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)
13
25
 
14
- 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
15
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
16
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
17
81
 
18
- @pl_mcp.tool()
19
- async def pca(request: PCAModel = PCAModel()):
20
- """Scatter plot in PCA coordinates. default figure for PCA plot"""
21
- try:
22
- result = await forward_request("pl_pca", request)
23
- if result is not None:
24
- return result
25
- adata = get_ads().get_adata(request=request)
26
- fig_path = sc_like_plot(sc.pl.pca, adata, request)
27
- return {"figpath": fig_path}
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
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
35
99
 
36
- @pl_mcp.tool()
37
- async def diffmap(request: DiffusionMapModel = DiffusionMapModel()):
38
- """Plot diffusion map embedding of cells."""
39
- try:
40
- result = await forward_request("pl_diffmap", request)
41
- if result is not None:
42
- return result
43
- adata = get_ads().get_adata(request=request)
44
- fig_path = sc_like_plot(sc.pl.diffmap, adata, request)
45
- return {"figpath": fig_path}
46
- except KeyError as e:
47
- raise e
48
- except Exception as e:
49
- if hasattr(e, '__context__') and e.__context__:
50
- raise Exception(f"{str(e.__context__)}")
51
- else:
52
- raise 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
53
117
 
54
- @pl_mcp.tool()
55
- async def violin(request: ViolinModel,):
56
- """Plot violin plot of one or more variables."""
57
- try:
58
- result = await forward_request("pl_violin", request)
59
- if result is not None:
60
- return result
61
- adata = get_ads().get_adata(request=request)
62
- fig_path = sc_like_plot(sc.pl.violin, adata, request)
63
- return {"figpath": fig_path}
64
- except KeyError as e:
65
- raise f"doest found {e} in current sampleid with adtype {request.adtype}"
66
- except Exception as e:
67
- if hasattr(e, '__context__') and e.__context__:
68
- raise Exception(f"{str(e.__context__)}")
69
- else:
70
- raise 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
71
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
72
153
 
73
- @pl_mcp.tool()
74
- async def stacked_violin(request: StackedViolinModel = StackedViolinModel()):
75
- """Plot stacked violin plots. Makes a compact image composed of individual violin plots stacked on top of each other."""
76
- try:
77
- result = await forward_request("pl_stacked_violin", request)
78
- if result is not None:
79
- return result
80
- adata = get_ads().get_adata(request=request)
81
- fig_path = sc_like_plot(sc.pl.stacked_violin, adata, request)
82
- return {"figpath": fig_path}
83
- except KeyError as e:
84
- raise e
85
- except Exception as e:
86
- if hasattr(e, '__context__') and e.__context__:
87
- raise Exception(f"{str(e.__context__)}")
88
- else:
89
- raise 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
90
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
91
189
 
92
- @pl_mcp.tool()
93
- async def heatmap(request: HeatmapModel):
94
- """Heatmap of the expression values of genes."""
95
- try:
96
- result = await forward_request("pl_heatmap", request)
97
- if result is not None:
98
- return result
99
- adata = get_ads().get_adata(request=request)
100
- fig_path = sc_like_plot(sc.pl.heatmap, adata, request)
101
- return {"figpath": fig_path}
102
- except KeyError as e:
103
- raise e
104
- except Exception as e:
105
- if hasattr(e, '__context__') and e.__context__:
106
- raise Exception(f"{str(e.__context__)}")
107
- else:
108
- raise 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
109
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
110
225
 
111
- @pl_mcp.tool()
112
- async def dotplot(request: DotplotModel):
113
- """Plot dot plot of expression values per gene for each group."""
114
- try:
115
- result = await forward_request("pl_dotplot", request)
116
- if result is not None:
117
- return result
118
- adata = get_ads().get_adata(request=request)
119
- fig_path = sc_like_plot(sc.pl.dotplot, adata, request)
120
- return {"figpath": fig_path}
121
- except KeyError as e:
122
- raise e
123
- except Exception as e:
124
- if hasattr(e, '__context__') and e.__context__:
125
- raise Exception(f"{str(e.__context__)}")
126
- else:
127
- raise 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
128
243
 
129
- @pl_mcp.tool()
130
- async def matrixplot(request: MatrixplotModel):
131
- """matrixplot, Create a heatmap of the mean expression values per group of each var_names."""
132
- try:
133
- result = await forward_request("pl_matrixplot", request)
134
- if result is not None:
135
- return result
136
- adata = get_ads().get_adata(request=request)
137
- fig_path = sc_like_plot(sc.pl.matrixplot, adata, request)
138
- return {"figpath": fig_path}
139
- except KeyError as e:
140
- raise e
141
- except Exception as e:
142
- if hasattr(e, '__context__') and e.__context__:
143
- raise Exception(f"{str(e.__context__)}")
144
- else:
145
- raise 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
146
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
147
279
 
148
- @pl_mcp.tool()
149
- async def tracksplot(request: TracksplotModel):
150
- """tracksplot, compact plot of expression of a list of genes."""
151
- try:
152
- result = await forward_request("pl_tracksplot", request)
153
- if result is not None:
154
- return result
155
- adata = get_ads().get_adata(request=request)
156
- fig_path = sc_like_plot(sc.pl.tracksplot, adata, request)
157
- return {"figpath": fig_path}
158
- except KeyError as e:
159
- raise e
160
- except Exception as e:
161
- if hasattr(e, '__context__') and e.__context__:
162
- raise Exception(f"{str(e.__context__)}")
163
- else:
164
- raise 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
165
297
 
166
- @pl_mcp.tool()
167
- async def scatter(request: EnhancedScatterModel = EnhancedScatterModel()):
168
- """Plot a scatter plot of two variables, Scatter plot along observations or variables axes."""
169
- try:
170
- result = await forward_request("pl_scatter", request)
171
- if result is not None:
172
- return result
173
- adata = get_ads().get_adata(request=request)
174
- fig_path = sc_like_plot(sc.pl.scatter, adata, request)
175
- return {"figpath": fig_path}
176
- except KeyError as e:
177
- raise e
178
- except Exception as e:
179
- if hasattr(e, '__context__') and e.__context__:
180
- raise Exception(f"{str(e.__context__)}")
181
- else:
182
- raise 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
183
315
 
184
- @pl_mcp.tool()
185
- async def embedding(request: EmbeddingModel):
186
- """Scatter plot for user specified embedding basis (e.g. umap, tsne, etc)."""
187
- try:
188
- result = await forward_request("pl_embedding", request)
189
- if result is not None:
190
- return result
191
- adata = get_ads().get_adata(request=request)
192
- fig_path = sc_like_plot(sc.pl.embedding, adata, request)
193
- return {"figpath": fig_path}
194
- except KeyError as e:
195
- from fastmcp.exceptions import ToolError
196
- raise ToolError(f"doest found {e} in current sampleid with adtype {request.adtype}")
197
- except Exception as e:
198
- if hasattr(e, '__context__') and e.__context__:
199
- raise Exception(f"{str(e.__context__)}")
200
- else:
201
- raise e
202
-
203
-
204
- @pl_mcp.tool()
205
- async def embedding_density(request: EmbeddingDensityModel):
206
- """Plot the density of cells in an embedding."""
207
- try:
208
- result = await forward_request("pl_embedding_density", request)
209
- if result is not None:
210
- return result
211
- adata = get_ads().get_adata(request=request)
212
- fig_path = sc_like_plot(sc.pl.embedding_density, adata, request)
213
- return {"figpath": fig_path}
214
- except KeyError as e:
215
- raise e
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
- @pl_mcp.tool()
223
- async def rank_genes_groups(request: RankGenesGroupsModel):
224
- """Plot ranking of genes based on differential expression."""
225
- try:
226
- result = await forward_request("pl_rank_genes_groups", request)
227
- if result is not None:
228
- return result
229
- adata = get_ads().get_adata(request=request)
230
- fig_path = sc_like_plot(sc.pl.rank_genes_groups, adata, request)
231
- return {"figpath": fig_path}
232
- except KeyError as e:
233
- raise e
234
- except Exception as e:
235
- if hasattr(e, '__context__') and e.__context__:
236
- raise Exception(f"{str(e.__context__)}")
237
- else:
238
- raise e
239
-
240
-
241
- @pl_mcp.tool()
242
- async def rank_genes_groups_dotplot(
243
- request: RankGenesGroupsDotplotModel,
244
- ):
245
- """Plot ranking of genes(DEGs) using dotplot visualization. Defualt plot DEGs for rank_genes_groups tool"""
246
- try:
247
- result = await forward_request("pl_rank_genes_groups_dotplot", request)
248
- if result is not None:
249
- return result
250
- adata = get_ads().get_adata(request=request)
251
- fig_path = sc_like_plot(sc.pl.rank_genes_groups_dotplot, adata, request)
252
- return {"figpath": fig_path}
253
- except KeyError as e:
254
- raise e
255
- except Exception as e:
256
- if hasattr(e, '__context__') and e.__context__:
257
- raise Exception(f"{str(e.__context__)}")
258
- else:
259
- raise e
260
-
261
-
262
- @pl_mcp.tool()
263
- async def clustermap(
264
- request: ClusterMapModel = ClusterMapModel()
265
- ):
266
- """Plot hierarchical clustering of cells and genes."""
267
- try:
268
- result = await forward_request("pl_clustermap", request)
269
- if result is not None:
270
- return result
271
- adata = get_ads().get_adata(request=request)
272
- fig_path = sc_like_plot(sc.pl.clustermap, adata, request)
273
- return {"figpath": fig_path}
274
- except KeyError as e:
275
- raise e
276
- except Exception as e:
277
- if hasattr(e, '__context__') and e.__context__:
278
- raise Exception(f"{str(e.__context__)}")
279
- else:
280
- raise e
281
-
282
- @pl_mcp.tool()
283
- async def highly_variable_genes(
284
- request: HighlyVariableGenesModel = HighlyVariableGenesModel()
285
- ):
286
- """plot highly variable genes; Plot dispersions or normalized variance versus means for genes."""
287
- try:
288
- result = await forward_request("pl_highly_variable_genes", request)
289
- if result is not None:
290
- return result
291
- adata = get_ads().get_adata(request=request)
292
- fig_path = sc_like_plot(sc.pl.highly_variable_genes, adata, request)
293
- return {"figpath": fig_path}
294
- except KeyError as e:
295
- raise e
296
- except Exception as e:
297
- if hasattr(e, '__context__') and e.__context__:
298
- raise Exception(f"{str(e.__context__)}")
299
- else:
300
- raise e
301
-
302
-
303
- @pl_mcp.tool()
304
- async def pca_variance_ratio(
305
- request: PCAVarianceRatioModel = PCAVarianceRatioModel()
306
- ):
307
- """Plot the PCA variance ratio to visualize explained variance."""
308
- try:
309
- result = await forward_request("pl_pca_variance_ratio", request)
310
- if result is not None:
311
- return result
312
- adata = get_ads().get_adata(request=request)
313
- fig_path = sc_like_plot(sc.pl.pca_variance_ratio, adata, request)
314
- return {"figpath": fig_path}
315
- except KeyError as e:
316
- raise e
317
- except Exception as e:
318
- if hasattr(e, '__context__') and e.__context__:
319
- raise Exception(f"{str(e.__context__)}")
320
- else:
321
- raise e