def group_metadata_per_zstack(self): '''Group all focal planes belonging to one z-stack (i.e. acquired at different z resolutions but at the same microscope stage position, time point and channel) together. Returns ------- pandas.DataFrame metadata for each 2D *Plane* element ''' md = self.metadata logger.info('group metadata per z-stack') zstacks = md.groupby([ 'well_name', 'well_position_x', 'well_position_y', 'channel_name', 'tpoint' ]) logger.debug('identified %d z-stacks', zstacks.ngroups) # Map the locations of each plane with the original image files # in order to be able to perform the intensity projection later on grouped_file_mapper_list = list() grouped_file_mapper_lut = collections.defaultdict(list) rows_to_drop = list() for key, indices in zstacks.groups.iteritems(): fm = ImageFileMapping() fm.files = list() fm.series = list() fm.planes = list() fm.ref_index = indices[0] for index in indices: fm.files.extend(self._file_mapper_list[index].files) fm.series.extend(self._file_mapper_list[index].series) fm.planes.extend(self._file_mapper_list[index].planes) grouped_file_mapper_list.append(fm) grouped_file_mapper_lut[tuple(fm.files)].append(fm) # Keep only the first record rows_to_drop.extend(indices[1:]) # Update metadata and file mapper objects self.metadata.drop(self.metadata.index[rows_to_drop], inplace=True) del self.metadata['zplane'] self._file_mapper_list = grouped_file_mapper_list self._file_mapper_lut = grouped_file_mapper_lut return self.metadata
def _combine_omexml_elements(self, omexml_images, omexml_metadata): logger.info('combine OMEXML elements') # We assume here that each image files contains the same number images. n_images = omexml_images.values()[0].image_count * len(omexml_images) if omexml_metadata is not None: extra_omexml_available = True if not isinstance(omexml_metadata, bioformats.omexml.OMEXML): raise TypeError('Argument "omexml_metadata" must have type ' 'bioformats.omexml.OMEXML.') if omexml_metadata.image_count != n_images: raise MetadataError( 'Number of images in "omexml_metadata" must match ' 'the total number of Image elements in "omexml_images".') else: extra_omexml_available = False omexml_metadata = bioformats.OMEXML(XML_DECLARATION) omexml_metadata.image_count = n_images image_element_attributes = {'AcquisitionDate', 'Name'} channel_element_attributes = {'Name'} pixel_element_attributes = { 'PixelType', 'SizeC', 'SizeT', 'SizeX', 'SizeY', 'SizeZ' } plane_element_attributes = { 'PositionX', 'PositionY', 'PositionZ', 'TheC', 'TheT', 'TheZ' } filenames = natsorted(omexml_images) count = 0 for i, f in enumerate(filenames): omexml_img = omexml_images[f] n_series = omexml_img.image_count for s in xrange(n_series): extracted_image = omexml_img.image(s) md_image = omexml_metadata.image(count) for attr in image_element_attributes: extracted_value = getattr(extracted_image, attr) if extracted_value is not None: setattr(md_image, attr, extracted_value) extracted_pixels = extracted_image.Pixels n_planes = extracted_pixels.plane_count if n_planes == 0: # Sometimes an image doesn't have any plane elements. # Let's create them for consistency. extracted_pixels = self._create_channel_planes( extracted_pixels) n_planes = extracted_pixels.plane_count md_pixels = md_image.Pixels md_pixels.plane_count = n_planes if extra_omexml_available and (md_pixels.plane_count != n_planes): raise MetadataError( 'Image element #%d in OMEXML obtained from additional ' 'metdata files must have the same number of Plane ' 'elements as the corresponding Image elements in the ' 'OMEXML element obtained from image file "%s".' % (i, f)) for attr in pixel_element_attributes: extracted_value = getattr(extracted_pixels, attr) if extracted_value is not None: # This is python-bioformats being stupid by setting # random default values. setattr(md_pixels, attr, extracted_value) for p in xrange(n_planes): extracted_plane = extracted_pixels.Plane(p) md_plane = md_pixels.Plane(p) for attr in plane_element_attributes: extracted_value = getattr(extracted_plane, attr) md_value = getattr(md_plane, attr) if md_value is None and extracted_value is not None: setattr(md_plane, attr, extracted_value) fm = ImageFileMapping() fm.ref_index = count + p fm.files = [f] fm.series = [s] fm.planes = [p] self._file_mapper_list.append(fm) self._file_mapper_lut[f].append(fm) n_channels = extracted_pixels.channel_count md_image.channel_count = n_channels for c in xrange(n_channels): extracted_channel = extracted_pixels.Channel(c) md_channel = md_pixels.Channel(c) for attr in channel_element_attributes: extracted_value = getattr(extracted_channel, attr) if extracted_value is not None: setattr(md_channel, attr, extracted_value) count += 1 return omexml_metadata