nnInteractive 2.3.0__tar.gz → 2.3.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 (90) hide show
  1. {nninteractive-2.3.0 → nninteractive-2.3.1}/PKG-INFO +1 -1
  2. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/remote/remote_session.py +19 -3
  3. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/remote/serialization.py +15 -6
  4. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/server/app.py +3 -1
  5. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive.egg-info/PKG-INFO +1 -1
  6. {nninteractive-2.3.0 → nninteractive-2.3.1}/pyproject.toml +1 -1
  7. {nninteractive-2.3.0 → nninteractive-2.3.1}/LICENSE +0 -0
  8. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/__init__.py +0 -0
  9. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/__init__.py +0 -0
  10. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/cvpr2025_challenge_baseline/__init__.py +0 -0
  11. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/cvpr2025_challenge_baseline/predict.py +0 -0
  12. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/inference_session.py +0 -0
  13. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/remote/__init__.py +0 -0
  14. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/remote/_protocol.py +0 -0
  15. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/server/__init__.py +0 -0
  16. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/inference/server/main.py +0 -0
  17. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/interaction/__init__.py +0 -0
  18. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/interaction/point.py +0 -0
  19. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/setup.py +0 -0
  20. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/metadata.py +0 -0
  21. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/reader.py +0 -0
  22. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/run.py +0 -0
  23. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/__init__.py +0 -0
  24. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/__init__.py +0 -0
  25. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/automatic_mask_generator.py +0 -0
  26. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/benchmark.py +0 -0
  27. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/build_sam.py +0 -0
  28. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/__init__.py +0 -0
  29. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/backbones/__init__.py +0 -0
  30. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/backbones/hieradet.py +0 -0
  31. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/backbones/image_encoder.py +0 -0
  32. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/backbones/utils.py +0 -0
  33. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/memory_attention.py +0 -0
  34. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/memory_encoder.py +0 -0
  35. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/position_encoding.py +0 -0
  36. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/sam/__init__.py +0 -0
  37. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/sam/mask_decoder.py +0 -0
  38. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/sam/prompt_encoder.py +0 -0
  39. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/sam/transformer.py +0 -0
  40. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/sam2_base.py +0 -0
  41. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/modeling/sam2_utils.py +0 -0
  42. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/sam2_image_predictor.py +0 -0
  43. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/sam2_video_predictor.py +0 -0
  44. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/sam2_video_predictor_legacy.py +0 -0
  45. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/utils/__init__.py +0 -0
  46. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/utils/amg.py +0 -0
  47. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/utils/misc.py +0 -0
  48. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/sam2/utils/transforms.py +0 -0
  49. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/setup.py +0 -0
  50. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/__init__.py +0 -0
  51. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/__init__.py +0 -0
  52. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/sam2_datasets.py +0 -0
  53. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/transforms.py +0 -0
  54. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/utils.py +0 -0
  55. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/vos_dataset.py +0 -0
  56. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/vos_raw_dataset.py +0 -0
  57. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/vos_sampler.py +0 -0
  58. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/dataset/vos_segment_loader.py +0 -0
  59. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/loss_fns.py +0 -0
  60. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/model/__init__.py +0 -0
  61. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/model/sam2.py +0 -0
  62. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/optimizer.py +0 -0
  63. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/scripts/sav_frame_extraction_submitit.py +0 -0
  64. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/train.py +0 -0
  65. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/trainer.py +0 -0
  66. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/utils/__init__.py +0 -0
  67. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/utils/checkpoint_utils.py +0 -0
  68. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/utils/data_utils.py +0 -0
  69. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/utils/distributed.py +0 -0
  70. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/utils/logger.py +0 -0
  71. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/sam2/training/utils/train_utils.py +0 -0
  72. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/supervoxel/src/supervoxel.py +0 -0
  73. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/trainer/__init__.py +0 -0
  74. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/trainer/nnInteractiveTrainer.py +0 -0
  75. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/__init__.py +0 -0
  76. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/bboxes.py +0 -0
  77. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/checkpoint_cleansing.py +0 -0
  78. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/crop.py +0 -0
  79. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/erosion_dilation.py +0 -0
  80. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/inference_helpers.py +0 -0
  81. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/os_shennanigans.py +0 -0
  82. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive/utils/rounding.py +0 -0
  83. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive.egg-info/SOURCES.txt +0 -0
  84. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive.egg-info/dependency_links.txt +0 -0
  85. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive.egg-info/entry_points.txt +0 -0
  86. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive.egg-info/requires.txt +0 -0
  87. {nninteractive-2.3.0 → nninteractive-2.3.1}/nnInteractive.egg-info/top_level.txt +0 -0
  88. {nninteractive-2.3.0 → nninteractive-2.3.1}/readme.md +0 -0
  89. {nninteractive-2.3.0 → nninteractive-2.3.1}/setup.cfg +0 -0
  90. {nninteractive-2.3.0 → nninteractive-2.3.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nnInteractive
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Inference code for nnInteractive
5
5
  Author: Helmholtz Imaging Applied Computer Vision Lab
6
6
  Author-email: Fabian Isensee <f.isensee@dkfz-heidelberg.de>
@@ -42,6 +42,16 @@ from nnInteractive.inference.remote._protocol import (
42
42
  from nnInteractive.inference.remote.serialization import pack_array, unpack_array
43
43
 
44
44
 
45
+ def _compression_threads() -> int:
46
+ """blosc2 thread count for client-side upload compression.
47
+
48
+ Full logical CPU count: blosc2 scales measurably onto SMT siblings, so use them all to
49
+ minimize upload latency. Per-call only (passed to pack_array → compress2), so it never
50
+ mutates blosc2's global nthreads.
51
+ """
52
+ return max(1, os.cpu_count() or 1)
53
+
54
+
45
55
  class SessionExpiredError(RuntimeError):
46
56
  """Raised when the server reports the client's lease no longer exists.
47
57
 
@@ -290,7 +300,7 @@ class nnInteractiveRemoteInferenceSession:
290
300
  def set_image(self, image: np.ndarray, image_properties: Optional[dict] = None) -> None:
291
301
  assert image.ndim == 4, f"expected a 4d image as input, got {image.ndim}d. Shape {image.shape}"
292
302
  meta = {"image_properties": image_properties or {}}
293
- resp = self._post_binary(PATH_SET_IMAGE, meta, pack_array(image))
303
+ resp = self._post_binary(PATH_SET_IMAGE, meta, pack_array(image, nthreads=_compression_threads()))
294
304
  info = resp.json()
295
305
  self.original_image_shape = tuple(info["original_image_shape"])
296
306
 
@@ -402,7 +412,9 @@ class nnInteractiveRemoteInferenceSession:
402
412
  "interaction_bbox": ([list(b) for b in interaction_bbox] if interaction_bbox is not None else None),
403
413
  }
404
414
  # Interactions (scribble/lasso masks) compress best with NOFILTER; skip auto-selection.
405
- resp = self._post_binary(path, meta, pack_array(mask_image, filters=[blosc2.Filter.NOFILTER]))
415
+ resp = self._post_binary(
416
+ path, meta, pack_array(mask_image, filters=[blosc2.Filter.NOFILTER], nthreads=_compression_threads())
417
+ )
406
418
  self._apply_prediction_response(resp)
407
419
 
408
420
  def add_initial_seg_interaction(
@@ -428,7 +440,11 @@ class nnInteractiveRemoteInferenceSession:
428
440
  "override_capability_checks": bool(override_capability_checks),
429
441
  }
430
442
  # Segmentations compress best with NOFILTER; skip auto-selection.
431
- resp = self._post_binary(PATH_ADD_INITIAL_SEG, meta, pack_array(initial_seg, filters=[blosc2.Filter.NOFILTER]))
443
+ resp = self._post_binary(
444
+ PATH_ADD_INITIAL_SEG,
445
+ meta,
446
+ pack_array(initial_seg, filters=[blosc2.Filter.NOFILTER], nthreads=_compression_threads()),
447
+ )
432
448
  self._apply_prediction_response(resp)
433
449
 
434
450
  # ------------------------------------------------------------------ #
@@ -51,18 +51,21 @@ _ID_CODEC = {v: k for k, v in _CODEC_ID.items()}
51
51
  _SELECT_FILTER_CROP_FRACTION = 0.25
52
52
 
53
53
 
54
- def _compress_all(raw: memoryview, total: int, codec: blosc2.Codec, clevel: int, filters: list) -> int:
54
+ def _compress_all(
55
+ raw: memoryview, total: int, codec: blosc2.Codec, clevel: int, filters: list, nthreads: Optional[int]
56
+ ) -> int:
55
57
  """Compressed byte length of ``raw`` under ``filters``, chunked exactly as pack_array does."""
58
+ extra = {} if nthreads is None else {"nthreads": nthreads}
56
59
  size = 0
57
60
  nchunks = (total + _CHUNK_SIZE - 1) // _CHUNK_SIZE
58
61
  for i in range(nchunks):
59
62
  start = i * _CHUNK_SIZE
60
63
  end = min(start + _CHUNK_SIZE, total)
61
- size += len(blosc2.compress2(raw[start:end], codec=codec, clevel=clevel, filters=filters))
64
+ size += len(blosc2.compress2(raw[start:end], codec=codec, clevel=clevel, filters=filters, **extra))
62
65
  return size
63
66
 
64
67
 
65
- def _select_filter(arr: np.ndarray, codec: blosc2.Codec, clevel: int) -> "blosc2.Filter":
68
+ def _select_filter(arr: np.ndarray, codec: blosc2.Codec, clevel: int, nthreads: Optional[int]) -> "blosc2.Filter":
66
69
  """Pick NOFILTER vs SHUFFLE for ``arr`` by trial-compressing a small centered crop.
67
70
 
68
71
  Uses ``compress2`` on the raw bytes — exactly the path pack_array takes — so the decision
@@ -79,7 +82,7 @@ def _select_filter(arr: np.ndarray, codec: blosc2.Codec, clevel: int) -> "blosc2
79
82
 
80
83
  best_filter, best_bytes = blosc2.Filter.NOFILTER, None
81
84
  for f in (blosc2.Filter.NOFILTER, blosc2.Filter.SHUFFLE):
82
- cb = _compress_all(raw, total, codec, clevel, [f])
85
+ cb = _compress_all(raw, total, codec, clevel, [f], nthreads)
83
86
  if best_bytes is None or cb < best_bytes:
84
87
  best_bytes, best_filter = cb, f
85
88
  return best_filter
@@ -95,6 +98,7 @@ def pack_array(
95
98
  codec: blosc2.Codec = blosc2.Codec.ZSTD,
96
99
  clevel: int = 3,
97
100
  filters: Optional[list] = None,
101
+ nthreads: Optional[int] = None,
98
102
  ) -> bytes:
99
103
  """Serialize a numpy array to a self-describing compressed byte string.
100
104
 
@@ -104,6 +108,10 @@ def pack_array(
104
108
  know the optimum (interactions and segmentations compress best with NOFILTER) should pass
105
109
  ``[blosc2.Filter.NOFILTER]`` to skip the selection. The chosen filter is self-describing
106
110
  inside the blosc2 frame, so unpack_array (decompress2) needs no changes.
111
+
112
+ ``nthreads`` is the per-call blosc2 thread count for compression. ``None`` (the default)
113
+ inherits blosc2's global ``nthreads`` (= core count). Passing an explicit value overrides
114
+ it for this call only, without mutating global state.
107
115
  """
108
116
  arr = np.ascontiguousarray(arr)
109
117
  dtype_str = arr.dtype.str.lstrip("<>|=").encode("ascii")
@@ -137,13 +145,14 @@ def pack_array(
137
145
  if filters is None:
138
146
  # Auto-select the better filter from a small centered crop, using the same
139
147
  # compress2 path as below for consistency.
140
- filters = [_select_filter(arr, codec, clevel)]
148
+ filters = [_select_filter(arr, codec, clevel, nthreads)]
141
149
 
150
+ extra = {} if nthreads is None else {"nthreads": nthreads}
142
151
  parts = [header, shape_bytes, struct.pack("<I", nchunks)]
143
152
  for i in range(nchunks):
144
153
  start = i * _CHUNK_SIZE
145
154
  end = min(start + _CHUNK_SIZE, total)
146
- chunk = blosc2.compress2(raw[start:end], codec=codec, clevel=clevel, filters=filters)
155
+ chunk = blosc2.compress2(raw[start:end], codec=codec, clevel=clevel, filters=filters, **extra)
147
156
  parts.append(struct.pack("<QQ", end - start, len(chunk)))
148
157
  parts.append(chunk)
149
158
  return b"".join(parts)
@@ -443,7 +443,9 @@ def make_app(
443
443
  session._last_paste_bbox = None
444
444
  return Response(
445
445
  # Segmentations compress best with NOFILTER; skip auto-selection.
446
- content=pack_array(sub, filters=[blosc2.Filter.NOFILTER]),
446
+ content=pack_array(
447
+ sub, filters=[blosc2.Filter.NOFILTER], nthreads=min(session.torch_n_threads, os.cpu_count())
448
+ ),
447
449
  media_type=CONTENT_TYPE_OCTET_STREAM,
448
450
  headers={META_HEADER: json.dumps(meta, separators=(",", ":"))},
449
451
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nnInteractive
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Inference code for nnInteractive
5
5
  Author: Helmholtz Imaging Applied Computer Vision Lab
6
6
  Author-email: Fabian Isensee <f.isensee@dkfz-heidelberg.de>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nnInteractive"
3
- version = "2.3.0"
3
+ version = "2.3.1"
4
4
  requires-python = ">=3.10"
5
5
  description = "Inference code for nnInteractive"
6
6
  readme = "readme.md"
File without changes
File without changes
File without changes
File without changes