def PruneCandidates(segmentation_one, segmentation_two, candidates, centers, radii, overlap): assert (segmentation_one.shape == segmentation_two.shape) zres, yres, xres = segmentation_one.shape # get the global grid box global_box = ib3shapes.IBBox((0, 0, 0), (zres, yres, xres)) indices = [] # iterate over every candidate for iv, candidate in enumerate(candidates): # create a local bounding box for this feature cz, cy, cx = centers[iv] mins = (cz - radii[IB_Z], cy - radii[IB_Y], cx - radii[IB_X]) maxs = (cz + radii[IB_Z], cy + radii[IB_Y], cx + radii[IB_X]) # first check if the local box is contained if 0 < mins[IB_X] and 0 < mins[IB_Y] and 0 < mins[IB_Z] and maxs[IB_X] < xres and maxs[IB_Y] < yres and maxs[IB_Z] < zres: indices.append(iv) # also allow otherwise valid candidates elif SearchCandidate(segmentation_one, segmentation_two, candidate, overlap, mins, maxs): indices.append(iv) # return which indices are valid return indices
def __init__(self, prefix): # initialize the prefix variable self.prefix = prefix # backwards compatability variable defaults self.affinity_filename = None self.boundary_filename = None self.gold_filename = None self.image_filename = None self.mask_filename = None self.rhoana_filename = None self.synapse = None self.crop_xmin = None self.crop_xmax = None self.crop_ymin = None self.crop_ymax = None self.crop_zmin = None self.crop_zmax = None # open the meta data txt file filename = 'meta/{}.meta'.format(prefix) with open(filename, 'r') as fd: lines = fd.readlines() for ix in range(0, len(lines), 2): # get the comment and the corresponding value comment = lines[ix].strip() value = lines[ix + 1].strip() if comment == '# resolution in nm': # separate into individual dimensions samples = value.split('x') # need to use 2, 1, and 0 here since the outward facing convention is x,y,z, not z, y, x self.resolution = (float(samples[2]), float(samples[1]), float(samples[0])) elif comment == '# affinity filename': self.affinity_filename = value elif comment == '# boundary filename': self.boundary_filename = value elif comment == '# gold filename': self.gold_filename = value elif comment == '# image filename': self.image_filename = value elif comment == '# mask filename': self.mask_filename = value elif comment == '# rhoana filename': self.rhoana_filename = value elif comment == '# synapse filename': self.synapse_filename = value elif comment == '# world bounding box': if value == 'None': self.bounding_box = ib3shapes.IBBox((0, 0, 0), (-1, -1, -1)) continue # separate into minimums and maximums minmax = value.split('-') mins = (minmax[0].strip('()')).split(',') maxs = (minmax[1].strip('()')).split(',') # split into individual mins for iv in range(NDIMS): mins[iv] = int(mins[iv]) maxs[iv] = int(maxs[iv]) # swap x and z tmp = mins[0] mins[0] = mins[2] mins[2] = tmp tmp = maxs[0] maxs[0] = maxs[2] maxs[2] = tmp # save the bounding box self.bounding_box = ib3shapes.IBBox(mins, maxs) elif comment == '# grid size': samples = value.split('x') self.grid_size = (int(samples[2]), int(samples[1]), int(samples[0])) elif comment == '# train/val/test crop': samples = value.split('x') self.crop_xmin = int(samples[0].split(':')[0]) self.crop_xmax = int(samples[0].split(':')[1]) self.crop_ymin = int(samples[1].split(':')[0]) self.crop_ymax = int(samples[1].split(':')[1]) self.crop_zmin = int(samples[2].split(':')[0]) self.crop_zmax = int(samples[2].split(':')[1]) else: sys.stderr.write( 'Unrecognized attribute in {}: {}\n'.format( prefix, comment)) sys.exit()
def GenerateFeatures(prefix_one, prefix_two, threshold, maximum_distance): # read in all relevant information segmentation_one = dataIO.ReadSegmentationData(prefix_one) segmentation_two = dataIO.ReadSegmentationData(prefix_two) assert (segmentation_one.shape == segmentation_two.shape) bbox_one = dataIO.GetWorldBBox(prefix_one) bbox_two = dataIO.GetWorldBBox(prefix_two) world_res = dataIO.Resolution(prefix_one) assert (world_res == dataIO.Resolution(prefix_two)) # get the radii for the relevant region radii = (int(maximum_distance / world_res[IB_Z] + 0.5), int(maximum_distance / world_res[IB_Y] + 0.5), int(maximum_distance / world_res[IB_X] + 0.5)) # parse out small segments segmentation_one = seg2seg.RemoveSmallConnectedComponents(segmentation_one, min_size=threshold) segmentation_two = seg2seg.RemoveSmallConnectedComponents(segmentation_two, min_size=threshold) # get the bounding box for the intersection world_box = ib3shapes.IBBox(bbox_one.mins, bbox_one.maxs) world_box.Intersection(bbox_two) # get the mins and maxs of truncated box mins_one = WorldToGrid(world_box.mins, bbox_one) mins_two = WorldToGrid(world_box.mins, bbox_two) maxs_one = WorldToGrid(world_box.maxs, bbox_one) maxs_two = WorldToGrid(world_box.maxs, bbox_two) # get the relevant subsections segmentation_one = segmentation_one[mins_one[IB_Z]:maxs_one[IB_Z], mins_one[IB_Y]:maxs_one[IB_Y], mins_one[IB_X]:maxs_one[IB_X]] segmentation_two = segmentation_two[mins_two[IB_Z]:maxs_two[IB_Z], mins_two[IB_Y]:maxs_two[IB_Y], mins_two[IB_X]:maxs_two[IB_X]] # create an emptu set and add dumby variable for numba candidates_set = set() # this set represents tuples of labels from GRID_ONE and GRID_TWO candidates_set.add((np.uint64(0), np.uint64(0))) FindOverlapCandidates(segmentation_one, segmentation_two, candidates_set) # get the reverse mappings forward_mapping_one, reverse_mapping_one = seg2seg.ReduceLabels(segmentation_one) forward_mapping_two, reverse_mapping_two = seg2seg.ReduceLabels(segmentation_two) # get the number of unique labels nlabels_one = reverse_mapping_one.size nlabels_two = reverse_mapping_two.size # calculate the center of overlap regions sums = np.zeros((nlabels_one, nlabels_two, 3), dtype=np.uint64) counter = np.zeros((nlabels_one, nlabels_two), dtype=np.uint64) FindCenters(segmentation_one, segmentation_two, forward_mapping_one, forward_mapping_two, sums, counter) # get the number of occurrences of all labels _, counts_one = np.unique(segmentation_one, return_counts=True) _, counts_two = np.unique(segmentation_two, return_counts=True) # iterate through candidate and locate centers candidates = [] centers = [] counts = [] for candidate in candidates_set: # skip extracellular space if not candidate[0] or not candidate[1]: continue # get forward mapping index_one = forward_mapping_one[candidate[0]] index_two = forward_mapping_two[candidate[1]] count = counter[index_one][index_two] center = (int(sums[index_one, index_two, IB_Z] / count + 0.5), int(sums[index_one, index_two, IB_Y] / count + 0.5), int(sums[index_one, index_two, IB_X] / count + 0.5)) # append to the lists candidates.append(candidate) centers.append(center) counts.append((counts_one[index_one], counts_two[index_two], count)) # find which dimension causes overlap if not bbox_one.mins[IB_X] == bbox_two.mins[IB_X]: overlap = IB_X if not bbox_one.mins[IB_Y] == bbox_two.mins[IB_Y]: overlap = IB_Y if not bbox_one.mins[IB_Z] == bbox_two.mins[IB_Z]: overlap = IB_Z # prune the candidates indices = PruneCandidates(segmentation_one, segmentation_two, candidates, centers, radii, overlap) pruned_candidates = [] pruned_centers = [] pruned_counts = [] for index in indices: # add the candidates pruned_candidates.append(candidates[index]) pruned_counts.append(counts[index]) center = (centers[index][IB_Z] + world_box.mins[IB_Z], centers[index][IB_Y] + world_box.mins[IB_Y], centers[index][IB_X] + world_box.mins[IB_X]) pruned_centers.append(center) # save all features SaveFeatures(prefix_one, prefix_two, pruned_candidates, pruned_centers, pruned_counts, threshold, maximum_distance)