Build Packages / Create release (push) Successful in 21s
Build Packages / build:portable:macos-arm64:nocuda (push) Successful in 5m0s
Build Packages / build:portable:linux-x86_64:nocuda (push) Successful in 16m46s
Build Packages / build:rugnux:linux-aarch64:cuda (push) Successful in 11m27s
Build Packages / build:portable:windows-x86_64:nocuda (push) Successful in 21m4s
Build Packages / build:portable:linux-x86_64:cuda (push) Successful in 18m54s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 26m32s
Build Packages / build:portable:windows-x86_64:cuda (push) Successful in 25m50s
Build Packages / build:jfjoch:rocky8:nocuda (push) Successful in 20m11s
Build Packages / build:jfjoch:ubuntu2204:nocuda (push) Successful in 19m1s
Build Packages / build:jfjoch:rocky9:nocuda (push) Successful in 22m53s
Build Packages / build:jfjoch:ubuntu2404:nocuda (push) Successful in 23m43s
Build Packages / Generate python client (push) Successful in 32s
Build Packages / Build documentation (push) Successful in 1m46s
Build Packages / build:jfjoch:rocky8:cuda-sls9 (push) Successful in 28m24s
Build Packages / build:jfjoch:rocky8:cuda (push) Successful in 30m21s
Build Packages / build:jfjoch:rocky9:cuda-sls9 (push) Successful in 32m44s
Build Packages / build:jfjoch:ubuntu2204:cuda (push) Successful in 20m17s
Build Packages / build:jfjoch:rocky9:cuda (push) Successful in 25m4s
Build Packages / build:jfjoch:ubuntu2404:cuda (push) Successful in 21m58s
Build Packages / Unit tests (push) Successful in 1h41m55s
Build Packages / Validation Battery (push) Successful in 32m16s
* Rugnux: Processes serial crystallography data from XFELs - SACLA (MPCCD), PAL-XFEL and European XFEL (CXI), LCLS (XTC) and SwissFEL Alvra (JUNGFRAU with a CrystFEL module geometry) - with several files or Jungfraujoch master files merged in one run (`rugnux *_master.h5`). * Rugnux: Stills processing takes a known unit cell and space group as a starting point, finds the beam centre (and, with a cell, the detector distance) from the images, detects the saturation level in other facilities' files and refines the placement of individual detector panels. * Rugnux: The stills report gives R_split and CC1/2 from frame half-sets, comparable with CrystFEL. * jfjoch_viewer: Opens the same XFEL file formats. * Validation: A stills battery checks Rugnux against deposited structures from SACLA, PAL-XFEL, LCLS, European XFEL and SwissFEL. * Rugnux: More reliable convergence of rotation scaling, and live molecular replacement starts as soon as the model is uploaded. * jfjoch_broker: Initialize clears the previous dataset's bearer tokens, image buffer and live Rugnux status, and a slow CUDA JIT cache is reported at start. Reviewed-on: #88 Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
66 lines
2.4 KiB
C++
66 lines
2.4 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include <random>
|
|
|
|
#include <catch2/catch_all.hpp>
|
|
|
|
#include "../image_analysis/scale_merge/CellPopulation.h"
|
|
|
|
TEST_CASE("CellPopulation_OnePopulationKeepsEverything", "[CellPopulation][portable]") {
|
|
std::mt19937 rng(7);
|
|
std::normal_distribution<double> d(0.004, 0.01);
|
|
std::vector<double> r(2000);
|
|
for (auto &x : r) x = d(rng);
|
|
const auto [low, high] = GivenCellPopulation(r);
|
|
for (double x : r)
|
|
CHECK((x >= low && x <= high));
|
|
}
|
|
|
|
TEST_CASE("CellPopulation_SecondFormLeftOut", "[CellPopulation][portable]") {
|
|
// Two crystal forms 9% apart in volume, the given cell one of them; whichever is given, its own
|
|
// population is kept and the other left out.
|
|
std::mt19937 rng(11);
|
|
std::normal_distribution<double> small(0.0, 0.012), large(0.09, 0.008);
|
|
std::vector<double> r;
|
|
for (int i = 0; i < 450; i++) r.push_back(small(rng));
|
|
for (int i = 0; i < 150; i++) r.push_back(large(rng));
|
|
|
|
// Kept frames of each form, against either cell.
|
|
const auto kept = [](const std::vector<double> &x, size_t from, size_t to) {
|
|
const auto [low, high] = GivenCellPopulation(x);
|
|
size_t n = 0;
|
|
for (size_t i = from; i < to; i++)
|
|
n += (x[i] >= low && x[i] <= high);
|
|
return n;
|
|
};
|
|
CHECK(kept(r, 0, 450) > 440);
|
|
CHECK(kept(r, 450, 600) < 3);
|
|
|
|
std::vector<double> r2;
|
|
for (double x : r) r2.push_back((1.0 + x) / 1.09 - 1.0);
|
|
CHECK(kept(r2, 450, 600) > 145);
|
|
CHECK(kept(r2, 0, 450) < 5);
|
|
}
|
|
|
|
TEST_CASE("CellPopulation_GivenCellOffTheCrystal", "[CellPopulation][portable]") {
|
|
// A given cell 3.5% smaller than the crystal's, and a single stray frame right at it: the crystal's
|
|
// population is kept, not the stray frame.
|
|
std::mt19937 rng(3);
|
|
std::normal_distribution<double> d(0.035, 0.003);
|
|
std::vector<double> r(2000);
|
|
for (auto &x : r) x = d(rng);
|
|
r.push_back(0.0);
|
|
const auto [low, high] = GivenCellPopulation(r);
|
|
size_t kept = 0;
|
|
for (double x : r)
|
|
kept += (x >= low && x <= high);
|
|
CHECK(kept >= 2000);
|
|
}
|
|
|
|
TEST_CASE("CellPopulation_TooFewFrames", "[CellPopulation][portable]") {
|
|
const auto [low, high] = GivenCellPopulation({0.0, 0.1, 0.2});
|
|
CHECK(std::isinf(low));
|
|
CHECK(std::isinf(high));
|
|
}
|