def test_zero_length(self): """Test reading BOT with zero length""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x00\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert [0] == get_frame_offsets(fp)
def test_read_be_tag(self): """Test DicomIO.read_be_tag indirectly""" # Tags are 2 + 2 = 4 bytes bytestream = b'\x01\x02\x03\x04\x05\x06' fp = DicomBytesIO(bytestream) fp.is_little_endian = False assert Tag(fp.read_be_tag()) == 0x01020304
def test_deferred_data_element_deprecated(): """Test the deprecation warning is working""" fp = DicomBytesIO() fp.is_little_endian = True fp.is_implicit_VR = True with pytest.deprecated_call(): elem = DeferredDataElement(0x00000000, 'UL', fp, 0, 0, 4)
def test_encapsulate_single_fragment_per_frame_bot(self): """Test encapsulating single fragment per frame with BOT values.""" ds = dcmread(JP2K_10FRAME_NOBOT) frames = decode_data_sequence(ds.PixelData) assert len(frames) == 10 data = encapsulate(frames, fragments_per_frame=1, has_bot=True) test_frames = decode_data_sequence(data) for a, b in zip(test_frames, frames): assert a == b fp = DicomBytesIO(data) fp.is_little_endian = True offsets = get_frame_offsets(fp) assert offsets == [ 0x0000, # 0 0x0eee, # 3822 0x1df6, # 7670 0x2cf8, # 11512 0x3bfc, # 15356 0x4ade, # 19166 0x59a2, # 22946 0x6834, # 26676 0x76e2, # 30434 0x8594 # 34196 ]
def test_charset_patient_names(self, filename, patient_name): """Test patient names are correctly decoded and encoded.""" # check that patient names are correctly read file_path = get_charset_files(filename + '.dcm')[0] ds = dcmread(file_path) ds.decode() assert patient_name == ds.PatientName # check that patient names are correctly written back fp = DicomBytesIO() fp.is_implicit_VR = False fp.is_little_endian = True ds.save_as(fp, write_like_original=False) fp.seek(0) ds = dcmread(fp) assert patient_name == ds.PatientName # check that patient names are correctly written back # without original byte string (PersonName3 only) if hasattr(ds.PatientName, 'original_string'): ds.PatientName.original_string = None fp = DicomBytesIO() fp.is_implicit_VR = False fp.is_little_endian = True ds.save_as(fp, write_like_original=False) fp.seek(0) ds = dcmread(fp) assert patient_name == ds.PatientName
def test_seq_item_looks_like_explicit_VR(self): # For issue 999. # Set up an implicit VR dataset with a "normal" group 8 tag, # followed by a sequence with an item (dataset) having # a data element length that looks like a potential valid VR ds = Dataset() ds.file_meta = Dataset() ds.file_meta.MediaStorageSOPClassUID = "1.1.1" ds.file_meta.MediaStorageSOPInstanceUID = "2.2.2" ds.is_implicit_VR = True ds.is_little_endian = True ds.SOPClassUID = '9.9.9' # First item group 8 in top-level dataset seq = Sequence() seq_ds = Dataset() seq_ds.BadPixelImage = b"\3" * 0x5244 # length looks like "DR" seq.append(seq_ds) ds.ReferencedImageSequence = seq dbio = DicomBytesIO() ds.save_as(dbio, write_like_original=False) # Now read the constructed dataset back in # In original issue, shows warning that has detected what appears # to be Explicit VR, then throws NotImplemented for the unknown VR dbio.seek(0) ds = dcmread(dbio) ds.remove_private_tags() # forces it to actually parse SQ
def test_encapsulate_single_fragment_per_frame_bot(self): """Test encapsulating single fragment per frame with BOT values.""" ds = dcmread(JP2K_10FRAME_NOBOT) frames = decode_data_sequence(ds.PixelData) assert len(frames) == 10 data = encapsulate(frames, fragments_per_frame=1, has_bot=True) test_frames = decode_data_sequence(data) for a, b in zip(test_frames, frames): assert a == b fp = DicomBytesIO(data) fp.is_little_endian = True length, offsets = get_frame_offsets(fp) assert offsets == [ 0x0000, # 0 0x0eee, # 3822 0x1df6, # 7670 0x2cf8, # 11512 0x3bfc, # 15356 0x4ade, # 19166 0x59a2, # 22946 0x6834, # 26676 0x76e2, # 30434 0x8594 # 34196 ]
def test_not_little_endian(self): """Test reading big endian raises exception""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x00\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = False assert_raises_regex(ValueError, "'fp.is_little_endian' must be True", get_frame_offsets, fp)
def test_single_fragment_no_delimiter(self): """Test single fragment is returned OK""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert read_item(fp) == b'\x01\x00\x00\x00'
def test_read_exact_length_raises(self): """Test DicomIO.read exact length raises if short""" fp = DicomBytesIO(b'\x00\x01\x03') fp.is_little_endian = True with pytest.raises(EOFError, match="Unexpected end of file. Read 3 bytes of 4 " "expected starting at position 0x0"): fp.read(length=4, need_exact_length=True)
def test_single_frame(self): """Test reading single-frame BOT item""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x00\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert [0] == get_frame_offsets(fp)
def encode(ds, is_implicit_VR, is_little_endian): f = DicomBytesIO() f.is_implicit_VR = is_implicit_VR f.is_little_endian = is_little_endian write_dataset(f, ds) rawstr = f.parent.getvalue() f.close() return rawstr
def encode_element(el, is_implicit_VR, is_little_endian): f = DicomBytesIO() f.is_implicit_VR = is_implicit_VR f.is_little_endian = is_little_endian write_data_element(f, el) rawstr = f.parent.getvalue() f.close() return rawstr
def test_lut_descriptor_empty(self): """Regression test for #1049: LUT empty raises.""" bs = DicomBytesIO(b'\x28\x00\x01\x11\x53\x53\x00\x00') bs.is_little_endian = True bs.is_implicit_VR = False ds = dcmread(bs, force=True) elem = ds[0x00281101] assert elem.value is None assert elem.VR == 'SS'
def test_read_le_ul(self): """Test DicomIO.read_leUL indirectly""" # UL are 4 bytes fixed bytestream = b'\x00\x00\x00\x00\xFF\xFF\x00\x00\xFE\xFF\xFF\xFF' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert fp.read_leUL() == 0 assert fp.read_leUL() == 0xFFFF assert fp.read_leUL() == 0xFFFFFFFE
def test_item_undefined_length(self): """Test exception raised if item length undefined.""" bytestream = (b'\xFE\xFF\x00\xE0' b'\xFF\xFF\xFF\xFF' b'\x00\x00\x00\x01') fp = DicomBytesIO(bytestream) fp.is_little_endian = True with pytest.raises(ValueError): get_nr_fragments(fp)
def test_not_little_endian(self): """Test reading big endian raises exception""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x00\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = False with pytest.raises(ValueError, match="'fp.is_little_endian' must be True"): get_frame_offsets(fp)
def test_read_be_us(self): """Test DicomIO.read_beUS indirectly""" # US are 2 bytes fixed bytestream = b'\x00\x00\x00\xFF\xFF\xFE' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert fp.read_beUS() == 0 assert fp.read_beUS() == 255 assert fp.read_beUS() == 0xFFFE
def test_single_fragment_delimiter(self): """Test single fragment is returned OK with sequence delimiter item""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\xDD\xE0' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert 1 == get_nr_fragments(fp)
def test_item_undefined_length(self): """Test exception raised if item length undefined.""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\xFF\xFF\xFF\xFF' \ b'\x00\x00\x00\x01' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert_raises_regex( ValueError, "Encapsulated data fragment had Undefined Length" " at data position 0x4", read_item, fp)
def test_single_fragment_no_delimiter(self): """Test single fragment is returned OK""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True fragments = generate_pixel_data_fragment(fp) assert next(fragments) == b'\x01\x00\x00\x00' pytest.raises(StopIteration, next, fragments)
def test_lut_descriptor_singleton(self): """Test LUT Descriptor with VM = 1""" bs = DicomBytesIO(b'\x28\x00\x01\x11\x53\x53\x02\x00\x00\xf5') bs.is_little_endian = True bs.is_implicit_VR = False ds = dcmread(bs, force=True) elem = ds[0x00281101] # No conversion to US if not a triplet assert elem.value == -2816 assert elem.VR == 'SS'
def test_item_undefined_length(self): """Test exception raised if item length undefined.""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\xFF\xFF\xFF\xFF' \ b'\x00\x00\x00\x01' fp = DicomBytesIO(bytestream) fp.is_little_endian = True with pytest.raises(ValueError, match="Encapsulated data fragment had Undefined " "Length at data position 0x4"): read_item(fp)
def test_multi_frame(self): """Test reading multi-frame BOT item""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x10\x00\x00\x00' \ b'\x00\x00\x00\x00' \ b'\x66\x13\x00\x00' \ b'\xF4\x25\x00\x00' \ b'\xFE\x37\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert [0, 4966, 9716, 14334] == get_frame_offsets(fp)
def test_bad_length_multiple(self): """Test raises exception if the item length is not a multiple of 4.""" # Length 10 bytestream = b'\xFE\xFF\x00\xE0' \ b'\x0A\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert_raises_regex( ValueError, "The length of the Basic Offset Table item is not " "a multiple of 4.", get_frame_offsets, fp)
def test_not_little_endian(self): """Test reading big endian raises exception""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = False fragments = generate_pixel_data_fragment(fp) assert_raises_regex(ValueError, "'fp.is_little_endian' must be True", next, fragments) pytest.raises(StopIteration, next, fragments)
def test_multi_fragments_no_delimiter(self): """Test multi fragments are returned OK""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x06\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert 2 == get_nr_fragments(fp)
def test_bad_tag(self): """Test raises exception if no item tag.""" # (fffe,e100) bytestream = b'\xFE\xFF\x00\xE1' \ b'\x08\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06\x07\x08' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert_raises_regex( ValueError, "Unexpected tag '\(fffe, e100\)' when " "parsing the Basic Table Offset item.", get_frame_offsets, fp)
def test_changed_character_set(self): # Regression test for #629 multiPN_name = get_charset_files("chrFrenMulti.dcm")[0] ds = dcmread(multiPN_name) # is Latin-1 ds.SpecificCharacterSet = 'ISO_IR 192' from pydicom.filebase import DicomBytesIO fp = DicomBytesIO() ds.save_as(fp, write_like_original=False) fp.seek(0) ds_out = dcmread(fp) # we expect UTF-8 encoding here assert b'Buc^J\xc3\xa9r\xc3\xb4me' == ds_out.get_item(0x00100010).value
def test_not_little_endian(self): """Test reading big endian raises exception""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = False fragments = generate_pixel_data_fragment(fp) with pytest.raises(ValueError, match="'fp.is_little_endian' must be True"): next(fragments) pytest.raises(StopIteration, next, fragments)
def test_multi_fragments_no_delimiter(self): """Test multi fragments are returned OK""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x06\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert read_item(fp) == b'\x01\x00\x00\x00' assert read_item(fp) == b'\x01\x02\x03\x04\x05\x06'
def test_bad_length_multiple(self): """Test raises exception if the item length is not a multiple of 4.""" # Length 10 bytestream = b'\xFE\xFF\x00\xE0' \ b'\x0A\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A' fp = DicomBytesIO(bytestream) fp.is_little_endian = True with pytest.raises(ValueError, match="The length of the Basic Offset Table item" " is not a multiple of 4."): get_frame_offsets(fp)
def test_bad_tag(self): """Test raises exception if no item tag.""" # (fffe,e100) bytestream = b'\xFE\xFF\x00\xE1' \ b'\x08\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06\x07\x08' fp = DicomBytesIO(bytestream) fp.is_little_endian = True with pytest.raises(ValueError, match="Unexpected tag '\(fffe, e100\)' when " "parsing the Basic Table Offset item."): get_frame_offsets(fp)
def test_multi_fragments_delimiter(self): """Test multi fragments are returned OK with sequence delimiter item""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x06\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06' \ b'\xFE\xFF\xDD\xE0' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert read_item(fp) == b'\x01\x00\x00\x00' assert read_item(fp) == b'\x01\x02\x03\x04\x05\x06'
def test_item_sequence_delimiter(self): """Test that the fragments are returned if seq delimiter hit.""" bytestream = (b'\xFE\xFF\x00\xE0' b'\x04\x00\x00\x00' b'\x01\x00\x00\x00' b'\xFE\xFF\xDD\xE0' b'\x00\x00\x00\x00' b'\xFE\xFF\x00\xE0' b'\x04\x00\x00\x00' b'\x02\x00\x00\x00') fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert 1 == get_nr_fragments(fp)
def test_item_undefined_length(self): """Test exception raised if item length undefined.""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\xFF\xFF\xFF\xFF' \ b'\x00\x00\x00\x01' fp = DicomBytesIO(bytestream) fp.is_little_endian = True fragments = generate_pixel_data_fragment(fp) assert_raises_regex( ValueError, "Undefined item length at offset 4 when " "parsing the encapsulated pixel data " "fragments.", next, fragments) pytest.raises(StopIteration, next, fragments)
def decode(bytestring, is_implicit_vr, is_little_endian, deflated=False): """Decode `bytestring` to a *pydicom* :class:`~pydicom.dataset.Dataset`. .. versionchanged:: 1.5 Added `deflated` keyword parameter Parameters ---------- byestring : io.BytesIO The encoded dataset in the DIMSE Message sent from the peer AE. is_implicit_vr : bool The dataset is encoded as implicit (``True``) or explicit VR (``False``). is_little_endian : bool The byte ordering of the encoded dataset, ``True`` for little endian, ``False`` for big endian. deflated : bool, optional ``True`` if the dataset has been encoded using *Deflated Explicit VR Little Endian* transfer syntax (default ``False``). Returns ------- pydicom.dataset.Dataset The decoded dataset. """ ## Logging transfer_syntax = '' if deflated: transfer_syntax = "Deflated " transfer_syntax += "Little Endian" if is_little_endian else "Big Endian" if is_implicit_vr: transfer_syntax += " Implicit" else: transfer_syntax += " Explicit" LOGGER.debug('pydicom.read_dataset() TransferSyntax="%s"', transfer_syntax) # Rewind to the start of the stream bytestring.seek(0) if deflated: # Decompress the dataset bytestring = DicomBytesIO( zlib.decompress(bytestring.getvalue(), -zlib.MAX_WBITS)) bytestring.is_implicit_VR = is_implicit_vr bytestring.is_little_endian = is_little_endian # Decode the dataset return read_dataset(bytestring, is_implicit_vr, is_little_endian)
def test_multi_fragments_no_delimiter(self): """Test multi fragments are returned OK""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x06\x00\x00\x00' \ b'\x01\x02\x03\x04\x05\x06' fp = DicomBytesIO(bytestream) fp.is_little_endian = True fragments = generate_pixel_data_fragment(fp) assert next(fragments) == b'\x01\x00\x00\x00' assert next(fragments) == b'\x01\x02\x03\x04\x05\x06' pytest.raises(StopIteration, next, fragments)
def test_item_undefined_length(self): """Test exception raised if item length undefined.""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\xFF\xFF\xFF\xFF' \ b'\x00\x00\x00\x01' fp = DicomBytesIO(bytestream) fp.is_little_endian = True fragments = generate_pixel_data_fragment(fp) with pytest.raises(ValueError, match="Undefined item length at offset 4 when " "parsing the encapsulated pixel data " "fragments."): next(fragments) pytest.raises(StopIteration, next, fragments)
def test_write_tag(self): """Test DicomIO.write_tag indirectly""" tag = Tag(0x01020304) # Little endian fp = DicomBytesIO() fp.is_little_endian = True fp.write_tag(tag) assert fp.getvalue() == b'\x02\x01\x04\x03' # Big endian fp = DicomBytesIO() fp.is_little_endian = False fp.write_tag(tag) assert fp.getvalue() == b'\x01\x02\x03\x04'
def test_item_sequence_delimiter_zero_length(self): """Test that the fragments are returned if seq delimiter hit.""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\xDD\xE0' \ b'\x00\x00\x00\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x02\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert read_item(fp) == b'\x01\x00\x00\x00' assert read_item(fp) is None assert read_item(fp) == b'\x02\x00\x00\x00'
def test_item_sequence_delimiter(self): """Test non-zero length seq delimiter reads correctly.""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\xDD\xE0' \ b'\x04\x00\x00\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x02\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert read_item(fp) == b'\x01\x00\x00\x00' assert read_item(fp) is None assert read_item(fp) == b'\x02\x00\x00\x00'
def test_item_sequence_delimiter(self): """Test that the fragments are returned if seq delimiter hit.""" bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\xFE\xFF\xDD\xE0' \ b'\x00\x00\x00\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x02\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True fragments = generate_pixel_data_fragment(fp) assert next(fragments) == b'\x01\x00\x00\x00' pytest.raises(StopIteration, next, fragments)
def test_dcmread_does_not_raise(self): """Test that reading from DicomBytesIO does not raise on EOF. Regression test for #358.""" ds = dcmread(mr_name) fp = DicomBytesIO() ds.save_as(fp, write_like_original=True) fp.seek(0) de_gen = data_element_generator(fp, False, True) try: while True: next(de_gen) except StopIteration: pass except EOFError: self.fail('Unexpected EOFError raised')
def test_item_bad_tag(self): """Test item is read if it has an unexpected tag""" # This should raise an exception instead bytestream = b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x01\x00\x00\x00' \ b'\x10\x00\x10\x00' \ b'\x04\x00\x00\x00' \ b'\xFF\x00\xFF\x00' \ b'\xFE\xFF\x00\xE0' \ b'\x04\x00\x00\x00' \ b'\x02\x00\x00\x00' fp = DicomBytesIO(bytestream) fp.is_little_endian = True assert read_item(fp) == b'\x01\x00\x00\x00' assert read_item(fp) == b'\xFF\x00\xFF\x00' assert read_item(fp) == b'\x02\x00\x00\x00'
def encode(ds, is_implicit_VR, is_little_endian): """ Given a pydicom Dataset, encode it to a byte stream Parameters ---------- ds - pydicom.dataset.Dataset The dataset to encode is_implicit_VR - bool Transfer syntax implicit/explicit VR is_little_endian - bool Transfer syntax byte ordering Returns ------- bytes or None The encoded dataset (if successful), None if encoding failed. """ f = DicomBytesIO() f.is_implicit_VR = is_implicit_VR f.is_little_endian = is_little_endian try: write_dataset(f, ds) except Exception as e: logger.error("pydicom.write_dataset() failed:") logger.error(e) f.close() return None rawstr = f.parent.getvalue() f.close() return rawstr