large-image-source-tifffile 1.28.3.dev2__py3-none-any.whl → 1.30.7.dev10__py3-none-any.whl

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.
@@ -7,7 +7,6 @@ from importlib.metadata import PackageNotFoundError
7
7
  from importlib.metadata import version as _importlib_version
8
8
 
9
9
  import numpy as np
10
- import zarr
11
10
 
12
11
  import large_image
13
12
  from large_image.cache_util import LruCacheMetaclass, methodcache
@@ -16,6 +15,7 @@ from large_image.exceptions import TileSourceError, TileSourceFileNotFoundError
16
15
  from large_image.tilesource import FileTileSource
17
16
 
18
17
  tifffile = None
18
+ zarr = None
19
19
 
20
20
  try:
21
21
  __version__ = _importlib_version(__name__)
@@ -37,6 +37,7 @@ def _lazyImport():
37
37
  module initialization because it is slow.
38
38
  """
39
39
  global tifffile
40
+ global zarr
40
41
 
41
42
  if tifffile is None:
42
43
  try:
@@ -55,6 +56,8 @@ def _lazyImport():
55
56
  logging.getLogger('tifffile.tifffile').addHandler(checkForMissingDataHandler())
56
57
  logging.getLogger('tifffile').setLevel(logging.WARNING)
57
58
  logging.getLogger('tifffile').addHandler(checkForMissingDataHandler())
59
+ if zarr is None:
60
+ import zarr
58
61
 
59
62
 
60
63
  def et_findall(tag, text):
@@ -180,7 +183,7 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
180
183
  ex = 'no maximum series'
181
184
  try:
182
185
  for idx, s in enumerate(self._tf.series):
183
- samples = np.prod(s.shape)
186
+ samples = math.prod(s.shape)
184
187
  if samples > maxsamples and 'X' in s.axes and 'Y' in s.axes:
185
188
  maxseries = idx
186
189
  maxsamples = samples
@@ -229,7 +232,7 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
229
232
  'sizeX': s.shape[s.axes.index('X')], 'sizeY': s.shape[s.axes.index('Y')]})
230
233
  self.sizeX = max(self.sizeX, s.shape[s.axes.index('X')])
231
234
  self.sizeY = max(self.sizeY, s.shape[s.axes.index('Y')])
232
- self._framecount = len(self._series) * np.prod(tuple(
235
+ self._framecount = len(self._series) * math.prod(tuple(
233
236
  1 if base.axes[sidx] in 'YXS' else v for sidx, v in enumerate(base.shape)))
234
237
  self._basis = {}
235
238
  basis = 1
@@ -256,14 +259,17 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
256
259
  for p in self._tf.pages:
257
260
  if (p not in pagesInSeries and getattr(p, 'keyframe', None) is not None and
258
261
  p.hash not in hashes and not len(set(p.axes) - set('YXS'))):
259
- id = 'image_%s' % p.index
260
- entry = {'page': p.index}
261
- entry['width'] = p.shape[p.axes.index('X')]
262
- entry['height'] = p.shape[p.axes.index('Y')]
263
- if (id not in self._associatedImages and
264
- max(entry['width'], entry['height']) <= self._maxAssociatedImageSize and
265
- max(entry['width'], entry['height']) >= self._minAssociatedImageSize):
266
- self._associatedImages[id] = entry
262
+ try:
263
+ id = 'image_%s' % p.index
264
+ entry = {'page': p.index}
265
+ entry['width'] = p.shape[p.axes.index('X')]
266
+ entry['height'] = p.shape[p.axes.index('Y')]
267
+ if (id not in self._associatedImages and
268
+ max(entry['width'], entry['height']) <= self._maxAssociatedImageSize and
269
+ max(entry['width'], entry['height']) >= self._minAssociatedImageSize):
270
+ self._associatedImages[id] = entry
271
+ except Exception:
272
+ pass
267
273
  for sidx, s in enumerate(self._tf.series):
268
274
  if sidx not in self._series and not len(set(s.axes) - set('YXS')):
269
275
  id = 'series_%d' % sidx
@@ -286,6 +292,79 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
286
292
  except Exception:
287
293
  pass
288
294
 
295
+ def _handle_indica(self):
296
+ import xml.etree.ElementTree
297
+
298
+ import large_image.tilesource.utilities
299
+
300
+ try:
301
+ root = xml.etree.ElementTree.fromstring(self._tf.pages[0].description)
302
+ self._xml = large_image.tilesource.utilities.etreeToDict(root)
303
+ self._channels = [c['name'] for c in
304
+ self._xml['indica']['image']['channels']['channel']]
305
+ if len(self._basis) == 1 and 'I' in self._basis:
306
+ self._basis['C'] = self._basis.pop('I')
307
+ self._associatedImages.clear()
308
+ except Exception:
309
+ pass
310
+
311
+ def _handle_ome(self):
312
+ """
313
+ For OME Tiff, if we didn't parse the mangification elsewhere, try to
314
+ parse it here.
315
+ """
316
+ import xml.etree.ElementTree
317
+
318
+ import large_image.tilesource.utilities
319
+
320
+ _omeUnitsToMeters = {
321
+ 'Ym': 1e24,
322
+ 'Zm': 1e21,
323
+ 'Em': 1e18,
324
+ 'Pm': 1e15,
325
+ 'Tm': 1e12,
326
+ 'Gm': 1e9,
327
+ 'Mm': 1e6,
328
+ 'km': 1e3,
329
+ 'hm': 1e2,
330
+ 'dam': 1e1,
331
+ 'm': 1,
332
+ 'dm': 1e-1,
333
+ 'cm': 1e-2,
334
+ 'mm': 1e-3,
335
+ '\u00b5m': 1e-6,
336
+ 'nm': 1e-9,
337
+ 'pm': 1e-12,
338
+ 'fm': 1e-15,
339
+ 'am': 1e-18,
340
+ 'zm': 1e-21,
341
+ 'ym': 1e-24,
342
+ '\u00c5': 1e-10,
343
+ }
344
+
345
+ try:
346
+ root = xml.etree.ElementTree.fromstring(self._tf.pages[0].description)
347
+ self._xml = large_image.tilesource.utilities.etreeToDict(root)
348
+ except Exception:
349
+ return
350
+ try:
351
+ try:
352
+ base = self._xml['OME']['Image'][0]['Pixels']
353
+ except Exception:
354
+ base = self._xml['OME']['Image']['Pixels']
355
+ if self._mm_x is None and 'PhysicalSizeX' in base:
356
+ self._mm_x = (
357
+ float(base['PhysicalSizeX']) * 1e3 *
358
+ _omeUnitsToMeters[base.get('PhysicalSizeXUnit', '\u00b5m')])
359
+ if self._mm_y is None and 'PhysicalSizeY' in base:
360
+ self._mm_y = (
361
+ float(base['PhysicalSizeY']) * 1e3 *
362
+ _omeUnitsToMeters[base.get('PhysicalSizeYUnit', '\u00b5m')])
363
+ self._mm_x = self._mm_x or self._mm_y
364
+ self._mm_y = self._mm_y or self._mm_x
365
+ except Exception:
366
+ pass
367
+
289
368
  def _handle_scn(self): # noqa
290
369
  """
291
370
  For SCN files, parse the xml and possibly adjust how associated images
@@ -351,6 +430,20 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
351
430
  except Exception:
352
431
  pass
353
432
 
433
+ def _handle_internal_ndpi(self, intmeta):
434
+ try:
435
+ ndpi = intmeta.pop('65449')
436
+ intmeta['ndpi'] = {}
437
+ for line in ndpi.replace('\r', '\n').split('\n'):
438
+ if '=' in line:
439
+ key, value = line.split('=', 1)
440
+ key = key.strip()
441
+ value = value.strip()
442
+ if key and key not in intmeta['ndpi'] and value:
443
+ intmeta['ndpi'][key] = value
444
+ except Exception:
445
+ pass
446
+
354
447
  def getNativeMagnification(self):
355
448
  """
356
449
  Get the magnification at a particular level.
@@ -420,6 +513,10 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
420
513
  json.dumps(result[key][subkey])
421
514
  except Exception:
422
515
  del result[key][subkey]
516
+ for key in dir(self._tf):
517
+ if (key.startswith('is_') and hasattr(self, '_handle_internal_' + key[3:]) and
518
+ getattr(self._tf, key)):
519
+ getattr(self, '_handle_internal_' + key[3:])(result)
423
520
  if hasattr(self, '_xml') and 'xml' not in result:
424
521
  result.pop('ImageDescription', None)
425
522
  result['xml'] = self._xml
@@ -490,6 +587,17 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
490
587
  self._nonempty_levels_list[frame] = nonempty
491
588
  return nonempty
492
589
 
590
+ def getPreferredLevel(self, level):
591
+ """
592
+ Given a desired level (0 is minimum resolution, self.levels - 1 is max
593
+ resolution), return the level that contains actual data that is no
594
+ lower resolution.
595
+
596
+ :param level: desired level
597
+ :returns level: a level with actual data that is no lower resolution.
598
+ """
599
+ return max(0, min(level, self.levels - 1))
600
+
493
601
  def _getZarrArray(self, series, sidx):
494
602
  with self._zarrlock:
495
603
  if sidx not in self._zarrcache:
@@ -533,7 +641,7 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
533
641
  else:
534
642
  bza = za
535
643
  if step > 2 ** self._maxSkippedLevels:
536
- tile = self._getTileFromEmptyLevel(x, y, z, **kwargs)
644
+ tile, _format = self._getTileFromEmptyLevel(x, y, z, **kwargs)
537
645
  tile = large_image.tilesource.base._imageToNumpy(tile)[0]
538
646
  else:
539
647
  sel = []
@@ -549,6 +657,8 @@ class TifffileFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
549
657
  sel.append(slice(series.shape[aidx]))
550
658
  baxis += 'S'
551
659
  else:
660
+ if axis not in self._basis and axis == 'I':
661
+ axis = 'C'
552
662
  sel.append((frame // self._basis[axis][0]) % self._basis[axis][2])
553
663
  tile = bza[tuple(sel)]
554
664
  # rotate
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: large-image-source-tifffile
3
- Version: 1.28.3.dev2
3
+ Version: 1.30.7.dev10
4
4
  Summary: A tifffile tilesource for large_image.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -15,14 +15,28 @@ 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.28.3.dev2
22
+ Requires-Dist: large-image>=1.30.7.dev10
21
23
  Requires-Dist: dask[array]
22
24
  Requires-Dist: tifffile[all]
23
25
  Requires-Dist: zarr
24
26
  Provides-Extra: girder
25
- Requires-Dist: girder-large-image >=1.28.3.dev2 ; extra == 'girder'
27
+ Requires-Dist: girder-large-image>=1.30.7.dev10; extra == "girder"
28
+ Dynamic: author
29
+ Dynamic: author-email
30
+ Dynamic: classifier
31
+ Dynamic: description
32
+ Dynamic: description-content-type
33
+ Dynamic: home-page
34
+ Dynamic: keywords
35
+ Dynamic: license
36
+ Dynamic: provides-extra
37
+ Dynamic: requires-dist
38
+ Dynamic: requires-python
39
+ Dynamic: summary
26
40
 
27
41
  A tifffile tilesource for large_image.
28
42
 
@@ -0,0 +1,8 @@
1
+ large_image_source_tifffile/__init__.py,sha256=vU1bFrCyklocQjzwiwiAITwLm0sfk-TnyDlIAwxqFeA,28899
2
+ large_image_source_tifffile/girder_source.py,sha256=8YsxpSK_UzbAcpjn6fIMlgKye2FchkB8_HTSQV0FpRA,1064
3
+ large_image_source_tifffile-1.30.7.dev10.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
4
+ large_image_source_tifffile-1.30.7.dev10.dist-info/METADATA,sha256=ESkktkSCBeCvqOXMH5oFMgUnce9s94mAc3CkHO2o-V4,1405
5
+ large_image_source_tifffile-1.30.7.dev10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
6
+ large_image_source_tifffile-1.30.7.dev10.dist-info/entry_points.txt,sha256=aILCN5f7-Zj8-WRXcABxCQvqJv9VLTvqRhZ_7HEyokc,190
7
+ large_image_source_tifffile-1.30.7.dev10.dist-info/top_level.txt,sha256=feOAsix2Rzy6mjy2Ua-N0-L6tlKsgvLdRhO6Hd8_ZFs,28
8
+ large_image_source_tifffile-1.30.7.dev10.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_tifffile/__init__.py,sha256=7hREWGbhyYOcz94l_vxMAOTUSJKtJY37TEIZdkvamNw,25001
2
- large_image_source_tifffile/girder_source.py,sha256=8YsxpSK_UzbAcpjn6fIMlgKye2FchkB8_HTSQV0FpRA,1064
3
- large_image_source_tifffile-1.28.3.dev2.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
4
- large_image_source_tifffile-1.28.3.dev2.dist-info/METADATA,sha256=2XRfComEY1H1fO7m6luWIfzukgRCnPmPJw6RVkiDpZw,1061
5
- large_image_source_tifffile-1.28.3.dev2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- large_image_source_tifffile-1.28.3.dev2.dist-info/entry_points.txt,sha256=aILCN5f7-Zj8-WRXcABxCQvqJv9VLTvqRhZ_7HEyokc,190
7
- large_image_source_tifffile-1.28.3.dev2.dist-info/top_level.txt,sha256=feOAsix2Rzy6mjy2Ua-N0-L6tlKsgvLdRhO6Hd8_ZFs,28
8
- large_image_source_tifffile-1.28.3.dev2.dist-info/RECORD,,