def test_send_assoc_ac_role(self, caplog): """Test ACSE.debug_send_associate_ac with role selection.""" with caplog.at_level(logging.DEBUG, logger='pynetdicom'): self.ae = ae = AE() ae.add_supported_context('1.2.840.10008.1.2', scu_role=True, scp_role=True) ae.add_supported_context('1.2.840.10008.1.3', scu_role=True, scp_role=True) ae.add_supported_context('1.2.840.10008.1.4', scu_role=True, scp_role=True) ae.add_requested_context('1.2.840.10008.1.2') ae.add_requested_context('1.2.840.10008.1.3') ae.add_requested_context('1.2.840.10008.1.4') ae.add_requested_context(VerificationSOPClass) ae.add_requested_context(VerificationSOPClass) scp = ae.start_server(('', 11112), block=False) ext_neg = [] ext_neg.append(build_role('1.2.840.10008.1.2', scu_role=True)) ext_neg.append(build_role('1.2.840.10008.1.3', scp_role=True)) ext_neg.append( build_role('1.2.840.10008.1.4', scu_role=True, scp_role=True)) assoc = ae.associate('localhost', 11112, ext_neg=ext_neg) self.add_scp_scu_role(self.associate_ac) contexts = self.associate_ac.presentation_context_definition_results_list for ii, cx in enumerate(contexts): cx.context_id = ii * 2 + 1 cx.result = 0 pdu = A_ASSOCIATE_AC() pdu.from_primitive(self.associate_ac) evt.trigger(assoc, evt.EVT_PDU_SENT, {'pdu': pdu}) messages = [ "Abstract Syntax: =Implicit VR Little Endian", "SCP/SCU Role: SCU", "Abstract Syntax: =1.2.840.10008.1.3", "SCP/SCU Role: SCP", "Abstract Syntax: =1.2.840.10008.1.4", "SCP/SCU Role: SCP/SCU", "Accepted Extended Negotiation: None", "Accepted Asynchronous Operations Window Negotiation: None", "User Identity Negotiation Response: None", ] for msg in messages: assert msg in caplog.text assoc.release() scp.shutdown()
def c_get_Option(): print('Executing the C_GET approach i.e. SCU c_get') handlers = [(evt.EVT_C_STORE, handle_store)] CompositeInstanceRetrieveWithoutBulkDataGet = '1.2.840.10008.5.1.4.1.2.5.3' SecondaryCaptureImageStorage = '1.2.840.10008.5.1.4.1.1.7' ae = AE(ae_title=AE_TITLE) ae.add_requested_context(CompositeInstanceRetrieveWithoutBulkDataGet) ae.add_requested_context(SecondaryCaptureImageStorage) role = build_role(SecondaryCaptureImageStorage, scp_role=True) assoc = ae.associate(SERVER_ADDRESS, PORT, ext_neg=[role], evt_handlers=handlers) if assoc.is_established: responses = assoc.send_c_get( create_queryDS('IMAGE'), CompositeInstanceRetrieveWithoutBulkDataGet) for (status, identifier) in responses: if status: print('C-GET query status: 0x{0:04x}'.format(status.Status)) else: print( 'Connection timed out, was aborted or received invalid response' ) assoc.release() else: print('Association rejected, aborted or never connected')
def test_basic(self): """Test basic operation of the QR get service.""" self.p = p = self.func([ "--database-location", self.db_location, "--instance-location", self.instance_location.name, "-d", ]) time.sleep(1) _send_datasets() time.sleep(1) query = Dataset() query.QueryRetrieveLevel = "PATIENT" query.PatientID = "1CT1" datasets = [] def handle_store(event): datasets.append(event.dataset) return 0x0000 self.ae = ae = AE() ae.acse_timeout = 5 ae.dimse_timeout = 5 ae.network_timeout = 5 model = PatientRootQueryRetrieveInformationModelGet ae.add_requested_context(model) ae.add_requested_context(CTImageStorage) role = build_role(CTImageStorage, scp_role=True) assoc = ae.associate( "localhost", 11112, ext_neg=[role], evt_handlers=[(evt.EVT_C_STORE, handle_store)], ) assert assoc.is_established responses = assoc.send_c_get(query, model) status, ds = next(responses) assert status.Status == 0xFF00 assert ds is None status, ds = next(responses) assert status.Status == 0x0000 assert ds is None pytest.raises(StopIteration, next, responses) assoc.release() p.terminate() p.wait() assert 1 == len(datasets) assert "CompressedSamples^CT1" == datasets[0].PatientName
def _cget_series(self, destdir, study_instance_uid, series_instance_UID): handlers = [(pynetdicom.evt.EVT_C_STORE, self._handle_store)] # # Initialise the Application Entity ae = pynetdicom.AE(ae_title=self.__local_aet) ae.add_requested_context( pynetdicom.sop_class.StudyRootQueryRetrieveInformationModelGet) # Add the requested presentation contexts (Storage SCP) roles = [] for storage_class in presentation_contexts: # Add the requested presentation contexts (QR SCU) ae.add_requested_context(storage_class) # Create an SCP/SCU Role Selection Negotiation item for CT Image Storage roles.append(pynetdicom.build_role(storage_class, scp_role=True)) # Create our Identifier (query) dataset # We need to supply a Unique Key Attribute for each level above the # Query/Retrieve level ds = pydicom.dataset.Dataset() ds.QueryRetrieveLevel = 'SERIES' # Unique key for SERIES level ds.SeriesInstanceUID = series_instance_UID # Associate with peer AE at IP 127.0.0.1 and port 11112 assoc = ae.associate(self.__host, self.__port, ae_title=self.__aet, ext_neg=roles, evt_handlers=handlers) if assoc.is_established: # Use the C-GET service to send the identifier responses = assoc.send_c_get( ds, pynetdicom.sop_class.StudyRootQueryRetrieveInformationModelGet) for (status, identifier) in responses: if status: pass else: raise ConnectionError( 'Connection timed out, was aborted or received invalid response' ) # Release the association assoc.release() else: raise ConnectionError( 'Association rejected, aborted or never connected')
def download_CT(ds, ID): """ Setup the connection """ PatientID = ID.split('_')[0] StudyDate = ID.split('_')[1] # Target directory save_to_dir = Path(f'retrieved_data/{name}{ID}/CT') for int_suffix in range(20): if save_to_dir.exists(): save_to_dir = Path(f'retrieved_data/{name}{ID}/CT_{int_suffix}') else: pass save_to_dir.mkdir(parents=True) #todir = f'retrieved_data/{PatientID}_{StudyDate}/CT' handlers = [(evt.EVT_C_STORE, lambda x: handle_store(event=x, todir=save_to_dir))] """ Setup type of data to download: PositronEmissionTomographyImageStorage for PET CTImageStorage for CT? """ #aeFIND.add_requested_context(CTImageStorage) role = build_role(CTImageStorage, scp_role=True) assoc = aeFIND.associate(addr='dali', port=11112, ext_neg=[role], ae_title="DALI", evt_handlers=handlers) if assoc.is_established: # Use the C-GET service to send the identifier responses = assoc.send_c_get( ds, PatientRootQueryRetrieveInformationModelGet) for (status, identifier) in responses: if status: print('C-GET 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')
def FnGetScu(UID,nombre): q='t' # Implement the handler for evt.EVT_C_STORE def handle_store(event): """Handle a C-STORE request event.""" ds = event.dataset ds.file_meta = event.file_meta # Save the dataset using the SOP Instance UID as the filename ds.save_as(ds.SOPInstanceUID, write_like_original=False) # Return a 'Success' status return 0x0000 handlers = [(evt.EVT_C_STORE, handle_store)] # Initialise the Application Entity ae = AE() # Add the requested presentation contexts (QR SCU) ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet) # Add the requested presentation context (Storage SCP) ae.add_requested_context('1.2.840.10008.5.1.4.1.1.2', transfer_syntax='1.2.840.10008.1.2.4.91') ae.add_supported_context('1.2.840.10008.5.1.4.1.1.2', transfer_syntax='1.2.840.10008.1.2') ae.add_requested_context('1.2.840.10008.5.1.4.1.1.2', transfer_syntax='1.2.840.10008.1.2') #print(ae) # Create an SCP/SCU Role Selection Negotiation item for CT Image Storage role = build_role(CTImageStorage, scp_role=True) # Create our Identifier (query) dataset # We need to supply a Unique Key Attribute for each level above the # Query/Retrieve level ds = Dataset() ds.QueryRetrieveLevel = 'STUDY' ds.StudyInstanceUID = UID ds.PatientID = '0' ds.Modality = 'CT' #ds.StudyInstanceUID ='1.2.826.0.1.3680043.8.1055.1.20111102150758591.92402465.76095170' ds.PatientName = nombre # Associate with peer AE at IP 127.0.0.1 and port 11112 assoc = ae.associate('127.0.0.1', 11120, ext_neg=[role], evt_handlers=handlers) if assoc.is_established: # Use the C-GET service to send the identifier responses = assoc.send_c_get(ds, PatientRootQueryRetrieveInformationModelGet) for (status, identifier) in responses: if status: print('C-GET query status: 0x{0:04x}'.format(status.Status)) #print(status) q= status.NumberOfCompletedSuboperations q=str(q) #print('id:',identifier) else: print('Connection timed out, was aborted or received invalid response') # Release the association #q.append(status.NumberOfCompletedSuboperations) assoc.release() else: print('Association rejected, aborted or never connected') return(q)
def initAE( self ): """Application Entity bereitstellen Status Codes: Non-service specific - 0xC000 to 0xC0FF Verwendete evt_handlers:: * EVT_ESTABLISHED * EVT_REJECTED * EVT_RELEASED Returns ------- status : hex - 0x0000 - alles OK - 0xC0FF -Verbindung fehlgeschlagen """ # sicherheitshalber bestehende schließen self.closeAE() # Initialise the Application Entity assoc = None try: # Initialise the Application Entity aet = self.config.dicom[self.server]["aet"] self.ae = AE( ae_title=aet ) # Patient Suche verwenden self.ae.requested_contexts = QueryRetrievePresentationContexts # patient level self.ae.add_requested_context( PatientRootQueryRetrieveInformationModelFind ) self.ae.add_requested_context( PatientRootQueryRetrieveInformationModelMove ) self.ae.add_requested_context( PatientRootQueryRetrieveInformationModelGet ) # Study level self.ae.add_requested_context( StudyRootQueryRetrieveInformationModelFind ) self.ae.add_requested_context( StudyRootQueryRetrieveInformationModelMove ) self.ae.add_requested_context( StudyRootQueryRetrieveInformationModelGet ) # patientStudyOnly self.ae.add_requested_context( PatientStudyOnlyQueryRetrieveInformationModelFind ) self.ae.add_requested_context( PatientStudyOnlyQueryRetrieveInformationModelMove ) self.ae.add_requested_context( PatientStudyOnlyQueryRetrieveInformationModelGet ) # Add the requested presentation context (Storage SCP) self.ae.add_requested_context( CTImageStorage ) self.ae.add_requested_context( XRayRadiationDoseSRStorage ) # use all Storages and Transfers storage_sop_classes = [ cx.abstract_syntax for cx in AllStoragePresentationContexts ] for uid in storage_sop_classes: self.ae.add_supported_context(uid, ALL_TRANSFER_SYNTAXES) # bei den handlern wird nicht auf EVT_REJECTED geprüft, da offline ja möglich ist handlers=[ ( evt.EVT_ESTABLISHED , self.handle_EVENT), #( evt.EVT_REJECTED , self.handle_event), ( evt.EVT_RELEASED, self.handle_EVENT), # für send_c_get ( evt.EVT_C_STORE, self.handle_STORE), ] # requestmode für den server festlegen: c_move oder c_get self.request_mode = self.config.get( ["dicom", self.server, "request_mode"], "c_move" ) # request_query_model für den server festlegen: P-patient S-series O-PS only self.request_query_model = self.config.get( ["dicom", self.server, "request_query_model"], "S" ) # Create an SCP/SCU Role Selection Negotiation item for CT Image Storage roles = [] roles.append( build_role(CTImageStorage, scp_role=True, scu_role=True ) ) roles.append( build_role(XRayRadiationDoseSRStorage, scp_role=True, scu_role=True) ) # Associate with peer AE assoc = self.ae.associate( self.config.dicom[self.server]['server_ip'], self.config.dicom[self.server]['server_port'], ae_title=self.config.dicom[self.server]['aec'], evt_handlers=handlers, ext_neg=roles ) except: # pragma: no cover pass self.assoc = None status = 0xC0FF if assoc and assoc.is_established: self.assoc = assoc status = 0x0000 logger.debug('dicomClass.initAE: Verbindung hergestellt') else: # pragma: no cover logger.warning('dicomClass.initAE: Association rejected, aborted or never connected') return status
# Return a 'Success' status return 0x0000 handlers = [(evt.EVT_C_STORE, handle_store)] # Initialise the Application Entity ae = AE() # Add the requested presentation contexts (QR SCU) ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet) # Add the requested presentation contexts (Storage SCP) ae.add_requested_context(CTImageStorage) # Create an SCP/SCU Role Selection Negotiation item for CT Image Storage role = build_role(CTImageStorage, scp_role=True) # Create our Identifier (query) dataset # We need to supply a Unique Key Attribute for each level above the # Query/Retrieve level ds = Dataset() ds.QueryRetrieveLevel = 'SERIES' # Unique key for PATIENT level ds.PatientID = '1234567' ds.StudyInstanceUID = '1.2.3' # Unique key for SERIES level ds.SeriesInstanceUID = '1.2.3.4' # Associate with peer AE at IP 127.0.0.1 and port 11112 assoc = ae.associate('127.0.0.1', 11112, ext_neg=[role], evt_handlers=handlers)
APP_LOGGER.debug('') # Create application entity # Binding to port 0 lets the OS pick an available port ae = AE(ae_title=args.calling_aet) for context in QueryRetrievePresentationContexts: ae.add_requested_context(context.abstract_syntax) for context in StoragePresentationContexts[:115]: ae.add_requested_context(context.abstract_syntax) # Add SCP/SCU Role Selection Negotiation to the extended negotiation # We want to act as a Storage SCP ext_neg = [] for context in StoragePresentationContexts: ext_neg.append(build_role(context.abstract_syntax, scp_role=True)) # Create query dataset d = Dataset() d.PatientName = '*' d.QueryRetrieveLevel = "PATIENT" if args.worklist: query_model = 'W' elif args.patient: query_model = 'P' elif args.study: query_model = 'S' elif args.psonly: query_model = 'O' else:
def main(args=None): """Run the application.""" if args is not None: sys.argv = args args = _setup_argparser() if args.version: print(f"getscu.py v{__version__}") sys.exit() APP_LOGGER = setup_logging(args, "getscu") APP_LOGGER.debug(f"getscu.py v{__version__}") APP_LOGGER.debug("") # Create query (identifier) dataset try: # If you're looking at this to see how QR Get works then `identifer` # is a pydicom Dataset instance with your query keys, e.g.: # identifier = Dataset() # identifier.QueryRetrieveLevel = 'PATIENT' # identifier.PatientName = '*' identifier = create_dataset(args, APP_LOGGER) except Exception as exc: APP_LOGGER.exception(exc) sys.exit(1) # Exclude these SOP Classes _exclusion = [ EncapsulatedSTLStorage, EncapsulatedOBJStorage, EncapsulatedMTLStorage, ] store_contexts = [ cx for cx in StoragePresentationContexts if cx.abstract_syntax not in _exclusion ] # Create application entity # Binding to port 0 lets the OS pick an available port ae = AE(ae_title=args.calling_aet) ae.acse_timeout = args.acse_timeout ae.dimse_timeout = args.dimse_timeout ae.network_timeout = args.network_timeout # Extended Negotiation - SCP/SCU Role Selection ext_neg = [] ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet) ae.add_requested_context(StudyRootQueryRetrieveInformationModelGet) ae.add_requested_context(PatientStudyOnlyQueryRetrieveInformationModelGet) for cx in store_contexts: ae.add_requested_context(cx.abstract_syntax) # Add SCP/SCU Role Selection Negotiation to the extended negotiation # We want to act as a Storage SCP ext_neg.append(build_role(cx.abstract_syntax, scp_role=True)) if args.study: query_model = StudyRootQueryRetrieveInformationModelGet elif args.psonly: query_model = PatientStudyOnlyQueryRetrieveInformationModelGet else: query_model = PatientRootQueryRetrieveInformationModelGet # Extended Negotiation - SOP Class Extended ext_opts = [args.relational_retrieval, args.enhanced_conversion] if any(ext_opts): app_info = b"" for option in ext_opts: app_info += b"\x01" if option else b"\x00" item = SOPClassExtendedNegotiation() item.sop_class_uid = query_model item.service_class_application_information = app_info ext_neg.append(item) # Request association with remote assoc = ae.associate( args.addr, args.port, ae_title=args.called_aet, ext_neg=ext_neg, evt_handlers=[(evt.EVT_C_STORE, handle_store, [args, APP_LOGGER])], max_pdu=args.max_pdu, ) if assoc.is_established: # Send query responses = assoc.send_c_get(identifier, query_model) for (status, rsp_identifier) in responses: # If `status.Status` is one of the 'Pending' statuses then # `rsp_identifier` is the C-GET response's Identifier dataset if status and status.Status in [0xFF00, 0xFF01]: # `rsp_identifier` is a pydicom Dataset containing a query # response. You may want to do something interesting here... pass assoc.release() else: sys.exit(1)
def get_dicom(key, dest, server="127.0.0.1", port=11112, title="ANY", retrieveLevel='SERIES', silent=False): #info_logger() handlers = [(evt.EVT_C_STORE, handle_store)] global storage_dest storage_dest = dest # Initialise the Application Entity ae = AE() _exclusion = [ PlannedImagingAgentAdministrationSRStorage, PerformedImagingAgestAdministrationSRStorage, EncapsulatedSTLStorage, ] store_contexts = [ cx for cx in StoragePresentationContexts if cx.abstract_syntax not in _exclusion ] # Extended Negotiation - SCP/SCU Role Selection ext_neg = [] ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet) ae.add_requested_context(StudyRootQueryRetrieveInformationModelGet) ae.add_requested_context(PatientStudyOnlyQueryRetrieveInformationModelGet) for cx in store_contexts: ae.add_requested_context(cx.abstract_syntax) # Add SCP/SCU Role Selection Negotiation to the extended negotiation # We want to act as a Storage SCP ext_neg.append(build_role(cx.abstract_syntax, scp_role=True)) # Create our Identifier (query) dataset # We need to supply a Unique Key Attribute for each level above the # Query/Retrieve level ds = Dataset() ds.QueryRetrieveLevel = retrieveLevel if retrieveLevel == "SERIES": ds.SeriesInstanceUID = key elif retrieveLevel == "PATIENT": ds.PatientID = key elif retrieveLevel == "STUDY": ds.StudyInstanceUID = key else: raise ValueError( "Retrieve level must be one of 'SERIES', 'PATIENT', 'STUDY' but {retrieveLevel} was passed" ) # Associate with peer AE at IP 127.0.0.1 and port 11112 assoc = ae.associate(server, port, ae_title=title, ext_neg=ext_neg, evt_handlers=handlers) if assoc.is_established: # Use the C-GET service to send the identifier responses = assoc.send_c_get( ds, PatientRootQueryRetrieveInformationModelGet) for (status, identifier) in responses: if status: #import pdb; pdb.set_trace() if status.NumberOfCompletedSuboperations >= 1: if not silent: print( f"{key} downloaded {status.NumberOfCompletedSuboperations} successfully" ) elif status.NumberOfCompletedSuboperations == 0: print(f"id {key} not found") else: print('C-GET 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')
from pynetdicom import (AE, StoragePresentationContexts, QueryRetrievePresentationContexts, build_role) from pynetdicom.pdu_primitives import UserIdentityNegotiation ae = AE() # Contexts proposed as a QR SCU ae.requested_contexts = QueryRetrievePresentationContexts # Contexts supported as a Storage SCP - requires Role Selection ae.requested_contexts = StoragePresentationContexts # Add role selection items for the storage contexts we will be supporting # as an SCP negotiation_items = [] for context in StoragePresentationContexts: role = build_role(context.abstract_syntax, scp_role=True) negotiation_items.append(role) # Add user identity negotiation request user_identity = UserIdentityNegotiation() user_identity.user_identity_type = 2 user_identity.primary_field = b'username' user_identity.secondary_field = b'password' negotiation_items.append(user_identity) # Associate with the peer at IP address 127.0.0.1 and port 11112 assoc = ae.associate('127.0.0.1', 11112, ext_neg=negotiation_items) if assoc.is_established: assoc.release()