def read(filename: str) -> Tuple[np.ndarray, czimd.CziMetadata]: """Read the pixel data of an CZI image file. Scaling factor of 1.0 will be used. :param filename: filename of the CZI to be read :return: CZI pixel data and the CziMetadata class """ # get the CZI metadata md = czimd.CziMetadata(filename) # read CZI using aicspylibczi aicsczi = CziFile(filename) # in case of a non-mosaic CZI file if not aicsczi.is_mosaic(): # get all scenes all_scenes, md = read_nonmosaic(filename=filename) # in case of a mosaic CZI file if aicsczi.is_mosaic(): # get all scenes all_scenes, md = read_mosaic(filename=filename, scale=1.0) return all_scenes, md
def read_nonmosaic(filename: str) -> Tuple[Union[np.ndarray, None], czimd.CziMetadata]: """Read CZI pixel data from non-mosaic image data :param filename: filename of the CZI file to be read :return: CZI pixel data and the CziMetadata class """ # get the CZI metadata md = czimd.CziMetadata(filename) # read CZI using aicspylibczi aicsczi = CziFile(filename) if aicsczi.is_mosaic(): # check if this CZIn is really a non-mosaic file print("CZI is a mosaic file. Please use the readczi_mosaic method instead") return None, md # get the shape for the 1st scene scene = czimd.CziScene(aicsczi, sceneindex=0) shape_all = scene.shape_single_scene # only update the shape for the scene if the CZI has an S-Dimension if scene.hasS: shape_all[scene.posS] = md.dims.SizeS print("Shape all Scenes : ", shape_all) print("DimString all Scenes : ", scene.single_scene_dimstr) # create an empty array with the correct dimensions all_scenes = np.empty(aicsczi.size, dtype=md.npdtype) # loop over scenes if CZI is not a mosaic image if md.dims.SizeS is None: sizeS = 1 else: sizeS = md.dims.SizeS for s in range(sizeS): # read the image stack for the current scene current_scene, shp = aicsczi.read_image(S=s) # create th index lists containing the slice objects if scene.hasS: idl_scene = [slice(None, None, None)] * (len(all_scenes.shape) - 2) idl_scene[aicsczi.dims.index("S")] = 0 idl_all = [slice(None, None, None)] * (len(all_scenes.shape) - 2) idl_all[aicsczi.dims.index("S")] = s # cast current stack into the stack for all scenes all_scenes[tuple(idl_all)] = current_scene[tuple(idl_scene)] # if there is no S-Dimension use the stack directly if not scene.hasS: all_scenes = current_scene print("Shape all scenes (no mosaic)", all_scenes.shape) return all_scenes, md
def __init__(self, slide_path: str): self.slide_path = slide_path reader = CziFile(slide_path) if not reader.is_mosaic(): raise NotImplementedError( 'This class has only been defined for mosaic czi files. ' 'You should be able to simply convert the non-mosaic czi-file ' 'into a format that can be opened with openslide.' ) self.bboxes = np.array(reader.mosaic_scene_bounding_boxes()) self.data_mask = self._get_data_mask(self.bboxes) self.shape = reader.read_mosaic_size() self.dimensions = self.shape[2:] self.region_mask = self._get_region_mask(self.shape)
return dims_dict, dimindex_list, numvalid_dims filename = r"C:\Temp\input\DTScan_ID4.czi" md, addmd = imf.get_metadata(filename) czi = CziFile(filename) # Get the shape of the data, the coordinate pairs are (start index, size) dimensions = czi.dims_shape() print(dimensions) print(czi.dims) print(czi.size) print(czi.is_mosaic()) # True # Mosaic files ignore the S dimension and use an internal mIndex to reconstruct, the scale factor allows one to generate a manageable image mosaic_data = czi.read_mosaic(C=0, scale_factor=1) print('CZI Mosaic Data Shape : ', mosaic_data.shape) md = {} md['SizeS'] = 1 md['SizeT'] = 3 md['SizeZ'] = 5 md['SizeC'] = 2 md['SizeY'] = 100 md['SizeX'] = 200 dimorder = 'STCYX' dims_dict, dimindex_list, numvalid_dims = get_dimorder(dimorder)
def get_metadata_czi(filename, dim2none=False, forceDim=False, forceDimname='SizeC', forceDimvalue=2, convert_scunit=True): """ Returns a dictionary with CZI metadata. Information CZI Dimension Characters: - '0': 'Sample', # e.g. RGBA - 'X': 'Width', - 'Y': 'Height', - 'C': 'Channel', - 'Z': 'Slice', # depth - 'T': 'Time', - 'R': 'Rotation', - 'S': 'Scene', # contiguous regions of interest in a mosaic image - 'I': 'Illumination', # direction - 'B': 'Block', # acquisition - 'M': 'Mosaic', # index of tile for compositing a scene - 'H': 'Phase', # e.g. Airy detector fibers - 'V': 'View', # e.g. for SPIM :param filename: filename of the CZI image :type filename: str :param dim2none: option to set non-existing dimension to None, defaults to False :type dim2none: bool, optional :param forceDim: option to force to not read certain dimensions, defaults to False :type forceDim: bool, optional :param forceDimname: name of the dimension not to read, defaults to SizeC :type forceDimname: str, optional :param forceDimvalue: index of the dimension not to read, defaults to 2 :type forceDimvalue: int, optional :param convert_scunit: convert scale unit string from 'µm' to 'micron', defaults to False :type convert_scunit: bool, optional :return: metadata - dictionary with the relevant CZI metainformation :rtype: dict """ # get CZI object czi = zis.CziFile(filename) # parse the XML into a dictionary metadatadict_czi = czi.metadata(raw=False) # initialize metadata dictionary metadata = create_metadata_dict() # get directory and filename etc. metadata['Directory'] = os.path.dirname(filename) metadata['Filename'] = os.path.basename(filename) metadata['Extension'] = 'czi' metadata['ImageType'] = 'czi' # add axes and shape information using czifile package metadata['Axes_czifile'] = czi.axes metadata['Shape_czifile'] = czi.shape # add axes and shape information using aicsimageio package czi_aics = AICSImage(filename) metadata['Axes_aics'] = czi_aics.dims try: metadata['Shape_aics'] = czi_aics.shape metadata['SizeX_aics'] = czi_aics.size_x metadata['SizeY_aics'] = czi_aics.size_y metadata['SizeC_aics'] = czi_aics.size_c metadata['SizeZ_aics'] = czi_aics.size_t metadata['SizeT_aics'] = czi_aics.size_t metadata['SizeS_aics'] = czi_aics.size_s except KeyError as e: metadata['Shape_aics'] = None metadata['SizeX_aics'] = None metadata['SizeY_aics'] = None metadata['SizeC_aics'] = None metadata['SizeZ_aics'] = None metadata['SizeT_aics'] = None metadata['SizeS_aics'] = None # get additional data by using pylibczi directly # Get the shape of the data, the coordinate pairs are (start index, size) aics_czi = CziFile(filename) metadata['dims_aicspylibczi'] = aics_czi.dims_shape()[0] metadata['dimorder_aicspylibczi'] = aics_czi.dims metadata['size_aicspylibczi'] = aics_czi.size metadata['czi_isMosaic'] = aics_czi.is_mosaic() # determine pixel type for CZI array metadata['NumPy.dtype'] = czi.dtype # check if the CZI image is an RGB image depending # on the last dimension entry of axes if czi.shape[-1] == 3: metadata['czi_isRGB'] = True try: metadata['PixelType'] = metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['PixelType'] except KeyError as e: print('Key not found:', e) metadata['PixelType'] = None try: metadata['SizeX'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeX']) except KeyError as e: metadata['SizeX'] = None try: metadata['SizeY'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeY']) except KeyError as e: metadata['SizeY'] = None try: metadata['SizeZ'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeZ']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeZ'] = None if not dim2none: metadata['SizeZ'] = 1 # for special cases do not read the SizeC from the metadata if forceDim and forceDimname == 'SizeC': metadata[forceDimname] = forceDimvalue if not forceDim: try: metadata['SizeC'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeC']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeC'] = None if not dim2none: metadata['SizeC'] = 1 # create empty lists for channel related information channels = [] channels_names = [] channels_colors = [] # in case of only one channel if metadata['SizeC'] == 1: # get name for dye try: channels.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel']['ShortName']) except KeyError as e: print('Exception:', e) try: channels.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel']['DyeName']) except KeyError as e: print('Exception:', e) channels.append('Dye-CH1') # get channel name try: channels_names.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel']['Name']) except KeyError as e: print('Exception:', e) channels_names.append['CH1'] # get channel color try: channels_colors.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel']['Color']) except KeyError as e: print('Exception:', e) channels_colors.append('#80808000') # in case of two or more channels if metadata['SizeC'] > 1: # loop over all channels for ch in range(metadata['SizeC']): # get name for dyes try: channels.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel'][ch]['ShortName']) except KeyError as e: print('Exception:', e) try: channels.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel'][ch]['DyeName']) except KeyError as e: print('Exception:', e) channels.append('Dye-CH' + str(ch)) # get channel names try: channels_names.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel'][ch]['Name']) except KeyError as e: print('Exception:', e) channels_names.append('CH' + str(ch)) # get channel colors try: channels_colors.append(metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel'][ch]['Color']) except KeyError as e: print('Exception:', e) # use grayscale instead channels_colors.append('80808000') # write channels information (as lists) into metadata dictionary metadata['Channels'] = channels metadata['ChannelNames'] = channels_names metadata['ChannelColors'] = channels_colors try: metadata['SizeT'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeT']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeT'] = None if not dim2none: metadata['SizeT'] = 1 try: metadata['SizeM'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeM']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeM'] = None if not dim2none: metadata['SizeM'] = 1 try: metadata['SizeB'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeB']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeB'] = None if not dim2none: metadata['SizeB'] = 1 try: metadata['SizeS'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeS']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeS'] = None if not dim2none: metadata['SizeS'] = 1 try: metadata['SizeH'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeH']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeH'] = None if not dim2none: metadata['SizeH'] = 1 try: metadata['SizeI'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeI']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeI'] = None if not dim2none: metadata['SizeI'] = 1 try: metadata['SizeV'] = np.int(metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['SizeV']) except Exception as e: # print('Exception:', e) if dim2none: metadata['SizeV'] = None if not dim2none: metadata['SizeV'] = 1 # get the scaling information try: # metadata['Scaling'] = metadatadict_czi['ImageDocument']['Metadata']['Scaling'] metadata['XScale'] = float(metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items']['Distance'][0]['Value']) * 1000000 metadata['YScale'] = float(metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items']['Distance'][1]['Value']) * 1000000 metadata['XScale'] = np.round(metadata['XScale'], 3) metadata['YScale'] = np.round(metadata['YScale'], 3) try: metadata['XScaleUnit'] = metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items']['Distance'][0]['DefaultUnitFormat'] metadata['YScaleUnit'] = metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items']['Distance'][1]['DefaultUnitFormat'] except KeyError as e: print('Key not found:', e) metadata['XScaleUnit'] = None metadata['YScaleUnit'] = None try: metadata['ZScale'] = float(metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items']['Distance'][2]['Value']) * 1000000 metadata['ZScale'] = np.round(metadata['ZScale'], 3) # additional check for faulty z-scaling if metadata['ZScale'] == 0.0: metadata['ZScale'] = 1.0 try: metadata['ZScaleUnit'] = metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items']['Distance'][2]['DefaultUnitFormat'] except KeyError as e: print('Key not found:', e) metadata['ZScaleUnit'] = metadata['XScaleUnit'] except Exception as e: # print('Exception:', e) if dim2none: metadata['ZScale'] = None metadata['ZScaleUnit'] = None if not dim2none: # set to isotropic scaling if it was single plane only metadata['ZScale'] = metadata['XScale'] metadata['ZScaleUnit'] = metadata['XScaleUnit'] except Exception as e: print('Exception:', e) print('Scaling Data could not be found.') # try to get software version try: metadata['SW-Name'] = metadatadict_czi['ImageDocument']['Metadata']['Information']['Application']['Name'] metadata['SW-Version'] = metadatadict_czi['ImageDocument']['Metadata']['Information']['Application']['Version'] except KeyError as e: print('Key not found:', e) metadata['SW-Name'] = None metadata['SW-Version'] = None try: metadata['AcqDate'] = metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['AcquisitionDateAndTime'] except KeyError as e: print('Key not found:', e) metadata['AcqDate'] = None # check if Instrument metadat actually exist if pydash.objects.has(metadatadict_czi, ['ImageDocument', 'Metadata', 'Information', 'Instrument']): # get objective data if isinstance(metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Objectives']['Objective'], list): num_obj = len(metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Objectives']['Objective']) else: num_obj = 1 # if there is only one objective found if num_obj == 1: try: metadata['ObjName'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective']['Name']) except KeyError as e: print('Key not found:', e) metadata['ObjName'].append(None) try: metadata['ObjImmersion'] = metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Objectives']['Objective']['Immersion'] except KeyError as e: print('Key not found:', e) metadata['ObjImmersion'] = None try: metadata['ObjNA'] = np.float(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective']['LensNA']) except KeyError as e: print('Key not found:', e) metadata['ObjNA'] = None try: metadata['ObjID'] = metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Objectives']['Objective']['Id'] except KeyError as e: print('Key not found:', e) metadata['ObjID'] = None try: metadata['TubelensMag'] = np.float(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['TubeLenses']['TubeLens']['Magnification']) except KeyError as e: print('Key not found:', e, 'Using Default Value = 1.0 for Tublens Magnification.') metadata['TubelensMag'] = 1.0 try: metadata['ObjNominalMag'] = np.float(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective']['NominalMagnification']) except KeyError as e: print('Key not found:', e, 'Using Default Value = 1.0 for Nominal Magnification.') metadata['ObjNominalMag'] = 1.0 try: if metadata['TubelensMag'] is not None: metadata['ObjMag'] = metadata['ObjNominalMag'] * metadata['TubelensMag'] if metadata['TubelensMag'] is None: print('No TublensMag found. Use 1 instead') metadata['ObjMag'] = metadata['ObjNominalMag'] * 1.0 except KeyError as e: print('Key not found:', e) metadata['ObjMag'] = None if num_obj > 1: for o in range(num_obj): try: metadata['ObjName'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective'][o]['Name']) except KeyError as e: print('Key not found:', e) metadata['ObjName'].append(None) try: metadata['ObjImmersion'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective'][o]['Immersion']) except KeyError as e: print('Key not found:', e) metadata['ObjImmersion'].append(None) try: metadata['ObjNA'].append(np.float(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective'][o]['LensNA'])) except KeyError as e: print('Key not found:', e) metadata['ObjNA'].append(None) try: metadata['ObjID'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective'][o]['Id']) except KeyError as e: print('Key not found:', e) metadata['ObjID'].append(None) try: metadata['TubelensMag'].append(np.float(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['TubeLenses']['TubeLens'][o]['Magnification'])) except KeyError as e: print('Key not found:', e, 'Using Default Value = 1.0 for Tublens Magnification.') metadata['TubelensMag'].append(1.0) try: metadata['ObjNominalMag'].append(np.float(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Objectives']['Objective'][o]['NominalMagnification'])) except KeyError as e: print('Key not found:', e, 'Using Default Value = 1.0 for Nominal Magnification.') metadata['ObjNominalMag'].append(1.0) try: if metadata['TubelensMag'] is not None: metadata['ObjMag'].append(metadata['ObjNominalMag'][o] * metadata['TubelensMag'][o]) if metadata['TubelensMag'] is None: print('No TublensMag found. Use 1 instead') metadata['ObjMag'].append(metadata['ObjNominalMag'][o] * 1.0) except KeyError as e: print('Key not found:', e) metadata['ObjMag'].append(None) # get detector information # check if there are any detector entries inside the dictionary if pydash.objects.has(metadatadict_czi, ['ImageDocument', 'Metadata', 'Information', 'Instrument', 'Detectors']): if isinstance(metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Detectors']['Detector'], list): num_detectors = len(metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Detectors']['Detector']) else: num_detectors = 1 # if there is only one detector found if num_detectors == 1: # check for detector ID try: metadata['DetectorID'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector']['Id']) except KeyError as e: metadata['DetectorID'].append(None) # check for detector Name try: metadata['DetectorName'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector']['Name']) except KeyError as e: metadata['DetectorName'].append(None) # check for detector model try: metadata['DetectorModel'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector']['Manufacturer']['Model']) except KeyError as e: metadata['DetectorModel'].append(None) # check for detector type try: metadata['DetectorType'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector']['Type']) except KeyError as e: metadata['DetectorType'].append(None) if num_detectors > 1: for d in range(num_detectors): # check for detector ID try: metadata['DetectorID'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector'][d]['Id']) except KeyError as e: metadata['DetectorID'].append(None) # check for detector Name try: metadata['DetectorName'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector'][d]['Name']) except KeyError as e: metadata['DetectorName'].append(None) # check for detector model try: metadata['DetectorModel'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector'][d]['Manufacturer']['Model']) except KeyError as e: metadata['DetectorModel'].append(None) # check for detector type try: metadata['DetectorType'].append(metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector'][d]['Type']) except KeyError as e: metadata['DetectorType'].append(None) # check for well information metadata['Well_ArrayNames'] = [] metadata['Well_Indices'] = [] metadata['Well_PositionNames'] = [] metadata['Well_ColId'] = [] metadata['Well_RowId'] = [] metadata['WellCounter'] = None metadata['SceneStageCenterX'] = [] metadata['SceneStageCenterY'] = [] try: print('Trying to extract Scene and Well information if existing ...') # extract well information from the dictionary allscenes = metadatadict_czi['ImageDocument']['Metadata']['Information']['Image']['Dimensions']['S']['Scenes']['Scene'] # loop over all detected scenes for s in range(metadata['SizeS']): if metadata['SizeS'] == 1: well = allscenes try: metadata['Well_ArrayNames'].append(allscenes['ArrayName']) except KeyError as e: # print('Key not found in Metadata Dictionary:', e) try: metadata['Well_ArrayNames'].append(well['Name']) except KeyError as e: print('Key not found in Metadata Dictionary:', e, 'Using A1 instead') metadata['Well_ArrayNames'].append('A1') try: metadata['Well_Indices'].append(allscenes['Index']) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['Well_Indices'].append(1) try: metadata['Well_PositionNames'].append(allscenes['Name']) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['Well_PositionNames'].append('P1') try: metadata['Well_ColId'].append(np.int(allscenes['Shape']['ColumnIndex'])) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['Well_ColId'].append(0) try: metadata['Well_RowId'].append(np.int(allscenes['Shape']['RowIndex'])) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['Well_RowId'].append(0) try: # count the content of the list, e.g. how many time a certain well was detected metadata['WellCounter'] = Counter(metadata['Well_ArrayNames']) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['WellCounter'].append(Counter({'A1': 1})) try: # get the SceneCenter Position sx = allscenes['CenterPosition'].split(',')[0] sy = allscenes['CenterPosition'].split(',')[1] metadata['SceneStageCenterX'].append(np.double(sx)) metadata['SceneStageCenterY'].append(np.double(sy)) except KeyError as e: metadata['SceneStageCenterX'].append(0.0) metadata['SceneStageCenterY'].append(0.0) if metadata['SizeS'] > 1: try: well = allscenes[s] metadata['Well_ArrayNames'].append(well['ArrayName']) except KeyError as e: # print('Key not found in Metadata Dictionary:', e) try: metadata['Well_ArrayNames'].append(well['Name']) except KeyError as e: print('Key not found in Metadata Dictionary:', e, 'Using A1 instead') metadata['Well_ArrayNames'].append('A1') # get the well information try: metadata['Well_Indices'].append(well['Index']) except KeyError as e: # print('Key not found in Metadata Dictionary:', e) metadata['Well_Indices'].append(None) try: metadata['Well_PositionNames'].append(well['Name']) except KeyError as e: # print('Key not found in Metadata Dictionary:', e) metadata['Well_PositionNames'].append(None) try: metadata['Well_ColId'].append(np.int(well['Shape']['ColumnIndex'])) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['Well_ColId'].append(None) try: metadata['Well_RowId'].append(np.int(well['Shape']['RowIndex'])) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['Well_RowId'].append(None) # count the content of the list, e.g. how many time a certain well was detected metadata['WellCounter'] = Counter(metadata['Well_ArrayNames']) # try: if isinstance(allscenes, list): try: # get the SceneCenter Position sx = allscenes[s]['CenterPosition'].split(',')[0] sy = allscenes[s]['CenterPosition'].split(',')[1] metadata['SceneStageCenterX'].append(np.double(sx)) metadata['SceneStageCenterY'].append(np.double(sy)) except KeyError as e: print('Key not found in Metadata Dictionary:', e) metadata['SceneCenterX'].append(0.0) metadata['SceneCenterY'].append(0.0) if not isinstance(allscenes, list): metadata['SceneStageCenterX'].append(0.0) metadata['SceneStageCenterY'].append(0.0) # count the number of different wells metadata['NumWells'] = len(metadata['WellCounter'].keys()) except (KeyError, TypeError) as e: print('No valid Scene or Well information found:', e) # close CZI file czi.close() # close AICSImage object czi_aics.close() # convert scale unit tom avoid encoding problems if convert_scunit: if metadata['XScaleUnit'] == 'µm': metadata['XScaleUnit'] = 'micron' if metadata['YScaleUnit'] == 'µm': metadata['YScaleUnit'] = 'micron' if metadata['ZScaleUnit'] == 'µm': metadata['ZScaleUnit'] = 'micron' return metadata
all_scenes_array = img.get_image_data() if not use_dask_delayed: print('Using AICSImageIO to read the image.') all_scenes_array = img.get_image_dask_data() if not use_aicsimageio and use_pylibczi is True: # read CZI using aicspylibczi czi = CziFile(filename) # for testing # Get the shape of the data print('Dimensions : ', czi.dims) print('Size : ', czi.size) print('Shape : ', czi.dims_shape()) print('IsMoasic : ', czi.is_mosaic()) if czi.is_mosaic(): print('Mosaic Size : ', czi.read_mosaic_size()) # get the required shape for all and single scenes shape_all, shape_single, same_shape = czt.get_shape_allscenes(czi, md) print('Required_Array Shape for all scenes: ', shape_all) for sh in shape_single: print('Required Array Shape for single scenes: ', sh) #array_type = 'dask' array_type = 'zarr' #array_type = 'numpy' if array_type == 'zarr':
def test_is_mosaic(data_dir, fname, expected): czi = CziFile(str(data_dir / fname)) assert czi.is_mosaic() == expected
def __init__(self, filename: str, dim2none: bool = False) -> None: # get metadata dictionary using pylibCZIrw with pyczi.open_czi(filename) as czidoc: md_dict = czidoc.metadata # get directory, filename, SW version and acquisition data self.info = CziInfo(filename) # get dimensions self.pyczi_dims = czidoc.total_bounding_box # get some additional metadata using aicspylibczi try: from aicspylibczi import CziFile # get the general CZI object using aicspylibczi aicsczi = CziFile(filename) self.aics_dimstring = aicsczi.dims self.aics_dims_shape = aicsczi.get_dims_shape() self.aics_size = aicsczi.size self.aics_ismosaic = aicsczi.is_mosaic() self.aics_dim_order, self.aics_dim_index, self.aics_dim_valid = self.get_dimorder( aicsczi.dims) self.aics_posC = self.aics_dim_order["C"] except ImportError as e: print("Use Fallback values because:", e) self.aics_dimstring = None self.aics_dims_shape = None self.aics_size = None self.aics_ismosaic = None self.aics_dim_order = None self.aics_dim_index = None self.aics_dim_valid = None self.aics_posC = None # get the pixel typed for all channels self.pixeltypes = czidoc.pixel_types self.isRGB = False # determine pixel type for CZI array by reading XML metadata self.pixeltype = md_dict["ImageDocument"]["Metadata"][ "Information"]["Image"]["PixelType"] # check if CZI is a RGB file if self.pixeltype in ["Bgr24", "Bgr48", "Bgr96Float"]: self.isRGB = True # determine pixel type for CZI array self.npdtype, self.maxvalue = self.get_dtype_fromstring( self.pixeltype) # get the dimensions and order self.image = CziDimensions(filename) # try to guess if the CZI is a mosaic file if self.image.SizeM is None or self.image.SizeM == 1: self.ismosaic = False else: self.ismosaic = True # get the bounding boxes self.bbox = CziBoundingBox(filename) # get information about channels self.channelinfo = CziChannelInfo(filename) # get scaling info self.scale = CziScaling(filename, dim2none=dim2none) # get objetive information self.objective = CziObjectives(filename) # get detector information self.detector = CziDetector(filename) # get detector information self.microscope = CziMicroscope(filename) # get information about sample carrier and wells etc. self.sample = CziSampleInfo(filename) # get additional metainformation self.add_metadata = CziAddMetaData(filename)
def execute(filepath, separator=';', filter_method='none', filter_size=3, threshold_method='triangle', min_objectsize=1000, max_holesize=100, saveformat='ome.tiff'): """Main function that executed the workflow. :param filepath: file path of the CZI image :type filepath: tsr :param separator: sepeartor for the CSV table, defaults to ';' :type separator: str, optional :param filter_method: smoothing filer, defaults to 'none' :type filter_method: str, optional :param filter_size: kernel size or radius of filter element, defaults to 3 :type filter_size: int, optional :param threshold_method: threshold method, defaults to 'triangle' :type threshold_method: str, optional :param min_objectsize: minimum object size, defaults to 1000 :type min_objectsize: int, optional :param max_holesize: maximum object size, defaults to 100 :type max_holesize: int, optional :param saveformat: format to save the segmented image, defaults to 'ome.tiff' :type saveformat: str, optional :return: outputs :rtype: dict """ print('--------------------------------------------------') print('FilePath : ', filepath) print(os.getcwd()) print('File exists : ', os.path.exists(filepath)) print('--------------------------------------------------') # define name for figure to be saved filename = os.path.basename(filepath) # get the metadata from the czi file md, additional_mdczi = imf.get_metadata(filepath) # to make it more readable extravt values from metadata dictionary stageX = md['SceneStageCenterX'] stageY = md['SceneStageCenterY'] # define columns names for dataframe cols = ['S', 'T', 'Z', 'C', 'Number'] objects = pd.DataFrame(columns=cols) # optional dipslay of "some" results - empty list = no display show_image = [0] # scalefactor to read CZI sf = 1.0 # index for channel - currently only single channel images are supported ! chindex = 0 # define maximum object sizes max_objectsize = 1000000000 # define save format for mask adapt_dtype_mask = True dtype_mask = np.int8 # check if it makes sense if max_holesize > min_objectsize: min_objectsize = max_holesize # read the czi mosaic image czi = CziFile(filepath) # get the shape of the data using aicspylibczi print('Dimensions : ', czi.dims) print('Size : ', czi.size) print('Shape : ', czi.dims_shape()) print('IsMosaic : ', czi.is_mosaic()) # read the mosaic pixel data mosaic = czi.read_mosaic(C=0, scale_factor=sf) print('Mosaic Shape :', mosaic.shape) # get the mosaic as NumPy.Array - must fit im memory !!! image2d = np.squeeze(mosaic, axis=0) md['SizeX_readmosaic'] = image2d.shape[1] md['SizeY_readmosaic'] = image2d.shape[0] # create the savename for the OME-TIFF if saveformat == 'ome.tiff': savename_seg = filename.split('.')[0] + '.ome.tiff' if saveformat == 'tiff': savename_seg = filename.split('.')[0] + '.tiff' # initialize empty dataframe results = pd.DataFrame() # main loop over all T - Z - C slices for s in progressbar.progressbar(range(md['SizeS']), redirect_stdout=True): for t in range(md['SizeT']): for z in range(md['SizeZ']): values = {'S': s, 'T': t, 'Z': z, 'C': chindex, 'Number': 0} # preprocessing - filter the image if filter_method == 'none' or filter_method == 'None': image2d_filtered = image2d if filter_method == 'median': image2d_filtered = median(image2d, selem=disk(filter_size)) if filter_method == 'gauss': image2d_filtered = gaussian(image2d, sigma=filter_size, mode='reflect') # threshold image binary = sgt.autoThresholding(image2d_filtered, method=threshold_method) # Remove contiguous holes smaller than the specified size mask = morphology.remove_small_holes(binary, area_threshold=max_holesize, connectivity=1, in_place=True) # remove small objects mask = morphology.remove_small_objects(mask, min_size=min_objectsize, in_place=True) # clear the border mask = segmentation.clear_border(mask, bgval=0, in_place=True) # label the objects mask = measure.label(binary) # adapt pixel type of mask if adapt_dtype_mask: mask = mask.astype(dtype_mask, copy=False) # measure region properties to_measure = ('label', 'area', 'centroid', 'bbox') # measure the specified parameters store in dataframe props = pd.DataFrame( measure.regionprops_table( mask, intensity_image=image2d, properties=to_measure)).set_index('label') # filter objects by size props = props[(props['area'] >= min_objectsize) & (props['area'] <= max_objectsize)] # add well information for CZI metadata try: props['WellId'] = md['Well_ArrayNames'][s] props['Well_ColId'] = md['Well_ColId'][s] props['Well_RowId'] = md['Well_RowId'][s] except (IndexError, KeyError) as error: # Output expected ImportErrors. print('Key not found:', error) print('Well Information not found. Using S-Index.') props['WellId'] = s props['Well_ColId'] = s props['Well_RowId'] = s # add plane indices props['S'] = s props['T'] = t props['Z'] = z props['C'] = chindex # count the number of objects values['Number'] = props.shape[0] # update dataframe containing the number of objects objects = objects.append(pd.DataFrame(values, index=[0]), ignore_index=True) results = results.append(props, ignore_index=True) # make sure the array as 5D of order (T, Z, C, X, Y) to write an correct OME-TIFF mask = imf.expand_dims5d(mask, md) # write the OME-TIFF suing apeer-ometiff-library io.write_ometiff(savename_seg, mask, omexml_string=None) # rename columns in pandas datatable results.rename(columns={ 'bbox-0': 'ystart', 'bbox-1': 'xstart', 'bbox-2': 'yend', 'bbox-3': 'xend' }, inplace=True) # calculate the bbox width in height in [pixel] and [micron] results['bbox_width'] = results['xend'] - results['xstart'] results['bbox_height'] = results['yend'] - results['ystart'] results['bbox_width_scaled'] = results['bbox_width'] * md['XScale'] results['bbox_height_scaled'] = results['bbox_height'] * md['XScale'] # calculate the bbox center StageXY results['bbox_center_stageX'], results[ 'bbox_center_stageY'] = bbox2stageXY( image_stageX=stageX, image_stageY=stageY, sizeX=md['SizeX'], sizeY=md['SizeY'], scale=md['XScale'], xstart=results['xstart'], ystart=results['ystart'], bbox_width=results['bbox_width'], bbox_height=results['bbox_height']) # show results print(results) print('Done.') # write the CSV data table print('Write to CSV File : ', filename) csvfile = os.path.splitext(filename)[0] + '_planetable.csv' results.to_csv(csvfile, sep=separator, index=False) # set the outputs outputs = {} outputs['segmented_image'] = savename_seg outputs['objects_table'] = csvfile return outputs
def get_metadata_czi(filename, dim2none=False, convert_scunit=True): """ Returns a dictionary with CZI metadata. Information CZI Dimension Characters: - '0':'Sample', # e.g. RGBA - 'X':'Width', - 'Y':'Height', - 'C':'Channel', - 'Z':'Slice', # depth - 'T':'Time', - 'R':'Rotation', - 'S':'Scene', # contiguous regions of interest in a mosaic image - 'I':'Illumination', # direction - 'B':'Block', # acquisition - 'M':'Mosaic', # index of tile for compositing a scene - 'H':'Phase', # e.g. Airy detector fibers - 'V':'View', # e.g. for SPIM :param filename: filename of the CZI image :type filename: str :param dim2none: option to set non-existing dimension to None, defaults to False :type dim2none: bool, optional :param convert_scunit: convert scale unit string from 'µm' to 'micron', defaults to False :type convert_scunit: bool, optional :return: metadata, metadata_add - dictionaries with the relevant CZI metainformation :rtype: dict """ # get metadata dictionary using pylibCZIrw czidoc = pyczi.open_czi(filename) metadatadict_czi = xmltodict.parse(czidoc.raw_metadata) # get czi object aicspylibczi aicsczi = CziFile(filename) # initialize metadata dictionary metadata = create_metadata_dict() # get directory and filename etc. metadata['Directory'] = os.path.dirname(filename) metadata['Filename'] = os.path.basename(filename) metadata['Extension'] = 'czi' metadata['ImageType'] = 'czi' # get additional data by using aicspylibczi directly metadata['aicsczi_dims'] = aicsczi.dims metadata['aicsczi_dims_shape'] = aicsczi.get_dims_shape() metadata['aicsczi_size'] = aicsczi.size metadata['isMosaic'] = aicsczi.is_mosaic() print('CZI is Mosaic :', metadata['isMosaic']) # get the dimensions of the bounding boxes for the scenes # metadata['BBoxes_Scenes'] = getbboxes_allscenes(czi, metadata, numscenes=metadata['SizeS']) metadata['bbox_all_scenes'] = aicsczi.get_all_scene_bounding_boxes() if aicsczi.is_mosaic(): metadata[ 'bbox_all_mosaic_scenes'] = aicsczi.get_all_mosaic_scene_bounding_boxes( ) metadata[ 'bbox_all_mosaic_tiles'] = aicsczi.get_all_mosaic_tile_bounding_boxes( ) metadata['bbox_all_tiles'] = aicsczi.get_all_tile_bounding_boxes() # get additional data by using pylibczirw directly metadata['pyczi_dims'] = czidoc.total_bounding_box metadata['pyczi_bbox_scenes'] = czidoc.scenes_bounding_rectangle metadata['pyczi_total_rect'] = czidoc.total_bounding_rectangle # check which dimension exist inside this CZI file metadata = checkdims_czi(czidoc, metadata) # determine pixel type for CZI array metadata['NumPy.dtype'] = {} for ch, px in czidoc.pixel_types.items(): metadata['NumPy.dtype'][ch] = get_dtype_fromstring(px) if czidoc._is_rgb(czidoc.get_channel_pixel_type(0)): metadata['isRGB'] = True #if 'A' in aicsczi.dims: # metadata['isRGB'] = True print('CZI is RGB :', metadata['isRGB']) # determine pixel type for CZI array by reading XML metadata try: metadata['PixelType'] = metadatadict_czi['ImageDocument']['Metadata'][ 'Information']['Image']['PixelType'] except KeyError as e: print('No PixelType :', e) metadata['PixelType'] = None try: metadata['SizeX'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeX']) except KeyError as e: print('No X Dimension :', e) metadata['SizeX'] = None try: metadata['SizeY'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeY']) except KeyError as e: print('No Y Dimension :', e) metadata['SizeY'] = None try: metadata['SizeZ'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeZ']) except KeyError as e: print('No Z Dimension :', e) if dim2none: metadata['SizeZ'] = None if not dim2none: metadata['SizeZ'] = 1 try: metadata['SizeC'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeC']) except KeyError as e: print('No C Dimension :', e) if dim2none: metadata['SizeC'] = None if not dim2none: metadata['SizeC'] = 1 # get dimension of consitent 5D stack using AICSImageio #aics_img = AICSImage(filename) #metadata['czi_dims5D_aics'] = aics_img.dims.order #metadata['czi_shape5D_aics'] = aics_img.dims.shape #metadata['czi_dict5D_aics'] = aics_img.dims.__dict__ # create empty lists for channel related information channels = [] channels_names = [] channels_colors = [] # in case of only one channel if metadata['SizeC'] == 1: # get name for dye try: channels.append( metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel']['ShortName']) except KeyError as e: print('Channel shortname not found :', e) try: channels.append( metadatadict_czi['ImageDocument']['Metadata'] ['DisplaySetting']['Channels']['Channel']['DyeName']) except KeyError as e: print('Channel dye not found :', e) channels.append('Dye-CH1') # get channel name try: channels_names.append( metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel']['Name']) except KeyError as e: try: channels_names.append( metadatadict_czi['ImageDocument']['Metadata'] ['DisplaySetting']['Channels']['Channel']['@Name']) except KeyError as e: print('Channel name found :', e) channels_names.append('CH1') # get channel color try: channels_colors.append( metadatadict_czi['ImageDocument']['Metadata']['DisplaySetting'] ['Channels']['Channel']['Color']) except KeyError as e: print('Channel color not found :', e) channels_colors.append('#80808000') # in case of two or more channels if metadata['SizeC'] > 1: # loop over all channels for ch in range(metadata['SizeC']): # get name for dyes try: channels.append( metadatadict_czi['ImageDocument']['Metadata'] ['DisplaySetting']['Channels']['Channel'][ch]['ShortName']) except KeyError as e: print('Channel shortname not found :', e) try: channels.append(metadatadict_czi['ImageDocument'] ['Metadata']['DisplaySetting']['Channels'] ['Channel'][ch]['DyeName']) except KeyError as e: print('Channel dye not found :', e) channels.append('Dye-CH' + str(ch)) # get channel names try: channels_names.append( metadatadict_czi['ImageDocument']['Metadata'] ['DisplaySetting']['Channels']['Channel'][ch]['Name']) except KeyError as e: try: channels_names.append( metadatadict_czi['ImageDocument']['Metadata'] ['DisplaySetting']['Channels']['Channel'][ch]['@Name']) except KeyError as e: print('Channel name not found :', e) channels_names.append('CH' + str(ch)) # get channel colors try: channels_colors.append( metadatadict_czi['ImageDocument']['Metadata'] ['DisplaySetting']['Channels']['Channel'][ch]['Color']) except KeyError as e: print('Channel color not found :', e) # use grayscale instead channels_colors.append('80808000') # write channels information (as lists) into metadata dictionary metadata['Channels'] = channels metadata['ChannelNames'] = channels_names metadata['ChannelColors'] = channels_colors try: metadata['SizeT'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeT']) except KeyError as e: print('No T Dimension :', e) if dim2none: metadata['SizeT'] = None if not dim2none: metadata['SizeT'] = 1 try: metadata['SizeM'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeM']) except KeyError as e: print('No M Dimension :', e) if dim2none: metadata['SizeM'] = None if not dim2none: metadata['SizeM'] = 1 try: metadata['SizeB'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeB']) except KeyError as e: print('No B Dimension :', e) if dim2none: metadata['SizeB'] = None if not dim2none: metadata['SizeB'] = 1 try: metadata['SizeS'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeS']) except KeyError as e: print('No S Dimension :', e) if dim2none: metadata['SizeS'] = None if not dim2none: metadata['SizeS'] = 1 try: metadata['SizeH'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeH']) except KeyError as e: print('No H Dimension :', e) if dim2none: metadata['SizeH'] = None if not dim2none: metadata['SizeH'] = 1 try: metadata['SizeI'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeI']) except KeyError as e: print('No I Dimension :', e) if dim2none: metadata['SizeI'] = None if not dim2none: metadata['SizeI'] = 1 try: metadata['SizeV'] = np.int( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Image']['SizeV']) except KeyError as e: print('No V Dimension :', e) if dim2none: metadata['SizeV'] = None if not dim2none: metadata['SizeV'] = 1 # get the XY scaling information try: metadata['XScale'] = float( metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items'] ['Distance'][0]['Value']) * 1000000 metadata['YScale'] = float( metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items'] ['Distance'][1]['Value']) * 1000000 metadata['XScale'] = np.round(metadata['XScale'], 3) metadata['YScale'] = np.round(metadata['YScale'], 3) try: metadata['XScaleUnit'] = metadatadict_czi['ImageDocument'][ 'Metadata']['Scaling']['Items']['Distance'][0][ 'DefaultUnitFormat'] metadata['YScaleUnit'] = metadatadict_czi['ImageDocument'][ 'Metadata']['Scaling']['Items']['Distance'][1][ 'DefaultUnitFormat'] except (KeyError, TypeError) as e: print('Error extracting XY ScaleUnit :', e) metadata['XScaleUnit'] = None metadata['YScaleUnit'] = None except (KeyError, TypeError) as e: print('Error extracting XY Scale :', e) # get the Z scaling information try: metadata['ZScale'] = float( metadatadict_czi['ImageDocument']['Metadata']['Scaling']['Items'] ['Distance'][2]['Value']) * 1000000 metadata['ZScale'] = np.round(metadata['ZScale'], 3) # additional check for faulty z-scaling if metadata['ZScale'] == 0.0: metadata['ZScale'] = 1.0 try: metadata['ZScaleUnit'] = metadatadict_czi['ImageDocument'][ 'Metadata']['Scaling']['Items']['Distance'][2][ 'DefaultUnitFormat'] except (IndexError, KeyError, TypeError) as e: print('Error extracting Z ScaleUnit :', e) metadata['ZScaleUnit'] = metadata['XScaleUnit'] except (IndexError, KeyError, TypeError) as e: print('Error extracting Z Scale :', e) if dim2none: metadata['ZScale'] = None metadata['ZScaleUnit'] = None if not dim2none: # set to isotropic scaling if it was single plane only metadata['ZScale'] = metadata['XScale'] metadata['ZScaleUnit'] = metadata['XScaleUnit'] # convert scale unit to avoid encoding problems if convert_scunit: if metadata['XScaleUnit'] == 'µm': metadata['XScaleUnit'] = 'micron' if metadata['YScaleUnit'] == 'µm': metadata['YScaleUnit'] = 'micron' if metadata['ZScaleUnit'] == 'µm': metadata['ZScaleUnit'] = 'micron' # try to get software version try: metadata['SW-Name'] = metadatadict_czi['ImageDocument']['Metadata'][ 'Information']['Application']['Name'] metadata['SW-Version'] = metadatadict_czi['ImageDocument']['Metadata'][ 'Information']['Application']['Version'] except KeyError as e: print('Key not found:', e) metadata['SW-Name'] = None metadata['SW-Version'] = None try: metadata['AcqDate'] = metadatadict_czi['ImageDocument']['Metadata'][ 'Information']['Image']['AcquisitionDateAndTime'] except KeyError as e: print('Key not found:', e) metadata['AcqDate'] = None # check if Instrument metadata actually exist if pydash.objects.has( metadatadict_czi, ['ImageDocument', 'Metadata', 'Information', 'Instrument']): if metadatadict_czi['ImageDocument']['Metadata']['Information'][ 'Instrument'] is not None: # get objective data if isinstance( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives']['Objective'], list): num_obj = len( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives']['Objective']) else: num_obj = 1 # if there is only one objective found if num_obj == 1: try: metadata['ObjName'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives'] ['Objective']['Name']) except (KeyError, TypeError) as e: print('No Objective Name :', e) metadata['ObjName'].append(None) try: metadata['ObjImmersion'] = \ metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Objectives'][ 'Objective']['Immersion'] except (KeyError, TypeError) as e: print('No Objective Immersion :', e) metadata['ObjImmersion'] = None try: metadata['ObjNA'] = np.float( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives'] ['Objective']['LensNA']) except (KeyError, TypeError) as e: print('No Objective NA :', e) metadata['ObjNA'] = None try: metadata['ObjID'] = \ metadatadict_czi['ImageDocument']['Metadata']['Information']['Instrument']['Objectives'][ 'Objective']['Id'] except (KeyError, TypeError) as e: print('No Objective ID :', e) metadata['ObjID'] = None try: metadata['TubelensMag'] = np.float( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['TubeLenses']['TubeLens'] ['Magnification']) except (KeyError, TypeError) as e: print('No Tubelens Mag. :', e, 'Using Default Value = 1.0.') metadata['TubelensMag'] = 1.0 try: metadata['ObjNominalMag'] = np.float( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives'] ['Objective']['NominalMagnification']) except (KeyError, TypeError) as e: print('No Nominal Mag.:', e, 'Using Default Value = 1.0.') metadata['ObjNominalMag'] = 1.0 try: if metadata['TubelensMag'] is not None: metadata['ObjMag'] = metadata[ 'ObjNominalMag'] * metadata['TubelensMag'] if metadata['TubelensMag'] is None: print( 'Using Tublens Mag = 1.0 for calculating Objective Magnification.' ) metadata['ObjMag'] = metadata['ObjNominalMag'] * 1.0 except (KeyError, TypeError) as e: print('No Objective Magnification :', e) metadata['ObjMag'] = None if num_obj > 1: for o in range(num_obj): try: metadata['ObjName'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives'] ['Objective'][o]['Name']) except KeyError as e: print('No Objective Name :', e) metadata['ObjName'].append(None) try: metadata['ObjImmersion'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives'] ['Objective'][o]['Immersion']) except KeyError as e: print('No Objective Immersion :', e) metadata['ObjImmersion'].append(None) try: metadata['ObjNA'].append( np.float(metadatadict_czi['ImageDocument'] ['Metadata']['Information']['Instrument'] ['Objectives']['Objective'][o]['LensNA'])) except KeyError as e: print('No Objective NA :', e) metadata['ObjNA'].append(None) try: metadata['ObjID'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives'] ['Objective'][o]['Id']) except KeyError as e: print('No Objective ID :', e) metadata['ObjID'].append(None) try: metadata['TubelensMag'].append( np.float( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['TubeLenses'] ['TubeLens'][o]['Magnification'])) except KeyError as e: print('No Tubelens Mag. :', e, 'Using Default Value = 1.0.') metadata['TubelensMag'].append(1.0) try: metadata['ObjNominalMag'].append( np.float( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Objectives'] ['Objective'][o]['NominalMagnification'])) except KeyError as e: print('No Nominal Mag. :', e, 'Using Default Value = 1.0.') metadata['ObjNominalMag'].append(1.0) try: if metadata['TubelensMag'] is not None: metadata['ObjMag'].append( metadata['ObjNominalMag'][o] * metadata['TubelensMag'][o]) if metadata['TubelensMag'] is None: print( 'Using Tublens Mag = 1.0 for calculating Objective Magnification.' ) metadata['ObjMag'].append( metadata['ObjNominalMag'][o] * 1.0) except KeyError as e: print('No Objective Magnification :', e) metadata['ObjMag'].append(None) # get detector information # check if there are any detector entries inside the dictionary if pydash.objects.has(metadatadict_czi, [ 'ImageDocument', 'Metadata', 'Information', 'Instrument', 'Detectors' ]): if isinstance( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector'], list): num_detectors = len( metadatadict_czi['ImageDocument']['Metadata']['Information'] ['Instrument']['Detectors']['Detector']) else: num_detectors = 1 # if there is only one detector found if num_detectors == 1: # check for detector ID try: metadata['DetectorID'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] ['Id']) except KeyError as e: print('DetectorID not found :', e) metadata['DetectorID'].append(None) # check for detector Name try: metadata['DetectorName'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] ['Name']) except KeyError as e: print('DetectorName not found :', e) metadata['DetectorName'].append(None) # check for detector model try: metadata['DetectorModel'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] ['Manufacturer']['Model']) except KeyError as e: print('DetectorModel not found :', e) metadata['DetectorModel'].append(None) # check for detector type try: metadata['DetectorType'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] ['Type']) except KeyError as e: print('DetectorType not found :', e) metadata['DetectorType'].append(None) if num_detectors > 1: for d in range(num_detectors): # check for detector ID try: metadata['DetectorID'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] [d]['Id']) except KeyError as e: print('DetectorID not found :', e) metadata['DetectorID'].append(None) # check for detector Name try: metadata['DetectorName'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] [d]['Name']) except KeyError as e: print('DetectorName not found :', e) metadata['DetectorName'].append(None) # check for detector model try: metadata['DetectorModel'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] [d]['Manufacturer']['Model']) except KeyError as e: print('DetectorModel not found :', e) metadata['DetectorModel'].append(None) # check for detector type try: metadata['DetectorType'].append( metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Instrument']['Detectors']['Detector'] [d]['Type']) except KeyError as e: print('DetectorType not found :', e) metadata['DetectorType'].append(None) # check for well information metadata['Well_ArrayNames'] = [] metadata['Well_Indices'] = [] metadata['Well_PositionNames'] = [] metadata['Well_ColId'] = [] metadata['Well_RowId'] = [] metadata['WellCounter'] = None metadata['SceneStageCenterX'] = [] metadata['SceneStageCenterY'] = [] try: print('Trying to extract Scene and Well information if existing ...') # extract well information from the dictionary allscenes = metadatadict_czi['ImageDocument']['Metadata'][ 'Information']['Image']['Dimensions']['S']['Scenes']['Scene'] # loop over all detected scenes for s in range(metadata['SizeS']): if metadata['SizeS'] == 1: well = allscenes try: metadata['Well_ArrayNames'].append(allscenes['ArrayName']) except KeyError as e: try: metadata['Well_ArrayNames'].append(well['Name']) except KeyError as e: # print('Well Name not found :', e) try: metadata['Well_ArrayNames'].append(well['@Name']) except KeyError as e: # print('Well @Name not found :', e) print('Well Name not found :', e, 'Using A1 instead') metadata['Well_ArrayNames'].append('A1') try: metadata['Well_Indices'].append(allscenes['Index']) except KeyError as e: try: metadata['Well_Indices'].append(allscenes['@Index']) except KeyError as e: print('Well Index not found :', e) metadata['Well_Indices'].append(1) try: metadata['Well_PositionNames'].append(allscenes['Name']) except KeyError as e: try: metadata['Well_PositionNames'].append( allscenes['@Name']) except KeyError as e: print('Well Position Names not found :', e) metadata['Well_PositionNames'].append('P1') try: metadata['Well_ColId'].append( np.int(allscenes['Shape']['ColumnIndex'])) except KeyError as e: print('Well ColumnIDs not found :', e) metadata['Well_ColId'].append(0) try: metadata['Well_RowId'].append( np.int(allscenes['Shape']['RowIndex'])) except KeyError as e: print('Well RowIDs not found :', e) metadata['Well_RowId'].append(0) try: # count the content of the list, e.g. how many time a certain well was detected metadata['WellCounter'] = Counter( metadata['Well_ArrayNames']) except KeyError: metadata['WellCounter'].append(Counter({'A1': 1})) try: # get the SceneCenter Position sx = allscenes['CenterPosition'].split(',')[0] sy = allscenes['CenterPosition'].split(',')[1] metadata['SceneStageCenterX'].append(np.double(sx)) metadata['SceneStageCenterY'].append(np.double(sy)) except (TypeError, KeyError) as e: print('Stage Positions XY not found :', e) metadata['SceneStageCenterX'].append(0.0) metadata['SceneStageCenterY'].append(0.0) if metadata['SizeS'] > 1: try: well = allscenes[s] metadata['Well_ArrayNames'].append(well['ArrayName']) except KeyError as e: try: metadata['Well_ArrayNames'].append(well['Name']) except KeyError as e: # print('Well Name not found :', e) try: metadata['Well_ArrayNames'].append(well['@Name']) except KeyError as e: # print('Well @Name not found :', e) print('Well Name not found. Using A1 instead') metadata['Well_ArrayNames'].append('A1') # get the well information try: metadata['Well_Indices'].append(well['Index']) except KeyError as e: try: metadata['Well_Indices'].append(well['@Index']) except KeyError as e: print('Well Index not found :', e) metadata['Well_Indices'].append(None) try: metadata['Well_PositionNames'].append(well['Name']) except KeyError as e: try: metadata['Well_PositionNames'].append(well['@Name']) except KeyError as e: print('Well Position Names not found :', e) metadata['Well_PositionNames'].append(None) try: metadata['Well_ColId'].append( np.int(well['Shape']['ColumnIndex'])) except KeyError as e: print('Well ColumnIDs not found :', e) metadata['Well_ColId'].append(None) try: metadata['Well_RowId'].append( np.int(well['Shape']['RowIndex'])) except KeyError as e: print('Well RowIDs not found :', e) metadata['Well_RowId'].append(None) # count the content of the list, e.g. how many time a certain well was detected metadata['WellCounter'] = Counter(metadata['Well_ArrayNames']) # try: if isinstance(allscenes, list): try: # get the SceneCenter Position sx = allscenes[s]['CenterPosition'].split(',')[0] sy = allscenes[s]['CenterPosition'].split(',')[1] metadata['SceneStageCenterX'].append(np.double(sx)) metadata['SceneStageCenterY'].append(np.double(sy)) except KeyError as e: print('Stage Positions XY not found :', e) metadata['SceneCenterX'].append(0.0) metadata['SceneCenterY'].append(0.0) if not isinstance(allscenes, list): metadata['SceneStageCenterX'].append(0.0) metadata['SceneStageCenterY'].append(0.0) # count the number of different wells metadata['NumWells'] = len(metadata['WellCounter'].keys()) except (KeyError, TypeError) as e: print('No valid Scene or Well information found:', e) # get additional meta data about the experiment etc. metadata_add = get_additional_metadata_czi(metadatadict_czi) return metadata, metadata_add
def open_image_stack(filepath): """ Open a file using AICSImageIO and display it using napari :param path: filepath of the image :type path: str """ if os.path.isfile(filepath): # remove existing layers from napari viewer.layers.select_all() viewer.layers.remove_selected() # get the metadata metadata, add_metadata = czt.get_metadata_czi(filepath) # add the global metadata and adapt the table display mdbrowser.update_metadata(metadata) mdbrowser.update_style() use_aicsimageio = True use_pylibczi = False # decide which tool to use to read the image if metadata['ImageType'] != 'czi': use_aicsimageio = True elif metadata['ImageType'] == 'czi' and metadata['isMosaic'] is False: use_aicsimageio = True elif metadata['ImageType'] == 'czi' and metadata['isMosaic'] is True: use_aicsimageio = False use_pylibczi = True """ # check if CZI has T or Z dimension hasT = False hasZ = False if 'T' in metadata['dims_aicspylibczi']: hasT = True if 'Z' in metadata['dims_aicspylibczi']: hasZ = True """ if use_aicsimageio: # get AICSImageIO object img = AICSImage(filepath) # check if the Dask Delayed Reader should be used if not checkboxes.cbox_dask.isChecked(): print('Using AICSImageIO normal ImageReader.') all_scenes_array = img.get_image_data() if checkboxes.cbox_dask.isChecked(): print('Using AICSImageIO Dask Delayed ImageReader') all_scenes_array = img.get_image_dask_data() if not use_aicsimageio and use_pylibczi is True: # read CZI using aicspylibczi czi = CziFile(filepath) # Get the shape of the data print('Dimensions : ', czi.dims) print('Size : ', czi.size) print('Shape : ', czi.dims_shape()) print('IsMoasic : ', czi.is_mosaic()) if czi.is_mosaic(): print('Mosaic Size : ', czi.read_mosaic_size()) # get the required shape for all and single scenes shape_all, shape_single, same_shape = czt.get_shape_allscenes(czi, metadata) print('Required_Array Shape for all scenes: ', shape_all) for sh in shape_single: print('Required Array Shape for single scenes: ', sh) if not same_shape: print('No all scenes have the same shape. Exiting ...') sys.exit() #array_type = 'dask' array_type = 'zarr' #array_type = 'numpy' if array_type == 'zarr': # define array to store all channels print('Using aicspylibCZI to read the image (ZARR array).') # option 1 all_scenes_array = zarr.create(tuple(shape_all), dtype=metadata['NumPy.dtype'], chunks=True) # option 2 # all_scenes_array = zarr.open(r'c:\Temp\czi_scene_all.zarr', mode='w', # shape=shape_all, # chunks=True, # dtype=md['NumPy.dtype']) if array_type == 'numpy': print('Using aicspylibCZI to read the image (Numpy.Array).') all_scenes_array = np.empty(shape_all, dtype=metadata['NumPy.dtype']) if array_type == 'zarr' or array_type == 'numpy': # loop over all scenes for s in range(metadata['SizeS']): # get the CZIscene for the current scene single_scene = czt.CZIScene(czi, metadata, sceneindex=s) out = czt.read_czi_scene(czi, single_scene, metadata) all_scenes_array[s, :, :, :, :, :] = np.squeeze(out, axis=0) print(all_scenes_array.shape) elif array_type == 'dask': def dask_load_sceneimage(czi, s, md): # get the CZIscene for the current scene single_scene = czt.CZIScene(czi, md, sceneindex=s) out = czt.read_czi_scene(czi, single_scene, md) return out sp = shape_all[1:] # create dask stack of lazy image readers print('Using aicspylibCZI to read the image (Dask.Array) + Delayed Reading.') lazy_process_image = dask.delayed(dask_load_sceneimage) # lazy reader lazy_arrays = [lazy_process_image(czi, s, metadata) for s in range(metadata['SizeS'])] dask_arrays = [ da.from_delayed(lazy_array, shape=sp, dtype=metadata['NumPy.dtype']) for lazy_array in lazy_arrays ] # Stack into one large dask.array all_scenes_array = da.stack(dask_arrays, axis=0) print(all_scenes_array.shape) do_scaling = checkboxes.cbox_autoscale.isChecked() # show the actual image stack nap.show_napari(viewer, all_scenes_array, metadata, blending='additive', adjust_contrast=do_scaling, gamma=0.85, add_mdtable=False, rename_sliders=True)
def read_mosaic(filename: str, scale: float=1.0) -> Tuple[Union[np.ndarray, None], czimd.CziMetadata]: """Read the pixel data of an CZI image file with an option scale factor to read the image with lower resolution and array size :param filename: filename of the CZI mosaic file to be read :param scale: scaling factor when reading the mosaic. :return: CZI pixel data and the updated CziMetadata class """ # do not allow scale > 1.0 if scale > 1.0: print("Scale factor > 1.0 is not recommended. Using scale = 1.0.") scale = 1.0 # get the CZI metadata md = czimd.CziMetadata(filename) # read CZI using aicspylibczi aicsczi = CziFile(filename) if not aicsczi.is_mosaic(): # check if this CZI is really a non-mosaic file print("CZI is not a mosaic file. Please use the read_nonmosaic method instead") return None, md # get data for 1st scene and create the required shape for all scenes scene = czimd.CziScene(aicsczi, sceneindex=0) shape_all = scene.shape_single_scene if scene.hasS: shape_all[scene.posS] = md.dims.SizeS if not scene.hasS: num_scenes = 1 print("Shape all Scenes (scale=1.0): ", shape_all) print("DimString all Scenes : ", scene.single_scene_dimstr) # create empty array to hold all scenes all_scenes = np.empty(shape_all, dtype=md.npdtype) resize_done = False # loop over scenes if CZI is not Mosaic for s in range(num_scenes): scene = czimd.CziScene(aicsczi, sceneindex=s) # create a slice object for all_scenes array if not scene.isRGB: #idl_all = [slice(None, None, None)] * (len(all_scenes.shape) - 2) idl_all = [slice(None, None, None)] * (len(shape_all) - 2) if scene.isRGB: #idl_all = [slice(None, None, None)] * (len(all_scenes.shape) - 3) idl_all = [slice(None, None, None)] * (len(shape_all) - 3) # update the entry with the current S index if not scene.hasS: idl_all[s] = s if scene.hasS: idl_all[scene.posS] = s # in case T-Z-H dimension are found if scene.hasT is True and scene.hasZ is True and scene.hasH is True: # read array for the scene for h, t, z, c in product(range(scene.sizeH), range(scene.sizeT), range(scene.sizeZ), range(scene.sizeC)): # read the array for the 1st scene using the ROI scene_array_htzc = aicsczi.read_mosaic(region=(scene.xstart, scene.ystart, scene.width, scene.height), scale_factor=scale, H=h, T=t, Z=z, C=c) print("Shape Single Scene (Scalefactor: ", scale, ": ", scene_array_htzc.shape) # check if all_scenes array must be resized due to scaling if scale < 1.0 and not resize_done: shape_all[-1] = scene_array_htzc.shape[-1] shape_all[-2] = scene_array_htzc.shape[-2] all_scenes = np.resize(all_scenes, shape_all) # add new entries to metadata md = adaptmd_scale(md, scene_array_htzc.shape[-1], scene_array_htzc.shape[-2], scale=scale) resize_done = True # create slide object for the current mosaic scene # idl_scene = [slice(None, None, None)] * (len(scene.shape_single_scene) - 2) idl_all[scene.posS] = s idl_all[scene.posH] = h idl_all[scene.posT] = t idl_all[scene.posZ] = z idl_all[scene.posC] = c # cast the current scene into the stack for all scenes all_scenes[tuple(idl_all)] = scene_array_htzc # in case T-Z-H dimension are found if scene.hasT is True and scene.hasZ is True and scene.hasH is False: # read array for the scene for t, z, c in product(range(scene.sizeT), range(scene.sizeZ), range(scene.sizeC)): # read the array for the 1st scene using the ROI scene_array_tzc = aicsczi.read_mosaic(region=(scene.xstart, scene.ystart, scene.width, scene.height), scale_factor=scale, T=t, Z=z, C=c) print("Shape Single Scene (Scalefactor: ", scale, ": ", scene_array_tzc.shape) # check if all_scenes array must be resized due to scaling if scale < 1.0 and not resize_done: shape_all[-1] = scene_array_tzc.shape[-1] shape_all[-2] = scene_array_tzc.shape[-2] all_scenes = np.resize(all_scenes, shape_all) # add new entries to metadata md = adaptmd_scale(md, scene_array_tzc.shape[-1], scene_array_tzc.shape[-2], scale=scale) resize_done = True # create slide object for the current mosaic scene # idl_scene = [slice(None, None, None)] * (len(scene.shape_single_scene) - 2) idl_all[scene.posS] = s idl_all[scene.posT] = t idl_all[scene.posZ] = z idl_all[scene.posC] = c # cast the current scene into the stack for all scenes all_scenes[tuple(idl_all)] = scene_array_tzc if scene.hasT is False and scene.hasZ is False: # create an array for the scene for c in range(scene.sizeC): scene_array_c = aicsczi.read_mosaic(region=(scene.xstart, scene.ystart, scene.width, scene.height), scale_factor=scale, C=c) print("Shape Single Scene (Scalefactor: ", scale, ": ", scene_array_c.shape) # check if all_scenes array must be resized due to scaling if scale < 1.0 and not resize_done: #new_shape = shape_all shape_all[-1] = scene_array_c.shape[-1] shape_all[-2] = scene_array_c.shape[-2] all_scenes = np.resize(all_scenes, shape_all) # add new entries to metadata md = adaptmd_scale(md, scene_array_c.shape[-1], scene_array_c.shape[-2], scale=scale) resize_done = True idl_all[scene.posS] = s idl_all[scene.posC] = c # cast the current scene into the stack for all scenes all_scenes[tuple(idl_all)] = scene_array_c return all_scenes, md
from lxml import etree as ET import imgfile_tools as imf import numpy as np filename = r"C:\Users\m1srh\OneDrive - Carl Zeiss AG\Smart_Microscopy_Workshop\datasets\OverViewScan.czi" metadata = {} # get metadata dictionary using aicspylibczi czi_aicspylibczi = CziFile(filename) metadatadict_czi = xmltodict.parse(ET.tostring(czi_aicspylibczi.meta)) # Get the shape of the data, the coordinate pairs are (start index, size) metadata['dims_aicspylibczi'] = czi_aicspylibczi.dims_shape()[0] metadata['axes_aicspylibczi'] = czi_aicspylibczi.dims metadata['size_aicspylibczi'] = czi_aicspylibczi.size metadata['czi_isMosaic'] = czi_aicspylibczi.is_mosaic() print('CZI is Mosaic :', metadata['czi_isMosaic']) metadata['SizeS'] = np.int(metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Image']['SizeS']) metadata['SizeT'] = np.int(metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Image']['SizeT']) metadata['SizeZ'] = np.int(metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Image']['SizeZ']) metadata['SizeC'] = np.int(metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Image']['SizeC']) metadata['SizeX'] = np.int(metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Image']['SizeX']) metadata['SizeY'] = np.int(metadatadict_czi['ImageDocument']['Metadata'] ['Information']['Image']['SizeY'])
# define save format for mask adapt_dtype_mask = True dtype_mask = np.int8 # check if it makes sense if minholesize > minsize: minsize = minholesize # read the czi mosaic image czi = CziFile(filename) # Get the shape of the data print('Dimensions : ', czi.dims) print('Size : ', czi.size) print('Shape : ', czi.dims_shape()) print('IsMosaic : ', czi.is_mosaic()) # read the mosaic pixel data mosaic = czi.read_mosaic(C=0, scale_factor=1.0) print('Mosaic Shape :', mosaic.shape) image2d = np.squeeze(mosaic, axis=0) md['SizeX_readmosaic'] = image2d.shape[1] md['SizeY_readmosaic'] = image2d.shape[0] image_counter = 0 results = pd.DataFrame() # create the savename for the OME-TIFF savename = filename.split('.')[0] + '.ome.tiff' #savename = filename.split('.')[0] + '.tiff'
print('SizeC : ', md['SizeC']) print('SizeX (czifile) : ', md['SizeX']) print('SizeY (czifile) : ', md['SizeY']) print('SizeY (aicsimageio) : ', md['SizeX_aics']) print('SizeY (aicsimageio) : ', md['SizeY_aics']) #################### czi = CziFile(filename) # Get the shape of the data, the coordinate pairs are (start index, size) dimensions = czi.dims_shape() print('CZI Dimensions : ', dimensions) print('CZI DimeString : ', czi.dims) print('CZI Size : ', czi.size) print('CZI IsMosaic : ', czi.is_mosaic()) print('CZI Scene Shape consistent : ', czi.shape_is_consistent) if md['ImageType'] == 'czi': isCZI = True else: isCZI = False if md['czi_isRGB']: isRGB = True else: isRGB = False if md['czi_isMosaic']: isMosaic = True else: