Example #1
0
    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()
Example #2
0
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')
Example #3
0
    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
Example #4
0
    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')
Example #5
0
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')
Example #6
0
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)
Example #7
0
    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
Example #8
0
    # 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)
Example #9
0
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:
Example #10
0
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)
Example #11
0
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')
Example #12
0
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()