large-image-source-zarr 1.30.2__tar.gz → 1.30.2.dev4__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.2 → large_image_source_zarr-1.30.2.dev4}/PKG-INFO +3 -3
  2. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr/__init__.py +31 -204
  3. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr.egg-info/PKG-INFO +3 -3
  4. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr.egg-info/requires.txt +2 -2
  5. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/LICENSE +0 -0
  6. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/README.rst +0 -0
  7. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr/girder_source.py +0 -0
  8. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr.egg-info/SOURCES.txt +0 -0
  9. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr.egg-info/dependency_links.txt +0 -0
  10. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr.egg-info/entry_points.txt +0 -0
  11. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/large_image_source_zarr.egg-info/top_level.txt +0 -0
  12. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/pyproject.toml +0 -0
  13. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/setup.cfg +0 -0
  14. {large_image_source_zarr-1.30.2 → large_image_source_zarr-1.30.2.dev4}/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.2
3
+ Version: 1.30.2.dev4
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.2
22
+ Requires-Dist: large-image>=1.30.2.dev4
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.2; extra == "girder"
27
+ Requires-Dist: girder-large-image>=1.30.2.dev4; extra == "girder"
28
28
  Provides-Extra: all
29
29
  Requires-Dist: large-image-converter; extra == "all"
30
30
 
@@ -98,9 +98,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
98
98
  self._largeImagePath = str(self._getLargeImagePath())
99
99
  self._zarr = None
100
100
  self._editable = False
101
- self._frameValues = None
102
- self._frameAxes = None
103
- self._frameUnits = None
104
101
  if not os.path.isfile(self._largeImagePath) and '//:' not in self._largeImagePath:
105
102
  raise TileSourceFileNotFoundError(self._largeImagePath) from None
106
103
  try:
@@ -155,9 +152,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
155
152
  self._imageDescription = None
156
153
  self._levels = []
157
154
  self._associatedImages = {}
158
- self._frameValues = None
159
- self._frameAxes = None
160
- self._frameUnits = None
161
155
 
162
156
  def __del__(self):
163
157
  if not hasattr(self, '_derivedSource'):
@@ -224,10 +218,10 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
224
218
  tuple that is used to find the maximum size array, preferring ome
225
219
  arrays, then total pixels, then channels. 'is_ome' is a boolean.
226
220
  'series' is a list of the found groups and arrays that match the
227
- best criteria. 'axes', 'axes_values', 'axes_units', and 'channels'
228
- are from the best array. 'associated' is a list of all groups and
229
- arrays that might be associated images. These have to be culled
230
- for the actual groups used in the series.
221
+ best criteria. 'axes' and 'channels' are from the best array.
222
+ 'associated' is a list of all groups and arrays that might be
223
+ associated images. These have to be culled for the actual groups
224
+ used in the series.
231
225
  """
232
226
  attrs = group.attrs.asdict() if group is not None else {}
233
227
  min_version = packaging.version.Version('0.4')
@@ -239,19 +233,9 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
239
233
  all(packaging.version.Version(m['version']) >= min_version
240
234
  for m in attrs['multiscales'] if 'version' in m))
241
235
  channels = None
242
- axes_values = None
243
- axes_units = None
244
236
  if is_ome:
245
237
  axes = {axis['name']: idx for idx, axis in enumerate(
246
238
  attrs['multiscales'][0]['axes'])}
247
- axes_values = {
248
- axis['name']: axis.get('values')
249
- for axis in attrs['multiscales'][0]['axes']
250
- }
251
- axes_units = {
252
- axis['name']: axis.get('unit')
253
- for axis in attrs['multiscales'][0]['axes']
254
- }
255
239
  if isinstance(attrs['omero'].get('channels'), list):
256
240
  channels = [channel['label'] for channel in attrs['omero']['channels']]
257
241
  if all(channel.startswith('Channel ') for channel in channels):
@@ -270,8 +254,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
270
254
  results['series'] = [(group, arr)]
271
255
  results['is_ome'] = is_ome
272
256
  results['axes'] = axes
273
- results['axes_values'] = axes_values
274
- results['axes_units'] = axes_units
275
257
  results['channels'] = channels
276
258
  elif check == results['best']:
277
259
  results['series'].append((group, arr))
@@ -351,44 +333,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
351
333
  except Exception:
352
334
  pass
353
335
 
354
- def _readFrameValues(self, found, baseArray):
355
- """
356
- Populate frame values and frame units from image metadata.
357
- """
358
- axes_values = found.get('axes_values')
359
- axes_units = found.get('axes_units')
360
- if isinstance(axes_values, dict):
361
- self._frameAxes = [
362
- a for a, i in sorted(self._axes.items(), key=lambda x: x[1])
363
- if axes_values.get(a) is not None
364
- ]
365
- self._frameUnits = {k: axes_units.get(k) for k in self.frameAxes if k in axes_units}
366
- frame_values_shape = [baseArray.shape[self._axes[a]] for a in self.frameAxes]
367
- frame_values_shape.append(len(frame_values_shape))
368
- frame_values = np.empty(frame_values_shape, dtype=object)
369
- all_frame_specs = self.getMetadata().get('frames')
370
- for axis, values in axes_values.items():
371
- if axis in self.frameAxes:
372
- slicing = [slice(None) for i in range(len(frame_values_shape))]
373
- axis_index = self.frameAxes.index(axis)
374
- slicing[-1] = axis_index
375
- if len(values) == frame_values_shape[axis_index]:
376
- # uniform values have same length as axis
377
- for i, value in enumerate(values):
378
- slicing[axis_index] = i
379
- frame_values[tuple(slicing)] = value
380
- elif len(values) == self._framecount:
381
- # non-uniform values have a value for every frame
382
- for i, value in enumerate(values):
383
- if all_frame_specs and len(all_frame_specs) > i:
384
- for k, j in all_frame_specs[i].items():
385
- if 'Index' in k:
386
- name = k.replace('Index', '').lower()
387
- if name:
388
- slicing[self._frameAxes.index(name)] = j
389
- frame_values[tuple(slicing)] = value
390
- self._frameValues = frame_values
391
-
392
336
  def _validateZarr(self):
393
337
  """
394
338
  Validate that we can read tiles from the zarr parent group in
@@ -403,11 +347,7 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
403
347
  self._series = found['series']
404
348
  baseGroup, baseArray = self._series[0]
405
349
  self._is_ome = found['is_ome']
406
- self._axes = {
407
- k.lower(): v
408
- for k, v in found['axes'].items()
409
- if baseArray.shape[v] > 1 or k in found.get('axes_values', {})
410
- }
350
+ self._axes = {k.lower(): v for k, v in found['axes'].items() if baseArray.shape[v] > 1}
411
351
  if len(self._series) > 1 and 'xy' in self._axes:
412
352
  msg = 'Conflicting xy axis data.'
413
353
  raise TileSourceError(msg)
@@ -446,10 +386,8 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
446
386
  stride = 1
447
387
  self._strides = {}
448
388
  self._axisCounts = {}
449
- for _, k in sorted(
450
- (-self._axes.get(k, 'tzc'.index(k) if k in 'tzc' else -1), k)
451
- for k in self._axes if k not in 'xys'
452
- ):
389
+ for _, k in sorted((-'tzc'.index(k) if k in 'tzc' else 1, k)
390
+ for k in self._axes if k not in 'xys'):
453
391
  self._strides[k] = stride
454
392
  self._axisCounts[k] = baseArray.shape[self._axes[k]]
455
393
  stride *= baseArray.shape[self._axes[k]]
@@ -458,7 +396,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
458
396
  self._axisCounts['xy'] = len(self._series)
459
397
  stride *= len(self._series)
460
398
  self._framecount = stride
461
- self._readFrameValues(found, baseArray)
462
399
 
463
400
  def _nonemptyLevelsList(self, frame=0):
464
401
  """
@@ -510,16 +447,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
510
447
  for axis in self._strides:
511
448
  frame['Index' + axis.upper()] = (
512
449
  idx // self._strides[axis]) % self._axisCounts[axis]
513
- if self.frameValues is not None and self.frameAxes is not None:
514
- current_frame_slice = tuple(
515
- frame['Index' + axis.upper()] for axis in self.frameAxes
516
- )
517
- current_frame_values = self.frameValues[current_frame_slice]
518
- for i, axis in enumerate(self.frameAxes):
519
- value = current_frame_values[i]
520
- # ensure that values are returned as native python types
521
- native_value = getattr(value, 'tolist', lambda v=value: v)()
522
- frame['Value' + axis.upper()] = native_value
523
450
  frames.append(frame)
524
451
  self._addMetadataFrameInformation(result, getattr(self, '_channels', None))
525
452
  return result
@@ -669,11 +596,7 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
669
596
  placement = {
670
597
  'x': x,
671
598
  'y': y,
672
- **{k: v for k, v in kwargs.items() if not k.endswith('_value')},
673
- }
674
- frame_values = {
675
- k.replace('_value', ''): v for k, v in kwargs.items()
676
- if k not in placement
599
+ **kwargs,
677
600
  }
678
601
  tile, mask, placement, axes = self._validateNewTile(tile, mask, placement, axes)
679
602
 
@@ -692,26 +615,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
692
615
  for i, a in enumerate(axes)
693
616
  ])
694
617
 
695
- if len(frame_values.keys()) > 0:
696
- # 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)
714
-
715
618
  current_arrays = dict(self._zarr.arrays())
716
619
  if store_path == '0':
717
620
  # if writing to base data, invalidate generated levels
@@ -789,48 +692,7 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
789
692
  )
790
693
  self._associatedImages[imageKey] = (group, arr)
791
694
 
792
- def _getAxisInternalMetadata(self, axis_name):
793
- """
794
- Get the metadata structure describing an axis in the image.
795
- This will be written to the image metadata.
796
-
797
- :param axis_name: a string corresponding to an axis in the image
798
- :returns: a dictionary describing the target axis
799
- """
800
- axis_metadata = {'name': axis_name}
801
- if axis_name in ['x', 'y']:
802
- axis_metadata['type'] = 'space'
803
- axis_metadata['unit'] = 'millimeter'
804
- elif axis_name in ['s', 'c']:
805
- axis_metadata['type'] = 'channel'
806
- if self.frameAxes is not None:
807
- axis_index = self.frameAxes.index(axis_name) if axis_name in self.frameAxes else None
808
- if axis_index is not None and self.frameValues is not None:
809
- all_frame_values = self.frameValues[..., axis_index]
810
- split = np.split(
811
- all_frame_values,
812
- all_frame_values.shape[axis_index],
813
- axis=axis_index,
814
- )
815
- uniform = all(len(np.unique(
816
- # convert all values to strings for mixed type comparison with np.unique
817
- (a[np.not_equal(a, None)]).astype(str),
818
- )) == 1 for a in split)
819
- if uniform:
820
- values = [a.flat[0] for a in split]
821
- else:
822
- values = all_frame_values.flatten().tolist()
823
- axis_metadata['values'] = values
824
- unit = self.frameUnits.get(axis_name) if self.frameUnits is not None else None
825
- if unit is not None:
826
- axis_metadata['unit'] = unit
827
- return axis_metadata
828
-
829
695
  def _writeInternalMetadata(self):
830
- """
831
- Write metadata to Zarr attributes.
832
- Metadata structure adheres to OME schema from https://ngff.openmicroscopy.org/latest/
833
- """
834
696
  self._checkEditable()
835
697
  with self._threadLock and self._processLock:
836
698
  name = str(self._tempdir.name).split('/')[-1]
@@ -855,11 +717,17 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
855
717
  }
856
718
  datasets.append(dataset_metadata)
857
719
  for a in sorted_axes:
858
- if a == 't':
720
+ axis_metadata = {'name': a}
721
+ if a in ['x', 'y']:
722
+ axis_metadata['type'] = 'space'
723
+ axis_metadata['unit'] = 'millimeter'
724
+ elif a in ['s', 'c']:
725
+ axis_metadata['type'] = 'channel'
726
+ elif a == 't':
859
727
  rdefs['defaultT'] = 0
860
728
  elif a == 'z':
861
729
  rdefs['defaultZ'] = 0
862
- axes.append(self._getAxisInternalMetadata(a))
730
+ axes.append(axis_metadata)
863
731
  if channel_axis is not None and len(arrays) > 0:
864
732
  base_array = list(arrays.values())[0]
865
733
  base_shape = base_array.shape
@@ -872,21 +740,21 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
872
740
  'inverted': False,
873
741
  'label': f'Band {c + 1}',
874
742
  }
875
- # slicing = tuple(
876
- # slice(None)
877
- # if k != ('c' if 'c' in self._axes else 's')
878
- # else c
879
- # for k, v in self._axes.items()
880
- # )
881
- # channel_data = base_array[slicing]
882
- # channel_min = np.min(channel_data)
883
- # channel_max = np.max(channel_data)
884
- # channel_metadata['window'] = {
885
- # 'end': channel_max,
886
- # 'max': channel_max,
887
- # 'min': channel_min,
888
- # 'start': channel_min,
889
- # }
743
+ slicing = tuple(
744
+ slice(None)
745
+ if k != ('c' if 'c' in self._axes else 's')
746
+ else c
747
+ for k, v in self._axes.items()
748
+ )
749
+ channel_data = base_array[slicing]
750
+ channel_min = np.min(channel_data)
751
+ channel_max = np.max(channel_data)
752
+ channel_metadata['window'] = {
753
+ 'end': channel_max,
754
+ 'max': channel_max,
755
+ 'min': channel_min,
756
+ 'start': channel_min,
757
+ }
890
758
  if len(self._channelNames) > c:
891
759
  channel_metadata['label'] = self._channelNames[c]
892
760
  if len(self._channelColors) > c:
@@ -994,47 +862,6 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
994
862
  self._checkEditable()
995
863
  self._channelColors = colors
996
864
 
997
- @property
998
- def frameAxes(self):
999
- return self._frameAxes
1000
-
1001
- @frameAxes.setter
1002
- def frameAxes(self, axes):
1003
- self._checkEditable()
1004
- self._frameAxes = axes
1005
-
1006
- @property
1007
- def frameUnits(self):
1008
- return self._frameUnits
1009
-
1010
- @frameUnits.setter
1011
- def frameUnits(self, units):
1012
- self._checkEditable()
1013
- if self.frameAxes is None:
1014
- err = 'frameAxes must be set first with a list of frame axis names.'
1015
- raise ValueError(err)
1016
- if not isinstance(units, dict) or not all(
1017
- k in self.frameAxes for k in units.keys()
1018
- ):
1019
- err = 'frameUnits must be a dictionary with keys that exist in frameAxes.'
1020
- raise ValueError(err)
1021
- self._frameUnits = units
1022
-
1023
- @property
1024
- def frameValues(self):
1025
- return self._frameValues
1026
-
1027
- @frameValues.setter
1028
- def frameValues(self, a):
1029
- self._checkEditable()
1030
- if self.frameAxes is None:
1031
- err = 'frameAxes must be set first with a list of frame axis names.'
1032
- raise ValueError(err)
1033
- if len(a.shape) != len(self.frameAxes) + 1:
1034
- err = f'frameValues must have {len(self.frameAxes) + 1} dimensions.'
1035
- raise ValueError(err)
1036
- self._frameValues = a
1037
-
1038
865
  def _generateDownsampledLevels(self, resample_method):
1039
866
  self._checkEditable()
1040
867
  current_arrays = dict(self._zarr.arrays())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: large-image-source-zarr
3
- Version: 1.30.2
3
+ Version: 1.30.2.dev4
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.2
22
+ Requires-Dist: large-image>=1.30.2.dev4
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.2; extra == "girder"
27
+ Requires-Dist: girder-large-image>=1.30.2.dev4; 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.2
1
+ large-image>=1.30.2.dev4
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.2
10
+ girder-large-image>=1.30.2.dev4