large-image-source-zarr 1.30.6.dev26__tar.gz → 1.30.6.dev35__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 (14) hide show
  1. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/PKG-INFO +3 -3
  2. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr/__init__.py +80 -28
  3. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr.egg-info/PKG-INFO +3 -3
  4. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr.egg-info/requires.txt +2 -2
  5. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/LICENSE +0 -0
  6. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/README.rst +0 -0
  7. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr/girder_source.py +0 -0
  8. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr.egg-info/SOURCES.txt +0 -0
  9. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr.egg-info/dependency_links.txt +0 -0
  10. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr.egg-info/entry_points.txt +0 -0
  11. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/large_image_source_zarr.egg-info/top_level.txt +0 -0
  12. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/pyproject.toml +0 -0
  13. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/setup.cfg +0 -0
  14. {large_image_source_zarr-1.30.6.dev26 → large_image_source_zarr-1.30.6.dev35}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: large-image-source-zarr
3
- Version: 1.30.6.dev26
3
+ Version: 1.30.6.dev35
4
4
  Summary: A OME Zarr tilesource for large_image.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -19,12 +19,12 @@ Classifier: Programming Language :: Python :: 3.13
19
19
  Requires-Python: >=3.6
20
20
  Description-Content-Type: text/x-rst
21
21
  License-File: LICENSE
22
- Requires-Dist: large-image>=1.30.6.dev26
22
+ Requires-Dist: large-image>=1.30.6.dev35
23
23
  Requires-Dist: zarr
24
24
  Requires-Dist: numcodecs
25
25
  Requires-Dist: imagecodecs-numcodecs!=2024.9.22
26
26
  Provides-Extra: girder
27
- Requires-Dist: girder-large-image>=1.30.6.dev26; extra == "girder"
27
+ Requires-Dist: girder-large-image>=1.30.6.dev35; extra == "girder"
28
28
  Provides-Extra: all
29
29
  Requires-Dist: large-image-converter; extra == "all"
30
30
 
@@ -158,6 +158,11 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
158
158
  self._frameValues = None
159
159
  self._frameAxes = None
160
160
  self._frameUnits = None
161
+ if not self._created:
162
+ try:
163
+ self._validateZarr()
164
+ except Exception:
165
+ pass
161
166
 
162
167
  def __del__(self):
163
168
  if not hasattr(self, '_derivedSource'):
@@ -363,6 +368,7 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
363
368
  if axes_values.get(a) is not None
364
369
  ]
365
370
  self._frameUnits = {k: axes_units.get(k) for k in self.frameAxes if k in axes_units}
371
+ self._frameValues = None
366
372
  frame_values_shape = [baseArray.shape[self._axes[a]] for a in self.frameAxes]
367
373
  frame_values_shape.append(len(frame_values_shape))
368
374
  frame_values = np.empty(frame_values_shape, dtype=object)
@@ -387,7 +393,8 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
387
393
  if name:
388
394
  slicing[self._frameAxes.index(name)] = j
389
395
  frame_values[tuple(slicing)] = value
390
- self._frameValues = frame_values
396
+ if frame_values.size > 0:
397
+ self._frameValues = frame_values
391
398
 
392
399
  def _validateZarr(self):
393
400
  """
@@ -645,6 +652,50 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
645
652
 
646
653
  return tile, mask, placement, axes
647
654
 
655
+ def _updateFrameValues(self, frame_values, placement, axes, new_axes, new_dims):
656
+ self._frameAxes = [
657
+ a for a in axes
658
+ if a in frame_values or
659
+ (self.frameAxes is not None and a in self.frameAxes)
660
+ ]
661
+ frames_shape = [new_dims[a] for a in self.frameAxes]
662
+ frames_shape.append(len(frames_shape))
663
+ if self.frameValues is None:
664
+ self._frameValues = np.empty(frames_shape, dtype=object)
665
+ elif self.frameValues.shape != frames_shape:
666
+ if len(new_axes):
667
+ for i in new_axes.values():
668
+ self._frameValues = np.expand_dims(self._frameValues, axis=i)
669
+ frame_padding = [
670
+ (0, s - self.frameValues.shape[i])
671
+ for i, s in enumerate(frames_shape)
672
+ ]
673
+ frame_padding[-1] = (0, 0)
674
+ self._frameValues = np.pad(self._frameValues, frame_padding)
675
+ for i in new_axes.values():
676
+ self._frameValues = np.insert(
677
+ self._frameValues, i, 0, axis=len(frames_shape) - 1,
678
+ )
679
+ current_frame_slice = tuple(placement.get(a) for a in self.frameAxes)
680
+ for i, k in enumerate(self.frameAxes):
681
+ self.frameValues[(*current_frame_slice, i)] = frame_values.get(k)
682
+
683
+ def _resizeImage(self, arr, new_shape, new_axes, chunking):
684
+ if new_shape != arr.shape:
685
+ if len(new_axes):
686
+ for i in new_axes.values():
687
+ arr = np.expand_dims(arr, axis=i)
688
+ arr = np.pad(
689
+ arr,
690
+ [(0, s - arr.shape[i]) for i, s in enumerate(new_shape)],
691
+ )
692
+ new_arr = zarr.empty(new_shape, chunks=chunking, dtype=arr.dtype)
693
+ new_arr[:] = arr[:]
694
+ arr = new_arr
695
+ else:
696
+ arr.resize(*new_shape)
697
+ return arr
698
+
648
699
  def addTile(self, tile, x=0, y=0, mask=None, axes=None, **kwargs):
649
700
  """
650
701
  Add a numpy or image tile to the image, expanding the image as needed
@@ -665,6 +716,12 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
665
716
  ``level`` is a reserved word and not permitted for an axis name.
666
717
  """
667
718
  self._checkEditable()
719
+ try:
720
+ # read any info written by other processes
721
+ self._validateZarr()
722
+ except TileSourceError:
723
+ pass
724
+ updateMetadata = False
668
725
  store_path = str(kwargs.pop('level', 0))
669
726
  placement = {
670
727
  'x': x,
@@ -678,9 +735,12 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
678
735
  tile, mask, placement, axes = self._validateNewTile(tile, mask, placement, axes)
679
736
 
680
737
  with self._threadLock and self._processLock:
738
+ old_axes = self._axes if hasattr(self, '_axes') else {}
681
739
  self._axes = {k: i for i, k in enumerate(axes)}
740
+ new_axes = {k: i for k, i in self._axes.items() if k not in old_axes}
682
741
  new_dims = {
683
742
  a: max(
743
+ self._axisCounts.get(a, 0) if hasattr(self, '_axisCounts') else 0,
684
744
  self._dims.get(store_path, {}).get(a, 0),
685
745
  placement.get(a, 0) + tile.shape[i],
686
746
  )
@@ -694,23 +754,8 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
694
754
 
695
755
  if len(frame_values.keys()) > 0:
696
756
  # update self.frameValues
697
- self.frameAxes = [
698
- a for a in axes
699
- if a in frame_values or
700
- (self.frameAxes is not None and a in self.frameAxes)
701
- ]
702
- frames_shape = [new_dims[a] for a in self.frameAxes]
703
- frames_shape.append(len(frames_shape))
704
- if self.frameValues is None:
705
- self.frameValues = np.empty(frames_shape, dtype=object)
706
- elif self.frameValues.shape != frames_shape:
707
- self.frameValues = np.pad(
708
- self.frameValues,
709
- [(0, s - self.frameValues.shape[i]) for i, s in enumerate(frames_shape)],
710
- )
711
- current_frame_slice = tuple(placement.get(a) for a in self.frameAxes)
712
- for i, k in enumerate(self.frameAxes):
713
- self.frameValues[(*current_frame_slice, i)] = frame_values.get(k)
757
+ updateMetadata = True
758
+ self._updateFrameValues(frame_values, placement, axes, new_axes, new_dims)
714
759
 
715
760
  current_arrays = dict(self._zarr.arrays())
716
761
  if store_path == '0':
@@ -728,16 +773,18 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
728
773
  ])
729
774
  else:
730
775
  arr = current_arrays[store_path]
731
- new_shape = tuple(max(v, arr.shape[i]) for i, v in enumerate(new_dims.values()))
732
- if new_shape != arr.shape:
733
- arr.resize(*new_shape)
734
- if arr.chunks[-1] != new_dims.get('s'):
735
- # rechunk if length of samples axis changes
736
- chunking = tuple([
737
- self._tileSize if a in ['x', 'y'] else
738
- new_dims.get('s') if a == 's' else 1
739
- for a in axes
740
- ])
776
+ new_shape = tuple(
777
+ max(v, arr.shape[old_axes[k]] if k in old_axes else 0)
778
+ for k, v in new_dims.items()
779
+ )
780
+ if arr.chunks[-1] != new_dims.get('s') or len(new_axes):
781
+ # rechunk if length of samples axis changed or any new axis added
782
+ chunking = tuple([
783
+ self._tileSize if a in ['x', 'y'] else
784
+ new_dims.get('s') if a == 's' else 1
785
+ for a in axes
786
+ ])
787
+ arr = self._resizeImage(arr, new_shape, new_axes, chunking)
741
788
 
742
789
  if mask is not None:
743
790
  arr[placement_slices] = np.where(mask, tile, arr[placement_slices])
@@ -767,6 +814,9 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
767
814
  self._levels = None
768
815
  self.levels = int(max(1, math.ceil(math.log(max(
769
816
  self.sizeX / self.tileWidth, self.sizeY / self.tileHeight)) / math.log(2)) + 1))
817
+ updateMetadata = True
818
+ if updateMetadata:
819
+ self._writeInternalMetadata()
770
820
 
771
821
  def addAssociatedImage(self, image, imageKey=None):
772
822
  """
@@ -1002,6 +1052,7 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
1002
1052
  def frameAxes(self, axes):
1003
1053
  self._checkEditable()
1004
1054
  self._frameAxes = axes
1055
+ self._writeInternalMetadata()
1005
1056
 
1006
1057
  @property
1007
1058
  def frameUnits(self):
@@ -1034,6 +1085,7 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
1034
1085
  err = f'frameValues must have {len(self.frameAxes) + 1} dimensions.'
1035
1086
  raise ValueError(err)
1036
1087
  self._frameValues = a
1088
+ self._writeInternalMetadata()
1037
1089
 
1038
1090
  def _generateDownsampledLevels(self, resample_method):
1039
1091
  self._checkEditable()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: large-image-source-zarr
3
- Version: 1.30.6.dev26
3
+ Version: 1.30.6.dev35
4
4
  Summary: A OME Zarr tilesource for large_image.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -19,12 +19,12 @@ Classifier: Programming Language :: Python :: 3.13
19
19
  Requires-Python: >=3.6
20
20
  Description-Content-Type: text/x-rst
21
21
  License-File: LICENSE
22
- Requires-Dist: large-image>=1.30.6.dev26
22
+ Requires-Dist: large-image>=1.30.6.dev35
23
23
  Requires-Dist: zarr
24
24
  Requires-Dist: numcodecs
25
25
  Requires-Dist: imagecodecs-numcodecs!=2024.9.22
26
26
  Provides-Extra: girder
27
- Requires-Dist: girder-large-image>=1.30.6.dev26; extra == "girder"
27
+ Requires-Dist: girder-large-image>=1.30.6.dev35; extra == "girder"
28
28
  Provides-Extra: all
29
29
  Requires-Dist: large-image-converter; extra == "all"
30
30
 
@@ -1,4 +1,4 @@
1
- large-image>=1.30.6.dev26
1
+ large-image>=1.30.6.dev35
2
2
  zarr
3
3
  numcodecs
4
4
  imagecodecs-numcodecs!=2024.9.22
@@ -7,4 +7,4 @@ imagecodecs-numcodecs!=2024.9.22
7
7
  large-image-converter
8
8
 
9
9
  [girder]
10
- girder-large-image>=1.30.6.dev26
10
+ girder-large-image>=1.30.6.dev35