Skip to content

Commit d905877

Browse files
Add dicom-rle as supported media type
1 parent 39dc8a7 commit d905877

File tree

3 files changed

+90
-10
lines changed

3 files changed

+90
-10
lines changed

data/retrieve_instance_pixeldata.rle

124 Bytes
Binary file not shown.

src/dicomweb_client/web.py

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Dict,
1515
Iterator,
1616
List,
17+
Mapping,
1718
Optional,
1819
Set,
1920
Sequence,
@@ -857,7 +858,9 @@ def _build_accept_header_field_value(
857858
def _build_multipart_accept_header_field_value(
858859
cls,
859860
media_types: Union[Tuple[Union[str, Tuple[str, str]], ...], None],
860-
supported_media_types: Union[Dict[str, str], Set[str]]
861+
supported_media_types: Union[
862+
Mapping[str, Union[str, Tuple[str, ...]]], Set[str]
863+
]
861864
) -> str:
862865
"""Build an accept header field value for a multipart request message.
863866
@@ -866,7 +869,9 @@ def _build_multipart_accept_header_field_value(
866869
media_types: Union[Tuple[Union[str, Tuple[str, str]], ...], None]
867870
Acceptable media types and optionally the UIDs of the corresponding
868871
transfer syntaxes
869-
supported_media_types: Union[Dict[str, str], Set[str]]
872+
supported_media_types: Union[
873+
Mapping[str, Union[str, Tuple[str, ...]]], Set[str]
874+
]
870875
Set of supported media types or mapping of transfer syntaxes
871876
to their corresponding media types
872877
@@ -894,7 +899,13 @@ def _build_multipart_accept_header_field_value(
894899
cls._assert_media_type_is_valid(media_type)
895900
field_value = f'multipart/related; type="{media_type}"'
896901
if isinstance(supported_media_types, dict):
897-
if media_type not in supported_media_types.values():
902+
media_type_in_supported_media_types = any(
903+
media_type == supported_media_types
904+
if isinstance(supported_media_types, str)
905+
else media_type in supported_media_types
906+
for supported_media_types in supported_media_types.values()
907+
)
908+
if not media_type_in_supported_media_types:
898909
if not (media_type.endswith('/*') or
899910
media_type.endswith('/')):
900911
raise ValueError(
@@ -908,14 +919,23 @@ def _build_multipart_accept_header_field_value(
908919
f'Transfer syntax "{transfer_syntax_uid}" '
909920
'is not supported for requested resource.'
910921
)
911-
expected_media_type = supported_media_types[
922+
expected_media_types = supported_media_types[
912923
transfer_syntax_uid
913924
]
914-
if expected_media_type != media_type:
915-
have_same_type = (
916-
cls._parse_media_type(media_type)[0] ==
917-
cls._parse_media_type(expected_media_type)[0]
925+
if not isinstance(expected_media_types, tuple):
926+
expected_media_types = (expected_media_types, )
927+
if media_type not in expected_media_types:
928+
have_same_type = next(
929+
(
930+
cls._same_media_type(
931+
media_type, expected_media_type
932+
)
933+
for expected_media_type
934+
in expected_media_types
935+
),
936+
False
918937
)
938+
919939
if (have_same_type and
920940
(media_type.endswith('/*') or
921941
media_type.endswith('/'))):
@@ -1057,7 +1077,7 @@ def _http_get_multipart(
10571077
default_media_type = '*/*'
10581078
supported_media_types = {
10591079
'1.2.840.10008.1.2.1': 'application/octet-stream',
1060-
'1.2.840.10008.1.2.5': 'image/x-dicom-rle',
1080+
'1.2.840.10008.1.2.5': ('image/x-dicom-rle', 'image/dicom-rle'),
10611081
'1.2.840.10008.1.2.4.50': 'image/jpeg',
10621082
'1.2.840.10008.1.2.4.51': 'image/jpeg',
10631083
'1.2.840.10008.1.2.4.57': 'image/jpeg',
@@ -1181,7 +1201,7 @@ def _http_get_multipart_image(
11811201
""" # noqa: E501
11821202
headers = {}
11831203
supported_media_types = {
1184-
'1.2.840.10008.1.2.5': 'image/x-dicom-rle',
1204+
'1.2.840.10008.1.2.5': ('image/x-dicom-rle', 'image/dicom-rle'),
11851205
'1.2.840.10008.1.2.4.50': 'image/jpeg',
11861206
'1.2.840.10008.1.2.4.51': 'image/jpeg',
11871207
'1.2.840.10008.1.2.4.57': 'image/jpeg',
@@ -1653,6 +1673,27 @@ def search_for_studies(
16531673
get_remaining=get_remaining
16541674
)
16551675

1676+
@classmethod
1677+
def _same_media_type(cls, first: str, second: str) -> bool:
1678+
"""Check if two media types have the same type.
1679+
1680+
Parameters
1681+
----------
1682+
first: str
1683+
First media type
1684+
second: str
1685+
Second media type
1686+
1687+
Returns
1688+
-------
1689+
bool
1690+
Whether media types have the same type
1691+
1692+
"""
1693+
return (
1694+
cls._parse_media_type(first)[0] == cls._parse_media_type(second)[0]
1695+
)
1696+
16561697
@classmethod
16571698
def _parse_media_type(cls, media_type: str) -> Tuple[str, str]:
16581699
"""Parse media type and extract its type and subtype.

tests/test_web.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,45 @@ def test_retrieve_instance_frames_jls(httpserver, client, cache_dir):
908908
assert request.path == expected_path
909909
assert request.accept_mimetypes[0][0][:35] == headers['content-type'][:35]
910910

911+
@pytest.mark.parametrize(
912+
"media_type", ["image/dicom-rle", "image/x-dicom-rle"]
913+
)
914+
def test_retrieve_instance_frames_rle(
915+
httpserver,
916+
client,
917+
cache_dir,
918+
media_type
919+
):
920+
cache_filename = str(cache_dir.joinpath('retrieve_instance_pixeldata.rle'))
921+
with open(cache_filename, 'rb') as f:
922+
content = f.read()
923+
headers = {
924+
'content-type': f'multipart/related; type="{media_type}"',
925+
}
926+
httpserver.serve_content(content=content, code=200, headers=headers)
927+
study_instance_uid = '1.2.3'
928+
series_instance_uid = '1.2.4'
929+
sop_instance_uid = '1.2.5'
930+
frame_numbers = [114]
931+
frame_list = ','.join([str(n) for n in frame_numbers])
932+
result = client.retrieve_instance_frames(
933+
study_instance_uid,
934+
series_instance_uid,
935+
sop_instance_uid,
936+
frame_numbers,
937+
media_types=(media_type, )
938+
)
939+
assert list(result) == [content]
940+
request = httpserver.requests[0]
941+
expected_path = (
942+
f'/studies/{study_instance_uid}'
943+
f'/series/{series_instance_uid}'
944+
f'/instances/{sop_instance_uid}'
945+
f'/frames/{frame_list}'
946+
)
947+
assert request.path == expected_path
948+
assert request.accept_mimetypes[0][0][:36] == headers['content-type'][:36]
949+
911950

912951
def test_retrieve_instance_frames_rendered_jpeg(httpserver, client, cache_dir):
913952
cache_filename = str(cache_dir.joinpath('retrieve_instance_pixeldata.jpg'))

0 commit comments

Comments
 (0)