def parse_array_definition(self): """Reads and returns the element type and length of the array. The position in the file must be just after the array encoded dtype. """ self.skipif4() enc_eltype = iou.read_long(self.f, "big") self.skipif4() length = iou.read_long(self.f, "big") return length, enc_eltype
def parse_struct_definition(self): """Reads and returns the struct definition tuple. The position in the file must be just after the struct encoded dtype. """ self.f.seek(4, 1) # Skip the name length self.skipif4(2) nfields = iou.read_long(self.f, "big") definition = () for ifield in range(nfields): self.f.seek(4, 1) self.skipif4(2) definition += (iou.read_long(self.f, "big"),) return definition
def parse_string_definition(self): """Reads and returns the length of the string. The position in the file must be just after the string encoded dtype. """ self.skipif4() return iou.read_long(self.f, "big")
def parse_header(self): self.dm_version = iou.read_long(self.f, "big") if self.dm_version not in (3, 4): raise NotImplementedError( "Currently we only support reading DM versions 3 and 4 but " "this file " "seems to be version %s " % self.dm_version) filesizeB = self.read_l_or_q(self.f, "big") is_little_endian = iou.read_long(self.f, "big") _logger.info('DM version: %i', self.dm_version) _logger.info('size %i B', filesizeB) _logger.info('Is file Little endian? %s', bool(is_little_endian)) if bool(is_little_endian): self.endian = 'little' else: self.endian = 'big'
def parse_struct_definition(self): """Reads and returns the struct definition tuple. The position in the file must be just after the struct encoded dtype. """ self.f.seek(4, 1) # Skip the name length self.skipif4(2) nfields = iou.read_long(self.f, "big") definition = () for ifield in range(nfields): self.f.seek(4, 1) self.skipif4(2) definition += (iou.read_long(self.f, "big"), ) return definition
def parse_tag_group(self, skip4=1): """Parse the root TagGroup of the given DM3 file f. Returns the tuple (is_sorted, is_open, n_tags). endian can be either 'big' or 'little'. """ is_sorted = iou.read_byte(self.f, "big") is_open = iou.read_byte(self.f, "big") self.skipif4(n=skip4) n_tags = iou.read_long(self.f, "big") return bool(is_sorted), bool(is_open), n_tags
def parse_tags(self, ntags, group_name='root', group_dict={}): """Parse the DM file into a dictionary. """ unnammed_data_tags = 0 unnammed_group_tags = 0 for tag in range(ntags): _logger.debug('Reading tag name at address: %s', self.f.tell()) tag_header = self.parse_tag_header() tag_name = tag_header['tag_name'] skip = True if (group_name == "ImageData" and tag_name == "Data") else False _logger.debug('Tag name: %s', tag_name[:20]) _logger.debug('Tag ID: %s', tag_header['tag_id']) if tag_header['tag_id'] == 21: # it's a TagType (DATA) if not tag_name: tag_name = 'Data%i' % unnammed_data_tags unnammed_data_tags += 1 _logger.debug('Reading data tag at address: %s', self.f.tell()) # Start reading the data # Raises IOError if it is wrong self.check_data_tag_delimiter() self.skipif4() infoarray_size = iou.read_long(self.f, 'big') _logger.debug("Infoarray size: %s", infoarray_size) self.skipif4() if infoarray_size == 1: # Simple type _logger.debug("Reading simple data") etype = iou.read_long(self.f, "big") data = self.read_simple_data(etype) elif infoarray_size == 2: # String _logger.debug("Reading string") enctype = iou.read_long(self.f, "big") if enctype != 18: raise IOError("Expected 18 (string), got %i" % enctype) string_length = self.parse_string_definition() data = self.read_string(string_length, skip=skip) elif infoarray_size == 3: # Array of simple type _logger.debug("Reading simple array") # Read array header enctype = iou.read_long(self.f, "big") if enctype != 20: # Should be 20 if it is an array raise IOError("Expected 20 (string), got %i" % enctype) size, enc_eltype = self.parse_array_definition() data = self.read_array(size, enc_eltype, skip=skip) elif infoarray_size > 3: enctype = iou.read_long(self.f, "big") if enctype == 15: # It is a struct _logger.debug("Reading struct") definition = self.parse_struct_definition() _logger.debug("Struct definition %s", definition) data = self.read_struct(definition, skip=skip) elif enctype == 20: # It is an array of complex type # Read complex array info # The structure is # 20 <4>, ? <4>, enc_dtype <4>, definition <?>, # size <4> self.skipif4() enc_eltype = iou.read_long(self.f, "big") if enc_eltype == 15: # Array of structs _logger.debug("Reading array of structs") definition = self.parse_struct_definition() self.skipif4() # Padding? size = iou.read_long(self.f, "big") _logger.debug("Struct definition: %s", definition) _logger.debug("Array size: %s", size) data = self.read_array( size=size, enc_eltype=enc_eltype, extra={"definition": definition}, skip=skip) elif enc_eltype == 18: # Array of strings _logger.debug("Reading array of strings") string_length = \ self.parse_string_definition() size = iou.read_long(self.f, "big") data = self.read_array( size=size, enc_eltype=enc_eltype, extra={"length": string_length}, skip=skip) elif enc_eltype == 20: # Array of arrays _logger.debug("Reading array of arrays") el_length, enc_eltype = \ self.parse_array_definition() size = iou.read_long(self.f, "big") data = self.read_array( size=size, enc_eltype=enc_eltype, extra={"size": el_length}, skip=skip) else: # Infoarray_size < 1 raise IOError("Invalided infoarray size ", infoarray_size) group_dict[tag_name] = data elif tag_header['tag_id'] == 20: # it's a TagGroup (GROUP) if not tag_name: tag_name = 'TagGroup%i' % unnammed_group_tags unnammed_group_tags += 1 _logger.debug( 'Reading Tag group at address: %s', self.f.tell()) ntags = self.parse_tag_group(skip4=3)[2] group_dict[tag_name] = {} self.parse_tags( ntags=ntags, group_name=tag_name, group_dict=group_dict[tag_name]) else: _logger.debug('File address:', self.f.tell()) raise DM3TagIDError(tag_header['tag_id'])
def parse_tags(self, ntags, group_name='root', group_dict={}): """Parse the DM file into a dictionary. """ unnammed_data_tags = 0 unnammed_group_tags = 0 for tag in range(ntags): _logger.debug('Reading tag name at address: %s', self.f.tell()) tag_header = self.parse_tag_header() tag_name = tag_header['tag_name'] skip = True if (group_name == "ImageData" and tag_name == "Data") else False _logger.debug('Tag name: %s', tag_name[:20]) _logger.debug('Tag ID: %s', tag_header['tag_id']) if tag_header['tag_id'] == 21: # it's a TagType (DATA) if not tag_name: tag_name = 'Data%i' % unnammed_data_tags unnammed_data_tags += 1 _logger.debug('Reading data tag at address: %s', self.f.tell()) # Start reading the data # Raises IOError if it is wrong self.check_data_tag_delimiter() self.skipif4() infoarray_size = iou.read_long(self.f, 'big') _logger.debug("Infoarray size: %s", infoarray_size) self.skipif4() if infoarray_size == 1: # Simple type _logger.debug("Reading simple data") etype = iou.read_long(self.f, "big") data = self.read_simple_data(etype) elif infoarray_size == 2: # String _logger.debug("Reading string") enctype = iou.read_long(self.f, "big") if enctype != 18: raise IOError("Expected 18 (string), got %i" % enctype) string_length = self.parse_string_definition() data = self.read_string(string_length, skip=skip) elif infoarray_size == 3: # Array of simple type _logger.debug("Reading simple array") # Read array header enctype = iou.read_long(self.f, "big") if enctype != 20: # Should be 20 if it is an array raise IOError("Expected 20 (string), got %i" % enctype) size, enc_eltype = self.parse_array_definition() data = self.read_array(size, enc_eltype, skip=skip) elif infoarray_size > 3: enctype = iou.read_long(self.f, "big") if enctype == 15: # It is a struct _logger.debug("Reading struct") definition = self.parse_struct_definition() _logger.debug("Struct definition %s", definition) data = self.read_struct(definition, skip=skip) elif enctype == 20: # It is an array of complex type # Read complex array info # The structure is # 20 <4>, ? <4>, enc_dtype <4>, definition <?>, # size <4> self.skipif4() enc_eltype = iou.read_long(self.f, "big") if enc_eltype == 15: # Array of structs _logger.debug("Reading array of structs") definition = self.parse_struct_definition() self.skipif4() # Padding? size = iou.read_long(self.f, "big") _logger.debug("Struct definition: %s", definition) _logger.debug("Array size: %s", size) data = self.read_array( size=size, enc_eltype=enc_eltype, extra={"definition": definition}, skip=skip) elif enc_eltype == 18: # Array of strings _logger.debug("Reading array of strings") string_length = \ self.parse_string_definition() size = iou.read_long(self.f, "big") data = self.read_array( size=size, enc_eltype=enc_eltype, extra={"length": string_length}, skip=skip) elif enc_eltype == 20: # Array of arrays _logger.debug("Reading array of arrays") el_length, enc_eltype = \ self.parse_array_definition() size = iou.read_long(self.f, "big") data = self.read_array(size=size, enc_eltype=enc_eltype, extra={"size": el_length}, skip=skip) else: # Infoarray_size < 1 raise IOError("Invalided infoarray size ", infoarray_size) group_dict[tag_name] = data elif tag_header['tag_id'] == 20: # it's a TagGroup (GROUP) if not tag_name: tag_name = 'TagGroup%i' % unnammed_group_tags unnammed_group_tags += 1 _logger.debug('Reading Tag group at address: %s', self.f.tell()) ntags = self.parse_tag_group(skip4=3)[2] group_dict[tag_name] = {} self.parse_tags(ntags=ntags, group_name=tag_name, group_dict=group_dict[tag_name]) else: _logger.debug('File address:', self.f.tell()) raise DM3TagIDError(tag_header['tag_id'])