The unmerged file reads the integration outcomes and the determined group, neither of which the P1 merge changes, except each image's mosaicity, which the batch headers carry and the merge rewrites. UnmergedMtz builds the file without it on a second thread, and SetUnmergedMtzMosaicity fills it in after the merge, so the file is the same bytes as before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1G8gJVAy6gp1K5Dz3NE5C
90 lines
4.7 KiB
C++
90 lines
4.7 KiB
C++
// SPDX-FileCopyrightText: 2025 Paul Scherrer Institute
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "../common/Reflection.h"
|
|
#include "../common/UnitCell.h"
|
|
#include "../common/DiffractionExperiment.h"
|
|
#include "IntegrationOutcome.h"
|
|
|
|
#include <gemmi/mtz.hpp>
|
|
|
|
struct MergeStatistics;
|
|
struct TwinningAnalysisResult;
|
|
|
|
// The error model as it is reported, already formatted. `isa` is the whole-range 1/sqrt(a*b), the
|
|
// same quantity XDS's ISa denotes, so a file written here is directly comparable with a CORRECT.LP;
|
|
// `isa_asymptotic` is the strong-reflection tier, which only the rotation path has. `a` and `b` are
|
|
// in XDS's convention, sigma^2 = a*(sigma0^2 + b*I^2). Empty strings are written as unknown.
|
|
struct ErrorModelReport {
|
|
std::string isa;
|
|
std::string isa_asymptotic;
|
|
std::string a;
|
|
std::string b;
|
|
};
|
|
|
|
// nthreads: workers for the per-reflection row formatting, which is the bulk of the file.
|
|
void WriteMmcifReflections(const std::vector<MergedReflection> &reflections,
|
|
const UnitCell &unitCell,
|
|
const DiffractionExperiment &experiment,
|
|
const MergeStatistics &statistics,
|
|
const ErrorModelReport &error_model,
|
|
const TwinningAnalysisResult &twinning,
|
|
const std::string &filename,
|
|
size_t nthreads);
|
|
|
|
void WriteMtzReflections(const std::vector<MergedReflection> &reflections,
|
|
const UnitCell &unitCell,
|
|
const DiffractionExperiment &experiment,
|
|
const std::string &filename);
|
|
|
|
// SHELX HKLF-4 text file (h k l I sigma(I), Bijvoet mates separate) for SHELXC / ANODE.
|
|
// nthreads: workers for the per-reflection row formatting, as for the mmCIF.
|
|
void WriteShelxHklReflections(const std::vector<MergedReflection> &reflections,
|
|
const DiffractionExperiment &experiment,
|
|
const std::string &filename,
|
|
size_t nthreads);
|
|
|
|
// Unmerged observations in the column and batch-header layout POINTLESS writes: aimless, pointless,
|
|
// careless and iotbx.merging_statistics all read that layout. H K L are the ASU indices and M/ISYM
|
|
// recovers the index the reflection was measured at (which is what careless needs to see the crystal
|
|
// frame) and says whether the observation is a partial.
|
|
// sum_partials: add the partials of each rocking event into one full, written at the batch of the
|
|
// event's centroid with the summed rocking-curve fraction in FRACTIONCALC - the plain sum every
|
|
// rotation program writes, over the events the combine would assemble (--min-partiality). False
|
|
// writes one row per integrated box instead, flagged as partials for the reading program to sum.
|
|
// Stills have no rocking events and are unaffected either way.
|
|
// The intensities carry the deterministic per-reflection corrections and nothing else - Lorentz
|
|
// and polarization in LP, the sensor's angle-dependent efficiency in QE, and the attenuation of the
|
|
// flight-path medium in FLIGHT - so raw counts are I / LP * QE * FLIGHT. The partiality and the
|
|
// per-image scale are left for the reading program to fit, since every program this file is for
|
|
// fits a scale model of its own.
|
|
void WriteUnmergedMtzReflections(const std::vector<IntegrationOutcome> &outcomes,
|
|
const UnitCell &unitCell,
|
|
const DiffractionExperiment &experiment,
|
|
bool sum_partials,
|
|
const std::string &filename,
|
|
size_t nthreads = 1);
|
|
|
|
// The same file in two steps, for a caller that builds it while the outcomes' per-image scale fields
|
|
// are still being written: UnmergedMtz reads everything but mosaicity_deg, which
|
|
// SetUnmergedMtzMosaicity then copies into the batch headers.
|
|
gemmi::Mtz UnmergedMtz(const std::vector<IntegrationOutcome> &outcomes,
|
|
const UnitCell &unitCell,
|
|
const DiffractionExperiment &experiment,
|
|
bool sum_partials,
|
|
size_t nthreads = 1);
|
|
void SetUnmergedMtzMosaicity(gemmi::Mtz &mtz, const std::vector<IntegrationOutcome> &outcomes);
|
|
|
|
void WriteReflections(const std::vector<MergedReflection> &reflections,
|
|
const UnitCell &unitCell,
|
|
const DiffractionExperiment &experiment,
|
|
const MergeStatistics &statistics,
|
|
const ErrorModelReport &error_model,
|
|
const TwinningAnalysisResult &twinning,
|
|
const std::string &filename,
|
|
size_t nthreads); |