ossify 0.2.0__tar.gz → 0.2.1__tar.gz

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 (35) hide show
  1. {ossify-0.2.0 → ossify-0.2.1}/PKG-INFO +2 -2
  2. {ossify-0.2.0 → ossify-0.2.1}/pyproject.toml +3 -3
  3. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/__init__.py +1 -1
  4. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/translate.py +42 -25
  5. {ossify-0.2.0 → ossify-0.2.1}/.github/workflows/mkdocs_publish.yml +0 -0
  6. {ossify-0.2.0 → ossify-0.2.1}/.github/workflows/python-package.yml +0 -0
  7. {ossify-0.2.0 → ossify-0.2.1}/.gitignore +0 -0
  8. {ossify-0.2.0 → ossify-0.2.1}/.pre-commit-config.yaml +0 -0
  9. {ossify-0.2.0 → ossify-0.2.1}/LICENSE +0 -0
  10. {ossify-0.2.0 → ossify-0.2.1}/README.md +0 -0
  11. {ossify-0.2.0 → ossify-0.2.1}/mkdocs.yml +0 -0
  12. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/__init__.py +0 -0
  13. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/base.py +0 -0
  14. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/graph.py +0 -0
  15. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/mapping.py +0 -0
  16. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/mesh.py +0 -0
  17. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/morph.py +0 -0
  18. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/points.py +0 -0
  19. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/_sync/table.py +0 -0
  20. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/algorithms.py +0 -0
  21. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/base.py +0 -0
  22. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/compartment_models/minnie65_ds15_us0_bd0.json +0 -0
  23. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/compartment_models/v1dd_ds15_us0_bd0.json +0 -0
  24. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/compartment_models/xgb/minnie65_ds15_us0_bd0.ubj +0 -0
  25. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/compartment_models/xgb/v1dd_ds15_us0_bd0.ubj +0 -0
  26. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/compartments.py +0 -0
  27. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/data_layers.py +0 -0
  28. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/file_io.py +0 -0
  29. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/graph_functions.py +0 -0
  30. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/plot.py +0 -0
  31. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/plot3d.py +0 -0
  32. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/plot_utils.py +0 -0
  33. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/structured_prediction.py +0 -0
  34. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/sync_classes.py +0 -0
  35. {ossify-0.2.0 → ossify-0.2.1}/src/ossify/utils.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ossify
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Mesh and skeleton analysis
5
5
  Author-email: Casey Schneider-Mizell <caseysm@gmail.com>
6
6
  License-File: LICENSE
7
7
  Classifier: License :: OSI Approved :: MIT License
8
8
  Requires-Python: >=3.11
9
- Requires-Dist: caveclient>=7.6.0
9
+ Requires-Dist: caveclient>=8.2.1
10
10
  Requires-Dist: cloud-files>=5.8.0
11
11
  Requires-Dist: fastremap>=1.15.1
12
12
  Requires-Dist: matplotlib>=3.10.6
@@ -6,12 +6,12 @@ build-backend = "hatchling.build"
6
6
  allow-direct-references = true
7
7
  [project]
8
8
  name = "ossify"
9
- version = "0.2.0"
9
+ version = "0.2.1"
10
10
  description = "Mesh and skeleton analysis"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.11"
13
13
  dependencies = [
14
- "caveclient>=7.6.0",
14
+ "caveclient>=8.2.1",
15
15
  "numpy>=2.0.2",
16
16
  "scipy>=1.15",
17
17
  "trimesh>=4.6.2",
@@ -95,7 +95,7 @@ default-groups = ["dev", "docs", "lint", "profile", "viz"]
95
95
 
96
96
 
97
97
  [tool.bumpversion]
98
- current_version = "0.2.0"
98
+ current_version = "0.2.1"
99
99
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
100
100
  serialize = ["{major}.{minor}.{patch}"]
101
101
  regex = false
@@ -5,7 +5,7 @@ from .base import *
5
5
  from .file_io import *
6
6
  from .translate import *
7
7
 
8
- __version__ = "0.2.0"
8
+ __version__ = "0.2.1"
9
9
 
10
10
 
11
11
  def __getattr__(name):
@@ -23,10 +23,10 @@ if TYPE_CHECKING:
23
23
  from caveclient import CAVEclientFull as CAVEclient
24
24
 
25
25
 
26
- # Synchronous bulk-skeleton download cap in the CAVE skeleton service
27
- # (caveclient.skeletonservice.MAX_BULK_SYNCHRONOUS_SKELETONS); larger lists are silently
28
- # truncated by the endpoint, so callers must chunk at this size.
29
- _BULK_SKELETON_CHUNK = 10
26
+ # Per-call cap for cached bulk-skeleton downloads via ``client.skeleton.fetch_skeletons``
27
+ # (caveclient.skeletonservice.MAX_BULK_CACHED_SKELETONS); longer lists are silently truncated
28
+ # by the endpoint, so callers must chunk at this size.
29
+ _BULK_SKELETON_CHUNK = 500
30
30
 
31
31
 
32
32
  class SWCCompartment(IntEnum):
@@ -563,23 +563,32 @@ def _get_bulk_skeletons(
563
563
  client: "CAVEclient",
564
564
  root_ids: list[int],
565
565
  skeleton_version: int,
566
- generate_missing: bool = False,
566
+ method: Literal["gcs", "server"] = "gcs",
567
567
  ) -> dict[int, dict]:
568
- """Download skeletons in bulk, chunked at the synchronous bulk cap.
569
-
570
- Returns ``{int root_id: skeleton_dict}``. Roots whose skeleton is not yet available
571
- (async/not-generated) are omitted — with ``generate_missing=False`` (the worker default,
572
- assuming a prior ``generate_bulk_skeletons_async`` pre-pass) these simply don't appear.
568
+ """Download cached skeletons in bulk, chunked at the cached-bulk cap.
569
+
570
+ Uses ``client.skeleton.fetch_skeletons``, which retrieves only already-cached skeletons and
571
+ skips the per-root chunkedgraph validation of the older ``get_bulk_skeletons`` path. With
572
+ ``method="gcs"`` (the default) skeleton H5 files are downloaded directly from the storage
573
+ bucket via a short-lived downscoped token, bypassing the service for data transfer — this
574
+ avoids the request rate limits that throttle bulk loads through the server. ``method="server"``
575
+ routes the download through the skeleton service instead.
576
+
577
+ Skeletons are never generated inline (``generate_missing_skeletons=False`` always). Returns
578
+ ``{int root_id: skeleton_dict}``; roots whose skeleton is not yet cached (async/not-generated)
579
+ are omitted — assuming a prior ``generate_bulk_skeletons_async`` pre-pass, these simply don't
580
+ appear.
573
581
  """
574
582
  out: dict[int, dict] = {}
575
583
  for i in range(0, len(root_ids), _BULK_SKELETON_CHUNK):
576
584
  chunk = root_ids[i : i + _BULK_SKELETON_CHUNK]
577
585
  with suppress_output():
578
- res = client.skeleton.get_bulk_skeletons(
586
+ res = client.skeleton.fetch_skeletons(
579
587
  chunk,
580
588
  skeleton_version=skeleton_version,
581
589
  output_format="dict",
582
- generate_missing_skeletons=generate_missing,
590
+ method=method,
591
+ generate_missing_skeletons=False,
583
592
  )
584
593
  for k, v in res.items():
585
594
  out[int(k)] = v
@@ -601,7 +610,7 @@ def load_cell_batch_from_client(
601
610
  omit_self_synapses: bool = True,
602
611
  skeleton_version: int = 4,
603
612
  skip_invalid: bool = False,
604
- generate_missing_skeletons: bool = False,
613
+ skeleton_download_method: Literal["gcs", "server"] = "gcs",
605
614
  row_limit: int = 500_000,
606
615
  ) -> dict[int, Cell]:
607
616
  """Load many cells with the poolable fetches batched into a few queries.
@@ -611,6 +620,9 @@ def load_cell_batch_from_client(
611
620
  each cell is then assembled network-free — no skeleton is fetched twice, and the batch is
612
621
  validated with a single round trip. All roots share one ``timestamp``.
613
622
 
623
+ All parameters not listed below match :func:`load_cell_from_client` and are applied
624
+ identically to every cell in the batch.
625
+
614
626
  Parameters
615
627
  ----------
616
628
  root_ids: list[int]
@@ -622,11 +634,14 @@ def load_cell_batch_from_client(
622
634
  skip_invalid: bool
623
635
  If True, roots that are not valid at ``timestamp`` — or whose skeleton is not available
624
636
  — are dropped from the result instead of raising.
625
- generate_missing_skeletons: bool
626
- Passed to ``get_bulk_skeletons``. Default False assumes skeletons were already produced
627
- by a ``generate_bulk_skeletons_async`` pre-pass; a worker then just downloads them (fast,
628
- and degrades gracefully on a cache miss). Set True to block on server-side generation.
629
- (all other parameters match :func:`load_cell_from_client`.)
637
+ skeleton_download_method: "gcs" or "server"
638
+ How ``fetch_skeletons`` retrieves cached skeletons. ``"gcs"`` (default) downloads H5 files
639
+ directly from the storage bucket via a downscoped token, bypassing the service for data
640
+ transfer and avoiding its request rate limits — preferred for bulk loads. ``"server"``
641
+ routes the download through the skeleton service instead.
642
+ row_limit: int
643
+ Passed to :func:`fetch_frames_batch`; guards against a silently-truncated pooled synapse
644
+ query at/above the server row limit (default 500,000). Set to 0 to disable.
630
645
 
631
646
  Returns
632
647
  -------
@@ -649,18 +664,20 @@ def load_cell_batch_from_client(
649
664
  + (" ..." if len(invalid_ids) > 5 else "")
650
665
  )
651
666
 
652
- # 2. Skeletons: one bulk download (chunked at the sync cap) to obtain lvl2_ids, then
653
- # injected into assembly. Assumes a prior generate_bulk_skeletons_async pre-pass.
667
+ # 2. Skeletons: one cached bulk download (chunked at the cached-bulk cap) to obtain lvl2_ids,
668
+ # then injected into assembly. Assumes a prior generate_bulk_skeletons_async pre-pass.
654
669
  sk_by_root = _get_bulk_skeletons(
655
- client, valid_ids, skeleton_version, generate_missing=generate_missing_skeletons
670
+ client,
671
+ valid_ids,
672
+ skeleton_version,
673
+ method=skeleton_download_method,
656
674
  )
657
675
  no_skeleton = [r for r in valid_ids if r not in sk_by_root]
658
676
  if no_skeleton and not skip_invalid:
659
677
  raise ValueError(
660
- f"{len(no_skeleton)} root id(s) have no available skeleton "
661
- f"(run generate_bulk_skeletons_async first, or pass generate_missing_skeletons=True "
662
- f"or skip_invalid=True): {no_skeleton[:5]}"
663
- + (" ..." if len(no_skeleton) > 5 else "")
678
+ f"{len(no_skeleton)} root id(s) have no cached skeleton "
679
+ f"(run generate_bulk_skeletons_async first, or pass skip_invalid=True): "
680
+ f"{no_skeleton[:5]}" + (" ..." if len(no_skeleton) > 5 else "")
664
681
  )
665
682
  valid_ids = [r for r in valid_ids if r in sk_by_root]
666
683
  lvl2_ids_by_root = {r: sk_by_root[r]["lvl2_ids"] for r in valid_ids}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes