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), 'OW or OB', 0xffffffffL, 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 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) self.assertTrue(isinstance(seq, Sequence), "Did not get Sequence, got type {0:s}".format(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 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) 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 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")) expected = ((8, 0x212a), 'IS', 2, '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 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 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 item1_value_bytes = "\1" * 126 item2_value_bytes = "\2" * 222 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_empty_AT(self): """Write empty AT correctly..........""" # Was issue 74 data_elem = DataElement(0x00280009, "AT", []) expected = hex2bytes(( " 28 00 09 00" # (0028,0009) Frame Increment Pointer " 00 00 00 00" # length 0 )) write_data_element(self.f1, data_elem) got = self.f1.parent.getvalue() msg = ("Did not write zero-length AT value correctly. " "Expected %r, got %r") % (bytes2hex(expected), bytes2hex(got)) msg = "%r %r" % (type(expected), type(got)) msg = "'%r' '%r'" % (expected, got) self.assertEqual(expected, got, msg)
def compare_write(self, hex_std, file_ds): """Write file and compare with expected byte string :arg hex_std: the bytes which should be written, as space separated hex :arg file_ds: a FileDataset instance containing the dataset to write """ out_filename = "scratch.dcm" write_file(out_filename, file_ds) std = hex2bytes(hex_std) bytes_written = open(out_filename,'rb').read() # print "std :", bytes2hex(std) # print "written:", bytes2hex(bytes_written) same, pos = bytes_identical(std, bytes_written) self.assert_(same, "Writing from scratch not expected result - first difference at 0x%x" % pos) if os.path.exists(out_filename): os.remove(out_filename) # get rid of the file
def compare_write(self, hex_std, file_ds): """Write file and compare with expected byte string :arg hex_std: the bytes which should be written, as space separated hex :arg file_ds: a FileDataset instance containing the dataset to write """ out_filename = "scratch.dcm" file_ds.save_as(out_filename) std = hex2bytes(hex_std) bytes_written = open(out_filename, 'rb').read() # print "std :", bytes2hex(std) # print "written:", bytes2hex(bytes_written) same, pos = bytes_identical(std, bytes_written) self.assertTrue(same, "Writing from scratch unexpected result - 1st diff at 0x%x" % pos) if os.path.exists(out_filename): os.remove(out_filename) # get rid of the file
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))