1- """Combines WADO and MINT to make make getting DICOM studies easy"""
1+ """Combines WADO and MINT to make make getting DICOM studies easy
2+
3+ Notes
4+ -----
5+ Design choices:
6+
7+ WADO and MINT modules should remain un-entangled so are not allowed to use
8+ each other's classes. Core has knowledge of both an can convert classes between the
9+ two if needed
10+
11+ """
212
3- from itertools import chain
413from pathlib import Path
5- from typing import List , Sequence
14+ from typing import List , Sequence , Union
615
716from dicomtrolley .mint import (
817 Mint ,
1120 MintStudy ,
1221)
1322from dicomtrolley .query import Query , QueryLevels
14- from dicomtrolley .wado import Wado
23+ from dicomtrolley .wado import InstanceReference , Wado
1524
1625
1726class Trolley :
18- """Combines WADO and MINT to make make getting DICOM studies easy
19-
20- Offers three different types of functions:
21- * Find - Search for things on server, but do not download yet
22- * Download - Quick methods that download some data to disk
23- * Get - Return pydicom datasets directly without writing to disk
24- """
27+ """Combines WADO and MINT to make make getting DICOM studies easy"""
2528
2629 def __init__ (self , wado : Wado , mint : Mint ):
2730 self .wado = wado
@@ -61,7 +64,7 @@ def download_study(self, study_instance_uid, output_dir):
6164 storage .save (dataset )
6265
6366 def fetch_all_datasets (self , mint_objects : List [MintObject ]):
64- """Get full DICOM dataset for each instance in study. Calls mint and wado
67+ """Get full DICOM dataset for each instance in study
6568
6669 Parameters
6770 ----------
@@ -73,36 +76,66 @@ def fetch_all_datasets(self, mint_objects: List[MintObject]):
7376 Generator[Dataset, None, None]
7477 The downloaded dataset and the context that was used to download it
7578 """
76-
77- for instance in self .extract_instances (mint_objects ):
78- yield self .get_dataset (instance )
79+ for ds in self .wado .datasets (self .extract_instances (mint_objects )):
80+ yield ds
7981
8082 @staticmethod
81- def extract_instances (mint_objects : Sequence [MintObject ]):
82- """Get all individual instances from input.
83+ def extract_instances (
84+ objects : Sequence [Union [MintObject , InstanceReference ]]
85+ ):
86+ """Get all individual instances from input
87+
88+ A pre-processing step for getting datasets
8389
8490 Parameters
8591 ----------
86- mint_objects : Sequence[MintObject]
92+ objects : Sequence[MintObject]
8793 Any combination of MintStudy, MintSeries and MintInstance instances
8894
89- A pre-processing step for getting datasets
95+ Returns
96+ -------
97+ List[InstanceReference]
98+ A reference to each instance (slice)
99+
90100 """
91- return list (chain (* (x .all_instances () for x in mint_objects )))
101+ instances = []
102+ for item in objects :
103+ if isinstance (item , InstanceReference ):
104+ instances .append (item )
105+ else :
106+ instances = instances + [
107+ to_reference (x ) for x in item .all_instances ()
108+ ]
109+ return instances
110+
111+ def fetch_all_datasets_async (self , mint_objects , max_workers = None ):
112+ """Get full DICOM dataset for each instance in study using multiple threads
113+
114+ Parameters
115+ ----------
116+ mint_objects: List[MintObject]
117+ get dataset for each instance contained in these objects
118+ max_workers: int, optional
119+ Max number of ThreadPoolExecutor workers to use. Defaults to
120+ ThreadPoolExecutor default
92121
93- def get_dataset (self , instance : MintInstance ):
94- """Get all DICOM data for this instance from server
122+ Raises
123+ ------
124+ DICOMTrolleyException
125+ If getting or parsing of any instance fails
95126
96127 Returns
97128 -------
98- Dataset
129+ Iterator[Dataset, None, None]
130+ The downloaded dataset and the context that was used to download it
131+
99132 """
100133
101- return self .wado .get_dataset (
102- study_instance_uid = instance . parent . parent . uid ,
103- series_instance_uid = instance . parent . uid ,
104- sop_instance_iud = instance . uid ,
105- )
134+ for ds in self .wado .datasets_async (
135+ instances = self . extract_instances ( mint_objects ) ,
136+ max_workers = max_workers ,
137+ ):
138+ yield ds
106139
107140
108141class DICOMStorageDir :
@@ -133,4 +166,15 @@ def generate_path(self, dataset):
133166 def get_value (dataset , tag_name ):
134167 """Extract value for use in path. If not found return default"""
135168 default = "unknown"
136- return dataset .get (tag_name , default ).replace ("." , "_" )
169+ return str (dataset .get (tag_name , default )).replace ("." , "_" )
170+
171+
172+ def to_reference (instance : MintInstance ) -> InstanceReference :
173+ """Simplify a more extensive MINT instance to an InstanceReference
174+ needed for calls to WADO functions
175+ """
176+ return InstanceReference (
177+ study_instance_uid = instance .parent .parent .uid ,
178+ series_instance_uid = instance .parent .uid ,
179+ sop_instance_iud = instance .uid ,
180+ )
0 commit comments