Cropped tissues¶
Cropped tissues: what a crop face is, and what inference does with it.
The problem¶
A tissue imaged in part, or cropped from a larger image, has cells that the image boundary cuts.
The mesh closes them with triangles lying on the boundary: crop faces, labelled (0, c) like
contact with the medium, although nothing beyond them was observed. Read as medium contact, they
make three kinds of error:
- a tension unknown for an interface that does not exist (the crop), and a fake junction line
(0, a, b)wherever the crop meets a cell-cell interface(a, b), with angles set by the crop plane rather than by the tissue; - force balances written at vertices on the crop, where the tissue that was cut away pulled;
- a pressure for every cut cell, from a volume that is partly the crop.
Measured on 433 plane crops of the 47 benchmark tissues (YoungDupre, median over the 42
equilibrium cases of the relative error of the gauge-matched tensions of the interfaces that touch
the crop): 13 %, 33 % and 40 % error with 10 %, 25 % and 40 % of the tissue cropped away when crop
faces are read as medium contact, against 10 %, 9 % and 12 % when they are kept out; every one of
the 13 tension methods improves at 25 % and 40 %, and LogLami stops failing on 25 of the crops.
The interfaces away from the crop are affected too: at 40 % their error was 17 points above the
uncropped tissue's, and 2 points above it with the crop kept out.
What inference does with a crop face¶
A mesh carries its crop as a mask of faces (DcelData(..., crop_faces=...)), never as a reserved
label. Then, in every tension method:
- a crop face carries no tension unknown and enters no equation; an interface made only of crop
faces (
DcelData.crop_interfaces) is absent from the tension map, never a number; - a junction edge with a vertex on a crop face gives no equation; the rest of a junction line
that ends on the crop still does (the angle-reading methods exclude such edges from the line
mean, as
foambryo.wedge_refusal.WedgeRefusalPolicy.ExcludeEdgeFromLineMeandoes for a folded edge, and both reasons combine); - a vertex on a crop face gives no force balance (the
VariationalandForceBalance*methods drop its three rows;Equilibriumdrops the edges that touch it); - an interface left with no equation is
nan, as an interface with no junction line already is.
And in the pressure methods, a cut cell (DcelData.cut_cells: a cell with a crop face or a
vertex on one) keeps its pressure as an unknown, so that its force is not pushed into anyone
else's, but the pressure is not reported: it comes back nan, with a CutCellPressureWarning
naming the cells. On the benchmark crops the cut cells' pressures read as measurements had 15 % to
46 % error; withholding them leaves the other cells' pressures as accurate as without the crop.
What has no formulation for crop faces yet refuses a cropped mesh with a ValueError, rather
than read the crop as medium: the two Laplace pressure methods (PressureComputationMethod.Laplace
and WeightedLaplace; PressureComputationMethod.has_crop_face_formulation says which methods
accept a cropped mesh), foambryo.compute_inference_diagnostics and
foambryo.infer_tensions_with_uncertainty. infer_force_balance follows the rules above.
On a mesh without crop faces none of this runs.
Where crop faces come from¶
delaunay-watershed-3d (dw3d) marks them during the reconstruction: the triangles a cell has on a
face of the image box that the cell reaches in the mask, unless that face is declared physical (a
coverslip); a mask none of whose cells reaches the image box has none. They reach foambryo
through dcel_mesh_from_segmentation_mask, or through a .rec file whose metadata appendix
records crop_faces = <first row> <count> (dw3d writes them as the last rows), or a .vtk file
with a crop_face cell array. A file written before crop faces were recorded carries no such
record; when its mesh has faces that look like a crop, dcel_mesh_from_file warns
(UnrecordedCropFacesWarning) instead of silently reading them as medium contact.
CutCellPressureWarning ¶
Bases: UserWarning
Emitted when a pressure inference withholds the pressures of cut cells, reported as nan.
A cut cell has a crop face, or a vertex on one: part of its surface and volume lie outside the
imaged volume. Its pressure is solved for, so that its force does not end up in the other
cells' pressures, but it is not a measurement and is reported as nan. The other cells'
pressures are unaffected.
UnrecordedCropFacesWarning ¶
Bases: UserWarning
Emitted when a mesh read from a file looks cropped but the file records no crop faces.
Such a mesh has triangles (0, c) lying flat on a face of its own bounding box, like the faces
a reconstruction places where the image boundary cuts a cell. Without a record of which they are, they
are read as contact with the medium, which puts large errors on the tensions near them and on
the pressures of the cells they close. Re-export the mesh with a current
delaunay-watershed-3d, or pass the crop faces explicitly (DcelData(..., crop_faces=...)).
crop_edges ¶
crop_edges(mesh: DcelData) -> frozenset[GeometricEdge]
Every mesh edge with a vertex on a crop face, as (min, max) vertex-key pairs.
A superset of the junction edges that touch the crop: the estimators match it against their own junction edges only, so the other edges it holds are never consulted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mesh
|
DcelData
|
the mesh. |
required |
Returns:
| Type | Description |
|---|---|
frozenset[GeometricEdge]
|
frozenset[GeometricEdge]: empty when the mesh has no crop face. |
vertex_rows_off_the_crop ¶
vertex_rows_off_the_crop(mesh: DcelData, excluded: NDArray[integer] | None = None) -> NDArray[np.intp]
Row indices 3v, 3v + 1, 3v + 2 of every vertex on no crop face and not in excluded.
The rows a vertex-wise force balance keeps on a cropped mesh: a vertex on a crop face is held by the tissue that was cut away, so its balance is not an observation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mesh
|
DcelData
|
the mesh. |
required |
excluded
|
NDArray | None
|
further vertex keys to leave out. |
None
|
Returns:
| Type | Description |
|---|---|
NDArray[intp]
|
NDArray[np.intp]: ascending row indices into a |
warn_on_cut_cell_pressures ¶
warn_on_cut_cell_pressures(cells: tuple[int, ...], stacklevel: int = 4) -> None
Emit CutCellPressureWarning naming the cut cells whose pressure is reported as nan.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cells
|
tuple[int, ...]
|
labels of the cut cells (nothing is emitted if empty). |
required |
stacklevel
|
int
|
passed to |
4
|
require_no_crop_faces ¶
require_no_crop_faces(mesh: DcelData, what: str) -> None
Refuse a cropped mesh in a computation that has no crop-aware formulation yet.
A crop face read as contact with the medium is the error this module exists to prevent, so a computation that would read it that way raises instead of returning a number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mesh
|
DcelData
|
the mesh. |
required |
what
|
str
|
the computation's name, for the message. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
if the mesh has crop faces. |
border_like_faces ¶
border_like_faces(points: NDArray[floating], triangles: NDArray[integer], labels: NDArray[integer]) -> NDArray[np.bool_]
Triangles that look like crop faces although nothing says they are.
A crop face, as a reconstruction writes it, is a triangle between the medium and a cell lying
flat on a face of the volume, so on a face of the mesh's own bounding box. A triangle counts
here when its labels are (0, c) in either order and its three vertices have exactly the
bounding box's minimum or maximum coordinate on one axis; and a bounding-box face counts only
when such triangles span at least BORDER_LIKE_MIN_SPAN of its extent on both of its other axes
and the largest patch of them connected through shared edges covers at least
BORDER_LIKE_MIN_PATCH_AREA of the face, so that the few scattered flat triangles an uncropped
tissue has at its extremes do not count.
A heuristic, used only to decide whether to warn: it misses the few crop-face vertices a junction relocation moved off the plane, and it cannot tell a crop from a large flat contact that coincides with the bounding box.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
NDArray[floating]
|
|
required |
triangles
|
NDArray[integer]
|
|
required |
labels
|
NDArray[integer]
|
|
required |
Returns:
| Type | Description |
|---|---|
NDArray[bool_]
|
NDArray[np.bool_]: |
warn_if_crop_faces_unrecorded ¶
warn_if_crop_faces_unrecorded(points: NDArray[floating], triangles: NDArray[integer], labels: NDArray[integer], source: str, stacklevel: int = 3) -> None
Emit UnrecordedCropFacesWarning when a mesh with no crop record has border-like faces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
NDArray[floating]
|
|
required |
triangles
|
NDArray[integer]
|
|
required |
labels
|
NDArray[integer]
|
|
required |
source
|
str
|
where the mesh came from, for the message. |
required |
stacklevel
|
int
|
passed to |
3
|
remove_crop_interfaces ¶
remove_crop_interfaces(solution, crop_interfaces: tuple[tuple[int, int], ...])
A tension solution without its crop interfaces, which must have come out undetermined.
Works on any solution dataclass with tensions (aligned with dict_tensions' keys),
dict_tensions, component_of, undetermined, fragmented and n_components
(junction_graph.ComponentTensionSolution, per_edge_tension_inference.YoungDupreLocalResult).
A crop interface has no equation, so it is undetermined in the solve; removing it changes no
other value. fragmented is re-read without it, so a mesh is not reported fragmented only
because its crop is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution
|
ComponentTensionSolution | YoungDupreLocalResult
|
the solution as the estimator returned it. |
required |
crop_interfaces
|
tuple[tuple[int, int], ...]
|
|
required |
Returns:
| Type | Description |
|---|---|
|
ComponentTensionSolution | YoungDupreLocalResult: a copy of |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if a crop interface received a finite tension, which would mean an equation read the crop: a defect, never a result. |
remove_crop_interfaces_from_map ¶
remove_crop_interfaces_from_map(dict_tensions: dict[tuple[int, int], float], crop_interfaces: tuple[tuple[int, int], ...]) -> tuple[NDArray[np.float64], dict[tuple[int, int], float]]
remove_crop_interfaces for a method that returns a plain map: (array, map) without them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dict_tensions
|
dict[tuple[int, int], float]
|
interface -> tension, in the method's own (sorted) key order. |
required |
crop_interfaces
|
tuple[tuple[int, int], ...]
|
|
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
NDArray[float64]
|
the tensions as an array in the map's key order, and the map, both without the |
dict[tuple[int, int], float]
|
crop interfaces. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if a crop interface received a finite tension. |