123/1-move.py
2023-08-08 22:04:06 +00:00

224 lines
6.9 KiB
Python
Executable file

#!/usr/bin/env python3
import os
import pprint
import sys
import time
from pydicom.dataset import Dataset
from pynetdicom import AE, evt, StoragePresentationContexts, debug_logger
from pynetdicom.sop_class import (
PatientRootQueryRetrieveInformationModelFind,
PatientRootQueryRetrieveInformationModelMove,
StudyRootQueryRetrieveInformationModelMove,
PatientStudyOnlyQueryRetrieveInformationModelMove,
)
# debug_logger()
Series = {}
dcm_dir = '/nn'
def handle_store(event):
# print(event)
"""Handle a C-STORE request event."""
ds = event.dataset
ds.file_meta = event.file_meta
# print(ds.SeriesInstanceUID)
# print(ds)
if ds.SeriesInstanceUID in Series:
s = Series[ds.SeriesInstanceUID]
else:
number = len(Series)
series_dir = os.path.join(dcm_dir, ds.PatientID, ds.StudyInstanceUID, ds.SeriesInstanceUID, str(number))
series_dir = os.path.join(dcm_dir, ds.PatientID, ds.StudyDate, ds.Modality, str(number))
series_dir = os.path.join(dcm_dir, ds.PatientID, ds.StudyDate, ds.Modality, hex(number)[2:])
s = {
'PatientID': ds.PatientID,
'StudyInstanceUID': ds.StudyInstanceUID,
'SeriesInstanceUID': ds.SeriesInstanceUID,
'Modality': ds.Modality,
'SeriesDescription': ds.SeriesDescription,
'path': series_dir,
'number': number,
}
# print(s)
print(s['path'], s['SeriesDescription'])
Series[ds.SeriesInstanceUID] = s
os.makedirs(s['path'], exist_ok=True)
filename = os.path.join(s['path'], ds.SOPInstanceUID)
# Save the dataset using the SOP Instance UID as the filename
ds.save_as(filename, write_like_original=False)
# Return a 'Success' status
return 0x0000
# Search in nested Python dict
def gen_dict_extract(key, var):
if hasattr(var,'items'):
for k, v in var.items():
if k == key:
yield v
if isinstance(v, dict):
for result in gen_dict_extract(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in gen_dict_extract(key, d):
yield result
def FindElement(identifier, element):
e = None
for v in gen_dict_extract(element, identifier.to_json_dict()):
e = v['Value'][0]
return e
def QueryDCM(PatientID):
handlers = [
(evt.EVT_C_STORE, handle_store),
]
# debug_logger()
StudyInstanceUID_DICT = {}
ae = AE()
ae.add_requested_context(PatientRootQueryRetrieveInformationModelFind)
assoc = ae.associate("192.168.10.56", 104,
ae_title = 'IQWEBX',
)
ds = Dataset()
ds.QueryRetrieveLevel = 'PATIENT'
ds.PatientID = PatientID
responses = assoc.send_c_find(ds, PatientRootQueryRetrieveInformationModelFind)
# print(responses)
for (status, identifier) in responses:
# print(status, identifier)
if status:
print('C-FIND query status: 0x{0:04X}'.format(status.Status))
else:
print('Connection timed out, was aborted or received invalid response')
if identifier:
# d = {}
# d['StudyDate' ] = FindElement(identifier, '00080020')
# d['ModalitiesInStudy'] = FindElement(identifier, '00080061')
# d['StudyInstanceUID' ] = FindElement(identifier, '0020000D')
# print(d)
# if (d['ModalitiesInStudy' ] not in StudyInstanceUID_DICT) or (
# d['StudyDate' ] > StudyInstanceUID_DICT[d['ModalitiesInStudy']]['StudyDate']):
# StudyInstanceUID_DICT[d['ModalitiesInStudy']] = d
# print(dir(identifier))
# print(identifier.keys())
for sq in identifier[(0x3109, 0x1035)]:
# print(sq)
# print(type(sq))
# exit()
d = {}
d['StudyDate' ] = FindElement(sq, '00080020')
d['ModalitiesInStudy'] = FindElement(sq, '00080061')
d['StudyInstanceUID' ] = FindElement(sq, '0020000D')
print(d)
if (d['ModalitiesInStudy' ] not in StudyInstanceUID_DICT) or (
d['StudyDate' ] > StudyInstanceUID_DICT[d['ModalitiesInStudy']]['StudyDate']):
StudyInstanceUID_DICT[d['ModalitiesInStudy']] = d
assoc.release()
pprint.pprint(StudyInstanceUID_DICT)
# exit()
# Initialise the Application Entity
ae = AE()
# Add a requested presentation context
ae.add_requested_context(PatientRootQueryRetrieveInformationModelMove)
# Add the Storage SCP's supported presentation contexts
ae.supported_contexts = StoragePresentationContexts
# Start our Storage SCP in non-blocking mode, listening on port 11120
ae.ae_title = 'OUR_STORE_SCP'
# scp = ae.start_server(("127.0.0.1", 11120), block=False, evt_handlers=handlers)
scp = ae.start_server(("0.0.0.0", 11120), block=False, evt_handlers=handlers)
for ModalitiesInStudy, d in StudyInstanceUID_DICT.items():
StudyInstanceUID = d['StudyInstanceUID']
# Create out identifier (query) dataset
ds = Dataset()
# ds.QueryRetrieveLevel = 'PATIENT'
# ds.PatientID = PatientID
ds.QueryRetrieveLevel = 'STUDY'
ds.StudyInstanceUID = StudyInstanceUID
# Associate with peer AE at IP 127.0.0.1 and port 11112
# assoc = ae.associate("127.0.0.1", 11112)
assoc = ae.associate("192.168.10.56", 104,
ae_title = 'IQWEBX',
)
if assoc.is_established:
# Use the C-MOVE service to send the identifier
responses = assoc.send_c_move(ds, 'OUR_STORE_SCP', PatientRootQueryRetrieveInformationModelMove)
# print(responses)
for (status, identifier) in responses:
# print(status, identifier)
if status:
print('C-MOVE query status: 0x{0:04x}'.format(status.Status))
else:
print('Connection timed out, was aborted or received invalid response')
# Release the association
assoc.release()
else:
print('Association rejected, aborted or never connected')
# Stop our Storage SCP
scp.shutdown()
def main():
if len(sys.argv) < 2:
print('Usage:', sys.argv[0], 'PatientID')
sys.exit()
print('hello')
print(sys.argv[0])
print(sys.argv[1])
start = time.time()
QueryDCM(sys.argv[1])
end = time.time()
print(end - start, 'seconds')
# for k, v in Series.items():
# print(v['number'], v['Modality'], v['SeriesDescription'], v['path'])
# print(v['path'], v['SeriesDescription'])
if __name__ == '__main__':
main()