def mod_zedge(composite, mod_id, algorithm, **kwargs): zedge_channel, zedge_channel_created = composite.channels.get_or_create(name="-zedge") for t in range(composite.series.ts): print("step02 | processing mod_zedge t{}/{}...".format(t + 1, composite.series.ts), end="\r") zdiff_mask = composite.masks.get(channel__name__contains=kwargs["channel_unique_override"], t=t).load() zbf = exposure.rescale_intensity(composite.gons.get(channel__name="-zbf", t=t).load() * 1.0) zedge = zbf.copy() binary_mask = zdiff_mask > 0 outside_edge = distance_transform_edt(dilate(edge_image(binary_mask), iterations=4)) outside_edge = 1.0 - exposure.rescale_intensity(outside_edge * 1.0) zedge *= outside_edge * outside_edge zedge_gon, zedge_gon_created = composite.gons.get_or_create( experiment=composite.experiment, series=composite.series, channel=zedge_channel, t=t ) zedge_gon.set_origin(0, 0, 0, t) zedge_gon.set_extent(composite.series.rs, composite.series.cs, 1) zedge_gon.array = zedge.copy() zedge_gon.save_array(composite.series.experiment.composite_path, composite.templates.get(name="source")) zedge_gon.save()
def create_region_tile(self, channel_unique_override, top_channel='-zbf', side_channel='-zunique', main_channel='-zunique'): tile_path = join(self.experiment.video_path, 'regions', self.series.name, channel_unique_override) if not exists(tile_path): os.makedirs(tile_path) for t in range(self.series.ts): zbf_gon = self.gons.get(t=t, channel__name=top_channel) zcomp_gon = self.gons.get(t=t, channel__name=side_channel) zmean_gon = self.gons.get(t=t, channel__name=main_channel) zbf = zbf_gon.load() zbf = zbf if len(zbf.shape)==2 or (len(zbf.shape)==2 and zbf.shape[2]==2) else np.squeeze(zbf[:,:,0]) zcomp = zcomp_gon.load() zcomp = zcomp if len(zcomp.shape)==2 or (len(zcomp.shape)==2 and zcomp.shape[2]==2) else np.squeeze(zcomp[:,:,0]) zmean = zmean_gon.load() zmean = zmean if len(zmean.shape)==2 or (len(zmean.shape)==2 and zmean.shape[2]==2) else np.squeeze(zmean[:,:,0]) zbf_mask_r = zbf.copy() zbf_mask_g = zbf.copy() zbf_mask_b = zbf.copy() zcomp_mask_r = zcomp.copy() zcomp_mask_g = zcomp.copy() zcomp_mask_b = zcomp.copy() # draw regions for region_instance in self.series.region_instances.filter(region_track_instance__t=t): # load mask mask = region_instance.masks.all()[0].load() # get mask outline mask_edge = edge_image(mask) # draw outlines in blue channel zbf_mask_r[mask_edge>0] = 0 zbf_mask_g[mask_edge>0] = 0 zbf_mask_b[mask_edge>0] = 255 zcomp_mask_r[mask_edge>0] = 0 zcomp_mask_g[mask_edge>0] = 0 zcomp_mask_b[mask_edge>0] = 255 # tile zbf, zbf_mask, zcomp, zcomp_mask top_half = np.concatenate((np.dstack([zbf, zbf, zbf]), np.dstack([zbf_mask_r, zbf_mask_g, zbf_mask_b])), axis=0) bottom_half = np.concatenate((np.dstack([zmean, zmean, zmean]), np.dstack([zcomp_mask_r, zcomp_mask_g, zcomp_mask_b])), axis=0) whole = np.concatenate((top_half, bottom_half), axis=1) imsave(join(tile_path, 'tile_{}_s{}_region-{}_t{}.tiff'.format(self.experiment.name, self.series.name, channel_unique_override, str_value(t, self.series.ts))), whole)
def create_zedge(self, channel_unique_override): zedge_channel, zedge_channel_created = self.channels.get_or_create(name='-zedge') for t in range(self.series.ts): print('step02 | processing mod_zedge t{}/{}...'.format(t+1, self.series.ts), end='\r') zunique_mask = self.masks.get(channel__name__contains=channel_unique_override, t=t).load() zbf = exposure.rescale_intensity(self.gons.get(channel__name='-zbf', t=t).load() * 1.0) zedge = zbf.copy() binary_mask = zunique_mask>0 outside_edge = distance_transform_edt(dilate(edge_image(binary_mask), iterations=4)) outside_edge = 1.0 - exposure.rescale_intensity(outside_edge * 1.0) zedge *= outside_edge * outside_edge zedge_gon, zedge_gon_created = self.gons.get_or_create(experiment=self.experiment, series=self.series, channel=zedge_channel, t=t) zedge_gon.set_origin(0,0,0,t) zedge_gon.set_extent(self.series.rs, self.series.cs, 1) zedge_gon.array = zedge.copy() zedge_gon.save_array(self.experiment.composite_path, self.templates.get(name='source')) zedge_gon.save() return zedge_channel
def mask_edge_image(mask_img): full_edge_img = np.zeros(mask_img.shape) for unique in [u for u in np.unique(mask_img) if u > 0]: full_edge_img += edge_image(mask_img == unique) return full_edge_img > 0
def handle(self, *args, **options): # vars experiment_name = options['expt'] series_name = options['series'] if experiment_name!='' and series_name!='': experiment = Experiment.objects.get(name=experiment_name) series = experiment.series.get(name=series_name) # cell_instance = series.cell_instances.get(t=48, cell__pk=4) # cell_instance = series.cell_instances.get(t=49, cell__pk=9) # cell_instance = series.cell_instances.get(pk=198) # load mask image # 1. for each cell mask, load mask image outlines = {} colours = ['red','green','blue','purple'] for i, cell_mask in enumerate(cell_instance.masks.filter(channel__name__contains='zunique')): mask_img = cell_mask.load() # get edge edge_img = edge_image(mask_img) # get list of points points_r, points_c = np.where(edge_img) points = [list(lm) for lm in list(zip(points_r, points_c))] sorted_points = roll_edge_v1(points) # plot distances in order cell_centre = np.array([cell_mask.r, cell_mask.c]) distances = np.array([np.linalg.norm(cell_centre - np.array(p)) for p in sorted_points]) argmin = np.argmin(distances) distances = np.roll(distances, -argmin) distances = gf(distances, sigma=2) # plt.plot(distances) # plt.scatter(cell_mask.c, cell_mask.r) # find peaks in distance array peaks = find_peaks(distances, np.array([9])) # plt.scatter(peaks, [distances[peak] for peak in peaks]) # roll back to find true peak positions true_peaks = np.array(peaks) + argmin true_peaks[true_peaks>=len(sorted_points)] -= len(sorted_points) # find end point of protrusions protrusion_end_points = [sorted_points[peak] for peak in true_peaks] for protrusion_end_point in protrusion_end_points: print('new protrusion for cell mask {} for cell instance {}'.format(cell_mask.pk, cell_instance.pk)) relative_end_point = cell_centre - np.array(protrusion_end_point) print(cell_centre, protrusion_end_point) print('length from centre: {} microns'.format(np.linalg.norm(relative_end_point * series.scaling()))) print('orientation: {} degrees'.format(180 / math.pi * math.atan2(relative_end_point[0], relative_end_point[1]))) # plt.scatter([sorted_points[peak][1] for peak in true_peaks], [sorted_points[peak][0] for peak in true_peaks]) # plot outlines to check plt.plot([point[1] for point in sorted_points], [point[0] for point in sorted_points], label='radius: 2') # plt.scatter(points_c, points_r, label=cell_mask.channel.name, color=colours[i]) # plt.legend() # plt.axis('equal') plt.show() else: print('Please enter an experiment')
def handle(self, *args, **options): composite = Composite.objects.get(experiment__name="260714", series__name="15") # frames previous_frame_index = 0 target_frame_index = 1 next_frame_index = 2 # stacks previous_gfp_stack = composite.gons.get(t=previous_frame_index, channel__name="0") previous_bf_stack = composite.gons.get(t=previous_frame_index, channel__name="1") target_gfp_stack = composite.gons.get(t=target_frame_index, channel__name="0") target_bf_stack = composite.gons.get(t=target_frame_index, channel__name="1") target_zmean_single = composite.gons.get(t=target_frame_index, channel__name="-zmean") target_zbf_single = composite.gons.get(t=target_frame_index, channel__name="-zbf") target_zmod_single = composite.gons.get(t=target_frame_index, channel__name="-zmod") next_gfp_stack = composite.gons.get(t=next_frame_index, channel__name="0") next_bf_stack = composite.gons.get(t=next_frame_index, channel__name="1") # images # previous_gfp = previous_gfp_stack.load() # previous_bf = previous_bf_stack.load() # target_gfp = target_gfp_stack.load() # target_bf = target_bf_stack.load() target_zmean = target_zmean_single.load() / 255.0 target_zbf = target_zbf_single.load() / 255.0 target_zbf_canny_s3 = canny(target_zbf, sigma=1).astype(float) target_zmod = target_zmod_single.load() / 255.0 * (composite.series.zs - 1) # next_gfp = next_gfp_stack.load() # next_bf = next_bf_stack.load() # 1. find maximum from marker # marker = composite.markers.get(pk=124) track_image = np.zeros(target_zmod.shape) class Traveller: movement_cost = 1 directions = [(0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)] spawned = False def __init__(self, r, c, direction_index, money, cost_function): self.r = r self.c = c self.direction_index = direction_index self.drdc() self.money = money self.cost_function = cost_function def drdc(self): self.dr, self.dc = self.directions[self.direction_index] def move(self): # pick one of five directions in the direction of travel, find the one that costs the least money # get array of direction indices relative to current new_directions = [ (abs(i), (i if i < 8 else i - 8) if i >= 0 else i + 7) for i in range(self.direction_index - 2, self.direction_index + 3) ] costs = [] for cost_index, direction in new_directions: dr, dc = self.directions[direction] new_r, new_c = self.r + dr, self.c + dc if ( 0 <= new_r < composite.series.rs and 0 <= new_c < composite.series.cs and 0 <= self.r < composite.series.rs and 0 <= self.c < composite.series.cs and track_image[new_r, new_c] == 0 ): # not out of bounds # print(new_r, new_c, self.r, self.c, dr, dc) # differences delta_z = int(target_zmod[new_r, new_c]) - int(target_zmod[self.r, self.c]) delta_zbf = (target_zbf[new_r, new_c] - target_zbf[self.r, self.c]) / target_zbf[self.r, self.c] delta_zmean = (target_zmean[new_r, new_c] - target_zmean[self.r, self.c]) / target_zmean[ self.r, self.c ] abs_zbf = target_zbf[new_r, new_c] abs_zmean = target_zmean[new_r, new_c] cost = self.cost_function(delta_z, delta_zbf, delta_zmean, abs_zbf, abs_zmean) costs.append({"cost": cost, "direction": direction}) if costs: min_direction = min(costs, key=lambda c: c["cost"]) track_image[self.r, self.c] = 1 self.r, self.c = tuple( np.array(self.directions[min_direction["direction"]]) + np.array((self.r, self.c)) ) self.money -= min_direction["cost"] else: self.money = 0 # cost functions def test_cost_function(delta_z, delta_zbf, delta_zmean, abs_zbf, abs_zmean): cost = 0 cost += np.abs(delta_z) * 8 cost += -delta_zbf * 4 if delta_zbf < 0 else 0 # cost += -delta_zmean * 10.0 return cost def dont_go_through_dark_edges(delta_z, delta_zbf, delta_zmean, abs_zbf, abs_zmean): cost = 0 cost += np.abs(delta_z) * 4 cost += -delta_zbf * 7 if delta_zbf < 0 else 0 return cost def dont_go_to_another_z(delta_z, delta_zbf, delta_zmean, abs_zbf, abs_zmean): cost = 0 cost += np.abs(delta_z) * 8 return cost # set up segmentation - round 1 travellers = [] for marker in composite.markers.filter(track_instance__t=target_frame_index): for i in range(10): travellers.append(Traveller(marker.r, marker.c, np.random.randint(0, 7), 10, dont_go_to_another_z)) iterations = 0 while sum([t.money for t in travellers]) > 0: iterations += 1 for traveller in travellers: if traveller.money > 0: traveller.move() if traveller.money <= 0: travellers.remove(traveller) del traveller # spawn travellers from edge of track_image or round 2 travellers = [] track_edge = edge_image(track_image) for r, c in zip(*np.where(track_edge > 0)): travellers.append(Traveller(r, c, np.random.randint(0, 7), 10, dont_go_through_dark_edges)) iterations = 0 while sum([t.money for t in travellers]) > 0: iterations += 1 for traveller in travellers: if traveller.money > 0: traveller.move() if traveller.money <= 0: travellers.remove(traveller) del traveller # print(iterations, len(travellers), sum([t.money for t in travellers])) # cut = target_zmean[marker.r-10: marker.r+10, marker.c-10: marker.c+10] # plt.imshow(cut) # plt.show() track_image = dilate(erode(erode(dilate(track_image)))) display_image = target_zbf.copy() display_image[track_image == 1] += 0.3 plt.imshow(display_image) plt.show()
def mod_step13_cell_masks(composite, mod_id, algorithm): # paths template = composite.templates.get(name='mask') # MASK TEMPLATE # create batches batch = 0 max_batch_size = 100 # channel cell_mask_channel, cell_mask_channel_created = composite.channels.get_or_create(name='cellmask') # mean # mask_mean_max = np.max([mask.mean for mask in composite.masks.all()]) # iterate over frames for t in range(composite.series.ts): print('step13 | processing mod_step13_cell_masks t{}... '.format(t), end='\r') # one mask for each marker markers = composite.series.markers.filter(t=t) # 1. get masks mask_gon_set = composite.gons.filter(channel__name__in=['pmodreduced','bfreduced'], t=t) bulk = create_bulk_from_image_set(mask_gon_set) for m, marker in enumerate(markers): print('step13 | processing mod_step13_cell_masks t{}, marker {}/{}... '.format(t, m, len(markers)), end='\r') if composite.gons.filter(marker=marker).count()==0: # marker parameters r, c, z = marker.r, marker.c, marker.z other_marker_positions = [(m.r,m.c) for m in markers.exclude(pk=marker.pk)] # get primary mask primary_mask = np.zeros(composite.series.shape(), dtype=float) # blank image mask_uids = [(i, uid) for i,uid in enumerate(bulk.gon_stack[r,c,:]) if uid>0] for i,uid in mask_uids: gon_pk = bulk.rv[i] mask = composite.masks.get(gon__pk=gon_pk, mask_id=uid) mask_array = (bulk.slice(pk=mask.gon.pk)==mask.mask_id).astype(float) # modify mask array based on parameters mask_z, mask_max_z, mask_mean, mask_std = mask.z, mask.max_z, mask.mean, mask.std z_term = 1.0 / (1.0 + 0.1*np.abs(z - mask_z)) # suppress z levels at increasing distances from marker max_z_term = 1.0 / (1.0 + 0.1*np.abs(z - mask_max_z)) # suppress z levels at increasing distances from marker # mean_term = mask_mean / mask_mean_max # raise mask according to mean std_term = 1.0 mask_array = mask_array * z_term * max_z_term * std_term # add to primary mask primary_mask += mask_array # get secondary mask - get unique masks that touch the edge of the primary mask secondary_mask = np.zeros(composite.series.shape(), dtype=float) # blank image secondary_mask_uids = [] edges = np.where(edge_image(primary_mask>0)) for r, c in zip(*edges): for i,uid in enumerate(bulk.gon_stack[r,c,:]): if (i,uid) not in secondary_mask_uids and (i,uid) not in mask_uids and uid>0: secondary_mask_uids.append((i,uid)) for i,uid in secondary_mask_uids: print('step13 | processing mod_step13_cell_masks t{}, marker {}/{}, secondary {}/{}... '.format(t, m, len(markers), i, len(secondary_mask_uids)), end='\r') gon_pk = bulk.rv[i] mask = composite.masks.get(gon__pk=gon_pk, mask_id=uid) mask_array = (bulk.slice(pk=mask.gon.pk)==mask.mask_id).astype(float) # modify mask array based on parameters mask_z, mask_max_z, mask_mean, mask_std = mask.z, mask.max_z, mask.mean, mask.std z_term = 1.0 / (1.0 + 0.1*np.abs(z - mask_z)) # suppress z levels at increasing distances from marker max_z_term = 1.0 / (1.0 + 0.1*np.abs(z - mask_max_z)) # suppress z levels at increasing distances from marker # mean_term = mask_mean / mask_mean_max # raise mask according to mean std_term = 1.0 foreign_marker_condition = 1.0 # if the mask contains a different marker foreign_marker_match = False foreign_marker_counter = 0 while not foreign_marker_match and foreign_marker_counter!=len(other_marker_positions)-1: r, c = other_marker_positions[foreign_marker_counter] foreign_marker_match = (mask_array>0)[r,c] if foreign_marker_match: foreign_marker_condition = 0.0 foreign_marker_counter += 1 mask_array = mask_array * z_term * max_z_term * std_term * foreign_marker_condition # add to primary mask secondary_mask += mask_array print('step13 | processing mod_step13_cell_masks t{}, marker {}/{}, saving square mask... '.format(t, m, len(markers)), end='\n' if t==composite.series.ts-1 else '\r') cell_mask = primary_mask + secondary_mask # finally, mean threshold mask cell_mask[cell_mask<nonzero_mean(cell_mask)] = 0 cell_mask[cell_mask<nonzero_mean(cell_mask)] = 0 # cut to size # I want every mask to be exactly the same size -> 128 pixels wide # I want the centre of the mask to be in the centre of image # Add black space around even past the borders of larger image # 1. determine centre of mass com_r, com_c = com(cell_mask>0) mask_square = np.zeros((256,256), dtype=float) if not np.isnan(com_r): # 2. cut to black and preserve boundaries cut, (cr, cc, crs, ccs) = cut_to_black(cell_mask) # 3. place cut inside square image using the centre of mass and the cut boundaries to hit the centre dr, dc = int(128 + cr - com_r), int(128 + cc - com_c) # 4. preserve coordinates of square to position gon small_r, small_c = mask_square[dr:dr+crs,dc:dc+ccs].shape mask_square[dr:dr+crs,dc:dc+ccs] = cut[:small_r,:small_c] # check batch and make folders, set url if not os.path.exists(os.path.join(composite.experiment.cp2_path, composite.series.name, str(batch))): os.makedirs(os.path.join(composite.experiment.cp2_path, composite.series.name, str(batch))) if len(os.listdir(os.path.join(composite.experiment.cp2_path, composite.series.name, str(batch))))>=max_batch_size: batch += 1 if not os.path.exists(os.path.join(composite.experiment.cp2_path, composite.series.name, str(batch))): os.makedirs(os.path.join(composite.experiment.cp2_path, composite.series.name, str(batch))) root = os.path.join(composite.experiment.cp2_path, composite.series.name, str(batch)) # CP PATH # cell mask gon cell_mask_gon = composite.gons.create(experiment=composite.experiment, series=composite.series, channel=cell_mask_channel, template=template) cell_mask_gon.set_origin(cr-dr, cc-dc, z, t) cell_mask_gon.set_extent(crs, ccs, 1) id_token = generate_id_token('img','Gon') cell_mask_gon.id_token = id_token file_name = template.rv.format(id_token) url = os.path.join(root, file_name) imsave(url, mask_square.copy()) cell_mask_gon.paths.create(composite=composite, channel=cell_mask_channel, template=template, url=url, file_name=file_name, t=t, z=z) # associate with marker marker.gon = cell_mask_gon cell_mask_gon.marker = marker marker.save() cell_mask_gon.save()
def create_tile(self, channel_unique_override, top_channel='-zbf', side_channel='-zunique', main_channel='-zedge', region_list=[]): tile_path = join(self.experiment.video_path, 'tile', self.series.name, '{}-{}'.format(dt.datetime.now().strftime('%Y-%m-%d-%H-%M'), channel_unique_override)) if not exists(tile_path): os.makedirs(tile_path) for t in range(self.series.ts): zbf_gon = self.gons.get(t=t, channel__name=top_channel) zcomp_gon = self.gons.get(t=t, channel__name=side_channel) zmean_gon = self.gons.get(t=t, channel__name=main_channel) mask_mask = self.masks.get(t=t, channel__name__contains=channel_unique_override) zbf = zbf_gon.load() zbf = zbf if len(zbf.shape)==2 or (len(zbf.shape)==2 and zbf.shape[2]==2) else np.squeeze(zbf[:,:,0]) zcomp = zcomp_gon.load() zcomp = zcomp if len(zcomp.shape)==2 or (len(zcomp.shape)==2 and zcomp.shape[2]==2) else np.squeeze(zcomp[:,:,0]) zmean = zmean_gon.load() zmean = zmean if len(zmean.shape)==2 or (len(zmean.shape)==2 and zmean.shape[2]==2) else np.squeeze(zmean[:,:,0]) mask = mask_mask.load() # remove cells in regions if region_list: for cell_mask in mask_mask.cell_masks.exclude(region__name__in=region_list): mask[mask==cell_mask.gray_value_id] = 0 # delete masks from image if not in regions mask_outline = mask_edge_image(mask) zbf_mask_r = zbf.copy() zbf_mask_g = zbf.copy() zbf_mask_b = zbf.copy() zcomp_mask_r = zcomp.copy() zcomp_mask_g = zcomp.copy() zcomp_mask_b = zcomp.copy() # drawing # 1. draw outlines in red channel zbf_mask_r[mask_outline>0] = 255 zbf_mask_g[mask_outline>0] = 0 zbf_mask_b[mask_outline>0] = 0 zcomp_mask_r[mask_outline>0] = 255 zcomp_mask_g[mask_outline>0] = 0 zcomp_mask_b[mask_outline>0] = 0 # draw markers markers = self.markers.filter(track_instance__t=t, track__cell__isnull=False) for marker in markers: if hasattr(marker.track_instance, 'cell_instance'): if marker.track_instance.cell_instance.masks.filter(channel__name__contains=channel_unique_override): if region_list==[] or (marker.track_instance.cell_instance.masks.get(channel__name__contains=channel_unique_override).region is not None and marker.track_instance.cell_instance.masks.get(channel__name__contains=channel_unique_override).region.name in region_list): # 2. draw markers in blue channel zbf_mask_r[marker.r-2:marker.r+3,marker.c-2:marker.c+3] = 0 zbf_mask_g[marker.r-2:marker.r+3,marker.c-2:marker.c+3] = 0 zbf_mask_b[marker.r-2:marker.r+3,marker.c-2:marker.c+3] = 255 zcomp_mask_r[marker.r-2:marker.r+3,marker.c-2:marker.c+3] = 0 zcomp_mask_g[marker.r-2:marker.r+3,marker.c-2:marker.c+3] = 0 zcomp_mask_b[marker.r-2:marker.r+3,marker.c-2:marker.c+3] = 255 # 3. draw text in green channel blank_slate = np.zeros(zbf.shape) blank_slate_img = Image.fromarray(blank_slate) draw = ImageDraw.Draw(blank_slate_img) draw.text((marker.c+5, marker.r+5), '{}'.format(marker.track.cell.pk), font=ImageFont.load_default(), fill='rgb(0,0,255)') blank_slate = np.array(blank_slate_img) zbf_mask_r[blank_slate>0] = 0 zbf_mask_g[blank_slate>0] = 255 zbf_mask_b[blank_slate>0] = 0 zcomp_mask_r[blank_slate>0] = 0 zcomp_mask_g[blank_slate>0] = 255 zcomp_mask_b[blank_slate>0] = 0 # draw regions for region_instance in self.series.region_instances.filter(region_track_instance__t=t): # load mask mask = region_instance.masks.all()[0].load() # get mask outline mask_edge = edge_image(mask) # draw outlines in blue channel zbf_mask_r[mask_edge>0] = 0 zbf_mask_g[mask_edge>0] = 0 zbf_mask_b[mask_edge>0] = 255 zcomp_mask_r[mask_edge>0] = 0 zcomp_mask_g[mask_edge>0] = 0 zcomp_mask_b[mask_edge>0] = 255 # tile zbf, zbf_mask, zcomp, zcomp_mask top_half = np.concatenate((np.dstack([zbf, zbf, zbf]), np.dstack([zbf_mask_r, zbf_mask_g, zbf_mask_b])), axis=0) bottom_half = np.concatenate((np.dstack([zmean, zmean, zmean]), np.dstack([zcomp_mask_r, zcomp_mask_g, zcomp_mask_b])), axis=0) whole = np.concatenate((top_half, bottom_half), axis=1) imsave(join(tile_path, 'tile_{}_s{}_marker-{}_t{}.tiff'.format(self.experiment.name, self.series.name, channel_unique_override, str_value(t, self.series.ts))), whole)