def test_allocation(): arr = Array5D.allocate(Slice5D.zero(x=slice(100, 200), y=slice(200, 300)), numpy.uint8) assert arr.shape == Shape5D(x=100, y=100) assert arr.location == Point5D.zero(x=100, y=200) arr = Array5D.allocate(Slice5D.zero(x=slice(-100, 200), y=slice(200, 300)), numpy.uint8) assert arr.shape == Shape5D(x=300, y=100) assert arr.location == Point5D.zero(x=-100, y=200)
def to_z_slice_pngs(self) -> Iterator[io.BytesIO]: for z_slice in self.split(self.shape.updated(z=1)): print(f"\nz_slice: {z_slice}") rendered_rgb = Array5D.allocate(z_slice.shape.updated(c=3), dtype=np.dtype("float32"), value=0) rendered_rgb_yxc = rendered_rgb.raw("yxc") for prediction_channel, color in zip( z_slice.split(z_slice.shape.updated(c=1)), self.channel_colors): print(f"\nprediction_channel: {prediction_channel}") class_rgb = Array5D(np.ones( prediction_channel.shape.updated(c=3).to_tuple("yxc")), axiskeys="yxc") class_rgb.raw("yxc")[...] *= np.asarray( [color.r, color.g, color.b]) * (color.a / 255) class_rgb.raw("cyx")[...] *= prediction_channel.raw("yx") rendered_rgb_yxc += class_rgb.raw("yxc") out_image = PIL.Image.fromarray( rendered_rgb.raw("yxc").astype(np.uint8)) # type: ignore out_file = io.BytesIO() out_image.save(out_file, "png") out_file.seek(0) yield out_file
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)
def _do_predict(self, roi: DataRoi) -> Predictions: feature_data = self.feature_extractor.compute(roi) predictions = Array5D.allocate( interval=self.get_expected_roi(roi), dtype=np.dtype('float32'), value=0, ) assert predictions.interval == self.get_expected_roi(roi) raw_linear_predictions: np.ndarray = predictions.linear_raw() def do_predict(forest: VigraRandomForest): return forest.predictProbabilities( feature_data.linear_raw()) * forest.treeCount() with ThreadPoolExecutor(max_workers=len(self.forests), thread_name_prefix="predictor") as executor: for forest_predictions in executor.map(do_predict, self.forests): raw_linear_predictions += forest_predictions raw_linear_predictions /= self.num_trees predictions.setflags(write=False) return Predictions( arr=predictions.raw(predictions.axiskeys), axiskeys=predictions.axiskeys, location=predictions.location, channel_colors=Color.sort(self.color_map.keys()), )
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)
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 _allocate(self, roi: Union[Shape5D, Slice5D], fill_value: int) -> Array5D: return Array5D.allocate(roi, dtype=self.dtype, value=fill_value)
def _allocate(self, interval: Union[Shape5D, Interval5D], fill_value: int) -> Array5D: return Array5D.allocate(interval, dtype=self.dtype, value=fill_value)
def test_sequence_datasource(): # fmt: off img1_data = Array5D(np.asarray([[[100, 101, 102, 103, 104], [105, 106, 107, 108, 109], [110, 111, 112, 113, 114], [115, 116, 117, 118, 119]], [[120, 121, 122, 123, 124], [125, 126, 127, 128, 129], [130, 131, 132, 133, 134], [135, 136, 137, 138, 139]], [[140, 141, 142, 143, 144], [145, 146, 147, 148, 149], [150, 151, 152, 153, 154], [155, 156, 157, 158, 159]]]), axiskeys="cyx") img2_data = Array5D(np.asarray([[[200, 201, 202, 203, 204], [205, 206, 207, 208, 209], [210, 211, 212, 213, 214], [215, 216, 217, 218, 219]], [[220, 221, 222, 223, 224], [225, 226, 227, 228, 229], [230, 231, 232, 233, 234], [235, 236, 237, 238, 239]], [[240, 241, 242, 243, 244], [245, 246, 247, 248, 249], [250, 251, 252, 253, 254], [255, 256, 257, 258, 259]]]), axiskeys="cyx") img3_data = Array5D(np.asarray([[[300, 301, 302, 303, 304], [305, 306, 307, 308, 309], [310, 311, 312, 313, 314], [315, 316, 317, 318, 319]], [[320, 321, 322, 323, 324], [325, 326, 327, 328, 329], [330, 331, 332, 333, 334], [335, 336, 337, 338, 339]], [[340, 341, 342, 343, 344], [345, 346, 347, 348, 349], [350, 351, 352, 353, 354], [355, 356, 357, 358, 359]]]), axiskeys="cyx") expected_x_2_4__y_1_3 = Array5D(np.asarray([ [[[107, 108], [112, 113]], [[127, 128], [132, 133]], [[147, 148], [152, 153]]], [[[207, 208], [212, 213]], [[227, 228], [232, 233]], [[247, 248], [252, 253]]], [[[307, 308], [312, 313]], [[327, 328], [332, 333]], [[347, 348], [352, 353]]], ]), axiskeys="zcyx") # fmt: on slice_x_2_4__y_1_3 = Slice5D(x=slice(2, 4), y=slice(1, 3)) urls = [ # create_n5(img1_data, axiskeys="cyx"), create_h5(img1_data, axiskeys_style="dims", axiskeys="cyx"), # create_n5(img2_data, axiskeys="cyx"), create_h5(img2_data, axiskeys_style="dims", axiskeys="cyx"), # create_n5(img3_data, axiskeys="cyx"), create_h5(img3_data, axiskeys_style="dims", axiskeys="cyx"), ] seq_ds = SequenceDataSource(urls, stack_axis="z") assert seq_ds.shape == Shape5D(x=5, y=4, c=3, z=3) data = seq_ds.retrieve(slice_x_2_4__y_1_3) assert (expected_x_2_4__y_1_3.raw("xyzc") == data.raw("xyzc")).all() seq_ds = SequenceDataSource(urls, stack_axis="z") data = seq_ds.retrieve(slice_x_2_4__y_1_3) assert (expected_x_2_4__y_1_3.raw("xyzc") == data.raw("xyzc")).all() seq_ds = SequenceDataSource(urls, stack_axis="c") expected_c = sum([img1_data.shape.c, img2_data.shape.c, img3_data.shape.c]) assert seq_ds.shape == img1_data.shape.with_coord(c=expected_c) cstack_data = Array5D.allocate(Shape5D(x=5, y=4, c=expected_c), dtype=img1_data.dtype) cstack_data.set(img1_data.translated(Point5D.zero(c=0))) cstack_data.set(img2_data.translated(Point5D.zero(c=3))) cstack_data.set(img3_data.translated(Point5D.zero(c=6))) assert seq_ds.shape == cstack_data.shape expected_data = cstack_data.cut(slice_x_2_4__y_1_3) data = seq_ds.retrieve(slice_x_2_4__y_1_3) assert (expected_data.raw("cxy") == data.raw("cxy")).all()
def enlarged(self, radius: Point5D, limits: Interval5D) -> "ConnectedComponents": """Enlarges the array by 'radius', and fills this halo with zero""" haloed_roi = self.interval.enlarged(radius).clamped(limits) haloed_data = Array5D.allocate(haloed_roi, value=0, dtype=self.dtype) haloed_data.set(self) return ConnectedComponents.from_array5d(haloed_data, labels=self.labels)