Skip to content

Commit

Permalink
Improve dicom multi level detection
Browse files Browse the repository at this point in the history
When there are multiple files in the same directory, we check if they
can be used together as different levels of the same dicom.  This was
done by extension, but some dicoms have the name structure of
DCM_<number> without extension.
  • Loading branch information
manthey committed Jun 8, 2023
1 parent 33147c2 commit 917ebdb
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 9 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

## 1.22.3

### Improvements
- Better DICOM multi-level detection ([#1196](../../pull/1196))

### Changes
- Change how extensions and fallback priorities interact ([#1192](../../pull/1192))
- Refactor reading the .large_image_config.yaml file on the girder client ([#1193](../../pull/1193))
- Refactor of the which-folders-have-annotations pipeline ([#1194](../../pull/1194))

### Bug Fixes
- Fix an issue converting multiframe files that vips reads as single frame ([#1195](../../pull/1195))
- Fix an issue converting multiframe files that vips reads as single frame ([#1195](../../pull/1195))

## 1.22.2

Expand Down
8 changes: 7 additions & 1 deletion large_image/tilesource/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re
import uuid

try:
Expand Down Expand Up @@ -77,7 +78,8 @@ def getSortedSourceList(availableSources, pathOrUri, mimeType=None, *args, **kwa
"""
uriWithoutProtocol = str(pathOrUri).split('://', 1)[-1]
isLargeImageUri = str(pathOrUri).startswith('large_image://')
extensions = [ext.lower() for ext in os.path.basename(uriWithoutProtocol).split('.')[1:]]
baseName = os.path.basename(uriWithoutProtocol)
extensions = [ext.lower() for ext in baseName.split('.')[1:]]
properties = {
'_geospatial_source': isGeospatial(pathOrUri),
}
Expand All @@ -90,6 +92,10 @@ def getSortedSourceList(availableSources, pathOrUri, mimeType=None, *args, **kwa
mimeType in availableSources[sourceName].mimeTypes):
fallback = False
priority = min(priority, availableSources[sourceName].mimeTypes[mimeType])
for regex in getattr(availableSources[sourceName], 'nameMatches', {}):
if re.match(regex, baseName):
fallback = False
priority = min(priority, availableSources[sourceName].nameMatches[regex])
for ext in extensions:
if ext in sourceExtensions:
fallback = False
Expand Down
20 changes: 13 additions & 7 deletions large_image/tilesource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,29 @@


class TileSource:
#: Name of the tile source
# Name of the tile source
name = None

#: A dictionary of known file extensions and the ``SourcePriority`` given
#: to each. It must contain a None key with a priority for the tile source
#: when the extension does not match.
# A dictionary of known file extensions and the ``SourcePriority`` given
# to each. It must contain a None key with a priority for the tile source
# when the extension does not match.
extensions = {
None: SourcePriority.FALLBACK
}

#: A dictionary of common mime-types handled by the source and the
#: ``SourcePriority`` given to each. This are used in place of or in
#: additional to extensions.
# A dictionary of common mime-types handled by the source and the
# ``SourcePriority`` given to each. This are used in place of or in
# additional to extensions.
mimeTypes = {
None: SourcePriority.FALLBACK
}

# A dictionary with regex strings as the keys and the ``SourcePriority``
# given to names that match that expression. This is used in addition to
# extensions and mimeTypes, with the highest priority match taken.
nameMatches = {
}

geospatial = False

def __init__(self, encoding='JPEG', jpegQuality=95, jpegSubsampling=0,
Expand Down
5 changes: 5 additions & 0 deletions sources/dicom/large_image_source_dicom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ class DICOMFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
None: SourcePriority.FALLBACK,
'application/dicom': SourcePriority.PREFERRED,
}
nameMatches = {
r'DCM_\d+$': SourcePriority.MEDIUM,
}

_minTileSize = 64
_maxTileSize = 4096
Expand Down Expand Up @@ -156,6 +159,8 @@ def _pathMightBeDicom(self, path):
return True
if re.match(r'^([1-9][0-9]*|0)(\.([1-9][0-9]*|0))+$', path) and len(path) <= 64:
return True
if re.match(r'^DCM_\d+$', path):
return True
return False

def getNativeMagnification(self):
Expand Down

0 comments on commit 917ebdb

Please sign in to comment.