Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions cellfinder/core/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

def main(
signal_array: types.array,
background_array: types.array,
voxel_sizes: Tuple[float, float, float],
background_array: types.array | Tuple[float, float, float] | None = None,
voxel_sizes: Tuple[float, float, float] | None = None,
start_plane: int = 0,
end_plane: int = -1,
trained_model: Optional[os.PathLike] = None,
Expand Down Expand Up @@ -55,8 +55,10 @@ def main(
----------
signal_array : numpy.ndarray or dask array
3D array representing the signal data in z, y, x order.
background_array : numpy.ndarray or dask array
3D array representing the signal data in z, y, x order.
background_array : numpy.ndarray or dask array, optional
3D array representing the background data in z, y, x order. This is
required when classification is enabled and optional when
``skip_classification=True``.
voxel_sizes : 3-tuple of floats
Size of your voxels in the z, y, and x dimensions (microns).
start_plane : int
Expand Down Expand Up @@ -188,6 +190,21 @@ def main(
from cellfinder.core.detect import detect
from cellfinder.core.tools import prep

# Preserve the historical positional API while allowing callers to omit
# background data for detection-only runs.
if voxel_sizes is None:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a clean way to retain the API, because while the positional API is maintained, you could pass the voxel sizes via the background array keyword argument, and these are very different things!

voxel_sizes = background_array
background_array = None

if voxel_sizes is None:
raise TypeError("voxel_sizes must be provided")

if not skip_classification and background_array is None:
raise ValueError(
"background_array must be provided unless "
"skip_classification=True"
)

if not skip_detection:
logger.info("Detecting cell candidates")

Expand Down
29 changes: 29 additions & 0 deletions tests/core/test_integration/test_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,35 @@ def test_synthetic_data(synthetic_bright_spots, no_free_cpus):
assert len(detected) == 8


def test_skip_classification_without_background_array(
synthetic_single_spot, no_free_cpus
):
signal_array, _, center = synthetic_single_spot
detected = main(
signal_array=signal_array.astype(np.float32),
voxel_sizes=voxel_sizes,
n_sds_above_mean_thresh=1.0,
n_free_cpus=no_free_cpus,
skip_classification=True,
)

assert len(detected) == 1
assert detected[0] == Cell(center, Cell.UNKNOWN)


def test_background_array_required_for_classification():
signal_array = np.zeros((5, 5, 5), dtype=np.float32)

with pytest.raises(
ValueError,
match=(
"background_array must be provided unless "
"skip_classification=True"
),
):
main(signal_array=signal_array, voxel_sizes=voxel_sizes)


@pytest.mark.parametrize("ndim", [1, 2, 4])
def test_data_dimension_error(ndim):
# Check for an error when non-3D data input
Expand Down