def run_server(self, use_abort): called = [False] def store_callback(message): called[0] = True return 0 association = odil.Association() association.set_tcp_timeout(1) association.receive_association("v4", 11113) store_scp = odil.StoreSCP(association) store_scp.set_callback(store_callback) message = association.receive_message() store_scp(message) termination_ok = False try: association.receive_message() except odil.AssociationReleased: termination_ok = True if called[0] and termination_ok: sys.exit(0) else: sys.exit(1)
def run_server(self): called = False association = odil.Association() association.set_tcp_timeout(1) association.receive_association("v4", 11113) get_scp = odil.GetSCP(association) generator = Generator() get_scp.set_generator(generator) message = association.receive_message() get_scp(message) termination_ok = False try: association.receive_message() except odil.AssociationReleased: termination_ok = True except odil.AssociationAborted: pass if called and termination_ok: return 0 else: return 1
def run_server(self, use_abort): called = [False] def echo_callback(message): called[0] = True return 0 association = odil.Association() association.set_tcp_timeout(1) association.receive_association("v4", 11113) echo_scp = odil.EchoSCP(association) echo_scp.set_callback(echo_callback) dispatcher = odil.SCPDispatcher(association) dispatcher.set_echo_scp(echo_scp) dispatcher.dispatch() termination_ok = False try: association.receive_message() except odil.AssociationReleased: termination_ok = True if called[0] and termination_ok: sys.exit(0) else: sys.exit(1)
def run_server(self): association = odil.Association() association.set_tcp_timeout(1) association.receive_association("v4", 11113) find_scp = odil.FindSCP(association) generator = Generator() find_scp.set_generator(generator) message = association.receive_message() find_scp(message) termination_ok = False try: association.receive_message() except odil.AssociationReleased: termination_ok = True except odil.AssociationAborted: pass if termination_ok: sys.exit(0) else: sys.exit(1)
def find(host, port, calling_ae_title, called_ae_title, level, keys, decode_uids): query = odil.DataSet() for key in keys: if "=" in key: key, value = key.split("=", 1) value = value.split("\\") else: value = None tag = getattr(odil.registry, key) if value is not None: vr = odil.registry.public_dictionary[tag].vr if vr in ["DS", "FL", "FD"]: value = [float(x) for x in value] elif vr in ["IS", "SL", "SS", "UL", "US"]: value = [int(x) for x in value] query.add(tag, value) else: query.add(tag) sop_class = getattr( odil.registry, "{}RootQueryRetrieveInformationModelFind".format(level.capitalize())) find_pc = odil.AssociationParameters.PresentationContext( 1, sop_class, [ odil.registry.ImplicitVRLittleEndian, odil.registry.ExplicitVRLittleEndian ], odil.AssociationParameters.PresentationContext.Role.SCU) association = odil.Association() association.set_peer_host(host) association.set_peer_port(port) association.update_parameters()\ .set_calling_ae_title(calling_ae_title)\ .set_called_ae_title(called_ae_title) \ .set_presentation_contexts([find_pc]) association.associate() logging.info("Association established") find = odil.FindSCU(association) find.set_affected_sop_class(sop_class) data_sets = find.find(query) print("{} answer{}".format(len(data_sets), "s" if len(data_sets) > 1 else "")) max_length = 0 for data_set in data_sets: max_length = max(max_length, find_max_name_length(data_set)) for data_set in data_sets: print_data_set(data_set, decode_uids, "", max_length, odil.Value.Strings()) print() association.release() logging.info("Association released")
def run_server(self, use_abort): called = False def echo_callback(message): called = True return 0 association = odil.Association() association.set_tcp_timeout(1) association.receive_association("v4", 11113) echo_scp = odil.EchoSCP(association) echo_scp.set_callback(echo_callback) message = association.receive_message() echo_scp(message) termination_ok = False try: association.receive_message() except odil.AssociationReleased: if not use_abort: termination_ok = True except odil.AssociationAborted: if use_abort: termination_ok = True if called and termination_ok: return 0 else: return 1
def test_parameters(self): parameters = odil.AssociationParameters() parameters.set_called_ae_title("foo") association = odil.Association() association.set_parameters(parameters) self.assertEqual(association.get_parameters().get_called_ae_title(), "foo")
def find_abstract_syntaxes(host, port, calling_ae_title, called_ae_title, level, keys): """ Return the abstract syntaxes corresponding to the query, based on SOP Classes in Study. """ query = odil.DataSet() for key in keys: key, value = key.split("=", 1) value = value.split("\\") if key in ["QueryRetrieveLevel", "SOPClassesInStudy"]: continue tag = getattr(odil.registry, key) vr = odil.registry.public_dictionary[tag].vr if vr in ["DS", "FL", "FD"]: value = [float(x) for x in value] elif vr in ["IS", "SL", "SS", "UL", "US"]: value = [int(x) for x in value] query.add(tag, value) query.add("QueryRetrieveLevel", ["STUDY"]) query.add("SOPClassesInStudy") find_syntax = getattr( odil.registry, "{}RootQueryRetrieveInformationModelFind".format(level.capitalize())) transfer_syntaxes = [ odil.registry.ImplicitVRLittleEndian, odil.registry.ExplicitVRLittleEndian ] find_pc = odil.AssociationParameters.PresentationContext( 1, find_syntax, transfer_syntaxes, odil.AssociationParameters.PresentationContext.Role.SCU) association = odil.Association() association.set_peer_host(host) association.set_peer_port(port) association.update_parameters()\ .set_calling_ae_title(calling_ae_title)\ .set_called_ae_title(called_ae_title) \ .set_presentation_contexts([find_pc]) association.associate() logging.info("Association established") find = odil.FindSCU(association) find.set_affected_sop_class(find_syntax) data_sets = find.find(query) sop_classes = set() for data_set in data_sets: if "SOPClassesInStudy" in data_set: sop_classes.update(data_set.as_string("SOPClassesInStudy")) return sop_classes
def setUp(self, contexts): self.association = odil.Association() self.association.set_peer_host(os.environ["ODIL_PEER_HOST_NAME"]) self.association.set_peer_port(int(os.environ["ODIL_PEER_PORT"])) self.association.update_parameters()\ .set_calling_ae_title(os.environ["ODIL_OWN_AET"])\ .set_called_ae_title(os.environ["ODIL_PEER_AET"]) \ .set_presentation_contexts(contexts) self.association.associate()
def store(host, port, calling_ae_title, called_ae_title, filenames): transfer_syntaxes = [ odil.registry.ExplicitVRLittleEndian, odil.registry.ImplicitVRLittleEndian, ] # Find all SOP classes to negotiate at association time. We don't need to # read the whole data set for this sop_classes = set() for filename in filenames: with odil.open(filename) as stream: _, data_set = odil.Reader.read_file( stream, halt_condition=lambda tag: tag > odil.registry.SOPClassUID) sop_classes.update(data_set.as_string("SOPClassUID")) presentation_contexts = [ odil.AssociationParameters.PresentationContext( 2 * i + 1, sop_class, transfer_syntaxes, odil.AssociationParameters.PresentationContext.Role.SCU) for i, sop_class in enumerate(sop_classes) ] # Create the association and the Store SCU association = odil.Association() association.set_peer_host(host) association.set_peer_port(port) association.update_parameters()\ .set_calling_ae_title(calling_ae_title)\ .set_called_ae_title(called_ae_title)\ .set_presentation_contexts(presentation_contexts) association.associate() negotiated_parameters = association.get_negotiated_parameters() negotiated_pc = negotiated_parameters.get_presentation_contexts() store = odil.StoreSCU(association) for filename in filenames: with odil.open(filename) as stream: _, data_set = odil.Reader.read_file(stream) try: store.set_affected_sop_class(data_set) store.store(data_set) except Exception as e: print("Could not store {}: {}".format(filename, e)) association.release()
def get_association(self, request): move_association = odil.Association() move_association.set_peer_host(self._association.get_peer_host()) move_association.set_peer_port(11114) presentation_contexts = [ odil.AssociationParameters.PresentationContext( 1, odil.registry.RawDataStorage, [odil.registry.ImplicitVRLittleEndian], odil.AssociationParameters.PresentationContext.Role.SCU)] move_association.update_parameters()\ .set_calling_ae_title( self._association.get_negotiated_parameters().get_called_ae_title())\ .set_called_ae_title(request.get_move_destination())\ .set_presentation_contexts(presentation_contexts) return move_association
def get_association(self, request): move_association = odil.Association() move_association.set_peer_host(self._association.get_peer_host()) move_association.set_peer_port(11114) presentation_contexts = [] for entry in odil.registry.uids_dictionary: if entry.data().name[-7:] == "Storage": presentation_context = odil.AssociationParameters.PresentationContext( 1 + 2 * len(presentation_contexts), entry.key(), [odil.registry.ImplicitVRLittleEndian], True, False) presentation_contexts.append(presentation_context) move_association.update_parameters()\ .set_calling_ae_title( self._association.get_negotiated_parameters().get_called_ae_title())\ .set_called_ae_title(request.get_move_destination())\ .set_presentation_contexts(presentation_contexts) return move_association
def echo(host, port, calling_ae_title, called_ae_title): association = odil.Association() association.set_peer_host(host) association.set_peer_port(port) association.update_parameters()\ .set_calling_ae_title(calling_ae_title)\ .set_called_ae_title(called_ae_title) \ .set_presentation_contexts([ odil.AssociationParameters.PresentationContext( 3, odil.registry.VerificationSOPClass, [ odil.registry.ImplicitVRLittleEndian ], True, False ) ]) association.associate() logging.info("Association established") echo = odil.EchoSCU(association) echo.echo() logging.info("C-ECHO successful") association.release() logging.info("Association released")
def test_peer_port(self): association = odil.Association() association.set_peer_port(1234) self.assertEqual(association.get_peer_port(), 1234)
import odil association = odil.Association() association.set_peer_host("184.73.255.26") association.set_peer_port(11112) presentation_contexts = [ odil.AssociationParameters.PresentationContext( 1, odil.registry.StudyRootQueryRetrieveInformationModelFIND, [odil.registry.ExplicitVRLittleEndian], True, False), odil.AssociationParameters.PresentationContext( 3, odil.registry.VerificationSOPClass, [odil.registry.ExplicitVRLittleEndian], True, False) ] association.update_parameters()\ .set_calling_ae_title("myself")\ .set_called_ae_title("AWSPIXELMEDPUB") \ .set_presentation_contexts(presentation_contexts) association.associate() query = odil.DataSet() query.add(odil.registry.PatientName, odil.Value.Strings(["*"])) query.add(odil.registry.QueryRetrieveLevel, odil.Value.Strings(["STUDY"])) query.add(odil.registry.StudyDescription) query.add(odil.registry.StudyDate) find = odil.FindSCU(association) find.set_affected_sop_class( odil.registry.StudyRootQueryRetrieveInformationModelFIND)
def get(host, port, calling_ae_title, called_ae_title, level, keys, directory, iso_9660, layout, dicomdir, patient_key, study_key, series_key, image_key): if dicomdir and not iso_9660: raise Exception("Cannot create a DICOMDIR without ISO-9660 filenames") query = odil.DataSet() for key in keys: key, value = key.split("=", 1) value = value.split("\\") tag = getattr(odil.registry, key) vr = odil.registry.public_dictionary[tag].vr if vr in ["DS", "FL", "FD"]: value = [float(x) for x in value] elif vr in ["IS", "SL", "SS", "UL", "US"]: value = [int(x) for x in value] query.add(tag, value) get_syntax = getattr( odil.registry, "{}RootQueryRetrieveInformationModelGet".format(level.capitalize())) transfer_syntaxes = [ odil.registry.ImplicitVRLittleEndian, odil.registry.ExplicitVRLittleEndian ] get_pc = odil.AssociationParameters.PresentationContext( 1, get_syntax, transfer_syntaxes, odil.AssociationParameters.PresentationContext.Role.SCU) abstract_syntaxes = find_abstract_syntaxes(host, port, calling_ae_title, called_ae_title, level, keys) if not abstract_syntaxes: # Negotiate ALL storage syntaxes. Is there a better way to do this? abstract_syntaxes = [ entry.key() for entry in odil.registry.uids_dictionary if entry.data().name.endswith("Storage") ] if len(abstract_syntaxes) > 126: raise Exception("Too many storage syntaxes") storage_pcs = [ odil.AssociationParameters.PresentationContext( 2 * (i + 1) + 1, uid, transfer_syntaxes, odil.AssociationParameters.PresentationContext.Role.SCP) for i, uid in enumerate(abstract_syntaxes) ] association = odil.Association() association.set_peer_host(host) association.set_peer_port(port) association.update_parameters()\ .set_calling_ae_title(calling_ae_title)\ .set_called_ae_title(called_ae_title) \ .set_presentation_contexts([get_pc]+storage_pcs) association.associate() logging.info("Association established") get = odil.GetSCU(association) get.set_affected_sop_class(get_syntax) class Callback(object): def __init__(self, directory): self.directory = directory self.completed = 0 self.remaining = 0 self.failed = 0 self.warning = 0 self.stored = {} self.files = [] self._study_ids = {} self._series_ids = {} def store(self, data_set): specific_character_set = odil.Value.Strings() if "SpecificCharacterSet" in data_set: specific_character_set = data_set.as_string( "SpecificCharacterSet") as_unicode = lambda x: odil.as_unicode(x, specific_character_set) if layout == "flat": directory = "" elif layout == "tree": # Patient directory: <PatientName> or <PatientID>. patient_directory = None if "PatientName" in data_set and data_set.as_string( "PatientName"): patient_directory = data_set.as_string("PatientName")[0] else: patient_directory = data_set.as_string("PatientID")[0] patient_directory = as_unicode(patient_directory) # Study directory: <StudyID>_<StudyDescription>, both parts are # optional. If both tags are missing or empty, default to a # numeric index based on StudyInstanceUID. study_directory = [] if "StudyID" in data_set and data_set.as_string("StudyID"): study_directory.append(data_set.as_string("StudyID")[0]) if ("StudyDescription" in data_set and data_set.as_string("StudyDescription")): study_directory.append( data_set.as_string("StudyDescription")[0]) if not study_directory: study_instance_uid = data_set.as_string( "StudyInstanceUID")[0] study_directory.append( self._study_ids.setdefault(study_instance_uid, 1 + len(self._study_ids))) study_directory = "_".join( as_unicode(x) for x in study_directory) # Study directory: <SeriesNumber>_<SeriesDescription>, both # parts are optional. If both tags are missing or empty, default # to a numeric index based on SeriesInstanceUID. series_directory = [] if "SeriesNumber" in data_set and data_set.as_int( "SeriesNumber"): series_directory.append( str(data_set.as_int("SeriesNumber")[0])) if ("SeriesDescription" in data_set and data_set.as_string("SeriesDescription")): series_directory.append( data_set.as_string("SeriesDescription")[0]) if not series_directory: series_instance_uid = data_set.as_string( "series_instance_uid")[0] series_directory.append( self._series_ids.setdefault(series_instance_uid, 1 + len(self._series_ids))) series_directory = "_".join( as_unicode(x) for x in series_directory) if iso_9660: patient_directory = to_iso_9660(patient_directory) study_directory = to_iso_9660(study_directory) series_directory = to_iso_9660(series_directory) directory = os.path.join(patient_directory, study_directory, series_directory) if not os.path.isdir(os.path.join(self.directory, directory)): os.makedirs(os.path.join(self.directory, directory)) else: raise NotImplementedError() self.stored.setdefault(directory, 0) if iso_9660: filename = "IM{:06d}".format(1 + self.stored[directory]) else: filename = as_unicode(data_set.as_string("SOPInstanceUID")[0]) with odil.open(os.path.join(self.directory, directory, filename), "wb") as fd: odil.Writer.write_file(data_set, fd) self.stored[directory] += 1 self.files.append(os.path.join(directory, filename)) def get(self, message): for type_ in ["completed", "remaining", "failed", "warning"]: base = "number_of_{}_sub_operations".format(type_) if getattr(message, "has_{}".format(base))(): setattr(self, type_, getattr(message, "get_{}".format(base))()) logging.info( "Remaining: {}, completed: {}, failed: {}, warning: {}".format( self.remaining, self.completed, self.failed, self.warning)) if not os.path.isdir(directory): os.makedirs(directory) if len(os.listdir(directory)): logging.warning("{} is not empty".format(directory)) callback = Callback(directory) get.get(query, callback.store, callback.get) print("Completed: {}, remaining: {}, failed: {}, warning: {}".format( callback.completed, callback.remaining, callback.failed, callback.warning)) association.release() logging.info("Association released") if dicomdir: logging.info("Creating DICOMDIR") create_dicomdir([os.path.join(directory, x) for x in callback.files], directory, patient_key, study_key, series_key, image_key)
def test_update_parameters(self): association = odil.Association() association.update_parameters().set_called_ae_title("foo") self.assertEqual(association.get_parameters().get_called_ae_title(), "foo")
def test_next_message_id(self): association = odil.Association() id1 = association.next_message_id() id2 = association.next_message_id() self.assertNotEqual(id1, id2)
def test_default_constructor(self): association = odil.Association() self.assertFalse(association.is_associated())
def test_peer_host(self): association = odil.Association() association.set_peer_host("pacs.example.com") self.assertEqual(association.get_peer_host(), "pacs.example.com")