dbdicom 0.2.5__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dbdicom might be problematic. Click here for more details.
- dbdicom/__init__.py +1 -28
- dbdicom/api.py +267 -0
- dbdicom/const.py +144 -0
- dbdicom/dataset.py +752 -0
- dbdicom/dbd.py +719 -0
- dbdicom/external/__pycache__/__init__.cpython-311.pyc +0 -0
- dbdicom/external/dcm4che/__pycache__/__init__.cpython-311.pyc +0 -0
- dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-311.pyc +0 -0
- dbdicom/register.py +527 -0
- dbdicom/{ds/types → sop_classes}/ct_image.py +2 -16
- dbdicom/{ds/types → sop_classes}/enhanced_mr_image.py +153 -26
- dbdicom/{ds/types → sop_classes}/mr_image.py +185 -140
- dbdicom/sop_classes/parametric_map.py +307 -0
- dbdicom/sop_classes/secondary_capture.py +140 -0
- dbdicom/sop_classes/segmentation.py +311 -0
- dbdicom/{ds/types → sop_classes}/ultrasound_multiframe_image.py +1 -15
- dbdicom/{ds/types → sop_classes}/xray_angiographic_image.py +2 -17
- dbdicom/utils/arrays.py +36 -0
- dbdicom/utils/files.py +0 -20
- dbdicom/utils/image.py +10 -629
- dbdicom-0.3.0.dist-info/METADATA +28 -0
- dbdicom-0.3.0.dist-info/RECORD +53 -0
- {dbdicom-0.2.5.dist-info → dbdicom-0.3.0.dist-info}/WHEEL +1 -1
- dbdicom/create.py +0 -457
- dbdicom/dro.py +0 -174
- dbdicom/ds/__init__.py +0 -10
- dbdicom/ds/create.py +0 -63
- dbdicom/ds/dataset.py +0 -869
- dbdicom/ds/dictionaries.py +0 -620
- dbdicom/ds/types/parametric_map.py +0 -226
- dbdicom/extensions/__init__.py +0 -9
- dbdicom/extensions/dipy.py +0 -448
- dbdicom/extensions/elastix.py +0 -503
- dbdicom/extensions/matplotlib.py +0 -107
- dbdicom/extensions/numpy.py +0 -271
- dbdicom/extensions/scipy.py +0 -1512
- dbdicom/extensions/skimage.py +0 -1030
- dbdicom/extensions/sklearn.py +0 -243
- dbdicom/extensions/vreg.py +0 -1390
- dbdicom/manager.py +0 -2132
- dbdicom/message.py +0 -119
- dbdicom/pipelines.py +0 -66
- dbdicom/record.py +0 -1893
- dbdicom/types/database.py +0 -107
- dbdicom/types/instance.py +0 -231
- dbdicom/types/patient.py +0 -40
- dbdicom/types/series.py +0 -2874
- dbdicom/types/study.py +0 -58
- dbdicom-0.2.5.dist-info/METADATA +0 -71
- dbdicom-0.2.5.dist-info/RECORD +0 -66
- {dbdicom-0.2.5.dist-info → dbdicom-0.3.0.dist-info/licenses}/LICENSE +0 -0
- {dbdicom-0.2.5.dist-info → dbdicom-0.3.0.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
dbdicom/register.py
ADDED
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
COLUMNS = [
|
|
6
|
+
# Identifiers (unique)
|
|
7
|
+
'PatientID',
|
|
8
|
+
'StudyInstanceUID',
|
|
9
|
+
'SeriesInstanceUID',
|
|
10
|
+
'SOPInstanceUID',
|
|
11
|
+
# Human-readable identifiers (not unique)
|
|
12
|
+
'PatientName',
|
|
13
|
+
'StudyDescription',
|
|
14
|
+
'StudyDate',
|
|
15
|
+
'SeriesDescription',
|
|
16
|
+
'SeriesNumber',
|
|
17
|
+
'InstanceNumber',
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def index(df:pd.DataFrame, entity):
|
|
22
|
+
if isinstance(entity, str):
|
|
23
|
+
rows = (df.removed==False)
|
|
24
|
+
elif len(entity)==2:
|
|
25
|
+
patient_id = uid(df, entity)
|
|
26
|
+
rows = (df.PatientID==patient_id) & (df.removed==False)
|
|
27
|
+
elif len(entity)==3:
|
|
28
|
+
study_uid = uid(df, entity)
|
|
29
|
+
rows = (df.StudyInstanceUID==study_uid) & (df.removed==False)
|
|
30
|
+
elif len(entity)==4:
|
|
31
|
+
series_uid = uid(df, entity)
|
|
32
|
+
rows = (df.SeriesInstanceUID==series_uid) & (df.removed==False)
|
|
33
|
+
return df.index[rows].tolist()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def files(df:pd.DataFrame, entity):
|
|
37
|
+
# Raises an error if the entity does not exist or has no files
|
|
38
|
+
df.sort_values(['PatientID', 'StudyInstanceUID', 'SeriesNumber', 'InstanceNumber'], inplace=True)
|
|
39
|
+
relpath = index(df, entity)
|
|
40
|
+
if relpath==[]:
|
|
41
|
+
raise ValueError(f'No files in entity {entity}')
|
|
42
|
+
if isinstance(entity, str):
|
|
43
|
+
return [os.path.join(entity, f) for f in relpath]
|
|
44
|
+
else:
|
|
45
|
+
return [os.path.join(entity[0], f) for f in relpath]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _prep(df:pd.DataFrame):
|
|
49
|
+
df = df[df.removed == False]
|
|
50
|
+
df.sort_values(['PatientID','StudyInstanceUID','SeriesNumber'], inplace=True)
|
|
51
|
+
return df
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def entity(df, path, uid):# information entity from uid
|
|
55
|
+
df = _prep(df)
|
|
56
|
+
|
|
57
|
+
patient_idx = {}
|
|
58
|
+
for uid_patient in df.PatientID.dropna().unique():
|
|
59
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
60
|
+
patient_name = df_patient.PatientName.values[0]
|
|
61
|
+
if patient_name in patient_idx:
|
|
62
|
+
patient_idx[patient_name] += 1
|
|
63
|
+
else:
|
|
64
|
+
patient_idx[patient_name] = 0
|
|
65
|
+
patient_desc = (patient_name, patient_idx[patient_name])
|
|
66
|
+
if uid == uid_patient:
|
|
67
|
+
return [path, patient_desc]
|
|
68
|
+
|
|
69
|
+
else:
|
|
70
|
+
|
|
71
|
+
study_idx = {}
|
|
72
|
+
for uid_study in df_patient.StudyInstanceUID.dropna().unique():
|
|
73
|
+
df_study = df_patient[df_patient.StudyInstanceUID == uid_study]
|
|
74
|
+
study_name = df_study.StudyDescription.values[0]
|
|
75
|
+
if study_name in study_idx:
|
|
76
|
+
study_idx[study_name] += 1
|
|
77
|
+
else:
|
|
78
|
+
study_idx[study_name] = 0
|
|
79
|
+
study_desc = (study_name, study_idx[study_name])
|
|
80
|
+
if uid == uid_study:
|
|
81
|
+
return [path, patient_desc, study_desc]
|
|
82
|
+
|
|
83
|
+
else:
|
|
84
|
+
|
|
85
|
+
series_idx = {}
|
|
86
|
+
for uid_series in df_study.SeriesInstanceUID.dropna().unique():
|
|
87
|
+
df_series = df_study[df_study.SeriesInstanceUID == uid_series]
|
|
88
|
+
series_name = df_series.SeriesDescription.values[0]
|
|
89
|
+
if series_name in series_idx:
|
|
90
|
+
series_idx[series_name] += 1
|
|
91
|
+
else:
|
|
92
|
+
series_idx[series_name] = 0
|
|
93
|
+
series_desc = (series_name, series_idx[series_name])
|
|
94
|
+
if uid == uid_series:
|
|
95
|
+
return [path, patient_desc, study_desc, series_desc]
|
|
96
|
+
|
|
97
|
+
raise ValueError(f"No information entity with UID {uid} was found.")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def uid(df, entity): # uid from entity
|
|
101
|
+
df = df[df.removed == False]
|
|
102
|
+
if len(entity)==2:
|
|
103
|
+
return _patient_uid(df, entity)
|
|
104
|
+
if len(entity)==3:
|
|
105
|
+
return _study_uid(df, entity)
|
|
106
|
+
if len(entity)==4:
|
|
107
|
+
return _series_uid(df, entity)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _patient_uid(df, patient):
|
|
111
|
+
patient = patient[1]
|
|
112
|
+
df = df[df.removed == False]
|
|
113
|
+
patients = {}
|
|
114
|
+
patient_idx = {}
|
|
115
|
+
for uid_patient in df.PatientID.dropna().unique():
|
|
116
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
117
|
+
patient_name = df_patient.PatientName.values[0]
|
|
118
|
+
if patient_name in patient_idx:
|
|
119
|
+
patient_idx[patient_name] += 1
|
|
120
|
+
else:
|
|
121
|
+
patient_idx[patient_name] = 0
|
|
122
|
+
patient_desc = (patient_name, patient_idx[patient_name])
|
|
123
|
+
if patient == patient_desc:
|
|
124
|
+
return uid_patient
|
|
125
|
+
patients[patient_desc] = uid_patient
|
|
126
|
+
if isinstance(patient, str):
|
|
127
|
+
patient_list = [p for p in patients.keys() if p[0]==patient]
|
|
128
|
+
if len(patient_list) == 1:
|
|
129
|
+
return patients[(patient, 0)]
|
|
130
|
+
elif len(patient_list) > 1:
|
|
131
|
+
raise ValueError(
|
|
132
|
+
f"Multiple patients with name {patient}."
|
|
133
|
+
f"Please specify the index in the call to patient_uid(). "
|
|
134
|
+
f"For instance ({patient}, {len(patients)-1})'. "
|
|
135
|
+
)
|
|
136
|
+
raise ValueError(f"Patient {patient} not found in database.")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _study_uid(df, study):
|
|
140
|
+
uid_patient = _patient_uid(df, study[:-1])
|
|
141
|
+
patient, study = study[1], study[2]
|
|
142
|
+
df = df[df.removed == False] # TODO_manager must do this before passing df
|
|
143
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
144
|
+
studies = {}
|
|
145
|
+
study_idx = {}
|
|
146
|
+
for uid_study in df_patient.StudyInstanceUID.dropna().unique():
|
|
147
|
+
df_study = df_patient[df_patient.StudyInstanceUID == uid_study]
|
|
148
|
+
study_desc = df_study.StudyDescription.values[0]
|
|
149
|
+
if study_desc in study_idx:
|
|
150
|
+
study_idx[study_desc] += 1
|
|
151
|
+
else:
|
|
152
|
+
study_idx[study_desc] = 0
|
|
153
|
+
study_desc = (study_desc, study_idx[study_desc])
|
|
154
|
+
if study == study_desc:
|
|
155
|
+
return uid_study
|
|
156
|
+
studies[study_desc] = uid_study
|
|
157
|
+
if isinstance(study, str):
|
|
158
|
+
studies_list = [s for s in studies.keys() if s[0]==study]
|
|
159
|
+
if len(studies_list) == 1:
|
|
160
|
+
return studies[(study, 0)]
|
|
161
|
+
elif len(studies_list) > 1:
|
|
162
|
+
raise ValueError(
|
|
163
|
+
f"Multiple studies with name {study}."
|
|
164
|
+
f"Please specify the index in the call to study_uid(). "
|
|
165
|
+
f"For instance ({study}, {len(studies)-1})'. "
|
|
166
|
+
)
|
|
167
|
+
raise ValueError(f"Study {study} not found in patient {patient}.")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _series_uid(df, series): # absolute path to series
|
|
171
|
+
uid_study = _study_uid(df, series[:-1])
|
|
172
|
+
study, sery = series[2], series[3]
|
|
173
|
+
df = df[df.removed == False]
|
|
174
|
+
df_study = df[df.StudyInstanceUID == uid_study]
|
|
175
|
+
series = {}
|
|
176
|
+
series_idx = {}
|
|
177
|
+
for uid_series in df_study.SeriesInstanceUID.dropna().unique():
|
|
178
|
+
df_series = df_study[df_study.SeriesInstanceUID == uid_series]
|
|
179
|
+
series_desc = df_series.SeriesDescription.values[0]
|
|
180
|
+
if series_desc in series_idx:
|
|
181
|
+
series_idx[series_desc] += 1
|
|
182
|
+
else:
|
|
183
|
+
series_idx[series_desc] = 0
|
|
184
|
+
series_desc = (series_desc, series_idx[series_desc])
|
|
185
|
+
if sery == series_desc:
|
|
186
|
+
return uid_series
|
|
187
|
+
series[series_desc] = uid_series
|
|
188
|
+
if isinstance(sery, str):
|
|
189
|
+
series_list = [s for s in series.keys() if s[0]==sery]
|
|
190
|
+
if len(series_list) == 1:
|
|
191
|
+
return series[(sery, 0)]
|
|
192
|
+
elif len(series_list) > 1:
|
|
193
|
+
raise ValueError(
|
|
194
|
+
f"Multiple series with name {sery}."
|
|
195
|
+
f"Please specify the index in the call to series_uid(). "
|
|
196
|
+
f"For instance ({sery}, {len(series)-1})'. "
|
|
197
|
+
)
|
|
198
|
+
raise ValueError(f"Series {sery} not found in study {study}.")
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def patients(df, database, name=None, contains=None, isin=None):
|
|
202
|
+
df = _prep(df)
|
|
203
|
+
simplified_patients = []
|
|
204
|
+
patients = []
|
|
205
|
+
patient_idx = {}
|
|
206
|
+
for uid_patient in df.PatientID.dropna().unique():
|
|
207
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
208
|
+
patient_name = df_patient.PatientName.values[0]
|
|
209
|
+
if patient_name in patient_idx:
|
|
210
|
+
patient_idx[patient_name] += 1
|
|
211
|
+
else:
|
|
212
|
+
patient_idx[patient_name] = 0
|
|
213
|
+
patients.append((patient_name, patient_idx[patient_name]))
|
|
214
|
+
for patient in patients:
|
|
215
|
+
if patient_idx[patient[0]] == 0:
|
|
216
|
+
simplified_patients.append(patient[0])
|
|
217
|
+
else:
|
|
218
|
+
simplified_patients.append(patient)
|
|
219
|
+
if name is not None:
|
|
220
|
+
patients_result = []
|
|
221
|
+
for s in simplified_patients:
|
|
222
|
+
if isinstance(s, str):
|
|
223
|
+
if s == name:
|
|
224
|
+
patients_result.append(s)
|
|
225
|
+
elif s[0] == name:
|
|
226
|
+
patients_result.append(s)
|
|
227
|
+
return [[path, p] for p in patients_result]
|
|
228
|
+
elif contains is not None:
|
|
229
|
+
patients_result = []
|
|
230
|
+
for s in simplified_patients:
|
|
231
|
+
if isinstance(s, str):
|
|
232
|
+
if contains in s:
|
|
233
|
+
patients_result.append(s)
|
|
234
|
+
elif contains in s[0]:
|
|
235
|
+
patients_result.append(s)
|
|
236
|
+
return [[database, p] for p in patients_result]
|
|
237
|
+
elif isin is not None:
|
|
238
|
+
patients_result = []
|
|
239
|
+
for s in simplified_patients:
|
|
240
|
+
if isinstance(s, str):
|
|
241
|
+
if s in isin:
|
|
242
|
+
patients_result.append(s)
|
|
243
|
+
elif s[0] in isin:
|
|
244
|
+
patients_result.append(s)
|
|
245
|
+
return [[database, p] for p in patients_result]
|
|
246
|
+
else:
|
|
247
|
+
return [[database, p] for p in simplified_patients]
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def studies(df, pat, name=None, contains=None, isin=None):
|
|
251
|
+
database, patient = pat[0], pat[1]
|
|
252
|
+
patient_as_str = isinstance(patient, str)
|
|
253
|
+
if patient_as_str:
|
|
254
|
+
patient = (patient, 0)
|
|
255
|
+
df = _prep(df)
|
|
256
|
+
simplified_studies = []
|
|
257
|
+
patient_idx = {}
|
|
258
|
+
for uid_patient in df.PatientID.dropna().unique():
|
|
259
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
260
|
+
patient_name = df_patient.PatientName.values[0]
|
|
261
|
+
if patient_name in patient_idx:
|
|
262
|
+
patient_idx[patient_name] += 1
|
|
263
|
+
else:
|
|
264
|
+
patient_idx[patient_name] = 0
|
|
265
|
+
if patient[0] == patient_name:
|
|
266
|
+
if patient_as_str:
|
|
267
|
+
if patient_idx[patient_name] > 0:
|
|
268
|
+
raise ValueError(
|
|
269
|
+
f"Multiple patients named {patient_name}. "
|
|
270
|
+
"Please provide an index along with the patient name."
|
|
271
|
+
)
|
|
272
|
+
if patient == (patient_name, patient_idx[patient_name]):
|
|
273
|
+
studies = []
|
|
274
|
+
study_idx = {}
|
|
275
|
+
for uid_study in df_patient.StudyInstanceUID.dropna().unique():
|
|
276
|
+
df_study = df_patient[df_patient.StudyInstanceUID == uid_study]
|
|
277
|
+
study_desc = df_study.StudyDescription.values[0]
|
|
278
|
+
if study_desc in study_idx:
|
|
279
|
+
study_idx[study_desc] += 1
|
|
280
|
+
else:
|
|
281
|
+
study_idx[study_desc] = 0
|
|
282
|
+
studies.append((study_desc, study_idx[study_desc]))
|
|
283
|
+
for study in studies:
|
|
284
|
+
if study_idx[study[0]] == 0:
|
|
285
|
+
simplified_studies.append(study[0])
|
|
286
|
+
else:
|
|
287
|
+
simplified_studies.append(study)
|
|
288
|
+
if not patient_as_str:
|
|
289
|
+
break
|
|
290
|
+
if name is not None:
|
|
291
|
+
studies_result = []
|
|
292
|
+
for s in simplified_studies:
|
|
293
|
+
if isinstance(s, str):
|
|
294
|
+
if s == name:
|
|
295
|
+
studies_result.append(s)
|
|
296
|
+
elif s[0] == name:
|
|
297
|
+
studies_result.append(s)
|
|
298
|
+
return [[database, patient, study] for study in studies_result]
|
|
299
|
+
elif contains is not None:
|
|
300
|
+
studies_result = []
|
|
301
|
+
for s in simplified_studies:
|
|
302
|
+
if isinstance(s, str):
|
|
303
|
+
if contains in s:
|
|
304
|
+
studies_result.append(s)
|
|
305
|
+
elif contains in s[0]:
|
|
306
|
+
studies_result.append(s)
|
|
307
|
+
return [[database, patient, study] for study in studies_result]
|
|
308
|
+
elif isin is not None:
|
|
309
|
+
studies_result = []
|
|
310
|
+
for s in simplified_studies:
|
|
311
|
+
if isinstance(s, str):
|
|
312
|
+
if s in isin:
|
|
313
|
+
studies_result.append(s)
|
|
314
|
+
elif s[0] in isin:
|
|
315
|
+
studies_result.append(s)
|
|
316
|
+
return [[database, patient, study] for study in studies_result]
|
|
317
|
+
else:
|
|
318
|
+
return [[database, patient, study] for study in simplified_studies]
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def series(df, stdy, name=None, contains=None, isin=None):
|
|
323
|
+
database, patient, study = stdy[0], stdy[1], stdy[2]
|
|
324
|
+
patient_as_str = isinstance(patient, str)
|
|
325
|
+
if patient_as_str:
|
|
326
|
+
patient = (patient, 0)
|
|
327
|
+
study_as_str = isinstance(study, str)
|
|
328
|
+
if study_as_str:
|
|
329
|
+
study = (study, 0)
|
|
330
|
+
df = _prep(df)
|
|
331
|
+
simplified_series = []
|
|
332
|
+
patient_idx = {}
|
|
333
|
+
for uid_patient in df.PatientID.dropna().unique():
|
|
334
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
335
|
+
patient_name = df_patient.PatientName.values[0]
|
|
336
|
+
if patient_name in patient_idx:
|
|
337
|
+
patient_idx[patient_name] += 1
|
|
338
|
+
else:
|
|
339
|
+
patient_idx[patient_name] = 0
|
|
340
|
+
if patient[0] == patient_name:
|
|
341
|
+
if patient_as_str:
|
|
342
|
+
if patient_idx[patient_name] > 0:
|
|
343
|
+
raise ValueError(
|
|
344
|
+
f"Multiple patients named {patient_name}. Please provide an index along with the patient name."
|
|
345
|
+
)
|
|
346
|
+
if patient == (patient_name, patient_idx[patient_name]):
|
|
347
|
+
study_idx = {}
|
|
348
|
+
for uid_study in df_patient.StudyInstanceUID.dropna().unique():
|
|
349
|
+
df_study = df_patient[df_patient.StudyInstanceUID == uid_study]
|
|
350
|
+
study_desc = df_study.StudyDescription.values[0]
|
|
351
|
+
if study_desc in study_idx:
|
|
352
|
+
study_idx[study_desc] += 1
|
|
353
|
+
else:
|
|
354
|
+
study_idx[study_desc] = 0
|
|
355
|
+
if study[0] == study_desc:
|
|
356
|
+
if study_as_str:
|
|
357
|
+
if study_idx[study_desc] > 0:
|
|
358
|
+
raise ValueError(
|
|
359
|
+
f"Multiple studies named {study_desc} in patient {patient_name}. Please provide an index along with the study description."
|
|
360
|
+
)
|
|
361
|
+
if study == (study_desc, study_idx[study_desc]):
|
|
362
|
+
series = []
|
|
363
|
+
series_idx = {}
|
|
364
|
+
for uid_sery in df_study.SeriesInstanceUID.dropna().unique():
|
|
365
|
+
df_series = df_study[df_study.SeriesInstanceUID == uid_sery]
|
|
366
|
+
series_desc = df_series.SeriesDescription.values[0]
|
|
367
|
+
if series_desc in series_idx:
|
|
368
|
+
series_idx[series_desc] += 1
|
|
369
|
+
else:
|
|
370
|
+
series_idx[series_desc] = 0
|
|
371
|
+
series.append((series_desc, series_idx[series_desc]))
|
|
372
|
+
for sery in series:
|
|
373
|
+
if series_idx[sery[0]] == 0:
|
|
374
|
+
simplified_series.append(sery[0])
|
|
375
|
+
else:
|
|
376
|
+
simplified_series.append(sery)
|
|
377
|
+
if not (patient_as_str or study_as_str):
|
|
378
|
+
break
|
|
379
|
+
if name is not None:
|
|
380
|
+
series_result = []
|
|
381
|
+
for s in simplified_series:
|
|
382
|
+
if isinstance(s, str):
|
|
383
|
+
if s == name:
|
|
384
|
+
series_result.append(s)
|
|
385
|
+
elif s[0] == name:
|
|
386
|
+
series_result.append(s)
|
|
387
|
+
return [[database, patient, study, series] for series in series_result]
|
|
388
|
+
elif contains is not None:
|
|
389
|
+
series_result = []
|
|
390
|
+
for s in simplified_series:
|
|
391
|
+
if isinstance(s, str):
|
|
392
|
+
if contains in s:
|
|
393
|
+
series_result.append(s)
|
|
394
|
+
elif contains in s[0]:
|
|
395
|
+
series_result.append(s)
|
|
396
|
+
return [[database, patient, study, series] for series in series_result]
|
|
397
|
+
elif isin is not None:
|
|
398
|
+
series_result = []
|
|
399
|
+
for s in simplified_series:
|
|
400
|
+
if isinstance(s, str):
|
|
401
|
+
if s in isin:
|
|
402
|
+
series_result.append(s)
|
|
403
|
+
elif s[0] in isin:
|
|
404
|
+
series_result.append(s)
|
|
405
|
+
return [[database, patient, study, series] for series in series_result]
|
|
406
|
+
else:
|
|
407
|
+
return [[database, patient, study, series] for series in simplified_series]
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def print_tree(df):
|
|
411
|
+
tree = summary(df)
|
|
412
|
+
for patient, studies in tree.items():
|
|
413
|
+
print(f"Patient: ({patient[0]}, {patient[1]})")
|
|
414
|
+
for study, series in studies.items():
|
|
415
|
+
print(f" Study: ({study[0]}, {study[1]})")
|
|
416
|
+
for s in series:
|
|
417
|
+
print(f" Series: ({s[0]}, {s[1]})")
|
|
418
|
+
|
|
419
|
+
def append(df, parent, child_name):
|
|
420
|
+
if len(parent) == 1:
|
|
421
|
+
return _new_patient(df, parent, child_name)
|
|
422
|
+
elif len(parent) == 2:
|
|
423
|
+
return _new_study(df, parent, child_name)
|
|
424
|
+
elif len(parent) == 3:
|
|
425
|
+
return _new_series(df, parent, child_name)
|
|
426
|
+
|
|
427
|
+
def _new_patient(df, database, patient_name):
|
|
428
|
+
# Count the number of series with the same description
|
|
429
|
+
desc = patient_name if isinstance(patient_name, str) else patient_name[0]
|
|
430
|
+
patients_in_db = patients(df, database, name=desc)
|
|
431
|
+
cnt = len(patients_in_db)
|
|
432
|
+
if cnt==0:
|
|
433
|
+
return [database, desc]
|
|
434
|
+
else:
|
|
435
|
+
return [database, (desc, cnt+1)]
|
|
436
|
+
|
|
437
|
+
def _new_study(df, patient, study_name): #len(patient)=2
|
|
438
|
+
# Count the number of series with the same description
|
|
439
|
+
desc = study_name if isinstance(study_name, str) else study_name[0]
|
|
440
|
+
studies_in_patient = studies(df, patient, name=desc)
|
|
441
|
+
cnt = len(studies_in_patient)
|
|
442
|
+
if cnt==0:
|
|
443
|
+
return patient + [desc]
|
|
444
|
+
else:
|
|
445
|
+
return patient + [(desc, cnt+1)]
|
|
446
|
+
|
|
447
|
+
def _new_series(df, study, series_name): #len(study)=3
|
|
448
|
+
# Count the number of series with the same description
|
|
449
|
+
desc = series_name if isinstance(series_name, str) else series_name[0]
|
|
450
|
+
series_in_study = series(df, study, name=desc)
|
|
451
|
+
cnt = len(series_in_study)
|
|
452
|
+
if cnt==0:
|
|
453
|
+
return study + [desc]
|
|
454
|
+
else:
|
|
455
|
+
return study + [(desc, cnt+1)]
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def uid_tree(df, path, depth=3):
|
|
459
|
+
|
|
460
|
+
if df is None:
|
|
461
|
+
raise ValueError('Cannot build tree - no database open')
|
|
462
|
+
df = df[df.removed == False]
|
|
463
|
+
df.sort_values(['PatientName','StudyDate','SeriesNumber','InstanceNumber'], inplace=True)
|
|
464
|
+
|
|
465
|
+
database = {'uid': path}
|
|
466
|
+
database['patients'] = []
|
|
467
|
+
for uid_patient in df.PatientID.dropna().unique():
|
|
468
|
+
patient = {'uid': uid_patient}
|
|
469
|
+
database['patients'].append(patient)
|
|
470
|
+
if depth >= 1:
|
|
471
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
472
|
+
patient['key'] = df_patient.index[0]
|
|
473
|
+
patient['studies'] = []
|
|
474
|
+
for uid_study in df_patient.StudyInstanceUID.dropna().unique():
|
|
475
|
+
study = {'uid': uid_study}
|
|
476
|
+
patient['studies'].append(study)
|
|
477
|
+
if depth >= 2:
|
|
478
|
+
df_study = df_patient[df_patient.StudyInstanceUID == uid_study]
|
|
479
|
+
study['key'] = df_study.index[0]
|
|
480
|
+
study['series'] = []
|
|
481
|
+
for uid_sery in df_study.SeriesInstanceUID.dropna().unique():
|
|
482
|
+
series = {'uid': uid_sery}
|
|
483
|
+
study['series'].append(series)
|
|
484
|
+
if depth == 3:
|
|
485
|
+
df_series = df_study[df_study.SeriesInstanceUID == uid_sery]
|
|
486
|
+
series['key'] = df_series.index[0]
|
|
487
|
+
return database
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def summary(df):
|
|
492
|
+
# A human-readable summary tree
|
|
493
|
+
|
|
494
|
+
df = _prep(df)
|
|
495
|
+
summary = {}
|
|
496
|
+
|
|
497
|
+
patient_idx = {}
|
|
498
|
+
for uid_patient in df.PatientID.dropna().unique():
|
|
499
|
+
df_patient = df[df.PatientID == uid_patient]
|
|
500
|
+
patient_name = df_patient.PatientName.values[0]
|
|
501
|
+
if patient_name in patient_idx:
|
|
502
|
+
patient_idx[patient_name] += 1
|
|
503
|
+
else:
|
|
504
|
+
patient_idx[patient_name] = 0
|
|
505
|
+
summary[patient_name, patient_idx[patient_name]] = {}
|
|
506
|
+
|
|
507
|
+
study_idx = {}
|
|
508
|
+
for uid_study in df_patient.StudyInstanceUID.dropna().unique():
|
|
509
|
+
df_study = df_patient[df_patient.StudyInstanceUID == uid_study]
|
|
510
|
+
study_desc = df_study.StudyDescription.values[0]
|
|
511
|
+
if study_desc in study_idx:
|
|
512
|
+
study_idx[study_desc] += 1
|
|
513
|
+
else:
|
|
514
|
+
study_idx[study_desc] = 0
|
|
515
|
+
summary[patient_name, patient_idx[patient_name]][study_desc, study_idx[study_desc]] = []
|
|
516
|
+
|
|
517
|
+
series_idx = {}
|
|
518
|
+
for uid_sery in df_study.SeriesInstanceUID.dropna().unique():
|
|
519
|
+
df_series = df_study[df_study.SeriesInstanceUID == uid_sery]
|
|
520
|
+
series_desc = df_series.SeriesDescription.values[0]
|
|
521
|
+
if series_desc in series_idx:
|
|
522
|
+
series_idx[series_desc] += 1
|
|
523
|
+
else:
|
|
524
|
+
series_idx[series_desc] = 0
|
|
525
|
+
summary[patient_name, patient_idx[patient_name]][study_desc, study_idx[study_desc]].append((series_desc, series_idx[series_desc]))
|
|
526
|
+
|
|
527
|
+
return summary
|
|
@@ -2,25 +2,11 @@
|
|
|
2
2
|
# Produced by pydicom codify utility script
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pydicom
|
|
5
|
-
from pydicom.dataset import
|
|
5
|
+
from pydicom.dataset import FileMetaDataset
|
|
6
6
|
from pydicom.sequence import Sequence
|
|
7
7
|
|
|
8
|
-
from dbdicom.ds.dataset import DbDataset
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
def __init__(self, dataset=None, template=None):
|
|
12
|
-
super().__init__()
|
|
13
|
-
|
|
14
|
-
if (dataset is None) and (template is None):
|
|
15
|
-
template = 'VPH'
|
|
16
|
-
|
|
17
|
-
if dataset is not None:
|
|
18
|
-
self.__dict__ = dataset.__dict__
|
|
19
|
-
|
|
20
|
-
if template == 'VPH':
|
|
21
|
-
vph(self)
|
|
22
|
-
|
|
23
|
-
def vph(ds):
|
|
9
|
+
def default(ds): #VPH
|
|
24
10
|
|
|
25
11
|
# File meta info data elements
|
|
26
12
|
ds.file_meta = FileMetaDataset()
|