large-image-converter 1.29.7.dev38__tar.gz → 1.29.8.dev6__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.

Potentially problematic release.


This version of large-image-converter might be problematic. Click here for more details.

Files changed (15) hide show
  1. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/PKG-INFO +5 -4
  2. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter/__init__.py +51 -10
  3. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter.egg-info/PKG-INFO +5 -4
  4. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter.egg-info/requires.txt +3 -3
  5. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/setup.py +1 -0
  6. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/LICENSE +0 -0
  7. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/README.rst +0 -0
  8. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter/__main__.py +0 -0
  9. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter/format_aperio.py +0 -0
  10. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter.egg-info/SOURCES.txt +0 -0
  11. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter.egg-info/dependency_links.txt +0 -0
  12. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter.egg-info/entry_points.txt +0 -0
  13. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/large_image_converter.egg-info/top_level.txt +0 -0
  14. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/pyproject.toml +0 -0
  15. {large-image-converter-1.29.7.dev38 → large-image-converter-1.29.8.dev6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: large-image-converter
3
- Version: 1.29.7.dev38
3
+ Version: 1.29.8.dev6
4
4
  Summary: Converter for Large Image.
5
5
  Author: Kitware Inc
6
6
  Author-email: kitware@kitware.com
@@ -16,8 +16,9 @@ Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Requires-Python: >=3.8
19
+ Description-Content-Type: text/x-rst
19
20
  License-File: LICENSE
20
- Requires-Dist: large-image-source-tiff>=1.29.7.dev38
21
+ Requires-Dist: large-image-source-tiff>=1.29.8.dev6
21
22
  Requires-Dist: numpy
22
23
  Requires-Dist: psutil
23
24
  Requires-Dist: pyvips
@@ -27,14 +28,14 @@ Requires-Dist: glymur; extra == "jp2k"
27
28
  Provides-Extra: geospatial
28
29
  Requires-Dist: gdal; extra == "geospatial"
29
30
  Provides-Extra: sources
30
- Requires-Dist: large-image[sources]>=1.29.7.dev38; extra == "sources"
31
+ Requires-Dist: large-image[sources]>=1.29.8.dev6; extra == "sources"
31
32
  Provides-Extra: stats
32
33
  Requires-Dist: packaging; extra == "stats"
33
34
  Requires-Dist: scikit-image; extra == "stats"
34
35
  Provides-Extra: all
35
36
  Requires-Dist: glymur; extra == "all"
36
37
  Requires-Dist: gdal; extra == "all"
37
- Requires-Dist: large-image[sources]>=1.29.7.dev38; extra == "all"
38
+ Requires-Dist: large-image[sources]>=1.29.8.dev6; extra == "all"
38
39
  Requires-Dist: packaging; extra == "all"
39
40
  Requires-Dist: scikit-image; extra == "all"
40
41
 
@@ -109,7 +109,7 @@ def _data_from_large_image(path, outputPath, **kwargs):
109
109
  _pool_add(tasks, (pool.submit(
110
110
  _convert_via_vips, img, savePath, outputPath, mime=mime, forTiled=False), ))
111
111
  results['images'][key] = savePath
112
- _drain_pool(pool, tasks)
112
+ _drain_pool(pool, tasks, 'associated images')
113
113
  return results
114
114
 
115
115
 
@@ -218,7 +218,7 @@ def _generate_multiframe_tiff(inputPath, outputPath, tempPath, lidata, **kwargs)
218
218
  _pool_add(tasks, (pool.submit(
219
219
  _convert_via_vips, subInputPath, savePath, tempPath, False), ))
220
220
  extraImages[key] = savePath
221
- _drain_pool(pool, tasks)
221
+ _drain_pool(pool, tasks, 'subpage')
222
222
  _output_tiff(outputList, outputPath, tempPath, lidata, extraImages, **kwargs)
223
223
 
224
224
 
@@ -349,7 +349,7 @@ def _concurrency_to_value(_concurrency=None, **kwargs):
349
349
  return max(1, large_image.config.cpu_count(logical=True) + _concurrency)
350
350
 
351
351
 
352
- def _get_thread_pool(memoryLimit=None, **kwargs):
352
+ def _get_thread_pool(memoryLimit=None, parentConcurrency=None, numItems=None, **kwargs):
353
353
  """
354
354
  Allocate a thread pool based on the specific concurrency.
355
355
 
@@ -357,12 +357,37 @@ def _get_thread_pool(memoryLimit=None, **kwargs):
357
357
  process per memoryLimit bytes of total memory.
358
358
  """
359
359
  concurrency = _concurrency_to_value(**kwargs)
360
+ if parentConcurrency and parentConcurrency > 1 and concurrency > 1:
361
+ concurrency = max(1, int(math.ceil(concurrency / parentConcurrency)))
360
362
  if memoryLimit:
363
+ if parentConcurrency:
364
+ memoryLimit *= parentConcurrency
361
365
  concurrency = min(concurrency, large_image.config.total_memory() // memoryLimit)
366
+ if numItems and numItems >= 1 and concurrency > numItems:
367
+ concurrency = numItems
362
368
  concurrency = max(1, concurrency)
363
369
  return concurrent.futures.ThreadPoolExecutor(max_workers=concurrency)
364
370
 
365
371
 
372
+ def _pool_log(left, total, label):
373
+ """
374
+ Log processing within a pool.
375
+
376
+ :param left: units left to process.
377
+ :param total: total units left to process.
378
+ :param label: label to log describing what is being processed.
379
+ """
380
+ if not hasattr(logger, '_pool_log_starttime'):
381
+ logger._pool_log_starttime = time.time()
382
+ if not hasattr(logger, '_pool_log_lastlog'):
383
+ logger._pool_log_lastlog = time.time()
384
+ if time.time() - logger._pool_log_lastlog < 10:
385
+ return
386
+ elapsed = time.time() - logger._pool_log_starttime
387
+ logger.debug('%d/%d %s left %4.2fs', left, total, label, elapsed)
388
+ logger._pool_log_lastlog = time.time()
389
+
390
+
366
391
  def _pool_add(tasks, newtask):
367
392
  """
368
393
  Add a new task to a pool, then drain any finished tasks at the start of the
@@ -381,7 +406,7 @@ def _pool_add(tasks, newtask):
381
406
  tasks.pop(0)
382
407
 
383
408
 
384
- def _drain_pool(pool, tasks):
409
+ def _drain_pool(pool, tasks, label=''):
385
410
  """
386
411
  Wait for all tasks in a pool to complete, then shutdown the pool.
387
412
 
@@ -389,6 +414,8 @@ def _drain_pool(pool, tasks):
389
414
  :param tasks: a list containing either lists or tuples, the last element
390
415
  of which is a task submitted to the pool. Altered.
391
416
  """
417
+ numtasks = len(tasks)
418
+ _pool_log(len(tasks), numtasks, label)
392
419
  while len(tasks):
393
420
  # This allows better stopping on a SIGTERM
394
421
  try:
@@ -396,6 +423,7 @@ def _drain_pool(pool, tasks):
396
423
  except concurrent.futures.TimeoutError:
397
424
  continue
398
425
  tasks.pop(0)
426
+ _pool_log(len(tasks), numtasks, label)
399
427
  pool.shutdown(False)
400
428
 
401
429
 
@@ -507,7 +535,8 @@ def _convert_large_image_tile(tilelock, strips, tile):
507
535
  strips[ty] = strips[ty].insert(vimg, x, 0, expand=True)
508
536
 
509
537
 
510
- def _convert_large_image_frame(frame, numFrames, ts, frameOutputPath, tempPath, **kwargs):
538
+ def _convert_large_image_frame(frame, numFrames, ts, frameOutputPath, tempPath,
539
+ parentConcurrency=None, **kwargs):
511
540
  """
512
541
  Convert a single frame from a large_image source. This parallelizes tile
513
542
  reads. Once all tiles are converted to a composited vips image, a tiff
@@ -518,18 +547,28 @@ def _convert_large_image_frame(frame, numFrames, ts, frameOutputPath, tempPath,
518
547
  :param ts: the open tile source.
519
548
  :param frameOutputPath: the destination name for the tiff file.
520
549
  :param tempPath: a temporary file in a temporary directory.
550
+ :param parentConcurrency: amount of concurrency used by parent task.
521
551
  """
522
552
  # The iterator tile size is a balance between memory use and fewer calls
523
553
  # and file handles.
524
554
  _iterTileSize = 4096
525
555
  logger.info('Processing frame %d/%d', frame + 1, numFrames)
526
556
  strips = []
527
- pool = _get_thread_pool(**kwargs)
557
+ pool = _get_thread_pool(
558
+ memoryLimit=FrameMemoryEstimate,
559
+ # allow multiple tiles even if we are using all the cores, as it
560
+ # balances I/O and computation
561
+ parentConcurrency=(parentConcurrency // 2),
562
+ **kwargs)
528
563
  tasks = []
529
564
  tilelock = threading.Lock()
530
565
  for tile in ts.tileIterator(tile_size=dict(width=_iterTileSize), frame=frame):
531
566
  _pool_add(tasks, (pool.submit(_convert_large_image_tile, tilelock, strips, tile), ))
532
- _drain_pool(pool, tasks)
567
+ _drain_pool(pool, tasks, f'tiles from frame {frame + 1}/{numFrames}')
568
+ minbands = min(strip.bands for strip in strips)
569
+ maxbands = max(strip.bands for strip in strips)
570
+ if minbands != maxbands:
571
+ strips = [strip[:minbands] for strip in strips]
533
572
  img = strips[0]
534
573
  for stripidx in range(1, len(strips)):
535
574
  img = img.insert(strips[stripidx], 0, stripidx * _iterTileSize, expand=True)
@@ -552,20 +591,21 @@ def _convert_large_image(inputPath, outputPath, tempPath, lidata, **kwargs):
552
591
  numFrames = len(lidata['metadata'].get('frames', [0]))
553
592
  outputList = []
554
593
  tasks = []
555
- pool = _get_thread_pool(memoryLimit=FrameMemoryEstimate, **kwargs)
556
594
  startFrame = 0
557
595
  endFrame = numFrames
558
596
  if kwargs.get('onlyFrame') is not None and str(kwargs.get('onlyFrame')):
559
597
  startFrame = int(kwargs.get('onlyFrame'))
560
598
  endFrame = startFrame + 1
599
+ pool = _get_thread_pool(memoryLimit=FrameMemoryEstimate,
600
+ numItems=endFrame - startFrame, **kwargs)
561
601
  for frame in range(startFrame, endFrame):
562
602
  frameOutputPath = tempPath + '-%d-%s.tiff' % (
563
603
  frame + 1, time.strftime('%Y%m%d-%H%M%S'))
564
604
  _pool_add(tasks, (pool.submit(
565
605
  _convert_large_image_frame, frame, numFrames, ts, frameOutputPath,
566
- tempPath, **kwargs), ))
606
+ tempPath, pool._max_workers, **kwargs), ))
567
607
  outputList.append(frameOutputPath)
568
- _drain_pool(pool, tasks)
608
+ _drain_pool(pool, tasks, 'frames')
569
609
  _output_tiff(outputList, outputPath, tempPath, lidata, **kwargs)
570
610
 
571
611
 
@@ -887,6 +927,7 @@ def convert(inputPath, outputPath=None, **kwargs): # noqa: C901
887
927
 
888
928
  :returns: outputPath if successful
889
929
  """
930
+ logger._pool_log_starttime = time.time()
890
931
  if kwargs.get('_concurrency'):
891
932
  os.environ['VIPS_CONCURRENCY'] = str(_concurrency_to_value(**kwargs))
892
933
  geospatial = kwargs.get('geospatial')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: large-image-converter
3
- Version: 1.29.7.dev38
3
+ Version: 1.29.8.dev6
4
4
  Summary: Converter for Large Image.
5
5
  Author: Kitware Inc
6
6
  Author-email: kitware@kitware.com
@@ -16,8 +16,9 @@ Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Requires-Python: >=3.8
19
+ Description-Content-Type: text/x-rst
19
20
  License-File: LICENSE
20
- Requires-Dist: large-image-source-tiff>=1.29.7.dev38
21
+ Requires-Dist: large-image-source-tiff>=1.29.8.dev6
21
22
  Requires-Dist: numpy
22
23
  Requires-Dist: psutil
23
24
  Requires-Dist: pyvips
@@ -27,14 +28,14 @@ Requires-Dist: glymur; extra == "jp2k"
27
28
  Provides-Extra: geospatial
28
29
  Requires-Dist: gdal; extra == "geospatial"
29
30
  Provides-Extra: sources
30
- Requires-Dist: large-image[sources]>=1.29.7.dev38; extra == "sources"
31
+ Requires-Dist: large-image[sources]>=1.29.8.dev6; extra == "sources"
31
32
  Provides-Extra: stats
32
33
  Requires-Dist: packaging; extra == "stats"
33
34
  Requires-Dist: scikit-image; extra == "stats"
34
35
  Provides-Extra: all
35
36
  Requires-Dist: glymur; extra == "all"
36
37
  Requires-Dist: gdal; extra == "all"
37
- Requires-Dist: large-image[sources]>=1.29.7.dev38; extra == "all"
38
+ Requires-Dist: large-image[sources]>=1.29.8.dev6; extra == "all"
38
39
  Requires-Dist: packaging; extra == "all"
39
40
  Requires-Dist: scikit-image; extra == "all"
40
41
 
@@ -1,4 +1,4 @@
1
- large-image-source-tiff>=1.29.7.dev38
1
+ large-image-source-tiff>=1.29.8.dev6
2
2
  numpy
3
3
  psutil
4
4
  pyvips
@@ -7,7 +7,7 @@ tifftools
7
7
  [all]
8
8
  glymur
9
9
  gdal
10
- large-image[sources]>=1.29.7.dev38
10
+ large-image[sources]>=1.29.8.dev6
11
11
  packaging
12
12
  scikit-image
13
13
 
@@ -18,7 +18,7 @@ gdal
18
18
  glymur
19
19
 
20
20
  [sources]
21
- large-image[sources]>=1.29.7.dev38
21
+ large-image[sources]>=1.29.8.dev6
22
22
 
23
23
  [stats]
24
24
  packaging
@@ -40,6 +40,7 @@ setup(
40
40
  'fallback_version': '0.0.0'},
41
41
  description=description,
42
42
  long_description=long_description,
43
+ long_description_content_type='text/x-rst',
43
44
  license='Apache Software License 2.0',
44
45
  author='Kitware Inc',
45
46
  author_email='kitware@kitware.com',