low pri features
This commit is contained in:
86
tests/node_tests/tip_shape_estimate.py
Normal file
86
tests/node_tests/tip_shape_estimate.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from tests.node_tests._shared import make_field
|
||||
|
||||
|
||||
def run_tip_shape(field, feature_type="edge", feature_radius=100e-9, n_points=100):
|
||||
from backend.nodes.tip_shape_estimate import TipShapeEstimate
|
||||
node = TipShapeEstimate()
|
||||
tip_shape, parameters = node.process(
|
||||
field=field,
|
||||
feature_type=feature_type,
|
||||
feature_radius=feature_radius,
|
||||
n_points=n_points,
|
||||
)
|
||||
return tip_shape, parameters
|
||||
|
||||
|
||||
# ── Output shape and type ────────────────────────────────────────────────────
|
||||
|
||||
def test_output_shape():
|
||||
"""tip_shape must be a 2D DataField."""
|
||||
from backend.data_types import DataField
|
||||
field = make_field(shape=(64, 64), xreal=64e-9, yreal=64e-9)
|
||||
tip_shape, _ = run_tip_shape(field, feature_type="edge", n_points=33)
|
||||
assert isinstance(tip_shape, DataField)
|
||||
assert tip_shape.data.ndim == 2
|
||||
assert tip_shape.data.shape[0] == tip_shape.data.shape[1]
|
||||
|
||||
|
||||
# ── Parameters table ─────────────────────────────────────────────────────────
|
||||
|
||||
def test_parameters_table():
|
||||
"""parameters must be a RecordTable containing a tip_radius entry."""
|
||||
from backend.data_types import RecordTable
|
||||
field = make_field(shape=(64, 64), xreal=64e-9, yreal=64e-9)
|
||||
_, parameters = run_tip_shape(field, feature_type="edge", n_points=33)
|
||||
assert isinstance(parameters, RecordTable)
|
||||
quantities = {row["quantity"] for row in parameters}
|
||||
assert "tip_radius" in quantities
|
||||
|
||||
|
||||
# ── Tip apex is maximum ──────────────────────────────────────────────────────
|
||||
|
||||
def test_tip_apex_is_maximum():
|
||||
"""The centre of the tip shape should be the highest point."""
|
||||
field = make_field(shape=(64, 64), xreal=64e-9, yreal=64e-9)
|
||||
tip_shape, _ = run_tip_shape(field, feature_type="edge", n_points=33)
|
||||
n = tip_shape.data.shape[0]
|
||||
ci = n // 2
|
||||
assert tip_shape.data[ci, ci] == pytest.approx(tip_shape.data.max(), abs=1e-20)
|
||||
|
||||
|
||||
# ── Sphere feature produces valid estimate ───────────────────────────────────
|
||||
|
||||
def test_sphere_feature():
|
||||
"""Using a synthetic sphere as input produces a valid tip estimate."""
|
||||
from backend.data_types import DataField
|
||||
|
||||
# Create a synthetic sphere on a 64x64 grid.
|
||||
R = 100e-9 # sphere radius
|
||||
n = 64
|
||||
pixel_size = 10e-9
|
||||
xreal = n * pixel_size
|
||||
Y, X = np.mgrid[:n, :n]
|
||||
r = np.sqrt((X - 32) ** 2 + (Y - 32) ** 2) * pixel_size
|
||||
data = np.sqrt(np.maximum(R ** 2 - r ** 2, 0.0))
|
||||
|
||||
field = make_field(data=data, xreal=xreal, yreal=xreal)
|
||||
|
||||
tip_shape, parameters = run_tip_shape(
|
||||
field, feature_type="sphere", feature_radius=R, n_points=33,
|
||||
)
|
||||
|
||||
# The output must be a valid 2D DataField.
|
||||
assert isinstance(tip_shape, DataField)
|
||||
assert tip_shape.data.ndim == 2
|
||||
|
||||
# Apex should be the maximum.
|
||||
ci = tip_shape.data.shape[0] // 2
|
||||
assert tip_shape.data[ci, ci] == pytest.approx(tip_shape.data.max(), abs=1e-20)
|
||||
|
||||
# Parameters should contain tip_radius.
|
||||
quantities = {row["quantity"]: row["value"] for row in parameters}
|
||||
assert "tip_radius" in quantities
|
||||
# The estimated radius must be a positive finite number.
|
||||
assert quantities["tip_radius"] > 0
|
||||
Reference in New Issue
Block a user