def test_write_UR_explicit_little(self): """Test writing elements with VR of UR works correctly. Elements with a VR of 'UR' use the newer explicit VR encoded (see PS3.5 Section 7.1.2). """ # Even length URL elem = DataElement(0x00080120, 'UR', 'ftp://bits') encoded_elem = self.encode_element(elem, False, True) # Tag pair (0008, 2001): 08 00 20 01 # VR (UR): \x55\x52 # Reserved: \x00\x00 # Length (4): \x0a\x00\x00\x00 # Value: \x66\x74\x70\x3a\x2f\x2f\x62\x69\x74\x73 ref_bytes = b'\x08\x00\x20\x01\x55\x52\x00\x00\x0a\x00\x00\x00' \ b'\x66\x74\x70\x3a\x2f\x2f\x62\x69\x74\x73' self.assertEqual(encoded_elem, ref_bytes) # Odd length URL has trailing \x20 (SPACE) padding elem.value = 'ftp://bit' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x08\x00\x20\x01\x55\x52\x00\x00\x0a\x00\x00\x00' \ b'\x66\x74\x70\x3a\x2f\x2f\x62\x69\x74\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty value elem.value = '' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x08\x00\x20\x01\x55\x52\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_UR_explicit_little(self): """Test writing elements with VR of UR works correctly. Elements with a VR of 'UR' use the newer explicit VR encoded (see PS3.5 Section 7.1.2). """ # Even length URL elem = DataElement(0x00080120, 'UR', 'ftp://bits') encoded_elem = self.encode_element(elem, False, True) # Tag pair (0008, 2001): 08 00 20 01 # VR (UR): \x55\x52 # Reserved: \x00\x00 # Length (4): \x0a\x00\x00\x00 # Value: \x66\x74\x70\x3a\x2f\x2f\x62\x69\x74\x73 ref_bytes = b'\x08\x00\x20\x01\x55\x52\x00\x00\x0a\x00\x00\x00' \ b'\x66\x74\x70\x3a\x2f\x2f\x62\x69\x74\x73' self.assertEqual(encoded_elem, ref_bytes) # Odd length URL has trailing \x20 (SPACE) padding elem.value = 'ftp://bit' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x08\x00\x20\x01\x55\x52\x00\x00\x0a\x00\x00\x00' \ b'\x66\x74\x70\x3a\x2f\x2f\x62\x69\x74\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty value elem.value = '' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x08\x00\x20\x01\x55\x52\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_UR_implicit_little(self): """Test writing elements with VR of UR works correctly.""" # Even length URL elem = DataElement(0x00080120, 'UR', 'http://github.com/darcymason/pydicom') encoded_elem = self.encode_element(elem) # Tag pair (0008, 2001): 08 00 20 01 # Length (36): 24 00 00 00 # Value: 68 to 6d ref_bytes = b'\x08\x00\x20\x01\x24\x00\x00\x00\x68\x74' \ b'\x74\x70\x3a\x2f\x2f\x67\x69\x74\x68\x75' \ b'\x62\x2e\x63\x6f\x6d\x2f\x64\x61\x72\x63' \ b'\x79\x6d\x61\x73\x6f\x6e\x2f\x70\x79\x64' \ b'\x69\x63\x6f\x6d' self.assertEqual(encoded_elem, ref_bytes) # Odd length URL has trailing \x20 (SPACE) padding elem.value = '../test/test.py' encoded_elem = self.encode_element(elem) # Tag pair (0008, 2001): 08 00 20 01 # Length (16): 10 00 00 00 # Value: 2e to 20 ref_bytes = b'\x08\x00\x20\x01\x10\x00\x00\x00\x2e\x2e' \ b'\x2f\x74\x65\x73\x74\x2f\x74\x65\x73\x74' \ b'\x2e\x70\x79\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty value elem.value = '' encoded_elem = self.encode_element(elem) self.assertEqual(encoded_elem, b'\x08\x00\x20\x01\x00\x00\x00\x00')
def test_write_UC_implicit_little(self): """Test writing elements with VR of UC works correctly.""" # VM 1, even data elem = DataElement(0x00189908, 'UC', 'Test') encoded_elem = self.encode_element(elem) # Tag pair (0018, 9908): 08 00 20 01 # Length (4): 04 00 00 00 # Value: \x54\x65\x73\x74 ref_bytes = b'\x18\x00\x08\x99\x04\x00\x00\x00\x54\x65\x73\x74' self.assertEqual(encoded_elem, ref_bytes) # VM 1, odd data - padded to even length elem.value = 'Test.' encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x06\x00\x00\x00\x54\x65\x73\x74\x2e\x20' self.assertEqual(encoded_elem, ref_bytes) # VM 3, even data elem.value = ['Aa', 'B', 'C'] encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x06\x00\x00\x00\x41\x61\x5c\x42\x5c\x43' self.assertEqual(encoded_elem, ref_bytes) # VM 3, odd data - padded to even length elem.value = ['A', 'B', 'C'] encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x06\x00\x00\x00\x41\x5c\x42\x5c\x43\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = '' encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_UR_implicit_little(self): """Test writing elements with VR of UR works correctly.""" # Even length URL elem = DataElement(0x00080120, 'UR', 'http://github.com/darcymason/pydicom') encoded_elem = self.encode_element(elem) # Tag pair (0008, 2001): 08 00 20 01 # Length (36): 24 00 00 00 # Value: 68 to 6d ref_bytes = b'\x08\x00\x20\x01\x24\x00\x00\x00\x68\x74' \ b'\x74\x70\x3a\x2f\x2f\x67\x69\x74\x68\x75' \ b'\x62\x2e\x63\x6f\x6d\x2f\x64\x61\x72\x63' \ b'\x79\x6d\x61\x73\x6f\x6e\x2f\x70\x79\x64' \ b'\x69\x63\x6f\x6d' self.assertEqual(encoded_elem, ref_bytes) # Odd length URL has trailing \x20 (SPACE) padding elem.value = '../test/test.py' encoded_elem = self.encode_element(elem) # Tag pair (0008, 2001): 08 00 20 01 # Length (16): 10 00 00 00 # Value: 2e to 20 ref_bytes = b'\x08\x00\x20\x01\x10\x00\x00\x00\x2e\x2e' \ b'\x2f\x74\x65\x73\x74\x2f\x74\x65\x73\x74' \ b'\x2e\x70\x79\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty value elem.value = '' encoded_elem = self.encode_element(elem) self.assertEqual(encoded_elem, b'\x08\x00\x20\x01\x00\x00\x00\x00')
def test_write_UC_implicit_little(self): """Test writing elements with VR of UC works correctly.""" # VM 1, even data elem = DataElement(0x00189908, 'UC', 'Test') encoded_elem = self.encode_element(elem) # Tag pair (0018, 9908): 08 00 20 01 # Length (4): 04 00 00 00 # Value: \x54\x65\x73\x74 ref_bytes = b'\x18\x00\x08\x99\x04\x00\x00\x00\x54\x65\x73\x74' self.assertEqual(encoded_elem, ref_bytes) # VM 1, odd data - padded to even length elem.value = 'Test.' encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x06\x00\x00\x00\x54\x65\x73\x74\x2e\x20' self.assertEqual(encoded_elem, ref_bytes) # VM 3, even data elem.value = ['Aa', 'B', 'C'] encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x06\x00\x00\x00\x41\x61\x5c\x42\x5c\x43' self.assertEqual(encoded_elem, ref_bytes) # VM 3, odd data - padded to even length elem.value = ['A', 'B', 'C'] encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x06\x00\x00\x00\x41\x5c\x42\x5c\x43\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = '' encoded_elem = self.encode_element(elem) ref_bytes = b'\x18\x00\x08\x99\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def subfix_HasTrailingNulls(elem: DataElement) -> bool: fixed = False if elem.is_empty: return False if type(elem.value) == MultiValue: v = elem.value else: v = [elem.value] for i in range(0, len(v)): if type(v[i]) == str or type(v[i]) == bytes: l = len(v[i]) idx = l - 1 while idx >= 0: if v[i][idx] == 0: idx -= 1 else: break idx = idx + 1 if idx < l: v[i] = v[i][:idx] if len(v) % 2 == 1: v[i] = v[i] + b'\x20' fixed = True if fixed: if type(elem.value) == MultiValue: elem.value = v else: elem.value = v[0] return fixed
def subfix_ReplaceSlashWithBackslash(attrib: DataElement, log: list) -> bool: fixed = False msg = mesgtext_cc.ErrorInfo('General Fix -', '') fix = 'fixed attribute <{}> ({}) value by changing slash to backslash {} -> {}' if type(attrib.value) == MultiValue: tmp = attrib.value else: tmp = [attrib.value] for idx in range(0, len(tmp)): old_val = tmp[idx] if type(tmp[idx]) == str: tmp[idx] = tmp[idx].replace('/', '\\') elif type(tmp[idx]) == bytes: x = bytearray() for elem in tmp[idx]: if elem == ord('/'): x.append(ord('\\')) else: x.append(elem) tmp[idx] = bytes(x) if old_val != tmp[idx]: msg.fix = fix.format(attrib.name, idx + 1, old_val, tmp[idx]) log.append(msg.getWholeMessage()) fixed = True if type(attrib.value) != MultiValue: attrib.value = tmp[0] return fixed
def testEqualityStandardElement(self): """DataElement: equality returns correct value for simple elements""" dd = DataElement(0x00100010, 'PN', 'ANON') self.assertTrue(dd == dd) ee = DataElement(0x00100010, 'PN', 'ANON') self.assertTrue(dd == ee) # Check value ee.value = 'ANAN' self.assertFalse(dd == ee) # Check tag ee = DataElement(0x00100011, 'PN', 'ANON') self.assertFalse(dd == ee) # Check VR ee = DataElement(0x00100010, 'SH', 'ANON') self.assertFalse(dd == ee) dd = DataElement(0x00080018, 'UI', '1.2.3.4') ee = DataElement(0x00080018, 'UI', '1.2.3.4') self.assertTrue(dd == ee) ee = DataElement(0x00080018, 'PN', '1.2.3.4') self.assertFalse(dd == ee)
def test_equality_standard_element(self): """DataElement: equality returns correct value for simple elements""" dd = DataElement(0x00100010, 'PN', 'ANON') assert dd == dd ee = DataElement(0x00100010, 'PN', 'ANON') assert dd == ee # Check value ee.value = 'ANAN' assert not dd == ee # Check tag ee = DataElement(0x00100011, 'PN', 'ANON') assert not dd == ee # Check VR ee = DataElement(0x00100010, 'SH', 'ANON') assert not dd == ee dd = DataElement(0x00080018, 'UI', '1.2.3.4') ee = DataElement(0x00080018, 'UI', '1.2.3.4') assert dd == ee ee = DataElement(0x00080018, 'PN', '1.2.3.4') assert not dd == ee
def testEqualityStandardElement(self): """DataElement: equality returns correct value for simple elements""" dd = DataElement(0x00100010, 'PN', 'ANON') self.assertTrue(dd == dd) ee = DataElement(0x00100010, 'PN', 'ANON') self.assertTrue(dd == ee) # Check value ee.value = 'ANAN' self.assertFalse(dd == ee) # Check tag ee = DataElement(0x00100011, 'PN', 'ANON') self.assertFalse(dd == ee) # Check VR ee = DataElement(0x00100010, 'SH', 'ANON') self.assertFalse(dd == ee) dd = DataElement(0x00080018, 'UI', '1.2.3.4') ee = DataElement(0x00080018, 'UI', '1.2.3.4') self.assertTrue(dd == ee) ee = DataElement(0x00080018, 'PN', '1.2.3.4') self.assertFalse(dd == ee)
def test_write_UC_explicit_little(self): """Test writing elements with VR of UC works correctly. Elements with a VR of 'UC' use the newer explicit VR encoding (see PS3.5 Section 7.1.2). """ # VM 1, even data elem = DataElement(0x00189908, 'UC', 'Test') encoded_elem = self.encode_element(elem, False, True) # Tag pair (0018, 9908): 08 00 20 01 # VR (UC): \x55\x43 # Reserved: \x00\x00 # Length (4): \x04\x00\x00\x00 # Value: \x54\x65\x73\x74 ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x04\x00\x00\x00' \ b'\x54\x65\x73\x74' self.assertEqual(encoded_elem, ref_bytes) # VM 1, odd data - padded to even length elem.value = 'Test.' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x06\x00\x00\x00' \ b'\x54\x65\x73\x74\x2e\x20' self.assertEqual(encoded_elem, ref_bytes) # VM 3, even data elem.value = ['Aa', 'B', 'C'] encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x06\x00\x00\x00' \ b'\x41\x61\x5c\x42\x5c\x43' self.assertEqual(encoded_elem, ref_bytes) # VM 3, odd data - padded to even length elem.value = ['A', 'B', 'C'] encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x06\x00\x00\x00' \ b'\x41\x5c\x42\x5c\x43\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = '' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_UC_explicit_little(self): """Test writing elements with VR of UC works correctly. Elements with a VR of 'UC' use the newer explicit VR encoding (see PS3.5 Section 7.1.2). """ # VM 1, even data elem = DataElement(0x00189908, 'UC', 'Test') encoded_elem = self.encode_element(elem, False, True) # Tag pair (0018, 9908): 08 00 20 01 # VR (UC): \x55\x43 # Reserved: \x00\x00 # Length (4): \x04\x00\x00\x00 # Value: \x54\x65\x73\x74 ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x04\x00\x00\x00' \ b'\x54\x65\x73\x74' self.assertEqual(encoded_elem, ref_bytes) # VM 1, odd data - padded to even length elem.value = 'Test.' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x06\x00\x00\x00' \ b'\x54\x65\x73\x74\x2e\x20' self.assertEqual(encoded_elem, ref_bytes) # VM 3, even data elem.value = ['Aa', 'B', 'C'] encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x06\x00\x00\x00' \ b'\x41\x61\x5c\x42\x5c\x43' self.assertEqual(encoded_elem, ref_bytes) # VM 3, odd data - padded to even length elem.value = ['A', 'B', 'C'] encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x06\x00\x00\x00' \ b'\x41\x5c\x42\x5c\x43\x20' self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = '' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x18\x00\x08\x99\x55\x43\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_inequality_sequence(self): """Test DataElement.__ne__ for sequence element""" dd = DataElement(0x300A00B0, 'SQ', []) assert not dd != dd assert not DataElement(0x300A00B0, 'SQ', []) != dd ee = DataElement(0x300A00B0, 'SQ', [Dataset()]) assert ee != dd # Check value dd.value = [Dataset()] dd[0].PatientName = 'ANON' ee[0].PatientName = 'ANON' assert not ee != dd ee[0].PatientName = 'ANONA' assert ee != dd
def test_inequality_sequence(self): """Test DataElement.__ne__ for sequence element""" dd = DataElement(0x300A00B0, 'SQ', []) assert not dd != dd ee = DataElement(0x300A00B0, 'SQ', []) assert not dd != ee ee = DataElement(0x300A00B0, 'SQ', [Dataset()]) assert dd != ee # Check value dd.value = [Dataset()] dd[0].PatientName = 'ANON' ee[0].PatientName = 'ANON' assert not dd != ee ee[0].PatientName = 'ANONA' assert dd != ee
def testEqualityPrivateElement(self): """DataElement: equality returns correct value for private elements""" dd = DataElement(0x01110001, 'PN', 'ANON') self.assertTrue(dd == dd) ee = DataElement(0x01110001, 'PN', 'ANON') self.assertTrue(dd == ee) # Check value ee.value = 'ANAN' self.assertFalse(dd == ee) # Check tag ee = DataElement(0x01110002, 'PN', 'ANON') self.assertFalse(dd == ee) # Check VR ee = DataElement(0x01110001, 'SH', 'ANON') self.assertFalse(dd == ee)
def test_write_OL_implicit_little(self): """Test writing elements with VR of OL works correctly.""" # TrackPointIndexList bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03' elem = DataElement(0x00660129, 'OL', bytestring) encoded_elem = self.encode_element(elem) # Tag pair (0066, 0129): 66 00 29 01 # Length (12): 0c 00 00 00 # | Tag | Length | Value -> ref_bytes = b'\x66\x00\x29\x01\x0c\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem) ref_bytes = b'\x66\x00\x29\x01\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_OD_implicit_little(self): """Test writing elements with VR of OD works correctly.""" # VolumetricCurvePoints bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03\x04\x05\x06\x07' elem = DataElement(0x0070150d, 'OD', bytestring) encoded_elem = self.encode_element(elem) # Tag pair (0070, 150d): 70 00 0d 15 # Length (16): 10 00 00 00 # | Tag | Length | Value -> ref_bytes = b'\x70\x00\x0d\x15\x10\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem) ref_bytes = b'\x70\x00\x0d\x15\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_OD_implicit_little(self): """Test writing elements with VR of OD works correctly.""" # VolumetricCurvePoints bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03\x04\x05\x06\x07' elem = DataElement(0x0070150d, 'OD', bytestring) encoded_elem = self.encode_element(elem) # Tag pair (0070, 150d): 70 00 0d 15 # Length (16): 10 00 00 00 # | Tag | Length | Value -> ref_bytes = b'\x70\x00\x0d\x15\x10\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem) ref_bytes = b'\x70\x00\x0d\x15\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_OL_implicit_little(self): """Test writing elements with VR of OL works correctly.""" # TrackPointIndexList bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03' elem = DataElement(0x00660129, 'OL', bytestring) encoded_elem = self.encode_element(elem) # Tag pair (0066, 0129): 66 00 29 01 # Length (12): 0c 00 00 00 # | Tag | Length | Value -> ref_bytes = b'\x66\x00\x29\x01\x0c\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem) ref_bytes = b'\x66\x00\x29\x01\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_equality_private_element(self): """DataElement: equality returns correct value for private elements""" dd = DataElement(0x01110001, 'PN', 'ANON') assert dd == dd ee = DataElement(0x01110001, 'PN', 'ANON') assert dd == ee # Check value ee.value = 'ANAN' assert not dd == ee # Check tag ee = DataElement(0x01110002, 'PN', 'ANON') assert not dd == ee # Check VR ee = DataElement(0x01110001, 'SH', 'ANON') assert not dd == ee
def testEqualityPrivateElement(self): """DataElement: equality returns correct value for private elements""" dd = DataElement(0x01110001, 'PN', 'ANON') self.assertTrue(dd == dd) ee = DataElement(0x01110001, 'PN', 'ANON') self.assertTrue(dd == ee) # Check value ee.value = 'ANAN' self.assertFalse(dd == ee) # Check tag ee = DataElement(0x01110002, 'PN', 'ANON') self.assertFalse(dd == ee) # Check VR ee = DataElement(0x01110001, 'SH', 'ANON') self.assertFalse(dd == ee)
def __setattr__(self, name, value): """Intercept any attempts to set a value for an instance attribute. If name is a dicom descriptive string (cleaned with CleanName), then set the corresponding tag and data_element. Else, set an instance (python) attribute as any other class would do. """ tag = tag_for_name(name) if tag is not None: # successfully mapped name to a tag if tag not in self: # don't have this tag yet->create the data_element instance VR = dictionaryVR(tag) data_element = DataElement(tag, VR, value) else: # already have this data_element, just changing its value data_element = self[tag] data_element.value = value # Now have data_element - store it in this dict self[tag] = data_element else: # name not in dicom dictionary - setting a non-dicom instance attribute # XXX note if user mis-spells a dicom data_element - no error!!! self.__dict__[name] = value
def __setattr__(self, name, value): """Intercept any attempts to set a value for an instance attribute. If name is a dicom descriptive string (cleaned with CleanName), then set the corresponding tag and data_element. Else, set an instance (python) attribute as any other class would do. """ tag = tag_for_name(name) if tag is not None: # successfully mapped name to a tag if tag not in self: # don't have this tag yet->create the data_element instance VR = dictionaryVR(tag) data_element = DataElement(tag, VR, value) else: # already have this data_element, just changing its value data_element = self[tag] data_element.value = value # Now have data_element - store it in this dict self[tag] = data_element else: # name not in dicom dictionary - setting a non-dicom instance attribute # XXX note if user mis-spells a dicom data_element - no error!!! self.__dict__[name] = value
def testEqualitySequenceElement(self): """DataElement: equality returns correct value for sequence elements""" dd = DataElement(0x300A00B0, 'SQ', []) self.assertTrue(dd == dd) ee = DataElement(0x300A00B0, 'SQ', []) self.assertTrue(dd == ee) # Check value e = Dataset() e.PatientName = 'ANON' ee.value = [e] self.assertFalse(dd == ee) # Check tag ee = DataElement(0x01110002, 'SQ', []) self.assertFalse(dd == ee) # Check VR ee = DataElement(0x300A00B0, 'SH', []) self.assertFalse(dd == ee) # Check with dataset dd = DataElement(0x300A00B0, 'SQ', [Dataset()]) dd.value[0].PatientName = 'ANON' ee = DataElement(0x300A00B0, 'SQ', [Dataset()]) ee.value[0].PatientName = 'ANON' self.assertTrue(dd == ee) # Check uneven sequences dd.value.append(Dataset()) dd.value[1].PatientName = 'ANON' self.assertFalse(dd == ee) ee.value.append(Dataset()) ee.value[1].PatientName = 'ANON' self.assertTrue(dd == ee) ee.value.append(Dataset()) ee.value[2].PatientName = 'ANON' self.assertFalse(dd == ee)
def testEqualitySequenceElement(self): """DataElement: equality returns correct value for sequence elements""" dd = DataElement(0x300A00B0, 'SQ', []) self.assertTrue(dd == dd) ee = DataElement(0x300A00B0, 'SQ', []) self.assertTrue(dd == ee) # Check value e = Dataset() e.PatientName = 'ANON' ee.value = [e] self.assertFalse(dd == ee) # Check tag ee = DataElement(0x01110002, 'SQ', []) self.assertFalse(dd == ee) # Check VR ee = DataElement(0x300A00B0, 'SH', []) self.assertFalse(dd == ee) # Check with dataset dd = DataElement(0x300A00B0, 'SQ', [Dataset()]) dd.value[0].PatientName = 'ANON' ee = DataElement(0x300A00B0, 'SQ', [Dataset()]) ee.value[0].PatientName = 'ANON' self.assertTrue(dd == ee) # Check uneven sequences dd.value.append(Dataset()) dd.value[1].PatientName = 'ANON' self.assertFalse(dd == ee) ee.value.append(Dataset()) ee.value[1].PatientName = 'ANON' self.assertTrue(dd == ee) ee.value.append(Dataset()) ee.value[2].PatientName = 'ANON' self.assertFalse(dd == ee)
def test_equality_sequence_element(self): """DataElement: equality returns correct value for sequence elements""" dd = DataElement(0x300A00B0, 'SQ', []) assert dd == dd ee = DataElement(0x300A00B0, 'SQ', []) assert dd == ee # Check value e = Dataset() e.PatientName = 'ANON' ee.value = [e] assert not dd == ee # Check tag ee = DataElement(0x01110002, 'SQ', []) assert not dd == ee # Check VR ee = DataElement(0x300A00B0, 'SH', []) assert not dd == ee # Check with dataset dd = DataElement(0x300A00B0, 'SQ', [Dataset()]) dd.value[0].PatientName = 'ANON' ee = DataElement(0x300A00B0, 'SQ', [Dataset()]) ee.value[0].PatientName = 'ANON' assert dd == ee # Check uneven sequences dd.value.append(Dataset()) dd.value[1].PatientName = 'ANON' assert not dd == ee ee.value.append(Dataset()) ee.value[1].PatientName = 'ANON' assert dd == ee ee.value.append(Dataset()) ee.value[2].PatientName = 'ANON' assert not dd == ee
def __setattr__(self, name, value): """Intercept any attempts to set a value for an instance attribute. If name is a DICOM keyword, set the corresponding tag and DataElement. Else, set an instance (python) attribute as any other class would do. Parameters ---------- name : str The element keyword for the DataElement you wish to add/change. If `name` is not a DICOM element keyword then this will be the name of the attribute to be added/changed. value The value for the attribute to be added/changed. """ tag = tag_for_keyword(name) if tag is not None: # successfully mapped name to a tag if tag not in self: # don't have this tag yet->create the data_element instance VR = dictionary_VR(tag) data_element = DataElement(tag, VR, value) else: # already have this data_element, just changing its value data_element = self[tag] data_element.value = value # Now have data_element - store it in this dict self[tag] = data_element elif repeater_has_keyword(name): # Check if `name` is repeaters element raise ValueError('{} is a DICOM repeating group ' 'element and must be added using ' 'the add() or add_new() methods.' .format(name)) else: # name not in dicom dictionary - setting a non-dicom instance # attribute # XXX note if user mis-spells a dicom data_element - no error!!! super(Dataset, self).__setattr__(name, value)
def __setattr__(self, name, value): """Intercept any attempts to set a value for an instance attribute. If name is a DICOM keyword, set the corresponding tag and DataElement. Else, set an instance (python) attribute as any other class would do. Parameters ---------- name : str The element keyword for the DataElement you wish to add/change. If `name` is not a DICOM element keyword then this will be the name of the attribute to be added/changed. value The value for the attribute to be added/changed. """ tag = tag_for_keyword(name) if tag is not None: # successfully mapped name to a tag if tag not in self: # don't have this tag yet->create the data_element instance VR = dictionary_VR(tag) data_element = DataElement(tag, VR, value) else: # already have this data_element, just changing its value data_element = self[tag] data_element.value = value # Now have data_element - store it in this dict self[tag] = data_element elif repeater_has_keyword(name): # Check if `name` is repeaters element raise ValueError('{} is a DICOM repeating group ' 'element and must be added using ' 'the add() or add_new() methods.' .format(name)) else: # name not in dicom dictionary - setting a non-dicom instance # attribute # XXX note if user mis-spells a dicom data_element - no error!!! super(Dataset, self).__setattr__(name, value)
def test_write_OD_explicit_little(self): """Test writing elements with VR of OD works correctly. Elements with a VR of 'OD' use the newer explicit VR encoding (see PS3.5 Section 7.1.2). """ # VolumetricCurvePoints bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03\x04\x05\x06\x07' elem = DataElement(0x0070150d, 'OD', bytestring) encoded_elem = self.encode_element(elem, False, True) # Tag pair (0070, 150d): 70 00 0d 15 # VR (OD): \x4f\x44 # Reserved: \x00\x00 # Length (16): \x10\x00\x00\x00 # | Tag | VR | Rsrvd | Length | Value -> ref_bytes = b'\x70\x00\x0d\x15\x4f\x44\x00\x00\x10\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x70\x00\x0d\x15\x4f\x44\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_OL_explicit_little(self): """Test writing elements with VR of OL works correctly. Elements with a VR of 'OL' use the newer explicit VR encoding (see PS3.5 Section 7.1.2). """ # TrackPointIndexList bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03' elem = DataElement(0x00660129, 'OL', bytestring) encoded_elem = self.encode_element(elem, False, True) # Tag pair (0066, 0129): 66 00 29 01 # VR (OL): \x4f\x4c # Reserved: \x00\x00 # Length (12): 0c 00 00 00 # | Tag | VR | Rsrvd | Length | Value -> ref_bytes = b'\x66\x00\x29\x01\x4f\x4c\x00\x00\x0c\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x66\x00\x29\x01\x4f\x4c\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_OD_explicit_little(self): """Test writing elements with VR of OD works correctly. Elements with a VR of 'OD' use the newer explicit VR encoding (see PS3.5 Section 7.1.2). """ # VolumetricCurvePoints bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03\x04\x05\x06\x07' elem = DataElement(0x0070150d, 'OD', bytestring) encoded_elem = self.encode_element(elem, False, True) # Tag pair (0070, 150d): 70 00 0d 15 # VR (OD): \x4f\x44 # Reserved: \x00\x00 # Length (16): \x10\x00\x00\x00 # | Tag | VR | Rsrvd | Length | Value -> ref_bytes = b'\x70\x00\x0d\x15\x4f\x44\x00\x00\x10\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x70\x00\x0d\x15\x4f\x44\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def test_write_OL_explicit_little(self): """Test writing elements with VR of OL works correctly. Elements with a VR of 'OL' use the newer explicit VR encoding (see PS3.5 Section 7.1.2). """ # TrackPointIndexList bytestring = b'\x00\x01\x02\x03\x04\x05\x06\x07' \ b'\x01\x01\x02\x03' elem = DataElement(0x00660129, 'OL', bytestring) encoded_elem = self.encode_element(elem, False, True) # Tag pair (0066, 0129): 66 00 29 01 # VR (OL): \x4f\x4c # Reserved: \x00\x00 # Length (12): 0c 00 00 00 # | Tag | VR | Rsrvd | Length | Value -> ref_bytes = b'\x66\x00\x29\x01\x4f\x4c\x00\x00\x0c\x00\x00\x00' + bytestring self.assertEqual(encoded_elem, ref_bytes) # Empty data elem.value = b'' encoded_elem = self.encode_element(elem, False, True) ref_bytes = b'\x66\x00\x29\x01\x4f\x4c\x00\x00\x00\x00\x00\x00' self.assertEqual(encoded_elem, ref_bytes)
def _correct_ambiguous_vr_element(elem: DataElement, ds: Dataset, is_little_endian: bool) -> DataElement: """Implementation for `correct_ambiguous_vr_element`. See `correct_ambiguous_vr_element` for description. """ # 'OB or OW': 7fe0,0010 PixelData if elem.tag == 0x7fe00010: # Compressed Pixel Data # PS3.5 Annex A.4 # If encapsulated, VR is OB and length is undefined if elem.is_undefined_length: elem.VR = 'OB' elif ds.is_implicit_VR: # Non-compressed Pixel Data - Implicit Little Endian # PS3.5 Annex A1: VR is always OW elem.VR = 'OW' else: # Non-compressed Pixel Data - Explicit VR # PS3.5 Annex A.2: # If BitsAllocated is > 8 then VR shall be OW, # else may be OB or OW. # If we get here, the data has not been written before # or has been converted from Implicit Little Endian, # so we default to OB for BitsAllocated 1 or 8 elem.VR = 'OW' if cast(int, ds.BitsAllocated) > 8 else 'OB' # 'US or SS' and dependent on PixelRepresentation # (0018,9810) Zero Velocity Pixel Value # (0022,1452) Mapped Pixel Value # (0028,0104)/(0028,0105) Smallest/Largest Valid Pixel Value # (0028,0106)/(0028,0107) Smallest/Largest Image Pixel Value # (0028,0108)/(0028,0109) Smallest/Largest Pixel Value in Series # (0028,0110)/(0028,0111) Smallest/Largest Image Pixel Value in Plane # (0028,0120) Pixel Padding Value # (0028,0121) Pixel Padding Range Limit # (0028,1101-1103) Red/Green/Blue Palette Color Lookup Table Descriptor # (0028,3002) LUT Descriptor # (0040,9216)/(0040,9211) Real World Value First/Last Value Mapped # (0060,3004)/(0060,3006) Histogram First/Last Bin Value elif elem.tag in [ 0x00189810, 0x00221452, 0x00280104, 0x00280105, 0x00280106, 0x00280107, 0x00280108, 0x00280109, 0x00280110, 0x00280111, 0x00280120, 0x00280121, 0x00281101, 0x00281102, 0x00281103, 0x00283002, 0x00409211, 0x00409216, 0x00603004, 0x00603006 ]: # US if PixelRepresentation value is 0x0000, else SS # For references, see the list at # https://github.com/darcymason/pydicom/pull/298 # PixelRepresentation is usually set in the root dataset while 'PixelRepresentation' not in ds and ds.parent and ds.parent(): ds = cast(Dataset, ds.parent()) # if no pixel data is present, none if these tags is used, # so we can just ignore a missing PixelRepresentation in this case if ('PixelRepresentation' not in ds and 'PixelData' not in ds or ds.PixelRepresentation == 0): elem.VR = 'US' byte_type = 'H' else: elem.VR = 'SS' byte_type = 'h' if elem.VM == 0: return elem # Need to handle type check for elements with VM > 1 elem_value = (elem.value if elem.VM == 1 else cast( Sequence[Any], elem.value)[0]) if not isinstance(elem_value, int): elem.value = convert_numbers(cast(bytes, elem.value), is_little_endian, byte_type) # 'OB or OW' and dependent on WaveformBitsAllocated # (5400, 0110) Channel Minimum Value # (5400, 0112) Channel Maximum Value # (5400, 100A) Waveform Padding Data # (5400, 1010) Waveform Data elif elem.tag in [0x54000110, 0x54000112, 0x5400100A, 0x54001010]: # If WaveformBitsAllocated is > 8 then OW, otherwise may be # OB or OW. # See PS3.3 C.10.9.1. if ds.is_implicit_VR: elem.VR = 'OW' else: elem.VR = 'OW' if cast(int, ds.WaveformBitsAllocated) > 8 else 'OB' # 'US or OW': 0028,3006 LUTData elif elem.tag == 0x00283006: # First value in LUT Descriptor is how many values in # LUTData, if there's only one value then must be US # As per PS3.3 C.11.1.1.1 if cast(Sequence[int], ds.LUTDescriptor)[0] == 1: elem.VR = 'US' if elem.VM == 0: return elem elem_value = (elem.value if elem.VM == 1 else cast( Sequence[Any], elem.value)[0]) if not isinstance(elem_value, int): elem.value = convert_numbers(cast(bytes, elem.value), is_little_endian, 'H') else: elem.VR = 'OW' # 'OB or OW': 60xx,3000 OverlayData and dependent on Transfer Syntax elif (elem.tag.group in range(0x6000, 0x601F, 2) and elem.tag.elem == 0x3000): # Implicit VR must be OW, explicit VR may be OB or OW # as per PS3.5 Section 8.1.2 and Annex A elem.VR = 'OW' return elem
def _correct_ambiguous_vr_element(elem: DataElement, ds: Dataset, is_little_endian: bool) -> DataElement: """Implementation for `correct_ambiguous_vr_element`. See `correct_ambiguous_vr_element` for description. """ # 'OB or OW': 7fe0,0010 PixelData if elem.tag == 0x7fe00010: # Compressed Pixel Data # PS3.5 Annex A.4 # If encapsulated, VR is OB and length is undefined if elem.is_undefined_length: elem.VR = VR.OB elif ds.is_implicit_VR: # Non-compressed Pixel Data - Implicit Little Endian # PS3.5 Annex A1: VR is always OW elem.VR = VR.OW else: # Non-compressed Pixel Data - Explicit VR # PS3.5 Annex A.2: # If BitsAllocated is > 8 then VR shall be OW, # else may be OB or OW. # If we get here, the data has not been written before # or has been converted from Implicit Little Endian, # so we default to OB for BitsAllocated 1 or 8 elem.VR = VR.OW if cast(int, ds.BitsAllocated) > 8 else VR.OB # 'US or SS' and dependent on PixelRepresentation elif elem.tag in _us_ss_tags: # US if PixelRepresentation value is 0x0000, else SS # For references, see the list at # https://github.com/darcymason/pydicom/pull/298 # PixelRepresentation is usually set in the root dataset while 'PixelRepresentation' not in ds and ds.parent and ds.parent(): ds = cast(Dataset, ds.parent()) # if no pixel data is present, none if these tags is used, # so we can just ignore a missing PixelRepresentation in this case if ('PixelRepresentation' not in ds and 'PixelData' not in ds or ds.PixelRepresentation == 0): elem.VR = VR.US byte_type = 'H' else: elem.VR = VR.SS byte_type = 'h' if elem.VM == 0: return elem # Need to handle type check for elements with VM > 1 elem_value = (elem.value if elem.VM == 1 else cast( Sequence[Any], elem.value)[0]) if not isinstance(elem_value, int): elem.value = convert_numbers(cast(bytes, elem.value), is_little_endian, byte_type) # 'OB or OW' and dependent on WaveformBitsAllocated elif elem.tag in _ob_ow_tags: # If WaveformBitsAllocated is > 8 then OW, otherwise may be # OB or OW. # See PS3.3 C.10.9.1. if ds.is_implicit_VR: elem.VR = VR.OW else: elem.VR = (VR.OW if cast(int, ds.WaveformBitsAllocated) > 8 else VR.OB) # 'US or OW': 0028,3006 LUTData elif elem.tag == 0x00283006: # First value in LUT Descriptor is how many values in # LUTData, if there's only one value then must be US # As per PS3.3 C.11.1.1.1 if cast(Sequence[int], ds.LUTDescriptor)[0] == 1: elem.VR = VR.US if elem.VM == 0: return elem elem_value = (elem.value if elem.VM == 1 else cast( Sequence[Any], elem.value)[0]) if not isinstance(elem_value, int): elem.value = convert_numbers(cast(bytes, elem.value), is_little_endian, 'H') else: elem.VR = VR.OW # 'OB or OW': 60xx,3000 OverlayData and dependent on Transfer Syntax elif elem.tag in _overlay_data_tags: # Implicit VR must be OW, explicit VR may be OB or OW # as per PS3.5 Section 8.1.2 and Annex A elem.VR = VR.OW return elem