large-image-source-ometiff 1.27.5.dev6__py3-none-any.whl → 1.30.7.dev12__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -105,6 +105,7 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
105
105
  msg = 'Not a recognized OME Tiff'
106
106
  raise TileSourceError(msg)
107
107
  info = getattr(base, '_description_record', None)
108
+ self._associatedImages = {}
108
109
  if not info or not info.get('OME'):
109
110
  msg = 'Not an OME Tiff'
110
111
  raise TileSourceError(msg)
@@ -115,6 +116,7 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
115
116
  except KeyError:
116
117
  msg = 'Not a recognized OME Tiff'
117
118
  raise TileSourceError(msg)
119
+ usesSubIfds = self._checkForSubIfds(base)
118
120
  omeimages = [
119
121
  entry['Pixels'] for entry in self._omeinfo['Image'] if
120
122
  len(entry['Pixels']['TiffData']) == len(self._omebase['TiffData'])]
@@ -125,10 +127,16 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
125
127
  omebylevel = dict(zip(levels, omeimages))
126
128
  self._omeLevels = [omebylevel.get(key) for key in range(max(omebylevel.keys()) + 1)]
127
129
  if base._tiffInfo.get('istiled'):
130
+ if usesSubIfds:
131
+ self._omeLevels = [None] * max(usesSubIfds) + [self._omeLevels[-1]]
128
132
  self._tiffDirectories = [
129
133
  self.getTiffDir(int(entry['TiffData'][0].get('IFD', 0)))
130
134
  if entry else None
131
135
  for entry in self._omeLevels]
136
+ if usesSubIfds:
137
+ for lvl in usesSubIfds:
138
+ if self._tiffDirectories[lvl] is None:
139
+ self._tiffDirectories[lvl] = False
132
140
  else:
133
141
  self._tiffDirectories = [
134
142
  self.getTiffDir(0, mustBeTiled=None)
@@ -149,7 +157,6 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
149
157
  # We can get the embedded images, but we don't currently use non-tiled
150
158
  # images as associated images. This would require enumerating tiff
151
159
  # directories not mentioned by the ome list.
152
- self._associatedImages = {}
153
160
  self._checkForInefficientDirectories()
154
161
 
155
162
  def _checkForOMEZLoop(self):
@@ -199,10 +206,47 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
199
206
  info['Image']['Pixels']['PlanesFromZloop'] = 'true'
200
207
  info['Image']['Pixels']['SizeZ'] = str(zloop)
201
208
 
209
+ def _checkForSubIfds(self, base):
210
+ """
211
+ Check if the first ifd has sub-ifds. If so, expect lower resolutions
212
+ to be in subifds, not in primary ifds.
213
+
214
+ :param base: base tiff directory
215
+ :returns: either False if no subifds are lower resolution, or a
216
+ dictionary of levels (keys) and values that are subifd numbers.
217
+ """
218
+ try:
219
+ levels = int(max(0, math.ceil(max(
220
+ math.log(float(base.imageWidth) / base.tileWidth),
221
+ math.log(float(base.imageHeight) / base.tileHeight)) / math.log(2))) + 1)
222
+ filled = {}
223
+ for z in range(levels - 2, -1, -1):
224
+ subdir = levels - 1 - z
225
+ scale = int(2 ** subdir)
226
+ try:
227
+ dir = self.getTiffDir(0, mustBeTiled=True, subDirectoryNum=subdir)
228
+ except Exception:
229
+ continue
230
+ if (dir is not None and
231
+ (dir.tileWidth in {base.tileWidth, dir.imageWidth}) and
232
+ (dir.tileHeight in {base.tileHeight, dir.imageHeight}) and
233
+ abs(dir.imageWidth * scale - base.imageWidth) <= scale and
234
+ abs(dir.imageHeight * scale - base.imageHeight) <= scale):
235
+ filled[z] = subdir
236
+ if not len(filled):
237
+ return False
238
+ filled[levels - 1] = 0
239
+ return filled
240
+ except TiffError:
241
+ return False
242
+
202
243
  def _parseOMEInfo(self): # noqa
203
244
  if isinstance(self._omeinfo['Image'], dict):
204
245
  self._omeinfo['Image'] = [self._omeinfo['Image']]
205
246
  for img in self._omeinfo['Image']:
247
+ if isinstance(img['Pixels'], list):
248
+ msg = 'OME Tiff has multiple pixels'
249
+ raise TileSourceError(msg)
206
250
  if isinstance(img['Pixels'].get('TiffData'), dict):
207
251
  img['Pixels']['TiffData'] = [img['Pixels']['TiffData']]
208
252
  if isinstance(img['Pixels'].get('Plane'), dict):
@@ -241,6 +285,32 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
241
285
  for entry in self._omebase['TiffData']}) > 1:
242
286
  msg = 'OME Tiff references multiple files'
243
287
  raise TileSourceError(msg)
288
+ if (len(self._omebase['TiffData']) ==
289
+ int(self._omebase['SizeT']) * int(self._omebase['SizeZ'])):
290
+ self._omebase['SizeC'] = 1
291
+ for img in self._omeinfo['Image'][1:]:
292
+ try:
293
+ if img['Name'] and img['Pixels']['TiffData'][0]['IFD']:
294
+ self._addAssociatedImage(
295
+ int(img['Pixels']['TiffData'][0]['IFD']),
296
+ None, None, img['Name'].split()[0])
297
+ except Exception:
298
+ pass
299
+ elif len(self._omeinfo['Image']) > 1:
300
+ multiple = False
301
+ for img in self._omeinfo['Image'][1:]:
302
+ try:
303
+ bpix = self._omeinfo['Image'][0]['Pixels']
304
+ imgpix = img['Pixels']
305
+ if imgpix['SizeX'] == bpix['SizeX'] and imgpix['SizeY'] == bpix['SizeY']:
306
+ multiple = True
307
+ break
308
+ except Exception:
309
+ multiple = True
310
+ if multiple:
311
+ # We should handle this as SizeXY
312
+ msg = 'OME Tiff references multiple images'
313
+ raise TileSourceError(msg)
244
314
  if (len(self._omebase['TiffData']) != int(self._omebase['SizeC']) *
245
315
  int(self._omebase['SizeT']) * int(self._omebase['SizeZ']) or
246
316
  len(self._omebase['TiffData']) != len(
@@ -343,8 +413,8 @@ class OMETiffFileTileSource(TiffFileTileSource, metaclass=LruCacheMetaclass):
343
413
  if subdir:
344
414
  scale = int(2 ** subdir)
345
415
  if (dir is None or
346
- (dir.tileWidth != self.tileWidth and dir.tileWidth != dir.imageWidth) or
347
- (dir.tileHeight != self.tileHeight and dir.tileHeight != dir.imageHeight) or
416
+ (dir.tileWidth not in {self.tileWidth, dir.imageWidth}) or
417
+ (dir.tileHeight not in {self.tileHeight, dir.imageHeight}) or
348
418
  abs(dir.imageWidth * scale - self.sizeX) > scale or
349
419
  abs(dir.imageHeight * scale - self.sizeY) > scale):
350
420
  return super().getTile(
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: large-image-source-ometiff
3
- Version: 1.27.5.dev6
3
+ Version: 1.30.7.dev12
4
4
  Summary: An OMETiff tilesource for large_image.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -15,12 +15,26 @@ Classifier: Programming Language :: Python :: 3.9
15
15
  Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
18
19
  Requires-Python: >=3.8
20
+ Description-Content-Type: text/x-rst
19
21
  License-File: LICENSE
20
- Requires-Dist: large-image >=1.27.5.dev6
21
- Requires-Dist: large-image-source-tiff >=1.27.5.dev6
22
+ Requires-Dist: large-image>=1.30.7.dev12
23
+ Requires-Dist: large-image-source-tiff>=1.30.7.dev12
22
24
  Provides-Extra: girder
23
- Requires-Dist: girder-large-image >=1.27.5.dev6 ; extra == 'girder'
25
+ Requires-Dist: girder-large-image>=1.30.7.dev12; extra == "girder"
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: provides-extra
35
+ Dynamic: requires-dist
36
+ Dynamic: requires-python
37
+ Dynamic: summary
24
38
 
25
39
  An OMETiff tilesource for large_image.
26
40
 
@@ -0,0 +1,8 @@
1
+ large_image_source_ometiff/__init__.py,sha256=r3Ii965r6Y8m9D7eRnYmyG58aLkXyXULMIv8XV9Y_lQ,20634
2
+ large_image_source_ometiff/girder_source.py,sha256=QotYLsC_JY3pOixVOXZ_wwtHJABSuWw_f_8Q5pDnNWo,1047
3
+ large_image_source_ometiff-1.30.7.dev12.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
4
+ large_image_source_ometiff-1.30.7.dev12.dist-info/METADATA,sha256=SoWIIh7cakdNmptH0fo6msVPd7S2_z4v3NGCsIxpZfo,1381
5
+ large_image_source_ometiff-1.30.7.dev12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
6
+ large_image_source_ometiff-1.30.7.dev12.dist-info/entry_points.txt,sha256=-xiaxFJTzRayHYwLkPsBXF0grk8j5nQy5cizSazP404,184
7
+ large_image_source_ometiff-1.30.7.dev12.dist-info/top_level.txt,sha256=Me0pziNZRmyYLdGAKu9zgDHHINn_7ayKLLYxTGXv5lo,27
8
+ large_image_source_ometiff-1.30.7.dev12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,8 +0,0 @@
1
- large_image_source_ometiff/__init__.py,sha256=ufxVdvDPSk1QwoIBSAyfwB6EHI78FnDnQPqO9Lx1PYU,17350
2
- large_image_source_ometiff/girder_source.py,sha256=QotYLsC_JY3pOixVOXZ_wwtHJABSuWw_f_8Q5pDnNWo,1047
3
- large_image_source_ometiff-1.27.5.dev6.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
4
- large_image_source_ometiff-1.27.5.dev6.dist-info/METADATA,sha256=eUR9Pnq1KdvrtXNhnpd6L1Xqsxwp7iLaAm1Y_MHL6hM,1037
5
- large_image_source_ometiff-1.27.5.dev6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- large_image_source_ometiff-1.27.5.dev6.dist-info/entry_points.txt,sha256=-xiaxFJTzRayHYwLkPsBXF0grk8j5nQy5cizSazP404,184
7
- large_image_source_ometiff-1.27.5.dev6.dist-info/top_level.txt,sha256=Me0pziNZRmyYLdGAKu9zgDHHINn_7ayKLLYxTGXv5lo,27
8
- large_image_source_ometiff-1.27.5.dev6.dist-info/RECORD,,