diff --git a/docs/CPU_DATA_ANALYSIS.md b/docs/CPU_DATA_ANALYSIS.md index dc5321c4e..de13ffdcc 100644 --- a/docs/CPU_DATA_ANALYSIS.md +++ b/docs/CPU_DATA_ANALYSIS.md @@ -17,7 +17,7 @@ This document describes the crystallographic algorithms implemented in Jungfrauj 11. space-group determination from the merged intensities (Laue group, screw axes, glide planes, centering, the centre of symmetry), the twinning check and the translational pseudo-symmetry check, 12. auxiliary statistics (Wilson plot, ⟨I/σ(I)⟩, CC1/2, CCref), 13. amplitude estimation (French–Wilson) and R-free test-set flagging, -14. optional model-based validation: rigid-body placement of a supplied model, R-free against it, sigma_A-weighted 2mFo−DFc / mFo−DFc electron-density maps, and an anomalous difference map with the strongest anomalous sites named. +14. optional model-based validation: rigid-body placement of a supplied model (molecular replacement where the rigid body does not place it, or for a predicted model), R-free against it, sigma_A-weighted 2mFo−DFc / mFo−DFc electron-density maps, and an anomalous difference map with the strongest anomalous sites named. The reference is split into four parts, in pipeline order; the section numbers run continuously @@ -31,8 +31,8 @@ across them and are the ones the rest of the documentation cites. reflection prediction, profile-fitted integration, scaling, merging, mosaicity and the auxiliary statistics. - [Space group and validation (§13–§14)](CPU_DATA_ANALYSIS_DECISIONS.md) — the space-group search, - twinning and translational pseudo-symmetry, the resolution cutoff, diffraction anisotropy, and - model-based validation. + twinning and translational pseudo-symmetry, the resolution cutoff, diffraction anisotropy, + model-based validation and molecular replacement. ## References @@ -82,6 +82,11 @@ The methods draw on, and in places reimplement, solutions from: - K. Diederichs & P. A. Karplus, *Nat. Struct. Biol.* **4** (1997), 269-275, and P. A. Karplus & K. Diederichs, *Science* **336** (2012), 1030-1033 (R_meas / R_pim, CC1/2 and CC\*). - M. S. Weiss, "Global indicators of X-ray data quality", *J. Appl. Cryst.* **34** (2001), 130-135 (R_pim). - IUCr Commission on Crystallographic Nomenclature, "Statistical descriptors in crystallography", *Acta Cryst.* **A45** (1989), 63-75, and *Acta Cryst.* **A51** (1995), 565-569 (uncertainty conventions). +- J. Navaza, "AMoRe: an automated package for molecular replacement", *Acta Cryst.* **A50** (1994), 157-163 (the rotation function on an interpolated molecular transform, §14.10). +- R. A. Crowther & D. M. Blow, "A method of positioning a known molecule in an unknown crystal structure", *Acta Cryst.* **23** (1967), 544-548 (the full-symmetry translation function, §14.10). +- B. W. Matthews, "Solvent content of protein crystals", *J. Mol. Biol.* **33** (1968), 491-497, and K. A. Kantardjieff & B. Rupp, "Matthews coefficient probabilities", *Protein Sci.* **12** (2003), 1865-1871 (how many copies the cell holds, §14.10). +- R. J. Read, "Pushing the boundaries of molecular replacement with maximum likelihood", *Acta Cryst.* **D57** (2001), 1373-1382; A. J. McCoy, R. W. Grosse-Kunstleve, L. C. Storoni & R. J. Read, "Likelihood-enhanced fast translation functions", *Acta Cryst.* **D61** (2005), 458-464; A. J. McCoy et al., "Phaser crystallographic software", *J. Appl. Cryst.* **40** (2007), 658-674; A. J. McCoy et al., *Proc. Natl. Acad. Sci. USA* **114** (2017), 3637-3641 (the likelihood target, the solution criterion and the expected gain of molecular replacement, §14.10). +- R. D. Oeffner, T. Croll, C. Millán et al., "Putting AlphaFold models to work with phenix.process_predicted_model and ISOLDE", *Acta Cryst.* **D78** (2022), 1303-1314, and J. Jumper et al., "Highly accurate protein structure prediction with AlphaFold", *Nature* **596** (2021), 583-589 (preparing a predicted model for molecular replacement, §14.10). (list is not exhaustive; the full citations, with DOIs, are in [ACKNOWLEDGEMENT.md](ACKNOWLEDGEMENT.md)) diff --git a/docs/CPU_DATA_ANALYSIS_DECISIONS.md b/docs/CPU_DATA_ANALYSIS_DECISIONS.md index 0f176560d..e976e4498 100644 --- a/docs/CPU_DATA_ANALYSIS_DECISIONS.md +++ b/docs/CPU_DATA_ANALYSIS_DECISIONS.md @@ -124,7 +124,7 @@ Everything lands in `_report.txt` section 4 (`ANISOTROPY_*` keys), in th ## 14. Model-based validation: R-free against a model and electron-density maps -Offline (`rugnux --model model.pdb`) the merged data can be scored against a supplied atomic model and electron-density maps computed — enough to confirm that a model fits the data and to inspect the density, not a substitute for refinement. **The structure itself is not refined**; the model is re-fractionalized into the data unit cell and then **placed as one rigid body** (§14.8), and the observed amplitudes are the French–Wilson $|F|$ from §10.8, so the R-free and the maps use exactly the same amplitudes as the written reflection file. The model, structure-factor, bulk-solvent and FFT machinery is provided by GEMMI. +Offline (`rugnux --model model.pdb`) the merged data can be scored against a supplied atomic model and electron-density maps computed — enough to confirm that a model fits the data and to inspect the density, not a substitute for refinement. **The structure itself is not refined**; the model is re-fractionalized into the data unit cell and then **placed as one rigid body** (§14.8) - or, where the rigid body does not place it and for a predicted model, by molecular replacement (§14.10) - and the observed amplitudes are the French–Wilson $|F|$ from §10.8, so the R-free and the maps use exactly the same amplitudes as the written reflection file. The model, structure-factor, bulk-solvent and FFT machinery is provided by GEMMI. ### 14.1 Model structure factors @@ -167,8 +167,8 @@ $m$ and $D$ are estimated on each dataset separately, so two datasets of one cry A model supplied with `--model` is a **hypothesis about the crystal**, not an instruction. It is always scaled, always placed (§14.8) and always scored, and its R-factors and maps are always reported — but before it is allowed to change anything about the reflections that are written, the -data have to accept it. There are only two such things (§14.6), and where the model claims neither the -question is never put: see the end of this section. +data have to accept it. There are only two such things (§14.6); the same verdict also says whether the +rigid body placed the model at all (below). **No fixed threshold on R can decide that**, and this was measured three ways. The classical acentric random-structure value is $R = 0.586$ at unit scale, but the scale here is fitted to minimise the very @@ -235,10 +235,8 @@ merges in 2 s. What remains is the cost of the *slowest* replicate: how many pla orientation needs varies by nearly half between them, so the concurrency saturates around 4×, and more threads than replicates buy nothing. The orientations are drawn up front, in order, from the fixed seed, so replicate $i$ gets the same orientation whatever order the threads run in — a σ that -depended on the scheduling would not be a measurement. Where the null is skipped, `--model` costs -what it did before the null existed (measured: indistinguishable, ~4 s against ~4 s, on a loaded -machine where a single run scatters by a second). Where it runs, that is the price of the answer -being a measurement rather than a threshold. +depended on the scheduling would not be a measurement. That is the price of the answer being a +measurement rather than a threshold. ### 14.6 Aligning the data to the model: enantiomorph and indexing ambiguity @@ -273,7 +271,7 @@ The refinement walks a coarse-to-fine ladder, 6 Å → 4.5 Å → 3.5 Å, each z The refinement sees **only the working reflections**. The step is then committed only if it lowers **R-free**, computed at full resolution on the free set it never saw; otherwise the model is put back exactly where it was read and the maps are the ones it would have given. The whole addition costs about two seconds. Note that the origin is a gauge in some space groups — free in all three directions in $P1$, and along the unique axis in a polar group — so those components of the translation are undetermined; nothing is done about that beyond the Levenberg–Marquardt damping and the R-free gate, which between them make an undetermined direction harmless rather than unstable. -Where a CUDA GPU is present, the refinement's target is evaluated on it: the same density, the same composition of $F_\mathrm{calc}$ from one copy of the model, the same bulk-solvent mask with its islands removed, the same scale fit and the same Jacobian, computed on the device, where a fit takes a fraction of a second rather than several seconds. The device is chosen once per validation - the real fit and every replicate of the null of §14.5 on the same one - and the CPU is used where there is no GPU, where the card has too little free memory for the fit's buffers, or after a CUDA failure, in which case the whole validation is run again on the CPU. The two agree to rounding and not bit for bit: the device measures distances in single precision and transforms with cuFFT instead of FFTW, and GEMMI's scale fit, whose stopping rule leaves it unconverged at about $10^{-4}$ of $|F|$, can respond to that rounding with a step of its own. A rigid-body step accepted or rejected on an R-free difference below about $5\cdot10^{-4}$ can therefore go either way between the two; every kernel is deterministic, so either one gives the same answer on every run. +Where a CUDA GPU is present, the refinement's target is evaluated on it: the same density, the same composition of $F_\mathrm{calc}$ from one copy of the model, the same bulk-solvent mask with its islands removed, the same scale fit and the same Jacobian, computed on the device, where a fit takes a fraction of a second rather than several seconds. The device is chosen once per validation, before anything is computed, and never revisited - the real fit and every replicate of the null of §14.5 on the same one. The structure factors go to the GPU where their buffers fit a quarter of the card's total memory (judged on the total, so the same input on the same machine always takes the same path), the rigid-body engines take up to another quarter, and the scale fits of §14.2 run on the GPU too, in engines of their own that take at most an eighth of the card; a part that does not fit, or a cell too small for the GPU's gridding, runs on the CPU, as everything does where there is no GPU. A CUDA failure ends the validation, not the run: the validation reports why it did not finish, decides nothing, and the reflection files are those of a run without a model. The two agree to rounding and not bit for bit: the device measures distances in single precision and transforms with cuFFT instead of FFTW, and GEMMI's scale fit, whose stopping rule leaves it unconverged at about $10^{-4}$ of $|F|$, can respond to that rounding with a step of its own. A rigid-body step accepted or rejected on an R-free difference below about $5\cdot10^{-4}$ can therefore go either way between the two; every kernel is deterministic, so either one gives the same answer on every run. The rotation and translation actually taken are reported (`RIGID_BODY_ROTATION_DEG`, `RIGID_BODY_SHIFT_A`), together with the R-free before it (`R_FREE_BEFORE_RIGID_BODY`), so what the placement bought is visible. @@ -283,5 +281,46 @@ The coordinates **as placed** are written as `_model.cif`, and as `_mr.mtz`/`.cif`, with the model as placed there. The structure factors come from the same GPU engine as §14.1 where there is a GPU. +### 14.10 Molecular replacement: placing a model the rigid body cannot + +The rigid body of §14.8 only moves a model that already sits near its place. A model it does not +place - the null of §14.5 is not beaten in the answer's merge nor in the twin hypothesis' one - is +searched for from scratch, and so is a **predicted** model, which has no placement of its own, and any +model given with `--mr`. The kind of model is read from the file: a prediction (ModelCIF's +`_ma_qa_metric`, or no cell and one B value per residue between 0 and 100) is trimmed to the residues +of pLDDT 70 and above, its B-factors made from the pLDDT and its coordinate error from them (following +Oeffner et al., 2022), and cut into rigid domains where the AlphaFold DB's predicted-aligned-error file +sits beside it; anything else is an experimental structure, used as its polymer alone. + +The search is the classical one, scored by likelihood. A rotation function over the point group, its +best peaks refined off the sampling grid (following Navaza, 1994); for each orientation a full-symmetry +translation function computed as one Fourier synthesis (following Crowther & Blow, 1967), in **every +space group the merge cannot tell apart** and in the twin hypothesis' subgroup; and the best +placements of each group put through the rigid body, the bulk solvent and R-free. Further copies are +added one at a time, up to the copy number the cell can hold by its Matthews coefficient (Matthews, +1968; the probabilities of Kantardjieff & Rupp, 2003), each with the copies already placed as a known +partial structure and ranked by the log-likelihood gain of the Rice/Woolfson distributions of +$E_\mathrm{obs}$ given $E_\mathrm{calc}$, with $\sigma_A$ falling off with the coordinate error +(following Read, 2001, and McCoy et al., 2005 and 2007). A model whose expected gain (McCoy et al., +2017) is too small to be found is not searched for. A copy is kept where it stands out from the +translation function's own peaks, packs without clashing, and lowers R-free; in $P1$, where the first +copy's position is a gauge, it has to stand out in the rotation function instead. + +Translational NCS changes what the search can tell apart (Read, Adams & McCoy, 2013): with a +pseudo-translation, one copy beside a translated twin of itself fits the data as well in a group whose +screw axes the translation turns into the chosen group's, so such a choice is left undecided unless the +copies, carried into the other group and refined there, fit clearly worse; and where the vector is half +a lattice vector, the placement is compared with every move of itself the vector allows, on the weak +reflections it modulates. + +The choice between groups and merges is a hypothesis comparison like §14.5: the candidate the choice +falls on has to beat a null of the same model placed from random orientations, and lead the other +groups by a margin in R-free. What the choice may do is limited exactly as for the rigid body, and +less: it may relabel the **enantiomorph** of the answer, past the anomalous check of §14.7, and never +reindexes; another group with the answer's rotations, or the twin hypothesis' subgroup, is written +beside the answer as `_mr.mtz`/`.cif` with the model as placed there, and the answer's own +files stay what the run decided. The rotation and translation functions, the rigid body and the +structure factors run on the GPU where there is one. The keys, thresholds and table are described in +[the results report](RUGNUX_REPORT.md#molecular-replacement). diff --git a/docs/CPU_DATA_ANALYSIS_IMAGE.md b/docs/CPU_DATA_ANALYSIS_IMAGE.md index 965899acc..0790bd52d 100644 --- a/docs/CPU_DATA_ANALYSIS_IMAGE.md +++ b/docs/CPU_DATA_ANALYSIS_IMAGE.md @@ -8,9 +8,9 @@ Part of the [CPU/GPU data-analysis reference](CPU_DATA_ANALYSIS.md); the section ``` -## 0. Getting the image onto the GPU: device-side bitshuffle+LZ4 decoding +## 0. Getting the image onto the GPU: device-side decoding -Images arrive bitshuffle+LZ4 compressed (HDF5 filter 32008), and everything from §1 onwards runs on +HDF5 images mostly arrive bitshuffle+LZ4 compressed (HDF5 filter 32008), and everything from §1 onwards runs on the GPU when one is present. Instead of decompressing on the host and uploading the image, the compressed chunk is uploaded — a few MB rather than tens of MB — and decoded on the device. The approach follows Jon Wright (ESRF); the kernels are Jungfraujoch's own. @@ -45,9 +45,21 @@ image to device memory and the second un-transposing and preprocessing out of it The block offsets inside the container can only be discovered by reading the block lengths in order, so that scan stays on the host. -Only `BSHUF_LZ4` is decoded on the device. For the zstd variants (`BSHUF_ZSTD`, `BSHUF_ZSTD_RLE`, -`BSHUF_ZSTD_RLE_HUFF`), and for uncompressed or float images, `BSLZ4DecoderGPU::Supports()` returns -false and the pipeline decompresses on the host and uploads as before. +Two stored formats of other detectors also reach the card as the file stores them. A miniCBF frame's +`x-CBF_BYTE_OFFSET` stream is decoded on the device into the same `int32` image: the stream is cut +into short parts; for every byte offset a part can be entered at, one thread works out where the +decode leaves the part, how many pixels it emitted and their running sum; a scan composing those maps +gives every part its true entry and running value; and a second walk writes the pixels. A stream that +ends before the image is refused, as on the host. A marCCD frame's 16-bit pixels cross the bus at two +bytes each and are widened by the preprocessing kernel itself, which tests the error marker and the +saturation cap on the pixel's value, so a marCCD's 65535 - its saturation marker, not an error - is +treated exactly as in the `int32` image the host would have made. Both are staged through the +engine's own page-locked buffer, as the BSLZ4 chunks are; `.cbf.gz` is still inflated on the host. + +For the zstd variants (`BSHUF_ZSTD`, `BSHUF_ZSTD_RLE`, `BSHUF_ZSTD_RLE_HUFF`), and for other +uncompressed or float images, the pipeline decompresses on the host and uploads as before. The host +decoders are the CPU build's path, not a fallback: a frame the device refuses is not retried on the +host. The container arrives off the network or off disk and is not trusted. Everything checkable on the host — declared sizes, the block scan, a block size that is not a multiple of 8 elements, a block diff --git a/docs/CPU_DATA_ANALYSIS_INDEXING.md b/docs/CPU_DATA_ANALYSIS_INDEXING.md index 4d29a16a4..919e1c5d9 100644 --- a/docs/CPU_DATA_ANALYSIS_INDEXING.md +++ b/docs/CPU_DATA_ANALYSIS_INDEXING.md @@ -230,6 +230,16 @@ also runs (rotation only, and not when a cell was given — `-C` already lowers and its answer is adopted only when it is an integer sub-cell of the standing one and ties or beats it on the validation frames. Everywhere else the standard pass's answer stands. +**A near tie is decided early and checked again late.** The first pass decides on validation frames +from the start of the sweep, so it can act at once - also while a collection is still being written. +Where one of its decisions was a near tie that later frames could tip (the lattice, the indexing +path, the beam centre, the spot-finding settings), the pass is run again once every frame is in, on a +copy of the run taken as it began and deciding on the rest of the sweep too, and only where that +re-check ends elsewhere is the whole run made again with every near tie decided late; a run that found +no lattice after carrying a near tie is made again likewise. The answer is therefore the one deciding +late throughout gives, at the cost of the re-checks (measured: a median of 0.9 s on the sets that had +one). + **A first pass that ends with no usable lattice tries a leaner, shallower one.** A crystal sitting in a crystalline powder floods the pass with spots that are not its own — measured, 2112 spots a frame against the 80 a clean crystal on the same beamline gives — and the FFT then takes its cell out of the diff --git a/docs/RUGNUX.md b/docs/RUGNUX.md index 8b3198a35..6a38593f8 100644 --- a/docs/RUGNUX.md +++ b/docs/RUGNUX.md @@ -2,20 +2,29 @@ `rugnux` is the **offline** crystallographic data-analysis tool of Jungfraujoch — the data-processing half of the system (see [Naming](NAMING.md) for where the name comes from). -It takes an existing HDF5 dataset, runs the full analysis pipeline — spot finding, indexing, -geometry refinement, Bragg integration and (optionally) scaling and merging — and writes the -results to a `_process.h5` file, plus reflection files (`.mtz`/`.cif`/`.hkl`) when merging is -requested. +It takes a stored dataset, runs the full analysis pipeline — spot finding, indexing, geometry +refinement, Bragg integration, scaling and merging — and writes the merged reflections +(`.mtz`/`.cif`/`.hkl`), the unmerged MTZ and the results report; the per-image `_process.h5` is +written only on request (`--write-process-h5`), or as the only output with `--no-merge`. -It runs the *same* analysis code as the online and interactive tools, just driven from the -command line over a file rather than a live detector stream. +It runs the *same* analysis code as the online and interactive tools, driven from the command line +over files. ``` -rugnux {} +rugnux {} [] ``` Run it with no arguments to print the usage. +Given the URL of a `jfjoch_broker` (`http://host:port/`) and the path the master file *will* have, +`rugnux` follows the broker's current collection while it is being written: the data files are read +as the broker reports them closed, processing starts on the first images, and the run ends with the +images the collection delivered. A choice made early on a near tie is checked again on every frame +once all are in, and the run is made again where that check ends elsewhere, so the answer is the one +the whole sweep gives. This is for rotation data and `--mode mx`; the collection's token is read from +`JUNGFRAUJOCH_HTTP_TOKEN` and sent only to the broker. With the master file already on disk, the URL +is ignored. + > **Note.** `rugnux` is under very active development. This page describes the tool and > its options at a high level; the authoritative, always-current list of options is the program's > own usage message — run `rugnux` with no arguments. @@ -41,6 +50,7 @@ rugnux -o myrun dataset_master.h5 rugnux -o myrun -z reference.mtz dataset_master.h5 # 3. with a known structure: R-work / R-free and sigma_A-weighted 2mFo-DFc / mFo-DFc maps +# (a predicted model, or one the rigid body cannot place, goes to molecular replacement) rugnux -o myrun --model model.pdb dataset_master.h5 # 4. with the space group and the cell pinned (-S takes either spelling: P43212 or 96) diff --git a/docs/RUGNUX_ADVANCED.md b/docs/RUGNUX_ADVANCED.md index d8697aef2..719b903dd 100644 --- a/docs/RUGNUX_ADVANCED.md +++ b/docs/RUGNUX_ADVANCED.md @@ -322,7 +322,7 @@ General: | Option | Description | | --- | --- | | `-o, --output-prefix ` | Output file prefix (default: `output`) | -| `-N, --threads ` | Number of worker threads (default, and for any value ≤ 0: all hardware threads). Some stages take fewer, because past a point more workers make them slower: the per-image loop of `--mode mx` uses at most 16 per GPU unless `-N` was given a positive value, and first-pass spot finding and the beam-stop pre-scan have ceilings of their own that `-N` does not lift. Scaling, merging and the space-group search use the full count | +| `-N, --threads ` | Number of worker threads (default, and for any value ≤ 0: every CPU the run may use - its affinity and cgroup quota). Some stages take fewer, because past a point more workers make them slower: the per-image loop of `--mode mx` uses at most 16 per GPU unless `-N` was given a positive value, and first-pass spot finding and the beam-stop pre-scan have ceilings of their own that `-N` does not lift. Scaling, merging and the space-group search use the full count | | `-s, --start-image ` | First image to process (default: 0) | | `-e, --end-image ` | Last image to process (default: all) | | `-t, --stride ` | Process every *n*-th image (default: 1) | diff --git a/docs/RUGNUX_INSTALL.md b/docs/RUGNUX_INSTALL.md index d96d7c9ed..650b2153c 100644 --- a/docs/RUGNUX_INSTALL.md +++ b/docs/RUGNUX_INSTALL.md @@ -115,10 +115,15 @@ build has no CUDA there and needs nothing installed beyond Xcode and CMake. As with the rest of Jungfraujoch, **serious performance requires an NVIDIA GPU**. The CUDA build provides the GPU fast-feedback indexer (`ffbidx`) and the GPU FFT indexer (`fft`); without CUDA only the CPU `fftw` indexer is available. With a GPU present most of the per-image pipeline runs on -the device — bitshuffle+LZ4 decompression, image preprocessing, azimuthal integration, spot finding, -prediction and Bragg integration — as do the pre-scan (beam-stop mask, background beam-centre fit, -spot widths, defective pixels), rotation scaling and merging with its correction surfaces, and the -`--model` rigid-body placement, with CPU implementations as the fallback where there is no GPU. The choice is automatic; +the device — bitshuffle+LZ4 decompression, miniCBF byte-offset decoding and marCCD widening, image +preprocessing, azimuthal integration, spot finding, prediction and Bragg integration — as do the +pre-scan (beam-stop mask, background beam-centre fit, spot widths, defective pixels; one accumulator +per card), rotation scaling and merging from the ingest of the reflections onwards (sorting and the +resolution cut included) with its correction surfaces, and `--model`: the structure factors, scale +fits and rigid-body placement of the validation and the rotation and translation functions of +molecular replacement. The CPU implementations are the path where there is no GPU, and the two agree +to rounding rather than bit for bit (parts of the scaling and the model fits round differently +on the card), so a GPU and a CPU run can differ in the last digits of the merged data. The choice is automatic; a CUDA build runs on the CPU when the GPU is hidden from it (`CUDA_VISIBLE_DEVICES= rugnux ...`). The thread count (`-N`) governs the CPU side of all of it. diff --git a/docs/RUGNUX_OVERVIEW.md b/docs/RUGNUX_OVERVIEW.md index 3feeed413..69cbdd48f 100644 --- a/docs/RUGNUX_OVERVIEW.md +++ b/docs/RUGNUX_OVERVIEW.md @@ -64,8 +64,10 @@ flags ([§10](CPU_DATA_ANALYSIS_INTEGRATION.md), **Write.** The merged `.mtz` / `.cif` / `.hkl`, the unmerged MTZ and the results report land next to each other ([Output files](RUGNUX_TUTORIAL.md#output-files)); with -`--model`, validation runs first and the maps and the placed model are written too -([§14](CPU_DATA_ANALYSIS_DECISIONS.md)). +`--model`, validation runs first - the model placed as a rigid body, or by molecular replacement +where that does not place it or the model is a prediction - and the maps and the placed model are +written too, with `_mr.mtz` where the model chooses another group or the twin hypothesis' +subgroup ([§14](CPU_DATA_ANALYSIS_DECISIONS.md)). **Stills instead.** Serial data skip the two-pass machinery: each image is indexed independently (with the known-cell `ffbidx` indexer where a cell is given), partiality comes from a per-crystal diff --git a/docs/RUGNUX_REPORT.md b/docs/RUGNUX_REPORT.md index 20e38ed2d..11673ea8d 100644 --- a/docs/RUGNUX_REPORT.md +++ b/docs/RUGNUX_REPORT.md @@ -977,7 +977,8 @@ nothing else. A `--model` is placed by molecular replacement where it has no placement of its own - a prediction - or where the rigid body did not place it (`MODEL_PLACEMENT=` above), and `--mr ` takes a model there -straight away, without trying the rigid body first. The search's keys (`MR_*`) and its table are in +straight away, without trying the rigid body first. It runs in a full `--mode mx` run, rotation and +serial stills alike; `--mode scale` places a model by the rigid body only. The search's keys (`MR_*`) and its table are in `5. MODEL VALIDATION`. Where it places the model, the R-factors, the maps and CC(model, data) of that section are of its placement, validated against the merge it was chosen on with nothing left to decide (the maps `_mr_*` where that merge is `_mr`); `MODEL_FIT` stays the rigid body's. Where diff --git a/docs/RUGNUX_TUTORIAL.md b/docs/RUGNUX_TUTORIAL.md index 67988771c..c6bc6c007 100644 --- a/docs/RUGNUX_TUTORIAL.md +++ b/docs/RUGNUX_TUTORIAL.md @@ -290,6 +290,11 @@ Absorption is corrected only by the empirical surface a rotation run fits and ke free set as `.mtz`, for refinement with that law. With `--model`, the maps come from whichever of the two merges the model fits better. See [The twin hypothesis](RUGNUX_REPORT.md#the-twin-hypothesis-twin_subgroup_). +- `_mr.mtz` / `.cif`, with `_mr_model.pdb` / `.cif` — only with `--model` (or `--mr`), + where the model, placed as a rigid body or by molecular replacement, chooses another space group + with the answer's rotations or the twin hypothesis' subgroup: that merge, labelled with the group + the model chose, beside the run's own answer, which is left as it was. See + [Validating against a model](RUGNUX_ADVANCED.md#validating-against-a-model-rugnux---model). - `_report.txt` — the **results report**: what the run determined, in a form both a person and a beamline script can read. Always written, next to the files above. See [The results report](RUGNUX_REPORT.md#the-results-report). diff --git a/image_analysis/structure_refinement/ModelValidation.cpp b/image_analysis/structure_refinement/ModelValidation.cpp index 92b55197a..e1148e07b 100644 --- a/image_analysis/structure_refinement/ModelValidation.cpp +++ b/image_analysis/structure_refinement/ModelValidation.cpp @@ -1381,7 +1381,7 @@ ModelValidationResult Validate(const std::vector &merged, } #ifdef JFJOCH_USE_CUDA } catch (const RigidBodyGPUFailure &) { - throw; // not the null's failure but the device's: the whole validation runs again on the CPU + throw; // not the null's failure but the device's: it ends the whole validation (ValidateAgainstModel) #endif } catch (const std::exception &e) { // The null could not be built, so no decision is licensed and none is taken - which is the diff --git a/tools/battery/README.md b/tools/battery/README.md index 3c438c8ca..69e882e01 100644 --- a/tools/battery/README.md +++ b/tools/battery/README.md @@ -244,7 +244,7 @@ R=build/rugnux/rugnux $B run --rugnux $R # full battery: open + inhouse $B run --rugnux $R --tier smoke # 21 sets covering readers, symmetry, known hard cases -$B run --rugnux $R --tier ci # 26 sets every recent release passed (CI, below), plus the wrong-model null +$B run --rugnux $R --tier ci # 28 sets every recent release passed (CI, below), plus the wrong-model null $B nullmodel --rugnux $R # the wrong-model null on its own (CI's second step) $B run --rugnux $R --only 5reo,lyso_ref # named sets $B run --rugnux $R --arm private # the private arm, on its own