Пример #1
0
 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)
Пример #2
0
 def __setstate__(self, data: JsonValue):
     data_obj = ensureJsonObject(data)
     self.__init__(
         path=Path(ensureJsonString(data_obj.get("path"))),
         location=Interval5D.from_json_value(data_obj.get("interval")).start,
         filesystem=JsonableFilesystem.from_json_value(data_obj.get("filesystem"))
     )
Пример #3
0
    def from_json_value(cls, data: JsonValue) -> "Annotation":
        data_dict = ensureJsonObject(data)
        raw_voxels = ensureJsonArray(data_dict.get("voxels"))
        voxels: Sequence[Point5D] = [
            Point5D.from_json_value(raw_voxel) for raw_voxel in raw_voxels
        ]

        color = Color.from_json_data(data_dict.get("color"))
        raw_data = DataSource.from_json_value(data_dict.get("raw_data"))

        start = Point5D.min_coords(voxels)
        stop = Point5D.max_coords(
            voxels
        ) + 1  # +1 because slice.stop is exclusive, but max_point isinclusive
        scribbling_roi = Interval5D.create_from_start_stop(start=start,
                                                           stop=stop)
        if scribbling_roi.shape.c != 1:
            raise ValueError(
                f"Annotations must not span multiple channels: {voxels}")
        scribblings = Array5D.allocate(scribbling_roi,
                                       dtype=np.dtype(bool),
                                       value=False)

        for voxel in voxels:
            scribblings.paint_point(point=voxel, value=True)

        return cls(scribblings._data,
                   axiskeys=scribblings.axiskeys,
                   color=color,
                   raw_data=raw_data,
                   location=start)
Пример #4
0
    def interpolate_from_points(cls, color: Color, voxels: Sequence[Point5D],
                                raw_data: DataSource):
        start = Point5D.min_coords(voxels)
        stop = Point5D.max_coords(
            voxels
        ) + 1  # +1 because slice.stop is exclusive, but max_point isinclusive
        scribbling_roi = Interval5D.create_from_start_stop(start=start,
                                                           stop=stop)
        if scribbling_roi.shape.c != 1:
            raise ValueError(
                f"Annotations must not span multiple channels: {voxels}")
        scribblings = Array5D.allocate(scribbling_roi,
                                       dtype=np.dtype(bool),
                                       value=False)

        anchor = voxels[0]
        for voxel in voxels:
            for interp_voxel in anchor.interpolate_until(voxel):
                scribblings.paint_point(point=interp_voxel, value=True)
            anchor = voxel

        return cls(scribblings._data,
                   axiskeys=scribblings.axiskeys,
                   color=color,
                   raw_data=raw_data,
                   location=start)
Пример #5
0
 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
Пример #6
0
 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()
Пример #7
0
 def _get_tile(self, tile: Interval5D) -> Array5D:
     if self.location != self.scale.voxel_offset:
         tile = tile.translated(-self.location).translated(
             self.scale.location)
     tile_path = self.path / self.scale.get_tile_path(tile)
     with self.filesystem.openbin(tile_path.as_posix()) as f:
         raw_tile_bytes = f.read()
     tile_5d = self.scale.encoding.decode(
         roi=tile, dtype=self.dtype,
         raw_chunk=raw_tile_bytes)  #type: ignore
     return tile_5d
Пример #8
0
 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
Пример #9
0
 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)
Пример #10
0
def test_skimage_datasource_tiles(png_image: Path):
    bs = DataRoi(SkimageDataSource(png_image, filesystem=OsFs("/")))
    num_checked_tiles = 0
    for tile in bs.split(Shape5D(x=2, y=2)):
        if tile == Interval5D.zero(x=(0, 2), y=(0, 2)):
            expected_raw = raw_0_2x0_2y
        elif tile == Interval5D.zero(x=(0, 2), y=(2, 4)):
            expected_raw = raw_0_2x2_4y
        elif tile == Interval5D.zero(x=(2, 4), y=(0, 2)):
            expected_raw = raw_2_4x0_2y
        elif tile == Interval5D.zero(x=(2, 4), y=(2, 4)):
            expected_raw = raw_2_4x2_4y
        elif tile == Interval5D.zero(x=(4, 5), y=(0, 2)):
            expected_raw = raw_4_5x0_2y
        elif tile == Interval5D.zero(x=(4, 5), y=(2, 4)):
            expected_raw = raw_4_5x2_4y
        else:
            raise Exception(f"Unexpected tile {tile}")
        assert (tile.retrieve().raw("yx") == expected_raw).all()
        num_checked_tiles += 1
    assert num_checked_tiles == 6
Пример #11
0
 def get_expected_roi(self, data_slice: Interval5D) -> Interval5D:
     c_start = data_slice.c[0]
     c_stop = c_start + self.num_classes
     return data_slice.updated(c=(c_start, c_stop))
Пример #12
0
 def _get_tile(self, tile: Interval5D) -> Array5D:
     slices = tile.translated(-self.location).to_slices(self.axiskeys)
     raw: np.ndarray = self._dataset[slices]
     return Array5D(raw, axiskeys=self.axiskeys, location=tile.start)
Пример #13
0
 def interval(self) -> Interval5D:
     return Interval5D(t=self.t, c=self.c, x=self.x, y=self.y, z=self.z)
Пример #14
0
 def is_tile(self, tile: Interval5D) -> bool:
     return tile.is_tile(tile_shape=self.tile_shape,
                         full_interval=self.interval,
                         clamped=True)