large-image-converter 1.29.7.dev38__py3-none-any.whl → 1.29.8.dev8__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.
Potentially problematic release.
This version of large-image-converter might be problematic. Click here for more details.
- large_image_converter/__init__.py +51 -10
- {large_image_converter-1.29.7.dev38.dist-info → large_image_converter-1.29.8.dev8.dist-info}/METADATA +5 -4
- large_image_converter-1.29.8.dev8.dist-info/RECORD +9 -0
- {large_image_converter-1.29.7.dev38.dist-info → large_image_converter-1.29.8.dev8.dist-info}/WHEEL +1 -1
- large_image_converter-1.29.7.dev38.dist-info/RECORD +0 -9
- {large_image_converter-1.29.7.dev38.dist-info → large_image_converter-1.29.8.dev8.dist-info}/LICENSE +0 -0
- {large_image_converter-1.29.7.dev38.dist-info → large_image_converter-1.29.8.dev8.dist-info}/entry_points.txt +0 -0
- {large_image_converter-1.29.7.dev38.dist-info → large_image_converter-1.29.8.dev8.dist-info}/top_level.txt +0 -0
|
@@ -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,
|
|
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(
|
|
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.
|
|
3
|
+
Version: 1.29.8.dev8
|
|
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.
|
|
21
|
+
Requires-Dist: large-image-source-tiff >=1.29.8.dev8
|
|
21
22
|
Requires-Dist: numpy
|
|
22
23
|
Requires-Dist: psutil
|
|
23
24
|
Requires-Dist: pyvips
|
|
@@ -25,7 +26,7 @@ Requires-Dist: tifftools
|
|
|
25
26
|
Provides-Extra: all
|
|
26
27
|
Requires-Dist: glymur ; extra == 'all'
|
|
27
28
|
Requires-Dist: gdal ; extra == 'all'
|
|
28
|
-
Requires-Dist: large-image[sources] >=1.29.
|
|
29
|
+
Requires-Dist: large-image[sources] >=1.29.8.dev8 ; extra == 'all'
|
|
29
30
|
Requires-Dist: packaging ; extra == 'all'
|
|
30
31
|
Requires-Dist: scikit-image ; extra == 'all'
|
|
31
32
|
Provides-Extra: geospatial
|
|
@@ -33,7 +34,7 @@ Requires-Dist: gdal ; extra == 'geospatial'
|
|
|
33
34
|
Provides-Extra: jp2k
|
|
34
35
|
Requires-Dist: glymur ; extra == 'jp2k'
|
|
35
36
|
Provides-Extra: sources
|
|
36
|
-
Requires-Dist: large-image[sources] >=1.29.
|
|
37
|
+
Requires-Dist: large-image[sources] >=1.29.8.dev8 ; extra == 'sources'
|
|
37
38
|
Provides-Extra: stats
|
|
38
39
|
Requires-Dist: packaging ; extra == 'stats'
|
|
39
40
|
Requires-Dist: scikit-image ; extra == 'stats'
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
large_image_converter/__init__.py,sha256=_ixZBvfS3K_jOh2T98o37EF8jjZLrpNTw-ZXkW9r--w,41181
|
|
2
|
+
large_image_converter/__main__.py,sha256=bGQaCR01kTGTnW2c2Z9z5BIiPSpCRPfj7_kPgppLeB4,13353
|
|
3
|
+
large_image_converter/format_aperio.py,sha256=NkKY3gaSjPlfxvcTQgFiMADdq_mkdpKjGQ7WT_QsvaM,11761
|
|
4
|
+
large_image_converter-1.29.8.dev8.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
5
|
+
large_image_converter-1.29.8.dev8.dist-info/METADATA,sha256=O_qx2QuWFeANQForu1cKGMtPKEySsVG5u5COzBCYqQE,4642
|
|
6
|
+
large_image_converter-1.29.8.dev8.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
7
|
+
large_image_converter-1.29.8.dev8.dist-info/entry_points.txt,sha256=TkXGWAaHgquk_ZXfqHTjQLjv8RZriv6ioiJd7JL6UIs,78
|
|
8
|
+
large_image_converter-1.29.8.dev8.dist-info/top_level.txt,sha256=cdRa-ZWWKzVHFsjK1Aq1f4bzAMPc3sgCpprmvpYczKg,22
|
|
9
|
+
large_image_converter-1.29.8.dev8.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
large_image_converter/__init__.py,sha256=EWUP451w9VZpI23NT7gw4fKIn2ouiROi_kA6ikfhxSY,39283
|
|
2
|
-
large_image_converter/__main__.py,sha256=bGQaCR01kTGTnW2c2Z9z5BIiPSpCRPfj7_kPgppLeB4,13353
|
|
3
|
-
large_image_converter/format_aperio.py,sha256=NkKY3gaSjPlfxvcTQgFiMADdq_mkdpKjGQ7WT_QsvaM,11761
|
|
4
|
-
large_image_converter-1.29.7.dev38.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
5
|
-
large_image_converter-1.29.7.dev38.dist-info/METADATA,sha256=irkivAq_rdKBJtD65COrpTvvdCv69T1oC_NfnTTlJcU,4609
|
|
6
|
-
large_image_converter-1.29.7.dev38.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
|
7
|
-
large_image_converter-1.29.7.dev38.dist-info/entry_points.txt,sha256=TkXGWAaHgquk_ZXfqHTjQLjv8RZriv6ioiJd7JL6UIs,78
|
|
8
|
-
large_image_converter-1.29.7.dev38.dist-info/top_level.txt,sha256=cdRa-ZWWKzVHFsjK1Aq1f4bzAMPc3sgCpprmvpYczKg,22
|
|
9
|
-
large_image_converter-1.29.7.dev38.dist-info/RECORD,,
|
{large_image_converter-1.29.7.dev38.dist-info → large_image_converter-1.29.8.dev8.dist-info}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|