-
Notifications
You must be signed in to change notification settings - Fork 0
/
range_query.py
135 lines (117 loc) · 4.3 KB
/
range_query.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import argparse
import sys
import io
import pandas as pd
from pydicom.dataset import Dataset
from logzero import logger
import tqdm
import qr
import date_utils
EXT_TABLE = {
'.csv': 'to_csv',
'.xlsx': 'to_excel',
}
def main():
parser = argparse.ArgumentParser(
description='Range based DICOM query.',
epilog=
'Use --add option with no value to query for additional fields. e.g. --add "ImageType="'
)
parser.add_argument('start',
help="Range start. (YYYYmmdd) e.g. 20201014",
metavar='<start>')
parser.add_argument('end', help="Range end. (YYYYmmdd)", metavar='<end>')
parser.add_argument('--output',
help="Output filename. Default: <start>-<end>.csv",
metavar='<output>')
parser.add_argument(
'--step',
help="Step size for query range in days. Default: %(default)s",
default=2,
type=int,
metavar='<int>')
parser.add_argument(
'--ext',
help=
"File extension for the output. Default: %(default)s. Choices: [%(choices)s]",
default='.csv',
choices=EXT_TABLE.keys(),
metavar='<ext>')
parser.add_argument('--add',
help="Additional condition for the query",
metavar='<key=value>',
default=[],
nargs='+')
parser.add_argument(
'--qrlevel',
help=
"Query retrieve level. Default: %(default)s. Choices: [%(choices)s]",
default='STUDY',
choices=['PATIENT', 'STUDY', 'SERIES'],
metavar='<level>')
parser.add_argument(
'--loglevel',
help="Loglevel. default:%(default)s. choices:[%(choices)s]",
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default='INFO',
metavar='<level>')
parser.add_argument('--progress',
help="Show progress bar",
action='store_true')
args = parser.parse_args()
logger.setLevel(args.loglevel)
start_date = date_utils.parse_date(args.start)
end_date = date_utils.parse_date(args.end)
if start_date > end_date:
print('Invalid range: start > end')
return 1
output_filename = args.output or '{}-{}{}'.format(args.start, args.end,
args.ext)
logger.debug('Output filename:%s', output_filename)
date_delta = end_date - start_date
logger.info('%s - %s (%s days)', args.start, args.end, date_delta.days + 1)
attributes = [
'PatientID', 'Modality', 'StudyDate', 'StudyDescription',
'AccessionNumber', 'StudyInstanceUID'
]
kvs = []
for keyvalue in args.add:
key, value = keyvalue.split('=')
kvs.append((key, value))
logger.info('Additional attribute %s=%s', key, value)
if key not in attributes:
attributes.append(key)
logger.info('Start querying')
all_result = []
generator = date_utils.split(start_date, end_date, args.step)
if args.progress:
generator = tqdm.tqdm(generator,
total=date_utils.split_size(
start_date, end_date, args.step))
for part_start, part_end in generator:
study_date = '{}-{}'.format(date_utils.date2str(part_start),
date_utils.date2str(part_end))
logger.debug(study_date)
ds = Dataset()
for attr in attributes:
setattr(ds, attr, '')
ds.StudyDate = study_date
ds.QueryRetrieveLevel = args.qrlevel
for key, value in kvs:
setattr(ds, key, value)
query_result = qr.query(ds, logger=logger)
if query_result:
all_result.extend([[getattr(r, attr) for attr in attributes]
for r in query_result])
logger.info('End querying')
logger.info('%d query results', len(all_result))
df = pd.DataFrame(all_result, columns=attributes)
if output_filename == '-':
s = io.StringIO()
getattr(df, EXT_TABLE[args.ext])(s, index=False)
print(s.getvalue())
else:
getattr(df, EXT_TABLE[args.ext])(output_filename, index=False)
return 0
if __name__ == "__main__":
sys.exit(main())