Skip to content

Commit 7ce4f1e

Browse files
committed
Merge branch 'master' into girder-5
2 parents faab1e3 + ad62849 commit 7ce4f1e

File tree

6 files changed

+44
-11
lines changed

6 files changed

+44
-11
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44

55
### Improvements
66

7-
- Speed up annotation centroid queries ([#1981](../../pull/1981))
7+
- Speed up annotation centroid queries ([#1981](../../pull/1981), [#1990](../../pull/1990))
88
- Improve large annotation load and display speed ([#1982](../../pull/1982))
99
- Denormalize some values in the annotation collection to support improving display speed ([#1984](../../pull/1984))
1010
- Improve indices for annotationelement queries ([#1985](../../pull/1985))
1111
- Use some raw bson handling to speed up annotationelement serialization ([#1986](../../pull/1986))
12+
- Improve indices used in large image associated files in girder ([#1988](../../pull/1988))
13+
14+
### Changes
15+
16+
- Skip adjacent DICOM file search during Girder import ([#1987](../../pull/1987))
17+
- Update to work with the most recent wsidicom ([#1989](../../pull/1989))
1218

1319
### Bug Fixes
1420

girder/girder_large_image/models/image_item.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,16 @@ def initialize(self):
5252
self.ensureIndices(['largeImage.fileId'])
5353
File().ensureIndices([
5454
([
55-
('isLargeImageThumbnail', pymongo.ASCENDING),
56-
('attachedToType', pymongo.ASCENDING),
5755
('attachedToId', pymongo.ASCENDING),
56+
('attachedToType', pymongo.ASCENDING),
57+
('isLargeImageThumbnail', pymongo.ASCENDING),
58+
('thumbnailKey', pymongo.ASCENDING),
5859
], {}),
5960
([
60-
('isLargeImageData', pymongo.ASCENDING),
61-
('attachedToType', pymongo.ASCENDING),
6261
('attachedToId', pymongo.ASCENDING),
62+
('attachedToType', pymongo.ASCENDING),
63+
('isLargeImageData', pymongo.ASCENDING),
64+
('thumbnailKey', pymongo.ASCENDING),
6365
], {}),
6466
])
6567

girder_annotation/girder_large_image_annotation/models/annotationelement.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def __getitem__(self, key):
352352
props[prop] = len(props)
353353
proplist.append([element.get(key, defaultProps.get(key)) for key in propskeys])
354354
yield [
355-
str(element.get('id') or entry['_id']),
355+
element.get('id', entry['_id']),
356356
(bbox['lowx'] + bbox['highx']) / 2,
357357
(bbox['lowy'] + bbox['highy']) / 2,
358358
bbox['size'] if entry.get('type') != 'point' else 0,

girder_annotation/girder_large_image_annotation/rest/annotation.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# limitations under the License.
1515
##############################################################################
1616

17+
import binascii
1718
import json
1819
import logging
1920
import struct
@@ -219,6 +220,14 @@ def _getAnnotation(self, annotation, params):
219220
:param params: paging and region parameters for the annotation.
220221
:returns: a function that will return a generator.
221222
"""
223+
import gc
224+
225+
# We increase the threshold2 value for python's gc, because we may
226+
# return a massive number of annotations and the garbage collection
227+
# full scan is _slow_ but probably not useful.
228+
threshold = gc.get_threshold()
229+
if threshold[2] < 100:
230+
gc.set_threshold(threshold[0], threshold[1], 100)
222231
# Ensure that we have read access to the parent item. We could fail
223232
# faster when there are permissions issues if we didn't load the
224233
# annotation elements before checking the item access permissions.
@@ -245,6 +254,7 @@ def generateResult():
245254
if centroids:
246255
# Add a null byte to indicate the start of the binary data
247256
yield b'\x00'
257+
packing = struct.Struct('<fffl')
248258
for element in Annotationelement().yieldElements(annotation, params, info):
249259
# The json conversion is fastest if we use defaults as much as
250260
# possible. The only value in an annotation element that needs
@@ -261,9 +271,9 @@ def generateResult():
261271
[int(x) if isinstance(x, float) and x.is_integer() else x for x in sub]
262272
for sub in hole] for hole in element['holes']]
263273
else:
264-
element = struct.pack(
265-
'>QL', int(element[0][:16], 16), int(element[0][16:24], 16),
266-
) + struct.pack('<fffl', *element[1:])
274+
element = (
275+
binascii.unhexlify(element[0]) if isinstance(element[0], str) else
276+
element[0].binary) + packing.pack(*element[1:])
267277
# Use orjson; it is much faster. The standard json library
268278
# could be used in its most default mode instead like so:
269279
# result = json.dumps(element, separators=(',', ':'))

sources/dicom/large_image_source_dicom/dicomweb_utils.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ def get_dicomweb_metadata(client, study_uid, series_uid):
2626

2727
def get_first_wsi_volume_metadata(client, study_uid, series_uid):
2828
# Find the first WSI Volume and return the DICOMweb metadata
29-
from wsidicom.uid import WSI_SOP_CLASS_UID
29+
try:
30+
from pydicom.uid import VLWholeSlideMicroscopyImageStorage
31+
except ImportError:
32+
from wsidicom.uid import WSI_SOP_CLASS_UID as VLWholeSlideMicroscopyImageStorage
3033

3134
image_type_tag = dicom_key_to_tag('ImageType')
3235
instance_uid_tag = dicom_key_to_tag('SOPInstanceUID')
@@ -46,7 +49,7 @@ def get_first_wsi_volume_metadata(client, study_uid, series_uid):
4649
volume_instance = None
4750
for instance in wsi_instances:
4851
class_type = instance.get(class_uid_tag, {}).get('Value')
49-
if not class_type or class_type[0] != WSI_SOP_CLASS_UID:
52+
if not class_type or class_type[0] != VLWholeSlideMicroscopyImageStorage:
5053
# Only look at WSI classes
5154
continue
5255

sources/dicom/large_image_source_dicom/girder_source.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ class DICOMGirderTileSource(DICOMFileTileSource, GirderTileSource):
2121

2222
_mayHaveAdjacentFiles = True
2323

24+
def __init__(self, item, *args, **kwargs):
25+
# This must be set before super() because parent's __init__ calls _getLargeImagePath()
26+
self._noCache = kwargs.get('noCache', False)
27+
super().__init__(item, *args, **kwargs)
28+
2429
def _getAssetstore(self):
2530
files = Item().childFiles(self.item, limit=1)
2631
if not files:
@@ -45,6 +50,13 @@ def _getFilesystemLargeImagePath(self):
4550
filelist = [
4651
File().getLocalFilePath(file) for file in Item().childFiles(self.item)
4752
if self._pathMightBeDicom(file['name'])]
53+
54+
if self._noCache:
55+
# Skip expensive folder scan during import checks.
56+
# During import, just return files from current item.
57+
# Adjacent files will be found later when actually viewing.
58+
return filelist if filelist else None
59+
4860
if len(filelist) != 1:
4961
return filelist
5062
try:

0 commit comments

Comments
 (0)