In get_volume_positions, the allow_missing_positions=True branch measures how far each slice sits from its nearest integer multiple of the spacing in units of the spacing:
origin_distance_multiples = (origin_distances - origin_distances.min()) / spacing
is_regular = np.allclose(origin_distance_multiples, origin_distance_multiples.round(), rtol=rtol, atol=atol)
atol is documented in mm, and in the regularly-spaced branch it is applied in mm (np.isclose(spacings, spacing, rtol=rtol, atol=atol)). In the missing-positions branch the same atol therefore accepts a larger physical deviation the wider the spacing: a slice 0.5 mm out of place is rejected with atol=0.1 at 1 mm spacing (deviation 0.5 slices) but accepted at 20 mm spacing (deviation 0.025 slices). rtol has the same problem in the other direction: np.allclose makes it relative to the rounded multiple, so it scales with the slice index rather than with the spacing as it does in the regular branch, and the logged "maximum spacing deviation" is printed in slices while the message reads as mm.
Reproduction:
from highdicom.spatial import get_volume_positions
orientation = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0]
for spacing in [1.0, 5.0, 10.0, 20.0]:
positions = [[0, 0, 0], [0, 0, spacing], [0, 0, 2 * spacing + 0.5]]
print(spacing, get_volume_positions(positions, orientation, allow_missing_positions=True, atol=0.1)[0])
# 1.0 None
# 5.0 None
# 10.0 None
# 20.0 20.0 <- 0.5 mm off, accepted
A small fix (compute the deviation in mm against round(multiple) * spacing + min, compare with atol + rtol * |spacing|, log in mm) with a test over several spacings is in #465, in case that is easier to judge than the description; happy to close it if you read this differently.
In
get_volume_positions, theallow_missing_positions=Truebranch measures how far each slice sits from its nearest integer multiple of the spacing in units of the spacing:atolis documented in mm, and in the regularly-spaced branch it is applied in mm (np.isclose(spacings, spacing, rtol=rtol, atol=atol)). In the missing-positions branch the sameatoltherefore accepts a larger physical deviation the wider the spacing: a slice 0.5 mm out of place is rejected withatol=0.1at 1 mm spacing (deviation 0.5 slices) but accepted at 20 mm spacing (deviation 0.025 slices).rtolhas the same problem in the other direction:np.allclosemakes it relative to the rounded multiple, so it scales with the slice index rather than with the spacing as it does in the regular branch, and the logged "maximum spacing deviation" is printed in slices while the message reads as mm.Reproduction:
A small fix (compute the deviation in mm against
round(multiple) * spacing + min, compare withatol + rtol * |spacing|, log in mm) with a test over several spacings is in #465, in case that is easier to judge than the description; happy to close it if you read this differently.