Example #1
4
class AEStorageSCP(threading.Thread):
    def __init__(self):
        self.ae = AE(port=11112, scp_sop_class=StorageSOPClassList)
        threading.Thread.__init__(self)
        self.daemon = True
        self.start()
        
    def run(self):
        self.ae.start()
        
    def stop(self):
        self.ae.stop()
Example #2
1
class AEVerificationSCP(threading.Thread):
    def __init__(self):
        self.ae = AE(port=11112, scp_sop_class=[VerificationSOPClass])
        threading.Thread.__init__(self)
        self.daemon = True
        self.start()
        
    def run(self):
        self.ae.start()
        
    def stop(self):
        self.ae.stop()
Example #3
1
 def test_associate_establish_release(self):
     """ Check SCU Association with SCP """
     scp = AEVerificationSCP()
     
     ae = AE(scu_sop_class=[VerificationSOPClass])
     assoc = ae.associate('localhost', 11112)
     self.assertTrue(assoc.is_established == True)
     
     assoc.release()
     self.assertTrue(assoc.is_established == False)
     
     self.assertRaises(SystemExit, scp.stop)
Example #4
1
 def test_on_c_store_called(self):
     """ Check that SCP AE.on_c_store(dataset) was called """
     scp = AEStorageSCP()
     
     ae = AE(scu_sop_class=StorageSOPClassList)
     assoc = ae.associate('localhost', 11112)
     #with patch.object(scp.ae, 'on_c_store') as mock:
     #    assoc.send_c_store(dataset)
         
     #mock.assert_called_with()
     
     assoc.release()
     
     self.assertRaises(SystemExit, scp.stop)
Example #5
1
 def test_on_c_echo_called(self):
     """ Check that SCP AE.on_c_echo() was called """
     scp = AEVerificationSCP()
     
     ae = AE(scu_sop_class=[VerificationSOPClass])
     assoc = ae.associate('localhost', 11112)
     with patch.object(scp.ae, 'on_c_echo') as mock:
         assoc.send_c_echo()
         
     mock.assert_called_with()
     
     assoc.release()
     
     self.assertRaises(SystemExit, scp.stop)
Example #6
1
    def test_association_acse_timeout(self):
        """ Check that the Association timeouts are being set correctly """
        scp = AEVerificationSCP()
        scp.ae.acse_timeout = 0
        scp.ae.dimse_timeout = 0
        
        ae = AE(scu_sop_class=[VerificationSOPClass])
        ae.acse_timeout = 0
        ae.dimse_timeout = 0
        assoc = ae.associate('localhost', 11112)
        self.assertTrue(scp.ae.active_associations[0].acse_timeout == 0)
        self.assertTrue(scp.ae.active_associations[0].dimse_timeout == 0)
        self.assertTrue(assoc.acse_timeout == 0)
        self.assertTrue(assoc.dimse_timeout == 0)
        assoc.release()
        
        scp.ae.acse_timeout = 21
        scp.ae.dimse_timeout = 22
        ae.acse_timeout = 31
        ae.dimse_timeout = 32

        assoc = ae.associate('localhost', 11112)
        self.assertTrue(scp.ae.active_associations[0].acse_timeout == 21)
        self.assertTrue(scp.ae.active_associations[0].dimse_timeout == 22)
        self.assertTrue(assoc.acse_timeout == 31)
        self.assertTrue(assoc.dimse_timeout == 32)
        assoc.release()
        
        self.assertRaises(SystemExit, scp.stop)
Example #7
1
 def test_ae_release_assoc(self):
     """ Association releases OK """
     # Start Verification SCP
     scp = AEVerificationSCP()
     
     ae = AE(scu_sop_class=[VerificationSOPClass])
     
     # Test N associate/release cycles
     for ii in range(10):
         assoc = ae.associate('localhost', 11112)
         self.assertTrue(assoc.is_established)
         
         if assoc.is_established:
             assoc.release()
             self.assertTrue(assoc.is_established == False)
             self.assertTrue(assoc.is_released == True)
             self.assertTrue(ae.active_associations == [])
     
     # Kill Verification SCP (important!)
     self.assertRaises(SystemExit, scp.stop)
Example #8
1
 def test_associate_max_pdu(self):
     """ Check Association has correct max PDUs on either end """
     scp = AEVerificationSCP()
     scp.ae.maximum_pdu_size = 54321
     
     ae = AE(scu_sop_class=[VerificationSOPClass])
     assoc = ae.associate('localhost', 11112, max_pdu=12345)
     
     self.assertTrue(scp.ae.active_associations[0].local_max_pdu == 54321)
     self.assertTrue(scp.ae.active_associations[0].peer_max_pdu == 12345)
     self.assertTrue(assoc.local_max_pdu == 12345)
     self.assertTrue(assoc.peer_max_pdu == 54321)
     
     assoc.release()
     
     # Check 0 max pdu value
     assoc = ae.associate('localhost', 11112, max_pdu=0)
     self.assertTrue(assoc.local_max_pdu == 0)
     self.assertTrue(scp.ae.active_associations[0].peer_max_pdu == 0)
     
     assoc.release()
     self.assertRaises(SystemExit, scp.stop)
Example #9
1
 def test_req_called_aet(self):
     """ Check AE require called aet change produces good value """
     ae = AE(scu_sop_class=['1.2.840.10008.1.1'])
     ae.require_called_aet = -10
     self.assertTrue(ae.require_called_aet == '')
     ae.require_called_aet = ['a']
     self.assertTrue(ae.require_called_aet == '')
     ae.require_called_aet = '10'
     self.assertTrue(ae.require_called_aet == '10')
     ae.require_called_aet = '     TEST     '
     self.assertTrue(ae.require_called_aet == 'TEST')
     ae.require_called_aet = '            TEST'
     self.assertTrue(ae.require_called_aet == 'TEST')
     ae.require_called_aet = '                 TEST'
     self.assertTrue(ae.require_called_aet == 'TEST')
     ae.require_called_aet = 'a            TEST'
     self.assertTrue(ae.require_called_aet == 'a            TES')
Example #10
0
 def test_max_pdu_good(self):
     """ Check AE maximum pdu size change produces good value """
     ae = AE(scu_sop_class=['1.2.840.10008.1.1'])
     ae.maximum_pdu_size = -10
     self.assertTrue(ae.maximum_pdu_size == 16382)
     ae.maximum_pdu_size = ['a']
     self.assertTrue(ae.maximum_pdu_size == 16382)
     ae.maximum_pdu_size = '10'
     self.assertTrue(ae.maximum_pdu_size == 16382)
     ae.maximum_pdu_size = 0
     self.assertTrue(ae.maximum_pdu_size == 0)
     ae.maximum_pdu_size = 5000
     self.assertTrue(ae.maximum_pdu_size == 5000)
Example #11
0
 def test_ae_title_good(self):
     """ Check AE title change produces good value """
     ae = AE(scu_sop_class=['1.2.840.10008.1.1'])
     ae.ae_title = '     TEST     '
     self.assertTrue(ae.ae_title == 'TEST            ')
     ae.ae_title = '            TEST'
     self.assertTrue(ae.ae_title == 'TEST            ')
     ae.ae_title = '                 TEST'
     self.assertTrue(ae.ae_title == 'TEST            ')
     ae.ae_title = 'a            TEST'
     self.assertTrue(ae.ae_title == 'a            TES')
     ae.ae_title = 'a        TEST'
     self.assertTrue(ae.ae_title == 'a        TEST   ')
Example #12
0
 def test_network_timeout(self):
     """ Check AE network timeout change produces good value """
     ae = AE(scu_sop_class=['1.2.840.10008.1.1'])
     ae.network_timeout = None
     self.assertTrue(ae.network_timeout == 60)
     ae.network_timeout = -100
     self.assertTrue(ae.network_timeout == 60)
     ae.network_timeout = 'a'
     self.assertTrue(ae.network_timeout == 60)
     ae.network_timeout = 0
     self.assertTrue(ae.network_timeout == 0)
     ae.network_timeout = 30
     self.assertTrue(ae.network_timeout == 30)
Example #13
0
 def test_max_assoc_good(self):
     """ Check AE maximum association change produces good value """
     ae = AE(scu_sop_class=['1.2.840.10008.1.1'])
     ae.maximum_associations = -10
     self.assertTrue(ae.maximum_associations == 1)
     ae.maximum_associations = ['a']
     self.assertTrue(ae.maximum_associations == 1)
     ae.maximum_associations = '10'
     self.assertTrue(ae.maximum_associations == 1)
     ae.maximum_associations = 0
     self.assertTrue(ae.maximum_associations == 1)
     ae.maximum_associations = 5
     self.assertTrue(ae.maximum_associations == 5)
    def test_callback_bad_identifier(self):
        """Test SCP handles a bad callback identifier"""
        self.scp = DummyFindSCP()
        self.scp.statuses = [0xFF00, 0xFE00]
        self.scp.identifiers = [None, None]
        self.scp.start()

        ae = AE()
        ae.add_requested_context(
            ProductCharacteristicsQueryInformationModelFind)
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(self.query, query_model='PC')
        status, identifier = next(result)
        assert status.Status == 0xC312
        pytest.raises(StopIteration, next, result)

        assoc.release()
        self.scp.stop()
    def test_scp_handler_context(self):
        """Test handler event's context attribute"""
        attrs = {}
        def handle(event):
            attrs['context'] = event.context
            attrs['assoc'] = event.assoc
            attrs['request'] = event.request
            attrs['identifier'] = event.identifier
            yield 0xFF00, self.query

        handlers = [(evt.EVT_C_FIND, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(ProductCharacteristicsQueryInformationModelFind)
        ae.add_requested_context(ProductCharacteristicsQueryInformationModelFind)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(self.query, query_model='PC')
        status, identifier = next(result)
        assert status.Status == 0xFF00
        status, identifier = next(result)
        assert status.Status == 0x0000
        with pytest.raises(StopIteration):
            next(result)

        assoc.release()
        assert assoc.is_released

        cx = attrs['context']
        assert cx.context_id == 1
        assert cx.abstract_syntax == ProductCharacteristicsQueryInformationModelFind
        assert cx.transfer_syntax == '1.2.840.10008.1.2'

        scp.shutdown()
Example #16
0
    def test_flag_td(self, capfd):
        """Test --dimse-timeout flag."""
        events = []

        def handle_move(event):
            events.append(event)
            time.sleep(0.1)
            yield 'localhost', 11113
            yield 0
            yield 0x0000, None

        def handle_abort(event):
            events.append(event)

        handlers = [
            (evt.EVT_C_MOVE, handle_move),
            (evt.EVT_ABORTED, handle_abort),
        ]

        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.requested_contexts = StoragePresentationContexts
        ae.supported_contexts = QueryRetrievePresentationContexts
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        p = self.func(['-td', '0.05', '-d', '-k', 'PatientName='])
        p.wait()
        assert p.returncode == 0

        time.sleep(0.1)
        scp.shutdown()

        out, err = capfd.readouterr()
        assert "DIMSE timeout reached while waiting for message" in err
        assert events[0].event == evt.EVT_C_MOVE
        assert events[1].event == evt.EVT_ABORTED
Example #17
0
    def test_scp_callback_context(self):
        """Test on_c_echo context parameter."""
        self.scp = DummyVerificationSCP()
        self.scp.start()

        ae = AE()
        ae.add_requested_context(VerificationSOPClass, '1.2.840.10008.1.2.1')
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        rsp = assoc.send_c_echo()
        assert rsp.Status == 0x0000
        assoc.release()
        assert assoc.is_released

        assert self.scp.context.context_id == 1
        assert self.scp.context.abstract_syntax == '1.2.840.10008.1.1'
        assert self.scp.context.transfer_syntax == '1.2.840.10008.1.2.1'

        self.scp.stop()
    def test_bad_req_identifier(self):
        """Test SCP handles a bad request identifier"""
        def handle(event):
            try:
                ds = event.identifier
                for elem in ds.iterall():
                    pass
            except NotImplementedError:
                yield 0xC310, None
                return

            yield 0x0000, None

        handlers = [(evt.EVT_C_FIND, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(ProductCharacteristicsQueryInformationModelFind)
        ae.add_requested_context(
            ProductCharacteristicsQueryInformationModelFind,
            ExplicitVRLittleEndian
        )
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

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

        req = C_FIND()
        req.MessageID = 1
        req.AffectedSOPClassUID = ProductCharacteristicsQueryInformationModelFind
        req.Priority = 2
        req.Identifier = BytesIO(b'\x08\x00\x01\x00\x04\x00\x00\x00\x00\x08\x00\x49')
        assoc.dimse.send_msg(req, 1)
        cx_id, rsp = assoc.dimse.get_msg(True)
        assert rsp.Status == 0xC310

        assoc.release()
        assert assoc.is_released
        scp.shutdown()
    def test_callback_status_int(self):
        """Test on_c_find yielding an int status"""
        self.scp = DummyFindSCP()
        self.scp.statuses = [0xFF00]
        self.scp.identifiers = [self.query]
        self.scp.start()

        ae = AE()
        ae.add_requested_context(ProductCharacteristicsQueryInformationModelFind)
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(self.query, query_model='PC')
        status, identifier = next(result)
        assert status.Status == 0xFF00
        status, identifier = next(result)
        assert status.Status == 0x0000

        assoc.release()
        self.scp.stop()
Example #20
0
    def test_flag_td(self, capfd):
        """Test --dimse-timeout flag."""
        events = []

        def handle_echo(event):
            events.append(event)
            time.sleep(0.1)
            return 0x0000

        def handle_abort(event):
            events.append(event)

        handlers = [
            (evt.EVT_C_ECHO, handle_echo),
            (evt.EVT_ABORTED, handle_abort),
        ]

        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.add_supported_context(Verification)
        scp = ae.start_server(("localhost", 11112),
                              block=False,
                              evt_handlers=handlers)

        p = self.func(["-td", "0.05", "-d"])
        p.wait()
        assert p.returncode == 0

        time.sleep(0.1)

        scp.shutdown()

        out, err = capfd.readouterr()
        assert "DIMSE timeout reached while waiting for message" in err
        assert events[0].event == evt.EVT_C_ECHO
        assert events[1].event == evt.EVT_ABORTED
    def test_scp_callback_context(self):
        """Test on_c_store caontext parameter"""
        self.scp = DummyStorageSCP()
        self.scp.start()

        ae = AE()
        ae.add_requested_context(CTImageStorage, '1.2.840.10008.1.2.1')
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        status = assoc.send_c_store(DATASET)
        assert status.Status == 0x0000
        assoc.release()
        assert assoc.is_released

        assert self.scp.context.context_id == 1
        assert self.scp.context.abstract_syntax == CTImageStorage
        assert self.scp.context.transfer_syntax == '1.2.840.10008.1.2.1'

        self.scp.stop()
    def test_no_response(self):
        """Test on_c_find yielding success status"""
        self.scp = DummyFindSCP()
        self.scp.statuses = []
        self.scp.identifiers = []
        self.scp.start()

        ae = AE()
        ae.add_requested_context(GeneralRelevantPatientInformationQuery)
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(self.query, query_model='G')
        status, identifier = next(result)
        assert status.Status == 0x0000
        assert identifier is None
        pytest.raises(StopIteration, next, result)

        assoc.release()
        self.scp.stop()
Example #23
0
def move_study(localAE, localPort, destIP, destAE, destPort, study):
    # Prepare local information
    ae = AE(ae_title=localAE)
    ae.acse_timeout = 30

    # Add a requested presentation context
    ae.add_requested_context(StudyRootQueryRetrieveInformationModelMove)

    # Associate with Peer
    assoc = ae.associate(destIP, destPort, ae_title=destAE)

    if assoc.is_established:
        # Use the C-Move service to send identifier
        responses = assoc.send_c_move(
            study, localAE, StudyRootQueryRetrieveInformationModelMove)

        imageIndex = 1
        for (status, identifier) in responses:
            if status:
                # print('C-MOVE query status: 0x{0:04x}'.format(status.Status))
                if status.Status in (0xFF00, 0xFF01):
                    print('Imaging is being downloaded... %s' % imageIndex)
                    imageIndex += 1
                elif status.Status in (0x0000, ):
                    print('Download is finished')

                    # Save study images into correct folder
                    folderName = study.PatientID + study.StudyInstanceUID
                    os.system("mkdir .\\images\\" + folderName)
                    os.system("move .\\rcv\\* .\\images\\" + folderName)
                    time.sleep(1)
                    print('Store study into %s' % folderName)

                    # Update task status
                    with open('tasks.txt', 'w') as f:
                        f.writelines(study.PatientID)
            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 test_scp_handler_return_int(self):
        """Test handler returning an int status"""
        def handle(event):
            return 0x0000

        handlers = [(evt.EVT_C_STORE, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(HangingProtocolStorage)
        ae.add_requested_context(HangingProtocolStorage)
        scp = ae.start_server(("localhost", 11112),
                              block=False,
                              evt_handlers=handlers)

        assoc = ae.associate("localhost", 11112)
        assert assoc.is_established
        rsp = assoc.send_c_store(DATASET)
        assert rsp.Status == 0x0000
        assert "ErrorComment" not in rsp
        assoc.release()
        assert assoc.is_released

        scp.shutdown()
Example #25
0
    def test_flag_debug(self, capfd):
        """Test --debug flag."""
        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.add_requested_context(Verification)

        self.p = p = self.func(["-d"])
        time.sleep(0.5)

        assoc = ae.associate("localhost", 11112)
        assert assoc.is_established
        status = assoc.send_c_echo()
        assert status.Status == 0x0000
        assoc.release()

        p.terminate()
        p.wait()

        out, err = capfd.readouterr()
        assert "pydicom.read_dataset()" in err
        assert "Accept Parameters" in err
Example #26
0
    def test_scp_handler_return_dataset_unknown(self):
        """Test a status ds with an unknown element."""
        def handle(event):
            status = Dataset()
            status.Status = 0x0001
            status.PatientName = 'test name'
            return status

        handlers = [(evt.EVT_C_ECHO, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(VerificationSOPClass)
        ae.add_requested_context(VerificationSOPClass)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        rsp = assoc.send_c_echo()
        assert rsp.Status == 0x0001
        assoc.release()
        assert assoc.is_released

        scp.shutdown()
Example #27
0
    def test_handler_status_none(self):
        """Test SCP handles handler not yielding a status"""
        def handle(event):
            yield None, self.query

        handlers = [(evt.EVT_C_FIND, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(GeneralRelevantPatientInformationQuery)
        ae.add_requested_context(GeneralRelevantPatientInformationQuery)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(self.query,
                                   GeneralRelevantPatientInformationQuery)
        status, identifier = next(result)
        assert status.Status == 0xC002
        pytest.raises(StopIteration, next, result)
        assoc.release()
        scp.shutdown()
Example #28
0
    def test_scp_handler_return_dataset(self):
        """Test handler returning a Dataset status"""

        def handle(event):
            status = Dataset()
            status.Status = 0x0001
            return status

        handlers = [(evt.EVT_C_ECHO, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(Verification)
        ae.add_requested_context(Verification)
        scp = ae.start_server(("localhost", 11112), block=False, evt_handlers=handlers)

        assoc = ae.associate("localhost", 11112)
        assert assoc.is_established
        rsp = assoc.send_c_echo()
        assert rsp.Status == 0x0001
        assoc.release()
        assert assoc.is_released

        scp.shutdown()
Example #29
0
    def test_flag_quiet(self, capfd):
        """Test --quiet flag."""
        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.add_requested_context(VerificationSOPClass)
        ae.add_requested_context(CTImageStorage)

        self.p = p = self.func(['-q'])
        time.sleep(0.5)

        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        status = assoc.send_c_echo()
        assert status.Status == 0x0000
        assoc.release()

        p.terminate()
        p.wait()

        out, err = capfd.readouterr()
        assert out == err == ''
    def test_scp_handler_return_int(self):
        """Test handler returning an int status"""
        def handle(event):
            return 0x0000, self.ds

        handlers = [(evt.EVT_N_GET, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(DisplaySystemSOPClass)
        ae.add_requested_context(DisplaySystemSOPClass)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        status, ds = assoc.send_n_get([(0x7fe0, 0x0010)],
                                      DisplaySystemSOPClass,
                                      '1.2.840.10008.5.1.1.40.1')
        assert status.Status == 0x0000
        assert not 'ErrorComment' in status
        assoc.release()
        scp.shutdown()
    def test_no_handlers(self):
        """Test with no transport event handlers bound."""
        self.ae = ae = AE()
        ae.add_supported_context(VerificationSOPClass)
        ae.add_requested_context(VerificationSOPClass)
        scp = ae.start_server(('', 11112), block=False)
        assert scp.get_handlers(evt.EVT_DIMSE_RECV) == []
        assert scp.get_handlers(evt.EVT_DIMSE_SENT) == []
        assoc = ae.associate('localhost', 11112)

        assert assoc.is_established
        assert len(scp.active_associations) == 1
        assert scp.get_handlers(evt.EVT_DIMSE_RECV) == []
        assert scp.get_handlers(evt.EVT_DIMSE_SENT) == []
        assert assoc.get_handlers(evt.EVT_DIMSE_RECV) == []
        assert assoc.get_handlers(evt.EVT_DIMSE_SENT) == []

        child = scp.active_associations[0]
        assert child.get_handlers(evt.EVT_DIMSE_RECV) == []
        assert child.get_handlers(evt.EVT_DIMSE_SENT) == []

        assoc.release()
        scp.shutdown()
Example #32
0
    def test_flag_store_aet(self):
        """Test the --store-aet flag."""
        # Value not actually checked
        events = []
        def handle_move(event):
            events.append(event)
            yield 'localhost', 11113
            yield 1
            yield 0xFF00, self.response

        def handle_accepted(event):
            events.append(event)

        handlers = [
            (evt.EVT_ACCEPTED, handle_accepted),
            (evt.EVT_C_MOVE, handle_move),
        ]

        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.requested_contexts = StoragePresentationContexts
        ae.supported_contexts = QueryRetrievePresentationContexts
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        p = self.func(
            ['--store', '--store-aet', 'SOMESCP', '-k', 'PatientName=']
        )
        p.wait()
        assert p.returncode == 0

        scp.shutdown()

        assert 'CT.1.2.3.4' in os.listdir()
        os.remove('CT.1.2.3.4')
        assert 'CT.1.2.3.4' not in os.listdir()
Example #33
0
    def test_scp_handler_identifier(self):
        """Test handler event's identifier property"""
        attrs = {}
        def handle(event):
            attrs['context'] = event.context
            attrs['assoc'] = event.assoc
            attrs['request'] = event.request
            attrs['identifier'] = event.identifier
            yield 0xFF00, self.query

        handlers = [(evt.EVT_C_FIND, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(ProductCharacteristicsQueryInformationModelFind)
        ae.add_requested_context(ProductCharacteristicsQueryInformationModelFind)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(self.query, query_model='PC')
        status, identifier = next(result)
        assert status.Status == 0xFF00
        status, identifier = next(result)
        assert status.Status == 0x0000
        with pytest.raises(StopIteration):
            next(result)

        assoc.release()
        assert assoc.is_released

        ds = attrs['identifier']
        ds.QueryRetrieveLevel = "PATIENT"
        ds.PatientName = '*'

        scp.shutdown()
Example #34
0
    def test_flag_abort(self):
        """Test --abort flag."""
        events = []

        def handle_echo(event):
            events.append(event)
            return 0x0000

        def handle_release(event):
            events.append(event)

        def handle_abort(event):
            events.append(event)

        handlers = [
            (evt.EVT_C_ECHO, handle_echo),
            (evt.EVT_RELEASED, handle_release),
            (evt.EVT_ABORTED, handle_abort),
        ]

        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.add_supported_context(Verification)
        scp = ae.start_server(("localhost", 11112),
                              block=False,
                              evt_handlers=handlers)

        p = self.func(["--abort"])
        p.wait()
        assert p.returncode == 0

        scp.shutdown()

        assert events[0].event == evt.EVT_C_ECHO
        assert events[1].event == evt.EVT_ABORTED
Example #35
0
    def test_pr_level_image(self):
        """Test IMAGE query level."""
        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        model = PatientRootQueryRetrieveInformationModelFind
        ae.add_requested_context(model)

        self.p = p = self.func(['-d'])
        time.sleep(0.5)
        _send_datasets()
        time.sleep(1)

        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        responses = assoc.send_c_find(self.q_image, model)
        for ii in range(5):
            status, ds = next(responses)
            assert status.Status == 0xFF00
            assert 'PatientID' in ds
            assert 'StudyInstanceUID' in ds
            assert 'SeriesInstanceUID' in ds
            assert 'SOPInstanceUID' in ds
            assert ds.RetrieveAETitle == 'QRSCP'
            assert ds.QueryRetrieveLevel == 'IMAGE'
            assert 6 == len(ds)

        status, ds = next(responses)
        assert status.Status == 0x0000
        assert ds is None
        pytest.raises(StopIteration, next, responses)

        assoc.release()

        p.terminate()
        p.wait()
Example #36
0
    def test_scp_handler_context(self):
        """Test handler event's context attribute"""
        attrs = {}

        def handle(event):
            attrs['context'] = event.context
            attrs['identifier'] = event.identifier
            attrs['request'] = event.request
            attrs['assoc'] = event.assoc
            yield 0xFF00, self.query

        handlers = [(evt.EVT_C_FIND, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(GeneralRelevantPatientInformationQuery)
        ae.add_requested_context(GeneralRelevantPatientInformationQuery)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(self.query,
                                   GeneralRelevantPatientInformationQuery)
        status, identifier = next(result)
        assert status.Status == 0xFF00
        status, identifier = next(result)
        assert status.Status == 0x0000
        assoc.release()
        assert assoc.is_released

        cx = attrs['context']
        assert cx.context_id == 1
        assert cx.abstract_syntax == GeneralRelevantPatientInformationQuery
        assert cx.transfer_syntax == '1.2.840.10008.1.2'

        scp.shutdown()
Example #37
0
    def test_flag_debug(self, capfd):
        """Test --debug flag."""
        def handle_store(event):
            return 0x0000

        def handle_move(event):
            yield 'localhost', 11113
            yield 0
            yield 0x0000, None

        handlers = [
            (evt.EVT_C_MOVE, handle_move),
        ]

        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.requested_contexts = StoragePresentationContexts
        ae.supported_contexts = QueryRetrievePresentationContexts
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)
        ae.supported_contexts = StoragePresentationContexts
        store_scp = ae.start_server(
            ('', 11113), block=False,
            evt_handlers=[(evt.EVT_C_STORE, handle_store)]
        )

        p = self.func(['-d', '-k', 'PatientName='])
        p.wait()
        assert p.returncode == 0

        out, err = capfd.readouterr()
        assert "Releasing Association" in err
        assert "Accept Parameters" in err

        store_scp.shutdown()
        scp.shutdown()
Example #38
0
    def test_flag_max_pdu(self):
        """Test --max-pdu flag."""
        events = []

        def handle_find(event):
            events.append(event)
            yield 0x0000, None

        def handle_release(event):
            events.append(event)

        handlers = [
            (evt.EVT_C_FIND, handle_find),
            (evt.EVT_RELEASED, handle_release)
        ]

        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.supported_contexts = (
            QueryRetrievePresentationContexts
            + BasicWorklistManagementPresentationContexts
        )
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)


        p = start_findscu(['--max-pdu', '123456', '-k', 'PatientName='])
        p.wait()
        assert p.returncode == 0

        scp.shutdown()

        assert events[0].event == evt.EVT_C_FIND
        assert events[1].event == evt.EVT_RELEASED
        requestor = events[1].assoc.requestor
        assert 123456 == requestor.maximum_length
Example #39
0
    def test_send_assoc_ac_sop_ext(self, caplog):
        """Test ACSE.debug_send_associate_ac with SOP Class Extended."""
        with caplog.at_level(logging.DEBUG, logger='pynetdicom'):
            self.ae = ae = AE()
            ae.add_supported_context(VerificationSOPClass)
            ae.add_requested_context(VerificationSOPClass)
            ae.add_requested_context(VerificationSOPClass)
            ae.add_requested_context(VerificationSOPClass)
            ae.add_requested_context(VerificationSOPClass)
            ae.add_requested_context(VerificationSOPClass)
            scp = ae.start_server(('', 11112), block=False)
            assoc = ae.associate('localhost', 11112)

            self.add_sop_ext(self.associate_ac)
            pdu = A_ASSOCIATE_AC()
            pdu.from_primitive(self.associate_ac)
            evt.trigger(assoc, evt.EVT_PDU_SENT, {'pdu': pdu})

            messages = [
                "Accepted Extended Negotiation:",
                "SOP Class: =1.2.3.4",
                "00  01",
                "SOP Class: =1.2.840.10008.1.1",
                "00  01  02  03  00  01  02  03  00  01  02  03  00  01  02"
                "  03",
                "00  01  02  03  00  01  02  03  00  01  02  03  00  01  02"
                "  03",
                "00  01  02  03  00  01  02  03",
                "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 #40
0
    def test_event_file_meta(self):
        """Test basic functioning of event.file_meta"""
        event_out = []

        def handle(event):
            ds = event.dataset
            ds.file_meta = event.file_meta

            event_out.append(ds)

            return 0x0000

        handlers = [(evt.EVT_C_STORE, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(CTImageStorage)
        ts = ae.supported_contexts[0].transfer_syntax[0]
        ae.add_requested_context(CTImageStorage)
        scp = ae.start_server(("localhost", 11112),
                              block=False,
                              evt_handlers=handlers)

        assoc = ae.associate("localhost", 11112)
        assert assoc.is_established
        rsp = assoc.send_c_store(DATASET)
        assert rsp.Status == 0x0000
        assert not "ErrorComment" in rsp
        assoc.release()
        assert assoc.is_released

        scp.shutdown()

        ds = event_out[0]
        meta = event_out[0].file_meta
        assert meta.MediaStorageSOPClassUID == CTImageStorage
        assert meta.MediaStorageSOPInstanceUID == ds.SOPInstanceUID
        assert meta.TransferSyntaxUID == ts
Example #41
0
    def test_handler_status_dataset_multi(self):
        """Test handler yielding a Dataset status with other elements"""
        def handle(event):
            status = Dataset()
            status.Status = 0xFF00
            status.ErrorComment = 'Test'
            status.OffendingElement = 0x00010001
            yield status, self.query

        handlers = [(evt.EVT_C_FIND, handle)]

        self.ae = ae = AE()
        ae.add_supported_context(
            ProductCharacteristicsQueryInformationModelFind)
        ae.add_requested_context(
            ProductCharacteristicsQueryInformationModelFind,
            ExplicitVRLittleEndian)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        result = assoc.send_c_find(
            self.query, ProductCharacteristicsQueryInformationModelFind)
        status, identifier = next(result)
        assert status.Status == 0xFF00
        assert status.ErrorComment == 'Test'
        assert status.OffendingElement == 0x00010001
        status, identifier = next(result)
        assert status.Status == 0x0000
        with pytest.raises(StopIteration):
            next(result)

        assoc.release()
        assert assoc.is_released
        scp.shutdown()
Example #42
0
    def test_flag_xi(self):
        """Test --request-implicit flag."""
        events = []

        def handle_store(event):
            events.append(event)
            return 0x0000

        def handle_release(event):
            events.append(event)

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

        self.ae = ae = AE()
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        ae.network_timeout = 5
        ae.add_supported_context(CTImageStorage)
        scp = ae.start_server(('', 11112), block=False, evt_handlers=handlers)

        p = start_storescu([DATASET_FILE, '-xi'])
        p.wait()
        assert p.returncode == 0

        scp.shutdown()

        assert events[0].event == evt.EVT_C_STORE
        assert events[0].dataset.PatientName == 'CompressedSamples^CT1'
        assert events[1].event == evt.EVT_RELEASED
        requestor = events[1].assoc.requestor
        cxs = requestor.primitive.presentation_context_definition_list
        cxs = requestor.primitive.presentation_context_definition_list
        assert len(cxs) == 128
        cxs = {cx.abstract_syntax: cx for cx in cxs}
        assert CTImageStorage in cxs
        assert cxs[CTImageStorage].transfer_syntax == [ImplicitVRLittleEndian]
Example #43
0
    def test_scp_callback_attr(self):
        """Test on_n_get attr parameter"""
        self.scp = DummyGetSCP()
        self.scp.start()

        ae = AE()
        ae.add_requested_context(DisplaySystemSOPClass, '1.2.840.10008.1.2.1')
        ae.acse_timeout = 5
        ae.dimse_timeout = 5
        assoc = ae.associate('localhost', 11112)
        assert assoc.is_established
        status, ds = assoc.send_n_get([(0x7fe0, 0x0010)],
                                      DisplaySystemSOPClass,
                                      '1.2.840.10008.5.1.1.40.1')
        assert status.Status == 0x0000
        assert 'PatientName' in ds
        assoc.release()
        assert assoc.is_released

        assert self.scp.attr == [(0x7fe0, 0x0010)]

        self.scp.stop()
Example #44
0
        scu_sop_classes = [VerificationSOPClass]
except:
    scu_sop_classes = [VerificationSOPClass]

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

logger.debug("$echoscu.py v%s %s $" % ("0.5.1", "2016-04-12"))
logger.debug("")


# Create local AE
# Binding to port 0, OS will pick an available port
ae = AE(
    ae_title=args.calling_aet,
    port=0,
    scu_sop_class=[VerificationSOPClass],
    scp_sop_class=[],
    transfer_syntax=transfer_syntaxes,
)

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

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

# If we successfully Associated then send N DIMSE C-ECHOs
Example #45
0
    dcm_files = [os.path.join(basedir, x) for x in dcm_files]
    for dcm in dcm_files:
        data = read_file(dcm, force=True)

        d = Dataset()
        d.QueryRetrieveLevel = dataset.QueryRetrieveLevel
        d.RetrieveAETitle = args.aetitle
        d.PatientName = data.PatientName
        yield d


# Create application entity
ae = AE(
    ae_title=args.aetitle,
    port=args.port,
    scu_sop_class=[],
    scp_sop_class=QueryRetrieveSOPClassList,
    transfer_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()
Example #46
0
 def __init__(self):
     self.ae = AE(port=11112, scp_sop_class=StorageSOPClassList)
     threading.Thread.__init__(self)
     self.daemon = True
     self.start()
Example #47
0
 def __init__(self):
     self.ae = AE(port=11112, scp_sop_class=[VerificationSOPClass])
     threading.Thread.__init__(self)
     self.daemon = True
     self.start()
Example #48
0
transfer_syntax = [ExplicitVRLittleEndian,
                   ImplicitVRLittleEndian,
                   DeflatedExplicitVRLittleEndian,
                   ExplicitVRBigEndian]
                   
if args.request_little:
    transfer_syntax = [ExplicitVRLittleEndian]
elif args.request_big:
    transfer_syntax = [ExplicitVRBigEndian]
elif args.request_implicit:
    transfer_syntax = [ImplicitVRLittleEndian]

# Bind to port 0, OS will pick an available port
ae = AE(ae_title=args.calling_aet,
        port=0,
        scu_sop_class=StorageSOPClassList,
        scp_sop_class=[],
        transfer_syntax=transfer_syntax)

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

if assoc.is_established:
    logger.info('Sending file: %s' %args.dcmfile_in)
    
    status = assoc.send_c_store(dataset)
    
    assoc.release()

# Quit
ae.quit()
Example #49
0
    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('$movescu.py v%s %s $' %('0.1.0', '2016-03-15'))
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, 
        scu_sop_class=QueryRetrieveSOPClassList, 
        scp_sop_class=StorageSOPClassList, 
        transfer_syntax=[ExplicitVRLittleEndian])

# Set the extended negotiation SCP/SCU role selection to allow us to receive
#   C-STORE requests for the supported SOP classes
ext_neg = []
for context in ae.presentation_contexts_scu:
    tmp = SCP_SCU_RoleSelectionNegotiation()
    tmp.sop_class_uid = context.AbstractSyntax
    tmp.scu_role = False
    tmp.scp_role = True
    
    ext_neg.append(tmp)

# Request association with remote