Files
Jungfraujoch/tools/jfjoch_extract_hkl.cpp
T
leonarski_fandClaude Opus 5 db9cc9106f rugnux: the per-reflection correction factor is named for what it is, not for what it once held
The factor multiplied into each integrated intensity was called rlp, for reciprocal
Lorentz-polarization, and until this week that is all it held. It now also carries
the sensor efficiency at the angle the beam arrives, and on the stills path it holds
that efficiency and the polarization with no Lorentz term at all - correctly, since
the Lorentz factor of a still is one. Three different products under one name that
promises exactly one of them, in code where the neighbouring member is the total
correction.

Rename it prescaling_corr: multiplicative, applied before scaling, therefore not a
scale, and silent about its contents - which is the point, since the contents have
now grown twice. It is also what DIALS calls the same product. The stills refinement
member spelled "1 / rlp" becomes inv_corr, and the comments and usage text that
promised "the Lorentz-polarization factor and nothing else" now say what is actually
there.

The Lorentz term keeps its own name where it is computed, because that name is
correct. The two external spellings are untouched: the CBOR key and the reflection
dataset are a published format, and a reader that meets an unknown key would take
the factor as zero, which both the merge key and the ingest treat as a reflection to
drop - so every reflection would vanish and the run would still exit zero.

No output changes: the merged and unmerged files of two full runs are byte for byte
what the previous binary wrote, four stored files from before the efficiency
correction still re-scale identically, and the reflection datasets of the process
file are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
2026-09-05 13:41:16 +02:00

168 lines
6.2 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <fstream>
#include <getopt.h>
#include "XdsIntegrateParser.h"
#include "../reader/JFJochHDF5Reader.h"
#include "../common/print_license.h"
#include "../common/Logger.h"
#include "../common/hkl_key.h"
void print_usage(Logger &logger) {
logger.Info("Usage ./jfjoch_extract_hkl {<options>} <path to master file>");
logger.Info("Options:");
logger.Info(" -I<num> Number of images");
logger.Info(" -o<file> Output filename");
logger.Info(" -x<num> Max dist from Ewald sphere");
logger.Info(" -R{<file>} Sum same HKL across neighboring images (image +/- 1) - optional reference INTEGRATE.HKL file name");
}
int main(int argc, char **argv) {
int64_t image_number = 0;
float max_dist_ewald_sphere = 1.0;
bool sum_neighboring = false;
std::string ref_file;
std::string output_filename = "out.hkl";
print_license("jfjoch_extract_hkl");
Logger logger("jfjoch_extract_hkl");
logger.Verbose(true);
int opt;
while ((opt = getopt(argc, argv, "I:x:o:R::")) != -1) {
switch (opt) {
case 'I':
image_number = atol(optarg);
break;
case 'x':
max_dist_ewald_sphere = atof(optarg);
break;
case 'o':
output_filename = optarg;
break;
case 'R':
sum_neighboring = true;
if (optarg)
ref_file = std::string(optarg);
break;
default: /* '?' */
print_usage(logger);
exit(EXIT_FAILURE);
}
}
if (optind != argc - 1) {
print_usage(logger);
exit(EXIT_FAILURE);
}
JFJochHDF5Reader reader;
reader.ReadFile(argv[optind]);
auto dataset = reader.LoadImage(image_number);
if (dataset) {
if (sum_neighboring) {
CrystalLattice latt;
IntegrateMap agg;
int64_t total_images = reader.GetNumberOfImages();
IntegrateMap xds_result;
if (!ref_file.empty())
xds_result = ParseXdsIntegrateHkl(ref_file);
for (int i = 0; i < total_images; ++i) {
auto dataset = reader.LoadImage(i);
if (!dataset) continue;
if (dataset->ImageData().indexing_lattice)
latt = dataset->ImageData().indexing_lattice.value();
for (const auto &r: dataset->ImageData().reflections) {
int64_t key = hkl_key(r.h, r.k, r.l);
auto it = agg.find(key);
HKLData data{
.h = r.h,
.k = r.k,
.l = r.l,
.I = r.I,
.last_image = i,
.count = 1,
.rlp = r.prescaling_corr,
.image_number = r.image_number
};
bool found = false;
if (it != agg.end()) {
for (auto &val: it->second) {
if (val.last_image == i - 1) {
val.I += r.I;
val.last_image = i;
val.count++;
found = true;
break;
}
}
}
if (!found)
agg[key].push_back(data);
}
}
std::fstream f(output_filename, std::ios::out);
for (const auto &[key, val]: agg) {
if (!val.empty()) {
if (xds_result.empty()) {
f << val[0].h << " " << val[0].k << " " << val[0].l << " " << val[0].I;
f << std::endl;
} else {
auto xds_it = xds_result.find(key);
if (xds_it != xds_result.end() && !xds_it->second.empty()) {
f << val[0].h << " " << val[0].k << " " << val[0].l << " " << val[0].I;
f << " " << xds_it->second[0].I << " " << val[0].rlp << " " << xds_it->second[0].rlp;
f << std::endl;
}
}
}
}
auto cc_result = ComputeCcByResolution(latt, agg,xds_result, 1.0, 50.0, 25);
for (int i = 0; i < cc_result.cc.size(); ++i)
std::cout << 1/ std::sqrt(cc_result.shell_mean_one_over_d2[i]) << " " << cc_result.cc[i]* 100.0 << " " << cc_result.pairs[i] << std::endl;
} else {
auto geom = dataset->Dataset().experiment.GetDiffractionGeometry();
std::fstream f(output_filename, std::ios::out);
if (dataset->ImageData().indexing_lattice) {
auto latt = dataset->ImageData().indexing_lattice.value();
Coord astar = latt.Astar();
Coord bstar = latt.Bstar();
Coord cstar = latt.Cstar();
auto uc = latt.GetUnitCell();
logger.Info("Cell {} {} {} {} {} {}", uc.a, uc.b, uc.c, uc.alpha, uc.beta, uc.gamma);
logger.Info("A {} {} {}", astar.x, astar.y, astar.z);
logger.Info("B {} {} {}", bstar.x, bstar.y, bstar.z);
logger.Info("C {} {} {}", cstar.x, cstar.y, cstar.z);
logger.Info("{} reflections identified", dataset->ImageData().reflections.size());
for (const auto &r: dataset->ImageData().reflections) {
auto recip = astar * r.h + bstar * r.k + cstar * r.l;
auto dist = geom.DistFromEwaldSphere(recip);
if (dist < max_dist_ewald_sphere)
f << r.l << " " << r.k << " " << r.h << " "
<< r.I << " " << r.sigma << " " << dist << " "
<< r.predicted_x << " " << r.predicted_y << " " << r.delta_phi_deg
<< std::endl;
}
}
}
}
}