def testImplVRLittleEndianUndefLength(self): """Raw read: Impl VR Little Endian with undefined length................""" # (7fe0,0010), OB, 2-byte reserved, 4-byte-length (UNDEFINED) hexstr1 = "e0 7f 10 00 ff ff ff ff" hexstr2 = " 41 42 43 44 45 46 47 48 49 4a" # 'content' hexstr3 = " fe ff dd e0 00 00 00 00" # Sequence Delimiter hexstr = hexstr1 + hexstr2 + hexstr3 infile = BytesIO(hex2bytes(hexstr)) expected = ((0x7fe0, 0x10), 'OB or OW', 0xffffffff, b'ABCDEFGHIJ', 0x8, True, True) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) got = next(de_gen) msg_loc = "in read of undefined length Implicit VR ='OB' short value)" self.assertEqual(got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc)) # Test again such that delimiter crosses default 128-byte read "chunks", etc for multiplier in (116, 117, 118, 120): multiplier = 116 hexstr2b = hexstr2 + " 00" * multiplier hexstr = hexstr1 + hexstr2b + hexstr3 infile = BytesIO(hex2bytes(hexstr)) expected = len('ABCDEFGHIJ' + '\0' * multiplier) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) got = next(de_gen) got_len = len(got.value) msg_loc = "in read of undefined length Implicit VR with 'multiplier' %d" % multiplier self.assertEqual(expected, got_len, "Expected value length %d, got %d in %s" % (expected, got_len, msg_loc)) msg = "Unexpected value start with multiplier %d on Implicit VR undefined length" % multiplier self.assertTrue(got.value.startswith(b'ABCDEFGHIJ\0'), msg)
def testImplVRLittleEndianUndefLength(self): """Raw read: Impl VR Little Endian with undefined length...""" # (7fe0,0010), OB, 2-byte reserved, 4-byte-length (UNDEFINED) hexstr1 = "e0 7f 10 00 ff ff ff ff" hexstr2 = " 41 42 43 44 45 46 47 48 49 4a" # 'content' hexstr3 = " fe ff dd e0 00 00 00 00" # Sequence Delimiter hexstr = hexstr1 + hexstr2 + hexstr3 infile = BytesIO(hex2bytes(hexstr)) expected = ((0x7fe0, 0x10), 'OB or OW', 0xffffffff, b'ABCDEFGHIJ', 0x8, True, True) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) assert expected == next(de_gen) # Test again such that delimiter crosses default 128-byte "chunks" for multiplier in (116, 117, 118, 120): multiplier = 116 hexstr2b = hexstr2 + " 00" * multiplier hexstr = hexstr1 + hexstr2b + hexstr3 infile = BytesIO(hex2bytes(hexstr)) expected = len('ABCDEFGHIJ' + '\0' * multiplier) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) got = next(de_gen) assert expected == len(got.value) assert got.value.startswith(b'ABCDEFGHIJ\0')
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 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 testExplVRLittleEndianEncapsulatedUndefLengthBadDelimiterLength(self): """Raw read: Expl VR Little Endian encapsulated pixel data with undefined length and a bad (non-zero) sequence delimiter length...""" hexstr = ( "e0 7f 10 00" # (7fe0, 0010) Pixel Data "4f 42 00 00" # VR OB, 2 bytes reserved "ff ff ff ff" # -1 undefined length "fe ff 00 e0" # (fffe, e000) Item Tag "10 00 00 00" # Item (dataset) Length "41 42 43 44" "45 46 47 48" "49 4a 4b 4c" "4d 4e 4f 50" "fe ff dd e0" # (fffe, edd) Sequence Delimiter "12 13 14 15" # bad non-0 required Item Length Field ) infile = BytesIO(hex2bytes(hexstr)) expected = ( (0x7fe0, 0x10), 'OB', 0xffffffff, # declared value length b'\xfe\xff\x00\xe0\x10\x00\x00\x00ABCDEFGHIJKLMNOP', 12, # value starts 12 bytes after beginning of element False, # is Implicit VR True, # is Little Endian True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) assert expected == next(de_gen) assert 44 == infile.tell()
def testExplVRLittleEndianEncapsulatedUndefLengthDeferred(self): """Raw read: Expl VR Little Endian encapsulated pixel data with undefined length that's longer than defer_size...""" hexstr = ( "e0 7f 10 00" # (7fe0, 0010) Pixel Data "4f 42 00 00" # VR OB, 2 bytes reserved "ff ff ff ff" # -1 undefined length "fe ff 00 e0" # (fffe, e000) Item Tag "14 00 00 00" # Item (dataset) Length "41 42 43 44" "45 46 47 48" "49 4a 4b 4c" "4d 4e 4f 50" "51 52 53 54" "fe ff dd e0" # (fffe, edd) Sequence Delimiter "00 00 00 00" # required Item Length Field of value 0 ) infile = BytesIO(hex2bytes(hexstr)) expected = ( (0x7fe0, 0x10), 'OB', 0xffffffff, # declared value length None, # extracted data 12, # value starts 12 bytes after beginning of element False, # is Implicit VR True, # is Little Endian True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True, defer_size=16) assert expected == next(de_gen) assert 48 == infile.tell()
def test_little_endian_explicit(self): """Test reading little endian explicit VR data""" # (0010, 0010) PatientName PN 6 ABCDEF bytestream = (b'\x10\x00\x10\x00' b'PN' b'\x06\x00' b'ABCDEF') fp = BytesIO(bytestream) # fp, is_implicit_VR, is_little_endian, gen = data_element_generator(fp, False, True) elem = DataElement(0x00100010, 'PN', 'ABCDEF') assert elem == DataElement_from_raw(next(gen), 'ISO_IR 100')
def testImplVRLittleEndian(self): """Raw read: Implicit VR Little Endian..................................""" # (0008,212a) {IS} 4-byte-length, value '1 ' infile = BytesIO(hex2bytes("08 00 2a 21 02 00 00 00 31 20")) expected = ((8, 0x212a), None, 2, b'1 ', 0x8, True, True) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) got = next(de_gen) msg_loc = "in read of Implicit VR='IS' data element (short length format)" self.assertEqual(got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc))
def testExplVRLittleEndianLongLength(self): """Raw read: Explicit VR Little Endian long length......................""" # (0002,0001) OB 2-byte-reserved 4-byte-length, value 0x00 0x01 infile = BytesIO(hex2bytes("02 00 01 00 4f 42 00 00 02 00 00 00 00 01")) expected = ((2, 1), 'OB', 2, b'\00\01', 0xc, False, True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) got = next(de_gen) msg_loc = "in read of Explicit VR='OB' data element (long length format)" self.assertEqual(got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc))
def testImplVRLittleEndian(self): """Raw read: Implicit VR Little Endian...""" # (0008,212a) {IS} 4-byte-length, value '1 ' infile = BytesIO(hex2bytes("08 00 2a 21 02 00 00 00 31 20")) expected = ((8, 0x212a), None, 2, b'1 ', 0x8, True, True) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) assert expected == next(de_gen)
def testExplVRLittleEndianLongLength(self): """Raw read: Explicit VR Little Endian long length...""" # (0002,0001) OB 2-byte-reserved 4-byte-length, value 0x00 0x01 bytes_input = "02 00 01 00 4f 42 00 00 02 00 00 00 00 01" infile = BytesIO(hex2bytes(bytes_input)) expected = ((2, 1), 'OB', 2, b'\00\01', 0xc, False, True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) assert expected == next(de_gen)
def test_little_endian_implicit(self): """Test reading little endian implicit VR data""" # (0010, 0010) PatientName PN 6 ABCDEF bytestream = b'\x10\x00\x10\x00' \ b'\x06\x00\x00\x00' \ b'ABCDEF' fp = BytesIO(bytestream) gen = data_element_generator(fp, is_implicit_VR=True, is_little_endian=True) elem = DataElement(0x00100010, 'PN', 'ABCDEF') assert elem == DataElement_from_raw(next(gen), 'ISO_IR 100')
def testExplVRLittleEndianShortLength(self): """Raw read: Explicit VR Little Endian short length.....................""" # (0008,212a) IS 2-byte-length, value '1 ' infile = BytesIO(hex2bytes("08 00 2a 21 49 53 02 00 31 20")) # XXX Assumes that a RawDataElement doesn't convert the value based # upon the VR value, thus it will remain a byte string since that is # the input expected = ((8, 0x212a), 'IS', 2, b'1 ', 0x8, False, True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) got = next(de_gen) msg_loc = "in read of Explicit VR='IS' data element (short length format)" self.assertEqual(got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc))
def test_big_endian_explicit(self): """Test reading big endian explicit VR data""" # (0010, 0010) PatientName PN 6 ABCDEF bytestream = b'\x00\x10\x00\x10' \ b'PN' \ b'\x00\x06' \ b'ABCDEF' fp = BytesIO(bytestream) # fp, is_implicit_VR, is_little_endian, gen = data_element_generator(fp, False, False) elem = DataElement(0x00100010, 'PN', 'ABCDEF') assert elem == DataElement_from_raw(next(gen), 'ISO_IR 100')
def testExplVRLittleEndianShortLength(self): """Raw read: Explicit VR Little Endian short length...""" # (0008,212a) IS 2-byte-length, value '1 ' infile = BytesIO(hex2bytes("08 00 2a 21 49 53 02 00 31 20")) # XXX Assumes that a RawDataElement doesn't convert the value based # upon the VR value, thus it will remain a byte string since that is # the input expected = ((8, 0x212a), 'IS', 2, b'1 ', 0x8, False, True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) assert expected == next(de_gen)
def testExplVRLittleEndianUndefLength(self): """Raw read: Expl VR Little Endian with undefined length...""" # (7fe0,0010), OB, 2-byte reserved, 4-byte-length (UNDEFINED) hexstr1 = "e0 7f 10 00 4f 42 00 00 ff ff ff ff" hexstr2 = " 41 42 43 44 45 46 47 48 49 4a" # 'content' hexstr3 = " fe ff dd e0 00 00 00 00" # Sequence Delimiter hexstr = hexstr1 + hexstr2 + hexstr3 infile = BytesIO(hex2bytes(hexstr)) expected = ((0x7fe0, 0x10), 'OB', 0xffffffff, b'ABCDEFGHIJ', 0xc, False, True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) got = next(de_gen) msg_loc = "in read of undefined length Explicit VR ='OB' short value)" self.assertEqual( got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc)) # Test again such that delimiter crosses default 128-byte "chunks" for multiplier in (116, 117, 118, 120): multiplier = 116 hexstr2b = hexstr2 + " 00" * multiplier hexstr = hexstr1 + hexstr2b + hexstr3 infile = BytesIO(hex2bytes(hexstr)) expected = len('ABCDEFGHIJ' + '\0' * multiplier) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) got = next(de_gen) got_len = len(got.value) msg_loc = "in read of undefined length Explicit VR ='OB'" msg_loc = "%s with 'multiplier' %d" % (msg_loc, multiplier) self.assertEqual( expected, got_len, "Expected value length %d, got %d in %s" % (expected, got_len, msg_loc)) msg = "Unexpected value start with multiplier %d" % (multiplier) msg = "%s on Expl VR undefined length" % (msg) self.assertTrue(got.value.startswith(b'ABCDEFGHIJ\0'), msg)
def testImplVRLittleEndian(self): """Raw read: Implicit VR Little Endian..................................""" # (0008,212a) {IS} 4-byte-length, value '1 ' infile = BytesIO(hex2bytes("08 00 2a 21 02 00 00 00 31 20")) expected = ((8, 0x212a), None, 2, b'1 ', 0x8, True, True) de_gen = data_element_generator(infile, is_implicit_VR=True, is_little_endian=True) got = next(de_gen) msg_loc = "in read of Implicit VR='IS' data element (short length format)" self.assertEqual( got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc))
def testExplVRLittleEndianLongLength(self): """Raw read: Explicit VR Little Endian long length......................""" # (0002,0001) OB 2-byte-reserved 4-byte-length, value 0x00 0x01 infile = BytesIO( hex2bytes("02 00 01 00 4f 42 00 00 02 00 00 00 00 01")) expected = ((2, 1), 'OB', 2, b'\00\01', 0xc, False, True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) got = next(de_gen) msg_loc = "in read of Explicit VR='OB' data element (long length format)" self.assertEqual( got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc))
def testExplVRBigEndian_UndefinedLengthSeq(self): """Raw read: ExplVR BigEndian Undefined Length SQ...""" # Create a fictional sequence with bytes directly, # similar to PS 3.5-2008 Table 7.5-2 p42 hexstr = ( "30 0a 00 B0" # (300a, 00b0) Beam Sequence " 53 51" # SQ " 00 00" # reserved " ff ff ff ff" # undefined length " ff fe e0 00" # (fffe, e000) Item Tag " 00 00 00 18" # Item (dataset) Length " 30 0a 00 c0" # (300A, 00C0) Beam Number " 49 53" # IS " 00 02" # length " 31 20" # value '1 ' " 30 0a 00 c2" # (300A, 00C2) Beam Name " 4c 4F" # LO " 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 " 49 53" # IS " 00 02" # length " 32 20" # value '2 ' " 30 0a 00 c2" # (300A, 00C2) Beam Name " 4C 4F" # LO " 00 06" # length " 42 65 61 6d 20 32" # value 'Beam 2' " ff fe E0 dd" # SQ delimiter " 00 00 00 00" # zero length ) infile = BytesIO(hex2bytes(hexstr)) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=False) seq = next(de_gen) # Note seq itself is not a raw data element. # The parser does parse undefined length SQ # 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 test_read_file_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) 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_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 testExplVRLittleEndianShortLength(self): """Raw read: Explicit VR Little Endian short length...""" # (0008,212a) IS 2-byte-length, value '1 ' infile = BytesIO(hex2bytes("08 00 2a 21 49 53 02 00 31 20")) # XXX Assumes that a RawDataElement doesn't convert the value based # upon the VR value, thus it will remain a byte string since that is # the input expected = ((8, 0x212a), 'IS', 2, b'1 ', 0x8, False, True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) got = next(de_gen) msg_loc = "in read of Explicit VR='IS'" msg_loc = "%s data element (short length format)" % (msg_loc) self.assertEqual( got, expected, "Expected: %r, got %r in %s" % (expected, got, msg_loc))
def testExplVRLittleEndianEncapsulatedUndefLengthAndItemLengthMIssing( self): """Raw read: Expl VR Little Endian encapsulated pixel data with undefined length and whose fragment (Item) ends before its length is specified...""" hexstr = ( "e0 7f 10 00" # (7fe0, 0010) Pixel Data "4f 42 00 00" # VR OB, 2 bytes reserved "ff ff ff ff" # -1 undefined length "fe ff 00 e0" # (fffe, e000) Item Tag ) infile = BytesIO(hex2bytes(hexstr)) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) with pytest.raises(EOFError): next(de_gen)
def testExplVRLittleEndianEncapsulatedUndefLengthTwoFragments(self): """Raw read: Expl VR Little Endian encapsulated pixel data with undefined length broken into two defined-length fragments...""" hexstr = ( "e0 7f 10 00" # (7fe0, 0010) Pixel Data "4f 42 00 00" # VR OB, 2 bytes reserved "ff ff ff ff" # -1 undefined length "fe ff 00 e0" # (fffe, e000) Item Tag "18 00 00 00" # Item (dataset) Length "41 42 43 44" "45 46 47 48" "49 4a 4b 4c" "4d 4e 4f 50" "51 52 53 54" "55 56 57 58" "fe ff 00 e0" # (fffe, e000) Item Tag "14 00 00 00" # Item (dataset) Length "41 42 43 44" "45 46 47 48" "49 4a 4b 4c" "4d 4e 4f 50" "51 52 53 54" "fe ff dd e0" # (fffe, edd) Sequence Delimiter "00 00 00 00" # required Item Length Field of value 0 ) infile = BytesIO(hex2bytes(hexstr)) expected = ( (0x7fe0, 0x10), 'OB', 0xffffffff, # declared value length (b'\xfe\xff\x00\xe0\x18\x00\x00\x00ABCDEFGHIJKLMNOPQRSTUVWX' b'\xfe\xff\x00\xe0\x14\x00\x00\x00ABCDEFGHIJKLMNOPQRST'), 12, # value starts 12 bytes after beginning of element False, # is Implicit VR True, # is Little Endian True) de_gen = data_element_generator(infile, is_implicit_VR=False, is_little_endian=True) assert expected == next(de_gen) assert 80 == infile.tell()
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 read_dataset(fp, is_implicit_VR, is_little_endian, bytelength=None, stop_when=None, defer_size=None, parent_encoding=default_encoding, specific_tags=None): """Return a Dataset instance containing the next dataset in the file. Parameters ---------- fp : an opened file object is_implicit_VR : boolean True if file transfer syntax is implicit VR. is_little_endian : boolean True if file has little endian transfer syntax. bytelength : int, None, optional None to read until end of file or ItemDeliterTag, else a fixed number of bytes to read stop_when : None, optional optional call_back function which can terminate reading. See help for data_element_generator for details defer_size : int, None, optional Size to avoid loading large elements in memory. See ``dcmread`` for more parameter info. parent_encoding : optional encoding to use as a default in case a Specific Character Set (0008,0005) isn't specified specific_tags : list or None See ``dcmread`` for parameter info. Returns ------- a Dataset instance See Also -------- pydicom.dataset.Dataset A collection (dictionary) of Dicom `DataElement` instances. """ raw_data_elements = dict() fpStart = fp.tell() de_gen = data_element_generator(fp, is_implicit_VR, is_little_endian, stop_when, defer_size, parent_encoding, specific_tags) try: while (bytelength is None) or (fp.tell() - fpStart < bytelength): raw_data_element = next(de_gen) # Read data elements. Stop on some errors, but return what was read tag = raw_data_element.tag # Check for ItemDelimiterTag --dataset is an item in a sequence if tag == BaseTag(0xFFFEE00D): break # Check if list element has length is 0 if not is_implicit_VR and hasattr(raw_data_element, "length") and raw_data_element.tag < Tag(0x004,0x000): if raw_data_element.length == 0: # rewind file pointer fp.seek(raw_data_element.value_tell - 8) break raw_data_elements[tag] = raw_data_element except StopIteration: pass except EOFError as details: # XXX is this error visible enough to user code with just logging? logger.error(str(details) + " in file " + getattr(fp, "name", "<no filename>")) except NotImplementedError as details: logger.error(details) return Dataset(raw_data_elements)