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