642cbc7271ea2cdbca9b4fb6c2834e3368a29350
Three changes to the rotation two-pass and what it reports. THE PRE-PASS STOPS EARLY. The first pass exists to measure five things for the second: the post-refined detector distance and beam, the goniometer rotation scale, the frame-order-smoothed mosaicity, the space group, and its own indexing result for the supercell guard. All five are settled by the time the group is adopted. It then carried on and did a full production run anyway - a fourth scale/combine/merge in the adopted group, the correction surfaces, the error model, the resolution cutoff, the twinning analysis, the Wilson B, the statistics table - and wrote MTZ, CIF, HKL and a report to <prefix>_01_*. The second pass remakes every bit of that at the refined geometry a few seconds later, which is the result anybody reads. Measured over the rotation test set, running it anyway was 10 % of the battery, and up to 21 % of a single merge-dominated crystal. It now stops at the space-group decision and writes nothing; the _01_* files go with it, since they existed to compare the two passes and nothing in the pipeline or the test harness reads them. One value had to move for that. Pass 2 asks whether pass 1 reached its space group by PROMOTING the point group, and read that off result.twinning - a struct only filled once the final merge has run. It is now recorded where it is decided. EVERY RUN NOW REPORTS WHERE ITS TIME WENT. The phase marks that drove the GUI progress label are now also timed, and the run ends with a table of wall time per phase summed over both passes, with the mean number of cores each phase kept busy beside it (CPU time over wall time). That second column is the one that matters: a phase with a large share and one core is a single thread doing all the work, which is a different problem from a phase that is simply large. It costs two clock reads per phase, and it means a slow dataset on a machine with no profiler on it can still be diagnosed from its log. The cores column needs process CPU time and is zero where the platform has no getrusage; the wall column works everywhere. AND THE PER-IMAGE COST LINE WAS WRONG. It divided the per-stage means, which are per worker, by the thread count - but the image loop is capped at four workers per GPU, so with 2 GPUs at -N 48 those are 8 and 48 and every stage was reported 6x too small. It divides by the loop's own worker count now, and names it, so the line says what it means. This was the one output anybody tuning the program would read first. Battery 6m52s -> 6m17s, space group 21/24 with the same three disagreements, no failures, and no merged result outside the spread the binary already has against itself between two runs. (One weak, 82%-complete crystal moves several points of R_meas between any two runs of any binary, this one included - measured at 39.7 / 31.7 / 35.5 / 35.8 / 40.1 across five battery runs of four different builds.) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Jungfraujoch
Application to receive data from the PSI JUNGFRAU and EIGER detectors.
All documentation is now placed in docs/ subdirectory and for the current version hosted on Jungfraujoch Read The Docs page.
Languages
C++
74.7%
HTML
8%
C
6.4%
TypeScript
4.4%
Tcl
2.3%
Other
4.1%