large-image-source-zarr 1.32.4.dev4__tar.gz → 1.32.4.dev5__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.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/PKG-INFO +3 -3
  2. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr/__init__.py +115 -22
  3. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr.egg-info/PKG-INFO +3 -3
  4. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr.egg-info/requires.txt +2 -2
  5. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/LICENSE +0 -0
  6. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/README.rst +0 -0
  7. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr/girder_source.py +0 -0
  8. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr.egg-info/SOURCES.txt +0 -0
  9. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr.egg-info/dependency_links.txt +0 -0
  10. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr.egg-info/entry_points.txt +0 -0
  11. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/large_image_source_zarr.egg-info/top_level.txt +0 -0
  12. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/pyproject.toml +0 -0
  13. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/setup.cfg +0 -0
  14. {large_image_source_zarr-1.32.4.dev4 → large_image_source_zarr-1.32.4.dev5}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: large-image-source-zarr
3
- Version: 1.32.4.dev4
3
+ Version: 1.32.4.dev5
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.
@@ -18,12 +18,12 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Requires-Python: >=3.6
19
19
  Description-Content-Type: text/x-rst
20
20
  License-File: LICENSE
21
- Requires-Dist: large-image>=1.32.4.dev4
21
+ Requires-Dist: large-image>=1.32.4.dev5
22
22
  Requires-Dist: zarr<3
23
23
  Requires-Dist: numcodecs<0.16
24
24
  Requires-Dist: imagecodecs-numcodecs!=2024.9.22
25
25
  Provides-Extra: girder
26
- Requires-Dist: girder-large-image>=1.32.4.dev4; extra == "girder"
26
+ Requires-Dist: girder-large-image>=1.32.4.dev5; extra == "girder"
27
27
  Provides-Extra: all
28
28
  Requires-Dist: large-image-converter; extra == "all"
29
29
  Dynamic: author
@@ -165,6 +165,8 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
165
165
  self._frameValues = None
166
166
  self._frameAxes = None
167
167
  self._frameUnits = None
168
+ self._projection = None
169
+ self._gcps = None
168
170
  if not self._created:
169
171
  try:
170
172
  self._validateZarr()
@@ -911,31 +913,33 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
911
913
  with self._threadLock and self._processLock:
912
914
  name = str(self._tempdir.name).split('/')[-1]
913
915
  arrays = dict(self._zarr.arrays())
914
- channel_axis = self._axes.get('c', self._axes.get('s'))
915
916
  datasets = []
916
917
  axes = []
917
918
  channels = []
918
- rdefs = {'model': 'color' if len(self._channelColors) else 'greyscale'}
919
- sorted_axes = [a[0] for a in sorted(self._axes.items(), key=lambda item: item[1])]
920
- for arr_name in arrays:
921
- level = int(arr_name)
922
- scale = [1.0 for a in sorted_axes]
923
- scale[self._axes.get('x')] = (self._mm_x or 0) * (2 ** level)
924
- scale[self._axes.get('y')] = (self._mm_y or 0) * (2 ** level)
925
- dataset_metadata = {
926
- 'path': arr_name,
927
- 'coordinateTransformations': [{
928
- 'type': 'scale',
929
- 'scale': scale,
930
- }],
931
- }
932
- datasets.append(dataset_metadata)
933
- for a in sorted_axes:
934
- if a == 't':
935
- rdefs['defaultT'] = 0
936
- elif a == 'z':
937
- rdefs['defaultZ'] = 0
938
- axes.append(self._getAxisInternalMetadata(a))
919
+ channel_axis = rdefs = None
920
+ if hasattr(self, '_axes'):
921
+ channel_axis = self._axes.get('c', self._axes.get('s'))
922
+ rdefs = {'model': 'color' if len(self._channelColors) else 'greyscale'}
923
+ sorted_axes = [a[0] for a in sorted(self._axes.items(), key=lambda item: item[1])]
924
+ for arr_name in arrays:
925
+ level = int(arr_name)
926
+ scale = [1.0 for a in sorted_axes]
927
+ scale[self._axes.get('x')] = (self._mm_x or 0) * (2 ** level)
928
+ scale[self._axes.get('y')] = (self._mm_y or 0) * (2 ** level)
929
+ dataset_metadata = {
930
+ 'path': arr_name,
931
+ 'coordinateTransformations': [{
932
+ 'type': 'scale',
933
+ 'scale': scale,
934
+ }],
935
+ }
936
+ datasets.append(dataset_metadata)
937
+ for a in sorted_axes:
938
+ if a == 't':
939
+ rdefs['defaultT'] = 0
940
+ elif a == 'z':
941
+ rdefs['defaultZ'] = 0
942
+ axes.append(self._getAxisInternalMetadata(a))
939
943
  if channel_axis is not None and len(arrays) > 0:
940
944
  base_array = list(arrays.values())[0]
941
945
  base_shape = base_array.shape
@@ -1183,6 +1187,76 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
1183
1187
  self._frameValues = a
1184
1188
  self._writeInternalMetadata()
1185
1189
 
1190
+ @property
1191
+ def projection(self):
1192
+ return self._projection
1193
+
1194
+ @projection.setter
1195
+ def projection(self, proj):
1196
+ import pyproj
1197
+
1198
+ self._checkEditable()
1199
+ try:
1200
+ pyproj.CRS.from_string(str(proj))
1201
+ except Exception as e:
1202
+ msg = f'Invalid projection value. Cannot be interpreted by pyproj: {str(e)}'
1203
+ raise TileSourceError(msg)
1204
+ self._projection = proj
1205
+ self._writeInternalMetadata()
1206
+
1207
+ @property
1208
+ def gcps(self):
1209
+ return self._gcps
1210
+
1211
+ @gcps.setter
1212
+ def gcps(self, gcps):
1213
+ self._checkEditable()
1214
+ if isinstance(gcps, str):
1215
+ gcps = list(zip(*[iter(gcps.split())] * 4))
1216
+ if (isinstance(gcps, list) or isinstance(gcps, tuple)):
1217
+ gcps = [
1218
+ [float(v) for v in gcp.split()]
1219
+ if isinstance(gcp, str) else gcp
1220
+ for gcp in gcps
1221
+ ]
1222
+ if any(
1223
+ not isinstance(gcp, list) and not isinstance(gcp, tuple)
1224
+ for gcp in gcps
1225
+ ):
1226
+ msg = 'Each GCP must be specified as a list, tuple, or space-separated string.'
1227
+ raise TileSourceError(msg)
1228
+ if any(len(gcp) != 4 for gcp in gcps):
1229
+ msg = (
1230
+ 'Each GCP must contain four values: '
1231
+ '[projected_x, projected_y, pixel_x, pixel_y].'
1232
+ )
1233
+ raise TileSourceError(msg)
1234
+ unique_gcps = []
1235
+ dup_gcps = []
1236
+ for gcp in gcps:
1237
+ if not any(
1238
+ u[0:2] == gcp[0:2] or u[2:4] == gcp[2:4]
1239
+ for u in unique_gcps
1240
+ ):
1241
+ unique_gcps.append(gcp)
1242
+ else:
1243
+ dup_gcps.append(gcp)
1244
+ gcps = unique_gcps
1245
+ if len(dup_gcps):
1246
+ msg = (
1247
+ f'Removed duplicate GCPs {dup_gcps} from list; shared projected '
1248
+ 'coordinate or pixel coordinate with another GCP.'
1249
+ )
1250
+ warnings.warn(msg, stacklevel=2)
1251
+ if len(gcps) < 2:
1252
+ msg = 'Must specify at least 2 unique GCPs.'
1253
+ raise TileSourceError(msg)
1254
+ else:
1255
+ msg = 'GCPs must be specified as a list, tuple, or space-separated string.'
1256
+ raise TileSourceError(msg)
1257
+ self._gcps = gcps
1258
+ self._writeInternalMetadata()
1259
+
1186
1260
  def _generateDownsampledLevels(self, resample_method):
1187
1261
  self._checkEditable()
1188
1262
  current_arrays = dict(self._zarr.arrays())
@@ -1249,6 +1323,23 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
1249
1323
  )
1250
1324
  self._validateZarr() # refresh self._levels before continuing
1251
1325
 
1326
+ def _applyGeoReferencing(self, path):
1327
+ if self.projection and not self.gcps:
1328
+ msg = (
1329
+ 'Projection was specified but GCPs were not specified. '
1330
+ 'Cannot write georeferenced file.'
1331
+ )
1332
+ raise TileSourceError(msg)
1333
+ import tifftools
1334
+
1335
+ setlist = []
1336
+ if self.projection is not None:
1337
+ setlist.append(('projection', self.projection))
1338
+ if self.gcps is not None and len(self.gcps):
1339
+ setlist.append(('gcps', self.gcps))
1340
+
1341
+ tifftools.tiff_set(path, setlist=setlist, overwrite=True)
1342
+
1252
1343
  def write(
1253
1344
  self,
1254
1345
  path,
@@ -1355,6 +1446,8 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
1355
1446
  params.update(converterParams)
1356
1447
  convert(str(attrs_path), path, overwrite=overwriteAllowed, **params)
1357
1448
 
1449
+ self._applyGeoReferencing(path)
1450
+
1358
1451
 
1359
1452
  def open(*args, **kwargs):
1360
1453
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: large-image-source-zarr
3
- Version: 1.32.4.dev4
3
+ Version: 1.32.4.dev5
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.
@@ -18,12 +18,12 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Requires-Python: >=3.6
19
19
  Description-Content-Type: text/x-rst
20
20
  License-File: LICENSE
21
- Requires-Dist: large-image>=1.32.4.dev4
21
+ Requires-Dist: large-image>=1.32.4.dev5
22
22
  Requires-Dist: zarr<3
23
23
  Requires-Dist: numcodecs<0.16
24
24
  Requires-Dist: imagecodecs-numcodecs!=2024.9.22
25
25
  Provides-Extra: girder
26
- Requires-Dist: girder-large-image>=1.32.4.dev4; extra == "girder"
26
+ Requires-Dist: girder-large-image>=1.32.4.dev5; extra == "girder"
27
27
  Provides-Extra: all
28
28
  Requires-Dist: large-image-converter; extra == "all"
29
29
  Dynamic: author
@@ -1,4 +1,4 @@
1
- large-image>=1.32.4.dev4
1
+ large-image>=1.32.4.dev5
2
2
  zarr<3
3
3
  numcodecs<0.16
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.32.4.dev4
10
+ girder-large-image>=1.32.4.dev5