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
scmcp_shared/schema/tl.py CHANGED
@@ -1,155 +1,146 @@
1
- from pydantic import Field, field_validator, ValidationInfo, BaseModel
2
- from typing import Optional, Union, List, Dict, Any, Tuple, Literal, Mapping
1
+ from pydantic import Field, field_validator, ValidationInfo, BaseModel
2
+ from typing import Optional, Union, List, Dict, Any, Literal
3
3
 
4
4
 
5
- class TSNEParams(BaseModel):
5
+ class TSNEParam(BaseModel):
6
6
  """Input schema for the t-SNE dimensionality reduction tool."""
7
+
8
+ adata: str = Field(..., description="The AnnData object variable name.")
7
9
  n_pcs: Optional[int] = Field(
8
10
  default=None,
9
11
  description="Number of PCs to use. If None, automatically determined.",
10
- ge=0
12
+ ge=0,
11
13
  )
12
14
  use_rep: Optional[str] = Field(
13
- default=None,
14
- description="Key for .obsm to use as representation."
15
+ default=None, description="Key for .obsm to use as representation."
15
16
  )
16
17
  perplexity: Optional[Union[float, int]] = Field(
17
18
  default=30,
18
19
  description="Related to number of nearest neighbors, typically between 5-50.",
19
- gt=0
20
+ gt=0,
20
21
  )
21
22
  early_exaggeration: Optional[Union[float, int]] = Field(
22
23
  default=12,
23
24
  description="Controls space between natural clusters in embedded space.",
24
- gt=0
25
+ gt=0,
25
26
  )
26
27
  learning_rate: Optional[Union[float, int]] = Field(
27
28
  default=1000,
28
29
  description="Learning rate for optimization, typically between 100-1000.",
29
- gt=0
30
+ gt=0,
30
31
  )
31
32
  use_fast_tsne: Optional[bool] = Field(
32
- default=False,
33
- description="Whether to use Multicore-tSNE implementation."
33
+ default=False, description="Whether to use Multicore-tSNE implementation."
34
34
  )
35
35
  n_jobs: Optional[int] = Field(
36
- default=None,
37
- description="Number of jobs for parallel computation.",
38
- gt=0
36
+ default=None, description="Number of jobs for parallel computation.", gt=0
39
37
  )
40
38
  metric: Optional[str] = Field(
41
- default='euclidean',
42
- description="Distance metric to use."
39
+ default="euclidean", description="Distance metric to use."
43
40
  )
44
-
45
- @field_validator('n_pcs', 'perplexity', 'early_exaggeration',
46
- 'learning_rate', 'n_jobs')
47
- def validate_positive_numbers(cls, v: Optional[Union[int, float]]) -> Optional[Union[int, float]]:
41
+
42
+ @field_validator(
43
+ "n_pcs", "perplexity", "early_exaggeration", "learning_rate", "n_jobs"
44
+ )
45
+ def validate_positive_numbers(
46
+ cls, v: Optional[Union[int, float]]
47
+ ) -> Optional[Union[int, float]]:
48
48
  """Validate positive numbers where applicable"""
49
49
  if v is not None and v <= 0:
50
50
  raise ValueError("must be a positive number")
51
51
  return v
52
-
53
- @field_validator('metric')
52
+
53
+ @field_validator("metric")
54
54
  def validate_metric(cls, v: str) -> str:
55
55
  """Validate distance metric is supported"""
56
- valid_metrics = ['euclidean', 'cosine', 'manhattan', 'l1', 'l2']
56
+ valid_metrics = ["euclidean", "cosine", "manhattan", "l1", "l2"]
57
57
  if v.lower() not in valid_metrics:
58
58
  raise ValueError(f"metric must be one of {valid_metrics}")
59
59
  return v.lower()
60
60
 
61
61
 
62
- class UMAPParams(BaseModel):
62
+ class UMAPParam(BaseModel):
63
63
  """Input schema for the UMAP dimensionality reduction tool."""
64
-
64
+
65
+ adata: str = Field(..., description="The AnnData object variable name.")
65
66
  min_dist: Optional[float] = Field(
66
- default=0.5,
67
- description="Minimum distance between embedded points.",
68
- gt=0
67
+ default=0.5, description="Minimum distance between embedded points.", gt=0
69
68
  )
70
-
71
69
  spread: Optional[float] = Field(
72
- default=1.0,
73
- description="Scale of embedded points.",
74
- gt=0
70
+ default=1.0, description="Scale of embedded points.", gt=0
75
71
  )
76
-
77
72
  n_components: Optional[int] = Field(
78
- default=2,
79
- description="Number of dimensions of the embedding.",
80
- gt=0
73
+ default=2, description="Number of dimensions of the embedding.", gt=0
81
74
  )
82
-
83
75
  maxiter: Optional[int] = Field(
84
76
  default=None,
85
77
  description="Number of iterations (epochs) of the optimization.",
86
- gt=0
78
+ gt=0,
87
79
  )
88
-
89
80
  alpha: Optional[float] = Field(
90
81
  default=1.0,
91
82
  description="Initial learning rate for the embedding optimization.",
92
- gt=0
83
+ gt=0,
93
84
  )
94
-
95
85
  gamma: Optional[float] = Field(
96
- default=1.0,
97
- description="Weighting applied to negative samples.",
98
- gt=0
86
+ default=1.0, description="Weighting applied to negative samples.", gt=0
99
87
  )
100
88
  negative_sample_rate: Optional[int] = Field(
101
- default=5,
102
- description="Number of negative samples per positive sample.",
103
- gt=0
89
+ default=5, description="Number of negative samples per positive sample.", gt=0
104
90
  )
105
91
  init_pos: Optional[str] = Field(
106
- default='spectral',
92
+ default="spectral",
107
93
  description="How to initialize the low dimensional embedding.",
108
94
  )
109
95
  random_state: Optional[int] = Field(
110
- default=0,
111
- description="Random seed for reproducibility."
96
+ default=0, description="Random seed for reproducibility."
112
97
  )
113
98
  a: Optional[float] = Field(
114
- default=None,
115
- description="Parameter controlling the embedding.",
116
- gt=0
99
+ default=None, description="Parameter controlling the embedding.", gt=0
117
100
  )
118
101
  b: Optional[float] = Field(
119
- default=None,
120
- description="Parameter controlling the embedding.",
121
- gt=0
102
+ default=None, description="Parameter controlling the embedding.", gt=0
122
103
  )
123
104
  method: Optional[str] = Field(
124
- default='umap',
125
- description="Implementation to use ('umap' or 'rapids')."
105
+ default="umap", description="Implementation to use ('umap' or 'rapids')."
126
106
  )
127
107
  neighbors_key: Optional[str] = Field(
128
- default=None,
129
- description="Key for neighbors settings in .uns."
130
- )
131
-
132
- @field_validator('min_dist', 'spread', 'n_components', 'maxiter',
133
- 'alpha', 'gamma', 'negative_sample_rate', 'a', 'b')
134
- def validate_positive_numbers(cls, v: Optional[Union[int, float]]) -> Optional[Union[int, float]]:
108
+ default=None, description="Key for neighbors settings in .uns."
109
+ )
110
+
111
+ @field_validator(
112
+ "min_dist",
113
+ "spread",
114
+ "n_components",
115
+ "maxiter",
116
+ "alpha",
117
+ "gamma",
118
+ "negative_sample_rate",
119
+ "a",
120
+ "b",
121
+ )
122
+ def validate_positive_numbers(
123
+ cls, v: Optional[Union[int, float]]
124
+ ) -> Optional[Union[int, float]]:
135
125
  """Validate positive numbers where applicable"""
136
126
  if v is not None and v <= 0:
137
127
  raise ValueError("must be a positive number")
138
128
  return v
139
-
140
- @field_validator('method')
129
+
130
+ @field_validator("method")
141
131
  def validate_method(cls, v: str) -> str:
142
132
  """Validate implementation method is supported"""
143
- if v.lower() not in ['umap', 'rapids']:
133
+ if v.lower() not in ["umap", "rapids"]:
144
134
  raise ValueError("method must be either 'umap' or 'rapids'")
145
135
  return v.lower()
146
136
 
147
137
 
148
- class DrawGraphParams(BaseModel):
138
+ class DrawGraphParam(BaseModel):
149
139
  """Input schema for the force-directed graph drawing tool."""
150
-
140
+
141
+ adata: str = Field(..., description="The AnnData object variable name.")
151
142
  layout: str = Field(
152
- default='fa',
143
+ default="fa",
153
144
  description="Graph layout algorithm ('fa', 'fr', 'kk', etc.)",
154
145
  )
155
146
  init_pos: Optional[Union[str, bool]] = Field(
@@ -157,41 +148,31 @@ class DrawGraphParams(BaseModel):
157
148
  description="Initial position for nodes ('paga'/True, False, or .obsm key)",
158
149
  )
159
150
  root: Optional[int] = Field(
160
- default=None,
161
- description="Root node for tree layouts",
162
- ge=0
163
- )
164
- random_state: int = Field(
165
- default=0,
166
- description="Random seed for reproducibility"
151
+ default=None, description="Root node for tree layouts", ge=0
167
152
  )
153
+ random_state: int = Field(default=0, description="Random seed for reproducibility")
168
154
  n_jobs: Optional[int] = Field(
169
- default=None,
170
- description="Number of jobs for parallel computation",
171
- gt=0
155
+ default=None, description="Number of jobs for parallel computation", gt=0
172
156
  )
173
157
  key_added_ext: Optional[str] = Field(
174
- default=None,
175
- description="Suffix for storing results in .obsm"
158
+ default=None, description="Suffix for storing results in .obsm"
176
159
  )
177
160
  neighbors_key: Optional[str] = Field(
178
- default=None,
179
- description="Key for neighbors settings in .uns"
161
+ default=None, description="Key for neighbors settings in .uns"
180
162
  )
181
163
  obsp: Optional[str] = Field(
182
- default=None,
183
- description="Key for adjacency matrix in .obsp"
164
+ default=None, description="Key for adjacency matrix in .obsp"
184
165
  )
185
-
186
- @field_validator('layout')
166
+
167
+ @field_validator("layout")
187
168
  def validate_layout(cls, v: str) -> str:
188
169
  """Validate layout is supported"""
189
- valid_layouts = ['fa', 'fr', 'grid_fr', 'kk', 'lgl', 'drl', 'rt']
170
+ valid_layouts = ["fa", "fr", "grid_fr", "kk", "lgl", "drl", "rt"]
190
171
  if v.lower() not in valid_layouts:
191
172
  raise ValueError(f"layout must be one of {valid_layouts}")
192
173
  return v.lower()
193
-
194
- @field_validator('root', 'n_jobs')
174
+
175
+ @field_validator("root", "n_jobs")
195
176
  def validate_positive_integers(cls, v: Optional[int]) -> Optional[int]:
196
177
  """Validate positive integers where applicable"""
197
178
  if v is not None and v <= 0:
@@ -199,13 +180,12 @@ class DrawGraphParams(BaseModel):
199
180
  return v
200
181
 
201
182
 
202
- class DiffMapParams(BaseModel):
183
+ class DiffMapParam(BaseModel):
203
184
  """Input schema for the Diffusion Maps dimensionality reduction tool."""
204
-
185
+
186
+ adata: str = Field(..., description="The AnnData object variable name.")
205
187
  n_comps: int = Field(
206
- default=15,
207
- description="The number of dimensions of the representation.",
208
- gt=0
188
+ default=15, description="The number of dimensions of the representation.", gt=0
209
189
  )
210
190
  neighbors_key: Optional[str] = Field(
211
191
  default=None,
@@ -214,14 +194,11 @@ class DiffMapParams(BaseModel):
214
194
  "and .obsp['connectivities'], .obsp['distances'] for connectivities and "
215
195
  "distances respectively. If specified, diffmap looks .uns[neighbors_key] for "
216
196
  "neighbors settings and uses the corresponding connectivities and distances."
217
- )
197
+ ),
218
198
  )
219
- random_state: int = Field(
220
- default=0,
221
- description="Random seed for reproducibility."
222
- )
223
-
224
- @field_validator('n_comps')
199
+ random_state: int = Field(default=0, description="Random seed for reproducibility.")
200
+
201
+ @field_validator("n_comps")
225
202
  def validate_positive_integers(cls, v: int) -> int:
226
203
  """Validate positive integers"""
227
204
  if v <= 0:
@@ -229,231 +206,227 @@ class DiffMapParams(BaseModel):
229
206
  return v
230
207
 
231
208
 
232
- class EmbeddingDensityParams(BaseModel):
209
+ class EmbeddingDensityParam(BaseModel):
233
210
  """Input schema for the embedding density calculation tool."""
234
-
211
+
212
+ adata: str = Field(..., description="The AnnData object variable name.")
235
213
  basis: str = Field(
236
- default='umap',
237
- description="The embedding over which the density will be calculated. This embedded representation should be found in `adata.obsm['X_[basis]']`."
214
+ default="umap",
215
+ description="The embedding over which the density will be calculated. This embedded representation should be found in `adata.obsm['X_[basis]']`.",
238
216
  )
239
217
  groupby: Optional[str] = Field(
240
218
  default=None,
241
- description="Key for categorical observation/cell annotation for which densities are calculated per category."
219
+ description="Key for categorical observation/cell annotation for which densities are calculated per category.",
242
220
  )
243
221
  key_added: Optional[str] = Field(
244
222
  default=None,
245
- description="Name of the `.obs` covariate that will be added with the density estimates."
223
+ description="Name of the `.obs` covariate that will be added with the density estimates.",
246
224
  )
247
225
  components: Optional[Union[str, List[str]]] = Field(
248
226
  default=None,
249
- description="The embedding dimensions over which the density should be calculated. This is limited to two components."
227
+ description="The embedding dimensions over which the density should be calculated. This is limited to two components.",
250
228
  )
251
-
252
- @field_validator('components')
253
- def validate_components(cls, v: Optional[Union[str, List[str]]]) -> Optional[Union[str, List[str]]]:
229
+
230
+ @field_validator("components")
231
+ def validate_components(
232
+ cls, v: Optional[Union[str, List[str]]]
233
+ ) -> Optional[Union[str, List[str]]]:
254
234
  """Validate that components are limited to two dimensions"""
255
235
  if v is not None and isinstance(v, list) and len(v) > 2:
256
236
  raise ValueError("components is limited to two dimensions")
257
237
  return v
258
238
 
259
239
 
260
- class LeidenParams(BaseModel):
240
+ class LeidenParam(BaseModel):
261
241
  """Input schema for the Leiden clustering algorithm."""
262
-
242
+
243
+ adata: str = Field(..., description="The AnnData object variable name.")
263
244
  resolution: Optional[float] = Field(
264
245
  default=1.0,
265
- description="A parameter value controlling the coarseness of the clustering. Higher values lead to more clusters."
246
+ description="A parameter value controlling the coarseness of the clustering. Higher values lead to more clusters.",
266
247
  )
267
-
268
248
  key_added: Optional[str] = Field(
269
- default='leiden',
270
- description="`adata.obs` key under which to add the cluster labels."
249
+ default="leiden",
250
+ description="`adata.obs` key under which to add the cluster labels.",
271
251
  )
272
-
273
252
  directed: Optional[bool] = Field(
274
253
  default=None,
275
- description="Whether to treat the graph as directed or undirected."
254
+ description="Whether to treat the graph as directed or undirected.",
276
255
  )
277
-
278
256
  use_weights: Optional[bool] = Field(
279
257
  default=True,
280
- description="If `True`, edge weights from the graph are used in the computation (placing more emphasis on stronger edges)."
258
+ description="If `True`, edge weights from the graph are used in the computation (placing more emphasis on stronger edges).",
281
259
  )
282
-
283
260
  n_iterations: Optional[int] = Field(
284
261
  default=-1,
285
- description="How many iterations of the Leiden clustering algorithm to perform. -1 runs until optimal clustering."
262
+ description="How many iterations of the Leiden clustering algorithm to perform. -1 runs until optimal clustering.",
286
263
  )
287
-
288
264
  neighbors_key: Optional[str] = Field(
289
265
  default=None,
290
- description="Use neighbors connectivities as adjacency. If specified, leiden looks .obsp[.uns[neighbors_key]['connectivities_key']] for connectivities."
266
+ description="Use neighbors connectivities as adjacency. If specified, leiden looks .obsp[.uns[neighbors_key]['connectivities_key']] for connectivities.",
291
267
  )
292
-
293
268
  obsp: Optional[str] = Field(
294
269
  default=None,
295
- description="Use .obsp[obsp] as adjacency. You can't specify both `obsp` and `neighbors_key` at the same time."
270
+ description="Use .obsp[obsp] as adjacency. You can't specify both `obsp` and `neighbors_key` at the same time.",
296
271
  )
297
-
298
- flavor: Optional[Literal['leidenalg', 'igraph']] = Field(
299
- default='igraph',
300
- description="Which package's implementation to use."
272
+ flavor: Optional[Literal["leidenalg", "igraph"]] = Field(
273
+ default="igraph", description="Which package's implementation to use."
301
274
  )
302
-
303
- @field_validator('resolution')
275
+
276
+ @field_validator("resolution")
304
277
  def validate_resolution(cls, v: float) -> float:
305
278
  """Validate resolution is positive"""
306
279
  if v <= 0:
307
280
  raise ValueError("resolution must be a positive number")
308
281
  return v
309
-
310
- @field_validator('obsp', 'neighbors_key')
311
- def validate_graph_source(cls, v: Optional[str], info: ValidationInfo) -> Optional[str]:
282
+
283
+ @field_validator("obsp", "neighbors_key")
284
+ def validate_graph_source(
285
+ cls, v: Optional[str], info: ValidationInfo
286
+ ) -> Optional[str]:
312
287
  """Validate that obsp and neighbors_key are not both specified"""
313
288
  values = info.data
314
- if v is not None and 'obsp' in values and 'neighbors_key' in values:
315
- if values['obsp'] is not None and values['neighbors_key'] is not None:
289
+ if v is not None and "obsp" in values and "neighbors_key" in values:
290
+ if values["obsp"] is not None and values["neighbors_key"] is not None:
316
291
  raise ValueError("Cannot specify both obsp and neighbors_key")
317
292
  return v
318
-
319
- @field_validator('flavor')
293
+
294
+ @field_validator("flavor")
320
295
  def validate_flavor(cls, v: str) -> str:
321
296
  """Validate flavor is supported"""
322
- if v not in ['leidenalg', 'igraph']:
297
+ if v not in ["leidenalg", "igraph"]:
323
298
  raise ValueError("flavor must be either 'leidenalg' or 'igraph'")
324
299
  return v
325
300
 
326
301
 
327
- class LouvainParams(BaseModel):
302
+ class LouvainParam(BaseModel):
328
303
  """Input schema for the Louvain clustering algorithm."""
329
-
304
+
305
+ adata: str = Field(..., description="The AnnData object variable name.")
330
306
  resolution: Optional[float] = Field(
331
307
  default=None,
332
- description="For the default flavor ('vtraag') or for 'RAPIDS', you can provide a resolution (higher resolution means finding more and smaller clusters), which defaults to 1.0."
308
+ description="For the default flavor ('vtraag') or for 'RAPIDS', you can provide a resolution (higher resolution means finding more and smaller clusters), which defaults to 1.0.",
333
309
  )
334
-
335
310
  random_state: int = Field(
336
- default=0,
337
- description="Change the initialization of the optimization."
311
+ default=0, description="Change the initialization of the optimization."
338
312
  )
339
-
340
313
  key_added: str = Field(
341
- default='louvain',
342
- description="Key under which to add the cluster labels."
314
+ default="louvain", description="Key under which to add the cluster labels."
343
315
  )
344
-
345
- flavor: Literal['vtraag', 'igraph', 'rapids'] = Field(
346
- default='vtraag',
347
- description="Package for computing the clustering: 'vtraag' (default, more powerful), 'igraph' (built-in method), or 'rapids' (GPU accelerated)."
316
+ flavor: Literal["vtraag", "igraph", "rapids"] = Field(
317
+ default="vtraag",
318
+ description="Package for computing the clustering: 'vtraag' (default, more powerful), 'igraph' (built-in method), or 'rapids' (GPU accelerated).",
348
319
  )
349
-
350
320
  directed: bool = Field(
351
- default=True,
352
- description="Interpret the adjacency matrix as directed graph."
321
+ default=True, description="Interpret the adjacency matrix as directed graph."
353
322
  )
354
-
355
- use_weights: bool = Field(
356
- default=False,
357
- description="Use weights from knn graph."
358
- )
359
-
323
+ use_weights: bool = Field(default=False, description="Use weights from knn graph.")
360
324
  partition_kwargs: Optional[Dict[str, Any]] = Field(
361
325
  default=None,
362
- description="Key word arguments to pass to partitioning, if 'vtraag' method is being used."
326
+ description="Key word arguments to pass to partitioning, if 'vtraag' method is being used.",
363
327
  )
364
-
365
328
  neighbors_key: Optional[str] = Field(
366
329
  default=None,
367
- description="Use neighbors connectivities as adjacency. If specified, louvain looks .obsp[.uns[neighbors_key]['connectivities_key']] for connectivities."
330
+ description="Use neighbors connectivities as adjacency. If specified, louvain looks .obsp[.uns[neighbors_key]['connectivities_key']] for connectivities.",
368
331
  )
369
-
370
332
  obsp: Optional[str] = Field(
371
333
  default=None,
372
- description="Use .obsp[obsp] as adjacency. You can't specify both `obsp` and `neighbors_key` at the same time."
334
+ description="Use .obsp[obsp] as adjacency. You can't specify both `obsp` and `neighbors_key` at the same time.",
373
335
  )
374
-
375
- @field_validator('resolution')
336
+
337
+ @field_validator("resolution")
376
338
  def validate_resolution(cls, v: Optional[float]) -> Optional[float]:
377
339
  """Validate resolution is positive if provided"""
378
340
  if v is not None and v <= 0:
379
341
  raise ValueError("resolution must be a positive number")
380
342
  return v
381
-
382
- @field_validator('obsp', 'neighbors_key')
383
- def validate_graph_source(cls, v: Optional[str], info: ValidationInfo) -> Optional[str]:
343
+
344
+ @field_validator("obsp", "neighbors_key")
345
+ def validate_graph_source(
346
+ cls, v: Optional[str], info: ValidationInfo
347
+ ) -> Optional[str]:
384
348
  """Validate that obsp and neighbors_key are not both specified"""
385
349
  values = info.data
386
- if v is not None and 'obsp' in values and 'neighbors_key' in values:
387
- if values['obsp'] is not None and values['neighbors_key'] is not None:
350
+ if v is not None and "obsp" in values and "neighbors_key" in values:
351
+ if values["obsp"] is not None and values["neighbors_key"] is not None:
388
352
  raise ValueError("Cannot specify both obsp and neighbors_key")
389
353
  return v
390
-
391
- @field_validator('flavor')
354
+
355
+ @field_validator("flavor")
392
356
  def validate_flavor(cls, v: str) -> str:
393
357
  """Validate flavor is supported"""
394
- if v not in ['vtraag', 'igraph', 'rapids']:
358
+ if v not in ["vtraag", "igraph", "rapids"]:
395
359
  raise ValueError("flavor must be one of 'vtraag', 'igraph', or 'rapids'")
396
360
  return v
397
361
 
398
362
 
399
- class DendrogramParams(BaseModel):
363
+ class DendrogramParam(BaseModel):
400
364
  """Input schema for the hierarchical clustering dendrogram tool."""
401
-
365
+
366
+ adata: str = Field(..., description="The AnnData object variable name.")
402
367
  groupby: str = Field(
403
368
  ..., # Required field
404
- description="The categorical observation annotation to use for grouping."
369
+ description="The categorical observation annotation to use for grouping.",
405
370
  )
406
371
  n_pcs: Optional[int] = Field(
407
372
  default=None,
408
373
  description="Use this many PCs. If n_pcs==0 use .X if use_rep is None.",
409
- ge=0
374
+ ge=0,
410
375
  )
411
376
  use_rep: Optional[str] = Field(
412
377
  default=None,
413
- description="Use the indicated representation. 'X' or any key for .obsm is valid."
378
+ description="Use the indicated representation. 'X' or any key for .obsm is valid.",
414
379
  )
415
380
  var_names: Optional[List[str]] = Field(
416
381
  default=None,
417
- description="List of var_names to use for computing the hierarchical clustering. If provided, use_rep and n_pcs are ignored."
382
+ description="List of var_names to use for computing the hierarchical clustering. If provided, use_rep and n_pcs are ignored.",
418
383
  )
419
384
  use_raw: Optional[bool] = Field(
420
385
  default=None,
421
- description="Only when var_names is not None. Use raw attribute of adata if present."
386
+ description="Only when var_names is not None. Use raw attribute of adata if present.",
422
387
  )
423
388
  cor_method: str = Field(
424
- default='pearson',
425
- description="Correlation method to use: 'pearson', 'kendall', or 'spearman'."
389
+ default="pearson",
390
+ description="Correlation method to use: 'pearson', 'kendall', or 'spearman'.",
426
391
  )
427
392
  linkage_method: str = Field(
428
- default='complete',
429
- description="Linkage method to use for hierarchical clustering."
393
+ default="complete",
394
+ description="Linkage method to use for hierarchical clustering.",
430
395
  )
431
396
  optimal_ordering: bool = Field(
432
397
  default=False,
433
- description="Reorders the linkage matrix so that the distance between successive leaves is minimal."
398
+ description="Reorders the linkage matrix so that the distance between successive leaves is minimal.",
434
399
  )
435
400
  key_added: Optional[str] = Field(
436
401
  default=None,
437
- description="By default, the dendrogram information is added to .uns[f'dendrogram_{groupby}']."
402
+ description="By default, the dendrogram information is added to .uns[f'dendrogram_{groupby}'].",
438
403
  )
439
-
440
- @field_validator('cor_method')
404
+
405
+ @field_validator("cor_method")
441
406
  def validate_cor_method(cls, v: str) -> str:
442
407
  """Validate correlation method is supported"""
443
- valid_methods = ['pearson', 'kendall', 'spearman']
408
+ valid_methods = ["pearson", "kendall", "spearman"]
444
409
  if v.lower() not in valid_methods:
445
410
  raise ValueError(f"cor_method must be one of {valid_methods}")
446
411
  return v.lower()
447
-
448
- @field_validator('linkage_method')
412
+
413
+ @field_validator("linkage_method")
449
414
  def validate_linkage_method(cls, v: str) -> str:
450
415
  """Validate linkage method is supported"""
451
- valid_methods = ['single', 'complete', 'average', 'weighted', 'centroid', 'median', 'ward']
416
+ valid_methods = [
417
+ "single",
418
+ "complete",
419
+ "average",
420
+ "weighted",
421
+ "centroid",
422
+ "median",
423
+ "ward",
424
+ ]
452
425
  if v.lower() not in valid_methods:
453
426
  raise ValueError(f"linkage_method must be one of {valid_methods}")
454
427
  return v.lower()
455
-
456
- @field_validator('n_pcs')
428
+
429
+ @field_validator("n_pcs")
457
430
  def validate_n_pcs(cls, v: Optional[int]) -> Optional[int]:
458
431
  """Validate n_pcs is non-negative"""
459
432
  if v is not None and v < 0:
@@ -461,207 +434,207 @@ class DendrogramParams(BaseModel):
461
434
  return v
462
435
 
463
436
 
464
- class DPTParams(BaseModel):
437
+ class DPTParam(BaseModel):
465
438
  """Input schema for the Diffusion Pseudotime (DPT) tool."""
466
-
439
+
440
+ adata: str = Field(..., description="The AnnData object variable name.")
467
441
  n_dcs: int = Field(
468
- default=10,
469
- description="The number of diffusion components to use.",
470
- gt=0
442
+ default=10, description="The number of diffusion components to use.", gt=0
471
443
  )
472
444
  n_branchings: int = Field(
473
- default=0,
474
- description="Number of branchings to detect.",
475
- ge=0
445
+ default=0, description="Number of branchings to detect.", ge=0
476
446
  )
477
447
  min_group_size: float = Field(
478
448
  default=0.01,
479
449
  description="During recursive splitting of branches, do not consider groups that contain less than min_group_size data points. If a float, refers to a fraction of the total number of data points.",
480
450
  gt=0,
481
- le=1.0
451
+ le=1.0,
482
452
  )
483
453
  allow_kendall_tau_shift: bool = Field(
484
454
  default=True,
485
- description="If a very small branch is detected upon splitting, shift away from maximum correlation in Kendall tau criterion to stabilize the splitting."
455
+ description="If a very small branch is detected upon splitting, shift away from maximum correlation in Kendall tau criterion to stabilize the splitting.",
486
456
  )
487
457
  neighbors_key: Optional[str] = Field(
488
458
  default=None,
489
- description="If specified, dpt looks .uns[neighbors_key] for neighbors settings and uses the corresponding connectivities and distances."
459
+ description="If specified, dpt looks .uns[neighbors_key] for neighbors settings and uses the corresponding connectivities and distances.",
490
460
  )
491
-
492
- @field_validator('n_dcs')
461
+
462
+ @field_validator("n_dcs")
493
463
  def validate_n_dcs(cls, v: int) -> int:
494
464
  """Validate n_dcs is positive"""
495
465
  if v <= 0:
496
466
  raise ValueError("n_dcs must be a positive integer")
497
467
  return v
498
-
499
- @field_validator('n_branchings')
468
+
469
+ @field_validator("n_branchings")
500
470
  def validate_n_branchings(cls, v: int) -> int:
501
471
  """Validate n_branchings is non-negative"""
502
472
  if v < 0:
503
473
  raise ValueError("n_branchings must be a non-negative integer")
504
474
  return v
505
-
506
- @field_validator('min_group_size')
475
+
476
+ @field_validator("min_group_size")
507
477
  def validate_min_group_size(cls, v: float) -> float:
508
478
  """Validate min_group_size is between 0 and 1"""
509
479
  if v <= 0 or v > 1:
510
480
  raise ValueError("min_group_size must be between 0 and 1")
511
481
  return v
512
482
 
513
- class PAGAParams(BaseModel):
483
+
484
+ class PAGAParam(BaseModel):
514
485
  """Input schema for the Partition-based Graph Abstraction (PAGA) tool."""
515
-
486
+
487
+ adata: str = Field(..., description="The AnnData object variable name.")
516
488
  groups: Optional[str] = Field(
517
489
  default=None,
518
- description="Key for categorical in adata.obs. You can pass your predefined groups by choosing any categorical annotation of observations. Default: The first present key of 'leiden' or 'louvain'."
490
+ description="Key for categorical in adata.obs. You can pass your predefined groups by choosing any categorical annotation of observations. Default: The first present key of 'leiden' or 'louvain'.",
519
491
  )
520
492
  use_rna_velocity: bool = Field(
521
493
  default=False,
522
- description="Use RNA velocity to orient edges in the abstracted graph and estimate transitions. Requires that adata.uns contains a directed single-cell graph with key ['velocity_graph']."
494
+ description="Use RNA velocity to orient edges in the abstracted graph and estimate transitions. Requires that adata.uns contains a directed single-cell graph with key ['velocity_graph'].",
523
495
  )
524
- model: Literal['v1.2', 'v1.0'] = Field(
525
- default='v1.2',
526
- description="The PAGA connectivity model."
496
+ model: Literal["v1.2", "v1.0"] = Field(
497
+ default="v1.2", description="The PAGA connectivity model."
527
498
  )
528
499
  neighbors_key: Optional[str] = Field(
529
500
  default=None,
530
- description="If specified, paga looks .uns[neighbors_key] for neighbors settings and uses the corresponding connectivities and distances."
501
+ description="If specified, paga looks .uns[neighbors_key] for neighbors settings and uses the corresponding connectivities and distances.",
531
502
  )
532
-
533
- @field_validator('model')
534
- def validate_Params(cls, v: str) -> str:
503
+
504
+ @field_validator("model")
505
+ def validate_Param(cls, v: str) -> str:
535
506
  """Validate model version is supported"""
536
- if v not in ['v1.2', 'v1.0']:
507
+ if v not in ["v1.2", "v1.0"]:
537
508
  raise ValueError("model must be either 'v1.2' or 'v1.0'")
538
509
  return v
539
510
 
540
511
 
541
- class IngestParams(BaseModel):
512
+ class IngestParam(BaseModel):
542
513
  """Input schema for the ingest tool that maps labels and embeddings from reference data to new data."""
543
-
514
+
515
+ adata: str = Field(..., description="The AnnData object variable name.")
516
+ adata_ref: str = Field(
517
+ ..., description="The reference AnnData object variable name."
518
+ )
544
519
  obs: Optional[Union[str, List[str]]] = Field(
545
520
  default=None,
546
- description="Labels' keys in adata_ref.obs which need to be mapped to adata.obs (inferred for observation of adata)."
521
+ description="Labels' keys in adata_ref.obs which need to be mapped to adata.obs (inferred for observation of adata).",
547
522
  )
548
-
549
523
  embedding_method: Union[str, List[str]] = Field(
550
- default=['umap', 'pca'],
551
- description="Embeddings in adata_ref which need to be mapped to adata. The only supported values are 'umap' and 'pca'."
524
+ default=["umap", "pca"],
525
+ description="Embeddings in adata_ref which need to be mapped to adata. The only supported values are 'umap' and 'pca'.",
552
526
  )
553
-
554
527
  labeling_method: str = Field(
555
- default='knn',
556
- description="The method to map labels in adata_ref.obs to adata.obs. The only supported value is 'knn'."
528
+ default="knn",
529
+ description="The method to map labels in adata_ref.obs to adata.obs. The only supported value is 'knn'.",
557
530
  )
558
-
559
531
  neighbors_key: Optional[str] = Field(
560
532
  default=None,
561
- description="If specified, ingest looks adata_ref.uns[neighbors_key] for neighbors settings and uses the corresponding distances."
533
+ description="If specified, ingest looks adata_ref.uns[neighbors_key] for neighbors settings and uses the corresponding distances.",
562
534
  )
563
-
564
- @field_validator('embedding_method')
565
- def validate_embedding_method(cls, v: Union[str, List[str]]) -> Union[str, List[str]]:
535
+
536
+ @field_validator("embedding_method")
537
+ def validate_embedding_method(
538
+ cls, v: Union[str, List[str]]
539
+ ) -> Union[str, List[str]]:
566
540
  """Validate embedding method is supported"""
567
- valid_methods = ['umap', 'pca']
568
-
541
+ valid_methods = ["umap", "pca"]
542
+
569
543
  if isinstance(v, str):
570
544
  if v.lower() not in valid_methods:
571
545
  raise ValueError(f"embedding_method must be one of {valid_methods}")
572
546
  return v.lower()
573
-
547
+
574
548
  elif isinstance(v, list):
575
549
  for method in v:
576
550
  if method.lower() not in valid_methods:
577
- raise ValueError(f"embedding_method must contain only values from {valid_methods}")
551
+ raise ValueError(
552
+ f"embedding_method must contain only values from {valid_methods}"
553
+ )
578
554
  return [method.lower() for method in v]
579
-
555
+
580
556
  return v
581
-
582
- @field_validator('labeling_method')
557
+
558
+ @field_validator("labeling_method")
583
559
  def validate_labeling_method(cls, v: str) -> str:
584
560
  """Validate labeling method is supported"""
585
- if v.lower() != 'knn':
561
+ if v.lower() != "knn":
586
562
  raise ValueError("labeling_method must be 'knn'")
587
563
  return v.lower()
588
564
 
589
565
 
590
- class RankGenesGroupsParams(BaseModel):
566
+ class RankGenesGroupsParam(BaseModel):
591
567
  """Input schema for the rank_genes_groups tool."""
592
-
568
+
569
+ adata: str = Field(..., description="The AnnData object variable name.")
593
570
  groupby: str = Field(
594
571
  ..., # Required field
595
- description="The key of the observations grouping to consider."
572
+ description="The key of the observations grouping to consider.",
596
573
  )
597
574
  mask_var: Optional[Union[str, List[bool]]] = Field(
598
- default=None,
599
- description="Select subset of genes to use in statistical tests."
575
+ default=None, description="Select subset of genes to use in statistical tests."
600
576
  )
601
577
  use_raw: Optional[bool] = Field(
602
- default=None,
603
- description="Use raw attribute of adata if present."
578
+ default=None, description="Use raw attribute of adata if present."
604
579
  )
605
- groups: Union[Literal['all'], List[str]] = Field(
606
- default='all',
607
- description="Subset of groups to which comparison shall be restricted, or 'all' for all groups."
580
+ groups: Union[Literal["all"], List[str]] = Field(
581
+ default="all",
582
+ description="Subset of groups to which comparison shall be restricted, or 'all' for all groups.",
608
583
  )
609
584
  reference: str = Field(
610
- default='rest',
611
- description="If 'rest', compare each group to the union of the rest of the group. If a group identifier, compare with respect to this group."
585
+ default="rest",
586
+ description="If 'rest', compare each group to the union of the rest of the group. If a group identifier, compare with respect to this group.",
612
587
  )
613
588
  n_genes: Optional[int] = Field(
614
589
  default=None,
615
590
  description="The number of genes that appear in the returned tables. Defaults to all genes.",
616
- gt=0
591
+ gt=0,
617
592
  )
618
593
  rankby_abs: bool = Field(
619
594
  default=False,
620
- description="Rank genes by the absolute value of the score, not by the score."
595
+ description="Rank genes by the absolute value of the score, not by the score.",
621
596
  )
622
597
  pts: bool = Field(
623
- default=False,
624
- description="Compute the fraction of cells expressing the genes."
598
+ default=False, description="Compute the fraction of cells expressing the genes."
625
599
  )
626
600
  key_added: Optional[str] = Field(
627
- default=None,
628
- description="The key in adata.uns information is saved to."
601
+ default=None, description="The key in adata.uns information is saved to."
629
602
  )
630
603
  method: Optional[str] = Field(
631
604
  default=None,
632
- description="Method for differential expression analysis. Default is 't-test'."
605
+ description="Method for differential expression analysis. Default is 't-test'.",
633
606
  )
634
607
  corr_method: str = Field(
635
- default='benjamini-hochberg',
636
- description="p-value correction method. Used only for 't-test', 't-test_overestim_var', and 'wilcoxon'."
608
+ default="benjamini-hochberg",
609
+ description="p-value correction method. Used only for 't-test', 't-test_overestim_var', and 'wilcoxon'.",
637
610
  )
638
611
  tie_correct: bool = Field(
639
612
  default=False,
640
- description="Use tie correction for 'wilcoxon' scores. Used only for 'wilcoxon'."
613
+ description="Use tie correction for 'wilcoxon' scores. Used only for 'wilcoxon'.",
641
614
  )
642
615
  layer: Optional[str] = Field(
643
616
  default=None,
644
- description="Key from adata.layers whose value will be used to perform tests on."
617
+ description="Key from adata.layers whose value will be used to perform tests on.",
645
618
  )
646
-
647
- @field_validator('method')
619
+
620
+ @field_validator("method")
648
621
  def validate_method(cls, v: Optional[str]) -> Optional[str]:
649
622
  """Validate method is supported"""
650
623
  if v is not None:
651
- valid_methods = ['t-test', 't-test_overestim_var', 'wilcoxon', 'logreg']
624
+ valid_methods = ["t-test", "t-test_overestim_var", "wilcoxon", "logreg"]
652
625
  if v not in valid_methods:
653
626
  raise ValueError(f"method must be one of {valid_methods}")
654
627
  return v
655
-
656
- @field_validator('corr_method')
628
+
629
+ @field_validator("corr_method")
657
630
  def validate_corr_method(cls, v: str) -> str:
658
631
  """Validate correction method is supported"""
659
- valid_methods = ['benjamini-hochberg', 'bonferroni']
632
+ valid_methods = ["benjamini-hochberg", "bonferroni"]
660
633
  if v not in valid_methods:
661
634
  raise ValueError(f"corr_method must be one of {valid_methods}")
662
635
  return v
663
-
664
- @field_validator('n_genes')
636
+
637
+ @field_validator("n_genes")
665
638
  def validate_n_genes(cls, v: Optional[int]) -> Optional[int]:
666
639
  """Validate n_genes is positive"""
667
640
  if v is not None and v <= 0:
@@ -669,62 +642,54 @@ class RankGenesGroupsParams(BaseModel):
669
642
  return v
670
643
 
671
644
 
672
- class FilterRankGenesGroupsParams(BaseModel):
645
+ class FilterRankGenesGroupsParam(BaseModel):
673
646
  """Input schema for filtering ranked genes groups."""
674
-
647
+
648
+ adata: str = Field(..., description="The AnnData object variable name.")
675
649
  key: Optional[str] = Field(
676
650
  default=None,
677
- description="Key from adata.uns where rank_genes_groups output is stored."
651
+ description="Key from adata.uns where rank_genes_groups output is stored.",
678
652
  )
679
-
680
653
  groupby: Optional[str] = Field(
681
- default=None,
682
- description="The key of the observations grouping to consider."
654
+ default=None, description="The key of the observations grouping to consider."
683
655
  )
684
-
685
656
  use_raw: Optional[bool] = Field(
686
- default=None,
687
- description="Use raw attribute of adata if present."
657
+ default=None, description="Use raw attribute of adata if present."
688
658
  )
689
-
690
659
  key_added: str = Field(
691
- default='rank_genes_groups_filtered',
692
- description="The key in adata.uns information is saved to."
660
+ default="rank_genes_groups_filtered",
661
+ description="The key in adata.uns information is saved to.",
693
662
  )
694
-
695
663
  min_in_group_fraction: float = Field(
696
664
  default=0.25,
697
665
  description="Minimum fraction of cells expressing the gene within the group.",
698
666
  ge=0.0,
699
- le=1.0
667
+ le=1.0,
700
668
  )
701
-
702
669
  min_fold_change: Union[int, float] = Field(
703
670
  default=1,
704
671
  description="Minimum fold change for a gene to be considered significant.",
705
- gt=0
672
+ gt=0,
706
673
  )
707
-
708
674
  max_out_group_fraction: float = Field(
709
675
  default=0.5,
710
676
  description="Maximum fraction of cells expressing the gene outside the group.",
711
677
  ge=0.0,
712
- le=1.0
678
+ le=1.0,
713
679
  )
714
-
715
680
  compare_abs: bool = Field(
716
681
  default=False,
717
- description="If True, compare absolute values of log fold change with min_fold_change."
682
+ description="If True, compare absolute values of log fold change with min_fold_change.",
718
683
  )
719
-
720
- @field_validator('min_in_group_fraction', 'max_out_group_fraction')
684
+
685
+ @field_validator("min_in_group_fraction", "max_out_group_fraction")
721
686
  def validate_fractions(cls, v: float) -> float:
722
687
  """Validate fractions are between 0 and 1"""
723
688
  if v < 0 or v > 1:
724
689
  raise ValueError("Fraction values must be between 0 and 1")
725
690
  return v
726
-
727
- @field_validator('min_fold_change')
691
+
692
+ @field_validator("min_fold_change")
728
693
  def validate_fold_change(cls, v: Union[int, float]) -> Union[int, float]:
729
694
  """Validate min_fold_change is positive"""
730
695
  if v <= 0:
@@ -732,70 +697,73 @@ class FilterRankGenesGroupsParams(BaseModel):
732
697
  return v
733
698
 
734
699
 
735
- class MarkerGeneOverlapParams(BaseModel):
700
+ class MarkerGeneOverlapParam(BaseModel):
736
701
  """Input schema for the marker gene overlap tool."""
737
-
702
+
703
+ adata: str = Field(..., description="The AnnData object variable name.")
704
+ adata_ref: str = Field(
705
+ ..., description="The reference AnnData object variable name."
706
+ )
738
707
  key: str = Field(
739
- default='rank_genes_groups',
740
- description="The key in adata.uns where the rank_genes_groups output is stored."
708
+ default="rank_genes_groups",
709
+ description="The key in adata.uns where the rank_genes_groups output is stored.",
741
710
  )
742
-
743
711
  method: str = Field(
744
- default='overlap_count',
745
- description="Method to calculate marker gene overlap: 'overlap_count', 'overlap_coef', or 'jaccard'."
712
+ default="overlap_count",
713
+ description="Method to calculate marker gene overlap: 'overlap_count', 'overlap_coef', or 'jaccard'.",
746
714
  )
747
-
748
- normalize: Optional[Literal['reference', 'data']] = Field(
715
+ normalize: Optional[Literal["reference", "data"]] = Field(
749
716
  default=None,
750
- description="Normalization option for the marker gene overlap output. Only applicable when method is 'overlap_count'."
717
+ description="Normalization option for the marker gene overlap output. Only applicable when method is 'overlap_count'.",
751
718
  )
752
-
753
719
  top_n_markers: Optional[int] = Field(
754
720
  default=None,
755
721
  description="The number of top data-derived marker genes to use. By default the top 100 marker genes are used.",
756
- gt=0
722
+ gt=0,
757
723
  )
758
-
759
724
  adj_pval_threshold: Optional[float] = Field(
760
725
  default=None,
761
726
  description="A significance threshold on the adjusted p-values to select marker genes.",
762
727
  gt=0,
763
- le=1.0
728
+ le=1.0,
764
729
  )
765
-
766
730
  key_added: str = Field(
767
- default='marker_gene_overlap',
768
- description="Name of the .uns field that will contain the marker overlap scores."
731
+ default="marker_gene_overlap",
732
+ description="Name of the .uns field that will contain the marker overlap scores.",
769
733
  )
770
-
771
- @field_validator('method')
734
+
735
+ @field_validator("method")
772
736
  def validate_method(cls, v: str) -> str:
773
737
  """Validate method is supported"""
774
- valid_methods = ['overlap_count', 'overlap_coef', 'jaccard']
738
+ valid_methods = ["overlap_count", "overlap_coef", "jaccard"]
775
739
  if v not in valid_methods:
776
740
  raise ValueError(f"method must be one of {valid_methods}")
777
741
  return v
778
-
779
- @field_validator('normalize')
780
- def validate_normalize(cls, v: Optional[str], info: ValidationInfo) -> Optional[str]:
742
+
743
+ @field_validator("normalize")
744
+ def validate_normalize(
745
+ cls, v: Optional[str], info: ValidationInfo
746
+ ) -> Optional[str]:
781
747
  """Validate normalize is only used with overlap_count method"""
782
748
  if v is not None:
783
- if v not in ['reference', 'data']:
749
+ if v not in ["reference", "data"]:
784
750
  raise ValueError("normalize must be either 'reference' or 'data'")
785
-
751
+
786
752
  values = info.data
787
- if 'method' in values and values['method'] != 'overlap_count':
788
- raise ValueError("normalize can only be used when method is 'overlap_count'")
753
+ if "method" in values and values["method"] != "overlap_count":
754
+ raise ValueError(
755
+ "normalize can only be used when method is 'overlap_count'"
756
+ )
789
757
  return v
790
-
791
- @field_validator('top_n_markers')
758
+
759
+ @field_validator("top_n_markers")
792
760
  def validate_top_n_markers(cls, v: Optional[int]) -> Optional[int]:
793
761
  """Validate top_n_markers is positive"""
794
762
  if v is not None and v <= 0:
795
763
  raise ValueError("top_n_markers must be a positive integer")
796
764
  return v
797
-
798
- @field_validator('adj_pval_threshold')
765
+
766
+ @field_validator("adj_pval_threshold")
799
767
  def validate_adj_pval_threshold(cls, v: Optional[float]) -> Optional[float]:
800
768
  """Validate adj_pval_threshold is between 0 and 1"""
801
769
  if v is not None and (v <= 0 or v > 1):
@@ -803,42 +771,33 @@ class MarkerGeneOverlapParams(BaseModel):
803
771
  return v
804
772
 
805
773
 
806
- class ScoreGenesParams(BaseModel):
774
+ class ScoreGenesParam(BaseModel):
807
775
  """Input schema for the score_genes tool that calculates gene scores based on average expression."""
808
-
776
+
777
+ adata: str = Field(..., description="The AnnData object variable name.")
778
+ gene_list: List[str] = Field(..., description="List of genes to score.")
809
779
  ctrl_size: int = Field(
810
780
  default=50,
811
781
  description="Number of reference genes to be sampled from each bin.",
812
- gt=0
782
+ gt=0,
813
783
  )
814
-
815
784
  gene_pool: Optional[List[str]] = Field(
816
785
  default=None,
817
- description="Genes for sampling the reference set. Default is all genes."
786
+ description="Genes for sampling the reference set. Default is all genes.",
818
787
  )
819
-
820
788
  n_bins: int = Field(
821
- default=25,
822
- description="Number of expression level bins for sampling.",
823
- gt=0
789
+ default=25, description="Number of expression level bins for sampling.", gt=0
824
790
  )
825
-
826
791
  score_name: str = Field(
827
- default='score',
828
- description="Name of the field to be added in .obs."
829
- )
830
-
831
- random_state: int = Field(
832
- default=0,
833
- description="The random seed for sampling."
792
+ default="score", description="Name of the field to be added in .obs."
834
793
  )
835
-
794
+ random_state: int = Field(default=0, description="The random seed for sampling.")
836
795
  use_raw: Optional[bool] = Field(
837
796
  default=None,
838
- description="Whether to use raw attribute of adata. Defaults to True if .raw is present."
797
+ description="Whether to use raw attribute of adata. Defaults to True if .raw is present.",
839
798
  )
840
-
841
- @field_validator('ctrl_size', 'n_bins')
799
+
800
+ @field_validator("ctrl_size", "n_bins")
842
801
  def validate_positive_integers(cls, v: int) -> int:
843
802
  """Validate positive integers"""
844
803
  if v <= 0:
@@ -846,47 +805,43 @@ class ScoreGenesParams(BaseModel):
846
805
  return v
847
806
 
848
807
 
849
- class ScoreGenesCellCycleParams(BaseModel):
808
+ class ScoreGenesCellCycleParam(BaseModel):
850
809
  """Input schema for the score_genes_cell_cycle tool that scores cell cycle genes."""
851
-
810
+
811
+ adata: str = Field(..., description="The AnnData object variable name.")
852
812
  s_genes: List[str] = Field(
853
813
  ..., # Required field
854
- description="List of genes associated with S phase."
814
+ description="List of genes associated with S phase.",
855
815
  )
856
816
  g2m_genes: List[str] = Field(
857
817
  ..., # Required field
858
- description="List of genes associated with G2M phase."
818
+ description="List of genes associated with G2M phase.",
859
819
  )
860
820
  gene_pool: Optional[List[str]] = Field(
861
821
  default=None,
862
- description="Genes for sampling the reference set. Default is all genes."
822
+ description="Genes for sampling the reference set. Default is all genes.",
863
823
  )
864
824
  n_bins: int = Field(
865
- default=25,
866
- description="Number of expression level bins for sampling.",
867
- gt=0
825
+ default=25, description="Number of expression level bins for sampling.", gt=0
868
826
  )
869
827
  score_name: Optional[str] = Field(
870
828
  default=None,
871
- description="Name of the field to be added in .obs. If None, the scores are added as 'S_score' and 'G2M_score'."
872
- )
873
- random_state: int = Field(
874
- default=0,
875
- description="The random seed for sampling."
829
+ description="Name of the field to be added in .obs. If None, the scores are added as 'S_score' and 'G2M_score'.",
876
830
  )
831
+ random_state: int = Field(default=0, description="The random seed for sampling.")
877
832
  use_raw: Optional[bool] = Field(
878
833
  default=None,
879
- description="Whether to use raw attribute of adata. Defaults to True if .raw is present."
834
+ description="Whether to use raw attribute of adata. Defaults to True if .raw is present.",
880
835
  )
881
-
882
- @field_validator('s_genes', 'g2m_genes')
836
+
837
+ @field_validator("s_genes", "g2m_genes")
883
838
  def validate_gene_lists(cls, v: List[str]) -> List[str]:
884
839
  """Validate gene lists are not empty"""
885
840
  if len(v) == 0:
886
841
  raise ValueError("Gene list cannot be empty")
887
842
  return v
888
-
889
- @field_validator('n_bins')
843
+
844
+ @field_validator("n_bins")
890
845
  def validate_positive_integers(cls, v: int) -> int:
891
846
  """Validate positive integers"""
892
847
  if v <= 0:
@@ -894,59 +849,52 @@ class ScoreGenesCellCycleParams(BaseModel):
894
849
  return v
895
850
 
896
851
 
897
-
898
-
899
- class PCAParams(BaseModel):
852
+ class PCAParam(BaseModel):
900
853
  """Input schema for the PCA preprocessing tool."""
901
-
854
+
855
+ adata: str = Field(..., description="The AnnData object variable name.")
902
856
  n_comps: Optional[int] = Field(
903
857
  default=None,
904
858
  description="Number of principal components to compute. Defaults to 50 or 1 - minimum dimension size.",
905
- gt=0
859
+ gt=0,
906
860
  )
907
-
861
+
908
862
  layer: Optional[str] = Field(
909
- default=None,
910
- description="If provided, which element of layers to use for PCA."
863
+ default=None, description="If provided, which element of layers to use for PCA."
911
864
  )
912
-
865
+
913
866
  zero_center: Optional[bool] = Field(
914
867
  default=True,
915
- description="If True, compute standard PCA from covariance matrix."
868
+ description="If True, compute standard PCA from covariance matrix.",
916
869
  )
917
-
918
- svd_solver: Optional[Literal["arpack", "randomized", "auto", "lobpcg", "tsqr"]] = Field(
919
- default=None,
920
- description="SVD solver to use."
870
+
871
+ svd_solver: Optional[Literal["arpack", "randomized", "auto", "lobpcg", "tsqr"]] = (
872
+ Field(default=None, description="SVD solver to use.")
921
873
  )
922
874
  mask_var: Optional[Union[str, bool]] = Field(
923
875
  default=None,
924
- description="Boolean mask or string referring to var column for subsetting genes."
876
+ description="Boolean mask or string referring to var column for subsetting genes.",
877
+ )
878
+ dtype: str = Field(
879
+ default="float32", description="Numpy data type string for the result."
925
880
  )
926
- # dtype: str = Field(
927
- # default="float32",
928
- # description="Numpy data type string for the result."
929
- # )
930
881
  chunked: bool = Field(
931
- default=False,
932
- description="If True, perform an incremental PCA on segments."
882
+ default=False, description="If True, perform an incremental PCA on segments."
933
883
  )
934
-
884
+
935
885
  chunk_size: Optional[int] = Field(
936
886
  default=None,
937
887
  description="Number of observations to include in each chunk.",
938
- gt=0
888
+ gt=0,
939
889
  )
940
-
890
+
941
891
  key_added: str = Field(
942
- default="X_pca",
943
- description="PCA embedding stored key in adata.obsm."
892
+ default="X_pca", description="PCA embedding stored key in adata.obsm."
944
893
  )
945
-
946
- @field_validator('n_comps', 'chunk_size')
894
+
895
+ @field_validator("n_comps", "chunk_size")
947
896
  def validate_positive_integers(cls, v: Optional[int]) -> Optional[int]:
948
897
  """Validate positive integers"""
949
898
  if v is not None and v <= 0:
950
899
  raise ValueError("must be a positive integer")
951
900
  return v
952
-