Skip to content

Commit 731864c

Browse files
author
hackermd
committed
Complete support for WADO-RS
* Add methods for WADO-RS Retrieve Rendered Transaction actions (``retrieve_series_rendered()``, ``retrieve_instance_rendered()`` and ``retrieve_instance_frames_rendered()``). * Add ``media_types`` parameter to methods for WADO-RS RetrieveStudy, RetrieveSeries, and RetrieveInstance actions (``retrieve_study()``, ``retrieve_series()`` and ``retrieve_instance()``) to allow users to specify acceptable media type ranges (including transfer syntaxes). * Change ``image_format`` parameter of method ``retrieve_instance_frames()`` to ``media_types`` for compatibility with other WADO-RS methods and to allow users to accept other non-image media types, e.g., to retrieve frames in video formats.
1 parent d95c11a commit 731864c

File tree

5 files changed

+60
-58
lines changed

5 files changed

+60
-58
lines changed

docs/usage.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ Retrieve a set of frames with default transfer syntax ("application/octet-stream
321321

322322
.. code-block:: python
323323
324-
frames = client.retrieve_frames(
324+
frames = client.retrieve_instance_frames(
325325
study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
326326
series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
327327
sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
@@ -332,7 +332,7 @@ Retrieve a set of frames of a given instances as JPEG compressed image:
332332

333333
.. code-block:: python
334334
335-
frames = client.retrieve_frames(
335+
frames = client.retrieve_instance_frames(
336336
study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
337337
series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
338338
sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
@@ -344,7 +344,7 @@ Retrieve a set of frames of a given instances as compressed image in any availab
344344

345345
.. code-block:: python
346346
347-
frames = client.retrieve_frames(
347+
frames = client.retrieve_instance_frames(
348348
study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
349349
series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
350350
sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
@@ -356,7 +356,7 @@ Retrieve a set of frames of a given instances as either JPEG 2000 or JPEG-LS com
356356

357357
.. code-block:: python
358358
359-
frames = client.retrieve_frames(
359+
frames = client.retrieve_instance_frames(
360360
study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
361361
series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
362362
sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
@@ -368,7 +368,7 @@ Retrieve a set of frames of a given instances as either JPEG, JPEG 2000 or JPEG-
368368

369369
.. code-block:: python
370370
371-
frames = client.retrieve_frames(
371+
frames = client.retrieve_instance_frames(
372372
study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
373373
series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
374374
sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
@@ -412,7 +412,7 @@ Retrieve a single frame of a multi-frame image instance rendered as a high-quali
412412

413413
.. code-block:: python
414414
415-
frames = client.retrieve_frames_rendered(
415+
frames = client.retrieve_instance_frames_rendered(
416416
study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
417417
series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
418418
sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'

src/dicomweb_client/api.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,8 +1903,9 @@ def retrieve_instance_rendered(self, study_instance_uid,
19031903
'retrieval of rendered instance.'.format(common_media_type)
19041904
)
19051905

1906-
def retrieve_frames(self, study_instance_uid, series_instance_uid,
1907-
sop_instance_uid, frame_numbers, media_types=None):
1906+
def retrieve_instance_frames(self, study_instance_uid, series_instance_uid,
1907+
sop_instance_uid, frame_numbers,
1908+
media_types=None):
19081909
'''Retrieves one or more frames of an individual DICOM instance.
19091910
19101911
Parameters
@@ -1961,9 +1962,12 @@ def retrieve_frames(self, study_instance_uid, series_instance_uid,
19611962
'retrieval of frames.'.format(common_media_type)
19621963
)
19631964

1964-
def retrieve_frames_rendered(self, study_instance_uid,
1965-
series_instance_uid, sop_instance_uid,
1966-
frame_number, media_types=None, params=None):
1965+
def retrieve_instance_frames_rendered(self, study_instance_uid,
1966+
series_instance_uid,
1967+
sop_instance_uid,
1968+
frame_number,
1969+
media_types=None,
1970+
params=None):
19671971
'''Retrieves one or more server-side rendered frames of an
19681972
individual DICOM instance.
19691973

src/dicomweb_client/cli.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -311,26 +311,22 @@ def _get_parser():
311311
)
312312
retrieve_instance_full_parser.set_defaults(func=_retrieve_instance)
313313

314-
retrieve_frames_parser = retrieve_subparsers.add_parser(
314+
retrieve_instance_frames_parser = retrieve_instance_subparsers.add_parser(
315315
'frames', description=(
316316
'Retrieve one or more frames of the pixel data element of an '
317317
'invidividual DICOM instance.'
318318
),
319-
parents=[
320-
abstract_required_study_parser, abstract_required_series_parser,
321-
abstract_required_instance_parser,
322-
abstract_save_parser, abstract_retrieve_parser
323-
]
319+
parents=[abstract_save_parser, abstract_retrieve_parser]
324320
)
325-
retrieve_frames_parser.add_argument(
321+
retrieve_instance_frames_parser.add_argument(
326322
'--numbers', metavar='NUM', type=int, nargs='+', dest='frame_numbers',
327323
help='frame numbers'
328324
)
329-
retrieve_frames_parser.add_argument(
325+
retrieve_instance_frames_parser.add_argument(
330326
'--show', action='store_true',
331327
help='display retrieved images'
332328
)
333-
retrieve_frames_parser.set_defaults(func=_retrieve_frames)
329+
retrieve_instance_frames_parser.set_defaults(func=_retrieve_instance_frames)
334330

335331
# WADO - bulkdata
336332
retrieve_bulkdata_parser = retrieve_subparsers.add_parser(
@@ -634,7 +630,7 @@ def _retrieve_instance_metadata(args):
634630
_print_metadata(metadata, args.prettify, args.dicomize)
635631

636632

637-
def _retrieve_frames(args):
633+
def _retrieve_instance_frames(args):
638634
'''Retrieves frames for an individual instances and either
639635
writes them to standard output or files on disk or displays them in a GUI
640636
(depending on the requested content type).
@@ -648,7 +644,7 @@ def _retrieve_frames(args):
648644
ca_bundle=args.ca_bundle,
649645
cert=args.cert
650646
)
651-
pixel_data = client.retrieve_frames(
647+
pixel_data = client.retrieve_instance_frames(
652648
args.study_instance_uid, args.series_instance_uid,
653649
args.sop_instance_uid, args.frame_numbers,
654650
media_types=args.media_types,

src/dicomweb_client/tests/test_api.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ def test_retrieve_instance_wrong_mime_type(httpserver, client, cache_dir):
367367
)
368368

369369

370-
def test_retrieve_frames_jpeg(httpserver, client, cache_dir):
370+
def test_retrieve_instance_frames_jpeg(httpserver, client, cache_dir):
371371
cache_filename = os.path.join(cache_dir, 'retrieve_instance_pixeldata.jpg')
372372
with open(cache_filename, 'rb') as f:
373373
content = f.read()
@@ -380,7 +380,7 @@ def test_retrieve_frames_jpeg(httpserver, client, cache_dir):
380380
sop_instance_uid = '1.2.5'
381381
frame_numbers = [114]
382382
frame_list = ','.join([str(n) for n in frame_numbers])
383-
result = client.retrieve_frames(
383+
result = client.retrieve_instance_frames(
384384
study_instance_uid, series_instance_uid, sop_instance_uid,
385385
frame_numbers, media_types=('image/jpeg', )
386386
)
@@ -394,8 +394,9 @@ def test_retrieve_frames_jpeg(httpserver, client, cache_dir):
394394
assert request.accept_mimetypes[0][0][:36] == headers['content-type'][:36]
395395

396396

397-
def test_retrieve_frames_jpeg_default_transfer_syntax(httpserver, client,
398-
cache_dir):
397+
def test_retrieve_instance_frames_jpeg_default_transfer_syntax(httpserver,
398+
client,
399+
cache_dir):
399400
cache_filename = os.path.join(cache_dir, 'retrieve_instance_pixeldata.jpg')
400401
with open(cache_filename, 'rb') as f:
401402
content = f.read()
@@ -407,7 +408,7 @@ def test_retrieve_frames_jpeg_default_transfer_syntax(httpserver, client,
407408
series_instance_uid = '1.2.4'
408409
sop_instance_uid = '1.2.5'
409410
frame_numbers = [114]
410-
client.retrieve_frames(
411+
client.retrieve_instance_frames(
411412
study_instance_uid, series_instance_uid, sop_instance_uid,
412413
frame_numbers, media_types=(
413414
('image/jpeg', '1.2.840.10008.1.2.4.50', ),
@@ -417,7 +418,7 @@ def test_retrieve_frames_jpeg_default_transfer_syntax(httpserver, client,
417418
assert request.accept_mimetypes[0][0][:36] == headers['content-type'][:36]
418419

419420

420-
def test_retrieve_frames_jp2(httpserver, client, cache_dir):
421+
def test_retrieve_instance_frames_jp2(httpserver, client, cache_dir):
421422
cache_filename = os.path.join(cache_dir, 'retrieve_instance_pixeldata.jp2')
422423
with open(cache_filename, 'rb') as f:
423424
content = f.read()
@@ -430,7 +431,7 @@ def test_retrieve_frames_jp2(httpserver, client, cache_dir):
430431
sop_instance_uid = '1.2.5'
431432
frame_numbers = [114]
432433
frame_list = ','.join([str(n) for n in frame_numbers])
433-
result = client.retrieve_frames(
434+
result = client.retrieve_instance_frames(
434435
study_instance_uid, series_instance_uid, sop_instance_uid,
435436
frame_numbers, media_types=('image/jp2', )
436437
)
@@ -444,7 +445,7 @@ def test_retrieve_frames_jp2(httpserver, client, cache_dir):
444445
assert request.accept_mimetypes[0][0][:35] == headers['content-type'][:35]
445446

446447

447-
def test_retrieve_frames_rendered_jpeg(httpserver, client, cache_dir):
448+
def test_retrieve_instance_frames_rendered_jpeg(httpserver, client, cache_dir):
448449
cache_filename = os.path.join(cache_dir, 'retrieve_instance_pixeldata.jpg')
449450
with open(cache_filename, 'rb') as f:
450451
content = f.read()
@@ -456,7 +457,7 @@ def test_retrieve_frames_rendered_jpeg(httpserver, client, cache_dir):
456457
series_instance_uid = '1.2.4'
457458
sop_instance_uid = '1.2.5'
458459
frame_numbers = [1]
459-
result = client.retrieve_frames_rendered(
460+
result = client.retrieve_instance_frames_rendered(
460461
study_instance_uid, series_instance_uid, sop_instance_uid,
461462
frame_numbers, media_types=('image/jpeg', )
462463
)
@@ -472,21 +473,22 @@ def test_retrieve_frames_rendered_jpeg(httpserver, client, cache_dir):
472473
assert request.accept_mimetypes[0][0][:11] == headers['content-type'][:11]
473474

474475

475-
def test_retrieve_frames_rendered_jpeg_transfer_syntax(httpserver, client):
476+
def test_retrieve_instance_frames_rendered_jpeg_transfer_syntax(httpserver,
477+
client):
476478
study_instance_uid = '1.2.3'
477479
series_instance_uid = '1.2.4'
478480
sop_instance_uid = '1.2.5'
479481
frame_numbers = [1]
480482
with pytest.raises(TypeError):
481-
client.retrieve_frames_rendered(
483+
client.retrieve_instance_frames_rendered(
482484
study_instance_uid, series_instance_uid, sop_instance_uid,
483485
frame_numbers, media_types=(
484486
('image/jpeg', '1.2.840.10008.1.2.4.50', ),
485487
)
486488
)
487489

488490

489-
def test_retrieve_frames_rendered_png(httpserver, client, cache_dir):
491+
def test_retrieve_instance_frames_rendered_png(httpserver, client, cache_dir):
490492
cache_filename = os.path.join(cache_dir, 'retrieve_instance_pixeldata.png')
491493
with open(cache_filename, 'rb') as f:
492494
content = f.read()
@@ -498,7 +500,7 @@ def test_retrieve_frames_rendered_png(httpserver, client, cache_dir):
498500
series_instance_uid = '1.2.4'
499501
sop_instance_uid = '1.2.5'
500502
frame_numbers = [1]
501-
result = client.retrieve_frames_rendered(
503+
result = client.retrieve_instance_frames_rendered(
502504
study_instance_uid, series_instance_uid, sop_instance_uid,
503505
frame_numbers, media_types=('image/png', )
504506
)

src/dicomweb_client/tests/test_cli.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -425,14 +425,14 @@ def test_parse_retrieve_instance_metadata_missing_argument_3(parser):
425425
])
426426

427427

428-
def test_parse_retrieve_frames(parser):
428+
def test_parse_retrieve_instance_frames(parser):
429429
args = parser.parse_args([
430-
'--url', 'http://localhost:8002', 'retrieve', 'frames',
430+
'--url', 'http://localhost:8002', 'retrieve', 'instances',
431431
'--study', '1.2.3', '--series', '1.2.4', '--instance', '1.2.5',
432-
'--numbers', '1'
432+
'frames', '--numbers', '1',
433433
])
434434
assert getattr(args, 'method') == 'retrieve'
435-
assert getattr(args, 'wado_ie') == 'frames'
435+
assert getattr(args, 'wado_ie') == 'instances'
436436
assert getattr(args, 'study_instance_uid') == '1.2.3'
437437
assert getattr(args, 'series_instance_uid') == '1.2.4'
438438
assert getattr(args, 'sop_instance_uid') == '1.2.5'
@@ -446,14 +446,14 @@ def test_parse_retrieve_frames(parser):
446446
assert getattr(args, 'dicomize')
447447

448448

449-
def test_parse_retrieve_frames_multiple(parser):
449+
def test_parse_retrieve_instance_frames_multiple(parser):
450450
args = parser.parse_args([
451-
'--url', 'http://localhost:8002', 'retrieve', 'frames',
451+
'--url', 'http://localhost:8002', 'retrieve', 'instances',
452452
'--study', '1.2.3', '--series', '1.2.4', '--instance', '1.2.5',
453-
'--numbers', '1', '2', '3'
453+
'frames', '--numbers', '1', '2', '3',
454454
])
455455
assert getattr(args, 'method') == 'retrieve'
456-
assert getattr(args, 'wado_ie') == 'frames'
456+
assert getattr(args, 'wado_ie') == 'instances'
457457
assert getattr(args, 'study_instance_uid') == '1.2.3'
458458
assert getattr(args, 'series_instance_uid') == '1.2.4'
459459
assert getattr(args, 'sop_instance_uid') == '1.2.5'
@@ -467,56 +467,56 @@ def test_parse_retrieve_frames_multiple(parser):
467467
assert getattr(args, 'dicomize')
468468

469469

470-
def test_parse_retrieve_frames_show(parser):
470+
def test_parse_retrieve_instance_frames_show(parser):
471471
args = parser.parse_args([
472-
'--url', 'http://localhost:8002', 'retrieve', 'frames',
472+
'--url', 'http://localhost:8002', 'retrieve', 'instances',
473473
'--study', '1.2.3', '--series', '1.2.4', '--instance', '1.2.5',
474-
'--numbers', '1', '--show'
474+
'frames', '--numbers', '1', '--show',
475475
])
476476
assert getattr(args, 'show') is True
477477
assert getattr(args, 'save') is False
478478
assert getattr(args, 'output_dir') == tempfile.gettempdir()
479479

480480

481-
def test_parse_retrieve_frames_save(parser):
481+
def test_parse_retrieve_instance_frames_save(parser):
482482
args = parser.parse_args([
483-
'--url', 'http://localhost:8002', 'retrieve', 'frames',
483+
'--url', 'http://localhost:8002', 'retrieve', 'instances',
484484
'--study', '1.2.3', '--series', '1.2.4', '--instance', '1.2.5',
485-
'--numbers', '1', '--save'
485+
'frames', '--numbers', '1', '--save',
486486
])
487487
assert getattr(args, 'show') is False
488488
assert getattr(args, 'save') is True
489489
assert getattr(args, 'output_dir') == tempfile.gettempdir()
490490

491491

492-
def test_parse_retrieve_frames_show_save(parser):
492+
def test_parse_retrieve_instance_frames_show_save(parser):
493493
args = parser.parse_args([
494-
'--url', 'http://localhost:8002', 'retrieve', 'frames',
494+
'--url', 'http://localhost:8002', 'retrieve', 'instances',
495495
'--study', '1.2.3', '--series', '1.2.4', '--instance', '1.2.5',
496-
'--numbers', '1', '--save', '--show'
496+
'frames', '--numbers', '1', '--save', '--show'
497497
])
498498
assert getattr(args, 'show') is True
499499
assert getattr(args, 'save') is True
500500
assert getattr(args, 'output_dir') == tempfile.gettempdir()
501501

502502

503-
def test_parse_retrieve_frames_save_file(parser):
503+
def test_parse_retrieve_instance_frames_save_file(parser):
504504
args = parser.parse_args([
505-
'--url', 'http://localhost:8002', 'retrieve', 'frames',
505+
'--url', 'http://localhost:8002', 'retrieve', 'instances',
506506
'--study', '1.2.3', '--series', '1.2.4', '--instance', '1.2.5',
507-
'--numbers', '1', '--save', '--output-dir', '/tmp'
507+
'frames', '--numbers', '1', '--save', '--output-dir', '/tmp',
508508
])
509509
assert getattr(args, 'show') is False
510510
assert getattr(args, 'save') is True
511511
assert getattr(args, 'output_dir') == '/tmp'
512512

513513

514-
def test_parse_retrieve_frames_missing_argument(parser):
514+
def test_parse_retrieve_instance_frames_missing_argument(parser):
515515
with pytest.raises(SystemExit):
516516
parser.parse_args([
517-
'--url', 'http://localhost:8002', 'retrieve', 'frames',
517+
'--url', 'http://localhost:8002', 'retrieve', 'instances',
518518
'--study', '1.2.3', '--series', '1.2.4', '--instance', '1.2.5',
519-
'--numbers'
519+
'frames', '--numbers',
520520
])
521521

522522

0 commit comments

Comments
 (0)