scmcp-shared 0.3.7__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 +80 -0
- scmcp_shared/backend.py +44 -0
- scmcp_shared/cli.py +76 -37
- 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/tool.py +11 -0
- scmcp_shared/schema/util.py +57 -72
- scmcp_shared/server/__init__.py +0 -12
- scmcp_shared/server/auto.py +54 -0
- 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} +127 -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.3.7.dist-info → scmcp_shared-0.5.0.dist-info}/METADATA +3 -1
- scmcp_shared-0.5.0.dist-info/RECORD +171 -0
- scmcp_shared/server/base.py +0 -148
- scmcp_shared-0.3.7.dist-info/RECORD +0 -21
- {scmcp_shared-0.3.7.dist-info → scmcp_shared-0.5.0.dist-info}/WHEEL +0 -0
- {scmcp_shared-0.3.7.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)
|
@@ -120,24 +148,36 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
120
148
|
func_kwargs = filter_args(request, sc.pp.calculate_qc_metrics)
|
121
149
|
ads = get_ads()
|
122
150
|
adata = ads.get_adata(adinfo=adinfo)
|
151
|
+
if request.qc_vars:
|
152
|
+
for var in request.qc_vars:
|
153
|
+
if var not in adata.var.columns:
|
154
|
+
return f"Cound find {var} in adata.var, consider to use mark_var tool to mark the variable"
|
123
155
|
func_kwargs["inplace"] = True
|
124
156
|
try:
|
125
157
|
sc.pp.calculate_qc_metrics(adata, **func_kwargs)
|
126
158
|
add_op_log(adata, sc.pp.calculate_qc_metrics, func_kwargs, adinfo)
|
127
159
|
except KeyError as e:
|
128
|
-
raise KeyError(
|
160
|
+
raise KeyError(
|
161
|
+
f"Cound find {e} in adata.var, consider to use mark_var tool to mark the variable"
|
162
|
+
)
|
129
163
|
return [generate_msg(adinfo, adata, ads)]
|
130
164
|
except ToolError as e:
|
131
165
|
raise ToolError(e)
|
132
166
|
except Exception as e:
|
133
|
-
if hasattr(e,
|
167
|
+
if hasattr(e, "__context__") and e.__context__:
|
134
168
|
raise ToolError(e.__context__)
|
135
169
|
else:
|
136
170
|
raise ToolError(e)
|
137
|
-
|
171
|
+
|
172
|
+
return Tool.from_function(
|
173
|
+
_calculate_qc_metrics, name="calculate_qc_metrics", enabled=True
|
174
|
+
)
|
138
175
|
|
139
176
|
def _tool_log1p(self):
|
140
|
-
def _log1p(
|
177
|
+
def _log1p(
|
178
|
+
request: Log1PParam = Log1PParam(),
|
179
|
+
adinfo: self.AdataInfo = self.AdataInfo(),
|
180
|
+
):
|
141
181
|
"""Logarithmize the data matrix"""
|
142
182
|
try:
|
143
183
|
result = forward_request("pp_log1p", request, adinfo)
|
@@ -157,14 +197,17 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
157
197
|
except ToolError as e:
|
158
198
|
raise ToolError(e)
|
159
199
|
except Exception as e:
|
160
|
-
if hasattr(e,
|
200
|
+
if hasattr(e, "__context__") and e.__context__:
|
161
201
|
raise ToolError(e.__context__)
|
162
202
|
else:
|
163
203
|
raise ToolError(e)
|
164
|
-
|
204
|
+
|
205
|
+
return Tool.from_function(_log1p, name="log1p", enabled=True)
|
165
206
|
|
166
207
|
def _tool_normalize_total(self):
|
167
|
-
def _normalize_total(
|
208
|
+
def _normalize_total(
|
209
|
+
request: NormalizeTotalParam, adinfo: self.AdataInfo = self.AdataInfo()
|
210
|
+
):
|
168
211
|
"""Normalize counts per cell to the same total count"""
|
169
212
|
try:
|
170
213
|
result = forward_request("pp_normalize_total", request, adinfo)
|
@@ -180,20 +223,25 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
180
223
|
except ToolError as e:
|
181
224
|
raise ToolError(e)
|
182
225
|
except Exception as e:
|
183
|
-
if hasattr(e,
|
226
|
+
if hasattr(e, "__context__") and e.__context__:
|
184
227
|
raise ToolError(e.__context__)
|
185
228
|
else:
|
186
229
|
raise ToolError(e)
|
187
|
-
|
230
|
+
|
231
|
+
return Tool.from_function(
|
232
|
+
_normalize_total, name="normalize_total", enabled=True
|
233
|
+
)
|
188
234
|
|
189
235
|
def _tool_highly_variable_genes(self):
|
190
|
-
def _highly_variable_genes(
|
236
|
+
def _highly_variable_genes(
|
237
|
+
request: HighlyVariableGenesParam, adinfo: self.AdataInfo = self.AdataInfo()
|
238
|
+
):
|
191
239
|
"""Annotate highly variable genes"""
|
192
240
|
try:
|
193
241
|
result = forward_request("pp_highly_variable_genes", request, adinfo)
|
194
242
|
if result is not None:
|
195
243
|
return result
|
196
|
-
try:
|
244
|
+
try:
|
197
245
|
func_kwargs = filter_args(request, sc.pp.highly_variable_genes)
|
198
246
|
ads = get_ads()
|
199
247
|
adata = ads.get_adata(adinfo=adinfo)
|
@@ -205,19 +253,24 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
205
253
|
except ToolError as e:
|
206
254
|
raise ToolError(e)
|
207
255
|
except Exception as e:
|
208
|
-
if hasattr(e,
|
256
|
+
if hasattr(e, "__context__") and e.__context__:
|
209
257
|
raise ToolError(e.__context__)
|
210
258
|
else:
|
211
259
|
raise ToolError(e)
|
212
|
-
|
260
|
+
|
261
|
+
return Tool.from_function(
|
262
|
+
_highly_variable_genes, name="highly_variable_genes", enabled=True
|
263
|
+
)
|
213
264
|
|
214
265
|
def _tool_regress_out(self):
|
215
|
-
def _regress_out(
|
266
|
+
def _regress_out(
|
267
|
+
request: RegressOutParam, adinfo: self.AdataInfo = self.AdataInfo()
|
268
|
+
):
|
216
269
|
"""Regress out (mostly) unwanted sources of variation."""
|
217
270
|
try:
|
218
271
|
result = forward_request("pp_regress_out", request, adinfo)
|
219
272
|
if result is not None:
|
220
|
-
return result
|
273
|
+
return result
|
221
274
|
func_kwargs = filter_args(request, sc.pp.regress_out)
|
222
275
|
ads = get_ads()
|
223
276
|
adata = ads.get_adata(adinfo=adinfo).copy()
|
@@ -228,44 +281,46 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
228
281
|
except ToolError as e:
|
229
282
|
raise ToolError(e)
|
230
283
|
except Exception as e:
|
231
|
-
if hasattr(e,
|
284
|
+
if hasattr(e, "__context__") and e.__context__:
|
232
285
|
raise ToolError(e.__context__)
|
233
286
|
else:
|
234
287
|
raise ToolError(e)
|
235
|
-
|
288
|
+
|
289
|
+
return Tool.from_function(_regress_out, name="regress_out", enabled=True)
|
236
290
|
|
237
291
|
def _tool_scale(self):
|
238
|
-
def _scale(request:
|
292
|
+
def _scale(request: ScaleParam, adinfo: self.AdataInfo = self.AdataInfo()):
|
239
293
|
"""Scale data to unit variance and zero mean"""
|
240
294
|
try:
|
241
295
|
result = forward_request("pp_scale", request, adinfo)
|
242
296
|
if result is not None:
|
243
|
-
return result
|
297
|
+
return result
|
244
298
|
func_kwargs = filter_args(request, sc.pp.scale)
|
245
299
|
ads = get_ads()
|
246
300
|
adata = ads.get_adata(adinfo=adinfo).copy()
|
247
301
|
|
248
302
|
sc.pp.scale(adata, **func_kwargs)
|
249
303
|
add_op_log(adata, sc.pp.scale, func_kwargs, adinfo)
|
250
|
-
|
304
|
+
|
251
305
|
ads.set_adata(adata, adinfo=adinfo)
|
252
306
|
return [generate_msg(adinfo, adata, ads)]
|
253
307
|
except ToolError as e:
|
254
308
|
raise ToolError(e)
|
255
309
|
except Exception as e:
|
256
|
-
if hasattr(e,
|
310
|
+
if hasattr(e, "__context__") and e.__context__:
|
257
311
|
raise ToolError(e.__context__)
|
258
312
|
else:
|
259
313
|
raise ToolError(e)
|
260
|
-
|
314
|
+
|
315
|
+
return Tool.from_function(_scale, name="scale", enabled=True)
|
261
316
|
|
262
317
|
def _tool_combat(self):
|
263
|
-
def _combat(request:
|
318
|
+
def _combat(request: CombatParam, adinfo: self.AdataInfo = self.AdataInfo()):
|
264
319
|
"""ComBat function for batch effect correction"""
|
265
320
|
try:
|
266
321
|
result = forward_request("pp_combat", request, adinfo)
|
267
322
|
if result is not None:
|
268
|
-
return result
|
323
|
+
return result
|
269
324
|
func_kwargs = filter_args(request, sc.pp.combat)
|
270
325
|
ads = get_ads()
|
271
326
|
adata = ads.get_adata(adinfo=adinfo).copy()
|
@@ -278,19 +333,22 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
278
333
|
except ToolError as e:
|
279
334
|
raise ToolError(e)
|
280
335
|
except Exception as e:
|
281
|
-
if hasattr(e,
|
336
|
+
if hasattr(e, "__context__") and e.__context__:
|
282
337
|
raise ToolError(e.__context__)
|
283
338
|
else:
|
284
339
|
raise ToolError(e)
|
285
|
-
|
340
|
+
|
341
|
+
return Tool.from_function(_combat, name="combat", enabled=True)
|
286
342
|
|
287
343
|
def _tool_scrublet(self):
|
288
|
-
def _scrublet(
|
344
|
+
def _scrublet(
|
345
|
+
request: ScrubletParam, adinfo: self.AdataInfo = self.AdataInfo()
|
346
|
+
):
|
289
347
|
"""Predict doublets using Scrublet"""
|
290
348
|
try:
|
291
349
|
result = forward_request("pp_scrublet", request, adinfo)
|
292
350
|
if result is not None:
|
293
|
-
return result
|
351
|
+
return result
|
294
352
|
func_kwargs = filter_args(request, sc.pp.scrublet)
|
295
353
|
ads = get_ads()
|
296
354
|
adata = ads.get_adata(adinfo=adinfo)
|
@@ -300,14 +358,17 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
300
358
|
except ToolError as e:
|
301
359
|
raise ToolError(e)
|
302
360
|
except Exception as e:
|
303
|
-
if hasattr(e,
|
361
|
+
if hasattr(e, "__context__") and e.__context__:
|
304
362
|
raise ToolError(e.__context__)
|
305
363
|
else:
|
306
364
|
raise ToolError(e)
|
307
|
-
|
365
|
+
|
366
|
+
return Tool.from_function(_scrublet, name="scrublet", enabled=True)
|
308
367
|
|
309
368
|
def _tool_neighbors(self):
|
310
|
-
def _neighbors(
|
369
|
+
def _neighbors(
|
370
|
+
request: NeighborsParam, adinfo: self.AdataInfo = self.AdataInfo()
|
371
|
+
):
|
311
372
|
"""Compute nearest neighbors distance matrix and neighborhood graph"""
|
312
373
|
try:
|
313
374
|
result = forward_request("pp_neighbors", request, adinfo)
|
@@ -322,8 +383,9 @@ class ScanpyPreprocessingMCP(BaseMCP):
|
|
322
383
|
except ToolError as e:
|
323
384
|
raise ToolError(e)
|
324
385
|
except Exception as e:
|
325
|
-
if hasattr(e,
|
386
|
+
if hasattr(e, "__context__") and e.__context__:
|
326
387
|
raise ToolError(e.__context__)
|
327
388
|
else:
|
328
389
|
raise ToolError(e)
|
329
|
-
|
390
|
+
|
391
|
+
return Tool.from_function(_neighbors, name="neighbors", enabled=True)
|