def test_read_bad_value_in_VR_enforce_valid_value(self): pydicom.config.enforce_valid_values = True # found a conversion assert '1A' == convert_value('SH', self.tag) # invalid literal for base 10 with pytest.raises(ValueError): convert_value('IS', self.tag)
def test_read_bad_value_in_VR_enforce_valid_value(self, enforce_valid_values): # found a conversion assert "1A" == convert_value("SH", self.tag) # invalid literal for base 10 with pytest.raises(ValueError): convert_value("IS", self.tag)
def test_read_bad_value_in_VR_default(self, allow_invalid_values): # found a conversion assert "1A" == convert_value("SH", self.tag) # converted with fallback vr "SH" assert "1A" == convert_value("IS", self.tag) pydicom.values.convert_retry_VR_order = ["FL", "UL"] # no fallback VR succeeded, returned original value untranslated assert b"1A" == convert_value("IS", self.tag)
def test_read_bad_value_in_VR_default(self): # found a conversion assert '1A' == convert_value('SH', self.tag) # converted with fallback vr "SH" assert '1A' == convert_value('IS', self.tag) pydicom.values.convert_retry_VR_order = ['FL', 'UL'] # no fallback VR succeeded, returned original value untranslated assert b'1A' == convert_value('IS', self.tag)
def testReadBadValueInVRDefault(self): # found a conversion self.assertEqual('1A', convert_value('SH', self.tag)) # converted with fallback vr "SH" self.assertEqual('1A', convert_value('IS', self.tag)) pydicom.values.convert_retry_VR_order = ['FL', 'UL'] # no fallback VR succeeded, returned original value untranslated self.assertEqual(b'1A', convert_value('IS', self.tag))
def test_convert_value_raises(self): """Test convert_value raises exception if unsupported VR""" converter_func = converters['PN'] del converters['PN'] with pytest.raises(NotImplementedError, match="Unknown Value Representation 'PN'"): convert_value('PN', None) # Fix converters converters['PN'] = converter_func assert 'PN' in converters
def fix_mismatch_callback(raw_elem, **kwargs): try: values.convert_value(raw_elem.VR, raw_elem) except ValueError: for vr in kwargs['with_VRs']: try: values.convert_value(vr, raw_elem) except ValueError: pass else: raw_elem = raw_elem._replace(VR=vr) return raw_elem
def fix_mismatch_callback(raw_elem, **kwargs): try: values.convert_value(raw_elem.VR, raw_elem) except TypeError: for vr in kwargs['with_VRs']: try: values.convert_value(vr, raw_elem) except TypeError: pass else: raw_elem = raw_elem._replace(VR=vr) break # i want to exit immediately after change is applied return raw_elem
def testEmptyItem(self): """Read sequence with a single empty item...............................""" # This is fix for issue 27 hexstr = ( "08 00 32 10" # (0008, 1032) SQ "Procedure Code Sequence" " 08 00 00 00" # length 8 " fe ff 00 e0" # (fffe, e000) Item Tag " 00 00 00 00" # length = 0 ) + ( # --------------- end of Sequence " 08 00 3e 10" # (0008, 103e) LO "Series Description" nopep8 " 0c 00 00 00" # length nopep8 " 52 20 41 44 44 20 56 49 45 57 53 20" # value nopep8 ) # "\x08\x00\x32\x10\x08\x00\x00\x00\xfe\xff\x00\xe0\x00\x00\x00\x00" # from issue 27, procedure code sequence (0008,1032) # hexstr += "\x08\x00\x3e\x10\x0c\x00\x00\x00\x52\x20\x41\x44\x44\x20\x56\x49\x45\x57\x53\x20" # data element following fp = BytesIO(hex2bytes(hexstr)) gen = data_element_generator(fp, is_implicit_VR=True, is_little_endian=True) raw_seq = next(gen) seq = convert_value("SQ", raw_seq) self.assertTrue(isinstance(seq, Sequence), "Did not get Sequence, got type {0}".format(str(type(seq)))) self.assertTrue(len(seq) == 1, "Expected Sequence with single (empty) item, got {0:d} item(s)".format(len(seq))) self.assertTrue(len(seq[0]) == 0, "Expected the sequence item (dataset) to be empty") elem2 = next(gen) self.assertEqual(elem2.tag, 0x0008103e, "Expected a data element after empty sequence item")
def testEmptyItem(self): """Read sequence with a single empty item...""" # This is fix for issue 27 hexstr = ( "08 00 32 10" # (0008, 1032) SQ "Procedure Code Sequence" " 08 00 00 00" # length 8 " fe ff 00 e0" # (fffe, e000) Item Tag " 00 00 00 00" # length = 0 ) + ( # --------------- end of Sequence " 08 00 3e 10" # (0008, 103e) LO "Series Description" nopep8 " 0c 00 00 00" # length nopep8 " 52 20 41 44 44 20 56 49 45 57 53 20" # value nopep8 ) # "\x08\x00\x32\x10\x08\x00\x00\x00\xfe\xff\x00\xe0\x00\x00\x00\x00" # from issue 27, procedure code sequence (0008,1032) # hexstr += "\x08\x00\x3e\x10\x0c\x00\x00\x00\x52\x20 # \x41\x44\x44\x20\x56\x49\x45\x57\x53\x20" # data element following fp = BytesIO(hex2bytes(hexstr)) gen = data_element_generator(fp, is_implicit_VR=True, is_little_endian=True) raw_seq = next(gen) seq = convert_value("SQ", raw_seq) assert isinstance(seq, Sequence) assert 1 == len(seq) assert 0 == len(seq[0]) elem2 = next(gen) assert 0x0008103e == elem2.tag
def DataElement_from_raw(raw_data_element, encoding=None): """Return a DataElement from a RawDataElement""" from pydicom.values import convert_value # XXX buried here to avoid circular import filereader->Dataset->convert_value->filereader (for SQ parsing) raw = raw_data_element # If user has hooked into conversion of raw values, call his/her routine if config.data_element_callback: raw = config.data_element_callback( raw_data_element, **config.data_element_callback_kwargs) VR = raw.VR if VR is None: # Can be if was implicit VR try: VR = dictionaryVR(raw.tag) except KeyError: if raw.tag.is_private: VR = 'OB' # just read the bytes, no way to know what they mean elif raw.tag.element == 0: # group length tag implied in versions < 3.0 VR = 'UL' else: raise KeyError( "Unknown DICOM tag {0:s} - can't look up VR".format( str(raw.tag))) try: value = convert_value(VR, raw, encoding) except NotImplementedError as e: raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag)) return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF, already_converted=True)
def fix_mismatch_callback(raw_elem: "RawDataElement", **kwargs: Any) -> "RawDataElement": if raw_elem.VR is None: return raw_elem try: values.convert_value(raw_elem.VR, raw_elem) except ValueError: for vr in kwargs['with_VRs']: try: values.convert_value(vr, raw_elem) except ValueError: pass else: raw_elem = raw_elem._replace(VR=vr) return raw_elem
def DataElement_from_raw(raw_data_element, encoding=None): """Return a DataElement from a RawDataElement""" from pydicom.values import convert_value # XXX buried here to avoid circular import filereader->Dataset->convert_value->filereader (for SQ parsing) raw = raw_data_element # If user has hooked into conversion of raw values, call his/her routine if config.data_element_callback: raw = config.data_element_callback(raw_data_element, **config.data_element_callback_kwargs) VR = raw.VR if VR is None: # Can be if was implicit VR try: VR = dictionaryVR(raw.tag) except KeyError: if raw.tag.is_private: VR = 'OB' # just read the bytes, no way to know what they mean elif raw.tag.element == 0: # group length tag implied in versions < 3.0 VR = 'UL' else: raise KeyError("Unknown DICOM tag {0:s} - can't look up VR".format(str(raw.tag))) try: value = convert_value(VR, raw, encoding) except NotImplementedError as e: raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag)) return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF, already_converted=True)
def DataElement_from_raw(raw_data_element, encoding=None): """Return a :class:`DataElement` created from `raw_data_element`. Parameters ---------- raw_data_element : RawDataElement namedtuple The raw data to convert to a :class:`DataElement`. encoding : str, optional The character encoding of the raw data. Returns ------- DataElement """ # XXX buried here to avoid circular import # filereader->Dataset->convert_value->filereader # (for SQ parsing) if in_py2: encoding = encoding or default_encoding from pydicom.values import convert_value raw = raw_data_element # If user has hooked into conversion of raw values, call his/her routine if config.data_element_callback: data_elem = config.data_element_callback raw = data_elem(raw_data_element, **config.data_element_callback_kwargs) VR = raw.VR if VR is None: # Can be if was implicit VR try: VR = dictionary_VR(raw.tag) except KeyError: # just read the bytes, no way to know what they mean if raw.tag.is_private: # for VR for private tags see PS3.5, 6.2.2 if raw.tag.is_private_creator: VR = 'LO' else: VR = 'UN' # group length tag implied in versions < 3.0 elif raw.tag.element == 0: VR = 'UL' else: msg = "Unknown DICOM tag {0:s}".format(str(raw.tag)) msg += " can't look up VR" raise KeyError(msg) try: value = convert_value(VR, raw, encoding) except NotImplementedError as e: raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag)) if raw.tag in _LUT_DESCRIPTOR_TAGS and value[0] < 0: # We only fix the first value as the third value is 8 or 16 value[0] += 65536 return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF, already_converted=True)
def fix_mismatch_callback(raw_elem, **kwargs): try: if raw_elem.VR: values.convert_value(raw_elem.VR, raw_elem) except TypeError as err: logging.error(err) except BaseException as err: for vr in kwargs['with_VRs']: try: values.convert_value(vr, raw_elem) except ValueError: pass except TypeError: continue else: raw_elem = raw_elem._replace(VR=vr) return raw_elem
def DataElement_from_raw(raw_data_element, encoding=None): """Return a DataElement created from the data in `raw_data_element`. Parameters ---------- raw_data_element : RawDataElement namedtuple The raw data to convert to a DataElement encoding : str The encoding of the raw data Returns ------- pydicom.dataelem.DataElement """ # XXX buried here to avoid circular import # filereader->Dataset->convert_value->filereader # (for SQ parsing) if in_py2: encoding = encoding or default_encoding from pydicom.values import convert_value raw = raw_data_element # If user has hooked into conversion of raw values, call his/her routine if config.data_element_callback: data_elem = config.data_element_callback raw = data_elem(raw_data_element, **config.data_element_callback_kwargs) VR = raw.VR if VR is None: # Can be if was implicit VR try: VR = dictionary_VR(raw.tag) except KeyError: # just read the bytes, no way to know what they mean if raw.tag.is_private: VR = 'OB' # group length tag implied in versions < 3.0 elif raw.tag.element == 0: VR = 'UL' else: msg = "Unknown DICOM tag {0:s}".format(str(raw.tag)) msg += " can't look up VR" raise KeyError(msg) try: value = convert_value(VR, raw, encoding) except NotImplementedError as e: raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag)) return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF, already_converted=True)
def DataElement_from_raw(raw_data_element, encoding=None): """Return a DataElement created from the data in `raw_data_element`. Parameters ---------- raw_data_element : RawDataElement namedtuple The raw data to convert to a DataElement encoding : str The encoding of the raw data Returns ------- pydicom.dataelem.DataElement """ # XXX buried here to avoid circular import # filereader->Dataset->convert_value->filereader # (for SQ parsing) if in_py2: encoding = encoding or default_encoding from pydicom.values import convert_value raw = raw_data_element # If user has hooked into conversion of raw values, call his/her routine if config.data_element_callback: data_elem = config.data_element_callback raw = data_elem(raw_data_element, **config.data_element_callback_kwargs) VR = raw.VR if VR is None: # Can be if was implicit VR try: VR = dictionary_VR(raw.tag) except KeyError: # just read the bytes, no way to know what they mean if raw.tag.is_private: # for VR for private tags see PS3.5, 6.2.2 if raw.tag.is_private_creator: VR = 'LO' else: VR = 'UN' # group length tag implied in versions < 3.0 elif raw.tag.element == 0: VR = 'UL' else: msg = "Unknown DICOM tag {0:s}".format(str(raw.tag)) msg += " can't look up VR" raise KeyError(msg) try: value = convert_value(VR, raw, encoding) except NotImplementedError as e: raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag)) return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF, already_converted=True)
def testImplVRBigEndian_ExplicitLengthSeq(self): """Raw read: ImplVR BigEndian SQ with explicit lengths...""" # Create a fictional sequence with bytes directly, # similar to PS 3.5-2008 Table 7.5-1 p42 hexstr = ( "30 0a 00 B0" # (300a, 00b0) Beam Sequence " 00 00 00 40" # length " ff fe e0 00" # (fffe, e000) Item Tag " 00 00 00 18" # Item (dataset) Length " 30 0a 00 c0" # (300A, 00C0) Beam Number " 00 00 00 02" # length " 31 20" # value '1 ' " 30 0a 00 c2" # (300A, 00C2) Beam Name " 00 00 00 06" # length " 42 65 61 6d 20 31" # value 'Beam 1' # ------------- " ff fe e0 00" # (fffe, e000) Item Tag " 00 00 00 18" # Item (dataset) Length " 30 0a 00 c0" # (300A, 00C0) Beam Number " 00 00 00 02" # length " 32 20" # value '2 ' " 30 0a 00 c2" # (300A, 00C2) Beam Name " 00 00 00 06" # length " 42 65 61 6d 20 32" # value 'Beam 2' ) infile = BytesIO(hex2bytes(hexstr)) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=False) raw_seq = next(de_gen) seq = convert_value("SQ", raw_seq) # The sequence is parsed, but only into raw data elements. # They will be converted when asked for. Check some: got = seq[0].BeamNumber self.assertTrue(got == 1, "Expected Beam Number 1, got {0!r}".format(got)) got = seq[1].BeamName self.assertTrue(got == 'Beam 2', "Expected Beam Name 'Beam 2', got {0:s}".format(got))
def testImplVRLittleEndian_ExplicitLengthSeq(self): """Raw read: ImplVR Little Endian SQ with explicit lengths...""" # Create a fictional sequence with bytes directly, # similar to PS 3.5-2008 Table 7.5-1 p42 hexstr = ( "0a 30 B0 00" # (300a, 00b0) Beam Sequence " 40 00 00 00" # length " fe ff 00 e0" # (fffe, e000) Item Tag " 18 00 00 00" # Item (dataset) Length " 0a 30 c0 00" # (300A, 00C0) Beam Number " 02 00 00 00" # length " 31 20" # value '1 ' " 0a 30 c2 00" # (300A, 00C2) Beam Name " 06 00 00 00" # length " 42 65 61 6d 20 31" # value 'Beam 1' # ------------- " fe ff 00 e0" # (fffe, e000) Item Tag " 18 00 00 00" # Item (dataset) Length " 0a 30 c0 00" # (300A, 00C0) Beam Number " 02 00 00 00" # length " 32 20" # value '2 ' " 0a 30 c2 00" # (300A, 00C2) Beam Name " 06 00 00 00" # length " 42 65 61 6d 20 32" # value 'Beam 2' ) infile = BytesIO(hex2bytes(hexstr)) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) raw_seq = next(de_gen) seq = convert_value("SQ", raw_seq) # The sequence is parsed, but only into raw data elements. # They will be converted when asked for. Check some: assert 1 == seq[0].BeamNumber assert 'Beam 2' == seq[1].BeamName
def testEmptyItem(self): """Read sequence with a single empty item...""" # This is fix for issue 27 hexstr = ( "08 00 32 10" # (0008, 1032) SQ "Procedure Code Sequence" " 08 00 00 00" # length 8 " fe ff 00 e0" # (fffe, e000) Item Tag " 00 00 00 00" # length = 0 ) + ( # --------------- end of Sequence " 08 00 3e 10" # (0008, 103e) LO "Series Description" nopep8 " 0c 00 00 00" # length nopep8 " 52 20 41 44 44 20 56 49 45 57 53 20" # value nopep8 ) # "\x08\x00\x32\x10\x08\x00\x00\x00\xfe\xff\x00\xe0\x00\x00\x00\x00" # from issue 27, procedure code sequence (0008,1032) # hexstr += "\x08\x00\x3e\x10\x0c\x00\x00\x00\x52\x20 # \x41\x44\x44\x20\x56\x49\x45\x57\x53\x20" # data element following fp = BytesIO(hex2bytes(hexstr)) gen = data_element_generator(fp, is_implicit_VR=True, is_little_endian=True) raw_seq = next(gen) seq = convert_value("SQ", raw_seq) got_type = "got type {0}".format(str(type(seq))) self.assertTrue(isinstance(seq, Sequence), "Did not get Sequence, %s" % got_type) expected = "Expected Sequence with single (empty) item" got = "got {0:d} item(s)".format(len(seq)) self.assertTrue(len(seq) == 1, "%s, %s" % (expected, got)) msg = "Expected the sequence item (dataset) to be empty" self.assertTrue(len(seq[0]) == 0, msg) elem2 = next(gen) self.assertEqual(elem2.tag, 0x0008103e, "Expected a data element after empty sequence item")
def DataElement_from_raw(raw_data_element: RawDataElement, encoding: Optional[List[str]] = None) -> DataElement: """Return a :class:`DataElement` created from `raw_data_element`. Parameters ---------- raw_data_element : RawDataElement The raw data to convert to a :class:`DataElement`. encoding : list of str, optional The character encoding of the raw data. Returns ------- DataElement Raises ------ KeyError If `raw_data_element` belongs to an unknown non-private tag and `config.enforce_valid_values` is set. """ # XXX buried here to avoid circular import # filereader->Dataset->convert_value->filereader # (for SQ parsing) from pydicom.values import convert_value raw = raw_data_element # If user has hooked into conversion of raw values, call his/her routine if config.data_element_callback: raw = config.data_element_callback( raw_data_element, encoding=encoding, **config.data_element_callback_kwargs) VR = raw.VR if VR is None: # Can be if was implicit VR try: VR = dictionary_VR(raw.tag) except KeyError: # just read the bytes, no way to know what they mean if raw.tag.is_private: # for VR for private tags see PS3.5, 6.2.2 if raw.tag.is_private_creator: VR = 'LO' else: VR = 'UN' # group length tag implied in versions < 3.0 elif raw.tag.element == 0: VR = 'UL' else: msg = "Unknown DICOM tag {0:s}".format(str(raw.tag)) if config.enforce_valid_values: msg += " can't look up VR" raise KeyError(msg) else: VR = 'UN' msg += " - setting VR to 'UN'" warnings.warn(msg) elif (VR == 'UN' and not raw.tag.is_private and config.replace_un_with_known_vr): # handle rare case of incorrectly set 'UN' in explicit encoding # see also DataElement.__init__() if (raw.length == 0xffffffff or raw.value is None or len(raw.value) < 0xffff): try: VR = dictionary_VR(raw.tag) except KeyError: pass try: value = convert_value(VR, raw, encoding) except NotImplementedError as e: raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag)) if raw.tag in _LUT_DESCRIPTOR_TAGS and value: # We only fix the first value as the third value is 8 or 16 try: if value[0] < 0: value[0] += 65536 except TypeError: pass return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF, already_converted=True)
def testReadBadValueInVREnforceValidValue(self): pydicom.config.enforce_valid_values = True # found a conversion self.assertEqual('1A', convert_value('SH', self.tag)) # invalid literal for base 10 self.assertRaises(ValueError, convert_value, 'IS', self.tag)
def DataElement_from_raw(raw_data_element: RawDataElement, encoding: Optional[Union[ str, MutableSequence[str]]] = None, dataset: Optional["Dataset"] = None) -> DataElement: """Return a :class:`DataElement` created from `raw_data_element`. Parameters ---------- raw_data_element : RawDataElement The raw data to convert to a :class:`DataElement`. encoding : str or list of str, optional The character encoding of the raw data. dataset : Dataset, optional If given, used to resolve the VR for known private tags. Returns ------- DataElement Raises ------ KeyError If `raw_data_element` belongs to an unknown non-private tag and :attr:`~pydicom.config.settings.reading_validation_mode` is set to ``RAISE``. """ # XXX buried here to avoid circular import # filereader->Dataset->convert_value->filereader # (for SQ parsing) from pydicom.values import convert_value raw = raw_data_element # If user has hooked into conversion of raw values, call his/her routine if config.data_element_callback: raw = config.data_element_callback( raw_data_element, encoding=encoding, **config.data_element_callback_kwargs) vr = raw.VR if vr is None: # Can be if was implicit VR try: vr = dictionary_VR(raw.tag) except KeyError: # just read the bytes, no way to know what they mean if raw.tag.is_private: # for VR for private tags see PS3.5, 6.2.2 vr = _private_vr_for_tag(dataset, raw.tag) # group length tag implied in versions < 3.0 elif raw.tag.element == 0: vr = VR_.UL else: msg = f"Unknown DICOM tag {str(raw.tag)}" if config.settings.reading_validation_mode == config.RAISE: raise KeyError(msg + " can't look up VR") vr = VR_.UN warnings.warn(msg + " - setting VR to 'UN'") elif vr == VR_.UN and config.replace_un_with_known_vr: # handle rare case of incorrectly set 'UN' in explicit encoding # see also DataElement.__init__() if raw.tag.is_private: vr = _private_vr_for_tag(dataset, raw.tag) elif raw.value is None or len(raw.value) < 0xffff: try: vr = dictionary_VR(raw.tag) except KeyError: pass try: value = convert_value(vr, raw, encoding) except NotImplementedError as e: raise NotImplementedError(f"{str(e)} in tag {raw.tag!r}") except BytesLengthException as e: message = ( f"{e} This occurred while trying to parse {raw.tag} according " f"to VR '{vr}'.") if config.convert_wrong_length_to_UN: warnings.warn(f"{message} Setting VR to 'UN'.") vr = VR_.UN value = raw.value else: raise BytesLengthException( f"{message} To replace this error with a warning set " "pydicom.config.convert_wrong_length_to_UN = True.") if raw.tag in _LUT_DESCRIPTOR_TAGS and value: # We only fix the first value as the third value is 8 or 16 try: if value[0] < 0: value[0] += 65536 except TypeError: pass return DataElement( raw.tag, vr, value, raw.value_tell, raw.length == 0xFFFFFFFF, already_converted=True, )