Skip to content

Commit

Permalink
Move downsample_area into public connectomics repository.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 693823309
  • Loading branch information
timblakely authored and copybara-github committed Nov 6, 2024
1 parent 8969e8a commit f989bcc
Showing 1 changed file with 54 additions and 0 deletions.
54 changes: 54 additions & 0 deletions connectomics/common/geom_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import numbers
from typing import Optional, Sequence

from connectomics.common import bounding_box
import numpy as np


Expand Down Expand Up @@ -100,3 +102,55 @@ def point_query_integral_image(summed_volume_table: np.ndarray,
else:
raise NotImplementedError(
'Only 2 and 3-dimensional integral images are supported.')


def downsample_area(
svt: np.ndarray,
box: bounding_box.BoundingBox,
scale: np.ndarray,
dtype: np.dtype,
mask_svt: Optional[np.ndarray] = None,
) -> tuple[bounding_box.BoundingBoxBase, np.ndarray]:
"""Downsamples data by area-averaging.
Args:
svt: [z, y, x] summed-volume table for the data to downsample
box: bounding box from which the source data was originates
scale: xyz downsampling factors
dtype: data type for the output array
mask_svt: [z, y, x] summed-volume table for the mask
Returns:
bounding box for the downsampled subvolume, downsampled subvolume as a
[1, z', y', x']-shaped array
"""
# The offset needs to be such that the first input voxel to the svt is
# evenly divisible by scale.
off = box.start - box.start // scale * scale
off[off > 0] = (scale - off)[off > 0]

scale_zyx = scale[::-1]
scale_vol = np.prod(scale)

# The value computed in ret below corresponds to an output cropped by
# scale - 1 on each side prior to striding, but we need the output to
# be cropped by the context expected by the processor.
ret = query_integral_image(
svt[off[2] :, off[1] :, off[0] :], diam=scale_zyx, stride=scale_zyx
)
if mask_svt is None:
ret = ret / scale_vol
else:
missing = query_integral_image(
mask_svt[off[2] :, off[1] :, off[0] :], diam=scale_zyx, stride=scale_zyx
)
norm = np.clip(scale_vol - missing, 1, None)
ret = ret / norm
ret[missing == scale_vol] = np.nan

ret = np.round(ret).astype(dtype)
out_box = bounding_box.BoundingBox(
start=(box.start + off) // scale, size=ret.shape[::-1]
)
ret = ret[np.newaxis, ...]
return out_box, ret

0 comments on commit f989bcc

Please sign in to comment.