示例#1
0
    def test_decode(self):
        """ Check decoding an assoc_rq produces the correct user information """
        pdu = A_ASSOCIATE_AC()
        pdu.decode(a_associate_ac)

        user_info = pdu.variable_items[2]

        assert user_info.item_type == 0x50
        assert user_info.item_length == 58
        assert len(user_info) == 62
        assert isinstance(user_info.user_data, list)

        # Test user items
        for item in user_info.user_data:
            # Maximum PDU Length (required)
            if isinstance(item, MaximumLengthSubItem):
                assert item.maximum_length_received == 16384
                assert user_info.maximum_length == 16384

            # Implementation Class UID (required)
            elif isinstance(item, ImplementationClassUIDSubItem):
                assert item.item_type == 0x52
                assert item.item_length == 27
                assert item.implementation_class_uid == UID(
                    '1.2.276.0.7230010.3.0.3.6.0')
                assert isinstance(item.item_type, int)
                assert isinstance(item.item_length, int)
                assert isinstance(item.implementation_class_uid, UID)

            # Implementation Version Name (optional)
            elif isinstance(item, ImplementationVersionNameSubItem):
                assert item.item_type == 0x55
                assert item.item_length == 15
                assert item.implementation_version_name == b'OFFIS_DCMTK_360'
                assert isinstance(item.item_type, int)
                assert isinstance(item.item_length, int)
                assert isinstance(item.implementation_version_name, bytes)
示例#2
0
    def test_decode(self):
        """Check decoding an assoc_rq produces the correct user information."""
        pdu = A_ASSOCIATE_RQ()
        pdu.decode(a_associate_rq)

        user_info = pdu.variable_items[2]

        assert user_info.item_type == 0x50
        assert user_info.item_length == 62
        assert len(user_info) == 66
        assert isinstance(user_info.user_data, list)

        # Test user items
        for item in user_info.user_data:
            # Maximum PDU Length (required)
            if isinstance(item, MaximumLengthSubItem):
                assert item.maximum_length_received == 16382
                assert user_info.maximum_length == 16382

            # Implementation Class UID (required)
            elif isinstance(item, ImplementationClassUIDSubItem):
                assert item.item_type == 0x52
                assert item.item_length == 32
                assert item.implementation_class_uid == UID(
                    '1.2.826.0.1.3680043.9.3811.0.9.0')
                assert isinstance(item.item_type, int)
                assert isinstance(item.item_length, int)
                assert isinstance(item.implementation_class_uid, UID)

            # Implementation Version Name (optional)
            elif isinstance(item, ImplementationVersionNameSubItem):
                assert item.item_type == 0x55
                assert item.item_length == 14
                assert item.implementation_version_name == b'PYNETDICOM_090'
                assert isinstance(item.item_type, int)
                assert isinstance(item.item_length, int)
                assert isinstance(item.implementation_version_name, bytes)
示例#3
0
    def test_transfer_syntax(self):
        """Test transfer syntax setter"""
        pc = PresentationContext(1)
        pc.TransferSyntax = ['1.2.840.10008.1.2']
        self.assertEqual(pc.TransferSyntax[0], UID('1.2.840.10008.1.2'))
        self.assertTrue(isinstance(pc.TransferSyntax[0], UID))
        pc.TransferSyntax = [b'1.2.840.10008.1.2.1']
        self.assertEqual(pc.TransferSyntax[0], UID('1.2.840.10008.1.2.1'))
        self.assertTrue(isinstance(pc.TransferSyntax[0], UID))
        pc.TransferSyntax = [UID('1.2.840.10008.1.2.2')]
        self.assertEqual(pc.TransferSyntax[0], UID('1.2.840.10008.1.2.2'))
        self.assertTrue(isinstance(pc.TransferSyntax[0], UID))

        with self.assertRaises(TypeError):
            pc.TransferSyntax = UID('1.4.1')

        pc.TransferSyntax = ['1.4.1.', '1.2.840.10008.1.2']
        self.assertEqual(pc.TransferSyntax[0], UID('1.2.840.10008.1.2'))
示例#4
0
    def test_transfer_syntax_good_uid(self):
        """ Check AE initialisation produces valid transfer syntaxes """
        ae = AE(scu_sop_class=['1.2.840.10008.1.1'],
                transfer_syntax=['1.2.840.10008.1.2'])
        self.assertTrue(ae.transfer_syntaxes == [UID('1.2.840.10008.1.2')])

        ae = AE(scu_sop_class=['1.2.840.10008.1.1'],
                transfer_syntax=['1.2.840.10008.1.2', '1.2.840.10008.1.1'])
        self.assertTrue(ae.transfer_syntaxes == [UID('1.2.840.10008.1.2')])

        ae = AE(scu_sop_class=['1.2.840.10008.1.1'],
                transfer_syntax=['1.2.840.10008.1.2', '1.2.840.10008.1.2.2'])
        self.assertTrue(ae.transfer_syntaxes == [UID('1.2.840.10008.1.2'),
                                                 UID('1.2.840.10008.1.2.2')])

        ae = AE(scu_sop_class=['1.2.840.10008.1.1'],
                transfer_syntax=[UID('1.2.840.10008.1.2')])
        self.assertTrue(ae.transfer_syntaxes == [UID('1.2.840.10008.1.2')])

        ae = AE(scu_sop_class=['1.2.840.10008.1.1'],
                transfer_syntax=[ImplicitVRLittleEndian])
        self.assertTrue(ae.transfer_syntaxes == [UID('1.2.840.10008.1.2')])
示例#5
0
    def _convert(self, val: Any) -> Any:
        """Convert `val` to an appropriate type for the element's VR."""
        # If the value is bytes and has a VR that can only be encoded
        # using the default character repertoire, convert it to a string
        if self.VR in DEFAULT_CHARSET_VR and isinstance(val, bytes):
            val = val.decode()

        if self.VR == VR_.IS:
            return pydicom.valuerep.IS(val, self.validation_mode)

        if self.VR == VR_.DA and config.datetime_conversion:
            return pydicom.valuerep.DA(val,
                                       validation_mode=self.validation_mode)

        if self.VR == VR_.DS:
            return pydicom.valuerep.DS(val, False, self.validation_mode)

        if self.VR == VR_.DT and config.datetime_conversion:
            return pydicom.valuerep.DT(val,
                                       validation_mode=self.validation_mode)

        if self.VR == VR_.TM and config.datetime_conversion:
            return pydicom.valuerep.TM(val,
                                       validation_mode=self.validation_mode)

        if self.VR == VR_.UI:
            return UID(val, self.validation_mode) if val is not None else None

        if self.VR == VR_.PN:
            return PersonName(val, validation_mode=self.validation_mode)

        if self.VR == VR_.AT and (val == 0 or val):
            return val if isinstance(val, BaseTag) else Tag(val)

        self.validate(val)
        return val
示例#6
0
    def test_transfer_syntax(self):
        """Test transfer syntax setter"""
        pc = PresentationContext(1)
        pc.TransferSyntax = ['1.2.840.10008.1.2']

        assert pc.TransferSyntax[0] == UID('1.2.840.10008.1.2')
        assert isinstance(pc.TransferSyntax[0], UID)
        pc.TransferSyntax = [b'1.2.840.10008.1.2.1']
        assert pc.TransferSyntax[0] == UID('1.2.840.10008.1.2.1')
        assert isinstance(pc.TransferSyntax[0], UID)
        pc.TransferSyntax = [UID('1.2.840.10008.1.2.2')]
        assert pc.TransferSyntax[0] == UID('1.2.840.10008.1.2.2')
        assert isinstance(pc.TransferSyntax[0], UID)

        with pytest.raises(TypeError):
            pc.TransferSyntax = UID('1.4.1')

        pc.TransferSyntax = ['1.4.1.', '1.2.840.10008.1.2']
        assert pc.TransferSyntax[0] == UID('1.2.840.10008.1.2')
示例#7
0
 def test_wrap_encode_uid(self):
     """Test PDU._wrap_encode_uid()."""
     pdu = PDU()
     uid = UID('1.2.840.10008.1.1')
     out = pdu._wrap_encode_uid(uid)
     assert out == b'1.2.840.10008.1.1'
示例#8
0
 def testCompareNone(self):
     """UID: comparing against None give False..."""
     # From issue 96
     uid = UID('1.2.3')
     self.assertNotEqual(uid, None, "Comparison to a number returned True")
示例#9
0
logging.basicConfig(filename='pynetdicom.log',
                    filemode='w',
                    format='%(name)s - %(levelname)s - %(message)s')
LOGGER = logging.getLogger('pynetdicom')
LOGGER.setLevel(logging.DEBUG)

#AEs & IP
scu_ae = os.environ.get('AE_TITLE')
dest_ae = os.environ.get('DEST_AE')
dest_ip = os.environ.get('DEST_IP')
print(scu_ae, dest_ae, dest_ip)

ae = AE(ae_title=scu_ae)
# this uid is for secondary image capture
uid = UID('1.2.840.10008.5.1.4.1.1.7')
ae.add_requested_context(uid)

ds = dcmread('tester2.dcm')

# work in progress, still not working with PACS
assoc = ae.associate(dest_ip, 5000, ae_title=dest_ae)

if assoc.is_established:
    print('Associated')
    status = assoc.send_c_store(ds)

    if status:
        print('C-STORE request status: 0x{0:04x}'.format(status.Status))
    else:
        print('Connection timed out, was aborted or received invalid resposne')
示例#10
0
 def test_is_private(self):
     """Test the is_private property"""
     uid = UID('1.2.840.10008.1.2')
     private_uid = UID('1.2.840.10009.1.2')
     self.assertTrue(private_uid.is_private)
     self.assertFalse(uid.is_private)
示例#11
0
 def testCompareNotEqualByName(self):
     """UID: comparing not equal by name..."""
     # from Issue 121
     ct_image_storage = UID('1.2.840.10008.5.1.4.1.1.2')
     msg = "UID not equal comparison by name was not correct"
     self.assertFalse(ct_image_storage != 'CT Image Storage', msg)
示例#12
0
    def test_sop_classes_good_uid(self):
        """ Check AE initialisation produces valid supported SOP classes """
        # scu_sop_class
        ae = AE(scu_sop_class=['1.2.840.10008.1.1', '1.2.840.10008.1.1.1'])
        self.assertTrue(ae.scu_supported_sop == [UID('1.2.840.10008.1.1'),
                                                 UID('1.2.840.10008.1.1.1')])
        ae = AE(scu_sop_class=[UID('1.2.840.10008.1.1')])
        self.assertTrue(ae.scu_supported_sop == [UID('1.2.840.10008.1.1')])

        ae = AE(scu_sop_class=[VerificationSOPClass])
        self.assertTrue(ae.scu_supported_sop == [UID('1.2.840.10008.1.1')])

        ae = AE(scu_sop_class=[1, VerificationSOPClass, 3])
        self.assertTrue(ae.scu_supported_sop == [UID('1.2.840.10008.1.1')])

        # scp_sop_class
        ae = AE(scp_sop_class=['1.2.840.10008.1.1', '1.2.840.10008.1.1.1'])
        self.assertTrue(ae.scp_supported_sop == [UID('1.2.840.10008.1.1'),
                                                 UID('1.2.840.10008.1.1.1')])
        ae = AE(scp_sop_class=[UID('1.2.840.10008.1.1')])
        self.assertTrue(ae.scp_supported_sop == [UID('1.2.840.10008.1.1')])

        ae = AE(scp_sop_class=[VerificationSOPClass])
        self.assertTrue(ae.scp_supported_sop == [UID('1.2.840.10008.1.1')])

        ae = AE(scp_sop_class=[1, VerificationSOPClass, 3])
        self.assertTrue(ae.scp_supported_sop == [UID('1.2.840.10008.1.1')])
示例#13
0
 def setup(self):
     self.enc = Encoder(UID('1.2.3'))
示例#14
0
 def test_string(self):
     """Check the string output."""
     primitive = ImplementationClassUIDNotification()
     primitive.implementation_class_uid = UID(
         '1.2.826.0.1.3680043.9.3811.0.9.0')
     assert '1.2.826.0.1.3680043.9.3811.0.9.0' in primitive.__str__()
示例#15
0
    def test_assignment_and_exceptions(self):
        """ Check incorrect types/values for properties raise exceptions """
        primitive = SOPClassCommonExtendedNegotiation()

        ## Check assignment
        # SOP Class UID
        reference_uid = UID('1.2.840.10008.5.1.4.1.1.2')

        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        assert primitive.sop_class_uid == reference_uid
        primitive.sop_class_uid = 'abc'
        assert primitive.sop_class_uid == 'abc'
        primitive.sop_class_uid = '1.2.840.10008.5.1.4.1.1.2'
        assert primitive.sop_class_uid == reference_uid
        primitive.sop_class_uid = UID('1.2.840.10008.5.1.4.1.1.2')
        assert primitive.sop_class_uid == reference_uid

        # Service Class UID
        primitive.service_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        assert primitive.service_class_uid == reference_uid
        primitive.service_class_uid = 'abc'
        assert primitive.service_class_uid == 'abc'
        primitive.service_class_uid = '1.2.840.10008.5.1.4.1.1.2'
        assert primitive.service_class_uid == reference_uid
        primitive.service_class_uid = UID('1.2.840.10008.5.1.4.1.1.2')
        assert primitive.service_class_uid == reference_uid

        # Related General SOP Class Identification
        ref_list = [
            UID('1.2.840.10008.5.1.4.1.1.2'),
            UID('1.2.840.10008.5.1.4.1.1.3'),
            UID('1.2.840.10008.5.1.4.1.1.4')
        ]

        uid_list = []
        uid_list.append(b'1.2.840.10008.5.1.4.1.1.2')
        uid_list.append('1.2.840.10008.5.1.4.1.1.3')
        uid_list.append(UID('1.2.840.10008.5.1.4.1.1.4'))
        primitive.related_general_sop_class_identification = uid_list
        assert primitive.related_general_sop_class_identification == ref_list
        primitive.related_general_sop_class_identification = ['abc']
        assert primitive.related_general_sop_class_identification == ['abc']

        with pytest.raises(TypeError):
            primitive.related_general_sop_class_identification = 'test'

        ## Check exceptions
        # SOP Class UID
        with pytest.raises(TypeError):
            primitive.sop_class_uid = 10

        with pytest.raises(TypeError):
            primitive.sop_class_uid = 45.2

        # Service Class UID
        with pytest.raises(TypeError):
            primitive.service_class_uid = 10

        with pytest.raises(TypeError):
            primitive.service_class_uid = 45.2

        # Related General SOP Class Identification
        with pytest.raises(TypeError):
            primitive.related_general_sop_class_identification = [10]

        with pytest.raises(TypeError):
            primitive.related_general_sop_class_identification = [45.2]

        # No value set
        primitive = SOPClassCommonExtendedNegotiation()
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive = SOPClassCommonExtendedNegotiation()
        primitive.service_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        with pytest.raises(ValueError):
            item = primitive.from_primitive()
示例#16
0
Set module shortcuts and globals
"""
from pydicom.uid import UID

version = ['0', '9', '1']
__version__ = '.'.join(version)

# Encoded as SH, 16 bytes maximum
# TODO: UPPER_CASE, change to PYNETDICOM_IMPLEMENTATION_VERSION
pynetdicom_version = 'PYNETDICOM3_' + ''.join(version)
assert 1 <= len(pynetdicom_version) <= 16

# UID prefix provided by https://www.medicalconnections.co.uk/Free_UID
# Encoded as UI, 64 bytes maximum
# TODO: UPPER_CASE, change to PYNETDICOM_UID_PREFIX
pynetdicom_uid_prefix = '1.2.826.0.1.3680043.9.3811.'
# TODO: UPPER_CASE, change to PYNETDICOM_IMPLEMENTATION_UID
pynetdicom_implementation_uid = UID(pynetdicom_uid_prefix + '.'.join(version))
assert pynetdicom_implementation_uid.is_valid

import logging

from pynetdicom3.applicationentity import ApplicationEntity as AE
from pynetdicom3.association import Association
from pynetdicom3.acse import ACSEServiceProvider as ACSE
from pynetdicom3.dimse import DIMSEServiceProvider as DIMSE
from pynetdicom3.dul import DULServiceProvider as DUL
from pynetdicom3.sop_class import STORAGE_CLASS_LIST as StorageSOPClassList
from pynetdicom3.sop_class import QR_CLASS_LIST as QueryRetrieveSOPClassList
from pynetdicom3.sop_class import VerificationSOPClass
示例#17
0
文件: util.py 项目: sjoerdk/pydicom
def apply_color_lut(arr, ds=None, palette=None):
    """Apply a color palette lookup table to `arr`.

    .. versionadded:: 1.4

    If (0028,1201-1203) *Palette Color Lookup Table Data* are missing
    then (0028,1221-1223) *Segmented Palette Color Lookup Table Data* must be
    present and vice versa. The presence of (0028,1204) *Alpha Palette Color
    Lookup Table Data* or (0028,1224) *Alpha Segmented Palette Color Lookup
    Table Data* is optional.

    Use of this function with the :dcm:`Enhanced Palette Color Lookup Table
    Module<part03/sect_C.7.6.23.html>` or :dcm:`Supplemental Palette Color LUT
    Module<part03/sect_C.7.6.19.html>` is not currently supported.

    Parameters
    ----------
    arr : numpy.ndarray
        The pixel data to apply the color palette to.
    ds : dataset.Dataset, optional
        Required if `palette` is not supplied. A
        :class:`~pydicom.dataset.Dataset` containing a suitable
        :dcm:`Image Pixel<part03/sect_C.7.6.3.html>` or
        :dcm:`Palette Color Lookup Table<part03/sect_C.7.9.html>` Module.
    palette : str or uid.UID, optional
        Required if `ds` is not supplied. The name of one of the
        :dcm:`well-known<part06/chapter_B.html>` color palettes defined by the
        DICOM Standard. One of: ``'HOT_IRON'``, ``'PET'``,
        ``'HOT_METAL_BLUE'``, ``'PET_20_STEP'``, ``'SPRING'``, ``'SUMMER'``,
        ``'FALL'``, ``'WINTER'`` or the corresponding well-known (0008,0018)
        *SOP Instance UID*.

    Returns
    -------
    numpy.ndarray
        The RGB or RGBA pixel data as an array of ``np.uint8`` or ``np.uint16``
        values, depending on the 3rd value of (0028,1201) *Red Palette Color
        Lookup Table Descriptor*.

    References
    ----------

    * :dcm:`Image Pixel Module<part03/sect_C.7.6.3.html>`
    * :dcm:`Supplemental Palette Color LUT Module<part03/sect_C.7.6.19.html>`
    * :dcm:`Enhanced Palette Color LUT Module<part03/sect_C.7.6.23.html>`
    * :dcm:`Palette Colour LUT Module<part03/sect_C.7.9.html>`
    * :dcm:`Supplemental Palette Color LUTs
      <part03/sect_C.8.16.2.html#sect_C.8.16.2.1.1.1>`
    """
    # Note: input value (IV) is the stored pixel value in `arr`
    # LUTs[IV] -> [R, G, B] values at the IV pixel location in `arr`
    if not ds and not palette:
        raise ValueError("Either 'ds' or 'palette' is required")

    if palette:
        # Well-known palettes are all 8-bits per entry
        datasets = {
            '1.2.840.10008.1.5.1': 'hotiron.dcm',
            '1.2.840.10008.1.5.2': 'pet.dcm',
            '1.2.840.10008.1.5.3': 'hotmetalblue.dcm',
            '1.2.840.10008.1.5.4': 'pet20step.dcm',
            '1.2.840.10008.1.5.5': 'spring.dcm',
            '1.2.840.10008.1.5.6': 'summer.dcm',
            '1.2.840.10008.1.5.7': 'fall.dcm',
            '1.2.840.10008.1.5.8': 'winter.dcm',
        }
        if not UID(palette).is_valid:
            try:
                uids = {
                    'HOT_IRON': '1.2.840.10008.1.5.1',
                    'PET': '1.2.840.10008.1.5.2',
                    'HOT_METAL_BLUE': '1.2.840.10008.1.5.3',
                    'PET_20_STEP': '1.2.840.10008.1.5.4',
                    'SPRING': '1.2.840.10008.1.5.5',
                    'SUMMER': '1.2.840.10008.1.5.6',
                    'FALL': '1.2.840.10008.1.5.8',
                    'WINTER': '1.2.840.10008.1.5.7',
                }
                palette = uids[palette]
            except KeyError:
                raise ValueError("Unknown palette '{}'".format(palette))

        try:
            from pydicom import dcmread
            fname = datasets[palette]
            ds = dcmread(get_palette_files(fname)[0])
        except KeyError:
            raise ValueError("Unknown palette '{}'".format(palette))

    # C.8.16.2.1.1.1: Supplemental Palette Color LUT
    # TODO: Requires greyscale visualisation pipeline
    if getattr(ds, 'PixelPresentation', None) in ['MIXED', 'COLOR']:
        raise ValueError(
            "Use of this function with the Supplemental Palette Color Lookup "
            "Table Module is not currently supported"
        )

    # All channels are supposed to be identical
    lut_desc = ds.RedPaletteColorLookupTableDescriptor
    # A value of 0 = 2^16 entries
    nr_entries = lut_desc[0] or 2**16

    # May be negative if Pixel Representation is 1
    first_map = lut_desc[1]
    # Actual bit depth may be larger (8 bit entries in 16 bits allocated)
    nominal_depth = lut_desc[2]
    dtype = np.dtype('uint{:.0f}'.format(nominal_depth))

    luts = []
    if 'RedPaletteColorLookupTableData' in ds:
        # LUT Data is described by PS3.3, C.7.6.3.1.6
        r_lut = ds.RedPaletteColorLookupTableData
        g_lut = ds.GreenPaletteColorLookupTableData
        b_lut = ds.BluePaletteColorLookupTableData
        a_lut = getattr(ds, 'AlphaPaletteColorLookupTableData', None)

        actual_depth = len(r_lut) / nr_entries * 8
        dtype = np.dtype('uint{:.0f}'.format(actual_depth))

        for lut in [ii for ii in [r_lut, g_lut, b_lut, a_lut] if ii]:
            luts.append(np.frombuffer(lut, dtype=dtype))
    elif 'SegmentedRedPaletteColorLookupTableData' in ds:
        # Segmented LUT Data is described by PS3.3, C.7.9.2
        r_lut = ds.SegmentedRedPaletteColorLookupTableData
        g_lut = ds.SegmentedGreenPaletteColorLookupTableData
        b_lut = ds.SegmentedBluePaletteColorLookupTableData
        a_lut = getattr(ds, 'SegmentedAlphaPaletteColorLookupTableData', None)

        endianness = '<' if ds.is_little_endian else '>'
        byte_depth = nominal_depth // 8
        fmt = 'B' if byte_depth == 1 else 'H'
        actual_depth = nominal_depth

        for seg in [ii for ii in [r_lut, g_lut, b_lut, a_lut] if ii]:
            len_seg = len(seg) // byte_depth
            s_fmt = endianness + str(len_seg) + fmt
            lut = _expand_segmented_lut(unpack(s_fmt, seg), s_fmt)
            luts.append(np.asarray(lut, dtype=dtype))
    else:
        raise ValueError("No suitable Palette Color Lookup Table Module found")

    if actual_depth not in [8, 16]:
        raise ValueError(
            "The bit depth of the LUT data '{:.1f}' is invalid (only 8 or 16 "
            "bits per entry allowed)".format(actual_depth)
        )

    lut_lengths = [len(ii) for ii in luts]
    if not all(ii == lut_lengths[0] for ii in lut_lengths[1:]):
        raise ValueError("LUT data must be the same length")

    # IVs < `first_map` get set to first LUT entry (i.e. index 0)
    clipped_iv = np.zeros(arr.shape, dtype=dtype)
    # IVs >= `first_map` are mapped by the Palette Color LUTs
    # `first_map` may be negative, positive or 0
    mapped_pixels = arr >= first_map
    clipped_iv[mapped_pixels] = arr[mapped_pixels] - first_map
    # IVs > number of entries get set to last entry
    np.clip(clipped_iv, 0, nr_entries - 1, out=clipped_iv)

    # Output array may be RGB or RGBA
    out = np.empty(list(arr.shape) + [len(luts)], dtype=dtype)
    for ii, lut in enumerate(luts):
        out[..., ii] = lut[clipped_iv]

    return out
示例#18
0
    # Get a list of all the class members of the current module
    members = inspect.getmembers(sys.modules[__name__],
                                 lambda mbr: isinstance(mbr, str))

    for obj in members:
        if hasattr(obj[1], "service_class") and obj[1] == uid:
            return cast(SOPClass, obj[1])

    sop_class = SOPClass(uid)
    sop_class._service_class = ServiceClass

    return sop_class


# Well-known SOP Instance UIDs for the supported Service Classes
DisplaySystemInstance = UID("1.2.840.10008.5.1.1.40.1")
"""``1.2.840.10008.5.1.1.40.1``

.. versionadded:: 1.5
"""
PrinterConfigurationRetrievalInstance = UID("1.2.840.10008.5.1.1.17.376")
"""``1.2.840.10008.5.1.1.17.376``

.. versionadded:: 1.5
"""
PrinterInstance = UID("1.2.840.10008.5.1.1.17")
"""``1.2.840.10008.5.1.1.17``

.. versionadded:: 1.5
"""
ProceduralEventLoggingInstance = UID("1.2.840.10008.1.40.1")
示例#19
0
    def test_presentation_context_abstract(self):
        """Check the presentation context generation abstract syntax"""
        ## SCU SOP Classes
        # str -> UID
        ae = AE(scu_sop_class=['1.1'], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scu[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.1'))
        self.assertTrue(isinstance(ab_syn, UID))

        # UID no change
        ae = AE(scu_sop_class=[UID('1.2')], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scu[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.2'))
        self.assertTrue(isinstance(ab_syn, UID))

        # sop_class -> UID
        ae = AE(scu_sop_class=[VerificationSOPClass], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scu[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.2.840.10008.1.1'))
        self.assertTrue(isinstance(ab_syn, UID))

        # bytes -> UID
        ae = AE(scu_sop_class=[b'1.3'], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scu[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.3'))
        self.assertTrue(isinstance(ab_syn, UID))

        # If not str, bytes, UID, serviceclass raise
        with self.assertRaises(TypeError):
            ae = AE(scu_sop_class=[12345], transfer_syntax=['1.2.840.10008.1.2'])

        # If not valid UID raise
        with self.assertRaises(TypeError):
            ae = AE(scu_sop_class=['1.3.'], transfer_syntax=['1.2.840.10008.1.2'])

        ## SCP SOP Classes
        # str -> UID
        ae = AE(scp_sop_class=['1.1'], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scp[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.1'))
        self.assertTrue(isinstance(ab_syn, UID))

        # UID no change
        ae = AE(scp_sop_class=[UID('1.2')], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scp[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.2'))
        self.assertTrue(isinstance(ab_syn, UID))

        # sop_class -> UID
        ae = AE(scp_sop_class=[VerificationSOPClass], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scp[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.2.840.10008.1.1'))
        self.assertTrue(isinstance(ab_syn, UID))

        # bytes -> UID
        ae = AE(scp_sop_class=[b'1.3'], transfer_syntax=['1.2.840.10008.1.2'])
        ab_syn = ae.presentation_contexts_scp[0].AbstractSyntax
        self.assertEqual(ab_syn, UID('1.3'))
        self.assertTrue(isinstance(ab_syn, UID))

        # If not str, bytes, UID, serviceclass raise
        with self.assertRaises(TypeError):
            ae = AE(scp_sop_class=[12345], transfer_syntax=['1.2.840.10008.1.2'])

        # If not valid UID raise
        with self.assertRaises(TypeError):
            ae = AE(scp_sop_class=['1.3.'], transfer_syntax=['1.2.840.10008.1.2'])
示例#20
0
 def test_inequality(self):
     """Test that UID.__ne__ works with private UIDs."""
     assert not self.uid != UID('9.9.999.90009.1.2')
     assert not self.uid != '9.9.999.90009.1.2'
     assert self.uid != UID('9.9.999.90009.1.3')
     assert self.uid != '9.9.999.90009.1.3'
示例#21
0
 def test_raises(self):
     """Test raises exception if not a str type"""
     with pytest.raises(TypeError):
         UID(1234)
示例#22
0
 def setup_class(self):
     """Set default UID"""
     self.uid = UID('9.9.999.90009.1.2')
示例#23
0
def build_context(abstract_syntax, transfer_syntax=None):
    """Return a PresentationContext built from the `abstract_syntax`.

    Parameters
    ----------
    abstract_syntax : str or UID or sop_class.SOPClass
        The UID or SOPClass instance to use as the abstract syntax.
    transfer_syntax : str/UID or list of str/UID
        The transfer syntax UID(s) to use (default: [Implicit VR Little Endian,
        Explicit VR Little Endian, Implicit VR Big Endian])

    Examples
    --------

    Specifying a presentation context with the default transfer syntaxes

    >>> from pynetdicom import build_context
    >>> context = build_context('1.2.840.10008.1.1')
    >>> print(context)
    Abstract Syntax: Verification SOP Class
    Transfer Syntax(es):
        =Implicit VR Little Endian
        =Explicit VR Little Endian
        =Explicit VR Big Endian

    Specifying the abstract syntax using a pynetdicom SOPClass instance and
    a single transfer syntax

    >>> from pynetdicom import build_context
    >>> from pynetdicom.sop_class import VerificationSOPClass
    >>> context = build_context(VerificationSOPClass, '1.2.840.10008.1.2')
    >>> print(context)
    Abstract Syntax: Verification SOP Class
    Transfer Syntax(es):
        =Implicit VR Little Endian

    Specifying multiple transfer syntaxes

    >>> from pydicom.uid import UID
    >>> from pynetdicom import build_context
    >>> context = build_context(UID('1.2.840.10008.1.1'),
                                ['1.2.840.10008.1.2',
    ...                          '1.2.840.10008.1.2.4.50'])
    >>> print(context)
    Abstract Syntax: Verification SOP Class
    Transfer Syntax(es):
        =Implicit VR Little Endian
        =JPEG Baseline (Process 1)


    Returns
    -------
    presentation.PresentationContext
    """
    if transfer_syntax is None:
        transfer_syntax = DEFAULT_TRANSFER_SYNTAXES

    abstract_syntax = UID(abstract_syntax)

    # Allow single transfer syntax values for convenience
    if isinstance(transfer_syntax, str):
        transfer_syntax = [transfer_syntax]

    context = PresentationContext()
    context.abstract_syntax = abstract_syntax
    context.transfer_syntax = transfer_syntax

    return context
示例#24
0
 def setup_class(self):
     """Set default UID"""
     self.uid = UID('1.2.840.10008.1.2')
示例#25
0
from pydicom.uid import UID

from ._version import __version__, __version_info__

# UID prefix provided by https://www.medicalconnections.co.uk/Free_UID
# Encoded as UI, 64 bytes maximum
PYNETDICOM_UID_PREFIX = '1.2.826.0.1.3680043.9.3811.'

# Encoded as SH, 16 bytes maximum
PYNETDICOM_IMPLEMENTATION_VERSION = (
    'PYNETDICOM_' + ''.join([str(ii) for ii in __version_info__['release']]))
assert 1 <= len(PYNETDICOM_IMPLEMENTATION_VERSION) <= 16

PYNETDICOM_IMPLEMENTATION_UID = UID(
    PYNETDICOM_UID_PREFIX +
    '.'.join([str(ii) for ii in __version_info__['release']]))
assert PYNETDICOM_IMPLEMENTATION_UID.is_valid

import logging

# Convenience imports
from pynetdicom import events as evt
from pynetdicom.ae import ApplicationEntity as AE
from pynetdicom.association import Association
from pynetdicom.presentation import (
    build_context,
    build_role,
    DEFAULT_TRANSFER_SYNTAXES,
    VerificationPresentationContexts,
    StoragePresentationContexts,
示例#26
0
    def test_assignment(self):
        """Check assignment works correctly"""
        assoc = A_ASSOCIATE()

        with pytest.raises(AttributeError):
            assoc.mode = "test value"

        with pytest.raises(AttributeError):
            assoc.presentation_requirements = "test value2"

        with pytest.raises(AttributeError):
            assoc.session_requirements = "test value3"

        assoc.application_context_name = None
        assert assoc.application_context_name is None
        assoc.application_context_name = "1.2.840.10008.3.1.1.1"
        assert assoc.application_context_name == UID("1.2.840.10008.3.1.1.1")
        assoc.application_context_name = b"1.2.840.10008.3.1.1.1"
        assert assoc.application_context_name == UID("1.2.840.10008.3.1.1.1")
        assoc.application_context_name = UID("1.2.840.10008.3.1.1.1")
        assert assoc.application_context_name == UID("1.2.840.10008.3.1.1.1")

        msg = "'Calling AE Title' must be str, not 'NoneType'"
        with pytest.raises(TypeError, match=msg):
            assoc.calling_ae_title = None

        assoc.calling_ae_title = "ABCDEF1234567890"
        assert assoc.calling_ae_title == "ABCDEF1234567890"

        msg = "'Called AE Title' must be str, not 'NoneType'"
        with pytest.raises(TypeError, match=msg):
            assoc.called_ae_title = None

        assert assoc.responding_ae_title == assoc.called_ae_title
        assoc.called_ae_title = "1234567890ABCDEF"
        assert assoc.called_ae_title == "1234567890ABCDEF"
        assert assoc.responding_ae_title == assoc.called_ae_title

        max_length = MaximumLengthNotification()
        max_length.maximum_length_received = 31222
        assoc.user_information.append(max_length)
        assert assoc.user_information[0].maximum_length_received == 31222

        assoc.user_information = ["a", max_length]
        assert assoc.user_information == [max_length]

        assoc.result = None
        assert assoc.result is None
        assoc.result = 0
        assoc.result = 1
        assert assoc.result == 1
        assoc.result = 2
        assert assoc.result == 2

        assoc.result_source = None
        assert assoc.result_source is None
        assoc.result_source = 1
        assert assoc.result_source == 1
        assoc.result_source = 2
        assert assoc.result_source == 2
        assoc.result_source = 3
        assert assoc.result_source == 3

        assoc.diagnostic = None
        assert assoc.diagnostic is None
        assoc.diagnostic = 1
        assert assoc.diagnostic == 1
        assoc.diagnostic = 2
        assert assoc.diagnostic == 2
        assoc.diagnostic = 3
        assert assoc.diagnostic == 3
        assoc.diagnostic = 7
        assert assoc.diagnostic == 7

        assoc.calling_presentation_address = None
        assert assoc.calling_presentation_address is None
        assoc.calling_presentation_address = ("10.40.94.43", 105)
        assert assoc.calling_presentation_address == ("10.40.94.43", 105)

        assoc.called_presentation_address = None
        assert assoc.called_presentation_address is None
        assoc.called_presentation_address = ("10.40.94.44", 106)
        assert assoc.called_presentation_address == ("10.40.94.44", 106)

        pc = PresentationContext()
        pc.context_id = 1
        assoc.presentation_context_definition_list = [pc]
        assert assoc.presentation_context_definition_list == [pc]
        assoc.presentation_context_definition_list = ["a", pc]
        assert assoc.presentation_context_definition_list == [pc]

        assoc.presentation_context_definition_results_list = [pc]
        assert assoc.presentation_context_definition_results_list == [pc]
        assoc.presentation_context_definition_results_list = ["a", pc]
        assert assoc.presentation_context_definition_results_list == [pc]

        assoc = A_ASSOCIATE()
        # No maximum_length_received set
        assert assoc.maximum_length_received is None

        # No MaximumLengthNotification present
        assoc.maximum_length_received = 31223
        assert assoc.user_information[0].maximum_length_received == 31223
        assert assoc.maximum_length_received == 31223

        # MaximumLengthNotification already present
        assoc.maximum_length_received = 31224
        assert assoc.maximum_length_received == 31224

        # No ImplementationClassUIDNotification present
        assoc.implementation_class_uid = "1.1.2.3.4"
        assert assoc.user_information[1].implementation_class_uid == UID("1.1.2.3.4")
        assert assoc.implementation_class_uid == UID("1.1.2.3.4")

        # ImplementationClassUIDNotification already present
        assoc.implementation_class_uid = "1.1.2.3.4"
        assert assoc.implementation_class_uid == UID("1.1.2.3.4")
示例#27
0
    def test_assignment_and_exceptions(self):
        """ Check incorrect types/values for properties raise exceptions """
        primitive = SCP_SCU_RoleSelectionNegotiation()

        ## Check assignment
        # SOP Class UID
        reference_uid = UID('1.2.840.10008.5.1.4.1.1.2')

        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        assert primitive.sop_class_uid == reference_uid

        primitive.sop_class_uid = '1.2.840.10008.5.1.4.1.1.2'
        assert primitive.sop_class_uid == reference_uid

        primitive.sop_class_uid = UID('1.2.840.10008.5.1.4.1.1.2')
        assert primitive.sop_class_uid == reference_uid

        # SCP Role
        primitive.scp_role = False
        assert primitive.scp_role is False

        # SCU Role
        primitive.scu_role = True
        assert primitive.scu_role is True

        ## Check exceptions
        with pytest.raises(TypeError):
            primitive.sop_class_uid = 10

        with pytest.raises(TypeError):
            primitive.sop_class_uid = 45.2

        with pytest.raises(TypeError):
            primitive.scp_role = 1

        with pytest.raises(TypeError):
            primitive.scp_role = 'abc'

        with pytest.raises(TypeError):
            primitive.scu_role = 1

        with pytest.raises(TypeError):
            primitive.scu_role = 'abc'

        # No value set
        primitive = SCP_SCU_RoleSelectionNegotiation()
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive.scp_role = False
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive = SCP_SCU_RoleSelectionNegotiation()
        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        primitive.scu_role = True
        item = primitive.from_primitive()
        assert item.scu_role
        assert not item.scp_role

        primitive = SCP_SCU_RoleSelectionNegotiation()
        primitive.scp_role = True
        primitive.scu_role = True
        with pytest.raises(ValueError):
            item = primitive.from_primitive()
示例#28
0
 def test_validate_uid_conformance_true(self, uid, is_valid):
     _config.ENFORCE_UID_CONFORMANCE = True
     assert validate_uid(UID(uid)) == is_valid[0]
示例#29
0
    def test_assignment(self):
        """ Check assignment works correctly """
        assoc = A_ASSOCIATE()

        with pytest.raises(AttributeError):
            assoc.mode = "test value"

        with pytest.raises(AttributeError):
            assoc.presentation_requirements = "test value2"

        with pytest.raises(AttributeError):
            assoc.session_requirements = "test value3"

        assoc.application_context_name = "1.2.840.10008.3.1.1.1"
        assert assoc.application_context_name == UID('1.2.840.10008.3.1.1.1')
        assoc.application_context_name = b"1.2.840.10008.3.1.1.1"
        assert assoc.application_context_name == UID('1.2.840.10008.3.1.1.1')
        assoc.application_context_name = UID("1.2.840.10008.3.1.1.1")
        assert assoc.application_context_name == UID('1.2.840.10008.3.1.1.1')

        assoc.calling_ae_title = 'ABCD1234ABCD12345'
        assert assoc.calling_ae_title == b'ABCD1234ABCD1234'

        assoc.called_ae_title = 'ABCD1234ABCD12345'
        assert assoc.called_ae_title == b'ABCD1234ABCD1234'
        assert assoc.responding_ae_title == b'ABCD1234ABCD1234'

        max_length = MaximumLengthNotification()
        max_length.maximum_length_received = 31222
        assoc.user_information.append(max_length)
        assert assoc.user_information[0].maximum_length_received == 31222

        assoc.user_information = ['a', max_length]
        assert assoc.user_information == [max_length]

        assoc.result = 0
        assert assoc.result == 0
        assoc.result = 1
        assert assoc.result == 1
        assoc.result = 2
        assert assoc.result == 2

        assoc.result_source = 1
        assert assoc.result_source == 1
        assoc.result_source = 2
        assert assoc.result_source == 2
        assoc.result_source = 3
        assert assoc.result_source == 3

        assoc.diagnostic = 1
        assert assoc.diagnostic == 1
        assoc.diagnostic = 2
        assert assoc.diagnostic == 2
        assoc.diagnostic = 3
        assert assoc.diagnostic == 3
        assoc.diagnostic = 7
        assert assoc.diagnostic == 7

        assoc.calling_presentation_address = ('10.40.94.43', 105)
        assert assoc.calling_presentation_address == ('10.40.94.43', 105)

        assoc.called_presentation_address = ('10.40.94.44', 106)
        assert assoc.called_presentation_address == ('10.40.94.44', 106)

        pc = PresentationContext()
        pc.context_id = 1
        assoc.presentation_context_definition_list = [pc]
        assert assoc.presentation_context_definition_list == [pc]
        assoc.presentation_context_definition_list = ['a', pc]
        assert assoc.presentation_context_definition_list == [pc]

        assoc.presentation_context_definition_results_list = [pc]
        assert assoc.presentation_context_definition_results_list == [pc]
        assoc.presentation_context_definition_results_list = ['a', pc]
        assert assoc.presentation_context_definition_results_list == [pc]

        assoc = A_ASSOCIATE()
        # No maximum_length_received set
        assert assoc.maximum_length_received is None

        # No MaximumLengthNotification present
        assoc.maximum_length_received = 31223
        assert assoc.user_information[0].maximum_length_received == 31223
        assert assoc.maximum_length_received == 31223

        # MaximumLengthNotification already present
        assoc.maximum_length_received = 31224
        assert assoc.maximum_length_received == 31224

        # No ImplementationClassUIDNotification present
        assoc.implementation_class_uid = '1.1.2.3.4'
        assert assoc.user_information[1].implementation_class_uid == UID(
            '1.1.2.3.4')
        assert assoc.implementation_class_uid == UID('1.1.2.3.4')

        # ImplementationClassUIDNotification already present
        assoc.implementation_class_uid = '1.1.2.3.4'
        assert assoc.implementation_class_uid == UID('1.1.2.3.4')
示例#30
0
 def test_validate_uid_conformance_false(self, uid, is_valid):
     _config.ENFORCE_UID_CONFORMANCE = False
     assert validate_uid(UID(uid)) == is_valid[1]