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_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_str_no_vr(self): """Test DataElement.__str__ output with no VR""" elem = DataElement(0x00100010, 'PN', 'ANON') assert "(0010, 0010) Patient's Name" in str(elem) assert "PN: 'ANON'" in str(elem) elem.showVR = False assert "(0010, 0010) Patient's Name" in str(elem) assert 'PN' not in str(elem)
def test_equality_class_members(self): """Test equality is correct when ignored class members differ.""" dd = DataElement(0x00100010, 'PN', 'ANON') dd.showVR = False dd.file_tell = 10 dd.maxBytesToDisplay = 0 dd.descripWidth = 0 ee = DataElement(0x00100010, 'PN', 'ANON') self.assertTrue(dd == ee)
def test_description_unknown_private(self): """Test DataElement.description with an unknown private element""" elem = DataElement(0x00110010, 'LO', 12345) elem.private_creator = 'TEST' assert elem.description() == 'Private tag data' elem = DataElement(0x00110F00, 'LO', 12345) assert elem.tag.is_private assert not hasattr(elem, 'private_creator') assert elem.description() == 'Private tag data'
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 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 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_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_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 __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 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 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 __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 apply_rules(self, rules: RuleSet, dataset: Dataset) -> Dataset: """Apply rules to each element in dataset, recursing into sequence elements This creates a deep copy of the input dataset. Except for PixelData, which will be a reference. PixelData is not copied because it can take up a lot of memory """ deidentified = Dataset() pixel_data_tag = 0x7FE00010 for element in dataset: if element.tag == pixel_data_tag: deidentified.add( element) # add pixel data as reference to save mem elif element.VR == VRs.Sequence.short_name: # recurse into sequences deidentified.add( DataElement( tag=element.tag, VR=element.VR, value=Sequence([ self.apply_rules(rules, sub_dataset) for sub_dataset in element ]), )) elif rule := rules.get_rule(element): if type(rule.operation) == Remove: continue # special handling. should be removed, do not add try: new = rule.operation.apply(element, dataset) deidentified.add(new) except ElementShouldBeRemoved: # Operators signals removal continue else: # no rule found. Just copy the element over deidentified.add( DataElement(tag=element.tag, VR=element.VR, value=element.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 get_idis_code_sequence(ruleset_names: List[str]) -> DataElement: """Create the element (0012,0064) - DeIdentificationMethodCodeSequence This sequence specifies what kind of anonymization has been performed. It is quite free form. This implementation uses the following format: DeIdentificationMethodCodeSequence will contain the code of each official DICOM deidentification profile that was used. Codes are taken from Table CID 7050 Parameters ---------- ruleset_names: List[str] list of names as defined in nema.E1_1_METHOD_INFO Returns ------- DataElement Sequence element (0012,0064) - DeIdentificationMethodCodeSequence. Will contain the code of each official DICOM deidentification profile passed Raises ------ ValueError When any name in ruleset_names is not recognized as a standard DICOM rule set """ code_per_name = {x.full_name: x for x in E1_1_METHOD_INFO} codes = [] for name in ruleset_names: try: # check whether we know this ruleset as a standard DICOM one ruleset_info = code_per_name[name] except KeyError: raise ValueError( f'Could not find the code for rule set "{name}". I do' f" not know this ruleset") # Create the required designation for this dataset code_dataset = Dataset() code_dataset.CodeValue = ruleset_info.code code_dataset.CodingSchemeDesignator = "DCM" code_dataset.CodeMeaning = ruleset_info.full_name codes.append(code_dataset) element = DataElement( tag=Tag("DeidentificationMethodCodeSequence"), VR=VRs.Sequence.short_name, value=Sequence(codes), ) return element
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 testEqualityInheritance(self): """DataElement: equality returns correct value for subclasses""" class DataElementPlus(DataElement): pass dd = DataElement(0x00100010, 'PN', 'ANON') ee = DataElementPlus(0x00100010, 'PN', 'ANON') self.assertTrue(ee == ee) self.assertTrue(dd == ee) self.assertTrue(ee == dd) ee = DataElementPlus(0x00100010, 'PN', 'ANONY') self.assertFalse(dd == ee) self.assertFalse(ee == dd)
def test_overlay(self): """Test correcting OverlayData""" # Implicit VR must be 'OW' ref_ds = Dataset() ref_ds.is_implicit_VR = True ref_ds.add(DataElement(0x60003000, 'OB or OW', b'\x00')) ref_ds.add(DataElement(0x601E3000, 'OB or OW', b'\x00')) ds = correct_ambiguous_vr(deepcopy(ref_ds), True) self.assertTrue(ds[0x60003000].VR == 'OW') self.assertTrue(ds[0x601E3000].VR == 'OW') self.assertTrue(ref_ds[0x60003000].VR == 'OB or OW') self.assertTrue(ref_ds[0x601E3000].VR == 'OB or OW') # Explicit VR may be 'OB' or 'OW' (leave unchanged) ref_ds.is_implicit_VR = False ds = correct_ambiguous_vr(deepcopy(ref_ds), True) self.assertTrue(ds[0x60003000].VR == 'OB or OW') self.assertTrue(ref_ds[0x60003000].VR == 'OB or OW') # Missing is_implicit_VR (leave unchanged) del ref_ds.is_implicit_VR ds = correct_ambiguous_vr(deepcopy(ref_ds), True) self.assertTrue(ds[0x60003000].VR == 'OB or OW') self.assertTrue(ref_ds[0x60003000].VR == 'OB or OW')
def get_deidentification_method( method: str = DEFAULT_DEIDENTIFICATION_METHOD, ) -> DataElement: """Create the element (0012,0063) - DeIdentificationMethod A string description of the deidentification method used Parameters ---------- method: str, optional String representing the deidentification method used. Defaults to 'idiscore <version>' """ return DataElement(tag=Tag("DeidentificationMethod"), VR=VRs.LongString.short_name, value=method)
def test_empty_AT(self): """Write empty AT correctly..........""" # Was issue 74 data_elem = DataElement(0x00280009, "AT", []) expected = hex2bytes(( " 28 00 09 00" # (0028,0009) Frame Increment Pointer " 00 00 00 00" # length 0 )) write_data_element(self.f1, data_elem) got = self.f1.parent.getvalue() msg = ("Did not write zero-length AT value correctly. " "Expected %r, got %r") % (bytes2hex(expected), bytes2hex(got)) msg = "%r %r" % (type(expected), type(got)) msg = "'%r' '%r'" % (expected, got) self.assertEqual(expected, got, msg)
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_equality_inheritance(self): """DataElement: equality returns correct value for subclasses""" class DataElementPlus(DataElement): pass dd = DataElement(0x00100010, 'PN', 'ANON') ee = DataElementPlus(0x00100010, 'PN', 'ANON') assert ee == ee assert dd == ee assert ee == dd ee = DataElementPlus(0x00100010, 'PN', 'ANONY') assert not dd == ee assert not ee == dd
def convert_to_dataset(json_obj): ds = Dataset() for key in json_obj: obj = json_obj[key] #print "*" , key, obj val = '' if 'Value' in obj: val = obj['Value'] if obj['vr'] == 'SQ' and val != '': child_ds_list = [] for val_item in val: child_ds = convert_to_dataset(val_item) child_ds_list.append(child_ds) #print (child_ds_list) #print "Creating SQ Element....." delem = DataElement(key, obj['vr'], child_ds_list) ds.add(delem) else: if val != '': val = val[0] delem = DataElement(key, obj['vr'], val) ds.add(delem) #print delem return ds
def test_data_element_factory_init(): """Check different init methods """ # factory casts tag init argument to Tag(). Verify that this works. assert type(DataElementFactory().tag) == BaseTag assert type(DataElement(tag="Modality", VR="SH", value="kees").tag) == BaseTag assert type(DataElementFactory(tag="Modality").tag) == BaseTag assert type(DataElementFactory(tag=(0x0010, 0x0020)).tag) == BaseTag # For unknown tags, just give a default VR. Assuming the default position # for users of DataElementFactory will be 'Don't care, just give me the Element' assert DataElementFactory(tag=(0xee30, 0xf120)).VR == VRs.LongString.short_name assert DataElementFactory.create(tag=(0xee30, 0xf120), value=100).VR == VRs.LongString.short_name
def subfix_UpdateOrInsertCodeAttribute(seqelem: DataElement, index: int, kw: str, value: str) -> str: text_fun = lambda ds, att: '{}: {}\t'.format(att, ds[att]) out_msg = '' if kw in seqelem.value[index]: out_msg = " {} modified <{}> -> <{}>".format( kw, seqelem.value[index][kw].value, value) seqelem.value[index][kw].value = value else: out_msg = "{} = <{}> was added".format(kw, value) newtag = Dictionary.tag_for_keyword(kw) newvr = Dictionary.dictionary_VR(newtag) elem = DataElement(newtag, newvr, value) seqelem.value[index].add(elem) return out_msg
def test_write_invalid_length_non_ascii_text( self, enforce_writing_invalid_values): fp = DicomBytesIO() ds = Dataset() ds.is_implicit_VR = True ds.is_little_endian = True ds.SpecificCharacterSet = "ISO_IR 192" # UTF-8 # the string length is 9, so constructing the data element # is possible ds.add(DataElement(0x00080050, "SH", "洪^吉洞=홍^길동")) # encoding the element during writing shall fail, # as the encoded length is 21, while only 16 bytes are allowed for SH msg = r"The value length \(21\) exceeds the maximum length of 16 *" with pytest.raises(ValueError, match=msg): ds.save_as(fp)
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 test_code_sequence(self): """Test utils.codify.code_dataelem""" # ControlPointSequence elem = DataElement(0x300A0111, 'SQ', []) elem.value.append(Dataset()) elem[0].PatientID = '1234' out = "\n" out += "# Control Point Sequence\n" out += "cp_sequence = Sequence()\n" out += "ds.ControlPointSequence = cp_sequence\n" out += "\n" out += "# Control Point Sequence: Control Point 1\n" out += "cp1 = Dataset()\n" out += "cp1.PatientID = '1234'\n" out += "cp_sequence.append(cp1)" assert code_dataelem(elem) == out
def write_PN(fp: DicomIO, elem: DataElement, encodings: Optional[List[str]] = None) -> None: if not encodings: encodings = [default_encoding] val: List[PersonName] if elem.VM == 1: val = [cast(PersonName, elem.value)] else: val = cast(List[PersonName], elem.value) enc = b'\\'.join([elem.encode(encodings) for elem in val]) if len(enc) % 2 != 0: enc += b' ' fp.write(enc)
def apply(self, element: DataElement, dataset: Optional[Dataset] = None) -> DataElement: vr = VRs.short_name_to_vr(element.VR) if element.tag.is_private: return self.clean_private(element, dataset) elif vr in VRs.date_like: return self.clean_date_time(element, dataset) elif vr in VRs.string_like: return DataElement(tag=element.tag, VR=element.VR, value="CLEANED") elif vr == VRs.Sequence: return copy(element) # sequence elements are processed later. pass else: # too difficult. Cannot do it raise ValueError( f"Cannot clean {element}. I don't know how to handle " f"tags of type '{vr}'")
def test_long_specific_char_set(self): """Test that specific character set is read even if it is longer than defer_size""" ds = Dataset() long_specific_char_set_value = ['ISO 2022IR 100'] * 9 ds.add(DataElement(0x00080005, 'CS', long_specific_char_set_value)) msg = (r"Unknown encoding 'ISO 2022IR 100' - using default encoding " r"instead") fp = BytesIO() file_ds = FileDataset(fp, ds) with pytest.warns(UserWarning, match=msg): file_ds.save_as(fp, write_like_original=True) with pytest.warns(UserWarning, match=msg): ds = dcmread(fp, defer_size=65, force=True) assert long_specific_char_set_value == ds[0x00080005].value
def add_field(self, field, value): """add a field to the dicom. If it's already present, update the value. """ value = parse_value(item=self.lookup, value=value, field=field, dicom=self.dicom) # Assume we don't want to add an empty value if value is not None: # If provided a field object, create based on keyword or tag identifer name = field if isinstance(field, DicomField): name = field.element.keyword or field.stripped_tag # Generate a tag item, add if it's a name found in the dicom dictionary tag = get_tag(name) # Second try, it might be a private (or other numerical) string identifier if not tag: tag = add_tag(name) if tag: uid = getattr(field, "uid", None) or str(tag["tag"]) # For a replacement, this is likely if uid in self.fields: element = self.fields[uid] # Nested fields while not hasattr(element, "value"): element = element.element element.value = value else: element = DataElement(tag["tag"], tag["VR"], value) self.dicom.add(element) self.fields[uid] = DicomField(element, name, uid) else: bot.warning("Cannot find tag for field %s, skipping." % name)
def testEqualityNoSequence(self): """Dataset: equality returns correct value with simple dataset""" # Test empty dataset assert Dataset() == Dataset() d = Dataset() d.SOPInstanceUID = '1.2.3.4' d.PatientName = 'Test' assert d == d e = Dataset() e.PatientName = 'Test' e.SOPInstanceUID = '1.2.3.4' assert d == e e.SOPInstanceUID = '1.2.3.5' assert not d == e # Check VR del e.SOPInstanceUID e.add(DataElement(0x00080018, 'PN', '1.2.3.4')) assert not d == e # Check Tag del e.SOPInstanceUID e.StudyInstanceUID = '1.2.3.4' assert not d == e # Check missing Element in self e.SOPInstanceUID = '1.2.3.4' assert not d == e # Check missing Element in other d = Dataset() d.SOPInstanceUID = '1.2.3.4' d.StudyInstanceUID = '1.2.3.4.5' e = Dataset() e.SOPInstanceUID = '1.2.3.4' assert not d == e
def add_new(self, tag, VR, value): """Add a DataElement to the Dataset. Parameters ---------- tag The DICOM (group, element) tag in any form accepted by pydicom.tag.Tag such as [0x0010, 0x0010], (0x10, 0x10), 0x00100010, etc. VR : str The 2 character DICOM value representation (see DICOM standard part 5, Section 6.2). value The value of the data element. One of the following: * a single string or number * a list or tuple with all strings or all numbers * a multi-value string with backslash separator * for a sequence DataElement, an empty list or list of Dataset """ data_element = DataElement(tag, VR, value) # use data_element.tag since DataElement verified it self[data_element.tag] = data_element
def testEqualityNoSequence(self): """Dataset: equality returns correct value with simple dataset""" d = Dataset() d.SOPInstanceUID = '1.2.3.4' d.PatientName = 'Test' self.assertTrue(d == d) e = Dataset() e.PatientName = 'Test' e.SOPInstanceUID = '1.2.3.4' self.assertTrue(d == e) e.SOPInstanceUID = '1.2.3.5' self.assertFalse(d == e) # Check VR del e.SOPInstanceUID e.add(DataElement(0x00080018, 'PN', '1.2.3.4')) self.assertFalse(d == e) # Check Tag del e.SOPInstanceUID e.StudyInstanceUID = '1.2.3.4' self.assertFalse(d == e) # Check missing Element in self e.SOPInstanceUID = '1.2.3.4' self.assertFalse(d == e) # Check missing Element in other d = Dataset() d.SOPInstanceUID = '1.2.3.4' d.StudyInstanceUID = '1.2.3.4.5' e = Dataset() e.SOPInstanceUID = '1.2.3.4' self.assertFalse(d == e)
def test_repeater_str(self): """Test a repeater group element displays the element name.""" elem = DataElement(0x60023000, 'OB', b'\x00') self.assertTrue('Overlay Data' in elem.__str__())
def test_description_group_length(self): """Test DataElement.description for Group Length element""" elem = DataElement(0x00100000, 'LO', 12345) assert 'Group Length' == elem.description()
def test_backslash(self): """DataElement: String with '\\' sets multi-valued data_element.""" data_element = DataElement((1, 2), "DS", r"42.1\42.2\42.3") assert 3 == data_element.VM
def test_repval_strange_type(self): """Test DataElement.repval doesn't break with bad types""" elem = DataElement(0x00020001, 'OB', 0) assert len(elem.repval) < 100
def test_repval_large_vm(self): """Test DataElement.repval doesn't return a huge string for a large vm""" elem = DataElement(0x00080054, 'AE', 'a\\' * 1000 + 'a') assert len(elem.repval) < 100
def test_repval_large_elem(self): """Test DataElement.repval doesn't return a huge string for a large value""" elem = DataElement(0x00820003, 'UT', 'a' * 1000) assert len(elem.repval) < 100
def test_repval_original_string(self): """Test DataElement.repval when original_string is present""" elem = DataElement(0x00100010, 'PN', 'ANON') elem.original_string = 'foo' assert "(0010, 0010) Patient's Name" in str(elem) assert "PN: 'foo'" in str(elem)
def test_description_group_length(self): """Test DataElement.description for Group Length element""" elem = DataElement(0x00100000, 'LO', 12345) assert elem.description() == 'Group Length'
def test_description_unknown(self): """Test DataElement.description with an unknown element""" elem = DataElement(0x00000004, 'LO', 12345) assert elem.description() == ''