def tifffile_arr(fname, verbose=False): """Convert tif to array using tifffile : :Source: tifffile # http://www.lfd.uci.edu/~gohlke/code/tifffile.py.html :Requires: from tifffile import imread, TiffFile : fname - full tiff file path and filename : verbose - True to print all information gleaned :Useage: :(1) a = imread(fname) ... or :(2) TiffFile.asarray(self, key=None, series=None, out=None, maxworkers=1) : key - int, slice, or sequence of page indices : Defines which pages to return as array. : series - int or TiffPageSeries : out - array if None or filename : maxworkers = default 1, number of threads to use to get data :Extra info: : kys = tif.__dict__.keys() : for k in kys: : print("{!s:<15}: {!s:<30}".format(k, tif.__dict__[k])) """ with TiffFile(fname) as tif: if verbose: print("\nTiff file: {}\nflags: {}".format(fname, tif.flags)) if tif.is_shaped and verbose: print("Shape info: {}\n".format(tif.shaped_metadata)) if tif.is_geotiff and verbose: print("Geotiff info:") d = tif.geotiff_metadata for key in d.keys(): print("- {}: {}".format(key, d[key])) # a = tif.asarray() # if tif.is_tiled: a = np.rollaxis(a, axis=2, start=0) return a, tif # uncomment and return tif for testing
def planes_data(self, klist, color_component, channel, time): ''' Read multiple planes using tifffile.py which is about 5 times faster than Pillow. ''' nc = self.nchannels pbase = 0 if channel is not None: pbase += channel if time is not None: nz = self.grid_size[2] pbase += nz*nc*time plist = [pbase + k for k in klist] if nc == 1 else [pbase + nc*k for k in klist] from tifffile import TiffFile with TiffFile(self.path) as tif: a = tif.asarray(key = plist) if a.ndim == 4: a = a[:,:,:,color_component] elif a.ndim == 2: a = a.reshape((1,) + tuple(a.shape)) # Make single-plane 3d return a
def getOrthoTif(fileName, zfBytes): fileName = fileName[fileName.rfind('/') + 1:] # Given a zipfile as bytes (i.e. from reading from a binary file), # Return a np array of rgbx values for each pixel bytesio = io.BytesIO(zfBytes) zfiles = zipfile.ZipFile(bytesio, "r") # find tif: for fn in zfiles.namelist(): if fn[-4:] == '.tif': # found it, turn into array: tif = TiffFile(io.BytesIO(zfiles.open(fn).read())) arr = tif.asarray(); # Divide image in 500 * 500 size res = [] factor = int(arr.shape[0]/500) hArr = np.split(arr, factor, axis=0) count = 0 for h in hArr: vArr = np.split(h, factor, axis = 1) for v in vArr: name = fileName + "-" + str(count) res.append((name, v)) count += 1 return res
def __init__(self, im_path, rG_background, haloTag_channel=2, rG_channel=1): if im_path[-4:] == '.nd2': self.image = [] with ND2Reader(im_path) as nd2: for channel in range(3): self.image.append(nd2[channel]) elif im_path[-4:] == '.tif': with TiffFile(im_path) as tif: self.image = tif.asarray() else: print( "check yo extension. I found '{}'. I can only use '.nd2' or '.tif'." .format(im_path[-4:])) self.haloTag_channel = haloTag_channel self.rG_channel = rG_channel self.rG_background = rG_background self.haloTag_threshold = None self.granule_count = None self.granule_mask = None self.ratios = []
def __init__(self, path): self.warning = '' self.path = path self.tilesize = 1024 ext = check_ext(path) if ext == '.ome.tif' or ext == '.ome.tiff': self.io = TiffFile(self.path, is_ome=False) self.group = zarr.open(self.io.series[0].aszarr()) self.reader = 'tifffile' self.ome_version = self._get_ome_version() print("OME ", self.ome_version) num_channels = self.get_shape()[0] tile_0 = self.get_tifffile_tile(num_channels, 0, 0, 0, 0) if (num_channels == 3 and tile_0.dtype == 'uint8'): self.rgba = True self.rgba_type = '3 channel' elif (num_channels == 1 and tile_0.dtype == 'uint8'): self.rgba = True self.rgba_type = '1 channel' else: self.rgba = False self.rgba_type = None else: self.io = OpenSlide(self.path) self.dz = DeepZoomGenerator(self.io, tile_size=1024, overlap=0, limit_bounds=True) self.reader = 'openslide' self.rgba = True self.rgba_type = None print("RGB ", self.rgba) print("RGB type ", self.rgba_type)
def read_movie(self): # Read info.txt self.info = {} with open(Path(self.dir / 'info.txt')) as f: for line in f: line = line.replace(" ", "") # remove white space if line == '\n': # skip empty line continue (key, value) = line.rstrip().split("=") self.info[key] = value self.dt = float(self.info['time_interval']) self.spot_size = int(self.info['spot_size']) self.save_trace = int(self.info['save_trace']) # Read movie.tif with TiffFile(self.path) as tif: imagej_hyperstack = tif.asarray() imagej_metadata = str(tif.imagej_metadata) self.metadata = imagej_metadata.split(',') # write meta_data with open(self.path.parent / 'meta_data.txt', 'w') as f: for item in imagej_metadata: f.write(item + '\n') # Crop the image to make the size integer multiple of 10 self.bin_size = 20 self.n_frame = np.size(imagej_hyperstack, 0) n_row = np.size(imagej_hyperstack, 1) self.n_row = int(int(n_row / self.bin_size) * self.bin_size) n_col = np.size(imagej_hyperstack, 2) self.n_col = int(int(n_col / self.bin_size) * self.bin_size) self.I_original = imagej_hyperstack[:, :self.n_row, :self.n_col] print('[frame, row, col] = [%d, %d, %d]' % (self.n_frame, self.n_row, self.n_col))
def __init__(self, wildcard): if isinstance(wildcard, list): self._files = sorted(map(os.path.abspath, wildcard), key=lambda x: x.split('/')[-1]) else: self._files = sorted(map(os.path.abspath, glob(wildcard)), key=lambda x: x.split('/')[-1]) self._stacks = [TiffFile(file, fastij=True) for file in self._files] self._n = [len(s.pages) for s in self._stacks] self._ntiffs = sum(self._n) self.load_header() self._i2j = np.vstack([ np.c_[i * np.ones(nn), np.arange(nn)] for i, nn in enumerate(self._n) ]).astype(int) if not self.is_structural: self._idx = np.reshape( np.arange(self._ntiffs, dtype=int), (self.nframes, self.nslices, self.nchannels)).transpose() else: self._idx = np.reshape(np.arange(self._ntiffs, dtype=int), (self.nslices, self.nframes, self.nchannels)).transpose([2, 0, 1]) self._img_dim = None
def __init__(self, file_like, permission='r', keep_file_open=True, **hints): """ Parameters ---------- file_like : str or file object keep_file_open : bool, default=True Whether to keep the file handle open hints : keyword of the form `is_<format>=<True|False>` Tells the Tiff reader that a file is or isn't of a specific subformat. If not provided, it it guessed by the Tiff reader. """ self._tiff = TiffFile(file_like, **hints) if not keep_file_open: self._tiff.close() self._series = 0 self._level = 0 self._cache = dict() super().__init__()
def tiff_files(self): if self._tiff_files is None: self._tiff_files = [ TiffFile(filename) for filename in self.filenames ] return self._tiff_files
def generate_new_metadata(img_paths, target_shape): ncycles = len(img_paths) time = [] planes = [] channels = [] metadata_list = [] phys_size_x_list = [] phys_size_y_list = [] for i in range(0, len(img_paths)): with TiffFile(img_paths[i]) as TF: img_axes = list(TF.series[0].axes) img_shape = TF.series[0].shape ome_meta = TF.ome_metadata metadata_list.append(ome_meta) for meta in metadata_list: pixels_info = extract_pixels_info(str_to_xml(meta)) time.append(pixels_info['SizeT']) planes.append(pixels_info['SizeZ']) channels.append(pixels_info['SizeC']) phys_size_x_list.append(pixels_info['PhysicalSizeX']) phys_size_y_list.append(pixels_info['PhysicalSizeY']) max_time = max(time) max_planes = max(planes) total_channels = sum(channels) max_phys_size_x = max(phys_size_x_list) max_phys_size_y = max(phys_size_y_list) sizes = { 'SizeX': str(target_shape[1]), 'SizeY': str(target_shape[0]), 'SizeC': str(total_channels), 'SizeZ': str(max_planes), 'SizeT': str(max_time), 'PhysicalSizeX': str(max_phys_size_x), 'PhysicalSizeY': str(max_phys_size_y) } # use metadata from first image as reference metadata ref_xml = str_to_xml(metadata_list[0]) # set proper ome attributes tags proper_ome_attribs = { 'xmlns': 'http://www.openmicroscopy.org/Schemas/OME/2016-06', 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation': 'http://www.openmicroscopy.org/Schemas/OME/2016-06 http://www.openmicroscopy.org/Schemas/OME/2016-06/ome.xsd' } ref_xml.attrib.clear() for attr, val in proper_ome_attribs.items(): ref_xml.set(attr, val) # set new dimension sizes for attr, size in sizes.items(): ref_xml.find('Image').find('Pixels').set(attr, size) # remove old channels and tiffdata old_channels = ref_xml.find('Image').find('Pixels').findall('Channel') for ch in old_channels: ref_xml.find('Image').find('Pixels').remove(ch) tiffdata = ref_xml.find('Image').find('Pixels').findall('TiffData') if tiffdata is not None or tiffdata != []: for td in tiffdata: ref_xml.find('Image').find('Pixels').remove(td) # add new channels write_format = '0' + str(len(str( ncycles)) + 1) + 'd' # e.g. for number 5 format = 02d, result = 05 channel_id = 0 for i in range(0, ncycles): channels, channel_names, channel_ids, channel_fluors, num_channels_per_cycle, num_zplanes_per_channel = extract_channel_info( str_to_xml(metadata_list[i])) cycle_name = 'c' + format(i + 1, write_format) + ' ' new_channel_names = [cycle_name + ch for ch in channel_names] for ch in range(0, len(channels)): new_channel_id = 'Channel:0:' + str(channel_id) new_channel_name = new_channel_names[ch] channels[ch].set('Name', new_channel_name) channels[ch].set('ID', new_channel_id) ref_xml.find('Image').find('Pixels').append(channels[ch]) channel_id += 1 # add new tiffdata ifd = 0 for t in range(0, max_time): for c in range(0, total_channels): for z in range(0, max_planes): ET.SubElement( ref_xml.find('Image').find('Pixels'), "TiffData", dict(FirstC=str(c), FirstT=str(t), FirstZ=str(z), IFD=str(ifd), PlaneCount=str(1))) ifd += 1 xml_declaration = '<?xml version="1.0" encoding="UTF-8"?>' result_ome_meta = xml_declaration + ET.tostring( ref_xml, method='xml', encoding='utf-8').decode('ascii', errors='ignore') return result_ome_meta
def mpacts_input_generator(param_xml, filehandler): def read_parms(param_xml): d_parm= {} param_xml.l_main_keys = ['body', 'mpacts_input_generator'] d_parm['input_file_csv'] = param_xml.get_value('input_file_csv', ['paths']) d_parm['input_file_frangi'] = param_xml.get_value('input_file_frangi', ['paths']) d_parm['input_file_threshold'] = param_xml.get_value('input_file_threshold', ['paths']) d_parm['output_folder'] = param_xml.get_value('output_folder', ['paths']) d_parm['nb_stack'] = param_xml.get_value('nb_stack', ['process_flow']) d_parm['nb_stack_timelapse'] = param_xml.get_value('nb_stack_timelapse', ['process_flow']) d_parm['shrink_spheres'] = param_xml.get_value('shrink_spheres', ['process_flow']) d_parm['overlap_tolerance'] = param_xml.get_value('overlap_tolerance', ['parms']) d_parm['file_spheres'] = param_xml.get_value('file_spheres', ['paths', 'output_folder']) d_parm['img_membranes_blend_z'] = param_xml.get_value('img_membranes_blend_z',['paths']) d_parm['img_exterior_outline'] = param_xml.get_value('img_exterior_outline',['paths']) param_xml.l_main_keys = ['body', 'RAM'] if param_xml.get_value('RAW_IMG_DIM_TZYX'): _, d_parm['zmax'], d_parm['ymax'], d_parm['xmax'] = param_xml.get_value('RAW_IMG_DIM_TZYX') else: _, d_parm['zmax'], d_parm['ymax'], d_parm['xmax'] = filehandler.d_loaded_files['IMG_RAW'].shape param_xml.l_main_keys = ['body', 'spheresDT', 'parms'] d_parm['zdim'],d_parm['ydim'],d_parm['xdim'] = param_xml.get_value('scaling_ZYX',l_path_keys=['body','RAM'],use_main_keys=False) param_xml.l_main_keys = ['body', 'MAIN', 'paths'] d_parm['img_raw_file']= param_xml.get_value('img_raw_file') if param_xml.get_value('img_exterior_outline'): #main image (manual membrane), takes precedence d_parm['img_exterior_outline'] = param_xml.get_value('img_exterior_outline') param_xml.l_main_keys = ['body', 'preprocessing', 'flowcontrol'] d_parm['l_stack_number_preprocess'] = param_xml.get_value('l_stack_number') return d_parm def get_spheres(s_spheres): # return should look like this ['1, [11, 243, 153], 53.0', '16, [14, 288, 164], 34.0'] l_matches = p.findall(s_spheres) return l_matches def get_sphere_info(s_sphere): # return should look like ['1', '11', '243', '153', '53', '0'] #print(s_sphere) l_matches = p2.findall(s_sphere) if len(l_matches) > 5: radius = float(l_matches[4]) + (float(l_matches[5]) / 100) else: radius = float(l_matches[4]) return [float(i) for i in [l_matches[1], l_matches[2], l_matches[3], radius]] def shrink_spheres(idS, idS_overlap_max,verbose=False): overlap_sphere = Sphere.d_idS_sph[idS_overlap_max] sum_radii = overlap_sphere.radius + radius dist = calc_dist_spheres(Sphere.d_idS_sph[idS], overlap_sphere) length_overlap = sum_radii - dist radius_corr = length_overlap / 2 if verbose:print('BEFORE SHRINKING : self radius=', radius, 'overlap radius=', overlap_sphere.radius, "they overlap with =", length_overlap, "the distance between them=", dist) new_radius_self = radius - radius_corr new_radius_overlap = overlap_sphere.radius - radius_corr # update the overlapping sphere in all datastructures overlap_sphere.radius = new_radius_overlap Sphere.d_idS_sph[idS_overlap_max] = overlap_sphere l_pixels = get_3D_sphere_coordinates(a_coordZYX=[overlap_sphere.z, overlap_sphere.y, overlap_sphere.x], radius=overlap_sphere.radius, limit_shape=(d_parm['zmax'], d_parm['ymax'], d_parm['xmax']), xy_vs_z=xy_vs_z) Sphere.a_labelview[Sphere.a_labelview == Sphere.d_idS_label[idS_overlap_max]] = 0 Sphere.a_labelview[l_pixels] = Sphere.d_idS_label[idS_overlap_max] if verbose:print('overlap_sphere', overlap_sphere) if verbose:print('number of pixels overlap sphere before = ', len(Sphere.a_sphereview[Sphere.a_sphereview == idS_overlap_max])) a_sphereview[a_sphereview == idS_overlap_max] = 0 a_sphereview[l_pixels] = idS_overlap_max if verbose:print('number of pixels overlap sphere after = ', len(Sphere.a_sphereview[Sphere.a_sphereview == idS_overlap_max])) if verbose:print('AFTER SHRINKING : self radius=', new_radius_self, 'overlap radius=', overlap_sphere.radius) return new_radius_self, new_radius_overlap def write_csv_output(): ls_columns = ["cell_label", # this array determines the order of the columns (besides the names) "x", "y", "z", "radius", "x_micron", "y_micron", "z_micron", "radius_micron"] d_df = {} # the dict that will be used to create the dataframe # initialize the ls_columns l_cell_label = [] l_x = [] l_y = [] l_z = [] l_radius = [] l_x_micron = [] l_y_micron = [] l_z_micron = [] l_radius_micron = [] if not d_parm['shrink_spheres']: for cell_label, l_nt_spheres in d_cellID_l_nt_spheres.items(): for nt_sphere in l_nt_spheres: l_cell_label.append(cell_label) l_x.append(int(nt_sphere.x)) l_y.append(int(nt_sphere.y)) l_z.append(int(nt_sphere.z)) l_radius.append(int(nt_sphere.radius)) l_x_micron.append(int(nt_sphere.x) * d_parm['xdim']) l_y_micron.append(int(nt_sphere.y) * d_parm['ydim']) l_z_micron.append(int(nt_sphere.z) * d_parm['zdim']) l_radius_micron.append(int(nt_sphere.radius) * d_parm['xdim']) else: for idS_i, idMesh_i in sorted(Sphere.d_idS_mesh_key.items(), key=lambda kv: kv[1]): sphere = Sphere.d_idS_sph[idS_i] l_cell_label.append(idMesh_i) l_x.append(int(sphere.zyx[2])) l_y.append(int(sphere.zyx[1])) l_z.append(int(sphere.zyx[0])) l_radius.append(float(sphere.radius)) l_x_micron.append(int(sphere.zyx[2]) * d_parm['xdim']) l_y_micron.append(int(sphere.zyx[1]) * d_parm['ydim']) l_z_micron.append(int(sphere.zyx[0]) * d_parm['zdim']) l_radius_micron.append(float(sphere.radius) * d_parm['xdim']) d_df[ls_columns[0]] = l_cell_label d_df[ls_columns[1]] = l_x d_df[ls_columns[2]] = l_y d_df[ls_columns[3]] = l_z d_df[ls_columns[4]] = l_radius d_df[ls_columns[5]] = l_x_micron d_df[ls_columns[6]] = l_y_micron d_df[ls_columns[7]] = l_z_micron d_df[ls_columns[8]] = l_radius_micron # output_path = os.path.join(filehandler.get_save_location(),'spheres_for_meshing.csv') d_parm['file_spheres'].parent.mkdir(parents=True, exist_ok=True) df_spheres = pd.DataFrame(d_df) df_spheres.sort_values(by=['cell_label', 'radius'],ascending=[True,False],inplace=True) df_spheres.to_csv(str(d_parm['file_spheres']), index=False) # filehandler.store_f_name('spheres_for_meshing',output_path) print('mpacts output written as', str(d_parm['file_spheres'])) class Sphere: idS = 0 d_idS_sph = {} d_idS_mesh_key = {} d_idS_label = {} d_parm = read_parms(param_xml) a_labelview = np.zeros((d_parm['zmax'], d_parm['ymax'], d_parm['xmax']), dtype='int') a_sphereview = np.zeros((d_parm['zmax'], d_parm['ymax'], d_parm['xmax']), dtype='int') #spheres will be sequentially added to these views def __init__(self, center_zyx, radius,mesh_key,label): Sphere.idS += 1 self.zyx = center_zyx self.radius = radius self.mesh_key = mesh_key self.label = label self.idS = Sphere.idS self.l_pixels=None self.update_l_pixels() Sphere.d_idS_sph[self.idS] = self Sphere.d_idS_mesh_key[self.idS] = mesh_key Sphere.d_idS_label[self.idS] = label def update_l_pixels(self): if self.radius > 0: self.l_pixels = get_3D_sphere_coordinates(a_coordZYX=self.zyx, radius=self.radius, limit_shape=(d_parm['zmax'], d_parm['ymax'], d_parm['xmax']), xy_vs_z=xy_vs_z) return def update_views(self,verbose=False): Sphere.a_sphereview[self.l_pixels] = 0 #only now the current sphere is added to the views Sphere.a_labelview[self.l_pixels] = 0 if verbose:print('__number of pixels overlap sphere ({1}) before = {0}'.format(len(self.l_pixels[0]),self.mesh_key)) self.update_l_pixels() Sphere.a_sphereview[self.l_pixels] = self.idS #only now the current sphere is added to the views Sphere.a_labelview[self.l_pixels] = self.label if verbose:print('__number of pixels overlap sphere ({1}) after = {0}'.format(len(self.l_pixels[0]),self.mesh_key)) return def get_sphere_of_max_overlap(self,verbose=False): ''' the sphere ID of the sphere that maximally overlaps with the current sphere is returned ''' bincount = np.bincount(Sphere.a_sphereview[self.l_pixels].flatten()) bincount[0] = 0 # not interested in overlap with zero region, so set zero count equal to zero sph_overlap_max = Sphere.d_idS_sph[np.argmax(bincount)] while sph_overlap_max.mesh_key==self.mesh_key: bincount[sph_overlap_max.idS] = 0 sph_overlap_max = Sphere.d_idS_sph[np.argmax(bincount)] # if len(bincount) > self.idS: # bincount[self.idS] = 0 # not interested in overlap with self if verbose:print("---> OVERLAPPING SPHERES DETECTED => nbpix overlap=", np.max(bincount)) #sanity test if sph_overlap_max.mesh_key==self.mesh_key: print("WARNING : The two spheres belong to the same mesh {0} ! not good !".format(self.mesh_key)) if not sph_overlap_max: print('no overlapping sphere from another label found, something is wrong') return sph_overlap_max def shrink_and_move_spheres(self, overlap_sphere,verbose=False): def shrink_radii(): sum_radii = overlap_sphere.radius + self.radius dist = self.calc_dist_spheres(overlap_sphere) length_overlap = max(sum_radii - dist,0) radius_corr = length_overlap / 4 #shrinkage radii will account for half the overlap, the other accounted will be covered by translation if verbose:print("-->they overlap with =", length_overlap, "the distance between them=", dist, "") if length_overlap==0: length_overlap = 1 radius_corr = 0.25 # we apply some shrinking to solve rounding errors that can cause looping self.radius = self.radius - radius_corr overlap_sphere.radius = overlap_sphere.radius - radius_corr return length_overlap,dist def set_new_centers(length_overlap,dist,verbose=False): ''' the centers are pushed in opposite directions. it will land midway the current radius. so the shrunken and translated sphere will be completely contained in the current sphere and pushed towards its own cluster. ''' scale_factor = length_overlap / (dist * 4 ) #dist = normalize vector; centers only need to shift with 1/4 ot the overlap (translation accounts for half of overlap, rest = shrinking) l_translation = [(i-j)*scale_factor for i,j in zip(overlap_sphere.zyx,self.zyx)] # translation_distance = length_overlap / 4 self.zyx = [math.floor(i - j) for i,j in zip(self.zyx,l_translation)] overlap_sphere.zyx = [math.floor(i + j) for i,j in zip(overlap_sphere.zyx,l_translation)] #sanity checks (temp) new_dist = self.calc_dist_spheres(overlap_sphere) new_sum_radii = overlap_sphere.radius + self.radius new_radius_overlap = new_sum_radii - new_dist if verbose:print('test : the new distance between these cells is {0} instead of the old distance {1}.'.format(new_dist,dist)) if verbose:print('test : the new length_overlap is now sum_radii{0} - new_dist{1} = {2}'.format(new_sum_radii, new_dist,new_radius_overlap)) if new_radius_overlap < 1e-5: if verbose:print("test : OK no overlap left :-)") return if verbose:print('_INITIAL : overlap_sphere:', overlap_sphere.repr()) if verbose:print('_INITIAL : self:', self.repr()) length_overlap, dist = shrink_radii() if (length_overlap>0 and dist>0): set_new_centers(length_overlap,dist) #CORE if verbose:print('_UPDATED : overlap_sphere:', overlap_sphere.repr()) if verbose:print('_UPDATED : self:', self.repr()) overlap_sphere.update_views() return def overlap_with_other_cell(self): ''' the cluster label of the sphere that maximally overlaps with the current sphere is returned ''' bincount = np.bincount(Sphere.a_labelview[self.l_pixels].flatten()) bincount[0] = 0 # not interested in overlap with zero region, so set zero count equal to zero if len(bincount) > self.label: bincount[self.label] = 0 # not interested in overlap with own cell bincount[bincount <= d_parm['overlap_tolerance']] = 0 # 1 pixel overlap is ignored return True if np.argmax(bincount)>0 else False def calc_dist_spheres(self, sphere2): a = (self.zyx[0]* xy_vs_z, self.zyx[1], self.zyx[2]) b = (sphere2.zyx[0]* xy_vs_z, sphere2.zyx[1], sphere2.zyx[2]) dst = distance.euclidean(a, b) return dst def repr(self): return "zyx:{0},radius:{1},mesh_key:{2},idS:{3},nb_pixels:{4}".format(self.zyx,self.radius,self.mesh_key,self.idS,len(self.l_pixels[0])) # PART 1 : make a csv of spheres per cell used in meshing # ------------------------------------------------------- # initialize d_parm = read_parms(param_xml) # filehandler.extend_save_info(extra_dir_1 = '008_mpacts_input',from_root=True,take_snapshot_after=True) LABEL_FILTERED = 9998 LABEL_VALIDATION = 9999 SKIP_LABEL = [LABEL_FILTERED, LABEL_VALIDATION] xy_vs_z = d_parm['zdim'] / d_parm['xdim'] # READ IN EXCEL------------------------------------------ df_ipt = pd.read_csv(str(d_parm['input_file_csv']), delimiter=',') df_ipt['validation_error'] = df_ipt['validation_error'].astype('str') # STEP 1 BUILD UP DATASTRUCTURES FROM EXCEL INPUT--------------------- p = re.compile(r"(?:\()(.+?)(?:\))") p2 = re.compile(r"\d+") nb_stack_timelapse = d_parm['nb_stack_timelapse'] if isinstance(d_parm['l_stack_number_preprocess'], str): d_parm['nb_stack'] = d_parm['nb_stack_timelapse'] #if not 'all' timesteps are processed, then only the first occurrence is processed else: d_parm['nb_stack'] = d_parm['nb_stack'] if not d_parm['shrink_spheres']: d_cellID_l_nt_spheres = {} # ix = mesh key nt_Sphere = namedtuple('nt_Sphere', ['z', 'y', 'x', 'radius']) for nb_time in d_parm['nb_stack']: for _, row_cluster in df_ipt[df_ipt.stack_nb == nb_time].iterrows(): if row_cluster.cluster_label in SKIP_LABEL: continue mesh_key = "{0}_{1}_t{2}".format("{:02d}".format(row_cluster.cluster_label), row_cluster.color, row_cluster.stack_nb) print(mesh_key) if row_cluster.validation_error != 'nan': print(row_cluster.validation_error) # ter info l_spheres = get_spheres(row_cluster['spheres(ctr,centre,radius)']) l_nt_spheres = [] for sphere in l_spheres: z, y, x, radius = get_sphere_info(sphere) nt_sphere = nt_Sphere(z=z, y=y, x=x, radius=radius) l_nt_spheres.append(nt_sphere) if l_nt_spheres: l_nt_spheres_old = d_cellID_l_nt_spheres.get(mesh_key) l_nt_spheres_new = l_nt_spheres_old + l_nt_spheres if l_nt_spheres_old else l_nt_spheres d_cellID_l_nt_spheres[mesh_key] = l_nt_spheres_new else: dd = {} #to avoid looping if the same combination keeps popping up for nb_time in d_parm['nb_stack']: # for now, will only be 1 timepoint e.g. [4] for _, row_cluster in df_ipt[df_ipt.stack_nb == nb_time].iterrows(): if row_cluster.cluster_label in SKIP_LABEL: continue mesh_key = "{0}_{1}_t{2}".format("{:02d}".format(row_cluster.cluster_label), row_cluster.color, row_cluster.stack_nb) print('processing this cluster :',mesh_key,flush=True) if row_cluster.validation_error != 'nan': print(row_cluster.validation_error) # ter info l_spheres = get_spheres(row_cluster['spheres(ctr,centre,radius)']) for sphere_i in l_spheres: z, y, x, radius = get_sphere_info(sphere_i) sph_curr = Sphere([int(z), int(y), int(x)], radius,mesh_key, int(row_cluster.cluster_label)) while (sph_curr.overlap_with_other_cell()): sph_overlap_max = sph_curr.get_sphere_of_max_overlap() dd.setdefault(sph_curr.idS, []).append(sph_overlap_max.idS) sph_curr.shrink_and_move_spheres(sph_overlap_max,verbose=False) sph_curr.update_l_pixels() sph_curr.update_views(verbose=False) write_csv_output() # PART 2 : make the pixel input for mpacts-PiCS # --------------------------------------------- with TiffFile(str(d_parm['input_file_frangi'])) as tif: a_frangi = tif.asarray() with TiffFile(str(d_parm['input_file_threshold'])) as tif: a_threshold = tif.asarray() a_mpacts_pixel_selector = np.where(a_threshold[d_parm['nb_stack'][0] - 1, ...], a_frangi[d_parm['nb_stack'][0] - 1, ...], 0) #if a exterior outine is given, this will also be blended in with the image. every pixel will get the maximum frangi value of that slice if isinstance(d_parm['img_exterior_outline'], Path) and d_parm['img_exterior_outline'].is_file(): with TiffFile(str(d_parm['img_exterior_outline'])) as tif: print('exterior_outline is blended into mpacts_pixel_selector :{0}'.format(d_parm['img_exterior_outline'])) a_exterior_outline = tif.asarray() if len(a_exterior_outline.shape)==4: a_exterior_outline = a_exterior_outline[d_parm['nb_stack'][0] - 1, ...] a_copy = np.zeros_like(a_mpacts_pixel_selector) for ix_z,a_z in enumerate(a_mpacts_pixel_selector): a_copy[ix_z] = np.where(a_exterior_outline[ix_z]>0,np.max(a_z),a_z) a_mpacts_pixel_selector = a_copy imsave(str(d_parm['output_folder'] / "exterior_outline_stack.tif"), a_exterior_outline) #if z_membrane detection is used, this will also be blended in with the image. every pixel will get the maximum frangi value of that slice if isinstance(d_parm['img_membranes_blend_z'], Path) and d_parm['img_membranes_blend_z'].is_file(): with TiffFile(str(d_parm['img_membranes_blend_z'])) as tif: a_membranes_blend_z = tif.asarray()[d_parm['nb_stack'][0] - 1, ...] a_copy = np.zeros_like(a_mpacts_pixel_selector) for ix_z,a_z in enumerate(a_mpacts_pixel_selector): a_copy[ix_z] = np.where(a_membranes_blend_z[ix_z]==3,np.max(a_z),a_z) #the z membranes has value 3 by convention a_mpacts_pixel_selector = a_copy imsave(str(d_parm['output_folder'] / "mpacts_pixel_selector.tif"),a_mpacts_pixel_selector) # PART 3 : make the raw image slice that can be uploaded into paraview for comparison (y inverted) # ----------------------------------------------------------------------------------------------- with TiffFile(str(d_parm['img_raw_file'])) as tif: a_raw = tif.asarray() if len(a_raw.shape)==4: a_raw = a_raw[nb_stack_timelapse[0] - 1, :] a_paraview = np.zeros_like(a_raw) if len(a_paraview.shape)==4: _, _, y_max, _ = a_paraview.shape else: _, y_max, _ = a_paraview.shape for i_y in range(0, y_max): a_paraview[:, i_y, :] = a_raw[:, -1 * (i_y - y_max + 1), :] # the paraview image is bottomed to aid vizualization (lowest intensity pixel should be zero) a_paraview = a_paraview - np.min(a_paraview) imsave(str(d_parm['output_folder'] / "raw_img_inverted_y.tif"), a_paraview) imsave(str(d_parm['output_folder'] / "raw_img_selected_stack .tif"), a_raw) return
]) } return a_peaks_extended, dflog if __name__ == "__main__": #read files input_file_original = "/home/wth/Downloads/testinfra/ISOLATED/z_membrane_detector/TL11_crop_1ch_emb1of1.tif" input_file_membrane_mask = "/home/wth/Downloads/testinfra/ISOLATED/z_membrane_detector/threshold(acceptance_level=10).tif" input_file_frangi = "/home/wth/Downloads/testinfra/ISOLATED/z_membrane_detector/frangi.tif" output_folder = Path( "/home/wth/Downloads/testinfra/ISOLATED/z_membrane_detector/") ix_stack = 0 with TiffFile(input_file_original) as tif: a_input = tif.asarray()[ix_stack, :].astype( float) #NP.GRADIENT ONLY WORKS WITH FLOATS !!!!! with TiffFile(input_file_membrane_mask) as tif: a_input_file_membrane_mask = tif.asarray()[ix_stack, :].astype(float) with TiffFile(input_file_frangi) as tif: a_input_file_frangi = tif.asarray()[ix_stack, :].astype(float) detect_z_membrane(a_input, a_input_file_membrane_mask, path_output_folder=output_folder, verbose=True) print("END")
def dtype(self): if self._dtype is None: with TiffFile(self._file) as tiff: self._dtype = tiff.pages[0].dtype return self._dtype
def import_tiff(self): tiff = TiffFile(self.full_name) self.tiff = tiff meta = tiff.series[0] if tiff.is_imagej: try: # if an imagej file, we know where, and can extract the x,y,z resolutions x_res = tiff.pages[0].tags["XResolution"].value y_res = tiff.pages[0].tags["YResolution"].value # X resolution stored as Fraction x_res = float(x_res[1]) / float(x_res[0]) z_res = tiff.imagej_metadata[ "spacing"] # .pages[0].imagej_tags['spacing'] # We're interested in X resolution relative to Z self.z_calibration = z_res / x_res print("z_scale_factor", self.z_calibration) except (AttributeError, KeyError) as ex: print("tiff resolution not recognised") elif self.tiff.is_ome: try: x_res = tiff.ome_metadata["Image"]["Pixels"]["PhysicalSizeX"] print(x_res) y_res = tiff.ome_metadata["Image"]["Pixels"]["PhysicalSizeY"] z_res = tiff.ome_metadata["Image"]["Pixels"]["PhysicalSizeZ"] # We're interested in X resolution relative to Z self.z_calibration = z_res / x_res print("z_scale_factor", self.z_calibration) except (AttributeError, KeyError) as ex: print("tiff resolution not recognised") self.order = meta.axes for n, axis in enumerate(self.order): if axis == "T": self.max_t = meta.shape[n] - 1 if axis in ["Z", "Q", "I"]: self.max_z = meta.shape[n] - 1 if axis == "Y": self.height = meta.shape[n] if axis == "X": self.width = meta.shape[n] if axis == "S": # RGB image colour channel self.numCH = meta.shape[n] # par_obj.tiff_reorder=False if axis == "C": self.numCH = meta.shape[n] self.bitDepth = meta.dtype self.array = self.tiff.asarray() # memmap=True) self.tiffarraymax = self.array.max() if self.bitDepth in ["uint8", "uint16"]: self.tiffarray_typemax = np.iinfo(self.bitDepth).max # 12 bit depth if self.bitDepth in ["uint16"] and self.tiffarraymax < 4096: self.tiffarray_typemax = 4095 else: self.tiffarray_typemax = np.finfo(self.bitDepth).max print(self.array.shape)
def plot_image_overlays(image, overlays, **kwargs): """Plot image and overlays (bytes) using matplotlib.""" fig, ax = pyplot.subplots() ax.imshow(image, cmap='gray') if not isinstance(overlays, list): overlays = [overlays] for overlay in overlays: roi = ImagejRoi.frombytes(overlay) roi.plot(ax, **kwargs) pyplot.show() # open an ImageJ TIFF file and read the image and overlay data # https://github.com/csachs/imagej-tiff-meta/ # blob/b6a74daa8c2adf7023d20a447d9a2799614c857a/box.tif with TiffFile('tests/box.tif') as tif: image = tif.pages[0].asarray() overlays = tif.imagej_metadata['Overlays'] plot_image_overlays(image, overlays) # segment the image with scikit-image labeled = label(image > 0.5 * image.max()) for region in regionprops(labeled): if region.area > 10000: labeled[labeled == region.label] = 0 elif region.area < 100: labeled[labeled == region.label] = 0 segmentation = 1.0 * (labeled > 0) # create ImageJ overlays from segmentation results
def read_dtype(self, file_name: Path) -> str: with TiffFile(file_name) as tif_file: return tif_file.series[ # pylint: disable=unsubscriptable-object 0 ].dtype.name
return ar pathlist = [] for expname in sorted(experiments): if experimentName is not None: if expname != experimentName: print(expname, 'does not match experiment key:', experimentName + '. skipping..') continue else: print('found match:', expname) # Make output filenames based on name pathlist.extend(experiments[expname]) mouse_vid = toNumpy(TiffFile(pathlist[0]).pages) mouse_vid_shape = mouse_vid.shape print("Found experiment!!") resize_factor = 1 print("Loaded movie part 1") hdf5FilePath = "mouse_vectors.hdf5" hdf5File = hdf5manager(hdf5FilePath) mouse_frame = mouse_vid[300] hdf5Dict = {} clicks = { "footFL": 0, "footFR": 0, "footBL": 0,
def evaluate(self, path, multichannel=True): px = 0 pz = 0 with TiffFile(path) as tif: image = tif.asarray() metadata = tif.imagej_metadata["Info"].split("\n") for tag in metadata: if "ScalingX" in tag: px = float( tag.split(" ")[-1]) * 10**6 # convert to micrometer if "ScalingZ" in tag: pz = float( tag.split(" ")[-1]) * 10**6 # convert to micrometer if px == 0 or pz == 0: raise ValueError("wtf metadata?") array = image[:, 2].astype(np.float64) if multichannel: lamb1 = image[:, 0].astype(np.float64) lamb1 = exposure.adjust_gamma(lamb1, gamma=0.9) lamb1 = np.clip((lamb1 / lamb1.max()) - 0.01, 0, 1) lamb1 /= lamb1.max() # thresh = threshold_otsu(array[10]) array = exposure.adjust_gamma(array, gamma=0.9) # array = gaussian_filter(array, sigma=0.05)#todo: check this parameter array = np.clip((array / array.max()) - 0.01, 0, 1) array /= array.max() binary = array != 0 lab = label(binary) print(lab.max()) coords = [] n_deg_coords = [] deg_volumes = [] ndeg_volumes = [] dia = [] n_deg_dia = [] for i in range(lab.max()): i += 1 print(i) indices = np.where(lab == i) # kick noise if indices[0].shape[0] < 30: lab[indices] = 0 else: n_indices = list(copy.deepcopy(indices)) position = [] c = False # kick two dimensional crops.... for z in range(3): position.append(n_indices[z].min()) n_indices[z] -= n_indices[z].min() if len(set(n_indices[z])) < 3: c = True if c: continue # new = np.zeros((n_indices[0].max()+1,n_indices[1].max()+1,n_indices[2].max()+1)).astype(np.uint8) new = array[indices[0].min():indices[0].max(), indices[1].min():indices[1].max(), indices[2].min():indices[2].max(), ] # indices Z,X,Y if multichannel: lamb_volume = lamb1[indices[0].min():indices[0].max(), indices[1].min():indices[1].max(), indices[2].min():indices[2].max(), ] lamb_ind = np.where(lamb_volume != 0) if lamb_ind[0].shape[0] > 0.1 * indices[0].shape[0]: deg_volumes.append(new) coords.append(position) dia.append( int( np.sqrt(( (indices[1].max() - indices[1].min())**2 + (indices[2].max() - indices[2].min())**2) / 2))) else: ndeg_volumes.append(new) n_deg_coords.append(position) n_deg_dia.append( int( np.sqrt(( (indices[1].max() - indices[1].min())**2 + (indices[2].max() - indices[2].min())**2) / 2))) else: deg_volumes.append(new) coords.append(position) dia.append( int( np.sqrt( ((indices[1].max() - indices[1].min())**2 + (indices[2].max() - indices[2].min())**2) / 2))) # break # set estimated diameter to median dia_est = np.mean(np.array(dia)) n_deg_dia_est = np.mean(np.array(n_deg_dia)) V2, V, new_label = get_masks_and_volume(px, pz, deg_volumes, array, coords, diameter=dia) V2ndeg, Vndeg, new_label_ndeg = get_masks_and_volume( px, pz, ndeg_volumes, array, n_deg_coords, diameter=n_deg_dia) #show_segmentation(array, label1=new_label_ndeg) return V2, V2ndeg, V2
def load_slice(self, slice_index: int = 0) -> np.ndarray: with TiffFile(self._file) as tiff: return tiff.asarray(key=slice_index)
def get_bedmap2(thklim=0.0): filename = inspect.getframeinfo(inspect.currentframe()).filename home = os.path.dirname(os.path.abspath(filename)) direc = home + '/antarctica/bedmap2/bedmap2_tiff/' sys.path.append(home + '/external_import_scripts') from tifffile import TiffFile b = TiffFile(direc + 'bedmap2_bed.tif') h = TiffFile(direc + 'bedmap2_surface.tif') H = TiffFile(direc + 'bedmap2_thickness.tif') mask = TiffFile(direc + 'bedmap2_icemask_grounded_and_shelves.tif') rock_mask = TiffFile(direc + 'bedmap2_rockmask.tif') b_uncert = TiffFile(direc + 'bedmap2_grounded_bed_uncertainty.tif') coverage = TiffFile(direc + 'bedmap2_coverage.tif') gl04c_WGS84 = TiffFile(direc + 'gl04c_geiod_to_WGS84.tif') b = b.asarray() h = h.asarray() H = H.asarray() mask = mask.asarray() rock_mask = rock_mask.asarray() b_uncert = b_uncert.asarray() coverage = coverage.asarray() gl04c_WGS84 = gl04c_WGS84.asarray() h[H < thklim] = b[H < thklim] + thklim H[H < thklim] = thklim vara = dict() # extents of domain : dx = 1000 west = -3333500.0 east = 3333500.0 north = 3333500.0 south = -3333500.0 #projection info : proj = 'stere' lat_0 = '-90' lat_ts = '-71' lon_0 = '0' names = [ 'B', 'S', 'H', 'mask', 'rock_mask', 'b_uncert', 'coverage', 'gl04c_WGS84' ] ftns = [b, h, H, mask, rock_mask, b_uncert, coverage, gl04c_WGS84] # retrieve data : vara['dataset'] = 'bedmap 2' for n, f in zip(names, ftns): vara[n] = { 'map_data': f[::-1, :], 'map_western_edge': west, 'map_eastern_edge': east, 'map_southern_edge': south, 'map_northern_edge': north, 'projection': proj, 'standard lat': lat_0, 'standard lon': lon_0, 'lat true scale': lat_ts } return vara
def dask_data(self) -> da.core.Array: """ Read a TIFF image file as a delayed dask array where each chunk of the constructed array is a delayed YX plane. Returns ------- img: dask.array.core.Array The constructed delayed YX plane dask array. """ if self._dask_data is None: # Load Tiff with TiffFile(self._file) as tiff: # Check each scene has the same shape # If scene shape checking fails, use the specified scene and update operating shape scenes = tiff.series operating_shape = scenes[0].shape for scene in scenes: if scene.shape != operating_shape: operating_shape = scenes[self.specific_s_index].shape scenes = [scenes[self.specific_s_index]] log.info( f"File contains variable dimensions per scene, " f"selected scene: {self.specific_s_index} for data retrieval." ) break # Get sample yx plane sample = scenes[0].pages[0].asarray() # Combine length of scenes and operating shape # Replace YX dims with empty dimensions operating_shape = (len(scenes), *operating_shape) operating_shape = operating_shape[:-2] + (1, 1) # Make ndarray for lazy arrays to fill lazy_arrays = np.ndarray(operating_shape, dtype=object) for all_page_index, (np_index, _) in enumerate( np.ndenumerate(lazy_arrays)): # Scene index is the first index in np_index scene_index = np_index[0] # This page index is current enumeration divided by scene index + 1 # For example if the image has 10 Z slices and 5 scenes, there would be 50 total pages this_page_index = all_page_index // (scene_index + 1) # Fill the numpy array with the delayed arrays lazy_arrays[np_index] = da.from_delayed(delayed( TiffReader._imread)(self._file, scene_index, this_page_index), shape=sample.shape, dtype=sample.dtype) # Convert the numpy array of lazy readers into a dask array data = da.block(lazy_arrays.tolist()) # Only return the scene dimension if multiple scenes are present if len(scenes) == 1: data = data[0, :] # Set _dask_data self._dask_data = data return self._dask_data
def file_reader(filename, record_by='image', force_read_resolution=False, **kwds): """ Read data from tif files using Christoph Gohlke's tifffile library. The units and the scale of images saved with ImageJ or Digital Micrograph is read. There is limited support for reading the scale of files created with Zeiss and FEI SEMs. Parameters ---------- filename: str record_by: {'image'} Has no effect because this format only supports recording by image. force_read_resolution: Bool Default: False. Force reading the x_resolution, y_resolution and the resolution_unit of the tiff tags. See http://www.awaresystems.be/imaging/tiff/tifftags/resolutionunit.html **kwds, optional """ _logger.debug('************* Loading *************') # For testing the use of local and skimage tifffile library lazy = kwds.pop('lazy', False) memmap = kwds.pop('memmap', None) with TiffFile(filename, **kwds) as tiff: # change in the Tifffiles API if hasattr(tiff.series[0], 'axes'): # in newer version the axes is an attribute axes = tiff.series[0].axes else: # old version axes = tiff.series[0]['axes'] is_rgb = tiff.pages[0].photometric == TIFF.PHOTOMETRIC.RGB _logger.debug("Is RGB: %s" % is_rgb) series = tiff.series[0] if hasattr(series, 'shape'): shape = series.shape dtype = series.dtype else: shape = series['shape'] dtype = series['dtype'] if is_rgb: axes = axes[:-1] names = ['R', 'G', 'B', 'A'] lastshape = shape[-1] dtype = np.dtype({ 'names': names[:lastshape], 'formats': [dtype] * lastshape }) shape = shape[:-1] op = {key: tag.value for key, tag in tiff.pages[0].tags.items()} names = [axes_label_codes[axis] for axis in axes] _logger.debug('Tiff tags list: %s' % op) _logger.debug("Photometric: %s" % op['PhotometricInterpretation']) _logger.debug('is_imagej: {}'.format(tiff.pages[0].is_imagej)) scales = [1.0] * len(names) offsets = [0.0] * len(names) units = [t.Undefined] * len(names) intensity_axis = {} try: scales_d, units_d, offsets_d, intensity_axis = _parse_scale_unit( tiff, op, shape, force_read_resolution) for i, name in enumerate(names): if name == 'height': scales[i], units[i] = scales_d['x'], units_d['x'] offsets[i] = offsets_d['x'] elif name == 'width': scales[i], units[i] = scales_d['y'], units_d['y'] offsets[i] = offsets_d['y'] elif name in ['depth', 'image series', 'time']: scales[i], units[i] = scales_d['z'], units_d['z'] offsets[i] = offsets_d['z'] except BaseException: _logger.info("Scale and units could not be imported") axes = [{ 'size': size, 'name': str(name), 'scale': scale, 'offset': offset, 'units': unit, } for size, name, scale, offset, unit in zip( shape, names, scales, offsets, units)] md = { 'General': { 'original_filename': os.path.split(filename)[1] }, 'Signal': { 'signal_type': "", 'record_by': "image", }, } if 'DateTime' in op: dt = datetime.strptime(op['DateTime'], "%Y:%m:%d %H:%M:%S") md['General']['date'] = dt.date().isoformat() md['General']['time'] = dt.time().isoformat() if 'units' in intensity_axis: md['Signal']['quantity'] = intensity_axis['units'] if 'scale' in intensity_axis and 'offset' in intensity_axis: dic = { 'gain_factor': intensity_axis['scale'], 'gain_offset': intensity_axis['offset'] } md['Signal']['Noise_properties'] = {'Variance_linear_model': dic} data_args = TiffFile, filename, is_rgb if lazy: from dask import delayed from dask.array import from_delayed memmap = 'memmap' val = delayed(_load_data, pure=True)(*data_args, memmap=memmap, **kwds) dc = from_delayed(val, dtype=dtype, shape=shape) # TODO: maybe just pass the memmap from tiffile? else: dc = _load_data(*data_args, memmap=memmap, **kwds) metadata_mapping = get_metadata_mapping(tiff.pages[0], op) return [{ 'data': dc, 'original_metadata': op, 'axes': axes, 'metadata': md, 'mapping': metadata_mapping, }]
def read(self, image_path: typing.Union[str, BytesIO, Path], mask_path=None, ext=None) -> Image: """ Read tiff image from tiff_file """ self.spacing, self.colors, self.channel_names, self.ranges = self.default_spacing, None, None, None with TiffFile(image_path) as image_file: total_pages_num = len(image_file.series[0]) # shape = self.image_file.series[0].shape axes = image_file.series[0].axes if image_file.is_lsm: self.read_lsm_metadata(image_file) elif image_file.is_imagej: self.read_imagej_metadata(image_file) elif image_file.is_ome: self.read_ome_metadata(image_file) else: x_spac, y_spac = self.read_resolution_from_tags(image_file) self.spacing = self.default_spacing[0], y_spac, x_spac mutex = Lock() count_pages = [0] def report_func(): mutex.acquire() count_pages[0] += 1 self.callback_function("step", count_pages[0]) mutex.release() if mask_path is not None: with TiffFile(mask_path) as mask_file: self.callback_function( "max", total_pages_num + len(mask_file.series[0])) self.verify_mask(mask_file, image_file) mask_file.report_func = report_func mask_data = mask_file.asarray() mask_data = self.update_array_shape( mask_data, mask_file.series[0].axes)[..., 0] else: mask_data = None self.callback_function("max", total_pages_num) image_file.report_func = report_func try: image_data = image_file.asarray() except ValueError as e: # pragma: no cover raise TiffFileException(*e.args) image_data = self.update_array_shape(image_data, axes) if not isinstance(image_path, (str, Path)): image_path = "" return self.image_class( image_data, self.spacing, mask=mask_data, default_coloring=self.colors, channel_names=self.channel_names, ranges=self.ranges, file_path=os.path.abspath(image_path), axes_order=self.return_order(), shift=self.shift, name=self.name, )
def read_array( self, file_name: Path, dtype: Union[type, np.dtype], z_slice: int, channel_index: Optional[int], sample_index: Optional[int], ) -> np.ndarray: with TiffFile(file_name) as tif_file: # Read metadata z_axis_name = self._find_right_z_axis_name(tif_file) used_axes = {"C", "Y", "X", "S"} | {z_axis_name} assert len(tif_file.series) == 1, "Multi-series tiff not supported" series = tif_file.series[0] # pylint: disable=unsubscriptable-object page = tif_file.pages[0] axes = {} for index, axis in enumerate(series.axes): axes[axis] = (True, index, series.shape[index]) for axis in used_axes: if axis not in axes: axes[axis] = (False, 0, 1) count = 0 page_axes = {} for index, axis in enumerate(page.axes): # when reading the data, we'll remove any axis that is not used, so the dimensionality shrinks page_axes[axis] = (index, index - count, page.shape[index]) if axis not in used_axes: count += 1 assert ( len(axes) > 0 and z_axis_name is not None ), "TiffReader initialization failed" # this calculation is possible this way because the extent for non existing axes gets set to one num_output_channel = axes["C"][2] * axes["S"][2] if channel_index is not None: num_output_channel //= axes["C"][2] if sample_index is not None: num_output_channel //= axes["S"][2] output_shape = (axes["X"][2], axes["Y"][2], num_output_channel) output = np.empty(output_shape, tif_file.pages[0].dtype) z_index = z_slice if axes[z_axis_name][0] else 0 output_channel_offset = 0 # Read the data for page_index, (data_c_index, data_s_index,) in self._find_correct_pages( tif_file, channel_index, sample_index, z_index, axes, z_axis_name, page_axes, ).items(): page_data = self._get_page_data(tif_file, page_index) # remove any axis that we do not use # left over axes [(C)YX(S)] (Z axis is not on same TiffPage) for axis in page_axes: if axis not in used_axes: page_data = page_data.take([0], page_axes[axis][1]) # axes order is then [YX(S)(C)] if page_data.ndim == 4: page_data = page_data.transpose( ( page_axes["X"][1], page_axes["Y"][1], page_axes["S"][1], page_axes["C"][1], ) ) elif page_data.ndim == 3: if "S" in page_axes: page_data = page_data.transpose( ( page_axes["X"][1], page_axes["Y"][1], page_axes["S"][1], ) ) else: page_data = page_data.transpose( ( page_axes["X"][1], page_axes["Y"][1], page_axes["C"][1], ) ) elif page_data.ndim == 2: page_data = page_data.transpose( (page_axes["X"][1], page_axes["Y"][1]) ) else: raise Exception if data_c_index is not None: page_data = page_data.take([data_c_index], -1) if data_s_index is not None: page_data = page_data.take([data_s_index], -1) if page_data.ndim == 4: # means C and S axis present and no data index set for c in range(page_data.shape[-1]): output[ :, :, output_channel_offset : output_channel_offset + page_axes["S"][2], ] = page_data[:, :, :, c] output_channel_offset += ( output_channel_offset + page_axes["S"][2] ) elif page_data.ndim == 3: next_channel_offset = output_channel_offset + page_data.shape[-1] output[:, :, output_channel_offset:next_channel_offset] = page_data output_channel_offset = next_channel_offset elif page_data.ndim == 2: output[:, :, output_channel_offset] = page_data output_channel_offset += 1 else: raise Exception("Invalid axis count") output = np.array(output, dtype) output = output.reshape(output.shape + (1,)) return output
def main(): with Timer() as time_all_files: path = "video_in" for file_name in glob.glob(os.path.join(path, '*.tif')): print("begin", file_name) with Timer() as time_video, TiffFile(file_name) as full_file: name = full_file.filename formats = str(full_file[-1]).split(": ")[1].split(", ") num_pages = full_file.__len__() size_pages = np.array(formats[0].split(" x "), dtype=np.uint16) flat_len = np.prod(size_pages) size_pix = int(formats[2].split(' ')[0]) max_uint16 = 2**(size_pix - 1) n_iter = range(num_pages) del formats # print("egegey") with Timer() as time_sum: sum_pages = np.zeros(size_pages, dtype=np.uint32) for n in n_iter: sum_pages += full_file[n].asarray() for i in range(flat_len): if sum_pages.flat[i] == 0: sum_pages.flat[i] = 1 print("time sum", time_sum.secs) # print(sum_pages) # input() # print(1 / (sum_pages)) with Timer() as time_rel: rel_kdr_max = np.vectorize(lambda n: np.amax( np.true_divide(full_file[n].asarray(), sum_pages))) rel_kdr_min = np.vectorize(lambda n: np.amin( np.true_divide(full_file[n].asarray(), sum_pages))) max_value = np.amax(rel_kdr_max(n_iter)) * num_pages min_value = np.amax(rel_kdr_min(n_iter)) * num_pages print("time_rel", time_rel.secs) print(min_value, max_value) with Timer() as time_round, TiffWriter('video_out/' + name, bigtiff=True) as tif: c_1_one_min = max_uint16 / (1 - min_value) c_1_max_one = max_uint16 / (max_value - 1) c_max_two = max_value - 2 # for n in n_iter: # # part_video = (np.around(full_file[n].asarray() * new_sum_pages)).astype(np.uint16) # page = full_file[n].asarray().flat # s_page = sum_pages.flat # print(n) # for i in range(flat_len): # rel = page[i] / s_page[i] * num_pages # if rel <= 1: # r_page[i] = np.around((rel - min_value) * c_1_one_min * max_uint16) # else: # r_page[i] = np.around((rel + c_max_two) * c_1_max_one * max_uint16) # tif.save(res_page) # # print(part_video) def func(n): rel = np.multiply( np.true_divide(full_file[n].asarray(), sum_pages), num_pages) tif.save( np.select([rel <= 1, rel > 1], [(np.around( np.multiply( np.subtract(rel, min_value), c_1_one_min))).astype(np.uint16), (np.around( np.multiply(np.add(rel, c_max_two), c_1_max_one))).astype( np.uint16)])) # print(n) np.vectorize(func)(n_iter) print("time_round", time_round.secs) # const_1 = max_uint16 / max_value # print(const_1) # new_sum_pages = np.multiply(1 / (sum_pages), const_1) # del sum_pages # print(new_sum_pages) # with Timer() as time_round, TiffWriter('video_out/' + name, bigtiff=True) as tif: # for n in n_iter: # part_video = (np.around(full_file[n].asarray() * new_sum_pages)).astype(np.uint16) # tif.save(part_video) # # print(part_video) # print("time_round", time_round.secs) # # del new_sum_pages print("time_video", time_video.secs) print() print("time_all_files", time_all_files.secs / 60, "minutes")
def read_dimensions(self, file_name: Path) -> Tuple[int, int]: with TiffFile(file_name) as tif_file: return ( TiffImageReader.find_count_of_axis(tif_file, "X"), TiffImageReader.find_count_of_axis(tif_file, "Y"), )
def get_roi( exp_img, mask_img, bg: Optional[int] = 0, method: str = "mean", polygonize: str = "convex", alpha: Optional[float] = None, ): # From skimage doc: The different color bands/channels are stored in the third dimension # so we need to transpose it # exp_img = np.transpose(imread(str(exp_img)), (2, 1, 0)) # read page by page, we don't know how user will store their file # some store 40 channels on one page, some store 1 channel per page try: from tifffile import TiffFile from skimage.io import imread from skimage.measure import label, regionprops, regionprops_table except ImportError: raise ImportError( "Required scikit-image, try `pip install scikit-image`.") exp = [] with TiffFile(str(exp_img)) as img: for i in img.pages: exp.append(i.asarray()) exp = np.asarray(exp) X, Y, C = 1, 2, 0 if exp.ndim > 4: raise ValueError("The dimensions of image are too much") else: # if the channels info store in one page if exp.shape[0] == 1: exp = exp[0] X, Y, C = 0, 1, 2 borders, centroids = [], [] cells = [] mask = imread(mask_img) label_mask = label(mask, background=bg) for cell in regionprops(label_mask): # if cell has less than 3 points, then it's meaningless if len(cell.coords) >= 3: border = points_shapes([(x, y) for x, y in cell.coords], method=polygonize, concavity=alpha) borders.append(border) centroids.append(cell.centroid) cells.append(cell.coords) if C == 0: cell_exp = [ getattr(np, method).__call__(exp[:, [i[0] for i in cell], [i[1] for i in cell]], axis=1) for cell in cells ] else: cell_exp = [ getattr(np, method).__call__(exp[[i[0] for i in cell], [i[1] for i in cell], :], axis=0) for cell in cells ] return cell_exp, borders, centroids
def read_sample_count(self, file_name: Path) -> int: with TiffFile(file_name) as tif_file: return TiffImageReader.find_count_of_axis(tif_file, "S")
def main(args): mode = args.mode input_path = args.input_path output_path = args.output_path weights_path = args.weights_path data_type = args.data_type patch_size = (args.patch_size, args.patch_size) batch_size = args.batch_size nepochs = args.nepochs if mode == 'train': training_list = get_training_list(input_path, data_type) total_length = len(training_list) validation_split = 0.1 train_data_length = int (total_length * (1 - validation_split)) validation_data_length = int (total_length * validation_split) total_length = int (total_length) print("Creating Generators...") train_data_gen = training_set_generator(training_list[:train_data_length],batch_size, patch_size) val_data_gen = training_set_generator(training_list[train_data_length:],batch_size, patch_size) val_steps = (total_length - train_data_length)//batch_size print("Beginning Training...") model = get_unet(patch_size[0], patch_size[1], 1) # from tensorflow.compat.v2.keras.utils import multi_gpu_model # model = multi_gpu_model(model, gpus=2) ckpt = ModelCheckpoint(filepath=weights_path, verbose=1, monitor='val_loss', mode='auto', save_best_only=True) model.fit_generator(train_data_gen, train_data_length//batch_size, epochs= nepochs, verbose=1, callbacks=[ckpt], validation_data=val_data_gen, validation_steps=val_steps) elif mode == 'predict': img_paths = get_images_pre(input_path, extension=data_type, recursive=True) if not os.path.exists(output_path + 'predict'): os.makedirs(output_path + 'predict') if not os.path.exists(output_path + 'original'): os.makedirs(output_path + 'original') if not os.path.exists(output_path + 'merged'): os.makedirs(output_path + 'merged') for i, img_path in enumerate(img_paths): img = io.imread(img_path).astype('float32') img = np.array(img).astype('float32') img /= 255. # import pdb; pdb.set_trace() # img = np.array(img).astype('float32') # img /= np.max(img) # img = img * 255. # img = Image.fromarray(img).convert('L') # img.save(input_path+ '/../' + '_original.png', 'PNG') # img = cv2.GaussianBlur(img, (5, 5), 0) # img = cv2.medianBlur(img, 5) scale_percent = 100 # percent of original size width = int(img.shape[1] * scale_percent / 100) height = int(img.shape[0] * scale_percent / 100) dim = (width, height) resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA) img = resized og_img = np.array(img) img /= np.max(img) meanVal = np.mean(img) stdVal = np.std(img) # meanVal = 0.10874228924512863159 # stdVal = 0.13627362251281738281 img -= meanVal img /= stdVal # meanVal = np.mean(img) # stdVal = np.std(img) # img -= meanVal # img /= stdVal crop_left = img.shape[0] % (2 ** 3) // 2 crop_right = img.shape[0] % (2 ** 3) - crop_left crop_up = img.shape[1] % (2 ** 3) // 2 crop_down = img.shape[1] % (2 ** 3) - crop_up img = img[crop_left: img.shape[0] - crop_right, crop_up:img.shape[1] - crop_down] og_img = og_img[crop_left: og_img.shape[0] - crop_right, crop_up:og_img.shape[1] - crop_down] img = img.reshape(1, img.shape[0], img.shape[1], 1) model = get_unet(*img.shape[1:]) model.load_weights(weights_path) o1, o2, out_img = model.predict(img) im = out_img.reshape(img.shape[1], img.shape[2]) im = (im-np.min(im))/(np.max(im)-np.min(im)) * 255.0 og_img = (og_img-np.min(og_img))/(np.max(og_img)-np.min(og_img)+0.000000001) * 255.0 path_list = img_path.split(os.sep) name_the_file = (path_list[-1].split('.'))[0] #og_img = np.power(og_img, 0.5) blended_im = 0.2*og_img + 0.8*im stacked_im = np.dstack((og_img, og_img, blended_im)) anno_img = np.array(stacked_im).astype('uint8') print (anno_img.shape) print (og_img.shape) im = Image.fromarray(im).convert('L') og_img = Image.fromarray(og_img).convert('L') im.save(output_path + 'predict/' + name_the_file + '_predict.png', 'PNG') og_img.save(output_path + 'original/' + name_the_file + '_original.png', 'PNG') anno_img = Image.fromarray(anno_img).convert('RGB') anno_img.save(output_path + 'merged/' + name_the_file + '_annotated_mean_std_gaussian_.png', 'PNG') elif mode == 'ts': #time series # os.environ['CUDA_VISIBLE_DEVICES'] = '-1' directory = input_path dirs = os.listdir(directory) for idx in tqdm(range(len(dirs))): f = dirs[idx] if f[-3:] != 'tif': continue # import pdb; pdb.set_trace() print(f) fpath = os.path.join(directory, f) # import pdb; pdb.set_trace() file_prefix = os.path.splitext(f)[0] # import pdb; pdb.set_trace() out_dir = os.path.join(output_path, file_prefix) # out_dir = os.path.join('./_2020_kody_data/output_timeseries_anno_test', file_prefix) # import pdb;pdb.set_trace() outdir_stacked = os.path.join(out_dir, 'stacked') outdir_act_mask = os.path.join(out_dir, 'act_mask') outdir_act_org = os.path.join(out_dir, 'act_org') # import pdb;pdb.set_trace() if not os.path.exists(outdir_stacked): os.makedirs(outdir_stacked) if not os.path.exists(outdir_act_mask): os.makedirs(outdir_act_mask) if not os.path.exists(outdir_act_org): os.makedirs(outdir_act_org) # import pdb;pdb.set_trace() print ("Working on", file_prefix) with TiffFile(fpath) as tif: tif = tif.asarray() ''' resize ''' # timesteps, h,w = tif.shape # org_h, org_w = h, w # scale_percent = 140 # # h = int(h * scale_percent / 100) # # h = 1120 # # w = int(w * scale_percent / 100) # # w = 1120 # dim= (h, w) # newTif = np.zeros((timesteps, h, w)) # for i in range(timesteps): # newTif[i,:,:] = cv2.resize(tif[i,:,:], dim, interpolation = cv2.INTER_AREA) # # tif = newTif ''' end Resize ''' print (tif.shape) num_channels = len(tif.shape) if num_channels == 5: ntimesteps = tif.shape[0] channel_actin = tif[:,:,0,:,:] channel_wall = tif[:,:,1,:,:] mip_actin = np.max(channel_actin, axis=1) _, h,w = mip_actin.shape elif num_channels == 4: ntimesteps = tif.shape[0] channel_actin = tif[:1,1,:,:] channel_wall = tif[:1,0,:,:] mip_actin = channel_actin _, h,w = mip_actin.shape else: ntimesteps = tif.shape[0] mip_actin = tif _, h,w = mip_actin.shape tif = mip_actin movie_list = [] mt_list = [] batch_size = 1 tiffInputs = prediction_set_generator(tif, batch_size) model = get_unet(tif.shape[1], tif.shape[2], 1) # model.load_weights('./man/MT_parallel_128_020_030_050_Cross_hourglass_checkpoint_manual.h5') # model.load_weights('./' + targetPath + '/crossUp_2p5.h5') # man_2p5 # model.load_weights('//raid1/stromules/yiliu_code/manual/_2020_kody_data/weight/at_weights.h5') # man_2p5 # model.load_weights('//raid1/stromules/yiliu_code/manual/nate_patches_2/mean_std_one_image_crossUp_2p5_00000010.h5') # man_2p5 model.load_weights(weights_path) # man_2p5 # im1, im2, out_img = model.predict(mt_mip, batch_size=len(mt_mip)) im1, im2, out_img = model.predict_generator(tiffInputs, (len(tif) // batch_size) + 1) out_img = np.array(out_img) # post processing for tstep in range(len(out_img)): curr_out_img = out_img[tstep] original_img = tif[tstep, :, :].astype('float32') original_img = np.array(original_img) original_img /= np.max(original_img) original_img = 255. * original_img # mt_mip /= 255 # mt_mip = cv2.GaussianBlur(mt_mip, (5, 5), 0) # # mt_mip = mt_mip.astype(np.uint8) # # mt_mip = color.rgb2gray(mt_mip) # # original_img = np.array(mt_mip) curr_out_img = curr_out_img.reshape(h, w) curr_out_img = (curr_out_img-np.min(curr_out_img))/(np.max(curr_out_img)-np.min(curr_out_img)) * 255.0 og_img = original_img / np.max(original_img) og_img = (og_img-np.min(og_img))/(np.max(og_img)-np.min(og_img)+0.000000001) * 255. where_are_NaNs = np.isnan(og_img) og_img[where_are_NaNs] = 0 where_are_NaNs = np.isnan(curr_out_img) curr_out_img[where_are_NaNs] = 0 blended_im = 0.8*(og_img) + 0.2*curr_out_img stacked_im = np.dstack((blended_im, curr_out_img, curr_out_img)) # stacked_im = cv2.resize(stacked_im, (org_h,org_w), interpolation = cv2.INTER_AREA) # curr_out_img = cv2.resize(curr_out_img, (org_h,org_w), interpolation = cv2.INTER_AREA) try: io.imsave(outdir_stacked + '/' + str(tstep) + '.tif', stacked_im.astype('uint8')) io.imsave(outdir_stacked + '/' + str(tstep) + '.png', stacked_im.astype('uint8')) io.imsave(outdir_act_mask + '/' + str(tstep) + '.tif', curr_out_img.astype('uint8')) io.imsave(outdir_act_mask + '/' + str(tstep) + '.png', curr_out_img.astype('uint8')) io.imsave(outdir_act_org + '/' + str(tstep) + '.png', original_img.astype('uint8')) except: import pdb; pdb.set_trace() mt_list.append(curr_out_img) movie_list.append(stacked_im) if not os.path.exists(out_dir + '/output_time_series/'): os.makedirs(out_dir + '/output_time_series/') if not os.path.exists(out_dir + '/output_time_series_movie/'): os.makedirs(out_dir + '/output_time_series_movie/') if not os.path.exists(out_dir + '/output_time_series_stacked/'): os.makedirs(out_dir + '/output_time_series_stacked/') imageio.mimsave(out_dir + '/output_time_series/' + file_prefix + '_mt.tif', mt_list) imageio.mimsave(out_dir + '/output_time_series_movie/' + file_prefix + '_movie.gif', movie_list, duration=0.2) imageio.mimsave(out_dir + '/output_time_series_stacked/' + file_prefix + '_stacked.tif', movie_list)
def read_z_slices_per_file(self, file_name: Path) -> int: with TiffFile(file_name) as tif_file: z_axis_name = self._find_right_z_axis_name(tif_file) return TiffImageReader.find_count_of_axis(tif_file, z_axis_name)