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")
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
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)
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")
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_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))
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)
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'))
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)))
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, ""
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)
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'))
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')])
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
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")
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'
def setup_class(self): """Set default UID""" self.uid = UID('9.9.999.90009.1.2')
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")
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')
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()
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
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__()
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,
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
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")
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
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]
def setup(self): self.enc = Encoder(UID('1.2.3'))
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)
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()
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)
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')
def setup_class(self): """Set default UID""" self.uid = UID('1.2.840.10008.1.2')