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,380 @@
1
+ """
2
+ Synapse data download utilities.
3
+
4
+ This module provides functions for downloading reference datasets from
5
+ Synapse (synapse.org), a platform commonly used for sharing biomedical
6
+ research data.
7
+
8
+ Authentication requires a Synapse account and auth token. Set the
9
+ SYNAPSE_AUTH_TOKEN environment variable or pass the token directly.
10
+
11
+ References:
12
+ - Synapse: https://www.synapse.org/
13
+ - synapseclient docs: https://python-docs.synapse.org/
14
+ """
15
+
16
+ import os
17
+ from pathlib import Path
18
+ from typing import Dict, List, Optional, Any
19
+
20
+ from spatialcore.core.logging import get_logger
21
+
22
+ logger = get_logger(__name__)
23
+
24
+
25
+ def authenticate_synapse(auth_token: Optional[str] = None) -> bool:
26
+ """
27
+ Authenticate with Synapse.
28
+
29
+ Parameters
30
+ ----------
31
+ auth_token : str, optional
32
+ Synapse authentication token. If None, uses SYNAPSE_AUTH_TOKEN
33
+ environment variable.
34
+
35
+ Returns
36
+ -------
37
+ bool
38
+ True if authentication successful.
39
+
40
+ Notes
41
+ -----
42
+ To get a Synapse auth token:
43
+ 1. Create account at synapse.org
44
+ 2. Go to Account Settings > Personal Access Tokens
45
+ 3. Generate token with "Download" scope
46
+ 4. Set SYNAPSE_AUTH_TOKEN environment variable
47
+
48
+ Examples
49
+ --------
50
+ >>> from spatialcore.annotation.synapse import authenticate_synapse
51
+ >>> # Using environment variable
52
+ >>> success = authenticate_synapse()
53
+ >>> # Using direct token
54
+ >>> success = authenticate_synapse("my_token")
55
+ """
56
+ try:
57
+ import synapseclient
58
+ except ImportError:
59
+ raise ImportError(
60
+ "synapseclient is required for Synapse downloads. "
61
+ "Install with: pip install synapseclient"
62
+ )
63
+
64
+ token = auth_token or os.environ.get("SYNAPSE_AUTH_TOKEN")
65
+
66
+ if not token:
67
+ logger.warning(
68
+ "No Synapse auth token provided. "
69
+ "Set SYNAPSE_AUTH_TOKEN environment variable or pass auth_token."
70
+ )
71
+ return False
72
+
73
+ try:
74
+ syn = synapseclient.Synapse()
75
+ syn.login(authToken=token, silent=True)
76
+ logger.info("Successfully authenticated with Synapse")
77
+ return True
78
+ except Exception as e:
79
+ logger.error(f"Synapse authentication failed: {e}")
80
+ return False
81
+
82
+
83
+ def download_synapse_reference(
84
+ synapse_id: str,
85
+ output_dir: Path,
86
+ auth_token: Optional[str] = None,
87
+ force: bool = False,
88
+ ) -> Path:
89
+ """
90
+ Download reference dataset from Synapse.
91
+
92
+ Parameters
93
+ ----------
94
+ synapse_id : str
95
+ Synapse entity ID (e.g., "syn12345678").
96
+ output_dir : Path
97
+ Directory to save downloaded file.
98
+ auth_token : str, optional
99
+ Synapse authentication token. If None, uses SYNAPSE_AUTH_TOKEN
100
+ environment variable.
101
+ force : bool, default False
102
+ Force re-download even if file exists.
103
+
104
+ Returns
105
+ -------
106
+ Path
107
+ Path to downloaded file.
108
+
109
+ Raises
110
+ ------
111
+ ImportError
112
+ If synapseclient is not installed.
113
+ ValueError
114
+ If authentication fails or entity not found.
115
+
116
+ Examples
117
+ --------
118
+ >>> from spatialcore.annotation.synapse import download_synapse_reference
119
+ >>> path = download_synapse_reference(
120
+ ... "syn12345678",
121
+ ... output_dir=Path("./data"),
122
+ ... )
123
+ >>> print(f"Downloaded to: {path}")
124
+ """
125
+ try:
126
+ import synapseclient
127
+ except ImportError:
128
+ raise ImportError(
129
+ "synapseclient is required for Synapse downloads. "
130
+ "Install with: pip install synapseclient"
131
+ )
132
+
133
+ output_dir = Path(output_dir)
134
+ output_dir.mkdir(parents=True, exist_ok=True)
135
+
136
+ # Get auth token
137
+ token = auth_token or os.environ.get("SYNAPSE_AUTH_TOKEN")
138
+ if not token:
139
+ raise ValueError(
140
+ "Synapse authentication required. "
141
+ "Set SYNAPSE_AUTH_TOKEN environment variable or pass auth_token."
142
+ )
143
+
144
+ # Initialize client
145
+ syn = synapseclient.Synapse()
146
+ try:
147
+ syn.login(authToken=token, silent=True)
148
+ except Exception as e:
149
+ raise ValueError(f"Synapse authentication failed: {e}")
150
+
151
+ # Get entity info
152
+ try:
153
+ entity = syn.get(synapse_id, downloadFile=False)
154
+ filename = entity.name
155
+ expected_path = output_dir / filename
156
+ except Exception as e:
157
+ raise ValueError(f"Failed to get Synapse entity '{synapse_id}': {e}")
158
+
159
+ # Check if already downloaded
160
+ if expected_path.exists() and not force:
161
+ logger.info(f"File already exists: {expected_path}")
162
+ return expected_path
163
+
164
+ # Download
165
+ logger.info(f"Downloading Synapse entity: {synapse_id}")
166
+ logger.info(f" Name: {filename}")
167
+
168
+ try:
169
+ entity = syn.get(synapse_id, downloadLocation=str(output_dir))
170
+ downloaded_path = Path(entity.path)
171
+ logger.info(f" Downloaded to: {downloaded_path}")
172
+ return downloaded_path
173
+ except Exception as e:
174
+ raise ValueError(f"Failed to download '{synapse_id}': {e}")
175
+
176
+
177
+ def get_synapse_entity_info(
178
+ synapse_id: str,
179
+ auth_token: Optional[str] = None,
180
+ ) -> Dict[str, Any]:
181
+ """
182
+ Get metadata for a Synapse entity.
183
+
184
+ Parameters
185
+ ----------
186
+ synapse_id : str
187
+ Synapse entity ID.
188
+ auth_token : str, optional
189
+ Synapse authentication token.
190
+
191
+ Returns
192
+ -------
193
+ Dict[str, Any]
194
+ Entity metadata including:
195
+ - name: File name
196
+ - id: Synapse ID
197
+ - content_type: MIME type
198
+ - size_mb: File size in MB
199
+ - md5: MD5 checksum
200
+ - created_on: Creation date
201
+ - modified_on: Last modified date
202
+
203
+ Examples
204
+ --------
205
+ >>> from spatialcore.annotation.synapse import get_synapse_entity_info
206
+ >>> info = get_synapse_entity_info("syn12345678")
207
+ >>> print(f"Size: {info['size_mb']:.1f} MB")
208
+ """
209
+ try:
210
+ import synapseclient
211
+ except ImportError:
212
+ raise ImportError(
213
+ "synapseclient is required. "
214
+ "Install with: pip install synapseclient"
215
+ )
216
+
217
+ token = auth_token or os.environ.get("SYNAPSE_AUTH_TOKEN")
218
+ if not token:
219
+ raise ValueError("Synapse authentication required.")
220
+
221
+ syn = synapseclient.Synapse()
222
+ syn.login(authToken=token, silent=True)
223
+
224
+ entity = syn.get(synapse_id, downloadFile=False)
225
+
226
+ # Extract metadata
227
+ info = {
228
+ "name": entity.name,
229
+ "id": entity.id,
230
+ "content_type": getattr(entity, "contentType", "unknown"),
231
+ "created_on": getattr(entity, "createdOn", None),
232
+ "modified_on": getattr(entity, "modifiedOn", None),
233
+ }
234
+
235
+ # Get file-specific info
236
+ if hasattr(entity, "contentSize"):
237
+ info["size_mb"] = entity.contentSize / (1024 * 1024)
238
+ if hasattr(entity, "md5"):
239
+ info["md5"] = entity.md5
240
+
241
+ return info
242
+
243
+
244
+ def list_synapse_folder(
245
+ folder_id: str,
246
+ auth_token: Optional[str] = None,
247
+ file_types: Optional[List[str]] = None,
248
+ ) -> List[Dict[str, Any]]:
249
+ """
250
+ List contents of a Synapse folder.
251
+
252
+ Parameters
253
+ ----------
254
+ folder_id : str
255
+ Synapse folder ID.
256
+ auth_token : str, optional
257
+ Synapse authentication token.
258
+ file_types : List[str], optional
259
+ Filter by file extensions (e.g., [".h5ad", ".h5"]).
260
+
261
+ Returns
262
+ -------
263
+ List[Dict[str, Any]]
264
+ List of entity metadata dictionaries.
265
+
266
+ Examples
267
+ --------
268
+ >>> from spatialcore.annotation.synapse import list_synapse_folder
269
+ >>> files = list_synapse_folder("syn12345", file_types=[".h5ad"])
270
+ >>> for f in files:
271
+ ... print(f"{f['name']}: {f['size_mb']:.1f} MB")
272
+ """
273
+ try:
274
+ import synapseclient
275
+ except ImportError:
276
+ raise ImportError(
277
+ "synapseclient is required. "
278
+ "Install with: pip install synapseclient"
279
+ )
280
+
281
+ token = auth_token or os.environ.get("SYNAPSE_AUTH_TOKEN")
282
+ if not token:
283
+ raise ValueError("Synapse authentication required.")
284
+
285
+ syn = synapseclient.Synapse()
286
+ syn.login(authToken=token, silent=True)
287
+
288
+ # Get folder children
289
+ children = list(syn.getChildren(folder_id))
290
+
291
+ results = []
292
+ for child in children:
293
+ # Filter by type if specified
294
+ if file_types is not None:
295
+ name = child.get("name", "")
296
+ if not any(name.endswith(ext) for ext in file_types):
297
+ continue
298
+
299
+ info = {
300
+ "name": child.get("name"),
301
+ "id": child.get("id"),
302
+ "type": child.get("type"),
303
+ }
304
+
305
+ # Add size if available
306
+ if "dataFileHandleId" in child:
307
+ try:
308
+ entity = syn.get(child["id"], downloadFile=False)
309
+ if hasattr(entity, "contentSize"):
310
+ info["size_mb"] = entity.contentSize / (1024 * 1024)
311
+ except Exception:
312
+ pass
313
+
314
+ results.append(info)
315
+
316
+ return results
317
+
318
+
319
+ def download_synapse_folder(
320
+ folder_id: str,
321
+ output_dir: Path,
322
+ auth_token: Optional[str] = None,
323
+ file_types: Optional[List[str]] = None,
324
+ force: bool = False,
325
+ ) -> List[Path]:
326
+ """
327
+ Download all files from a Synapse folder.
328
+
329
+ Parameters
330
+ ----------
331
+ folder_id : str
332
+ Synapse folder ID.
333
+ output_dir : Path
334
+ Directory to save downloaded files.
335
+ auth_token : str, optional
336
+ Synapse authentication token.
337
+ file_types : List[str], optional
338
+ Only download files with these extensions.
339
+ force : bool, default False
340
+ Force re-download even if files exist.
341
+
342
+ Returns
343
+ -------
344
+ List[Path]
345
+ Paths to downloaded files.
346
+
347
+ Examples
348
+ --------
349
+ >>> from spatialcore.annotation.synapse import download_synapse_folder
350
+ >>> paths = download_synapse_folder(
351
+ ... "syn12345",
352
+ ... output_dir=Path("./data"),
353
+ ... file_types=[".h5ad"],
354
+ ... )
355
+ """
356
+ # List folder contents
357
+ files = list_synapse_folder(folder_id, auth_token, file_types)
358
+
359
+ if not files:
360
+ logger.warning(f"No matching files found in folder {folder_id}")
361
+ return []
362
+
363
+ logger.info(f"Found {len(files)} files to download")
364
+
365
+ downloaded = []
366
+ for file_info in files:
367
+ if file_info.get("type") == "org.sagebionetworks.repo.model.FileEntity":
368
+ try:
369
+ path = download_synapse_reference(
370
+ file_info["id"],
371
+ output_dir,
372
+ auth_token,
373
+ force,
374
+ )
375
+ downloaded.append(path)
376
+ except Exception as e:
377
+ logger.warning(f"Failed to download {file_info['name']}: {e}")
378
+
379
+ logger.info(f"Downloaded {len(downloaded)} files")
380
+ return downloaded