def __init__(self, settings_filename=None, settings=None, prefix=''): if settings is None and settings_filename is None: raise ValueError("Either a settings object or a settings filename has to be given.") if not settings is None: self.settings = settings elif not settings_filename is None: self.settings = Settings(os.path.abspath(settings_filename), dctGlobals=globals()) for folder in self.settings.make_folder: if not os.path.isdir(folder): print 'made folder %s' % folder os.makedirs(folder) self.ov = Overlay() self.sw = SimpleWorkflow(settings=self.settings) self.prefix=prefix
class Select(object): def __init__(self, settings_filename=None, settings=None, prefix=''): if settings is None and settings_filename is None: raise ValueError("Either a settings object or a settings filename has to be given.") if not settings is None: self.settings = settings elif not settings_filename is None: self.settings = Settings(os.path.abspath(settings_filename), dctGlobals=globals()) for folder in self.settings.make_folder: if not os.path.isdir(folder): print 'made folder %s' % folder os.makedirs(folder) self.ov = Overlay() self.sw = SimpleWorkflow(settings=self.settings) self.prefix=prefix def overlay_graph(self, img, labels=None): thickness = 3 radius_offset=2 if labels is None: labels = [] width = img.shape[1] height = img.shape[0] #img = self.sw.reduce_range(img_16bit) colim = color.gray2rgb(img) if self.nodes is None: print 'graph is not yet built.' return # max_color = max(colorvalue) # if max_color > 1.0: # colorvalue = [a / np.float(max_color) for a in colorvalue] # first we draw the edges for node_id, node in self.nodes.iteritems(): for nb_id in node['neighbors']: nb_center = self.nodes[nb_id]['center'] rr, cc = skimage.draw.line(np.int(np.round(node['center'][0])), np.int(np.round(node['center'][1])), np.int(np.round(self.nodes[nb_id]['center'][0])), np.int(np.round(self.nodes[nb_id]['center'][1])) ) colorvalue = (255,255,255) indices = filter(lambda i: rr[i] > 0 and rr[i] < height and cc[i]>0 and cc[i]<width, range(len(rr)) ) rr = rr[indices] cc = cc[indices] for i, col in enumerate(colorvalue): colim[rr,cc,i] = col # second, we draw the graph labels for nodelabel, node in self.nodes.iteritems(): rr, cc = skimage.draw.circle(np.round(node['center'][0]), np.round(node['center'][1]), self.settings.graph_radius) indices = filter(lambda i: rr[i] > 0 and rr[i] < height and cc[i]>0 and cc[i]<width, range(len(rr)) ) rr = rr[indices] cc = cc[indices] if node['chosen']: colorvalue = self.settings.graph_color_code[0] elif node['allowed']: colorvalue = self.settings.graph_color_code[1] else: colorvalue = self.settings.graph_color_code[2] for i, col in enumerate(colorvalue): colim[rr,cc,i] = col if nodelabel in labels: colorvalue = labels[nodelabel] for cocentric in range(thickness): rr, cc = skimage.draw.circle_perimeter(np.int(np.round(node['center'][0])), np.int(np.round(node['center'][1])), np.int(self.settings.graph_radius+radius_offset+cocentric), method='andres') indices = filter(lambda i: rr[i] > 0 and rr[i] < height and cc[i]>0 and cc[i]<width, range(len(rr)) ) rr = rr[indices] cc = cc[indices] for i, col in enumerate(colorvalue): colim[rr,cc,i] = col return colim def find_neighbors(self, imbin, max_extension): background = np.zeros(imbin.shape) background[imbin==0] = 255 distance = ndi.distance_transform_edt(background) cell_labels = label(imbin, neighbors=4, background=0) # this is a hack, as background pixels obtain label -1 # and we do not want to have negative values. # from version 0.12 this can be removed, probably. cell_labels = cell_labels - cell_labels.min() # the mask is an extension of the initial shape by max_extension. # it can be derived from the distance map (straight forward) mask = np.zeros(imbin.shape) mask[distance < max_extension] = 255 # The watershed of the distance transform of the background. # this corresponds an approximation of the "cells" labels = watershed(distance, cell_labels, mask=mask) if self.settings.debug_screen_output: out_filename = os.path.join(self.settings.img_debug_folder, '%s16_distance.png' % self.prefix) temp = distance / distance.max() skimage.io.imsave(out_filename, temp) out_filename = os.path.join(self.settings.img_debug_folder, '%s16_labels_from_ws.png' % self.prefix) skimage.io.imsave(out_filename, labels) return cell_labels, labels def read_header(self, filename): impil = Image.open(filename) tagged_string = impil.tag.tagdata[270] root = ET.fromstring(tagged_string.strip('\x00')) subtree = root.find('PlaneInfo') properties = subtree.findall('prop') #<prop id="stage-position-x" type="float" value="18988"/> #<prop id="stage-position-y" type="float" value="15355"/> #<prop id="stage-label" type="string" value=""/> #<prop id="z-position" type="float" value="-1392.99"/> x = None y = None z = None for pr in properties: if 'id' in pr.attrib and pr.attrib['id'] == 'z-position': z = float(pr.attrib['value']) if 'id' in pr.attrib and pr.attrib['id'] == 'stage-position-x': x = float(pr.attrib['value']) if 'id' in pr.attrib and pr.attrib['id'] == 'stage-position-y': y = float(pr.attrib['value']) print 'x %f, y %f, z %f ' % (x, y, z) return x, y, z def get_properties(self, imbin, img): props = {} cell_labels = label(imbin, neighbors=4, background=0) cell_labels = cell_labels - cell_labels.min() properties = measure.regionprops(cell_labels, img) areas = [0] + [pr.area for pr in properties] convex_areas = [1] + [pr.convex_area for pr in properties] mean_intensities = [0.0] + [pr.mean_intensity for pr in properties] eccentricities = [0.0] + [pr.eccentricity for pr in properties] centers = [(0.0, 0.0)] + [pr.centroid for pr in properties] perimeters = [1.0] + [pr.perimeter for pr in properties] a = np.array(areas) b = np.array(perimeters) b[b==0.0] = 1.0 circ = 2 * np.sqrt(np.pi) * a / b c = np.array(convex_areas) cc_ar = a.astype(np.dtype('float')) / c.astype(np.dtype('float')) for i in range(1, cell_labels.max()+1): props[i] = { 'area': areas[i], 'mean_intensity': mean_intensities[i], 'eccentricity': eccentricities[i], 'center': centers[i], 'circularity': circ[i], 'cc_ar': cc_ar[i], } return props def distance_to_avg(self, props): # calc average: mean_area = np.mean([props[i]['area'] for i in props.keys()]) std_area = np.std([props[i]['area'] for i in props.keys()]) mean_intensity = np.mean([props[i]['mean_intensity'] for i in props.keys()]) std_intensity = np.std([props[i]['mean_intensity'] for i in props.keys()]) mean_ecc = np.mean([props[i]['eccentricity'] for i in props.keys()]) std_ecc = np.std([props[i]['eccentricity'] for i in props.keys()]) mean_circ = np.mean([props[i]['circularity'] for i in props.keys()]) std_circ = np.std([props[i]['circularity'] for i in props.keys()]) mean_cc_ar = np.mean([props[i]['cc_ar'] for i in props.keys()]) std_cc_ar = np.std([props[i]['cc_ar'] for i in props.keys()]) if std_area==0.0: std_area = 1.0 if std_intensity==0.0: std_intensity = 1.0 if std_ecc==0.0: std_ecc = 1.0 if std_circ==0.0: std_circ = 1.0 if std_cc_ar==0.0: std_cc_ar = 1.0 for i in props.keys(): # temp = (props[i]['area'] - mean_area)**2 + \ # (props[i]['mean_intensity'] - mean_intensity)**2 + \ # (props[i]['eccentricity'] - mean_ecc)**2 temp = ((props[i]['area'] - mean_area) / std_area)**2 + \ ((props[i]['mean_intensity'] - mean_intensity) / std_intensity)**2 + \ ((props[i]['eccentricity'] - mean_ecc) / std_ecc)**2 + \ ((props[i]['cc_ar'] - mean_cc_ar) / std_cc_ar)**2 + \ ((props[i]['circularity'] - mean_circ) / std_circ)**2 props[i]['distance'] = np.sqrt(temp) return props def old_select_label(self, labels=None): if labels is None: keys = sorted(filter(lambda x: self.nodes[x]['allowed'], self.nodes.keys())) elif len(labels) > 0: keys = sorted(filter(lambda x: self.nodes[x]['allowed'], labels)) else: keys = [] if len(keys) == 0: return None distances = [self.nodes[i]['distance'] for i in keys] min_distance = np.min(distances) possible_labels = filter(lambda i: self.nodes[i]['distance'] == min_distance, keys) if len(possible_labels) > 0: lb = possible_labels[0] self.nodes[lb]['chosen'] = True self.nodes[lb]['allowed'] = False else: lb = None return lb def select_label(self, labels=None): if labels is None: keys = sorted(filter(lambda x: self.nodes[x]['allowed'], self.nodes.keys())) elif len(labels) > 0: keys = sorted(filter(lambda x: self.nodes[x]['allowed'], labels)) else: keys = [] if len(keys) == 0: return None distances = np.array([self.nodes[i]['distance'] for i in keys]) min_distance = np.min(distances) possible_labels = filter(lambda i: self.nodes[i]['distance'] == min_distance, keys) if len(possible_labels) > 0: lb = possible_labels[0] else: lb = None return lb def eudist(self, a, b): res = np.sqrt(np.sum((np.array(a) - np.array(b))**2)) return res def normalize_vec_eu(self, a): mean_a = np.mean(a) std_a = np.std(a) if std_a > 0: norm_vec = (a - mean_a) / std_a else: norm_vec = a - mean_a return norm_vec def normalize_vec(self, a): min_a = np.min(a) max_a = np.max(a) if max_a > min_a: norm_vec = (a.astype('float') - min_a) / (max_a - min_a) else: norm_vec = a.astype('float') - min_a return norm_vec def select_cluster_nodes(self, labels=None): if labels is None: # in this case we take all the allowed nodes keys = sorted(filter(lambda x: self.nodes[x]['allowed'], self.nodes.keys())) elif len(labels) > 0: # in this case we take only the given set of labels (but only the subset which is allowed). keys = sorted(filter(lambda x: self.nodes[x]['allowed'], labels)) else: return None if len(keys) == 0: return None # among these labels, we need to find a seed for a cluster of cluster_size. # this seed is found by minimizing the feature distance. As no seed is guaranteed # to result in a valid cluster, we take all valid nodes and rank them according to their distance to the mean cell. if self.settings.ordered_cell_selection: dist_to_avg = self.normalize_vec(np.array([self.nodes[i]['distance'] for i in keys])) np_connections = self.normalize_vec(np.array([len(self.nodes[i]['neighbors']) for i in keys])) x = self.normalize_vec(np.array([self.nodes[i]['center'][1] for i in keys])) y = self.normalize_vec(np.array([self.nodes[i]['center'][0] for i in keys])) scores = np.array(1000 * np_connections + 100 * x + 10 * y + dist_to_avg) indices = scores.argsort() ranked_keys = np.array(keys)[indices] else: dist_to_avg = self.normalize_vec(np.array([self.nodes[i]['distance'] for i in keys])) #x = self.normalize_vec(np.array([self.nodes[i]['center'][1] for i in keys])) #y = self.normalize_vec(np.array([self.nodes[i]['center'][0] for i in keys])) np_connections = self.normalize_vec(np.array([len(self.nodes[i]['neighbors']) for i in keys])) scores = np.array(10 * (np.max(np_connections) - np_connections) + dist_to_avg) indices = scores.argsort() ranked_keys = np.array(keys)[indices] #print 'node selection : ', labels, ' --> ', ranked_keys #print '\t', [len(self.nodes[i]['neighbors']) for i in keys] #print '\t', [len(self.nodes[i]['neighbors']) for i in ranked_keys] cluster_size = self.settings.cluster_size cluster_defined = False # loop over all potential cluster seeds while not cluster_defined and len(ranked_keys) > 0: # get the cluster seed (the best one remaining) v = ranked_keys[0] ranked_keys = ranked_keys[1:] #cluster_nodes = [ranked_keys[0]] cluster_nodes = [] waiting_nodes = np.array([v]) nb_chosen = len(cluster_nodes) # loop to expand the cluster seed to reach cluster_size if possible. while nb_chosen < cluster_size and len(waiting_nodes) > 0: # for all waiting_nodes we calculate the maximal distance to the already selected nodes (cluster_nodes) # minimizing the maximal distance allows to have compact classes. if len(waiting_nodes) > 1 and len(cluster_nodes) > 0: eu_dist = [np.max(np.array([self.eudist(self.nodes[wo]['center'], self.nodes[cn]['center']) for cn in cluster_nodes])) for wo in waiting_nodes] indices = np.array(eu_dist).argsort() waiting_nodes = waiting_nodes[indices] node_added = False while not node_added and len(waiting_nodes) > 0: o = waiting_nodes[0] waiting_nodes = waiting_nodes[1:] #if self.nodes[o]['allowed'] and not o in cluster_nodes: if not o in cluster_nodes: cluster_nodes.append(o) node_added = True # add the neighbors to the waiting_nodes for nb in self.nodes[o]['neighbors']: # neighbors are added if self.nodes[nb]['allowed'] and not nb in waiting_nodes and not nb in cluster_nodes: waiting_nodes = np.append(waiting_nodes, nb) nb_chosen = len(cluster_nodes) if len(cluster_nodes) < cluster_size: # in this case, it was not possible to expand the cluster sufficiently. We can therefore set the corresponding # nodes to "not allowed" for node_id in cluster_nodes: self.nodes[node_id]['allowed'] = False else: cluster_defined = True if not cluster_defined: cluster_nodes = None return cluster_nodes def build_graph(self, adjmat, props): self.nodes = {} for i in range(1, adjmat.shape[0]): lab_vec = np.where(adjmat[i,:])[0] self.nodes[i] = {'allowed': True, 'neighbors': lab_vec[lab_vec>0], 'distance': props[i]['distance'], 'center': props[i]['center'], 'chosen': False, 'min_dist': adjmat.shape[0] + 1} return # recursive expansion def rec_expansion(self, lb, k): if k==0: return neighbors = self.nodes[lb]['neighbors'] for nb in neighbors: self.nodes[nb]['allowed'] = False self.expansion(nb, k-1) return def expansion_one_step(self, lb): changed=[] neighbors = self.nodes[lb]['neighbors'] for nb in neighbors: if self.nodes[nb]['allowed']: changed.append(nb) self.nodes[nb]['allowed'] = False return changed def expansion(self, lb, K): labels_todo = [lb] next_step = [] for i in range(K): for lb in labels_todo: changed = self.expansion_one_step(lb) next_step.extend(changed) labels_todo = next_step next_step = [] candidates = [] for lb in labels_todo: candidates.extend(self.nodes[lb]['neighbors'].tolist()) candidates = list(set(candidates)) candidates = filter(lambda x: self.nodes[x]['allowed'], candidates) return candidates def get_chosen_labels(self): chosen = filter(lambda x: self.nodes[x]['chosen'], self.nodes.keys()) return chosen def choose_labels_backup(self, K, imin_param=None): if self.settings.debug_screen_output: for node_id, node in self.nodes.iteritems(): print '%i: %s' % (node_id, self.nodes[node_id]['neighbors']) imin = imin_param if not imin_param is None: if not imin_param.dtype == 'uint8': imin = self.sw.reduce_range(imin_param, minmax=True) # initialization Lres = [] lb = self.select_label() #self.nodes[lb]['chosen'] = True #self.nodes[lb]['min_dist'] = 0 #self.nodes[lb]['allowed'] = False #Lcand = self.nodes[lb]['neighbors'].tolist() Lcand = [lb] #for nb in self.nodes[lb]['neighbors']: # Lcand.append(nb) r=0 while len(Lcand) > 0: # gets the best label among the candidates # the best means the closest to the average. v = self.select_label(Lcand) if self.settings.debug_screen_output: if not v is None: print 'Candidate: %i\tlabel: %i from %s' % (r, v, str(Lcand)) else: print 'no suitable candidate from candidate list' if v is None: # if none of the candidates is suitable, # we enlarge the search to all nodes. v = self.select_label() if v is None: # this means that there is no suitable candidate. Lcand = [] break # v has been selected. if self.settings.graph_overlay and not imin is None: colim = self.overlay_graph(imin, labels=dict(zip(Lcand, [(230, 200, 0) for ttt in Lcand]))) skimage.io.imsave(os.path.join(self.settings.img_graph_overlay_folder, '%sgraph_overlay_candidate%03i_a.png' % (self.prefix, r)), colim) self.nodes[v]['chosen'] = True if self.settings.graph_overlay and not imin is None: colim = self.overlay_graph(imin, labels=dict(zip(Lcand, [(230, 200, 0) for ttt in Lcand]))) skimage.io.imsave(os.path.join(self.settings.img_graph_overlay_folder, '%sgraph_overlay_candidate%03i_b.png' % (self.prefix, r)), colim) Lres.append(v) Q1 = Queue() Q2 = Queue() Q1.put(v) # expansion step for k in range(K+1): if self.settings.debug_screen_output and k>0: print '\texpansion: node %i\texpansion step %i\tcandidate: %i' % (v, k, r) while not Q1.empty(): n = Q1.get() self.nodes[n]['min_dist'] = min(self.nodes[n]['min_dist'], k) self.nodes[n]['allowed'] = False if self.settings.debug_screen_output: print '\t\t--> from Q1: %i' % n for nb in self.nodes[n]['neighbors']: if self.nodes[nb]['min_dist'] > k: Q2.put(nb) if self.settings.graph_overlay and not imin is None and k>0: lc_filtered = filter(lambda x: self.nodes[x]['allowed'], Lcand) colim = self.overlay_graph(imin, labels=dict(zip(lc_filtered, [(230, 200, 0) for ttt in lc_filtered]))) skimage.io.imsave(os.path.join(self.settings.img_graph_overlay_folder, '%sgraph_overlay_candidate%03i_step%03i.png' % (self.prefix, r, k)), colim) Q1 = Q2 Q2 = Queue() # add new candidates while not Q1.empty(): n = Q1.get() if self.nodes[n]['allowed']: Lcand.append(n) if len(Lcand) == 0: v = self.select_label() if not v is None: Lcand = [v] Lcand = list(set(filter(lambda x: x != v and self.nodes[x]['allowed'], Lcand))) r += 1 return Lres def choose_labels(self, K, imin_param=None): if self.settings.debug_screen_output: for node_id, node in self.nodes.iteritems(): print '%i: %s' % (node_id, self.nodes[node_id]['neighbors']) imin = imin_param if not imin_param is None: if not imin_param.dtype == 'uint8': imin = self.sw.reduce_range(imin_param, minmax=True) cluster_size = self.settings.cluster_size cluster_dist = self.settings.cluster_dist # initialization Lres = [] if self.settings.ordered_cell_selection: #np_connections = self.normalize_vec(np.array([len(self.nodes[i]['neighbors']) for i in keys])) keys = sorted(self.nodes.keys()) x = self.normalize_vec(np.array([self.nodes[i]['center'][1] for i in keys])) y = self.normalize_vec(np.array([self.nodes[i]['center'][0] for i in keys])) scores = np.array(x**2 + y**2) indices = scores.argsort() lb = keys[indices[0]] else: lb = self.select_label() Lcand = [lb] #Lcand = self.select_cluster_nodes() r=0 while len(Lcand) > 0: # gets the best label among the candidates # the best means the closest to the average. #v = self.select_label(Lcand) v = self.select_cluster_nodes(Lcand) # if self.settings.debug_screen_output: # if not v is None: # print 'Candidate: %i\tlabel: %i from %s' % (r, v, str(Lcand)) # else: # print 'no suitable candidate from candidate list' if v is None: # if none of the candidates is suitable, # we enlarge the search to all nodes. v = self.select_cluster_nodes() if v is None: # this means that there is no suitable candidate. # the algorithm has to stop Lcand = [] break # v has been selected. if self.settings.graph_overlay and not imin is None: colim = self.overlay_graph(imin, labels=dict(zip(Lcand, [(230, 200, 0) for ttt in Lcand]))) skimage.io.imsave(os.path.join(self.settings.img_graph_overlay_folder, '%sgraph_overlay_candidate%03i_a.png' % (self.prefix, r)), colim) # all nodes in the cluster are set to "chosen" for s in v: self.nodes[s]['chosen'] = True if self.settings.graph_overlay and not imin is None: colim = self.overlay_graph(imin, labels=dict(zip(Lcand, [(230, 200, 0) for ttt in Lcand]))) skimage.io.imsave(os.path.join(self.settings.img_graph_overlay_folder, '%sgraph_overlay_candidate%03i_b.png' % (self.prefix, r)), colim) Lres.extend(v) Q1 = Queue() Q2 = Queue() for node_id in v: Q1.put(node_id) # expansion step for k in range(K+1): #if self.settings.debug_screen_output and k>0: # print '\texpansion: node %i\texpansion step %i\tcandidate: %i' % (v, k, r) while not Q1.empty(): n = Q1.get() self.nodes[n]['min_dist'] = min(self.nodes[n]['min_dist'], k) self.nodes[n]['allowed'] = False # if self.settings.debug_screen_output: # print '\t\t--> from Q1: %i' % n for nb in self.nodes[n]['neighbors']: if self.nodes[nb]['min_dist'] > k: Q2.put(nb) if self.settings.graph_overlay and not imin is None and k>0: lc_filtered = filter(lambda x: self.nodes[x]['allowed'], Lcand) colim = self.overlay_graph(imin, labels=dict(zip(lc_filtered, [(230, 200, 0) for ttt in lc_filtered]))) skimage.io.imsave(os.path.join(self.settings.img_graph_overlay_folder, '%sgraph_overlay_candidate%03i_step%03i.png' % (self.prefix, r, k)), colim) Q1 = Q2 Q2 = Queue() # add new candidates while not Q1.empty(): n = Q1.get() if self.nodes[n]['allowed']: Lcand.append(n) if len(Lcand) == 0: v = self.select_cluster_nodes() if not v is None: Lcand = v Lcand = list(set(filter(lambda x: not self.nodes[x]['chosen'] and self.nodes[x]['allowed'], Lcand))) r += 1 return Lres def centers_to_text_file(self, imout, filename): # get the centers labels = label(imout, neighbors=4, background=0) properties = measure.regionprops(labels, imout) #pdb.set_trace() centers = [(0.0, 0.0)] + [ (pr.centroid[0] * self.settings.param_pixel_size, pr.centroid[1] * self.settings.param_pixel_size) for pr in properties] fp = open(filename, 'w') for x,y in centers[1:]: fp.write('%f\t%f\n' % (x,y)) fp.close() return def centers_to_px_text_file(self, imout, filename): # get the centers labels = label(imout, neighbors=4, background=0) properties = measure.regionprops(labels, imout) centers = [(0.0, 0.0)] + [pr.centroid for pr in properties] fp = open(filename, 'w') for x,y in centers[1:]: fp.write('%i\t%i\n' % (x,y)) fp.close() return def export_metamorph(self, imout, filename, stage_coord=None): if stage_coord is None: stage_coord = (0, 0, 0) # get the centers labels = label(imout, neighbors=4, background=0) properties = measure.regionprops(labels, imout) # check centers #for pr in properties: # print 'image coordinates (pixel) : %i, %i' % (pr.centroid[0], pr.centroid[1]) centers = [(0.0, 0.0)] + [ (pr.centroid[0] * self.settings.param_pixel_size, pr.centroid[1] * self.settings.param_pixel_size) for pr in properties] nb_cells = len(centers) -1 # write the information in a metamorph .stg format. fp = open(filename, 'w') fp.write('"Stage Memory List", Version 6.0\n') fp.write('0, 0, 0, 0, 0, 0, 0, "um", "um"\n') fp.write('0\n') fp.write('%i\n' % nb_cells) # image dimension in micrometer w = imout.shape[1] * self.settings.param_pixel_size h = imout.shape[0] * self.settings.param_pixel_size print 'width and height : ', w, h i = 1 for y, x in centers[1:]: x_o = stage_coord[0] + y - h / 2.0 y_o = stage_coord[1] + w / 2.0 - x z_o = stage_coord[2] #print x, y, ' ---> ', x_o, y_o, z_o tempStr = '"Cell%i", %f, %f, %f, 0, 0, FALSE, -9999, TRUE, TRUE, 0, -1, ""\n' % (i, x_o, y_o, z_o) fp.write(tempStr) i += 1 fp.close() # write the original point (in order to get back to the origin) extension = os.path.splitext(filename)[-1] basefilename = os.path.splitext(filename)[0] origin_filename = basefilename + '_origin' + extension fp = open(origin_filename, 'w') fp.write('"Stage Memory List", Version 6.0\n') fp.write('0, 0, 0, 0, 0, 0, 0, "um", "um"\n') fp.write('0\n') fp.write('1\n') tempStr = '"Cell1", %f, %f, %f, 0, 0, FALSE, -9999, TRUE, TRUE, 0, -1, ""\n' % (stage_coord[0], stage_coord[1], stage_coord[2]) fp.write(tempStr) fp.close() return def circles_to_xml_file(self, imout, filename): # get the centers labels = label(imout, neighbors=4, background=0) properties = measure.regionprops(labels, imout) centers = [(0.0, 0.0)] + [pr.centroid for pr in properties] fp = open(filename, 'w') for x,y in centers[1:]: fp.write('%i\t%i\n' % (x,y)) fp.close() return def __call__(self, imin, imbin, K, max_extension=100): # First we label cellular regions. # this can be done by a simple voronoi approach or by some other method. # here it is done with voronoi (with max extension of 100). cell_labels, labels = self.find_neighbors(imbin, max_extension) if self.settings.debug: skimage.io.imsave(os.path.join(self.settings.img_debug_folder, '%s16_basis_for_graph.png' % self.prefix), labels) # find the co-occurence matrix. # The co-occurence matrix informs us about the neighboring relationships. # From there, we can build the graph. # attention : this does only work for < 256 objects. # in order to fix this, I need to patch skimage. cooc = skimage.feature.greycomatrix(labels, [1], [0, np.pi/4, np.pi/2, 3*np.pi/4, np.pi, 5*np.pi/4, 3*np.pi/2, 7*np.pi/4], levels=labels.max() + 1) # we sum over different directions cooc = np.sum(cooc[:,:,0,:], axis=2) # and we remove the diagonal cooc = cooc - np.diag(np.diag(cooc)) # adjacency matrix corresponds to the entries > 0. adjmat = cooc>0 # calculate properties to find the most "representative cell" node_properties = self.get_properties(imbin, imin) self.distance_to_avg(node_properties) # build graph self.build_graph(adjmat, node_properties) # select the cells (main algorithm) labres = self.choose_labels(K, imin) # get an output image label_values = np.zeros((labels.max() + 1)).astype(np.uint8) label_values[np.array(labres)] = 255 imout = label_values[cell_labels] if self.settings.single_mask: skimage.io.imsave(os.path.join(self.settings.img_single_output_folder, '%s_selected_cells.png' % self.prefix), imout) label_values[label_values==0] = 100 label_values[0] = 0 temp = label_values[cell_labels] skimage.io.imsave(os.path.join(self.settings.img_single_output_folder, '%s_selected_and_other_cells.png' % self.prefix), temp) return imout