scmcp-shared 0.4.0__py3-none-any.whl → 0.5.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 -3
- scmcp_shared/agent.py +58 -8
- scmcp_shared/backend.py +44 -0
- scmcp_shared/cli.py +75 -46
- scmcp_shared/kb.py +38 -0
- scmcp_shared/logging_config.py +6 -8
- scmcp_shared/mcp_base.py +184 -0
- scmcp_shared/schema/io.py +101 -59
- scmcp_shared/schema/pl.py +386 -490
- scmcp_shared/schema/pp.py +514 -265
- scmcp_shared/schema/preset/__init__.py +15 -0
- scmcp_shared/schema/preset/io.py +103 -0
- scmcp_shared/schema/preset/pl.py +843 -0
- scmcp_shared/schema/preset/pp.py +616 -0
- scmcp_shared/schema/preset/tl.py +917 -0
- scmcp_shared/schema/preset/util.py +123 -0
- scmcp_shared/schema/tl.py +355 -407
- scmcp_shared/schema/util.py +57 -72
- scmcp_shared/server/__init__.py +0 -12
- scmcp_shared/server/auto.py +10 -8
- scmcp_shared/server/code.py +3 -0
- scmcp_shared/server/preset/__init__.py +14 -0
- scmcp_shared/server/{io.py → preset/io.py} +26 -22
- scmcp_shared/server/{pl.py → preset/pl.py} +162 -78
- scmcp_shared/server/{pp.py → preset/pp.py} +123 -65
- scmcp_shared/server/{tl.py → preset/tl.py} +142 -79
- scmcp_shared/server/{util.py → preset/util.py} +123 -66
- scmcp_shared/util.py +109 -38
- scmcp_shared/vector_db/decoupler.lance/_transactions/0-9499b1b5-85d4-44c2-8f05-1bcce87fe4ef.txn +3 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/1-1632e7a3-4427-4077-8d03-57437144443d.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/10-dcf66479-eafb-4193-9358-198154aea1c1.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/11-2c6ddc17-49f5-47b5-8764-753297cf9e1b.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/12-f079d0a2-9c1c-4e7a-abf6-3e3c4cddac11.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/13-5bda9382-a06e-493d-85cb-e066172778ce.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/14-6f9c669f-25e2-4096-b7ea-9b421a37e110.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/15-2068cca9-31e8-45a3-86d1-bcb8924c72b9.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/16-72356bb2-5c98-424e-97aa-a92fa3453da6.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/17-9baa67ce-f6d3-478c-9511-20d01988d4d5.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/18-b9f2e28e-c4c5-4ce7-bf58-402d53a39558.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/19-d199d9f9-7990-4ec0-adde-e98c1c927202.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/2-3827747c-095e-41cb-af69-3814bab3a588.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/20-31c197a3-7a23-472f-a7e3-056c0ff11e3a.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/21-066e3024-36f8-4557-83ae-d2f338ec045c.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/22-1d1ccbe5-7c4c-4882-986a-c61ec2f7925e.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/23-b2c41628-b2d6-49f1-81b5-3cd9100894b4.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/24-e43e2e8d-9dd8-479f-b63c-d147e737c49f.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/25-188708e9-5ee1-4b5c-8e13-45dec8efd60d.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/26-4f4b6316-5680-4b31-8dd6-215cce66d7b5.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/27-c1855f86-abab-44ef-9e61-1312dffc9b06.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/28-650d2be0-e977-4177-b457-b733eea8b6ea.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/29-e47751d8-0e44-46da-82bd-4836b00a8431.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/3-518fc9b8-67de-48f7-94c8-f2398c63dbc5.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/30-0db3ea0f-deca-4b5b-9d70-9fb5f741f90c.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/31-ef76f0bb-bcfa-4031-b3ad-94b51ee818a9.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/32-a763e0f1-5c8d-460f-a455-0c6f6c4f1450.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/33-30bce2aa-8e6f-4f42-a323-c420133aa20f.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/34-f91ec2f9-d34b-4fcf-8bc7-564c28e50538.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/35-7f36a75c-96a7-4868-a4db-5d5f78ecf850.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/36-f2df7f99-a37c-458a-958d-7eb5e81eee18.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/37-e0af7415-955b-4167-8705-fa9ddb643e9a.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/38-6c24a9f0-ce71-4dda-8193-479aa23c5456.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/39-72b8a20c-3112-4cf1-8b05-b74a2c02c3f2.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/4-42904942-5a79-4f28-90ce-35a4ae8c40d1.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/40-95ac7526-6a2e-4914-9654-288c41bff370.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/41-13430464-5e62-4aa8-9709-513693a75095.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/42-cbb1ad83-a906-4540-bc37-4db158eac618.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/43-3c246401-d742-49a9-b24d-cfc457685461.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/44-11315c14-ecf4-4e3d-8690-46d57cb3e8c0.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/45-7bbf4bc6-96d4-425a-afa2-34aec7121c85.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/5-82dda0b4-7838-4f04-90f3-4b1e932c6891.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/6-c78352d8-16ba-4814-bd7f-74b8c0c5efe7.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/7-bb882b35-63f3-4c52-870f-6a64e3ac7f3c.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/8-fc84ad1b-1b59-4822-8fc7-70f4eb18f6d9.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_transactions/9-3404dcf1-bb17-40e6-9e5d-d9942dff90b2.txn +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/1.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/10.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/11.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/12.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/13.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/14.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/15.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/16.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/17.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/18.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/19.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/2.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/20.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/21.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/22.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/23.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/24.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/25.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/26.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/27.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/28.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/29.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/3.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/30.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/31.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/32.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/33.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/34.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/35.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/36.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/37.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/38.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/39.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/4.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/40.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/41.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/42.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/43.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/44.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/45.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/46.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/5.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/6.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/7.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/8.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/_versions/9.manifest +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/0cc94dc3-2ca3-403c-a9df-59753f24b3f2.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/254a1a71-cdd2-4cca-b7ec-a50540fed62c.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/2574d216-5f05-4794-9e1c-986fafde6ab4.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/26c7bbe7-5f97-4453-b065-123b764448b3.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/286595a6-88f6-4b05-861e-e4f607a6fcdb.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/33219b1a-7575-46ef-bb64-2bdbde1e692b.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/344ad7dd-98bb-41de-b347-2f17bf5735cb.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/395b1ecb-68fe-4dd3-a770-4b3ed393ae0c.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/3db97f4c-9c35-44b7-9042-82b4006c5a22.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/4540246e-b0bb-4f4d-8f98-60a64f1c42ed.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/4643dbc0-9e45-4b63-81e1-e06cf9bddcec.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/4f28eb52-d409-43f2-ae17-d1826f209006.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/4fda4a22-35f0-4897-b4c5-6cedefba66e6.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/51ee77b6-ab24-44c0-916e-b81ff3912731.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/539d15c9-e88b-400c-9ab7-08f5e8dca10d.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/54007132-91f5-4909-8678-c471ef4d100f.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/546d88ec-0d5c-42bb-bccc-3271f3f183a4.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/6912ad8a-343c-4ca1-b1b7-4300125e688e.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/6b72e4f7-3051-40a4-a492-6d9eff1c647d.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/6d7ee320-ae1c-4e49-8ce5-c85971b11ce6.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/6ea47b70-69d4-43e9-b2c6-442fe50e4dd1.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/72adb5ed-bf11-4d06-b146-0272d333db08.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/745907df-e261-4f4b-a757-2c01c058bf27.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/78988307-4c66-4ad7-b295-7463ecd53609.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/798ce305-6d60-4f28-b82a-e1f647907abf.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/7c159cce-2741-442b-9c63-f44bf2996718.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/7cd7a818-e68b-4fa8-bad3-23b60c386670.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/7ec553ed-0c7a-4bac-99b2-2ad976b40466.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/83efdc85-d990-4762-b69a-fb1c3938f60f.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/8c1613b3-8d69-49c5-bfd0-a021bb516faf.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/95cd1b22-1f93-4133-9841-de21549ad8c5.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/9a2ea5d4-087e-4d3a-b64b-6c568b8a0010.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/b1c47dc6-450a-4dca-b465-badb6a3619c2.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/b21d183a-c51d-463b-932e-9beb2e0da9aa.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/b2598625-8683-4c33-be40-6f1a7555dc2c.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/b7297b39-1fc5-4886-be21-708b369bef59.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/b7d90085-5bd6-48f9-8a73-17eb7cf556fa.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/b988ceee-57fc-423b-8e67-5729086c6946.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/bfd68ea6-ddf4-44bb-aa87-2669f0462f7d.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/cb8ac58e-0e59-4391-95ab-6195e71b9625.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/d0f10434-afb5-49c5-9e77-d39a4f8cca94.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/d3f89fec-5795-4e11-8c15-bc2206a7fae2.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/e063c8a4-5ef1-4933-a049-b41049d9be5f.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/e2348b24-f290-4fe2-a6c8-e98009ae4c1b.lance +0 -0
- scmcp_shared/vector_db/decoupler.lance/data/e5d3f893-6763-40dc-9d02-04e2f56a4883.lance +0 -0
- {scmcp_shared-0.4.0.dist-info → scmcp_shared-0.5.0.dist-info}/METADATA +2 -1
- scmcp_shared-0.5.0.dist-info/RECORD +171 -0
- scmcp_shared/server/base.py +0 -148
- scmcp_shared-0.4.0.dist-info/RECORD +0 -24
- {scmcp_shared-0.4.0.dist-info → scmcp_shared-0.5.0.dist-info}/WHEEL +0 -0
- {scmcp_shared-0.4.0.dist-info → scmcp_shared-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,20 +1,28 @@
|
|
1
|
-
import os
|
2
|
-
import inspect
|
3
1
|
import scanpy as sc
|
4
|
-
from fastmcp import FastMCP, Context
|
5
2
|
from fastmcp.tools.tool import Tool
|
6
3
|
from fastmcp.exceptions import ToolError
|
7
|
-
from
|
8
|
-
from
|
9
|
-
from
|
10
|
-
|
4
|
+
from scmcp_shared.schema.preset import AdataInfo
|
5
|
+
from scmcp_shared.schema.preset.pp import *
|
6
|
+
from scmcp_shared.util import (
|
7
|
+
filter_args,
|
8
|
+
add_op_log,
|
9
|
+
forward_request,
|
10
|
+
get_ads,
|
11
|
+
generate_msg,
|
12
|
+
)
|
13
|
+
from scmcp_shared.mcp_base import BaseMCP
|
11
14
|
|
12
15
|
|
13
16
|
class ScanpyPreprocessingMCP(BaseMCP):
|
14
|
-
def __init__(
|
17
|
+
def __init__(
|
18
|
+
self,
|
19
|
+
include_tools: list = None,
|
20
|
+
exclude_tools: list = None,
|
21
|
+
AdataInfo: AdataInfo = AdataInfo,
|
22
|
+
):
|
15
23
|
"""
|
16
24
|
Initialize ScanpyPreprocessingMCP with optional tool filtering.
|
17
|
-
|
25
|
+
|
18
26
|
Args:
|
19
27
|
include_tools (list, optional): List of tool names to include. If None, all tools are included.
|
20
28
|
exclude_tools (list, optional): List of tool names to exclude. If None, no tools are excluded.
|
@@ -23,7 +31,9 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
23
31
|
super().__init__("ScanpyMCP-PP-Server", include_tools, exclude_tools, AdataInfo)
|
24
32
|
|
25
33
|
def _tool_subset_cells(self):
|
26
|
-
def _subset_cells(
|
34
|
+
def _subset_cells(
|
35
|
+
request: SubsetCellParam, adinfo: self.AdataInfo = self.AdataInfo()
|
36
|
+
):
|
27
37
|
"""filter or subset cells based on total genes expressed counts and numbers. or values in adata.obs[obs_key]"""
|
28
38
|
try:
|
29
39
|
result = forward_request("subset_cells", request, adinfo)
|
@@ -39,34 +49,44 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
39
49
|
# Subset based on obs (cells) criteria
|
40
50
|
if request.obs_key is not None:
|
41
51
|
if request.obs_key not in adata.obs.columns:
|
42
|
-
raise ValueError(
|
52
|
+
raise ValueError(
|
53
|
+
f"Key '{request.obs_key}' not found in adata.obs"
|
54
|
+
)
|
43
55
|
mask = True # Start with all cells selected
|
44
56
|
if request.obs_value is not None:
|
45
57
|
mask = mask & (adata.obs[request.obs_key] == request.obs_value)
|
46
58
|
if request.obs_min is not None:
|
47
|
-
mask = mask & (adata.obs[request.obs_key] >= request.obs_min)
|
59
|
+
mask = mask & (adata.obs[request.obs_key] >= request.obs_min)
|
48
60
|
if request.obs_max is not None:
|
49
|
-
mask = mask & (adata.obs[request.obs_key] <= request.obs_max)
|
61
|
+
mask = mask & (adata.obs[request.obs_key] <= request.obs_max)
|
50
62
|
adata = adata[mask, :]
|
51
|
-
add_op_log(
|
63
|
+
add_op_log(
|
64
|
+
adata,
|
65
|
+
"subset_cells",
|
52
66
|
{
|
53
|
-
|
54
|
-
|
55
|
-
|
67
|
+
"obs_key": request.obs_key,
|
68
|
+
"obs_value": request.obs_value,
|
69
|
+
"obs_min": request.obs_min,
|
70
|
+
"obs_max": request.obs_max,
|
71
|
+
},
|
72
|
+
adinfo,
|
56
73
|
)
|
57
74
|
ads.set_adata(adata, adinfo=adinfo)
|
58
75
|
return [generate_msg(adinfo, adata, ads)]
|
59
76
|
except ToolError as e:
|
60
77
|
raise ToolError(e)
|
61
78
|
except Exception as e:
|
62
|
-
if hasattr(e,
|
79
|
+
if hasattr(e, "__context__") and e.__context__:
|
63
80
|
raise ToolError(e.__context__)
|
64
81
|
else:
|
65
82
|
raise ToolError(e)
|
66
|
-
|
83
|
+
|
84
|
+
return Tool.from_function(_subset_cells, name="subset_cells", enabled=True)
|
67
85
|
|
68
86
|
def _tool_subset_genes(self):
|
69
|
-
def _subset_genes(
|
87
|
+
def _subset_genes(
|
88
|
+
request: SubsetGeneParam, adinfo: self.AdataInfo = self.AdataInfo()
|
89
|
+
):
|
70
90
|
"""filter or subset genes based on number of cells or counts, or values in adata.var[var_key] or subset highly variable genes"""
|
71
91
|
try:
|
72
92
|
result = forward_request("pp_subset_genes", request, adinfo)
|
@@ -77,40 +97,48 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
77
97
|
adata = ads.get_adata(adinfo=adinfo).copy()
|
78
98
|
if request.highly_variable:
|
79
99
|
adata = adata[:, adata.var.highly_variable]
|
80
|
-
add_op_log(adata, "subset_genes",
|
81
|
-
{"hpv": "true"}, adinfo
|
82
|
-
)
|
100
|
+
add_op_log(adata, "subset_genes", {"hpv": "true"}, adinfo)
|
83
101
|
if func_kwargs:
|
84
102
|
sc.pp.filter_genes(adata, **func_kwargs)
|
85
103
|
add_op_log(adata, sc.pp.filter_genes, func_kwargs, adinfo)
|
86
104
|
if request.var_key is not None:
|
87
105
|
if request.var_key not in adata.var.columns:
|
88
|
-
raise ValueError(
|
106
|
+
raise ValueError(
|
107
|
+
f"Key '{request.var_key}' not found in adata.var"
|
108
|
+
)
|
89
109
|
mask = True # Start with all genes selected
|
90
110
|
if request.var_min is not None:
|
91
111
|
mask = mask & (adata.var[request.var_key] >= request.var_min)
|
92
112
|
if request.var_max is not None:
|
93
|
-
mask = mask & (adata.var[request.var_key] <= request.var_max)
|
113
|
+
mask = mask & (adata.var[request.var_key] <= request.var_max)
|
94
114
|
adata = adata[:, mask]
|
95
|
-
add_op_log(
|
115
|
+
add_op_log(
|
116
|
+
adata,
|
117
|
+
"subset_genes",
|
96
118
|
{
|
97
|
-
|
98
|
-
|
99
|
-
|
119
|
+
"var_key": request.var_key,
|
120
|
+
"var_min": request.var_min,
|
121
|
+
"var_max": request.var_max,
|
122
|
+
"hpv": request.highly_variable,
|
123
|
+
},
|
124
|
+
adinfo,
|
100
125
|
)
|
101
126
|
ads.set_adata(adata, adinfo=adinfo)
|
102
127
|
return [generate_msg(adinfo, adata, ads)]
|
103
128
|
except ToolError as e:
|
104
129
|
raise ToolError(e)
|
105
130
|
except Exception as e:
|
106
|
-
if hasattr(e,
|
131
|
+
if hasattr(e, "__context__") and e.__context__:
|
107
132
|
raise ToolError(e.__context__)
|
108
133
|
else:
|
109
134
|
raise ToolError(e)
|
110
|
-
|
135
|
+
|
136
|
+
return Tool.from_function(_subset_genes, name="subset_genes", enabled=True)
|
111
137
|
|
112
138
|
def _tool_calculate_qc_metrics(self):
|
113
|
-
def _calculate_qc_metrics(
|
139
|
+
def _calculate_qc_metrics(
|
140
|
+
request: CalculateQCMetrics, adinfo: self.AdataInfo = self.AdataInfo()
|
141
|
+
):
|
114
142
|
"""Calculate quality control metrics(common metrics: total counts, gene number, percentage of counts in ribosomal and mitochondrial) for AnnData."""
|
115
143
|
try:
|
116
144
|
result = forward_request("pp_calculate_qc_metrics", request, adinfo)
|
@@ -129,19 +157,27 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
129
157
|
sc.pp.calculate_qc_metrics(adata, **func_kwargs)
|
130
158
|
add_op_log(adata, sc.pp.calculate_qc_metrics, func_kwargs, adinfo)
|
131
159
|
except KeyError as e:
|
132
|
-
raise KeyError(
|
160
|
+
raise KeyError(
|
161
|
+
f"Cound find {e} in adata.var, consider to use mark_var tool to mark the variable"
|
162
|
+
)
|
133
163
|
return [generate_msg(adinfo, adata, ads)]
|
134
164
|
except ToolError as e:
|
135
165
|
raise ToolError(e)
|
136
166
|
except Exception as e:
|
137
|
-
if hasattr(e,
|
167
|
+
if hasattr(e, "__context__") and e.__context__:
|
138
168
|
raise ToolError(e.__context__)
|
139
169
|
else:
|
140
170
|
raise ToolError(e)
|
141
|
-
|
171
|
+
|
172
|
+
return Tool.from_function(
|
173
|
+
_calculate_qc_metrics, name="calculate_qc_metrics", enabled=True
|
174
|
+
)
|
142
175
|
|
143
176
|
def _tool_log1p(self):
|
144
|
-
def _log1p(
|
177
|
+
def _log1p(
|
178
|
+
request: Log1PParam = Log1PParam(),
|
179
|
+
adinfo: self.AdataInfo = self.AdataInfo(),
|
180
|
+
):
|
145
181
|
"""Logarithmize the data matrix"""
|
146
182
|
try:
|
147
183
|
result = forward_request("pp_log1p", request, adinfo)
|
@@ -161,14 +197,17 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
161
197
|
except ToolError as e:
|
162
198
|
raise ToolError(e)
|
163
199
|
except Exception as e:
|
164
|
-
if hasattr(e,
|
200
|
+
if hasattr(e, "__context__") and e.__context__:
|
165
201
|
raise ToolError(e.__context__)
|
166
202
|
else:
|
167
203
|
raise ToolError(e)
|
168
|
-
|
204
|
+
|
205
|
+
return Tool.from_function(_log1p, name="log1p", enabled=True)
|
169
206
|
|
170
207
|
def _tool_normalize_total(self):
|
171
|
-
def _normalize_total(
|
208
|
+
def _normalize_total(
|
209
|
+
request: NormalizeTotalParam, adinfo: self.AdataInfo = self.AdataInfo()
|
210
|
+
):
|
172
211
|
"""Normalize counts per cell to the same total count"""
|
173
212
|
try:
|
174
213
|
result = forward_request("pp_normalize_total", request, adinfo)
|
@@ -184,20 +223,25 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
184
223
|
except ToolError as e:
|
185
224
|
raise ToolError(e)
|
186
225
|
except Exception as e:
|
187
|
-
if hasattr(e,
|
226
|
+
if hasattr(e, "__context__") and e.__context__:
|
188
227
|
raise ToolError(e.__context__)
|
189
228
|
else:
|
190
229
|
raise ToolError(e)
|
191
|
-
|
230
|
+
|
231
|
+
return Tool.from_function(
|
232
|
+
_normalize_total, name="normalize_total", enabled=True
|
233
|
+
)
|
192
234
|
|
193
235
|
def _tool_highly_variable_genes(self):
|
194
|
-
def _highly_variable_genes(
|
236
|
+
def _highly_variable_genes(
|
237
|
+
request: HighlyVariableGenesParam, adinfo: self.AdataInfo = self.AdataInfo()
|
238
|
+
):
|
195
239
|
"""Annotate highly variable genes"""
|
196
240
|
try:
|
197
241
|
result = forward_request("pp_highly_variable_genes", request, adinfo)
|
198
242
|
if result is not None:
|
199
243
|
return result
|
200
|
-
try:
|
244
|
+
try:
|
201
245
|
func_kwargs = filter_args(request, sc.pp.highly_variable_genes)
|
202
246
|
ads = get_ads()
|
203
247
|
adata = ads.get_adata(adinfo=adinfo)
|
@@ -209,19 +253,24 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
209
253
|
except ToolError as e:
|
210
254
|
raise ToolError(e)
|
211
255
|
except Exception as e:
|
212
|
-
if hasattr(e,
|
256
|
+
if hasattr(e, "__context__") and e.__context__:
|
213
257
|
raise ToolError(e.__context__)
|
214
258
|
else:
|
215
259
|
raise ToolError(e)
|
216
|
-
|
260
|
+
|
261
|
+
return Tool.from_function(
|
262
|
+
_highly_variable_genes, name="highly_variable_genes", enabled=True
|
263
|
+
)
|
217
264
|
|
218
265
|
def _tool_regress_out(self):
|
219
|
-
def _regress_out(
|
266
|
+
def _regress_out(
|
267
|
+
request: RegressOutParam, adinfo: self.AdataInfo = self.AdataInfo()
|
268
|
+
):
|
220
269
|
"""Regress out (mostly) unwanted sources of variation."""
|
221
270
|
try:
|
222
271
|
result = forward_request("pp_regress_out", request, adinfo)
|
223
272
|
if result is not None:
|
224
|
-
return result
|
273
|
+
return result
|
225
274
|
func_kwargs = filter_args(request, sc.pp.regress_out)
|
226
275
|
ads = get_ads()
|
227
276
|
adata = ads.get_adata(adinfo=adinfo).copy()
|
@@ -232,44 +281,46 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
232
281
|
except ToolError as e:
|
233
282
|
raise ToolError(e)
|
234
283
|
except Exception as e:
|
235
|
-
if hasattr(e,
|
284
|
+
if hasattr(e, "__context__") and e.__context__:
|
236
285
|
raise ToolError(e.__context__)
|
237
286
|
else:
|
238
287
|
raise ToolError(e)
|
239
|
-
|
288
|
+
|
289
|
+
return Tool.from_function(_regress_out, name="regress_out", enabled=True)
|
240
290
|
|
241
291
|
def _tool_scale(self):
|
242
|
-
def _scale(request:
|
292
|
+
def _scale(request: ScaleParam, adinfo: self.AdataInfo = self.AdataInfo()):
|
243
293
|
"""Scale data to unit variance and zero mean"""
|
244
294
|
try:
|
245
295
|
result = forward_request("pp_scale", request, adinfo)
|
246
296
|
if result is not None:
|
247
|
-
return result
|
297
|
+
return result
|
248
298
|
func_kwargs = filter_args(request, sc.pp.scale)
|
249
299
|
ads = get_ads()
|
250
300
|
adata = ads.get_adata(adinfo=adinfo).copy()
|
251
301
|
|
252
302
|
sc.pp.scale(adata, **func_kwargs)
|
253
303
|
add_op_log(adata, sc.pp.scale, func_kwargs, adinfo)
|
254
|
-
|
304
|
+
|
255
305
|
ads.set_adata(adata, adinfo=adinfo)
|
256
306
|
return [generate_msg(adinfo, adata, ads)]
|
257
307
|
except ToolError as e:
|
258
308
|
raise ToolError(e)
|
259
309
|
except Exception as e:
|
260
|
-
if hasattr(e,
|
310
|
+
if hasattr(e, "__context__") and e.__context__:
|
261
311
|
raise ToolError(e.__context__)
|
262
312
|
else:
|
263
313
|
raise ToolError(e)
|
264
|
-
|
314
|
+
|
315
|
+
return Tool.from_function(_scale, name="scale", enabled=True)
|
265
316
|
|
266
317
|
def _tool_combat(self):
|
267
|
-
def _combat(request:
|
318
|
+
def _combat(request: CombatParam, adinfo: self.AdataInfo = self.AdataInfo()):
|
268
319
|
"""ComBat function for batch effect correction"""
|
269
320
|
try:
|
270
321
|
result = forward_request("pp_combat", request, adinfo)
|
271
322
|
if result is not None:
|
272
|
-
return result
|
323
|
+
return result
|
273
324
|
func_kwargs = filter_args(request, sc.pp.combat)
|
274
325
|
ads = get_ads()
|
275
326
|
adata = ads.get_adata(adinfo=adinfo).copy()
|
@@ -282,19 +333,22 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
282
333
|
except ToolError as e:
|
283
334
|
raise ToolError(e)
|
284
335
|
except Exception as e:
|
285
|
-
if hasattr(e,
|
336
|
+
if hasattr(e, "__context__") and e.__context__:
|
286
337
|
raise ToolError(e.__context__)
|
287
338
|
else:
|
288
339
|
raise ToolError(e)
|
289
|
-
|
340
|
+
|
341
|
+
return Tool.from_function(_combat, name="combat", enabled=True)
|
290
342
|
|
291
343
|
def _tool_scrublet(self):
|
292
|
-
def _scrublet(
|
344
|
+
def _scrublet(
|
345
|
+
request: ScrubletParam, adinfo: self.AdataInfo = self.AdataInfo()
|
346
|
+
):
|
293
347
|
"""Predict doublets using Scrublet"""
|
294
348
|
try:
|
295
349
|
result = forward_request("pp_scrublet", request, adinfo)
|
296
350
|
if result is not None:
|
297
|
-
return result
|
351
|
+
return result
|
298
352
|
func_kwargs = filter_args(request, sc.pp.scrublet)
|
299
353
|
ads = get_ads()
|
300
354
|
adata = ads.get_adata(adinfo=adinfo)
|
@@ -304,14 +358,17 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
304
358
|
except ToolError as e:
|
305
359
|
raise ToolError(e)
|
306
360
|
except Exception as e:
|
307
|
-
if hasattr(e,
|
361
|
+
if hasattr(e, "__context__") and e.__context__:
|
308
362
|
raise ToolError(e.__context__)
|
309
363
|
else:
|
310
364
|
raise ToolError(e)
|
311
|
-
|
365
|
+
|
366
|
+
return Tool.from_function(_scrublet, name="scrublet", enabled=True)
|
312
367
|
|
313
368
|
def _tool_neighbors(self):
|
314
|
-
def _neighbors(
|
369
|
+
def _neighbors(
|
370
|
+
request: NeighborsParam, adinfo: self.AdataInfo = self.AdataInfo()
|
371
|
+
):
|
315
372
|
"""Compute nearest neighbors distance matrix and neighborhood graph"""
|
316
373
|
try:
|
317
374
|
result = forward_request("pp_neighbors", request, adinfo)
|
@@ -326,8 +383,9 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
326
383
|
except ToolError as e:
|
327
384
|
raise ToolError(e)
|
328
385
|
except Exception as e:
|
329
|
-
if hasattr(e,
|
386
|
+
if hasattr(e, "__context__") and e.__context__:
|
330
387
|
raise ToolError(e.__context__)
|
331
388
|
else:
|
332
389
|
raise ToolError(e)
|
333
|
-
|
390
|
+
|
391
|
+
return Tool.from_function(_neighbors, name="neighbors", enabled=True)
|