Skip to content

Commit

Permalink
Merge pull request #792 from girder/tile-frame-quad-info-options
Browse files Browse the repository at this point in the history
Add some automating options to getTileFramesQuadInfo
  • Loading branch information
manthey authored Mar 4, 2022
2 parents b1a1686 + c740125 commit 2d05fdc
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 15 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Change Log

## Version 1.11.2

### Improvements
- Emit events when an overlay annotation layer is created ([#787](../../pull/787))
- Minor improvements to setFrameQuad to make it more flexible ([#790](../../pull/790))
- Support drawing polygon selection regions ([#791](../../pull/791))
- Add some automating options to getTileFramesQuadInfo ([#792](../../pull/792))

### Changes
- Change how we do a version check ([#785](../../pull/785))

## Version 1.11.1

### Improvements
Expand Down
23 changes: 15 additions & 8 deletions girder/girder_large_image/rest/tiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -1257,17 +1257,24 @@ def stream():
'replace the defaults.', required=False)
.param('query', 'Addition query parameters that would be passed to '
'tile endpoints, such as style.', required=False)
.param('frameBase', 'Starting frame number (default 0)',
.param('frameBase', 'Starting frame number (default 0). If c/z/t/xy '
'then step through values from 0 to number of that axis - 1. '
'The axis specification in only useful for cache reporting or '
'scheduling',
required=False, dataType='int')
.param('frameStride', 'Only use every frameStride frame of the image '
'(default 1)', required=False, dataType='int')
'(default 1). c/z/t/xy to use the length of that axis',
required=False, dataType='int')
.param('frameGroup', 'Group frames when using multiple textures to '
'keep boundaries at a multiple of the group size number.',
'keep boundaries at a multiple of the group size number. '
'c/z/t/xy to use the length of that axis.',
required=False, dataType='int')
.param('frameGroupFactor', 'Ignore grouping if the resultant images '
'would be more than this factor smaller than without grouping '
'(default 4)', required=False, dataType='int')
.param('frameGroupStride', 'Reorder frames based on the to stride.',
.param('frameGroupStride', 'Reorder frames based on the to stride '
'(default 1). "auto" to use frameGroup / frameStride if that '
'value is an integer.',
required=False, dataType='int')
.param('maxTextureSize', 'Maximum texture size in either dimension. '
'This should be the smaller of a desired value and of the '
Expand Down Expand Up @@ -1299,11 +1306,11 @@ def tileFramesQuadInfo(self, item, params):
options = self._parseParams(params, False, [
('format', str),
('query', str),
('frameBase', int),
('frameStride', int),
('frameGroup', int),
('frameBase', str),
('frameStride', str),
('frameGroup', str),
('frameGroupFactor', int),
('frameGroupStride', int),
('frameGroupStride', str),
('maxTextureSize', int),
('maxTextures', int),
('maxTotalTexturePixels', int),
Expand Down
35 changes: 31 additions & 4 deletions large_image/tilesource/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,18 +681,21 @@ def getTileFramesQuadInfo(metadata, options=None):
{'encoding': 'JPEG', 'jpegQuality': 85, 'jpegSubsampling': 1}.
query: Additional query options to add to the tile source, such as
style.
frameBase: (default 0) Starting frame number used.
frameBase: (default 0) Starting frame number used. c/z/xy/z to step
through that index length (0 to 1 less than the value), which is
probably only useful for cache reporting or scheduling.
frameStride: (default 1) Only use every ``frameStride`` frame of the
image.
image. c/z/xy/z to use that axis length.
frameGroup: (default 1) If above 1 and multiple textures are used, each
texture will have an even multiple of the group size number of
frames. This helps control where texture loading transitions
occur.
occur. c/z/xy/z to use that axis length.
frameGroupFactor: (default 4) If ``frameGroup`` would reduce the size
of the tile images beyond this factor, don't use it.
frameGroupStride: (default 1) If ``frameGroup`` is above 1 and multiple
textures are used, then the frames are reordered based on this
stride value.
stride value. "auto" to use frameGroup / frameStride if that
value is an integer.
maxTextureSize: Limit the maximum texture size to a square of this
size.
maxTextures: (default 1) If more than one, allow multiple textures to
Expand Down Expand Up @@ -730,6 +733,30 @@ def getTileFramesQuadInfo(metadata, options=None):
}
opts = defaultOptions.copy()
opts.update(options or {})

opts['frameStride'] = (
int(opts['frameStride']) if str(opts['frameStride']).isdigit() else
metadata.get('IndexRange', {}).get('Index' + opts['frameStride'].upper(), 1))
opts['frameGroup'] = (
int(opts['frameGroup']) if str(opts['frameGroup']).isdigit() else
metadata.get('IndexRange', {}).get('Index' + opts['frameGroup'].upper(), 1))
opts['frameGroupStride'] = (
int(opts['frameGroupStride']) if opts['frameGroupStride'] != 'auto' else
max(1, opts['frameGroup'] // opts['frameStride']))
if str(opts['frameBase']).isdigit():
opts['frameBase'] = int(opts['frameBase'])
else:
status = {
'metadata': metadata,
'options': opts,
'src': [],
}
for val in range(metadata.get(
'IndexRange', {}).get('Index' + opts['frameBase'].upper(), 1)):
opts['frameBase'] = val
result = getTileFramesQuadInfo(metadata, opts)
status['src'].extend(result['src'])
return status
sizeX, sizeY = metadata['sizeX'], metadata['sizeY']
numFrames = len(metadata.get('frames', [])) or 1
frames = []
Expand Down
21 changes: 18 additions & 3 deletions test/test_source_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,10 +427,24 @@ def testTileOverlapWithRegionOffset():
'left': 2880,
'top': 3816,
}),
({
'maxTextures': 8,
'maxTextureSize': 4096,
'frameBase': 'c',
'frameStride': 'c',
'frameGroup': 'z',
'frameGroupStride': 'auto',
}, 10, None, None, {
'framesAcross': 5,
'height': 624,
'width': 816,
}, None, None),
])
def testGetTileFramesQuadInfo(options, lensrc, lenquads, frame10, src0, srclast, quads10):
metadata = {
'frames': [0] * 250,
'IndexRange': {'IndexC': 5, 'IndexZ': 25, 'IndexT': 2},
'levels': 10,
'sizeX': 100000,
'sizeY': 75000,
Expand All @@ -439,8 +453,9 @@ def testGetTileFramesQuadInfo(options, lensrc, lenquads, frame10, src0, srclast,
}
results = large_image.tilesource.utilities.getTileFramesQuadInfo(metadata, options)
assert len(results['src']) == lensrc
assert len(results['quads']) == lenquads
if len(results['frames']) > 10:
if lenquads:
assert len(results['quads']) == lenquads
if frame10 is not None and len(results['frames']) > 10:
assert results['frames'][10] == frame10
for key, value in src0.items():
if value is not None:
Expand All @@ -450,7 +465,7 @@ def testGetTileFramesQuadInfo(options, lensrc, lenquads, frame10, src0, srclast,
if srclast is not None:
for key, value in srclast.items():
assert results['src'][-1][key] == value
if len(results['quads']) > 10 and quads10 is not None:
if quads10 is not None and len(results['quads']) > 10:
crop10 = results['quads'][10]['crop']
for key, value in quads10.items():
assert crop10[key] == value

0 comments on commit 2d05fdc

Please sign in to comment.