Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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')
Example #4
0
 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)
Example #5
0
 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)
Example #6
0
 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'
Example #7
0
    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
Example #8
0
    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)
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
    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)
Example #12
0
    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
Example #13
0
    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)
Example #14
0
    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)
Example #15
0
    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)
Example #16
0
    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))
Example #17
0
    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)
Example #18
0
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
Example #19
0
    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)
Example #20
0
    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')
Example #22
0
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)
Example #23
0
 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)
Example #24
0
    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)
Example #25
0
    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)
Example #26
0
    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
Example #27
0
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
Example #28
0
    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)
Example #29
0
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
Example #31
0
    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)
Example #32
0
    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)
Example #33
0
    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
Example #34
0
    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
Example #35
0
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)
Example #36
0
    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}'")
Example #37
0
    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
Example #38
0
    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)
Example #39
0
    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
Example #40
0
    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
Example #41
0
    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)
Example #42
0
    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)
Example #43
0
 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__())
Example #44
0
 def test_description_group_length(self):
     """Test DataElement.description for Group Length element"""
     elem = DataElement(0x00100000, 'LO', 12345)
     assert 'Group Length' == elem.description()
Example #45
0
 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
Example #46
0
 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
Example #47
0
 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
Example #48
0
 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
Example #49
0
 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)
Example #50
0
 def test_description_group_length(self):
     """Test DataElement.description for Group Length element"""
     elem = DataElement(0x00100000, 'LO', 12345)
     assert elem.description() == 'Group Length'
Example #51
0
 def test_description_unknown(self):
     """Test DataElement.description with an unknown element"""
     elem = DataElement(0x00000004, 'LO', 12345)
     assert elem.description() == ''