RESULT-CHANGING (owner approved): stills unmerged MTZ written only for the crystals on the run's cell
The unmerged MTZ took every integrated still. A still whose cell is not close to the run's - the same test, with the same tolerances, the merge applies - was indexed in another lattice (on few spots, typically an axis multiple), so its H K L do not name the reflections a reading program takes them for: aimless or careless would scale them in as wrong reflections. On two 25k-frame XFEL runs such frames carried 60% of the integrated reflections, and the 824 MB file was the largest single cost after the merge (about 7 s in --mode scale). Rotation runs are unchanged (one lattice). The orientation matrix in the batch headers is likewise taken from the first crystal on the run's cell. Test: Unmerged MTZ: on stills, only the crystals on the run's cell. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1033,6 +1033,15 @@ gemmi::Mtz UnmergedMtz(const std::vector<IntegrationOutcome> &outcomes,
|
||||
// removing them turns its test into an assumption. XDS and DIALS draw the line in the same place.
|
||||
const char centering = mtz.spacegroup ? mtz.spacegroup->hm[0] : 'P';
|
||||
|
||||
// On stills only the crystals the merge takes are written: one whose cell is not the run's was indexed
|
||||
// in another lattice (on few spots, typically an axis multiple), so its indices do not name the
|
||||
// reflections they would be read as. A rotation run has the one lattice.
|
||||
const auto &indexing = experiment.GetIndexingSettings();
|
||||
const auto merged_crystal = [&](const IntegrationOutcome &outcome) {
|
||||
return scanning || outcome.latt.GetUnitCell().is_close(unitCell, indexing.GetUnitCellDistTolerance(),
|
||||
indexing.GetUnitCellAngleTolerance_deg());
|
||||
};
|
||||
|
||||
std::vector<std::vector<Reflection>> fulls;
|
||||
if (scanning && sum_partials)
|
||||
fulls = SumRockingEvents(outcomes,
|
||||
@@ -1057,8 +1066,9 @@ gemmi::Mtz UnmergedMtz(const std::vector<IntegrationOutcome> &outcomes,
|
||||
add_row(r);
|
||||
} else {
|
||||
for (const auto &outcome : outcomes)
|
||||
for (const auto &r : outcome.reflections)
|
||||
add_row(r);
|
||||
if (merged_crystal(outcome))
|
||||
for (const auto &r : outcome.reflections)
|
||||
add_row(r);
|
||||
}
|
||||
|
||||
// Every row has its own slot, so they are filled on several workers.
|
||||
@@ -1104,7 +1114,7 @@ gemmi::Mtz UnmergedMtz(const std::vector<IntegrationOutcome> &outcomes,
|
||||
// the sweep, which is the one matrix POINTLESS also writes into every batch.
|
||||
std::optional<CrystalLattice> lattice_at_zero;
|
||||
for (const auto &outcome : outcomes) {
|
||||
if (outcome.reflections.empty() || outcome.latt.CalcVolume() <= 1.0f)
|
||||
if (outcome.reflections.empty() || outcome.latt.CalcVolume() <= 1.0f || !merged_crystal(outcome))
|
||||
continue;
|
||||
const float mid_deg = phi_start_deg(outcome.reflections.front().image_number) + wedge_deg / 2.0f;
|
||||
lattice_at_zero = gon ? outcome.latt.Multiply(gon->GetTransformationAngle(mid_deg)) : outcome.latt;
|
||||
|
||||
Reference in New Issue
Block a user