def AffectedSOPClassUID(self, value):
     """
     Sets the Affected SOP Class UID parameter
     
     Parameters
     ----------
     value : pydicom.uid.UID, bytes or str
         The value for the Affected SOP Class UID
     """
     if isinstance(value, UID):
         pass
     elif isinstance(value, str):
         value = UID(value)
     elif isinstance(value, bytes):
         value = UID(value.decode('utf-8'))
     elif value is None:
         pass
     else:
         raise TypeError("Affected SOP Class UID must be a " \
                 "pydicom.uid.UID, str or bytes")
     
     if value is not None:
         try:
             value.is_valid()
         except:
             logger.error("Affected SOP Class UID is an invalid UID")
             raise ValueError("Affected SOP Class UID is an invalid UID")
     
     self._affected_sop_class_uid = value
 def transfer_syntaxes(self, transfer_syntaxes):
     
     self._transfer_syntaxes = []
     
     try:
         for syntax in transfer_syntaxes:
             try:
                 if isinstance(syntax, str):
                     sop_uid = UID(syntax)
                     sop_uid.is_valid()
                 elif isinstance(syntax, UID):
                     sop_uid = syntax
                     sop_uid.is_valid()
                 elif 'UID' in sop_class.__dict__.keys():
                     sop_uid = UID(syntax.UID)
                     sop_uid.is_valid()
                 else:
                     raise ValueError("Transfer syntax SOP class must be "
                                 "a UID str, UID or ServiceClass subclass")
                 
                 if sop_uid.is_transfer_syntax:
                     self._transfer_syntaxes.append(sop_uid)
                 else:
                     logger.warning("Attempted to add a non-transfer syntax "
                         "UID '%s'" %syntax)
             
             except InvalidUID:
                 raise ValueError("Transfer syntax contained an invalid "
                         "UID string")
         if self._transfer_syntaxes == []:
             raise ValueError("Transfer syntax must be a list of SOP Classes")
     except:
         raise ValueError("Transfer syntax SOP class must be a "
                             "UID str, UID or ServiceClass subclass")
Exemple #3
0
    def AbstractSyntax(self, value):
        """ 
        `value` must be a pydicom.uid.UID, a string UID or a byte string UID
        """
        if isinstance(value, bytes):
            value = UID(value.decode("utf-8"))
        elif isinstance(value, UID):
            pass
        elif isinstance(value, str):
            value = UID(value)
        elif value is None:
            pass
        else:
            raise ValueError("PresentationContext(): Invalid abstract syntax")

        self.__abstract_syntax = value
Exemple #4
0
 def TransferSyntax(self, value):
     """
     `value` must be a list of pydicom.uid.UIDs, string UIDs or byte string
     UIDs
     """
     self.__transfer_syntax = []
     for ii in value:
         if isinstance(value, bytes):
             ii = UID(ii.decode("utf-8"))
         elif isinstance(ii, UID):
             pass
         elif isinstance(ii, str):
             ii = UID(ii)
         else:
             raise ValueError("PresentationContext(): Invalid transfer " "syntax item")
         self.__transfer_syntax.append(ii)
Exemple #5
0
    def add_transfer_syntax(self, transfer_syntax):
        """
        Parameters
        ----------
        transfer_syntax - pydicom.uid.UID, bytes or str
            The transfer syntax to add to the Presentation Context
        """
        if isinstance(transfer_syntax, str):
            transfer_syntax = UID(transfer_syntax)
        elif isinstance(transfer_syntax, bytes):
            transfer_syntax = UID(transfer_syntax.decode("utf-8"))
        else:
            raise ValueError("transfer_syntax must be a pydicom.uid.UID, bytes or str")

        if isinstance(transfer_syntax, UID):
            if transfer_syntax not in self.TransferSyntax:
                self.TransferSyntax.append(transfer_syntax)
    def scu_supported_sop(self, sop_list):
        """
        A valid SOP is either a str UID (ie '1.2.840.10008.1.1') or a
        valid pydicom.uid.UID object (UID.is_valid() shouldn't cause an 
        exception) or a pynetdicom.SOPclass.ServiceClass subclass with a UID 
        attribute(ie VerificationSOPClass)
        """
        self._scu_supported_sop = []
        
        try:
            for sop_class in sop_list:
                try:
                    if isinstance(sop_class, str):
                        sop_uid = UID(sop_class)
                        sop_uid.is_valid()
                    elif isinstance(sop_class, UID):
                        sop_uid = sop_class
                        sop_uid.is_valid()
                    elif 'UID' in sop_class.__dict__.keys():
                        sop_uid = UID(sop_class.UID)
                        sop_uid.is_valid()
                    else:
                        raise ValueError("SCU SOP class must be a UID str, "
                                "UID or ServiceClass subclass")
                                
                    self._scu_supported_sop.append(sop_uid)
                
                except InvalidUID:
                    raise ValueError("SCU SOP classes contained an invalid "
                            "UID string")
                except Exception as e:
                    logger.warning("Invalid SCU SOP class '%s'" %sop_class)

            if sop_list != [] and self._scu_supported_sop == []:
                raise ValueError("No valid SCU SOP classes were supplied")
        except TypeError:
            raise ValueError("scu_sop_class must be a list")
        except:
            raise ValueError("scu_sop_class must be a list of SOP Classes")
Exemple #7
0
    def test_is_deflated(self):
        """Test that UID.is_deflated works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert not UID('1.2.840.10008.1.2').is_deflated
        assert not UID('1.2.840.10008.1.2.1').is_deflated
        assert UID('1.2.840.10008.1.2.1.99').is_deflated
        assert not UID('1.2.840.10008.1.2.2').is_deflated
        assert not UID('1.2.840.10008.1.2.4.50').is_deflated

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_deflated
Exemple #8
0
    def test_abstract_syntax(self):
        """Test abstract syntax setter"""
        pc = PresentationContext(1)
        pc.AbstractSyntax = '1.1.1'
        self.assertEqual(pc.AbstractSyntax, UID('1.1.1'))
        self.assertTrue(isinstance(pc.AbstractSyntax, UID))
        pc.AbstractSyntax = b'1.2.1'
        self.assertEqual(pc.AbstractSyntax, UID('1.2.1'))
        self.assertTrue(isinstance(pc.AbstractSyntax, UID))
        pc.AbstractSyntax = UID('1.3.1')
        self.assertEqual(pc.AbstractSyntax, UID('1.3.1'))
        self.assertTrue(isinstance(pc.AbstractSyntax, UID))

        pc.AbstractSyntax = UID('1.4.1.')
        self.assertEqual(pc.AbstractSyntax, UID('1.3.1'))
        self.assertTrue(isinstance(pc.AbstractSyntax, UID))
Exemple #9
0
    def test_abstract_syntax(self):
        """Test abstract syntax setter"""
        pc = PresentationContext(1)
        pc.AbstractSyntax = '1.1.1'
        assert pc.AbstractSyntax == UID('1.1.1')
        assert isinstance(pc.AbstractSyntax, UID)
        pc.AbstractSyntax = b'1.2.1'
        assert pc.AbstractSyntax == UID('1.2.1')
        assert isinstance(pc.AbstractSyntax, UID)
        pc.AbstractSyntax = UID('1.3.1')
        assert pc.AbstractSyntax == UID('1.3.1')
        assert isinstance(pc.AbstractSyntax, UID)

        pc.AbstractSyntax = UID('1.4.1.')
        assert pc.AbstractSyntax == UID('1.3.1')
        assert isinstance(pc.AbstractSyntax, UID)
Exemple #10
0
    def test_decode_properties(self):
        """ Check decoding the stream produces the correct properties """
        pdu = A_ASSOCIATE_AC()
        pdu.Decode(a_associate_ac)

        context = pdu.presentation_context[0]

        # Check ID property
        context_id = context.ID
        self.assertTrue(isinstance(context_id, int))
        self.assertEqual(context_id, 1)

        # Check Result
        result = pdu.presentation_context[0].result_reason
        self.assertEqual(result, 0)
        self.assertTrue(isinstance(result, int))

        # Check transfer syntax
        syntax = pdu.presentation_context[0].transfer_syntax
        self.assertTrue(syntax.is_transfer_syntax)
        self.assertTrue(isinstance(syntax, UID))
        self.assertEqual(syntax, UID('1.2.840.10008.1.2'))
Exemple #11
0
    def testKnownUID(self):
        """UID: Known UID properties accessed....................."""

        msg = "UID: expected '{1:s}', got '{2:s}' for UID {0:s}"

        uid = UID('1.2.840.10008.1.2')  # Implicit VR Little Endian
        expected = 'Implicit VR Little Endian'
        got = uid.name
        self.assertEqual(got, expected, msg.format("name", expected, got))

        expected = 'Transfer Syntax'
        got = uid.type
        self.assertEqual(got, expected, msg.format("type", expected, got))

        expected = 'Default Transfer Syntax for DICOM'
        got = uid.info
        self.assertEqual(got, expected, msg.format("info", expected, got))

        expected = False
        got = uid.is_retired
        self.assertEqual(got, expected,
                         msg.format("is_retired", str(expected), str(got)))
Exemple #12
0
    def test_transfer_syntax(self):
        """Test transfer syntax setter"""
        pc = PresentationContext()
        pc.context_id = 1
        pc.transfer_syntax = ['1.2.840.10008.1.2']

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

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

        pc.transfer_syntax = [1234, UID('1.4.1')]
        assert pc.transfer_syntax == [UID('1.4.1')]
def validate_ui(value: UID) -> Tuple[bool, str]:

    from pynetdicom import _config

    if not isinstance(value, str):
        return False, "must be pydicom.uid.UID"

    value = UID(value)

    if _config.ENFORCE_UID_CONFORMANCE:
        if value.is_valid:
            return True, ""

        return False, "UID is non-conformant"

    if not 0 < len(value):
        return False, "must not be an empty str"

    if not len(value) < 65:
        return False, "must not exceed 64 characters"

    return True, ""
Exemple #14
0
 def _convert(self, val):
     """Take the value and convert to number, etc if possible"""
     if self.VR == 'IS':
         return pydicom.valuerep.IS(val)
     elif self.VR == 'DA' and config.datetime_conversion:
         return pydicom.valuerep.DA(val)
     elif self.VR == 'DS':
         return pydicom.valuerep.DS(val)
     elif self.VR == 'DT' and config.datetime_conversion:
         return pydicom.valuerep.DT(val)
     elif self.VR == 'TM' and config.datetime_conversion:
         return pydicom.valuerep.TM(val)
     elif self.VR == "UI":
         return UID(val)
     elif not in_py2 and self.VR == "PN":
         return PersonName(val)
     # Later may need this for PersonName as for UI,
     #    but needs more thought
     # elif self.VR == "PN":
     #    return PersonName(val)
     else:  # is either a string or a type 2 optionally blank string
         return val  # this means a "numeric" value could be empty string ""
    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)
    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)
Exemple #17
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'))
Exemple #18
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')])
Exemple #19
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
Exemple #20
0
    def scp_supported_sop(self, sop_list):
        """Set the AE's supported SCP SOP classes.

        Examples of the `sop_list` items:
        - '1.2.3.4'
        - b'1.2.3.4.5'
        - pydicom.uid.UID('1.2.3')
        - pynetdicom3.sop_class.VerificationSOPClass

        Parameters
        ----------
        sop_list : list of str, bytes, UID, pynetdicom3.sop_class.ServiceClass
            The supported SCP SOP classes.
        """
        # pylint: disable=attribute-defined-outside-init
        self._scp_supported_sop = []
        if not isinstance(sop_list, list):
            raise TypeError("scp_supported_sop must be a list of SOP " \
                               "classes.")

        for sop_class in sop_list:
            if isinstance(sop_class, str):
                sop_uid = UID(sop_class)
            elif isinstance(sop_class, bytes):
                sop_uid = UID(sop_class.decode('utf-8'))
            elif isclass(sop_class):
                if 'UID' in sop_class.__dict__:
                    sop_uid = sop_class.UID
                else:
                    continue
            else:
                continue

            try:
                sop_uid.is_valid()
            except InvalidUID:
                continue

            self._scp_supported_sop.append(sop_uid)

        if sop_list != [] and self._scp_supported_sop == []:
            raise TypeError("No valid SCP SOP classes were supplied")
Exemple #21
0
class TestUID(object):
    """Test DICOM UIDs"""
    @classmethod
    def setup_class(self):
        """Set default UID"""
        self.uid = UID('1.2.840.10008.1.2')

    def test_equality(self):
        """Test that UID.__eq__ works."""
        assert self.uid == UID('1.2.840.10008.1.2')
        assert self.uid == '1.2.840.10008.1.2'
        assert self.uid == 'Implicit VR Little Endian'
        assert not self.uid == UID('1.2.840.10008.1.2.1')
        assert not self.uid == '1.2.840.10008.1.2.1'
        assert not self.uid == 'Explicit VR Little Endian'
        # Issue 96
        assert not self.uid == 3
        assert not self.uid is None

    def test_inequality(self):
        """Test that UID.__ne__ works."""
        assert not self.uid != UID('1.2.840.10008.1.2')
        assert not self.uid != '1.2.840.10008.1.2'
        assert not self.uid != 'Implicit VR Little Endian'
        assert self.uid != UID('1.2.840.10008.1.2.1')
        assert self.uid != '1.2.840.10008.1.2.1'
        assert self.uid != 'Explicit VR Little Endian'
        # Issue 96
        assert self.uid != 3
        assert self.uid is not None

    def test_hash(self):
        """Test that UID.__hash_- works."""
        assert hash(self.uid) == hash(self.uid)

    def test_str(self):
        """Test that UID.__str__ works."""
        assert self.uid.__str__() == 'Implicit VR Little Endian'

    def test_is_implicit_vr(self):
        """Test that UID.is_implicit_VR works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert UID('1.2.840.10008.1.2').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.1').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.1.99').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.2').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.4.50').is_implicit_VR

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_implicit_VR

    def test_is_little_endian(self):
        """Test that UID.is_little_endian works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert UID('1.2.840.10008.1.2').is_little_endian
        assert UID('1.2.840.10008.1.2.1').is_little_endian
        assert UID('1.2.840.10008.1.2.1.99').is_little_endian
        assert not UID('1.2.840.10008.1.2.2').is_little_endian
        assert UID('1.2.840.10008.1.2.4.50').is_little_endian

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_little_endian

    def test_is_deflated(self):
        """Test that UID.is_deflated works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert not UID('1.2.840.10008.1.2').is_deflated
        assert not UID('1.2.840.10008.1.2.1').is_deflated
        assert UID('1.2.840.10008.1.2.1.99').is_deflated
        assert not UID('1.2.840.10008.1.2.2').is_deflated
        assert not UID('1.2.840.10008.1.2.4.50').is_deflated

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_deflated

    def test_is_transfer_syntax(self):
        """Test that UID.is_transfer_syntax works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert UID('1.2.840.10008.1.2').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.1').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.1.99').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.2').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.4.50').is_transfer_syntax

        assert not UID('1.2.840.10008.5.1.4.1.1.2').is_transfer_syntax

    def test_is_compressed(self):
        """Test that UID.is_compressed works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert not UID('1.2.840.10008.1.2').is_compressed
        assert not UID('1.2.840.10008.1.2.1').is_compressed
        assert not UID('1.2.840.10008.1.2.1.99').is_compressed
        assert not UID('1.2.840.10008.1.2.2').is_compressed
        assert UID('1.2.840.10008.1.2.4.50').is_compressed

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_compressed

    def test_is_encapsulated(self):
        """Test that UID.is_encapsulated works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert not UID('1.2.840.10008.1.2').is_encapsulated
        assert not UID('1.2.840.10008.1.2.1').is_encapsulated
        assert not UID('1.2.840.10008.1.2.1.99').is_encapsulated
        assert not UID('1.2.840.10008.1.2.2').is_encapsulated
        assert UID('1.2.840.10008.1.2.4.50').is_encapsulated

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_encapsulated

    def test_name(self):
        """Test that UID.name works."""
        assert self.uid.name == 'Implicit VR Little Endian'
        assert UID('1.2.840.10008.5.1.4.1.1.2').name == 'CT Image Storage'

    def test_type(self):
        """Test that UID.type works."""
        assert self.uid.type == 'Transfer Syntax'
        assert UID('1.2.840.10008.5.1.4.1.1.2').type == 'SOP Class'

    def test_info(self):
        """Test that UID.info works."""
        assert self.uid.info == 'Default Transfer Syntax for DICOM'
        assert UID('1.2.840.10008.5.1.4.1.1.2').info == ''

    def test_is_retired(self):
        """Test that UID.is_retired works."""
        assert not self.uid.is_retired
        assert UID('1.2.840.10008.1.2.2').is_retired

    def test_is_valid(self):
        """Test that UID.is_valid works."""
        for invalid_uid in ('1' * 65,
                            '1.' + ('2' * 63),
                            '',
                            '.',
                            '1.',
                            '1.01',
                            '1.a.2'):
            assert not UID(invalid_uid).is_valid

        for valid_uid in ('0',
                          '1',
                          '0.1',
                          '1' * 64,
                          '1.' + ('2' * 62),
                          '1.0.23'):
            assert UID(valid_uid).is_valid

    def test_is_private(self):
        """Test the is_private property"""
        private_uid = UID('1.2.840.10009.1.2')
        assert private_uid.is_private
        assert not self.uid.is_private
 def test_validate_uid_conformance_true(self, uid, is_valid):
     _config.ENFORCE_UID_CONFORMANCE = True
     assert validate_uid(UID(uid)) == is_valid[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'
Exemple #24
0
 def setup_class(self):
     """Set default UID"""
     self.uid = UID('9.9.999.90009.1.2')
Exemple #25
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")
Exemple #26
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')
Exemple #27
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()
Exemple #28
0
class TestUIDPrivate(object):
    """Test private UIDs"""
    @classmethod
    def setup_class(self):
        """Set default UID"""
        self.uid = UID('9.9.999.90009.1.2')

    def test_equality(self):
        """Test that UID.__eq__ works with private UIDs."""
        assert self.uid == UID('9.9.999.90009.1.2')
        assert self.uid == '9.9.999.90009.1.2'
        assert not self.uid == UID('9.9.999.90009.1.3')
        assert not self.uid == '9.9.999.90009.1.3'

    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'

    def test_hash(self):
        """Test that UID.__hash_- works with private UIDs."""
        assert hash(self.uid) == hash(self.uid)

    def test_str(self):
        """Test that UID.__str__ works with private UIDs."""
        assert self.uid.__str__() == '9.9.999.90009.1.2'

    def test_is_implicit_vr(self):
        """Test that UID.is_implicit_VR works with private UIDs."""
        with pytest.raises(ValueError):
            self.uid.is_implicit_VR

    def test_is_little_endian(self):
        """Test that UID.is_little_endian works with private UIDs."""
        with pytest.raises(ValueError):
            self.uid.is_little_endian

    def test_is_deflated(self):
        """Test that UID.is_deflated works with private UIDs."""
        with pytest.raises(ValueError):
            self.uid.is_deflated

    def test_is_transfer_syntax(self):
        """Test that UID.is_transfer_syntax works with private UIDs."""
        with pytest.raises(ValueError):
            self.uid.is_transfer_syntax

    def test_is_compressed(self):
        """Test that UID.is_compressed works with private UIDs."""
        with pytest.raises(ValueError):
            self.uid.is_compressed

    def test_is_encapsulated(self):
        """Test that UID.is_encapsulated works with private UIDs."""
        with pytest.raises(ValueError):
            self.uid.is_encapsulated

    def test_name(self):
        """Test that UID.name works with private UIDs."""
        assert self.uid.name == '9.9.999.90009.1.2'

    def test_type(self):
        """Test that UID.type works with private UIDs."""
        assert self.uid.type == ''

    def test_info(self):
        """Test that UID.info works with private UIDs."""
        assert self.uid.info == ''

    def test_is_retired(self):
        """Test that UID.is_retired works with private UIDs."""
        assert not self.uid.is_retired

    def test_is_valid(self):
        """Test that UID.is_valid works with private UIDs."""
        assert self.uid.is_valid

    def test_is_private(self):
        """Test that UID.is_private works with private UIDs."""
        assert self.uid.is_private
Exemple #29
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__()
Exemple #30
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,
Exemple #31
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
Exemple #32
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")
Exemple #33
0
class TestUID(object):
    """Test DICOM UIDs"""
    @classmethod
    def setup_class(self):
        """Set default UID"""
        self.uid = UID('1.2.840.10008.1.2')

    def test_equality(self):
        """Test that UID.__eq__ works."""
        assert self.uid == UID('1.2.840.10008.1.2')
        assert self.uid == '1.2.840.10008.1.2'
        assert '1.2.840.10008.1.2' == self.uid
        assert self.uid == 'Implicit VR Little Endian'
        assert 'Implicit VR Little Endian' == self.uid
        assert not self.uid == UID('1.2.840.10008.1.2.1')
        assert not self.uid == '1.2.840.10008.1.2.1'
        assert not '1.2.840.10008.1.2.1' == self.uid
        assert not self.uid == 'Explicit VR Little Endian'
        assert not 'Explicit VR Little Endian' == self.uid
        # Issue 96
        assert not self.uid == 3
        assert self.uid is not None

    def test_equality_deprecation_warning(self):
        """Test the deprecation warning is working"""
        uid = UID('1.2.840.10008.1.1')
        assert uid.name == 'Verification SOP Class'
        assert uid == 'Verification SOP Class'
        with pytest.deprecated_call():
            assert uid == 'Verification SOP Class'
            assert 'Verification SOP Class' == uid

    def test_inequality(self):
        """Test that UID.__ne__ works."""
        assert not self.uid != UID('1.2.840.10008.1.2')
        assert not self.uid != '1.2.840.10008.1.2'
        assert not '1.2.840.10008.1.2' != self.uid
        assert not self.uid != 'Implicit VR Little Endian'
        assert not 'Implicit VR Little Endian' != self.uid
        assert self.uid != UID('1.2.840.10008.1.2.1')
        assert self.uid != '1.2.840.10008.1.2.1'
        assert '1.2.840.10008.1.2.1' != self.uid
        assert self.uid != 'Explicit VR Little Endian'
        assert 'Explicit VR Little Endian' != self.uid
        # Issue 96
        assert self.uid != 3

    def test_inequality_deprecation_warning(self):
        """Test the deprecation warning is working"""
        uid = UID('1.2.840.10008.1.1')
        assert uid.name == 'Verification SOP Class'
        assert uid != 'Implicit VR Little Endian'
        with pytest.deprecated_call():
            assert uid != 'Implicit VR Little Endian'
            assert 'Implicit VR Little Endian' != uid

    def test_hash(self):
        """Test that UID.__hash_- works."""
        assert hash(self.uid) == hash(self.uid)

    def test_str(self):
        """Test that UID.__str__ works."""
        assert self.uid.__str__() == '1.2.840.10008.1.2'

    def test_is_implicit_vr(self):
        """Test that UID.is_implicit_VR works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert UID('1.2.840.10008.1.2').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.1').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.1.99').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.2').is_implicit_VR
        assert not UID('1.2.840.10008.1.2.4.50').is_implicit_VR

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_implicit_VR

    def test_is_little_endian(self):
        """Test that UID.is_little_endian works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert UID('1.2.840.10008.1.2').is_little_endian
        assert UID('1.2.840.10008.1.2.1').is_little_endian
        assert UID('1.2.840.10008.1.2.1.99').is_little_endian
        assert not UID('1.2.840.10008.1.2.2').is_little_endian
        assert UID('1.2.840.10008.1.2.4.50').is_little_endian

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_little_endian

    def test_is_deflated(self):
        """Test that UID.is_deflated works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert not UID('1.2.840.10008.1.2').is_deflated
        assert not UID('1.2.840.10008.1.2.1').is_deflated
        assert UID('1.2.840.10008.1.2.1.99').is_deflated
        assert not UID('1.2.840.10008.1.2.2').is_deflated
        assert not UID('1.2.840.10008.1.2.4.50').is_deflated

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_deflated

    def test_is_transfer_syntax(self):
        """Test that UID.is_transfer_syntax works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert UID('1.2.840.10008.1.2').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.1').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.1.99').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.2').is_transfer_syntax
        assert UID('1.2.840.10008.1.2.4.50').is_transfer_syntax

        assert not UID('1.2.840.10008.5.1.4.1.1.2').is_transfer_syntax

    def test_is_compressed(self):
        """Test that UID.is_compressed works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert not UID('1.2.840.10008.1.2').is_compressed
        assert not UID('1.2.840.10008.1.2.1').is_compressed
        assert not UID('1.2.840.10008.1.2.1.99').is_compressed
        assert not UID('1.2.840.10008.1.2.2').is_compressed
        assert UID('1.2.840.10008.1.2.4.50').is_compressed

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_compressed

    def test_is_encapsulated(self):
        """Test that UID.is_encapsulated works."""
        # '1.2.840.10008.1.2' Implicit VR Little Endian
        # '1.2.840.10008.1.2.1' Explicit VR Little Endian
        # '1.2.840.10008.1.2.1.99' Deflated Explicit VR Little Endian
        # '1.2.840.10008.1.2.2' Explicit VR Big Endian
        # '1.2.840.10008.1.2.4.50'JPEG Baseline (Process 1)
        assert not UID('1.2.840.10008.1.2').is_encapsulated
        assert not UID('1.2.840.10008.1.2.1').is_encapsulated
        assert not UID('1.2.840.10008.1.2.1.99').is_encapsulated
        assert not UID('1.2.840.10008.1.2.2').is_encapsulated
        assert UID('1.2.840.10008.1.2.4.50').is_encapsulated

        with pytest.raises(ValueError):
            UID('1.2.840.10008.5.1.4.1.1.2').is_encapsulated

    def test_name(self):
        """Test that UID.name works."""
        assert self.uid.name == 'Implicit VR Little Endian'
        assert UID('1.2.840.10008.5.1.4.1.1.2').name == 'CT Image Storage'

    def test_name_with_equal_hash(self):
        """Test that UID name works for UID with same hash as predefined UID.
        """
        class MockedUID(UID):
            # Force the UID to return the same hash as one of the
            # uid dictionary entries (any will work).
            # The resulting hash collision forces the usage of the `eq`
            # operator while checking for containment in the uid dictionary
            # (regression test for issue #499)
            def __hash__(self):
                return hash(JPEGLSLossy)

        uid = MockedUID('1.2.3')
        assert uid.name == '1.2.3'

    def test_type(self):
        """Test that UID.type works."""
        assert self.uid.type == 'Transfer Syntax'
        assert UID('1.2.840.10008.5.1.4.1.1.2').type == 'SOP Class'

    def test_info(self):
        """Test that UID.info works."""
        assert self.uid.info == 'Default Transfer Syntax for DICOM'
        assert UID('1.2.840.10008.5.1.4.1.1.2').info == ''

    def test_is_retired(self):
        """Test that UID.is_retired works."""
        assert not self.uid.is_retired
        assert UID('1.2.840.10008.1.2.2').is_retired

    def test_is_valid(self):
        """Test that UID.is_valid works."""
        for invalid_uid in ('1' * 65,
                            '1.' + ('2' * 63),
                            '',
                            '.',
                            '1.',
                            '1.01',
                            '1.a.2'):
            assert not UID(invalid_uid).is_valid

        for valid_uid in ('0',
                          '1',
                          '0.1',
                          '1' * 64,
                          '1.' + ('2' * 62),
                          '1.0.23'):
            assert UID(valid_uid).is_valid

    def test_is_private(self):
        """Test the is_private property"""
        private_uid = UID('1.2.840.10009.1.2')
        assert private_uid.is_private
        assert not self.uid.is_private

    def test_raises(self):
        """Test raises exception if not a str type"""
        with pytest.raises(TypeError):
            UID(1234)

    def test_transitive(self):
        """Test for #256"""
        a = '1.2.840.10008.1.1'
        uid = UID(a)
        b = str(uid)
        assert uid.name == 'Verification SOP Class'
        assert uid == a
        assert uid == b
        assert a == b
Exemple #34
0
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
 def test_validate_uid_conformance_false(self, uid, is_valid):
     _config.ENFORCE_UID_CONFORMANCE = False
     assert validate_uid(UID(uid)) == is_valid[1]
Exemple #36
0
 def setup(self):
     self.enc = Encoder(UID('1.2.3'))
Exemple #37
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)
Exemple #38
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()
Exemple #39
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)
Exemple #40
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')
Exemple #41
0
 def setup_class(self):
     """Set default UID"""
     self.uid = UID('1.2.840.10008.1.2')