Stop treating a goniometer axis and a grid scan as alternatives
They are not alternatives: a grid is usually collected at a particular head position, so an axis and a grid describe different parts of the same setup. The exclusion was enforced independently in four places - the API converter, the CBOR serializer, the writer and the reader - and each silently dropped the grid scan when an axis was present. Nothing warned. The writer now builds one chain from the base outwards, spindle -> chi -> phi -> helical -> grid translations, instead of two branches. NXmx applies the deepest dependency first, so the sample ends up innermost, which is what it physically is: the grid stage rides on the head and the head rides on the spindle. The grid translations consequently move inside the rotation - identical to before at omega = 0, and right rather than wrong when it is not. A grid scan with no axis at all now writes a stationary omega. NXmx has no way to say "there is no rotation", and a sample chain of translations alone is not something readers accept: dxtbx raises outright on it, so every grid-scan master we have written so far cannot be opened by DIALS. Measured on a file matching the new chain: dials.import reads it. At 0 degrees the rotation is the identity whatever the axis points along, so the conventional vector carries no geometric claim - it only has to be well formed. The API change is deliberately not breaking: no field changes type or cardinality, only the prose saying the two were exclusive, and a request that set both used to lose one silently and now does not. JFJochReader_GridScan asserted the absence of a goniometer; it now asserts the axis is present and stationary, which is the contract that matters - a grid scan must not read back as a sweep. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -490,7 +490,11 @@ TEST_CASE("JFJochReader_GridScan", "[HDF5][Full]") {
|
||||
auto dataset = reader.GetDataset();
|
||||
|
||||
|
||||
REQUIRE(!dataset->experiment.GetGoniometer().has_value());
|
||||
// A grid scan carries a stationary spindle: NXmx cannot say "no rotation", and a chain of
|
||||
// translations alone is not readable (dxtbx raises on it). It must not read back as a sweep.
|
||||
REQUIRE(dataset->experiment.GetGoniometer().has_value());
|
||||
CHECK(!dataset->experiment.GetGoniometer()->IsScanning());
|
||||
CHECK(dataset->experiment.GetGoniometer()->GetIncrement_deg() == 0.0f);
|
||||
REQUIRE(dataset->experiment.GetGridScan().has_value());
|
||||
|
||||
CHECK(dataset->experiment.GetGridScan()->IsSnakeScan());
|
||||
|
||||
Reference in New Issue
Block a user