Ejemplo n.º 1
0
import os

from pydicom import dcmread
from pydicom.data import get_testdata_files
from pydicom.dataset import Dataset

from pynetdicom import AE
from pynetdicom.sop_class import ModalityWorklistInformationFind

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

# Add a requested presentation context
ae.add_supported_context(ModalityWorklistInformationFind)


# Implement the AE.on_c_store callback
def on_c_find(ds, context, info):
    print(ds)
    """Respond to a C-FIND request Identifier `ds`.

    Parameters
    ----------
    ds : pydicom.dataset.Dataset
        The Identifier dataset send by the peer.
    context : namedtuple
        The presentation context that the dataset was sent under.
    info : dict
        Information about the association and query/retrieve request.

    Yields
Ejemplo n.º 2
0
logger = logging.getLogger('pynetdicom')


# Implement a handler 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()
ae = AE(ae_title=b'abc')

# Add the supported presentation contexts
ae.supported_contexts = StoragePresentationContexts

# Start listening for incoming association requests
ae.start_server(('', 4100), evt_handlers=handlers)
Ejemplo n.º 3
0
def main(args=None):
    """Run the application."""
    if args is not None:
        sys.argv = args

    args = _setup_argparser()

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

    APP_LOGGER = setup_logging(args, 'getscu')
    APP_LOGGER.debug('getscu.py v{0!s}'.format(__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 = [
        PlannedImagingAgentAdministrationSRStorage,
        PerformedImagingAgestAdministrationSRStorage,
        EncapsulatedSTLStorage,
    ]
    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 receive_store(nr_assoc, ds_per_assoc, write_ds=False, use_yappi=False):
    """Run a Storage SCP and transfer datasets with sequential storescu's.

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

    def handle(event):
        if write_ds:
            # TODO: optimise write using event.request.DataSet instead
            # Standard write using dataset decode and re-encode
            tfile = tempfile.TemporaryFile(mode='w+b')
            ds = event.dataset
            ds.file_meta = event.file_meta
            ds.save_as(tfile)

        return 0x0000

    ae = AE()
    ae.acse_timeout = 5
    ae.dimse_timeout = 5
    ae.network_timeout = 5
    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

    for ii in range(nr_assoc):
        p = start_storescu(ds_per_assoc)
        # Block until transfer is complete
        p.wait()
        if p.returncode != 0:
            is_successful = False
            break

    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()
def send_store(nr_assoc, ds_per_assoc, use_yappi=False):
    """Send a number of sequential C-STORE requests.

    Parameters
    ----------
    nr_assoc : int
        The total number of (sequential) 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()

    # Start SCP
    server = start_storescp()
    time.sleep(0.5)

    ae = AE()
    ae.acse_timeout = 5
    ae.dimse_timeout = 5
    ae.network_timeout = 5
    ae.add_requested_context(DATASET.SOPClassUID, ImplicitVRLittleEndian)

    # Start timer
    start_time = time.time()
    run_times = []

    is_successful = True

    for ii in range(nr_assoc):
        if not is_successful:
            break

        assoc = ae.associate('localhost', 11112)

        if assoc.is_established:
            for jj in range(ds_per_assoc):
                try:
                    status = assoc.send_c_store(DATASET)
                    if status and status.Status != 0x0000:
                        is_successful = False
                        break
                except RuntimeError:
                    is_successful = False
                    break

            assoc.release()
            if is_successful:
                run_times.append(time.time() - start_time)
        else:
            is_successful = False
            break

    if is_successful:
        print("C-STORE SCU 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 SCU benchmark failed")

    server.terminate()
Ejemplo n.º 6
0
def FnMwlScp():

    # Implement the handler for evt.EVT_C_FIND
    def handle_find(event):
        """Handle a C-FIND request event."""
        ds = event.identifier
        #print(ds)

        # Import stored SOP Instances
        instances = []
        instances = FnInfoMsql()
        matching = []

        #if 'QueryRetrieveLevel' not in ds:
        # Failure
        #   yield 0xC000, None
        #  return

        if ds.PatientName != '0':
            matching = [
                inst for inst in instances
                if inst.PatientName == ds.PatientName
            ]
        if ds.StudyInstanceUID != '0':
            matching = [
                inst for inst in instances
                if inst.StudyInstanceUID == ds.StudyInstanceUID
            ]

            #  print('matching:',matching)

            # Skip the other possibile values...

        # Skip the other possible attributes...

        # Skip the other QR levels...

        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.Modality = instance.Modality
            identifier.StudyDate = ds.StudyDate
            #print('inst:',instance.SOPInstanceUID)
            identifier.SOPInstanceUID = instance.SOPInstanceUID
            identifier.SeriesDescription = instance.SeriesDescription
            identifier.ProtocolName = instance.ProtocolName
            identifier.StudyDescription = instance.StudyDescription

            # 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(ModalityWorklistInformationFind)
    # print (ae)
    ae.title = b'ANY-SCP'
    #print (ae)
    # Start listening for incoming association requests
    ae.start_server(('', 11140), evt_handlers=handlers)
Ejemplo n.º 7
0
from pynetdicom.sop_class import UltrasoundMultiframeImageStorage

logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("storage_scu_log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(handler)
logger.addHandler(console)

ae = AE(ae_title=b'MY_STORAGE_SCU')
ae.add_requested_context(UID('1.2.840.10008.5.1.4.1.1.3.1'))
# ae.add_requested_context(UltrasoundMultiframeImageStorage)
for cx in ae.requested_contexts:
    print(cx)

# assoc = ae.associate('192.168.3.5', 4100)
assoc = ae.associate('127.0.0.1', 4100)

if assoc.is_established:
    logger.info('assoc is established')
    # dataset = dcmread('./MRI.dcm')
    dataset = dcmread('./IMG00001')
    # `status` is the response from the peer to the store request
    # but may be an empty pydicom Dataset if the peer timed out or
    # sent an invalid dataset.
Ejemplo n.º 8
0
 def setup(self):
     ae = AE()
     self.assoc = Association(ae, MODE_REQUESTOR)
Ejemplo n.º 9
0
    return status_ds


handlers = [(evt.EVT_C_STORE, handle_store)]

# Test output-directory
if args.output_directory is not None:
    if not os.access(args.output_directory, os.W_OK | os.X_OK):
        APP_LOGGER.error('No write permissions or the output '
                         'directory may not exist:')
        APP_LOGGER.error("    {0!s}".format(args.output_directory))
        sys.exit()

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

# Add presentation contexts with specified transfer syntaxes
for context in StoragePresentationContexts:
    ae.add_supported_context(context.abstract_syntax, transfer_syntax)
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.timeout
ae.acse_timeout = args.acse_timeout
ae.dimse_timeout = args.dimse_timeout

ae.start_server((args.bind_addr, args.port), evt_handlers=handlers)
Ejemplo n.º 10
0
def main(args=None):
    """Run the application."""
    if args is not None:
        sys.argv = args

    args = _setup_argparser()

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

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

    APP_LOGGER.debug('Using configuration from:'.format(args.config))
    APP_LOGGER.debug('  {}'.format(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 = validate_ae_title(ae_title.encode("ascii"), use_short=True)
        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 = 'sqlite:///{}'.format(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, 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(VerificationSOPClass, 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
    )
Ejemplo n.º 11
0
    transfer_syntax.remove(ExplicitVRLittleEndian)
    transfer_syntax.insert(0, ExplicitVRLittleEndian)

if args.prefer_big and ExplicitVRBigEndian in transfer_syntax:
    transfer_syntax.remove(ExplicitVRBigEndian)
    transfer_syntax.insert(0, ExplicitVRBigEndian)


def on_c_echo(context, info):
    """Optional implementation of the AE.on_c_echo callback."""
    # Return a Success response to the peer
    # We could also return a pydicom Dataset with a (0000, 0900) Status
    #   element
    return 0x0000


# Create application entity
ae = AE(ae_title=args.aetitle, port=args.port)
ae.add_supported_context(VerificationSOPClass, 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

# Set callback
ae.on_c_echo = on_c_echo

ae.start()
Ejemplo n.º 12
0
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("storage_scu_log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s\
                              - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(console)

ds = dcmread('/Volumes/Transcend/mediclouds/PACS/MRI.dcm')
# ds = dcmread('/Volumes/Transcend/mediclouds/PACS/IMG00001')
ae = AE(ae_title=b'ilab_scu')

ae.requested_contexts = StoragePresentationContexts
# ae.add_requested_context(VerificationPresentationContexts)
# ae.add_requested_context(VerificationSOPClass)

# for cx in ae.requested_contexts:
#     print(cx)

assoc = ae.associate('192.168.3.5', 4100, ae_title=b'lkjds')

if assoc.is_established:
    logger.info('assoc is established')
    dataset = dcmread('./MRI.dcm')
    # dataset = dcmread('./IMG00001')
    # `status` is the response from the peer to the store request
Ejemplo n.º 13
0
def main(args=None):
    """Run the application."""
    if args is not None:
        sys.argv = args

    args = _setup_argparser()

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

    APP_LOGGER = setup_logging(args, 'movescu')
    APP_LOGGER.debug(f'movescu.py v{__version__}')
    APP_LOGGER.debug('')

    # Create query (identifier) dataset
    try:
        # If you're looking at this to see how QR Move 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)

    # Create application entity
    ae = AE()

    # Start the Store SCP (optional)
    scp = None
    if args.store:
        transfer_syntax = ALL_TRANSFER_SYNTAXES[:]
        store_handlers = [(evt.EVT_C_STORE, handle_store, [args, APP_LOGGER])]
        ae.ae_title = args.store_aet
        for cx in AllStoragePresentationContexts:
            ae.add_supported_context(cx.abstract_syntax, transfer_syntax)

        scp = ae.start_server(('', args.store_port),
                              block=False,
                              evt_handlers=store_handlers)

    ae.ae_title = args.calling_aet
    ae.acse_timeout = args.acse_timeout
    ae.dimse_timeout = args.dimse_timeout
    ae.network_timeout = args.network_timeout
    ae.requested_contexts = QueryRetrievePresentationContexts
    ae.supported_contexts = []

    # Query/Retrieve Information Models
    if args.study:
        query_model = StudyRootQueryRetrieveInformationModelMove
    elif args.psonly:
        query_model = PatientStudyOnlyQueryRetrieveInformationModelMove
    else:
        query_model = PatientRootQueryRetrieveInformationModelMove

    # Extended Negotiation
    ext_neg = []
    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 = [item]

    # Request association with remote AE
    assoc = ae.associate(args.addr,
                         args.port,
                         ae_title=args.called_aet,
                         max_pdu=args.max_pdu,
                         ext_neg=ext_neg)
    if assoc.is_established:
        # Send query
        move_aet = args.move_aet or args.calling_aet
        responses = assoc.send_c_move(identifier, move_aet, query_model)
        for (status, rsp_identifier) in responses:
            # If `status.Status` is one of the 'Pending' statuses then
            #   `rsp_identifier` is the C-MOVE 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()
        _EXIT_VALUE = 0
    else:
        _EXIT_VALUE = 1

    # Shutdown the Storage SCP (if used)
    if scp:
        scp.shutdown()

    sys.exit(_EXIT_VALUE)
Ejemplo n.º 14
0
def _send_ctimage(hostname, port, transfersyntax):
    ae = AE()
    ae.add_requested_context(CTImageStorage, transfersyntax)
    assoc = ae.associate(hostname, int(port))
    return assoc
Ejemplo n.º 15
0
 def __init__(self, port=11112):
     self.ae = AE(port=port)
     self.ae.supported_contexts = VerificationPresentationContexts
     self.ae.add_supported_context('1.2.3.4')
     DummyBaseSCP.__init__(self)
     self.status = 0x0000
Ejemplo n.º 16
0
def main(args=None):
    """Run the application."""
    if args is not None:
        sys.argv = args

    args = _setup_argparser()

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

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

    # Create query (identifier) dataset
    try:
        # If you're looking at this to see how QR Find 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)
        raise exc
        sys.exit(1)

    # Create application entity
    # Binding to port 0 lets the OS pick an available port
    ae = AE(ae_title=args.calling_aet)

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

    # Set the Presentation Contexts we are requesting the Find SCP support
    ae.requested_contexts = (QueryRetrievePresentationContexts +
                             BasicWorklistManagementPresentationContexts)

    # Query/Retrieve Information Models
    if args.worklist:
        query_model = ModalityWorklistInformationFind
    elif args.study:
        query_model = StudyRootQueryRetrieveInformationModelFind
    elif args.psonly:
        query_model = PatientStudyOnlyQueryRetrieveInformationModelFind
    else:
        query_model = PatientRootQueryRetrieveInformationModelFind

    # Request association with (QR/BWM) Find SCP
    assoc = ae.associate(args.addr,
                         args.port,
                         ae_title=args.called_aet,
                         max_pdu=args.max_pdu)
    if assoc.is_established:
        # Send C-FIND request, `responses` is a generator
        responses = assoc.send_c_find(identifier, query_model)
        # Used to generate filenames if args.write used
        fname = generate_filename()
        for (status, rsp_identifier) in responses:
            # If `status.Status` is one of the 'Pending' statuses then
            #   `rsp_identifier` is the C-FIND response's Identifier dataset
            if status and status.Status in [0xFF00, 0xFF01]:
                if args.write:
                    rsp_identifier.file_meta = get_file_meta(
                        assoc, query_model)
                    rsp_identifier.save_as(next(fname),
                                           write_like_original=False)

        # Release the association
        assoc.release()
    else:
        sys.exit(1)
Ejemplo n.º 17
0
        transfer_syntax = [ImplicitVRLittleEndian]
except:
    transfer_syntax = [ImplicitVRLittleEndian]

#-------------------------- CREATE AE and ASSOCIATE ---------------------------

if args.version:
    print('echoscu.py v%s' % (VERSION))
    sys.exit()

LOGGER.debug('echoscu.py v%s', VERSION)
LOGGER.debug('')

# Create local AE
# Binding to port 0, OS will pick an available port
ae = AE(ae_title=args.calling_aet)

ae.add_requested_context(VerificationSOPClass, transfer_syntax)

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

# Request association with remote AE
assoc = ae.associate(args.peer,
                     args.port,
                     ae_title=args.called_aet,
                     max_pdu=args.max_pdu)

# If we successfully Associated then send N DIMSE C-ECHOs
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('storescu.py v{__version__}')
        sys.exit()

    APP_LOGGER = setup_logging(args, 'storescu')
    APP_LOGGER.debug('storescu.py v{__version__}')
    APP_LOGGER.debug('')

    lfiles, badfiles = get_files(args.path, args.recurse)

    for bad in badfiles:
        APP_LOGGER.error("Cannot access path: {bad}")

    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

    if args.required_contexts:
        # Only propose required presentation contexts
        lfiles, contexts = get_contexts(lfiles, APP_LOGGER)
        try:
            for abstract, transfer in contexts.items():
                for tsyntax in transfer:
                    ae.add_requested_context(abstract, tsyntax)
        except ValueError:
            raise ValueError(
                "More than 128 presentation contexts required with "
                "the '--required-contexts' flag, please try again "
                "without it or with fewer files"
            )
    else:
        # Propose the default presentation contexts
        if args.request_little:
            transfer_syntax = [ExplicitVRLittleEndian]
        elif args.request_big:
            transfer_syntax = [ExplicitVRBigEndian]
        elif args.request_implicit:
            transfer_syntax = [ImplicitVRLittleEndian]
        else:
            transfer_syntax = [
                ExplicitVRLittleEndian,
                ImplicitVRLittleEndian,
                DeflatedExplicitVRLittleEndian,
                ExplicitVRBigEndian
            ]

        for cx in StoragePresentationContexts:
            ae.add_requested_context(cx.abstract_syntax, transfer_syntax)

    if not lfiles:
        APP_LOGGER.warning("No suitable DICOM files found")
        sys.exit()

    # Request association with remote
    assoc = ae.associate(
        args.addr, args.port, ae_title=args.called_aet, max_pdu=args.max_pdu
    )
    if assoc.is_established:
        ii = 1
        for fpath in lfiles:
            APP_LOGGER.info('Sending file: {fpath}')
            try:
                ds = dcmread(fpath)
                status = assoc.send_c_store(ds, ii)
                ii += 1
            except InvalidDicomError:
                APP_LOGGER.error('Bad DICOM file: {fpath}')
            except Exception as exc:
                APP_LOGGER.error("Store failed: {fpath}")
                APP_LOGGER.exception(exc)

        assoc.release()
    else:
        sys.exit(1)
Ejemplo n.º 19
0
    LOGGER.setLevel(logging.INFO)
    pynetdicom_logger = logging.getLogger('pynetdicom')
    pynetdicom_logger.setLevel(logging.INFO)

if args.debug:
    LOGGER.setLevel(logging.DEBUG)
    pynetdicom_logger = logging.getLogger('pynetdicom')
    pynetdicom_logger.setLevel(logging.DEBUG)

LOGGER.debug('$getscu.py v{0!s}'.format(VERSION))
LOGGER.debug('')


# Create application entity
# Binding to port 0 lets the OS pick an available port
ae = AE(ae_title=args.calling_aet, port=0)

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:
    role = SCP_SCU_RoleSelectionNegotiation()
    role.sop_class_uid = context.abstract_syntax
    role.scp_role = True
    role.scu_role = False
    ext_neg.append(role)
Ejemplo n.º 20
0
    ds.file_meta = meta

    # Set the transfer syntax attributes of the dataset
    ds.is_little_endian = context.transfer_syntax.is_little_endian
    ds.is_implicit_VR = context.transfer_syntax.is_implicit_VR

    # 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)]

ae = AE()

ae.add_requested_context(StudyRootQueryRetrieveInformationModelGet)
# Add the requested presentation context (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 = '8435'