示例#1
0
    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
示例#2
0
    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
示例#3
0
    def test_japanese_multi_byte_personname(self):
        """Test japanese person name which has multi byte strings are
        correctly encoded."""
        file_path = get_charset_files('chrH32.dcm')[0]
        ds = dcmread(file_path)
        ds.decode()

        if hasattr(ds.PatientName, 'original_string'):
            original_string = 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_out = dcmread(fp)
            assert original_string == ds_out.PatientName.original_string

        japanese_pn = PersonName(u"Mori^Ogai=森^鷗外=もり^おうがい")
        pyencs = pydicom.charset.convert_encodings(
            ["ISO 2022 IR 6", "ISO 2022 IR 87", "ISO 2022 IR 159"])
        actual_encoded = bytes(japanese_pn.encode(pyencs))
        expect_encoded = (
            b"\x4d\x6f\x72\x69\x5e\x4f\x67\x61\x69\x3d\x1b\x24\x42\x3f"
            b"\x39\x1b\x28\x42\x5e\x1b\x24\x28\x44\x6c\x3f\x1b\x24\x42"
            b"\x33\x30\x1b\x28\x42\x3d\x1b\x24\x42\x24\x62\x24\x6a\x1b"
            b"\x28\x42\x5e\x1b\x24\x42\x24\x2a\x24\x26\x24\x2c\x24\x24"
            b"\x1b\x28\x42")
        assert expect_encoded == actual_encoded
示例#4
0
    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
示例#5
0
 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
示例#6
0
 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
示例#7
0
 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')
示例#8
0
 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')
示例#9
0
    def test_japanese_multi_byte_personname(self):
        """Test japanese person name which has multi byte strings are
        correctly encoded."""
        file_path = get_charset_files('chrH32.dcm')[0]
        ds = dcmread(file_path)
        ds.decode()

        if hasattr(ds.PatientName, 'original_string'):
            original_string = 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_out = dcmread(fp)
            assert original_string == ds_out.PatientName.original_string
示例#10
0
def write_file_meta_info(fp, file_meta, enforce_standard=True):
    """Write the File Meta Information elements in `file_meta` to `fp`.

    If `enforce_standard` is ``True`` then the file-like `fp` should be
    positioned past the 128 byte preamble + 4 byte prefix (which should
    already have been written).

    **DICOM File Meta Information Group Elements**

    From the DICOM standard, Part 10,
    :dcm:`Section 7.1<part10/chapter_7.html#sect_7.1>`,  any DICOM file shall
    contain a 128-byte preamble, a 4-byte DICOM prefix 'DICM' and (at a
    minimum) the following Type 1 DICOM Elements (from
    :dcm:`Table 7.1-1<part10/chapter_7.html#table_7.1-1>`):

    * (0002,0000) *File Meta Information Group Length*, UL, 4
    * (0002,0001) *File Meta Information Version*, OB, 2
    * (0002,0002) *Media Storage SOP Class UID*, UI, N
    * (0002,0003) *Media Storage SOP Instance UID*, UI, N
    * (0002,0010) *Transfer Syntax UID*, UI, N
    * (0002,0012) *Implementation Class UID*, UI, N

    If `enforce_standard` is ``True`` then (0002,0000) will be added/updated,
    (0002,0001) and (0002,0012) will be added if not already present and the
    other required elements will be checked to see if they exist. If
    `enforce_standard` is ``False`` then `file_meta` will be written as is
    after minimal validation checking.

    The following Type 3/1C Elements may also be present:

    * (0002,0013) *Implementation Version Name*, SH, N
    * (0002,0016) *Source Application Entity Title*, AE, N
    * (0002,0017) *Sending Application Entity Title*, AE, N
    * (0002,0018) *Receiving Application Entity Title*, AE, N
    * (0002,0102) *Private Information*, OB, N
    * (0002,0100) *Private Information Creator UID*, UI, N

    If `enforce_standard` is ``True`` then (0002,0013) will be added/updated.

    *Encoding*

    The encoding of the *File Meta Information* shall be *Explicit VR Little
    Endian*.

    Parameters
    ----------
    fp : file-like
        The file-like to write the File Meta Information to.
    file_meta : pydicom.dataset.Dataset
        The File Meta Information elements.
    enforce_standard : bool
        If ``False``, then only the *File Meta Information* elements already in
        `file_meta` will be written to `fp`. If ``True`` (default) then a DICOM
        Standards conformant File Meta will be written to `fp`.

    Raises
    ------
    ValueError
        If `enforce_standard` is ``True`` and any of the required *File Meta
        Information* elements are missing from `file_meta`, with the
        exception of (0002,0000), (0002,0001) and (0002,0012).
    ValueError
        If any non-Group 2 Elements are present in `file_meta`.
    """
    validate_file_meta(file_meta, enforce_standard)

    if enforce_standard and 'FileMetaInformationGroupLength' not in file_meta:
        # Will be updated with the actual length later
        file_meta.FileMetaInformationGroupLength = 0

    # Write the File Meta Information Group elements
    # first write into a buffer to avoid seeking back, that can be
    # expansive and is not allowed if writing into a zip file
    buffer = DicomBytesIO()
    buffer.is_little_endian = True
    buffer.is_implicit_VR = False
    write_dataset(buffer, file_meta)

    # If FileMetaInformationGroupLength is present it will be the first written
    #   element and we must update its value to the correct length.
    if 'FileMetaInformationGroupLength' in file_meta:
        # Update the FileMetaInformationGroupLength value, which is the number
        #   of bytes from the end of the FileMetaInformationGroupLength element
        #   to the end of all the File Meta Information elements.
        # FileMetaInformationGroupLength has a VR of 'UL' and so has a value
        #   that is 4 bytes fixed. The total length of when encoded as
        #   Explicit VR must therefore be 12 bytes.
        file_meta.FileMetaInformationGroupLength = buffer.tell() - 12
        buffer.seek(0)
        write_data_element(buffer, file_meta[0x00020000])

    fp.write(buffer.getvalue())
示例#11
0
class TestWriteFileMetaInfo(unittest.TestCase):
    """Unit tests for _write_file_meta_info."""
    def setUp(self):
        """Create an empty file-like for use in testing."""
        self.fp = DicomBytesIO()

    def test_bad_elements(self):
        """Test that non-group 2 elements aren't written to the file meta."""
        meta = Dataset()
        meta.PatientID = '12345678'
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)

    def test_missing_elements(self):
        """Test that missing required elements raises ValueError."""
        meta = Dataset()
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.MediaStorageSOPClassUID = '1.1'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.MediaStorageSOPInstanceUID = '1.2'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.TransferSyntaxUID = '1.3'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

    def test_prefix(self):
        """Test that the 'DICM' prefix is present."""
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        self.fp.seek(0)
        prefix = self.fp.read(4)
        self.assertEqual(prefix, b'DICM')

    def test_group_length(self):
        """Test that the value for FileMetaInformationGroupLength is OK."""
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        # 78 in total, - 4 for prefix, - 12 for group length = 62
        self.fp.seek(12)
        self.assertEqual(self.fp.read(4), b'\x3E\x00\x00\x00')

    def test_group_length_updated(self):
        """Test that FileMetaInformationGroupLength gets updated if present."""
        meta = Dataset()
        meta.FileMetaInformationGroupLength = 100  # Actual length
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        self.fp.seek(12)
        self.assertEqual(self.fp.read(4), b'\x3E\x00\x00\x00')
        # Check original file meta is unchanged/updated
        self.assertEqual(meta.FileMetaInformationGroupLength, 62)
        self.assertEqual(meta.FileMetaInformationVersion, b'\x00\x01')
        self.assertEqual(meta.MediaStorageSOPClassUID, '1.1')
        self.assertEqual(meta.MediaStorageSOPInstanceUID, '1.2')
        self.assertEqual(meta.TransferSyntaxUID, '1.3')
        self.assertEqual(meta.ImplementationClassUID, '1.4')

    def test_version(self):
        """Test that the value for FileMetaInformationVersion is OK."""
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        self.fp.seek(16 + 12)
        self.assertEqual(self.fp.read(2), b'\x00\x01')

    def test_filelike_position(self):
        """Test that the file-like's ending position is OK."""
        # 4 bytes prefix
        # 8 + 4 bytes FileMetaInformationGroupLength
        # 12 + 2 bytes FileMetaInformationVersion
        # 8 + 4 bytes MediaStorageSOPClassUID
        # 8 + 4 bytes MediaStorageSOPInstanceUID
        # 8 + 4 bytes TransferSyntaxUID
        # 8 + 4 bytes ImplementationClassUID
        # 78 bytes total
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)
        self.assertEqual(self.fp.tell(), 78)

        # 8 + 6 bytes ImplementationClassUID
        # 80 bytes total, group length 64
        self.fp.seek(0)
        meta.ImplementationClassUID = '1.4.1'
        _write_file_meta_info(self.fp, meta)
        # Check File Meta length
        self.assertEqual(self.fp.tell(), 80)
        # Check Group Length
        self.fp.seek(12)
        self.assertEqual(self.fp.read(4), b'\x40\x00\x00\x00')
        _write_file_meta_info(self.fp, meta)
示例#12
0
def write_file_meta_info(fp, file_meta, enforce_standard=True):
    """Write the File Meta Information elements in `file_meta` to `fp`.

    If `enforce_standard` is True then the file-like `fp` should be positioned
    past the 128 byte preamble + 4 byte prefix (which should already have been
    written).

    DICOM File Meta Information Group Elements
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    From the DICOM standard, Part 10 Section 7.1, any DICOM file shall contain
    a 128-byte preamble, a 4-byte DICOM prefix 'DICM' and (at a minimum) the
    following Type 1 DICOM Elements (from Table 7.1-1):
        * (0002,0000) FileMetaInformationGroupLength, UL, 4
        * (0002,0001) FileMetaInformationVersion, OB, 2
        * (0002,0002) MediaStorageSOPClassUID, UI, N
        * (0002,0003) MediaStorageSOPInstanceUID, UI, N
        * (0002,0010) TransferSyntaxUID, UI, N
        * (0002,0012) ImplementationClassUID, UI, N

    If `enforce_standard` is True then (0002,0000) will be added/updated,
    (0002,0001) and (0002,0012) will be added if not already present and the
    other required elements will be checked to see if they exist. If
    `enforce_standard` is False then `file_meta` will be written as is after
    minimal validation checking.

    The following Type 3/1C Elements may also be present:
        * (0002,0013) ImplementationVersionName, SH, N
        * (0002,0016) SourceApplicationEntityTitle, AE, N
        * (0002,0017) SendingApplicationEntityTitle, AE, N
        * (0002,0018) ReceivingApplicationEntityTitle, AE, N
        * (0002,0100) PrivateInformationCreatorUID, UI, N
        * (0002,0102) PrivateInformation, OB, N

    If `enforce_standard` is True then (0002,0013) will be added/updated.

    Encoding
    ~~~~~~~~
    The encoding of the File Meta Information shall be Explicit VR Little
    Endian

    Parameters
    ----------
    fp : file-like
        The file-like to write the File Meta Information to.
    file_meta : pydicom.dataset.Dataset
        The File Meta Information DataElements.
    enforce_standard : bool
        If False, then only the File Meta Information elements already in
        `file_meta` will be written to `fp`. If True (default) then a DICOM
        Standards conformant File Meta will be written to `fp`.

    Raises
    ------
    ValueError
        If `enforce_standard` is True and any of the required File Meta
        Information elements are missing from `file_meta`, with the
        exception of (0002,0000), (0002,0001) and (0002,0012).
    ValueError
        If any non-Group 2 Elements are present in `file_meta`.
    """
    validate_file_meta(file_meta, enforce_standard)

    if enforce_standard and 'FileMetaInformationGroupLength' not in file_meta:
        # Will be updated with the actual length later
        file_meta.FileMetaInformationGroupLength = 0

    # Write the File Meta Information Group elements
    # first write into a buffer to avoid seeking back, that can be
    # expansive and is not allowed if writing into a zip file
    buffer = DicomBytesIO()
    buffer.is_little_endian = True
    buffer.is_implicit_VR = False
    write_dataset(buffer, file_meta)

    # If FileMetaInformationGroupLength is present it will be the first written
    #   element and we must update its value to the correct length.
    if 'FileMetaInformationGroupLength' in file_meta:
        # Update the FileMetaInformationGroupLength value, which is the number
        #   of bytes from the end of the FileMetaInformationGroupLength element
        #   to the end of all the File Meta Information elements.
        # FileMetaInformationGroupLength has a VR of 'UL' and so has a value
        #   that is 4 bytes fixed. The total length of when encoded as
        #   Explicit VR must therefore be 12 bytes.
        file_meta.FileMetaInformationGroupLength = buffer.tell() - 12
        buffer.seek(0)
        write_data_element(buffer, file_meta[0x00020000])

    fp.write(buffer.getvalue())
示例#13
0
class TestWriteFileMetaInfo(unittest.TestCase):
    """Unit tests for _write_file_meta_info."""
    def setUp(self):
        """Create an empty file-like for use in testing."""
        self.fp = DicomBytesIO()

    def test_bad_elements(self):
        """Test that non-group 2 elements aren't written to the file meta."""
        meta = Dataset()
        meta.PatientID = '12345678'
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)

    def test_missing_elements(self):
        """Test that missing required elements raises ValueError."""
        meta = Dataset()
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.MediaStorageSOPClassUID = '1.1'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.MediaStorageSOPInstanceUID = '1.2'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.TransferSyntaxUID = '1.3'
        self.assertRaises(ValueError, _write_file_meta_info, self.fp, meta)
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

    def test_prefix(self):
        """Test that the 'DICM' prefix is present."""
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        self.fp.seek(0)
        prefix = self.fp.read(4)
        self.assertEqual(prefix, b'DICM')

    def test_group_length(self):
        """Test that the value for FileMetaInformationGroupLength is OK."""
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        # 78 in total, - 4 for prefix, - 12 for group length = 62
        self.fp.seek(12)
        self.assertEqual(self.fp.read(4), b'\x3E\x00\x00\x00')

    def test_group_length_updated(self):
        """Test that FileMetaInformationGroupLength gets updated if present."""
        meta = Dataset()
        meta.FileMetaInformationGroupLength = 100 # Actual length
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        self.fp.seek(12)
        self.assertEqual(self.fp.read(4), b'\x3E\x00\x00\x00')
        # Check original file meta is unchanged/updated
        self.assertEqual(meta.FileMetaInformationGroupLength, 62)
        self.assertEqual(meta.FileMetaInformationVersion, b'\x00\x01')
        self.assertEqual(meta.MediaStorageSOPClassUID, '1.1')
        self.assertEqual(meta.MediaStorageSOPInstanceUID, '1.2')
        self.assertEqual(meta.TransferSyntaxUID, '1.3')
        self.assertEqual(meta.ImplementationClassUID, '1.4')

    def test_version(self):
        """Test that the value for FileMetaInformationVersion is OK."""
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)

        self.fp.seek(16 + 12)
        self.assertEqual(self.fp.read(2), b'\x00\x01')

    def test_filelike_position(self):
        """Test that the file-like's ending position is OK."""
        # 4 bytes prefix
        # 8 + 4 bytes FileMetaInformationGroupLength
        # 12 + 2 bytes FileMetaInformationVersion
        # 8 + 4 bytes MediaStorageSOPClassUID
        # 8 + 4 bytes MediaStorageSOPInstanceUID
        # 8 + 4 bytes TransferSyntaxUID
        # 8 + 4 bytes ImplementationClassUID
        # 78 bytes total
        meta = Dataset()
        meta.MediaStorageSOPClassUID = '1.1'
        meta.MediaStorageSOPInstanceUID = '1.2'
        meta.TransferSyntaxUID = '1.3'
        meta.ImplementationClassUID = '1.4'
        _write_file_meta_info(self.fp, meta)
        self.assertEqual(self.fp.tell(), 78)

        # 8 + 6 bytes ImplementationClassUID
        # 80 bytes total, group length 64
        self.fp.seek(0)
        meta.ImplementationClassUID = '1.4.1'
        _write_file_meta_info(self.fp, meta)
        # Check File Meta length
        self.assertEqual(self.fp.tell(), 80)
        # Check Group Length
        self.fp.seek(12)
        self.assertEqual(self.fp.read(4), b'\x40\x00\x00\x00')
        _write_file_meta_info(self.fp, meta)