def test_bgr_plane_data_x(data_dir, fname, p_index, ans_file): ans = np.load(data_dir / ans_file) with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) img, dims = czi.read_image() assert img[0, p_index, :, :].shape == ans.shape np.testing.assert_array_almost_equal(img[0, p_index, :, :], ans)
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_image( img: Path, read_dims: Optional[Dict[str, int]] = None ) -> Tuple[np.ndarray, List[Tuple[str, int]]]: # Catch optional read dim if read_dims is None: read_dims = {} # Init czi czi = CziFile(img) # Read image log.debug(f"Reading dimensions: {read_dims}") data, dims = czi.read_image(**read_dims) # Drop dims that shouldn't be provided back ops = [] real_dims = [] for i, dim_info in enumerate(dims): # Expand dimension info dim, size = dim_info # If the dim was provided in the read dims we know a single plane for that # dimension was requested so remove it if dim in read_dims: ops.append(0) # Otherwise just read the full slice else: ops.append(slice(None, None, None)) real_dims.append(dim_info) # Convert ops and run getitem return data[tuple(ops)], real_dims
def test_mosaic_image_two(data_dir, fname, expects): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) sze = czi.read_mosaic_size() rgion = (sze[0], sze[1], int(sze[2] / 2), int(sze[3] / 2)) img = czi.read_mosaic(region=rgion, C=0, M=0) assert img.shape == expects
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 test_mosaic_image(data_dir, fname, expects): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) sze = czi.read_mosaic_size() assert sze[2] == 1756 assert sze[3] == 624 img = czi.read_mosaic(scale_factor=0.1, C=0) assert img.shape[0] == 1
def test_read_image_from_istream(data_dir, fname, expected_img_shape, expected_img_dims): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) assert czi.shape_is_consistent data = czi.read_image() assert data[0].shape == expected_img_shape assert data[1] == expected_img_dims
def _daread_safe( img: Union[str, Path], chunk_by_dims: List[str] = [ Dimensions.SpatialZ, Dimensions.SpatialY, Dimensions.SpatialX, ], S: int = 0, ) -> Tuple[da.core.Array, str]: """ Safely read a CZI image file as a delayed dask array where certain dimensions act as the chunk size. Parameters ---------- img: Union[str, Path] The filepath to read. chunk_by_dims: List[str] The dimensions to use as the for mapping the chunks / blocks. Default: [Dimensions.SpatialZ, Dimensions.SpatialY, Dimensions.SpatialX] Note: SpatialY and SpatialX will always be added to the list if not present. S: int If the image has different dimensions on any scene from another, the dask array construction will fail. In that case, use this parameter to specify a specific scene to construct a dask array for. Default: 0 (select the first scene) Returns ------- img: dask.array.core.Array The constructed dask array where certain dimensions are chunked. dims: str The dimension order as a string. """ # Resolve image path img = CziReader._resolve_image_path(img) # Init temp czi czi = CziFile(img) # Safely construct the dask array or catch any exception try: return CziReader._daread(img=img, czi=czi, chunk_by_dims=chunk_by_dims, S=S) except Exception as e: # A really bad way to close any connection to the CZI object czi._bytes = None czi.reader = None raise e
def _read_image( img: Path, read_dims: Optional[Dict[str, int]] = None ) -> Tuple[np.ndarray, List[Tuple[str, int]]]: """ Read and return the squeezed image data requested along with the dimension info that was read. Parameters ---------- img: Path Path to the CZI file to read. read_dims: Optional[Dict[str, int]] The dimensions to read from the file as a dictionary of string to integer. Default: None (Read all data from the image) Returns ------- data: np.ndarray The data read for the dimensions provided. read_dimensions: List[Tuple[str, int]]] The dimension sizes that were returned from the read. """ # Catch optional read dim if read_dims is None: read_dims = {} # Init czi czi = CziFile(img) # Read image log.debug(f"Reading dimensions: {read_dims}") data, dims = czi.read_image(**read_dims) # Drop dims that shouldn't be provided back ops = [] real_dims = [] for i, dim_info in enumerate(dims): # Expand dimension info dim, size = dim_info # If the dim was provided in the read dims we know a single plane for that # dimension was requested so remove it if dim in read_dims: ops.append(0) # Otherwise just read the full slice else: ops.append(slice(None, None, None)) real_dims.append(dim_info) # Convert ops and run getitem return data[tuple(ops)], real_dims
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)
def test_metadata(data_dir, fname, xp_query, expected): czi = CziFile(str(data_dir / fname), metafile_out="tmp.txt") meta = czi.meta vs = meta.find(xp_query) assert int(vs.text) == expected meta = czi.meta vs = meta.find(xp_query) assert int(vs.text) == expected
def metadata(self) -> _Element: """ Load and return the metadata from the CZI file Returns ------- The lxml Element Tree of the metadata """ # We can't serialize lxml element trees so don't save the tree to the object state return CziFile(self._file).meta
def _read_immediate(self) -> da.core.Array: # Init temp czi czi = CziFile(self._file) # Safely construct the numpy array or catch any exception try: # Get image dims indicies image_dim_indices = czi.dims_shape() # Catch inconsistent scene dimension sizes if len(image_dim_indices) > 1: # Choose the provided scene log.info( f"File contains variable dimensions per scene, " f"selected scene: {self.specific_s_index} for data retrieval." ) # Get the specific scene if self.specific_s_index < len(image_dim_indices): data, _ = czi.read_image( **{Dimensions.Scene: self.specific_s_index}) else: raise exceptions.InconsistentShapeError( f"The CZI image provided has variable dimensions per scene. " f"Please provide a valid index to the 'S' parameter to create " f"a dask array for the index provided. " f"Provided scene index: {self.specific_s_index}. " f"Scene index range: 0-{len(image_dim_indices)}.") else: # If the list is length one that means that all the scenes in the image # have the same dimensions # Read all data in the image data, _ = czi.read_image() # A really bad way to close any connection to the CZI object czi._bytes = None czi.reader = None except Exception as e: # A really bad way to close any connection to the CZI object czi._bytes = None czi.reader = None raise e return data
def load_tile(coords, slide_path, data_mask, region_mask, width, downsample, fast): """Load a tile from the czi-file (parallizeable).""" # Load reader. reader = CziFile(slide_path) # Unpack coords. i, (x, y) = coords # Define final out_shape. out_shape = (int(width/downsample), int(width/downsample)) # Get data and region percentages. tile_mask = Polygon( [[x, y], [x+width, y], [x+width, y+width], [x, y+width], [x, y]]) intersection = tile_mask.intersection(data_mask) data_perc = intersection.area/tile_mask.area region_perc = tile_mask.intersection(region_mask).area/tile_mask.area if data_perc < 0.05 or region_perc < 1: # Return empty image. tile = np.ones(out_shape + (3,)) * 255 else: # Load tile. bbox = (x, y, width, width) if fast: tile = reader.read_mosaic(bbox, C=0, scale_factor=1/downsample) else: tile = reader.read_mosaic(bbox, C=0) if tile.shape[0] == 1: # Something is wrong with the tile... tile = np.ones(out_shape + (3,)) * 255 else: tile = np.moveaxis(tile, 0, 2) tile = cv2.resize(tile, out_shape, cv2.INTER_LANCZOS4) if data_perc < 1: mask = polygon_to_mask(intersection, x, y, width, downsample) mask = cv2.resize(mask, out_shape, cv2.INTER_LANCZOS4) tile[mask == 0] = 255 tile = tile.astype(np.uint8) return i, tile
def test_read_image_mosaic(data_dir, fname): czi = CziFile(str(data_dir / fname)) czi.read_image(M=0) assert True
def test_mosaic_subblock_rect(data_dir, fname, s_index, m_index, expected): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) data = czi.mosaic_scene_bounding_boxes(s_index) assert data == expected
def test_cores_arg(): assert CziFile._get_cores_from_kwargs({'cores': 4}) == 4
def test_subblock_rect(data_dir, fname, s_index, m_index, expected): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) args = {'S': s_index} if m_index < 0 else {'S': s_index, 'M': m_index} data = czi.read_subblock_rect(**args) assert data == expected
def test_collected_by(data_dir, filename, expected_creator): czi = CziFile(data_dir / filename) assert czi_metadata.created_by(czi) == expected_creator
for d in dims: dims_dict[d] = dimstring.find(d) dimindex_list.append(dimstring.find(d)) numvalid_dims = sum(i > 0 for i in dimindex_list) 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
hasZ = True if use_aicsimageio: img = AICSImage(filename) if use_dask_delayed: print('Using AICSImageIO to read the image (Dask Delayed Reader).') 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)
def test_read_image_two(data_dir, fname, exp_str, exp_dict): czi = CziFile(str(data_dir / fname)) dims = czi.dims dim_dict = czi.dims_shape() assert dims == exp_str assert dim_dict == exp_dict
def test_read_dims_sizes(data_dir, fname, expected): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) data = czi.size assert data == expected
def test_read_subblock_meta(data_dir, fname, expected): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) data = czi.read_subblock_metadata() assert expected in data[0][1]
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
def test_read_unified_subblock_meta(data_dir, fname, expected): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) data = czi.read_subblock_metadata(unified_xml=True) assert expected in etree.tostring(data)
def test_datetime_created(data_dir, filename, expected_datetime): czi = CziFile(data_dir / filename) assert czi_metadata.datetime_created(czi) == expected_datetime
def test_conversion_types(in_, out_): ans = CziFile.convert_to_buffer(in_) assert ans.__class__ == out_.__class__
def test_channel_names(data_dir, filename, expected_channels): czi = CziFile(data_dir / filename) assert czi_metadata.channel_names(czi) == expected_channels
def test_image_shape(data_dir, fname, expects): with open(data_dir / fname, 'rb') as fp: czi = CziFile(czi_filename=fp) shape = czi.dims_shape() assert shape == expects