v1.0.0-rc.131 (#39)
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m20s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m46s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m27s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m32s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m57s
Build Packages / build:rpm (rocky8) (push) Successful in 11m54s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m9s
Build Packages / build:rpm (rocky9) (push) Successful in 12m37s
Build Packages / Generate python client (push) Successful in 24s
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 57s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m12s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m4s
Build Packages / Unit tests (push) Successful in 1h17m43s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m20s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m46s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m27s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m32s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m57s
Build Packages / build:rpm (rocky8) (push) Successful in 11m54s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m9s
Build Packages / build:rpm (rocky9) (push) Successful in 12m37s
Build Packages / Generate python client (push) Successful in 24s
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 57s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m12s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m4s
Build Packages / Unit tests (push) Successful in 1h17m43s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.124. * jfjoch_broker: Fix bug in saving JUNGFRAU calibration (pedestal/pedestalRMS) * jfjoch_viewer: Fix calibration (pedestal) images being open flipped * jfjoch_process: Add space group detection (EXPERIMENTAL) Reviewed-on: #39
This commit was merged in pull request #39.
This commit is contained in:
+86
-42
@@ -10,6 +10,7 @@
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "../reader/JFJochHDF5Reader.h"
|
||||
#include "../common/Logger.h"
|
||||
@@ -25,7 +26,8 @@
|
||||
#include "../receiver/JFJochReceiverPlots.h"
|
||||
#include "../compression/JFJochCompressor.h"
|
||||
#include "../image_analysis/scale_merge/FrenchWilson.h"
|
||||
#include "../image_analysis/WriteMmcif.h" // (actually include at top of file)
|
||||
#include "../image_analysis/scale_merge/SearchSpaceGroup.h"
|
||||
#include "../image_analysis/WriteMmcif.h"
|
||||
|
||||
void print_usage(Logger &logger) {
|
||||
logger.Info("Usage ./jfjoch_analysis {<options>} <input.h5>");
|
||||
@@ -517,6 +519,7 @@ int main(int argc, char **argv) {
|
||||
logger.Info("Rotation Indexing found lattice");
|
||||
}
|
||||
|
||||
// --- Optional: run scaling (mosaicity refinement) on accumulated reflections ---
|
||||
// --- Optional: run scaling (mosaicity refinement) on accumulated reflections ---
|
||||
if (run_scaling) {
|
||||
logger.Info("Running scaling (mosaicity refinement) ...");
|
||||
@@ -528,6 +531,8 @@ int main(int argc, char **argv) {
|
||||
scale_opts.merge_friedel = !anomalous_mode;
|
||||
scale_opts.d_min_limit_A = d_min_scale_merge.value_or(0.0);
|
||||
|
||||
const bool fixed_space_group = space_group || experiment.GetGemmiSpaceGroup().has_value();
|
||||
|
||||
if (space_group)
|
||||
scale_opts.space_group = *space_group;
|
||||
else
|
||||
@@ -538,46 +543,89 @@ int main(int argc, char **argv) {
|
||||
auto scale_end = std::chrono::steady_clock::now();
|
||||
double scale_time = std::chrono::duration<double>(scale_end - scale_start).count();
|
||||
|
||||
if (scale_result && !fixed_space_group) {
|
||||
logger.Info("Searching for space group from P1-merged reflections ...");
|
||||
|
||||
SearchSpaceGroupOptions sg_opts;
|
||||
sg_opts.crystal_system.reset();
|
||||
sg_opts.centering = '\0';
|
||||
sg_opts.merge_friedel = !anomalous_mode;
|
||||
sg_opts.d_min_limit_A = d_min_scale_merge.value_or(0.0);
|
||||
sg_opts.min_i_over_sigma = 0.0;
|
||||
sg_opts.min_operator_cc = 0.80;
|
||||
sg_opts.min_pairs_per_operator = 20;
|
||||
sg_opts.min_total_compared = 100;
|
||||
sg_opts.test_systematic_absences = true;
|
||||
|
||||
const auto sg_search = SearchSpaceGroup(scale_result->merged, sg_opts);
|
||||
|
||||
logger.Info("");
|
||||
{
|
||||
std::istringstream iss(SearchSpaceGroupResultToText(sg_search));
|
||||
std::string line;
|
||||
while (std::getline(iss, line)) {
|
||||
if (!line.empty())
|
||||
logger.Info("{}", line);
|
||||
}
|
||||
}
|
||||
logger.Info("");
|
||||
|
||||
if (sg_search.best_space_group.has_value()) {
|
||||
logger.Info("Re-running scaling in detected space group {}", sg_search.best_space_group->short_name());
|
||||
|
||||
scale_opts.space_group = *sg_search.best_space_group;
|
||||
|
||||
auto rescale_start = std::chrono::steady_clock::now();
|
||||
auto refined_scale_result = indexer.ScaleRotationData(scale_opts);
|
||||
auto rescale_end = std::chrono::steady_clock::now();
|
||||
|
||||
if (refined_scale_result) {
|
||||
scale_result = std::move(refined_scale_result);
|
||||
scale_time += std::chrono::duration<double>(rescale_end - rescale_start).count();
|
||||
}
|
||||
} else {
|
||||
logger.Warning("No space group accepted; keeping P1-merged result");
|
||||
}
|
||||
}
|
||||
|
||||
if (scale_result) {
|
||||
end_msg.scale_factor = scale_result->image_scale_g;
|
||||
|
||||
logger.Info("Scaling completed in {:.2f} s ({} unique reflections)",
|
||||
scale_time, scale_result->merged.size());
|
||||
logger.Info("Scaling completed in {:.2f} s ({} unique reflections)",
|
||||
scale_time, scale_result->merged.size());
|
||||
|
||||
// Print resolution-shell statistics table
|
||||
// Print resolution-shell statistics table
|
||||
{
|
||||
const auto &stats = scale_result->statistics;
|
||||
logger.Info("");
|
||||
logger.Info(" {:>8s} {:>8s} {:>8s} {:>8s} {:>8s} {:>10s}",
|
||||
"d_min", "N_obs", "N_uniq", "Rmeas", "<I/sig>", "Complete");
|
||||
logger.Info(" {:->8s} {:->8s} {:->8s} {:->8s} {:->8s} {:->10s}",
|
||||
"", "", "", "", "", "");
|
||||
for (const auto &sh: stats.shells) {
|
||||
if (sh.unique_reflections == 0)
|
||||
continue;
|
||||
std::string compl_str = (sh.completeness > 0.0)
|
||||
? fmt::format("{:8.1f}%", sh.completeness * 100.0)
|
||||
: " N/A";
|
||||
logger.Info(" {:8.2f} {:8d} {:8d} {:8.3f}% {:8.1f} {:>10s}",
|
||||
sh.d_min, sh.total_observations, sh.unique_reflections,
|
||||
sh.rmeas * 100, sh.mean_i_over_sigma, compl_str);
|
||||
}
|
||||
{
|
||||
const auto& stats = scale_result->statistics;
|
||||
logger.Info("");
|
||||
logger.Info(" {:>8s} {:>8s} {:>8s} {:>8s} {:>8s} {:>10s}",
|
||||
"d_min", "N_obs", "N_uniq", "Rmeas", "<I/sig>", "Complete");
|
||||
const auto &ov = stats.overall;
|
||||
logger.Info(" {:->8s} {:->8s} {:->8s} {:->8s} {:->8s} {:->10s}",
|
||||
"", "", "", "", "", "");
|
||||
for (const auto& sh : stats.shells) {
|
||||
if (sh.unique_reflections == 0)
|
||||
continue;
|
||||
std::string compl_str = (sh.completeness > 0.0)
|
||||
? fmt::format("{:8.1f}%", sh.completeness * 100.0)
|
||||
: " N/A";
|
||||
logger.Info(" {:8.2f} {:8d} {:8d} {:8.3f}% {:8.1f} {:>10s}",
|
||||
sh.d_min, sh.total_observations, sh.unique_reflections,
|
||||
sh.rmeas * 100, sh.mean_i_over_sigma, compl_str);
|
||||
}
|
||||
// Overall
|
||||
{
|
||||
const auto& ov = stats.overall;
|
||||
logger.Info(" {:->8s} {:->8s} {:->8s} {:->8s} {:->8s} {:->10s}",
|
||||
"", "", "", "", "", "");
|
||||
std::string compl_str = (ov.completeness > 0.0)
|
||||
? fmt::format("{:8.1f}%", ov.completeness * 100.0)
|
||||
: " N/A";
|
||||
logger.Info(" {:>8s} {:8d} {:8d} {:8.3f}% {:8.1f} {:>10s}",
|
||||
"Overall", ov.total_observations, ov.unique_reflections,
|
||||
ov.rmeas * 100, ov.mean_i_over_sigma, compl_str);
|
||||
}
|
||||
logger.Info("");
|
||||
std::string compl_str = (ov.completeness > 0.0)
|
||||
? fmt::format("{:8.1f}%", ov.completeness * 100.0)
|
||||
: " N/A";
|
||||
logger.Info(" {:>8s} {:8d} {:8d} {:8.3f}% {:8.1f} {:>10s}",
|
||||
"Overall", ov.total_observations, ov.unique_reflections,
|
||||
ov.rmeas * 100, ov.mean_i_over_sigma, compl_str);
|
||||
}
|
||||
logger.Info("");
|
||||
}
|
||||
|
||||
// Write image.dat (image_id mosaicity_deg K)
|
||||
{
|
||||
const std::string img_path = output_prefix + "_image.dat";
|
||||
std::ofstream img_file(img_path);
|
||||
@@ -586,13 +634,13 @@ int main(int argc, char **argv) {
|
||||
} else {
|
||||
img_file << "# image_id mosaicity_deg K\n";
|
||||
for (size_t i = 0; i < scale_result->mosaicity_deg.size(); ++i) {
|
||||
img_file << i << " " << scale_result->mosaicity_deg[i] << " " << scale_result->image_scale_g[i] << "\n";
|
||||
img_file << i << " " << scale_result->mosaicity_deg[i] << " " << scale_result->image_scale_g[i]
|
||||
<< "\n";
|
||||
}
|
||||
img_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// --- French-Wilson: convert I → F ---
|
||||
{
|
||||
FrenchWilsonOptions fw_opts;
|
||||
fw_opts.acentric = true; // typical for MX
|
||||
@@ -601,7 +649,6 @@ int main(int argc, char **argv) {
|
||||
auto fw = FrenchWilson(scale_result->merged, fw_opts);
|
||||
{
|
||||
{
|
||||
// Write scaled.hkl (h k l I sigma)
|
||||
const std::string hkl_path = output_prefix + "_amplitudes.hkl";
|
||||
std::ofstream hkl_file(hkl_path);
|
||||
if (!hkl_file) {
|
||||
@@ -619,23 +666,20 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
MmcifMetadata cif_meta;
|
||||
|
||||
// Unit cell — from rotation indexing result or experiment setting
|
||||
if (rotation_indexer_ret.has_value()) {
|
||||
cif_meta.unit_cell = rotation_indexer_ret->lattice.GetUnitCell();
|
||||
} else if (experiment.GetUnitCell().has_value()) {
|
||||
cif_meta.unit_cell = experiment.GetUnitCell().value();
|
||||
}
|
||||
|
||||
// Space group
|
||||
if (auto sg = experiment.GetGemmiSpaceGroup(); sg.has_value()) {
|
||||
if (scale_opts.space_group.has_value()) {
|
||||
cif_meta.space_group_name = scale_opts.space_group->hm;
|
||||
cif_meta.space_group_number = scale_opts.space_group->number;
|
||||
} else if (auto sg = experiment.GetGemmiSpaceGroup(); sg.has_value()) {
|
||||
cif_meta.space_group_name = sg->hm;
|
||||
cif_meta.space_group_number = sg->number;
|
||||
} else if (space_group) {
|
||||
cif_meta.space_group_name = space_group->hm;
|
||||
cif_meta.space_group_number = space_group->number;
|
||||
}
|
||||
|
||||
// Detector & experiment info
|
||||
cif_meta.detector_name = experiment.GetDetectorDescription();
|
||||
cif_meta.wavelength_A = experiment.GetWavelength_A();
|
||||
cif_meta.detector_distance_mm = experiment.GetDetectorDistance_mm();
|
||||
|
||||
Reference in New Issue
Block a user