def _resample_relative( self, inside: np.ndarray, outside: np.ndarray, bb: Roi ) -> Optional[np.ndarray]: offset = outside - inside with np.errstate(divide="ignore", invalid="ignore"): # bb_crossings will be 0 if inside is on the bb, 1 if outside is on the bb bb_x = np.asarray( [ (np.asarray(bb.get_begin()) - inside) / offset, (np.asarray(bb.get_end() - Coordinate([1, 1, 1])) - inside) / offset, ] ) if np.sum(np.logical_and((bb_x > 0), (bb_x <= 1))) > 0: # all values of bb_x between 0, 1 represent a crossing of a bounding plane # the minimum of which is the (normalized) distance to the closest bounding plane s = np.min(bb_x[np.logical_and((bb_x > 0), (bb_x <= 1))]) return Coordinate(np.floor(np.array(inside) + s * offset)) else: logging.debug( ( "Could not create a node on the bounding box {} " + "given points (inside:{}, ouside:{})" ).format(bb, inside, outside) ) return None
def process(self, batch, request): points = batch.points[self.points] mask = self.settings.mask voxel_size = self.spec[self.array].voxel_size # get roi used for creating the new array (points_roi does no # necessarily align with voxel size) enlarged_vol_roi = points.spec.roi.snap_to_grid(voxel_size) offset = enlarged_vol_roi.get_begin() / voxel_size shape = enlarged_vol_roi.get_shape() / voxel_size data_roi = Roi(offset, shape) logger.debug("Points in %s", points.spec.roi) for i, point in points.data.items(): logger.debug("%d, %s", i, point.location) logger.debug("Data roi in voxels: %s", data_roi) logger.debug("Data roi in world units: %s", data_roi*voxel_size) if len(points.data.items()) == 0: # If there are no points at all, just create an empty matrix. rasterized_points_data = np.zeros(data_roi.get_shape(), dtype=self.spec[self.array].dtype) elif mask is not None: mask_array = batch.arrays[mask].crop(enlarged_vol_roi) # get those component labels in the mask, that contain points labels = [] for i, point in points.data.items(): v = Coordinate(point.location / voxel_size) v -= data_roi.get_begin() labels.append(mask_array.data[v]) # Make list unique labels = list(set(labels)) # zero label should be ignored if 0 in labels: labels.remove(0) if len(labels) == 0: logger.debug("Points and provided object mask do not overlap. No points to rasterize.") rasterized_points_data = np.zeros(data_roi.get_shape(), dtype=self.spec[self.array].dtype) else: # create data for the whole points ROI, "or"ed together over # individual object masks rasterized_points_data = np.sum( [ self.__rasterize( points, data_roi, voxel_size, self.spec[self.array].dtype, self.settings, Array(data=mask_array.data==label, spec=mask_array.spec)) for label in labels ], axis=0) else: # create data for the whole points ROI without mask rasterized_points_data = self.__rasterize( points, data_roi, voxel_size, self.spec[self.array].dtype, self.settings) # fix bg/fg labelling if requested if (self.settings.bg_value != 0 or self.settings.fg_value != 1): replaced = replace( rasterized_points_data, [0, 1], [self.settings.bg_value, self.settings.fg_value]) rasterized_points_data = replaced.astype(self.spec[self.array].dtype) # create array and crop it to requested roi spec = self.spec[self.array].copy() spec.roi = data_roi*voxel_size rasterized_points = Array( data=rasterized_points_data, spec=spec) batch.arrays[self.array] = rasterized_points.crop(request[self.array].roi) # restore requested ROI of points if self.points in request: request_roi = request[self.points].roi points.spec.roi = request_roi points.data = {i: p for i, p in points.data.items() if request_roi.contains(p.location)} # restore requested mask if mask is not None: batch.arrays[mask] = batch.arrays[mask].crop(request[mask].roi)