Ejemplo n.º 1
0
 def test_shutdown(self):
     """Test trying to shutdown a socket that's already closed."""
     ae = AE()
     ae.add_supported_context('1.2.840.10008.1.1')
     server = ae.start_server(('', 11112), block=False)
     server.socket.close()
     server.shutdown()
Ejemplo n.º 2
0
Archivo: scp.py Proyecto: Ch00k/dino
class SCP:
    def __init__(self, host: str, port: int, ae_title: str):
        self.address = (host, port)
        self.ae = AE(ae_title=ae_title)
        self.create_context()
        self.handlers: List[Tuple] = []

    def create_context(self) -> None:
        for storage_class in list(_STORAGE_CLASSES.values()) + list(
                _VERIFICATION_CLASSES.values()):
            self.ae.add_supported_context(
                abstract_syntax=storage_class,
                transfer_syntax=ALL_TRANSFER_SYNTAXES,
            )

    def add_handler(self, event_type: InterventionEvent, func: Callable,
                    args: Tuple) -> None:
        handler = (event_type, func, args)
        self.handlers.append(handler)

    def start(self, block: bool = True) -> None:
        self.ae.start_server(
            address=self.address,
            block=block,
            evt_handlers=self.handlers,
        )

    def stop(self) -> None:
        self.ae.shutdown()
Ejemplo n.º 3
0
class DummyVerificationSCP(DummyBaseSCP):
    """A threaded dummy verification SCP used for testing"""
    def __init__(self, port=11112):
        self.ae = AE()
        self.port = port
        self.ae.supported_contexts = VerificationPresentationContexts
        self.ae.add_supported_context('1.2.3.4')
        DummyBaseSCP.__init__(self)
        self.status = 0x0000

    def on_c_echo(self, context, info):
        """Callback for ae.on_c_echo

        Parameters
        ----------
        delay : int or float
            Wait `delay` seconds before sending a response
        """
        self.context = context
        self.info = info
        time.sleep(self.delay)

        if self.send_abort:
            self.ae.active_associations[0].abort()

        return self.status
Ejemplo n.º 4
0
class DummyStorageSCP(threading.Thread):
    def __init__(self, port=11112):
        """Initialise the class"""
        self.ae = AE(b'DUMMY_SCP', port)
        self.ae.add_supported_context(CTImageStorage)
        self.ae.add_supported_context(RTImageStorage)
        #self.ae.on_c_echo = self.on_c_echo
        self.ae.on_c_store = self.on_c_store
        #self.ae.on_c_find = self.on_c_find
        #self.ae.on_c_get = self.on_c_get
        #self.ae.on_c_move = self.on_c_move
        threading.Thread.__init__(self)
        self.daemon = True
        self.RECEIVED_DS = 0

    def run(self):
        """The thread run method"""
        self.ae.start()

    def start(self):
        """The thread run method"""
        self.ae.start()

    def stop(self):
        """Stop the SCP thread"""
        self.ae.stop()

    def on_c_store(self, ds, context, info):
        """Callback for ae.on_c_store"""
        return 0x0000
Ejemplo n.º 5
0
def FnStoreScp():

# Implement a handler for evt.EVT_C_STORE
 def handle_store(event):
    """Handle a C-STORE request event."""
    # Decode the C-STORE request's *Data Set* parameter to a pydicom Dataset
    ds = event.dataset

    # Add the File Meta Information
    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()

# Support presentation contexts for all storage SOP Classes

 ae.add_supported_context('1.2.840.10008.5.1.4.1.1.2', transfer_syntax='1.2.840.10008.1.2.4.91')


# Start listening for incoming association requests
 ae.start_server(('', 11112), evt_handlers=handlers)
Ejemplo n.º 6
0
def receive_store_simultaneous(test_ds, nr_assoc, ds_per_assoc, use_yappi=False):
    """Run a Storage SCP and transfer datasets with simultaneous storescu's.

    Parameters
    ----------
    test_ds : pydicom.dataset.Dataset
        The test dataset to use
    nr_assoc : int
        The number of simultaneous associations that will be made.
    ds_per_assoc : int
        The number of C-STORE requests sent per successful association.
    use_yappi : bool, optional
        True to use the yappi profiler, False otherwise (default).
    """
    if use_yappi:
        init_yappi()

    def handle(event):
        return 0x0000

    ae = AE()
    ae.acse_timeout = 5
    ae.dimse_timeout = 5
    ae.network_timeout = 5
    ae.maximum_associations = 15
    ae.add_supported_context(test_ds.SOPClassUID, ImplicitVRLittleEndian)

    server = ae.start_server(
        ("localhost", 11112), block=False, evt_handlers=[(evt.EVT_C_STORE, handle)]
    )

    time.sleep(0.5)
    start_time = time.time()
    is_successful = True

    processes = []
    for ii in range(nr_assoc):
        processes.append(start_storescu(test_ds, ds_per_assoc))

    while None in [pp.poll() for pp in processes]:
        pass

    returncodes = list(set([pp.returncode for pp in processes]))
    if len(returncodes) != 1 or returncodes[0] != 0:
        is_successful = False

    if is_successful:
        print(
            f"C-STORE SCP transferred {nr_assoc * ds_per_assoc} total "
            f"{os.path.basename(test_ds.filename)} datasets over "
            f"{nr_assoc} association{'' if nr_assoc == 1 else 's'} "
            f"in {time.time() - start_time:.2f} s"
        )
    else:
        print("C-STORE SCP benchmark failed")

    server.shutdown()
Ejemplo n.º 7
0
def receive_store_simultaneous(nr_assoc, ds_per_assoc, use_yappi=False):
    """Run a Storage SCP and transfer datasets with simultaneous storescu's.

    Parameters
    ----------
    nr_assoc : int
        The number of simultaneous associations that will be made.
    ds_per_assoc : int
        The number of C-STORE requests sent per successful association.
    use_yappi : bool, optional
        True to use the yappi profiler, False otherwise (default).
    """
    if use_yappi:
        init_yappi()

    def handle(event):
        return 0x0000

    ae = AE()
    ae.acse_timeout = 5
    ae.dimse_timeout = 5
    ae.network_timeout = 5
    ae.maximum_associations = 15
    ae.add_supported_context(DATASET.SOPClassUID, ImplicitVRLittleEndian)

    server = ae.start_server(
        ('', 11112), block=False, evt_handlers=[(evt.EVT_C_STORE, handle)]
    )

    time.sleep(0.5)

    start_time = time.time()
    run_times = []

    is_successful = True

    processes = []
    for ii in range(nr_assoc):
        processes.append(start_storescu(ds_per_assoc))

    while None in [pp.poll() for pp in processes]:
        pass

    returncodes = list(set([pp.returncode for pp in processes]))
    if len(returncodes) != 1 or returncodes[0] != 0:
        is_successful = False

    if is_successful:
        print(
            "C-STORE SCP transferred {} total datasets over {} "
            "association(s) in {:.2f} s"
            .format(nr_assoc * ds_per_assoc, nr_assoc, time.time() - start_time)
        )
    else:
        print("C-STORE SCP benchmark failed")

    server.shutdown()
Ejemplo n.º 8
0
    def test_tls_not_server_yes_client(self, client_context):
        """Test wrapping the requestor socket with TLS (but not server)."""
        ae = AE()
        ae.add_supported_context('1.2.840.10008.1.1')
        server = ae.start_server(('', 11112), block=False)

        ae.add_requested_context('1.2.840.10008.1.1')
        assoc = ae.associate('', 11112, tls_args=(client_context, None))
        assert assoc.is_aborted

        server.shutdown()
Ejemplo n.º 9
0
    def create_application_entity(self,
                                  allow_echo: bool = True,
                                  maximum_pdu_size: int = 0) -> AE:
        """
        Returns an :class:`~pynetdicom.ae.ApplicationEntity` instance.

        Parameters
        ----------
        allow_echo : bool
            Whether to enable C-ECHO request handling or not, default is True
        maximum_pdu_size : int
            Maximal PDU size. By default, overrides pynetdicom's default
            setting to 0 (unlimited)

        Returns
        -------
        AE
            DICOM networking application entity
        """
        from django_dicom.models.networking import (
            messages as networking_messages, )

        logger = logging.getLogger("data.dicom.networking")

        # Get application entity title from the application settings and log
        # start.
        ae_title = get_application_entity_title()
        start_message = networking_messages.APPLICATION_ENTITY_START.format(
            title=ae_title)
        logger.info(start_message)

        # Create application entity instance.
        application_entity = AE(ae_title=ae_title)

        # Log end.
        end_message = networking_messages.APPLICATION_ENTITY_SUCCESS
        logger.info(end_message)

        # Add C-ECHO request handling if *allow_echo=True*.
        if allow_echo:
            application_entity.add_supported_context(VerificationSOPClass,
                                                     ALL_TRANSFER_SYNTAXES[:])
            logger.debug(networking_messages.C_ECHO_ENABLED)

        # Modify the maximal PDU size to optimize throughput.
        application_entity.maximum_pdu_size = maximum_pdu_size
        if maximum_pdu_size != 0:
            message = networking_messages.PDU_LIMIT_CONFIGURATION.format(
                maximum_pdu_size=maximum_pdu_size)
            logger.debug(message)

        return application_entity
    def start(self):
        """ Start the server and listen to specified address and port """
        ae = AE(self._server_config.ae_title)
        ae.add_supported_context(ModalityWorklistInformationFind)
        self._logger.info(
            'Running worklist server with AE title {}, ip: {}, listening to port: {}'
            .format(self._server_config.ae_title,
                    self._server_config.network_address.address,
                    self._server_config.network_address.port))

        self._server = ae.start_server(self._server_config.network_address,
                                       evt_handlers=self._handlers,
                                       block=self._blocking)
Ejemplo n.º 11
0
    def test_tls_not_server_not_client(self):
        """Test associating with no TLS on either end."""
        ae = AE()
        ae.add_supported_context('1.2.840.10008.1.1')
        server = ae.start_server(('', 11112), block=False)

        ae.add_requested_context('1.2.840.10008.1.1')
        assoc = ae.associate('', 11112)
        assert assoc.is_established
        assoc.release()
        assert assoc.is_released

        server.shutdown()
Ejemplo n.º 12
0
def main(args=None):
    """Run the application."""
    if args is not None:
        sys.argv = args

    args = _setup_argparser()
    if args.version:
        print('storescp.py v{}'.format(__version__))
        sys.exit()

    APP_LOGGER = setup_logging(args, 'storescp')
    APP_LOGGER.debug('storescp.py v{0!s}'.format(__version__))
    APP_LOGGER.debug('')

    # Set Transfer Syntax options
    transfer_syntax = ALL_TRANSFER_SYNTAXES[:]

    if args.prefer_uncompr:
        transfer_syntax.remove(ImplicitVRLittleEndian)
        transfer_syntax.append(ImplicitVRLittleEndian)
    elif args.prefer_little:
        transfer_syntax.remove(ExplicitVRLittleEndian)
        transfer_syntax.insert(0, ExplicitVRLittleEndian)
    elif args.prefer_big:
        transfer_syntax.remove(ExplicitVRBigEndian)
        transfer_syntax.insert(0, ExplicitVRBigEndian)
    elif args.implicit:
        transfer_syntax = [ImplicitVRLittleEndian]

    handlers = [(evt.EVT_C_STORE, handle_store, [args, APP_LOGGER])]

    # Create application entity
    ae = AE(ae_title=args.ae_title)

    # Add presentation contexts with specified transfer syntaxes
    for context in AllStoragePresentationContexts:
        ae.add_supported_context(context.abstract_syntax, transfer_syntax)

    if not args.no_echo:
        for context in VerificationPresentationContexts:
            ae.add_supported_context(context.abstract_syntax, transfer_syntax)

    ae.maximum_pdu_size = args.max_pdu

    # Set timeouts
    ae.network_timeout = args.network_timeout
    ae.acse_timeout = args.acse_timeout
    ae.dimse_timeout = args.dimse_timeout

    ae.start_server((args.bind_address, args.port), evt_handlers=handlers)
Ejemplo n.º 13
0
class ServiceClassProvider:
    def __init__(self, aet: str, config: ServiceClassProviderConfig) -> None:
        self.config = config
        self.address = ("127.0.0.1", config.port)

        self.ae = AE(ae_title=aet)
        self.ae.implementation_class_uid = config.implementation_class_uid
        self.ae.implementation_version_name = f'{aet}_{config.implementation_class_uid.split(".")[-1]}'[:
                                                                                                        16]

        self.SUPPORTED_ABSTRACT_SYNTAXES: List[str] = [
            _STORAGE_CLASSES.get('CTImageStorage'),
            _STORAGE_CLASSES.get('EnhancedCTImageStorage'),
            _STORAGE_CLASSES.get('LegacyConvertedEnhancedCTImageStorage')
        ]
        for abstract_syntax in self.SUPPORTED_ABSTRACT_SYNTAXES:
            self.ae.add_supported_context(abstract_syntax,
                                          ALL_TRANSFER_SYNTAXES)
        self.ae.add_supported_context(
            _VERIFICATION_CLASSES.get("VerificationSOPClass"),
            DEFAULT_TRANSFER_SYNTAXES)

        self.ae.require_calling_aet = ["PYNETDICOM"]

    def handle_c_store(self, event: Event) -> int:
        ds = event.dataset
        ds.file_meta = event.file_meta

        metadata: Dict[str, Optional[ParsedElementValue]] = {
            "CallingAET": cast(str, event.assoc.requestor.ae_title.strip()),
            "SopInstanceUID": safe_get(ds, 0x00080018),
            "StudyInstanceUID": safe_get(ds, 0x0020000D),
            "Modality": safe_get(ds, 0x00080060),
        }
        log_message_meta = " - ".join(
            [f"{k}={v}" for k, v in metadata.items() if v])
        logger.info(f"Processed C-STORE {log_message_meta}")

        ds.save_as(metadata, write_like_original=False)

        return 0x0000

    def start(self) -> None:
        logger.info(
            f"Starting DIMSE C-STORE AE on address={self.address} aet={self.ae.ae_title}"
        )
        self.handlers = [(events.EVT_C_STORE, self.handle_c_store)]
        self.ae.start_server(self.address,
                             block=True,
                             evt_handlers=self.handlers)
Ejemplo n.º 14
0
    def test_tls_yes_server_not_client(self, server_context):
        """Test wrapping the requestor socket with TLS (and server)."""
        ae = AE()
        ae.add_supported_context('1.2.840.10008.1.1')
        server = ae.start_server(
            ('', 11112),
            block=False,
            ssl_context=server_context,
        )

        ae.add_requested_context('1.2.840.10008.1.1')
        assoc = ae.associate('', 11112)
        assert assoc.is_aborted

        server.shutdown()
class DicomSCP:
    def __init__(self):
        self.ae = AE()
        self.ae.ae_title = "BPPACS"
        self.ae.add_supported_context(OphthalmicPhotography8BitImageStorage, SYNTAX_UIDS)

    def start(self):
        self.ae.start_server(('', 11112), evt_handlers=[(evt.EVT_C_ECHO, self.handle_echo), (evt.EVT_C_STORE, self.handle_store)])

    def handle_echo(self, event):
        log.info("Echo called")
        return 0x0000

    def handle_store(self, event):
        log.info("Store received for patient %s" % event.dataset.PatientID)
        return 0x0000
Ejemplo n.º 16
0
    def test_tls_yes_server_yes_client(self, server_context, client_context):
        """Test associating with no TLS on either end."""
        ae = AE()
        ae.add_supported_context('1.2.840.10008.1.1')
        server = ae.start_server(
            ('', 11112),
            block=False,
            ssl_context=server_context,
        )

        ae.add_requested_context('1.2.840.10008.1.1')
        assoc = ae.associate('', 11112, tls_args=(client_context, None))
        assert assoc.is_established
        assoc.release()
        assert assoc.is_released

        server.shutdown()
Ejemplo n.º 17
0
class DummyDeleteSCP(DummyBaseSCP):
    """A threaded dummy delete SCP used for testing"""
    def __init__(self, port=11112):
        self.ae = AE(port=port)
        # Print Job SOP Class
        self.ae.add_supported_context(PrintJobSOPClass)
        self.ae.add_supported_context(VerificationSOPClass)
        DummyBaseSCP.__init__(self)
        self.status = 0x0000

    def on_n_delete(self, context, info):
        """Callback for ae.on_n_delete"""
        self.context = context
        self.info = info
        time.sleep(self.delay)

        return self.status
Ejemplo n.º 18
0
def main(args=None):
    """Run the application."""
    if args is not None:
        sys.argv = args

    args = _setup_argparser()

    if args.version:
        print(f"echoscp.py v{__version__}")
        sys.exit()

    APP_LOGGER = setup_logging(args, "echoscp")
    APP_LOGGER.debug(f"echoscp.py v{__version__}")
    APP_LOGGER.debug("")

    # Set Transfer Syntax options
    transfer_syntax = ALL_TRANSFER_SYNTAXES[:]

    if args.prefer_uncompr:
        transfer_syntax.remove(str(ImplicitVRLittleEndian))
        transfer_syntax.append(ImplicitVRLittleEndian)
    elif args.prefer_little:
        transfer_syntax.remove(str(ExplicitVRLittleEndian))
        transfer_syntax.insert(0, ExplicitVRLittleEndian)
    elif args.prefer_big:
        transfer_syntax.remove(str(ExplicitVRBigEndian))
        transfer_syntax.insert(0, ExplicitVRBigEndian)
    elif args.implicit:
        transfer_syntax = [ImplicitVRLittleEndian]

    handlers = [(evt.EVT_C_ECHO, handle_echo)]

    # Create application entity
    ae = AE(ae_title=args.ae_title)
    ae.add_supported_context(Verification, transfer_syntax)
    ae.maximum_pdu_size = args.max_pdu
    ae.network_timeout = args.network_timeout
    ae.acse_timeout = args.acse_timeout
    ae.dimse_timeout = args.dimse_timeout

    ae.start_server((args.bind_address, args.port), evt_handlers=handlers)
Ejemplo n.º 19
0
class DummySetSCP(DummyBaseSCP):
    """A threaded dummy get SCP used for testing"""
    def __init__(self, port=11112):
        self.ae = AE(port=port)
        self.ae.add_supported_context(PrintJobSOPClass)
        self.ae.add_supported_context(VerificationSOPClass)
        DummyBaseSCP.__init__(self)
        self.status = 0x0000
        ds = Dataset()
        ds.PatientName = 'Test'
        ds.SOPClassUID = PrintJobSOPClass
        ds.SOPInstanceUID = '1.2.3.4'
        self.dataset = ds

    def on_n_set(self, ds, context, info):
        """Callback for ae.on_n_get"""

        self.context = context
        self.info = info
        time.sleep(self.delay)

        return self.status, self.dataset
Ejemplo n.º 20
0
class ServiceClassProvider:
    def __init__(self, aet: str, config: ServiceClassProviderConfig) -> None:
        self.config = config
        self.address = ("0.0.0.0", config.port)

        self.ae = AE(ae_title=aet)
        self.ae.implementation_class_uid = config.implementation_class_uid
        self.ae.implementation_version_name = f'{aet}_{config.implementation_class_uid.split(".")[-1]}'[:16]

        self.SUPPORTED_ABSTRACT_SYNTAXES: List[str] = [
            sop_class.DigitalXRayImagePresentationStorage,
            sop_class.DigitalXRayImageProcessingStorage,
            sop_class.CTImageStorage,
        ]
        for abstract_syntax in self.SUPPORTED_ABSTRACT_SYNTAXES:
            self.ae.add_supported_context(abstract_syntax, ALL_TRANSFER_SYNTAXES)
        self.ae.add_supported_context(VerificationSOPClass, DEFAULT_TRANSFER_SYNTAXES)

        self.ae.require_calling_aet = ["SAMPLESCU"]

    def handle_c_store(self, event: Event) -> int:
        ds = event.dataset
        ds.file_meta = event.file_meta

        metadata: Dict[str, Optional[ParsedElementValue]] = {
            "CallingAET": cast(str, event.assoc.requestor.ae_title.strip()),
            "SopInstanceUID": safe_get(ds, 0x00080018),
            "StudyInstanceUID": safe_get(ds, 0x0020000D),
            "Modality": safe_get(ds, 0x00080060),
        }
        log_message_meta = " - ".join([f"{k}={v}" for k, v in metadata.items() if v])
        logger.info(f"Processed C-STORE {log_message_meta}")

        return 0x0000

    def start(self) -> None:
        logger.info(f"Starting DIMSE C-STORE AE on address={self.address} aet={self.ae.ae_title}")
        self.handlers = [(events.EVT_C_STORE, self.handle_c_store)]
        self.ae.start_server(self.address, block=True, evt_handlers=self.handlers)
Ejemplo n.º 21
0
    def listen(self, recieved_callback, ae_title="PYNETDICOM"):

        self.recieved_callback = recieved_callback

        # Initialise the Application Entity and specify the listen port
        ae = AE(ae_title=ae_title)

        # Add the supported presentation context
        ae.add_supported_context(VerificationSOPClass)
        for context in StoragePresentationContexts:
            ae.add_supported_context(context.abstract_syntax)

        handlers = [
            (evt.EVT_C_MOVE, self.on_c_store),
            (evt.EVT_C_STORE, self.on_c_store),
            (evt.EVT_C_ECHO, self.on_c_echo),
            (evt.EVT_ACCEPTED, self.on_association_accepted),
            (evt.EVT_RELEASED, self.on_association_released),
        ]

        # Start listening for incoming association requests
        ae.start_server(("", self.port), evt_handlers=handlers)
Ejemplo n.º 22
0
def main():

    global inference_queue
    inference_queue = deque()

    global dicom_store
    dicom_store = {}

    # Parent folder to all storage requests
    os_helpers.make_directory(config.SCP_STORAGE_PATH)

    ae = AE()
    ae.network_timeout = None
    ae.acse_timeout = None
    ae.dimse_timeout = None
    ae.maximum_pdu_size = 0
    ae.maximum_associations = 14  # Tested with 14 threads

    handlers = [
        (evt.EVT_ACCEPTED, handle_accepted),
        (evt.EVT_C_STORE, handle_store),
        (evt.EVT_RELEASED, handle_release),
    ]

    storage_sop_classes = [
        cx.abstract_syntax for cx in AllStoragePresentationContexts
    ]

    for uid in storage_sop_classes:
        ae.add_supported_context(uid, ALL_TRANSFER_SYNTAXES)

    ae.start_server((config.SCP_IP, config.SCP_PORT),
                    block=False,
                    evt_handlers=handlers)

    print_listening()

    inference_loop()
Ejemplo n.º 23
0
def main():
    handlers = [(evt.EVT_C_STORE, handle_store),
                (evt.EVT_RELEASED, handle_release)]

    ae = AE()
    ae.network_timeout = None
    ae.acse_timeout = None
    ae.dimse_timeout = None
    ae.maximum_pdu_size = 0
    ae.maximum_associations = 1  # TODO Handle more than one

    storage_sop_classes = [
        cx.abstract_syntax for cx in AllStoragePresentationContexts
    ]

    for uid in storage_sop_classes:
        ae.add_supported_context(uid, ALL_TRANSFER_SYNTAXES)

    print("\nListening for association request on port:", config.SCP_PORT)

    ae.start_server((config.SCP_IP, config.SCP_PORT),
                    block=True,
                    evt_handlers=handlers)
Ejemplo n.º 24
0
Archivo: scp.py Proyecto: qurit/raiven
class SCP:
    _handlers = [
        (evt.EVT_REQUESTED, handle_association_request),
        (evt.EVT_RELEASED, handle_association_release),
        (evt.EVT_C_STORE, handle_store),
    ]

    def __init__(self,
                 ae_title='PICOM_SCP',
                 host='localhost',
                 port=11112,
                 debug=False):
        self.ae_title = ae_title
        self.host = host
        self.port = port

        self._ae = AE(ae_title)
        self._ae.supported_contexts = AllStoragePresentationContexts
        self._ae.add_supported_context(VerificationSOPClass)

        # if debug:
        #     debug_logger()

    def start_server(self, blocking=False):
        msg = f"Starting DICOM SCP {self.ae_title} on port {self.port}"
        logger.info(msg)
        print(msg)

        self._ae.start_server((self.host, self.port),
                              block=blocking,
                              evt_handlers=self._handlers)

    def stop_server(self):
        self._ae.shutdown()

    def get_ae(self) -> AE:
        return self._ae
Ejemplo n.º 25
0
def main(args=None):
    """Run the application."""
    if args is not None:
        sys.argv = args

    args = _setup_argparser()

    if args.version:
        print(f"qrscp.py v{__version__}")
        sys.exit()

    APP_LOGGER = setup_logging(args, "qrscp")
    APP_LOGGER.debug(f"qrscp.py v{__version__}")
    APP_LOGGER.debug("")

    APP_LOGGER.debug("Using configuration from:")
    APP_LOGGER.debug(f"  {args.config}")
    APP_LOGGER.debug("")
    config = ConfigParser()
    config.read(args.config)

    if args.ae_title:
        config["DEFAULT"]["ae_title"] = args.ae_title
    if args.port:
        config["DEFAULT"]["port"] = args.port
    if args.max_pdu:
        config["DEFAULT"]["max_pdu"] = args.max_pdu
    if args.acse_timeout:
        config["DEFAULT"]["acse_timeout"] = args.acse_timeout
    if args.dimse_timeout:
        config["DEFAULT"]["dimse_timeout"] = args.dimse_timeout
    if args.network_timeout:
        config["DEFAULT"]["network_timeout"] = args.network_timeout
    if args.bind_address:
        config["DEFAULT"]["bind_address"] = args.bind_address
    if args.database_location:
        config["DEFAULT"]["database_location"] = args.database_location
    if args.instance_location:
        config["DEFAULT"]["instance_location"] = args.instance_location

    # Log configuration settings
    _log_config(config, APP_LOGGER)
    app_config = config["DEFAULT"]

    dests = {}
    for ae_title in config.sections():
        dest = config[ae_title]
        # Convert to bytes and validate the AE title
        ae_title = set_ae(ae_title, "ae_title", False, False)
        dests[ae_title] = (dest["address"], dest.getint("port"))

    # Use default or specified configuration file
    current_dir = os.path.abspath(os.path.dirname(__file__))
    instance_dir = os.path.join(current_dir, app_config["instance_location"])
    db_path = os.path.join(current_dir, app_config["database_location"])

    # The path to the database
    db_path = f"sqlite:///{db_path}"
    db.create(db_path)

    # Clean up the database and storage directory
    if args.clean:
        response = input(
            "This will delete all instances from both the storage directory "
            "and the database. Are you sure you wish to continue? [yes/no]: ")
        if response != "yes":
            sys.exit()

        if clean(db_path, instance_dir, APP_LOGGER):
            sys.exit()
        else:
            sys.exit(1)

    # Try to create the instance storage directory
    os.makedirs(instance_dir, exist_ok=True)

    ae = AE(app_config["ae_title"])
    ae.maximum_pdu_size = app_config.getint("max_pdu")
    ae.acse_timeout = app_config.getfloat("acse_timeout")
    ae.dimse_timeout = app_config.getfloat("dimse_timeout")
    ae.network_timeout = app_config.getfloat("network_timeout")

    ## Add supported presentation contexts
    # Verification SCP
    ae.add_supported_context(Verification, ALL_TRANSFER_SYNTAXES)

    # Storage SCP - support all transfer syntaxes
    for cx in AllStoragePresentationContexts:
        ae.add_supported_context(cx.abstract_syntax,
                                 ALL_TRANSFER_SYNTAXES,
                                 scp_role=True,
                                 scu_role=False)

    # Query/Retrieve SCP
    ae.add_supported_context(PatientRootQueryRetrieveInformationModelFind)
    ae.add_supported_context(PatientRootQueryRetrieveInformationModelMove)
    ae.add_supported_context(PatientRootQueryRetrieveInformationModelGet)
    ae.add_supported_context(StudyRootQueryRetrieveInformationModelFind)
    ae.add_supported_context(StudyRootQueryRetrieveInformationModelMove)
    ae.add_supported_context(StudyRootQueryRetrieveInformationModelGet)

    # Set our handler bindings
    handlers = [
        (evt.EVT_C_ECHO, handle_echo, [args, APP_LOGGER]),
        (evt.EVT_C_FIND, handle_find, [db_path, args, APP_LOGGER]),
        (evt.EVT_C_GET, handle_get, [db_path, args, APP_LOGGER]),
        (evt.EVT_C_MOVE, handle_move, [dests, db_path, args, APP_LOGGER]),
        (evt.EVT_C_STORE, handle_store,
         [instance_dir, db_path, args, APP_LOGGER]),
    ]

    # Listen for incoming association requests
    ae.start_server((app_config["bind_address"], app_config.getint("port")),
                    evt_handlers=handlers)
            if ds.PatientName not in ['*', '', '?']:
                matching = [
                    inst for inst in instances
                    if inst.PatientName == ds.PatientName
                ]

    for instance in matching:
        # Check if C-CANCEL has been received
        if event.is_cancelled:
            yield (0XFE00, None)
            return

        identifier = Dataset()
        identifier.PatientName = instance.PatientName
        identifier.QueryRetrieveLevel = ds.QueryRetrieveLevel

        # Pending
        yield (0XFF00, identifier)


handlers = [(evt.EVT_C_FIND, handle_find)]

# Initialise the Application Entity and specify the listen port
ae = AE()

# Add the supported presentation context
ae.add_supported_context(PatientRootQueryRetrieveInformationModelFind)

# Start listening for incoming association requests
ae.start_server(('', 11112), evt_handlers=handlers)
Ejemplo n.º 27
0
    except:
        dcm_files = []
        yield 0

    for dcm in dcm_files:
        ds = dcmread(dcm, force=True)
        yield 0xFF00, ds


handlers = [(evt.EVT_C_GET, handle_get)]

# Create application entity
ae = AE(ae_title=args.aetitle)

for context in StoragePresentationContexts:
    ae.add_supported_context(context.abstract_syntax,
                             transfer_syntax,
                             scp_role=True,
                             scu_role=False)
for context in QueryRetrievePresentationContexts:
    ae.add_supported_context(context.abstract_syntax, transfer_syntax)

ae.maximum_pdu_size = args.max_pdu

# Set timeouts
ae.network_timeout = args.timeout
ae.acse_timeout = args.acse_timeout
ae.dimse_timeout = args.dimse_timeout

ae.start_server(('', args.port), evt_handlers=handlers)
Ejemplo n.º 28
0
    dcm_files = [os.path.join(basedir, x) for x in dcm_files]
    for dcm in dcm_files:
        data = dcmread(dcm, force=True)

        ds = Dataset()
        if 'QueryRetrieveLevel' in dataset:
            ds.QueryRetrieveLevel = dataset.QueryRetrieveLevel
        ds.RetrieveAETitle = args.aetitle
        ds.PatientName = data.PatientName

        status_ds = Dataset()
        status_ds.Status = 0xFF00
        yield status_ds, ds


# Create application entity
ae = AE(ae_title=args.aetitle)
for context in QueryRetrievePresentationContexts:
    ae.add_supported_context(context.abstract_syntax, transfer_syntax)

ae.maximum_pdu_size = args.max_pdu

# Set timeouts
ae.network_timeout = args.timeout
ae.acse_timeout = args.acse_timeout
ae.dimse_timeout = args.dimse_timeout

ae.on_c_find = on_c_find

ae.start_server(('', args.port))
Ejemplo n.º 29
0
        log = (f"{datetime.datetime.now():%Y-%m-%d|%H:%M:%S} "
               f"| {ds.AccessionNumber} "
               f"| {ds.SeriesDescription} \n")
        with open(logfile, 'a') as f:
            f.write(log)
    except Exception as e:
        with open(logfile, 'a') as f:
            f.write(traceback.format_exc())

    return 0x0000


#get the storage path
storage_dir = os.environ['storage']
logfile = os.environ['log']
aetitle = os.environ['aetitle']
aeport = int(os.environ['aeport'])

handlers = [(evt.EVT_C_STORE, handle_store, [storage_dir])]

# Initialise the Application Entity
ae = AE(ae_title=bytes(aetitle, encoding='UTF-8'))

# Add the supported presentation contexts
ae.supported_contexts = StoragePresentationContexts
ae.add_supported_context(VerificationSOPClass)
ae.add_supported_context(MRImageStorage, JPEG2000Lossless)

# Start listening for incoming association requests
ae.start_server(('0.0.0.0', aeport), evt_handlers=handlers)
Ejemplo n.º 30
0
    host = "192.168.8.177"
    port = "4242"
    arg0 = '-ds'  #-ds all files under dir, '' single file
    arg1 = '-q'  #--v verbose  q quick, d debug
    arg2 = '-cx'  #require context

    file = fname
    storescu.main([arg0, host, port, file, arg1, arg2])
    print("file send!", file)
    os.remove(file)
    return 0x0000


handlers = [(evt.EVT_C_STORE, handle_store, ['out'])]
#context_a = _build_context(CTImageStorage, JPEGLossless)
#context_b = _build_context(CTImageStorage, JPEG2000Lossless)
ae = AE()
#ae.add_requested_context(context_a)
#ae.add_requested_context(context_b)
storage_sop_classes = [
    cx.abstract_syntax for cx in AllStoragePresentationContexts
] + [JPEGLossless] + [JPEG2000Lossless] + [VerificationSOPClass] + [
    CTImageStorage
] + [VerificationSOPClass]

for uid in storage_sop_classes:
    ae.add_supported_context(uid, ALL_TRANSFER_SYNTAXES)
n = 0
#ae.add_supported_context(CTImageStorage, VerificationSOPClass)
ae.start_server(('', 11112), block=True, evt_handlers=handlers)