def __init__( self, *, stack_axis: str, datasources: Iterable[DataSource], ): self.stack_axis = stack_axis self.datasources = sorted(datasources, key=lambda ds: ds.location[stack_axis]) tile_shapes = {ds.tile_shape for ds in self.datasources} if len(tile_shapes) != 1: raise ValueError( f"All datasources must have the same tile shape. Tile shapes: {tile_shapes}" ) tile_shape = tile_shapes.pop() if any(ds.shape[stack_axis] % tile_shape[stack_axis] != 0 for ds in self.datasources): raise ValueError( f"Stacking over axis that are not multiple of the tile size is not supported" ) self.stack_levels = [ ds.location[stack_axis] for ds in self.datasources ] interval = Interval5D.enclosing(ds.interval for ds in self.datasources) super().__init__(dtype=self.datasources[0].dtype, interval=interval, axiskeys=stack_axis + Point5D.LABELS.replace(stack_axis, ""), tile_shape=tile_shape)
def label_at(self, point: Point5D) -> int: point_roi = Interval5D.enclosing([point]) if not self.interval.contains(point_roi): raise ValueError(f"Point {point} is not inside the labels at {self.interval}") label = self.cut(point_roi).raw("x")[0] if label == 0: raise ValueError(f"Point {point} is not on top of an object") return label
def show(self): data = self.data_tile.retrieve().cut(copy=True) for axis in "xyz": increment = Point5D.zero(**{axis: 1}) for pos in (self.position + increment, self.position - increment): if data.interval.contains(Interval5D.enclosing([pos])): data.paint_point(pos, 0) data.paint_point(self.position, 255) data.show_images()
def merge(annotations: Sequence["Annotation"], color_map: Optional[Dict[Color, np.uint8]] = None) -> Array5D: out_roi = Interval5D.enclosing(annot.interval for annot in annotations) out = Array5D.allocate(interval=out_roi, value=0, dtype=np.dtype('uint8')) color_map = color_map or Color.create_color_map( annot.color for annot in annotations) for annot in annotations: out.set(annot.colored(color_map[annot.color]), mask_value=0) return out
def __init__( self, *, position: Point5D, # an anchor point within datasource klass: int, datasource: DataSource, # an object label is tied to the datasource components_extractor: ConnectedComponentsExtractor, # and also to the method used to extract the objects ): position_roi = DataRoi(datasource, **Interval5D.enclosing([position]).to_dict()) self.data_tile = position_roi.get_tiles( datasource.tile_shape, clamp=False).__next__().clamped(datasource.shape) self.position = position self.klass = klass self.datasource = datasource self.components_extractor = components_extractor # compute connected components in constructor to prevent creation of bad annotation self.label = components_extractor.compute( self.data_tile).label_at(position)