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.
Files changed (172) hide show
  1. scmcp_shared/__init__.py +1 -3
  2. scmcp_shared/agent.py +80 -0
  3. scmcp_shared/backend.py +44 -0
  4. scmcp_shared/cli.py +76 -37
  5. scmcp_shared/kb.py +38 -0
  6. scmcp_shared/logging_config.py +6 -8
  7. scmcp_shared/mcp_base.py +184 -0
  8. scmcp_shared/schema/io.py +101 -59
  9. scmcp_shared/schema/pl.py +386 -490
  10. scmcp_shared/schema/pp.py +514 -265
  11. scmcp_shared/schema/preset/__init__.py +15 -0
  12. scmcp_shared/schema/preset/io.py +103 -0
  13. scmcp_shared/schema/preset/pl.py +843 -0
  14. scmcp_shared/schema/preset/pp.py +616 -0
  15. scmcp_shared/schema/preset/tl.py +917 -0
  16. scmcp_shared/schema/preset/util.py +123 -0
  17. scmcp_shared/schema/tl.py +355 -407
  18. scmcp_shared/schema/tool.py +11 -0
  19. scmcp_shared/schema/util.py +57 -72
  20. scmcp_shared/server/__init__.py +0 -12
  21. scmcp_shared/server/auto.py +54 -0
  22. scmcp_shared/server/code.py +3 -0
  23. scmcp_shared/server/preset/__init__.py +14 -0
  24. scmcp_shared/server/{io.py → preset/io.py} +26 -22
  25. scmcp_shared/server/{pl.py → preset/pl.py} +162 -78
  26. scmcp_shared/server/{pp.py → preset/pp.py} +127 -65
  27. scmcp_shared/server/{tl.py → preset/tl.py} +142 -79
  28. scmcp_shared/server/{util.py → preset/util.py} +123 -66
  29. scmcp_shared/util.py +109 -38
  30. scmcp_shared/vector_db/decoupler.lance/_transactions/0-9499b1b5-85d4-44c2-8f05-1bcce87fe4ef.txn +3 -0
  31. scmcp_shared/vector_db/decoupler.lance/_transactions/1-1632e7a3-4427-4077-8d03-57437144443d.txn +0 -0
  32. scmcp_shared/vector_db/decoupler.lance/_transactions/10-dcf66479-eafb-4193-9358-198154aea1c1.txn +0 -0
  33. scmcp_shared/vector_db/decoupler.lance/_transactions/11-2c6ddc17-49f5-47b5-8764-753297cf9e1b.txn +0 -0
  34. scmcp_shared/vector_db/decoupler.lance/_transactions/12-f079d0a2-9c1c-4e7a-abf6-3e3c4cddac11.txn +0 -0
  35. scmcp_shared/vector_db/decoupler.lance/_transactions/13-5bda9382-a06e-493d-85cb-e066172778ce.txn +0 -0
  36. scmcp_shared/vector_db/decoupler.lance/_transactions/14-6f9c669f-25e2-4096-b7ea-9b421a37e110.txn +0 -0
  37. scmcp_shared/vector_db/decoupler.lance/_transactions/15-2068cca9-31e8-45a3-86d1-bcb8924c72b9.txn +0 -0
  38. scmcp_shared/vector_db/decoupler.lance/_transactions/16-72356bb2-5c98-424e-97aa-a92fa3453da6.txn +0 -0
  39. scmcp_shared/vector_db/decoupler.lance/_transactions/17-9baa67ce-f6d3-478c-9511-20d01988d4d5.txn +0 -0
  40. scmcp_shared/vector_db/decoupler.lance/_transactions/18-b9f2e28e-c4c5-4ce7-bf58-402d53a39558.txn +0 -0
  41. scmcp_shared/vector_db/decoupler.lance/_transactions/19-d199d9f9-7990-4ec0-adde-e98c1c927202.txn +0 -0
  42. scmcp_shared/vector_db/decoupler.lance/_transactions/2-3827747c-095e-41cb-af69-3814bab3a588.txn +0 -0
  43. scmcp_shared/vector_db/decoupler.lance/_transactions/20-31c197a3-7a23-472f-a7e3-056c0ff11e3a.txn +0 -0
  44. scmcp_shared/vector_db/decoupler.lance/_transactions/21-066e3024-36f8-4557-83ae-d2f338ec045c.txn +0 -0
  45. scmcp_shared/vector_db/decoupler.lance/_transactions/22-1d1ccbe5-7c4c-4882-986a-c61ec2f7925e.txn +0 -0
  46. scmcp_shared/vector_db/decoupler.lance/_transactions/23-b2c41628-b2d6-49f1-81b5-3cd9100894b4.txn +0 -0
  47. scmcp_shared/vector_db/decoupler.lance/_transactions/24-e43e2e8d-9dd8-479f-b63c-d147e737c49f.txn +0 -0
  48. scmcp_shared/vector_db/decoupler.lance/_transactions/25-188708e9-5ee1-4b5c-8e13-45dec8efd60d.txn +0 -0
  49. scmcp_shared/vector_db/decoupler.lance/_transactions/26-4f4b6316-5680-4b31-8dd6-215cce66d7b5.txn +0 -0
  50. scmcp_shared/vector_db/decoupler.lance/_transactions/27-c1855f86-abab-44ef-9e61-1312dffc9b06.txn +0 -0
  51. scmcp_shared/vector_db/decoupler.lance/_transactions/28-650d2be0-e977-4177-b457-b733eea8b6ea.txn +0 -0
  52. scmcp_shared/vector_db/decoupler.lance/_transactions/29-e47751d8-0e44-46da-82bd-4836b00a8431.txn +0 -0
  53. scmcp_shared/vector_db/decoupler.lance/_transactions/3-518fc9b8-67de-48f7-94c8-f2398c63dbc5.txn +0 -0
  54. scmcp_shared/vector_db/decoupler.lance/_transactions/30-0db3ea0f-deca-4b5b-9d70-9fb5f741f90c.txn +0 -0
  55. scmcp_shared/vector_db/decoupler.lance/_transactions/31-ef76f0bb-bcfa-4031-b3ad-94b51ee818a9.txn +0 -0
  56. scmcp_shared/vector_db/decoupler.lance/_transactions/32-a763e0f1-5c8d-460f-a455-0c6f6c4f1450.txn +0 -0
  57. scmcp_shared/vector_db/decoupler.lance/_transactions/33-30bce2aa-8e6f-4f42-a323-c420133aa20f.txn +0 -0
  58. scmcp_shared/vector_db/decoupler.lance/_transactions/34-f91ec2f9-d34b-4fcf-8bc7-564c28e50538.txn +0 -0
  59. scmcp_shared/vector_db/decoupler.lance/_transactions/35-7f36a75c-96a7-4868-a4db-5d5f78ecf850.txn +0 -0
  60. scmcp_shared/vector_db/decoupler.lance/_transactions/36-f2df7f99-a37c-458a-958d-7eb5e81eee18.txn +0 -0
  61. scmcp_shared/vector_db/decoupler.lance/_transactions/37-e0af7415-955b-4167-8705-fa9ddb643e9a.txn +0 -0
  62. scmcp_shared/vector_db/decoupler.lance/_transactions/38-6c24a9f0-ce71-4dda-8193-479aa23c5456.txn +0 -0
  63. scmcp_shared/vector_db/decoupler.lance/_transactions/39-72b8a20c-3112-4cf1-8b05-b74a2c02c3f2.txn +0 -0
  64. scmcp_shared/vector_db/decoupler.lance/_transactions/4-42904942-5a79-4f28-90ce-35a4ae8c40d1.txn +0 -0
  65. scmcp_shared/vector_db/decoupler.lance/_transactions/40-95ac7526-6a2e-4914-9654-288c41bff370.txn +0 -0
  66. scmcp_shared/vector_db/decoupler.lance/_transactions/41-13430464-5e62-4aa8-9709-513693a75095.txn +0 -0
  67. scmcp_shared/vector_db/decoupler.lance/_transactions/42-cbb1ad83-a906-4540-bc37-4db158eac618.txn +0 -0
  68. scmcp_shared/vector_db/decoupler.lance/_transactions/43-3c246401-d742-49a9-b24d-cfc457685461.txn +0 -0
  69. scmcp_shared/vector_db/decoupler.lance/_transactions/44-11315c14-ecf4-4e3d-8690-46d57cb3e8c0.txn +0 -0
  70. scmcp_shared/vector_db/decoupler.lance/_transactions/45-7bbf4bc6-96d4-425a-afa2-34aec7121c85.txn +0 -0
  71. scmcp_shared/vector_db/decoupler.lance/_transactions/5-82dda0b4-7838-4f04-90f3-4b1e932c6891.txn +0 -0
  72. scmcp_shared/vector_db/decoupler.lance/_transactions/6-c78352d8-16ba-4814-bd7f-74b8c0c5efe7.txn +0 -0
  73. scmcp_shared/vector_db/decoupler.lance/_transactions/7-bb882b35-63f3-4c52-870f-6a64e3ac7f3c.txn +0 -0
  74. scmcp_shared/vector_db/decoupler.lance/_transactions/8-fc84ad1b-1b59-4822-8fc7-70f4eb18f6d9.txn +0 -0
  75. scmcp_shared/vector_db/decoupler.lance/_transactions/9-3404dcf1-bb17-40e6-9e5d-d9942dff90b2.txn +0 -0
  76. scmcp_shared/vector_db/decoupler.lance/_versions/1.manifest +0 -0
  77. scmcp_shared/vector_db/decoupler.lance/_versions/10.manifest +0 -0
  78. scmcp_shared/vector_db/decoupler.lance/_versions/11.manifest +0 -0
  79. scmcp_shared/vector_db/decoupler.lance/_versions/12.manifest +0 -0
  80. scmcp_shared/vector_db/decoupler.lance/_versions/13.manifest +0 -0
  81. scmcp_shared/vector_db/decoupler.lance/_versions/14.manifest +0 -0
  82. scmcp_shared/vector_db/decoupler.lance/_versions/15.manifest +0 -0
  83. scmcp_shared/vector_db/decoupler.lance/_versions/16.manifest +0 -0
  84. scmcp_shared/vector_db/decoupler.lance/_versions/17.manifest +0 -0
  85. scmcp_shared/vector_db/decoupler.lance/_versions/18.manifest +0 -0
  86. scmcp_shared/vector_db/decoupler.lance/_versions/19.manifest +0 -0
  87. scmcp_shared/vector_db/decoupler.lance/_versions/2.manifest +0 -0
  88. scmcp_shared/vector_db/decoupler.lance/_versions/20.manifest +0 -0
  89. scmcp_shared/vector_db/decoupler.lance/_versions/21.manifest +0 -0
  90. scmcp_shared/vector_db/decoupler.lance/_versions/22.manifest +0 -0
  91. scmcp_shared/vector_db/decoupler.lance/_versions/23.manifest +0 -0
  92. scmcp_shared/vector_db/decoupler.lance/_versions/24.manifest +0 -0
  93. scmcp_shared/vector_db/decoupler.lance/_versions/25.manifest +0 -0
  94. scmcp_shared/vector_db/decoupler.lance/_versions/26.manifest +0 -0
  95. scmcp_shared/vector_db/decoupler.lance/_versions/27.manifest +0 -0
  96. scmcp_shared/vector_db/decoupler.lance/_versions/28.manifest +0 -0
  97. scmcp_shared/vector_db/decoupler.lance/_versions/29.manifest +0 -0
  98. scmcp_shared/vector_db/decoupler.lance/_versions/3.manifest +0 -0
  99. scmcp_shared/vector_db/decoupler.lance/_versions/30.manifest +0 -0
  100. scmcp_shared/vector_db/decoupler.lance/_versions/31.manifest +0 -0
  101. scmcp_shared/vector_db/decoupler.lance/_versions/32.manifest +0 -0
  102. scmcp_shared/vector_db/decoupler.lance/_versions/33.manifest +0 -0
  103. scmcp_shared/vector_db/decoupler.lance/_versions/34.manifest +0 -0
  104. scmcp_shared/vector_db/decoupler.lance/_versions/35.manifest +0 -0
  105. scmcp_shared/vector_db/decoupler.lance/_versions/36.manifest +0 -0
  106. scmcp_shared/vector_db/decoupler.lance/_versions/37.manifest +0 -0
  107. scmcp_shared/vector_db/decoupler.lance/_versions/38.manifest +0 -0
  108. scmcp_shared/vector_db/decoupler.lance/_versions/39.manifest +0 -0
  109. scmcp_shared/vector_db/decoupler.lance/_versions/4.manifest +0 -0
  110. scmcp_shared/vector_db/decoupler.lance/_versions/40.manifest +0 -0
  111. scmcp_shared/vector_db/decoupler.lance/_versions/41.manifest +0 -0
  112. scmcp_shared/vector_db/decoupler.lance/_versions/42.manifest +0 -0
  113. scmcp_shared/vector_db/decoupler.lance/_versions/43.manifest +0 -0
  114. scmcp_shared/vector_db/decoupler.lance/_versions/44.manifest +0 -0
  115. scmcp_shared/vector_db/decoupler.lance/_versions/45.manifest +0 -0
  116. scmcp_shared/vector_db/decoupler.lance/_versions/46.manifest +0 -0
  117. scmcp_shared/vector_db/decoupler.lance/_versions/5.manifest +0 -0
  118. scmcp_shared/vector_db/decoupler.lance/_versions/6.manifest +0 -0
  119. scmcp_shared/vector_db/decoupler.lance/_versions/7.manifest +0 -0
  120. scmcp_shared/vector_db/decoupler.lance/_versions/8.manifest +0 -0
  121. scmcp_shared/vector_db/decoupler.lance/_versions/9.manifest +0 -0
  122. scmcp_shared/vector_db/decoupler.lance/data/0cc94dc3-2ca3-403c-a9df-59753f24b3f2.lance +0 -0
  123. scmcp_shared/vector_db/decoupler.lance/data/254a1a71-cdd2-4cca-b7ec-a50540fed62c.lance +0 -0
  124. scmcp_shared/vector_db/decoupler.lance/data/2574d216-5f05-4794-9e1c-986fafde6ab4.lance +0 -0
  125. scmcp_shared/vector_db/decoupler.lance/data/26c7bbe7-5f97-4453-b065-123b764448b3.lance +0 -0
  126. scmcp_shared/vector_db/decoupler.lance/data/286595a6-88f6-4b05-861e-e4f607a6fcdb.lance +0 -0
  127. scmcp_shared/vector_db/decoupler.lance/data/33219b1a-7575-46ef-bb64-2bdbde1e692b.lance +0 -0
  128. scmcp_shared/vector_db/decoupler.lance/data/344ad7dd-98bb-41de-b347-2f17bf5735cb.lance +0 -0
  129. scmcp_shared/vector_db/decoupler.lance/data/395b1ecb-68fe-4dd3-a770-4b3ed393ae0c.lance +0 -0
  130. scmcp_shared/vector_db/decoupler.lance/data/3db97f4c-9c35-44b7-9042-82b4006c5a22.lance +0 -0
  131. scmcp_shared/vector_db/decoupler.lance/data/4540246e-b0bb-4f4d-8f98-60a64f1c42ed.lance +0 -0
  132. scmcp_shared/vector_db/decoupler.lance/data/4643dbc0-9e45-4b63-81e1-e06cf9bddcec.lance +0 -0
  133. scmcp_shared/vector_db/decoupler.lance/data/4f28eb52-d409-43f2-ae17-d1826f209006.lance +0 -0
  134. scmcp_shared/vector_db/decoupler.lance/data/4fda4a22-35f0-4897-b4c5-6cedefba66e6.lance +0 -0
  135. scmcp_shared/vector_db/decoupler.lance/data/51ee77b6-ab24-44c0-916e-b81ff3912731.lance +0 -0
  136. scmcp_shared/vector_db/decoupler.lance/data/539d15c9-e88b-400c-9ab7-08f5e8dca10d.lance +0 -0
  137. scmcp_shared/vector_db/decoupler.lance/data/54007132-91f5-4909-8678-c471ef4d100f.lance +0 -0
  138. scmcp_shared/vector_db/decoupler.lance/data/546d88ec-0d5c-42bb-bccc-3271f3f183a4.lance +0 -0
  139. scmcp_shared/vector_db/decoupler.lance/data/6912ad8a-343c-4ca1-b1b7-4300125e688e.lance +0 -0
  140. scmcp_shared/vector_db/decoupler.lance/data/6b72e4f7-3051-40a4-a492-6d9eff1c647d.lance +0 -0
  141. scmcp_shared/vector_db/decoupler.lance/data/6d7ee320-ae1c-4e49-8ce5-c85971b11ce6.lance +0 -0
  142. scmcp_shared/vector_db/decoupler.lance/data/6ea47b70-69d4-43e9-b2c6-442fe50e4dd1.lance +0 -0
  143. scmcp_shared/vector_db/decoupler.lance/data/72adb5ed-bf11-4d06-b146-0272d333db08.lance +0 -0
  144. scmcp_shared/vector_db/decoupler.lance/data/745907df-e261-4f4b-a757-2c01c058bf27.lance +0 -0
  145. scmcp_shared/vector_db/decoupler.lance/data/78988307-4c66-4ad7-b295-7463ecd53609.lance +0 -0
  146. scmcp_shared/vector_db/decoupler.lance/data/798ce305-6d60-4f28-b82a-e1f647907abf.lance +0 -0
  147. scmcp_shared/vector_db/decoupler.lance/data/7c159cce-2741-442b-9c63-f44bf2996718.lance +0 -0
  148. scmcp_shared/vector_db/decoupler.lance/data/7cd7a818-e68b-4fa8-bad3-23b60c386670.lance +0 -0
  149. scmcp_shared/vector_db/decoupler.lance/data/7ec553ed-0c7a-4bac-99b2-2ad976b40466.lance +0 -0
  150. scmcp_shared/vector_db/decoupler.lance/data/83efdc85-d990-4762-b69a-fb1c3938f60f.lance +0 -0
  151. scmcp_shared/vector_db/decoupler.lance/data/8c1613b3-8d69-49c5-bfd0-a021bb516faf.lance +0 -0
  152. scmcp_shared/vector_db/decoupler.lance/data/95cd1b22-1f93-4133-9841-de21549ad8c5.lance +0 -0
  153. scmcp_shared/vector_db/decoupler.lance/data/9a2ea5d4-087e-4d3a-b64b-6c568b8a0010.lance +0 -0
  154. scmcp_shared/vector_db/decoupler.lance/data/b1c47dc6-450a-4dca-b465-badb6a3619c2.lance +0 -0
  155. scmcp_shared/vector_db/decoupler.lance/data/b21d183a-c51d-463b-932e-9beb2e0da9aa.lance +0 -0
  156. scmcp_shared/vector_db/decoupler.lance/data/b2598625-8683-4c33-be40-6f1a7555dc2c.lance +0 -0
  157. scmcp_shared/vector_db/decoupler.lance/data/b7297b39-1fc5-4886-be21-708b369bef59.lance +0 -0
  158. scmcp_shared/vector_db/decoupler.lance/data/b7d90085-5bd6-48f9-8a73-17eb7cf556fa.lance +0 -0
  159. scmcp_shared/vector_db/decoupler.lance/data/b988ceee-57fc-423b-8e67-5729086c6946.lance +0 -0
  160. scmcp_shared/vector_db/decoupler.lance/data/bfd68ea6-ddf4-44bb-aa87-2669f0462f7d.lance +0 -0
  161. scmcp_shared/vector_db/decoupler.lance/data/cb8ac58e-0e59-4391-95ab-6195e71b9625.lance +0 -0
  162. scmcp_shared/vector_db/decoupler.lance/data/d0f10434-afb5-49c5-9e77-d39a4f8cca94.lance +0 -0
  163. scmcp_shared/vector_db/decoupler.lance/data/d3f89fec-5795-4e11-8c15-bc2206a7fae2.lance +0 -0
  164. scmcp_shared/vector_db/decoupler.lance/data/e063c8a4-5ef1-4933-a049-b41049d9be5f.lance +0 -0
  165. scmcp_shared/vector_db/decoupler.lance/data/e2348b24-f290-4fe2-a6c8-e98009ae4c1b.lance +0 -0
  166. scmcp_shared/vector_db/decoupler.lance/data/e5d3f893-6763-40dc-9d02-04e2f56a4883.lance +0 -0
  167. {scmcp_shared-0.3.7.dist-info → scmcp_shared-0.5.0.dist-info}/METADATA +3 -1
  168. scmcp_shared-0.5.0.dist-info/RECORD +171 -0
  169. scmcp_shared/server/base.py +0 -148
  170. scmcp_shared-0.3.7.dist-info/RECORD +0 -21
  171. {scmcp_shared-0.3.7.dist-info → scmcp_shared-0.5.0.dist-info}/WHEEL +0 -0
  172. {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 ..schema.pp import *
8
- from ..schema import AdataInfo
9
- from ..util import filter_args, add_op_log, forward_request, get_ads, generate_msg
10
- from .base import BaseMCP
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__(self, include_tools: list = None, exclude_tools: list = None, AdataInfo: AdataInfo = AdataInfo):
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(request: SubsetCellParams, adinfo: self.AdataInfo=self.AdataInfo()):
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(f"Key '{request.obs_key}' not found in adata.obs")
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(adata, "subset_cells",
63
+ add_op_log(
64
+ adata,
65
+ "subset_cells",
52
66
  {
53
- "obs_key": request.obs_key, "obs_value": request.obs_value,
54
- "obs_min": request.obs_min, "obs_max": request.obs_max
55
- }, adinfo
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, '__context__') and e.__context__:
79
+ if hasattr(e, "__context__") and e.__context__:
63
80
  raise ToolError(e.__context__)
64
81
  else:
65
82
  raise ToolError(e)
66
- return Tool.from_function(_subset_cells, name="subset_cells")
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(request: SubsetGeneParams, adinfo: self.AdataInfo=self.AdataInfo()):
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(f"Key '{request.var_key}' not found in adata.var")
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(adata, "subset_genes",
115
+ add_op_log(
116
+ adata,
117
+ "subset_genes",
96
118
  {
97
- "var_key": request.var_key, "var_min": request.var_min, "var_max": request.var_max,
98
- "hpv": request.highly_variable
99
- }, adinfo
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, '__context__') and e.__context__:
131
+ if hasattr(e, "__context__") and e.__context__:
107
132
  raise ToolError(e.__context__)
108
133
  else:
109
134
  raise ToolError(e)
110
- return Tool.from_function(_subset_genes, name="subset_genes")
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(request: CalculateQCMetrics, adinfo: self.AdataInfo=self.AdataInfo()):
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(f"Cound find {e} in adata.var")
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, '__context__') and e.__context__:
167
+ if hasattr(e, "__context__") and e.__context__:
134
168
  raise ToolError(e.__context__)
135
169
  else:
136
170
  raise ToolError(e)
137
- return Tool.from_function(_calculate_qc_metrics, name="calculate_qc_metrics")
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(request: Log1PParams=Log1PParams(), adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
200
+ if hasattr(e, "__context__") and e.__context__:
161
201
  raise ToolError(e.__context__)
162
202
  else:
163
203
  raise ToolError(e)
164
- return Tool.from_function(_log1p, name="log1p")
204
+
205
+ return Tool.from_function(_log1p, name="log1p", enabled=True)
165
206
 
166
207
  def _tool_normalize_total(self):
167
- def _normalize_total(request: NormalizeTotalParams, adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
226
+ if hasattr(e, "__context__") and e.__context__:
184
227
  raise ToolError(e.__context__)
185
228
  else:
186
229
  raise ToolError(e)
187
- return Tool.from_function(_normalize_total, name="normalize_total")
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(request: HighlyVariableGenesParams, adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
256
+ if hasattr(e, "__context__") and e.__context__:
209
257
  raise ToolError(e.__context__)
210
258
  else:
211
259
  raise ToolError(e)
212
- return Tool.from_function(_highly_variable_genes, name="highly_variable_genes")
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(request: RegressOutParams, adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
284
+ if hasattr(e, "__context__") and e.__context__:
232
285
  raise ToolError(e.__context__)
233
286
  else:
234
287
  raise ToolError(e)
235
- return Tool.from_function(_regress_out, name="regress_out")
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: ScaleParams, adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
310
+ if hasattr(e, "__context__") and e.__context__:
257
311
  raise ToolError(e.__context__)
258
312
  else:
259
313
  raise ToolError(e)
260
- return Tool.from_function(_scale, name="scale")
314
+
315
+ return Tool.from_function(_scale, name="scale", enabled=True)
261
316
 
262
317
  def _tool_combat(self):
263
- def _combat(request: CombatParams, adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
336
+ if hasattr(e, "__context__") and e.__context__:
282
337
  raise ToolError(e.__context__)
283
338
  else:
284
339
  raise ToolError(e)
285
- return Tool.from_function(_combat, name="combat")
340
+
341
+ return Tool.from_function(_combat, name="combat", enabled=True)
286
342
 
287
343
  def _tool_scrublet(self):
288
- def _scrublet(request: ScrubletParams, adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
361
+ if hasattr(e, "__context__") and e.__context__:
304
362
  raise ToolError(e.__context__)
305
363
  else:
306
364
  raise ToolError(e)
307
- return Tool.from_function(_scrublet, name="scrublet")
365
+
366
+ return Tool.from_function(_scrublet, name="scrublet", enabled=True)
308
367
 
309
368
  def _tool_neighbors(self):
310
- def _neighbors(request: NeighborsParams, adinfo: self.AdataInfo=self.AdataInfo()):
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, '__context__') and e.__context__:
386
+ if hasattr(e, "__context__") and e.__context__:
326
387
  raise ToolError(e.__context__)
327
388
  else:
328
389
  raise ToolError(e)
329
- return Tool.from_function(_neighbors, name="neighbors")
390
+
391
+ return Tool.from_function(_neighbors, name="neighbors", enabled=True)