spatialcore 0.1.9__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 (36) hide show
  1. spatialcore/__init__.py +122 -0
  2. spatialcore/annotation/__init__.py +253 -0
  3. spatialcore/annotation/acquisition.py +529 -0
  4. spatialcore/annotation/annotate.py +603 -0
  5. spatialcore/annotation/cellxgene.py +365 -0
  6. spatialcore/annotation/confidence.py +802 -0
  7. spatialcore/annotation/discovery.py +529 -0
  8. spatialcore/annotation/expression.py +363 -0
  9. spatialcore/annotation/loading.py +529 -0
  10. spatialcore/annotation/markers.py +297 -0
  11. spatialcore/annotation/ontology.py +1282 -0
  12. spatialcore/annotation/patterns.py +247 -0
  13. spatialcore/annotation/pipeline.py +620 -0
  14. spatialcore/annotation/synapse.py +380 -0
  15. spatialcore/annotation/training.py +1457 -0
  16. spatialcore/annotation/validation.py +422 -0
  17. spatialcore/core/__init__.py +34 -0
  18. spatialcore/core/cache.py +118 -0
  19. spatialcore/core/logging.py +135 -0
  20. spatialcore/core/metadata.py +149 -0
  21. spatialcore/core/utils.py +768 -0
  22. spatialcore/data/gene_mappings/ensembl_to_hugo_human.tsv +86372 -0
  23. spatialcore/data/markers/canonical_markers.json +83 -0
  24. spatialcore/data/ontology_mappings/ontology_index.json +63865 -0
  25. spatialcore/plotting/__init__.py +109 -0
  26. spatialcore/plotting/benchmark.py +477 -0
  27. spatialcore/plotting/celltype.py +329 -0
  28. spatialcore/plotting/confidence.py +413 -0
  29. spatialcore/plotting/spatial.py +505 -0
  30. spatialcore/plotting/utils.py +411 -0
  31. spatialcore/plotting/validation.py +1342 -0
  32. spatialcore-0.1.9.dist-info/METADATA +213 -0
  33. spatialcore-0.1.9.dist-info/RECORD +36 -0
  34. spatialcore-0.1.9.dist-info/WHEEL +5 -0
  35. spatialcore-0.1.9.dist-info/licenses/LICENSE +201 -0
  36. spatialcore-0.1.9.dist-info/top_level.txt +1 -0
@@ -0,0 +1,149 @@
1
+ """Metadata tracking for AnnData operations."""
2
+
3
+ import json
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from typing import Any, Dict, Optional, Union
7
+
8
+ import anndata as ad
9
+
10
+
11
+ class MetadataTracker:
12
+ """
13
+ Track operations performed on AnnData objects.
14
+
15
+ Stores metadata in adata.uns['spatialcore_metadata'] and optionally
16
+ writes to a JSON file.
17
+
18
+ Parameters
19
+ ----------
20
+ adata
21
+ AnnData object to track.
22
+ json_path
23
+ Optional path to write metadata JSON file.
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ adata: ad.AnnData,
29
+ json_path: Optional[Union[str, Path]] = None,
30
+ ) -> None:
31
+ self.adata = adata
32
+ self.json_path = Path(json_path) if json_path else None
33
+
34
+ if "spatialcore_metadata" not in adata.uns:
35
+ adata.uns["spatialcore_metadata"] = {
36
+ "created": datetime.now().isoformat(),
37
+ "operations": [],
38
+ }
39
+ else:
40
+ # Ensure operations is a list (may be numpy array after h5ad reload)
41
+ meta = adata.uns["spatialcore_metadata"]
42
+ if "operations" not in meta:
43
+ meta["operations"] = []
44
+ elif not isinstance(meta["operations"], list):
45
+ meta["operations"] = list(meta["operations"])
46
+
47
+ def log_operation(
48
+ self,
49
+ function_name: str,
50
+ parameters: Dict[str, Any],
51
+ outputs: Optional[Dict[str, str]] = None,
52
+ ) -> None:
53
+ """
54
+ Log an operation to the metadata.
55
+
56
+ Parameters
57
+ ----------
58
+ function_name
59
+ Name of the function that was called.
60
+ parameters
61
+ Dictionary of parameters passed to the function.
62
+ outputs
63
+ Dictionary describing where outputs were stored
64
+ (e.g., {'obs': 'cell_type', 'obsm': 'X_spatial_nmf'}).
65
+ """
66
+ entry = {
67
+ "timestamp": datetime.now().isoformat(),
68
+ "function": function_name,
69
+ "parameters": _serialize_params(parameters),
70
+ }
71
+ if outputs:
72
+ entry["outputs"] = outputs
73
+
74
+ self.adata.uns["spatialcore_metadata"]["operations"].append(entry)
75
+
76
+ if self.json_path:
77
+ self._write_json()
78
+
79
+ def _write_json(self) -> None:
80
+ """Write metadata to JSON file."""
81
+ with open(self.json_path, "w") as f:
82
+ json.dump(self.adata.uns["spatialcore_metadata"], f, indent=2)
83
+
84
+ def get_history(self) -> list:
85
+ """Return list of all operations performed."""
86
+ return self.adata.uns["spatialcore_metadata"]["operations"]
87
+
88
+
89
+ def update_metadata(
90
+ adata: ad.AnnData,
91
+ function_name: str,
92
+ parameters: Dict[str, Any],
93
+ outputs: Optional[Dict[str, str]] = None,
94
+ ) -> None:
95
+ """
96
+ Convenience function to update metadata without creating a tracker.
97
+
98
+ Parameters
99
+ ----------
100
+ adata
101
+ AnnData object to update.
102
+ function_name
103
+ Name of the function that was called.
104
+ parameters
105
+ Dictionary of parameters passed to the function.
106
+ outputs
107
+ Dictionary describing where outputs were stored.
108
+ """
109
+ tracker = MetadataTracker(adata)
110
+ tracker.log_operation(function_name, parameters, outputs)
111
+
112
+
113
+ def prepare_metadata_for_h5ad(adata: ad.AnnData) -> None:
114
+ """
115
+ Convert metadata to h5ad-compatible format.
116
+
117
+ The operations list contains nested dicts that can't be serialized
118
+ directly to h5ad. This function converts it to a JSON string.
119
+
120
+ Parameters
121
+ ----------
122
+ adata
123
+ AnnData object with spatialcore_metadata.
124
+ """
125
+ if "spatialcore_metadata" in adata.uns:
126
+ meta = adata.uns["spatialcore_metadata"]
127
+ if "operations" in meta and isinstance(meta["operations"], list):
128
+ # Convert operations list to JSON string for h5ad compatibility
129
+ meta["operations_json"] = json.dumps(meta["operations"])
130
+ meta["operations"] = [] # Clear the list to avoid serialization issues
131
+
132
+
133
+ def _serialize_params(params: Dict[str, Any]) -> Dict[str, Any]:
134
+ """Convert parameters to JSON-serializable format."""
135
+ serialized = {}
136
+ for key, value in params.items():
137
+ if isinstance(value, (str, int, float, bool, type(None))):
138
+ serialized[key] = value
139
+ elif isinstance(value, (list, tuple)):
140
+ serialized[key] = list(value)
141
+ elif isinstance(value, dict):
142
+ serialized[key] = _serialize_params(value)
143
+ elif isinstance(value, Path):
144
+ serialized[key] = str(value)
145
+ elif isinstance(value, ad.AnnData):
146
+ serialized[key] = f"<AnnData: {value.shape[0]} obs x {value.shape[1]} var>"
147
+ else:
148
+ serialized[key] = str(type(value).__name__)
149
+ return serialized