PCG backend: decision log¶
One dated paragraph per decision, in order: what was decided, what forced
it, what it superseded. The full record behind each entry is in
pcg_priors_history.md (cited by its dated headings and, after
2026-08-29, by "dev item N" of its Active dev list). The present-tense
description of the backend is pcg_backend_overview.md; a new decision is
appended here AND the affected overview paragraph is rewritten. Entries
that are no longer in force say so in their last sentence.
2026-08-25 -- Support contract verified; cross-iteration ML warm start
adopted. Audit confirmed P H P on both sides of the normal operator and
one P on the right-hand side (test=pcg_recon stage 3b asserts symmetry
and positivity). The ML replay was made to warm-start from the previous
iteration's ML half (validated on bgal), because a 2-iteration replay
from the unregularized base could not close the beyond-band gap. History:
Stage 0/1. Warm starts retired 2026-09-10.
2026-08-26 -- Binary-envelope solvent prior Q_s on by default at
pcg_solvent_lambda_rel=0.1; abinitio3D forces automsk=yes from the
first NU stage; suppression readout in the convergence report. A
real-space penalty on solvent variation (weighted centering, L^T L),
anchored to the data scale, calibrated on bgal (active regime ~1e-1,
over-flattening from 3e-1) and the neutral fixture. History: §4, the
DECISION entries of 2026-08-26, Stage 5 records. Prior removed
2026-08-27; the forced automasking removed 2026-08-28; the readout left
with the prior.
2026-08-27 -- Suppression thresholds are not portable; over-flattening guidance moved to shipped-vs-base FSC inflation. The streptavidin and bgal ladders did not overlay (convergence state and data-scale anchoring differ across box sizes), so the absolute-percentage bounds were retracted and the inflation of the shipped pair's FSC=0.143 over the base pair's (> 5%) became the portable over-regularization signal. History: Stage 5 records of 2026-08-27. Left with the priors.
2026-08-27 -- Direct NU-evidence precision Q_NU becomes priority 1;
Q_s removed. The NU competition's per-voxel cross-half evidence,
compacted into a frozen evidence state with an explicit calibrated null,
replaces P_tau in the replay in NU mode (mode-exclusive; never
additive). The first run failed on a saturated null (a detection
threshold used as a likelihood offset); the same-day redesign to a
lower-quartile null center passed, and the first truth-judged 1WCM
two-way ablation showed Q_NU beating P_tau. Q_s and its plumbing
were removed. History: §3, §5, Stage 6 records. Q_NU removed
2026-09-06.
2026-08-28 -- Q_NU default-on in NU mode (pcg_nu_lambda_rel=0.1
dynamic default); post-hoc NU filtering and forced automasking retired
from the PCG NU path; Q_NU supports trailing reconstruction (evidence
pair = FSC pair). First NU-replay abinitio3D on bgal: the loop worked,
the solvent-era stage-6 overlap collapse was largely cured, cost was
production-viable. History: dated DECISION entries of 2026-08-28.
Superseded 2026-09-06.
2026-08-29 -- Wilson prior Q_W implemented, corrected twice on
truth-judged failures, validated, adjudicated against Q_NU and REMOVED
the same day. On 1WCM Q_NU dominated at every shell even with Q_W
given the ground-truth spectrum. Stage 7 closed. History: Stage 7.1
records and the removal DECISION.
2026-08-29 -- automsk=yes regenerates the evidence envelope under the
Q_NU replay; refine3D_auto joins the PCG bypass; adaptive band
granularity (Stage 6.6) reduced to the nu_refine shell walk. The
a-priori frontier-tracked candidate proposal degraded on 1WCM and was
withdrawn; the final form mirrors the gridding challenger (accept a shell
only on unary win-fraction >= 5%), validated on 1WCM. History: DECISIONs
of 2026-08-29, Stage 6.6 records. The evidence envelope and the
nu_refine walk survive; the Q_NU-specific parts left with Q_NU.
2026-08-29/30 -- Q_NU inert on PfCRT at the default strength;
auto-lambda controller implemented. Suppression 3% on PfCRT versus ~35%
on 1WCM and bgal at the same lambda_rel: the data-scale anchoring uses
the low-band mean of D while the prior competes in the fine shells, so
the effective strength is a dataset property. A one-pole plant model and
a memoryless secant controller on the persisted suppression readout were
added, then (2026-08-31) an AIMD outer loop on the setpoint driven by the
shipped-pair FSC trajectory. History: dev item 2. Removed 2026-09-06.
2026-08-31 -- Final reconstructions keep the PCG backend. The
original-sampling final reconstructions of abinitio3D and refine3D_auto
had silently dropped to a gridding objfun=cc pass; they now run
bootstrap_rec3D on the refinement's backend (cc pass for sigma
availability, then the regularized pass). History: dev item 2
(FINAL-RECONSTRUCTION Q_NU POLICY).
2026-09-01 -- envfsc=yes restored as the refine3D_auto default;
solvent constraint via the lowest-bin convention (dev item 4); direct PCG
support constraint pcg_mskfile (dev item 5, experimental); refine3D_auto
startup made reconstruct -> mask -> re-reconstruct -> refine (dev item 7).
The conservative density automask at envmsklp returned as the FSC
envelope; the NU filter and prior regained a solvent clamp (background
voxels fixed to the coarsest candidate) without re-multiplying references;
an arbitrary [0,1] support can be installed as P; and the PfCRT
refine3D_auto collapse was traced by elimination to a first matching
against unfiltered raw halves. History: dev items 4, 5, 7. The
"references multiplied by the NU envelope" hypothesis (dev item 6) was
falsified the same day.
2026-09-02 -- References are never multiplied by an envelope;
automsk=yes means a heavily low-passed background instead. With the
startup fixed, the PfCRT refine3D_auto collapse tracked the first
consumption of envelope-masked references on both backends
(rec_backend=gridding reproduced it; filt_mode=none automsk=no was
healthy). The NU evidence envelope omits the detergent by design, so a
reference multiplied by it is protein-only while the images contain the
micelle: a model-data mismatch under the euclid objective. Principle
(user): a reference must never hard-remove density present in the images;
excluded density is down-weighted by fixing the filter-field background
(the envelope complement) to the coarsest bank candidate, cisTEM-style.
The code-review response of the same day removed the post-hoc
nu_filter_vols from the PCG path in every mode. History: dev items 8, 9.
2026-09-06 -- Q_NU REMOVED from the PCG backend in its entirety; the
PCG path follows the gridding NU competition exactly. Together with the
auto-lambda/auto-target controllers, the stats file, the bootstrap
calibration pass, the parameters, UI, readout, operator and
test=pcg_priors. Rationale (user): an elegant estimator that ends in a
parameter optimization the competition never needed; the belt on PfCRT
and the msp1 trajectories are the record. The gridding volassemble NU
section was extracted into simple_nu_state_filter and is called from
both backends: base pair seeds the bank, P_tau pair is the auxiliary
member, nu_refine=yes runs the shell walk, finest selected label is the
handoff. History: dev item 2 (DECISION 2026-09-06).
2026-09-06 -- Solve-support policy correction: no density envelope
anywhere unless automsk=yes. Dev item 5 had made the envelope the
replay support unconditionally in ML mode; every msp1 and streptavidin
run since 2026-09-01 solved the shipped pair on the envelope while the
base pair stayed spherical, so their two FSCs were never comparable. Rule:
automsk=yes gates the envelope; under it the replay takes the envelope
and envfsc=yes extends it to the base. History: dev item 2
(SOLVE-SUPPORT POLICY CORRECTION). The envfsc split superseded
2026-09-09.
2026-09-06 -- Matching low-pass ceiling in the NU stages; sigma2 loader carry-over removed; stage-boundary FSC=0.5 promotion. The fine NU handoff must not set the abinitio3D matching band by itself (user verdict); the implicit sibling/parent-directory sigma2 carry-over that had seeded ten msp1 runs from a foreign run's residuals was removed entirely. History: dev item 2 (USER VERDICT, LOG EVIDENCE, msp1 STAGE-7 COLLAPSE ROOT CAUSE).
2026-09-07 -- PfCRT regression (7/7 at 6.0-6.5 A): the ceiling was the
ladder's FINAL value, not the 4.5 A hard bound; NU stages run their full
budget. Map-level audit by cross-FSC against the July reference showed
the sets parting at stage 6. Fixes: cap = LPSTOP_BOUNDS(1), minits =
maxits in NU stages. Not implicated: the backend, the stage-1 floor, the
FSC=0.5 promotion, the sigma bootstrap. History: dev item 2 (PfCRT
REGRESSION 2026-09-07).
2026-09-07 -- Final-reconstruction stage made standalone
(bootstrap_rec3D); canonical sigma2 store reviewed; sequence validated
on msp1 (best msp1 map to date). Image-power seed, gridding ML bootstrap
map carrying the workflow's filtering, residual sigma pass, PCG final map
with a cold-solve floor of five iterations. History: dev items 10-12.
2026-09-08 -- nu_input=gridding|ml alternatives tried and reverted.
Feeding the NU competition a gridding-equivalent M^-1 b pair made the
PfCRT histograms worse and stage 7 collapsed; the truncated-CG base pair
remains the NU input. History: run record 2026-09-08b.
2026-09-09 -- One support, applied once: gridding products deapodized
and given the same soft spherical support as PCG; no second mask anywhere;
evaluate_halfmap_pair masks nothing of its own; postprocess skips its
post-hoc mask for any volume with the provenance sidecar; hard solve
domain + output window replaces the soft P H P. Audit of every
mask3D_soft consumer; the soft formulation had let the band depend on
the CG state where 0 < P < 1. History: records 2026-09-09b/c.
2026-09-09 -- automsk=yes implies envfsc=yes on both backends; the
density envelope constrains both PCG solves. The 09-06 split (spherical
base under envfsc=no) is retired: on PCG the envelope is the support of
base and replay once a prior reconstruction exists, so the FSC pair is
envelope-constrained in the estimator; on gridding the same envelope is
applied post hoc with the phase-randomized correction. The masked-FSC
bias of the constrained pair is acknowledged and REPORTED (>>> FSC MODE),
not corrected. Final reconstructions inherit automsk. History: dev item
2 (SOLVE-SUPPORT POLICY, ENVFSC COUPLING; CODE REVIEW RESPONSE).
2026-09-09 -- NU evidence envelope keeps control of the filtering; its
null has two regimes; shared physical dilation minimum. With the PCG
base pair envelope-constrained, the envelope's mixture null (median/MAD
over the whole support) sat on the zero/zero spike; the null is now
designated on the density envelope's dilation ring for a constrained pair
(Euclidean shell, at full weight of the base support) and stays the
robust mixture estimate for a spherical pair, with the density envelope
as the fallback background. The dilation has a shared minimum of 7.5 A
(the former abinitio3D 7 layers at 1.075 A), an explicit binwidth wins
either way, and the ring's evidence occupancy is logged. pcg_mskfile is
reported as a constrained support. The vestigial AMSK_FREQ regeneration
planner was removed. History: dev item 2 (NU EVIDENCE ENVELOPE UNDER THE
DOUBLE SUPPORT; CODE REVIEW RESPONSE).
2026-09-10 -- Cross-iteration warm starts RETIRED; base from zero, replay
from the shell-shrunk current base; maxits_pcg=2 kept. PfCRT
gridding_vs_pcg (10 vs 9 restarts): every PCG solve was ITS=2 fixed; the
replay's relative residual never fell below 1 and grew to 10^3-10^4 in the
failed runs through the warm start from the previous ML half; the base
pair carried no fine-shell evidence at the stage-6 take-off (0% of the
mask at 7.96 A vs gridding's 6.4%). The user's simulated-data calibration
(two iterations beat gridding, beyond five nothing interpretable changes)
fixes the budget. The first cold-start run: 3.98 A with side chains,
identical to the gridding successes, cost unchanged. INIT= added to the
solve summary line. History: dev item 2 (PfCRT REGRESSION gridding_vs_pcg
2026-09-10, RESULT).
2026-09-10 -- Replay start rejected when worse than zero (streptavidin
canonical 9/10). With the canonical sigma store the PCG backend missed one
streptavidin run in ten (gridding 10/10; legacy 10/10 on both): the map
had the wrong symmetry axis. The logs of the good and the bad run are
identical in the sigma flow (no PCG-specific branch exists in the
canonical store) and part in stage 3, the first PCG/ML stage and the
symmetry-search stage, where the bad run stalled at 6 A instead of
reaching 4.5 A, so the axis was searched on a weaker map. The one
PCG-specific fragility there: the replay started from the shell-shrunk
base at INIT 2-4 and ended at RESID 0.4-2, a half-converged transient
that is both the matching reference and the symmetry-search input at
that stage. Guard, inside the solver and free: solve_core computes the
start's residual anyway, and when it exceeds 1
(PCG_START_MAX_REL_RESID) the start is discarded before the first
iteration and the residual is b itself (no operator application; a
first version that re-ran the whole solve was withdrawn as too costly).
Logged per solve. Whether this closes the 9/10 is to be measured; the
store itself is not implicated. History: this log entry.
2026-09-10 -- Documentation split. pcg_priors.md frozen as
pcg_priors_history.md; this log and pcg_backend_overview.md created.
2026-09-11 -- FSC gate removed from the NU bank and the matching low-pass
under nu_refine=yes; extension is NU evidence only. refine3D_auto had
stopped extending in resolution. The 2026-09-08 fsc/1.5 cap
(init_nu_filter(fsc_res=), nu_bank_cap_find) truncated the static
bank and bounded the shell walk (max_find) by the base pair's FSC=0.143,
so the finest label -- and with it the matching low-pass handoff -- could
never lead the global FSC by more than about two ladder labels, while the
FSC of the base pair lags the local evidence precisely where the map is
extending; the loop that used to carry refine3D_auto from the FSC to the
evidence-supported resolution (July 2026) was closed. Decision (Hans):
nonuniform_filter_state passes no FSC to the bank under nu_refine=yes
(full static ladder), the shell walk runs without max_find, and the
handoff stays the raw finest selected label; get_nu_bank_cap_find
removed. The cap remains in static-bank mode (nu_refine=no, the
abinitio3D ladder), where the walk does not run and the PfCRT
regularized-pair pinning it was written for was in any case fixed at the
root by the like-for-like coarse-to-fine selection of the same day. Logged
as NU BANK UNCAPPED (nu_refine=yes). Stale policy text describing a
PCG-only two-shell FSC bound on the walk and a 5%-support handoff with FSC
headroom was corrected at the same time (nonuniform_filtering_policy.md
sections 8, 10, 12; reconstruct3D_pcg_policy.md;
refine3D_auto_policy.md). Compile and the refine3D_auto rerun are Hans's.
2026-09-11 -- Final and startup PCG reconstructions get a support
reference. On bgal the refine3D_auto resolution doc reported the gridding
FSC wording for a PCG run: bootstrap_rec3D deleted vol<state> from the
final reconstruct3D command line, so build_pcg_state_support found no
reference, the base pair bootstrapped on the sphere and only the replay
took the envelope; the reported FSC was the post-hoc/corrected one. Fix:
the final PCG reconstruct3D receives the step-2 gridding bootstrap map
(same name, same sampling, automasked as the refinement) as vol<state>;
refine3D_auto's startup reconstruction receives the initial volume as
vol1. Both base pairs are now envelope-constrained and FSC MODE reads
estimator-constrained, as in every refinement iteration.
2026-09-13 -- Shell-walk acceptance is a majority test; matching handoff
floor on signal voxels. Review of the aldolase refine3D_auto log (38.8k
particles, box 192 at 1.3 A, PCG) with the ladder-only Potts pricing in
place: the cleanup no longer erases the walk (voxels on walked labels 62333
-> 62333), which exposed the acceptance rule. The challenge compares filters
one shell apart voxel by voxel with no margin (null win rate 50%) against a 5%
threshold, so every shell was accepted until the frontier halved below 32
voxels: depth = log2(frontier/32) = 12 at the bootstrap, 11 at iteration 1,
with four shells accepted while the majority preferred the coarser filter.
The raw-finest handoff then set the matching band from 54 voxels (3.37 A vs
FSC=0.143 3.62 A) and, once the walk died from iteration 2 on (0% wins on
frontiers of 4-424 voxels), from seeded remnants of 4-36 voxels; the band
sat finer than the FSC in every iteration, the FSC never moved in 20
iterations, orientation overlap was 0.998 from iteration 4 and cFAR decayed
0.70 -> 0.55. Changes: (1) extend_nu_filter_highres accepts a shell only if
wins - n/2 >= NU_HIGHRES_EXTENSION_MAJORITY_Z (3) * sqrt(n)/2 on the tested
frontier, seed floor unchanged (majority_z in the stats; logged per
challenge with the win count instead of the previously misleading
extended 0 on rejections). (2) get_nu_filtmap_finest_selected_lp takes
min_signal_pct: the floor is relative to the signal voxels (mask minus
nu_solvent_lmask, count_nu_solvent_clamped), and
record_nu_alignment_lowpass_limit passes NU_ALIGN_LP_MIN_SIGNAL_PCT (1%)
with min_assigned_pct=0, logging NU MATCHING LOW-PASS HANDOFF on the
master. On the aldolase bootstrap both rules land at 3.67-3.73 A. Compile and
rerun are Hans's; the expected signature is a walk that stops where the win
rate crosses 50%, a handoff at or just finer than the FSC=0.143, and cFAR no
longer decaying.
2026-09-13 -- Ordered-label Potts prior prices the discrete ladder only.
Hans's hypothesis: the prior is too conservative for nu_refine=yes. In the
code every accepted shell became one more integer coordinate
(new_coords(i) = real(i) at the three bank rebuilds and in
setup_nu_candidate_coords), so the hinge (d-1)+(d-1)^2 priced one
Fourier shell like one ladder rung and grew quadratically with the walk
length, while adjacent walked candidates differ little in unary; the
post-extension cleanup (refine_nu_extension_filtmap_ordered_labels, run
after every accepted shell) pulled the leading edge back and the next
frontier shrank under the 32-voxel / 5% gate. Change
(nu_potts_coord_for_label, nu_static_ladder_count in
simple_nu_filter_bank.f90): coordinate = ladder position for labels
1..min(8, n_base), the finest ladder position for every walked shell. The
coordinate is no longer a label identity: nu_effective_base_label_for_candidate
returns the clamped label directly, and the evidence-state ordering assertion
checks cutoff_finds instead of coordinates (the evidence posterior keeps its
own shell-distance continuation). New master log line per cleanup:
NU post-extension cleanup: voxels on walked labels a -> b. Discontinuity
statistics use the same coordinates and now count walked transitions as
identical. Compile and rerun are Hans's; the expected signature is walked
populations surviving the cleanup and accepted shell steps advancing across
iterations.
2026-09-14 -- Regularized pair in closed form; replay solve and its
FSC-shrunk start retired; MRES on the summary line. Trigger: aldolase
refine3D_auto (18.6k ptcls, box 192) with every replay start rejected
(INIT 3-7) and every from-zero replay at RESID 1.0-1.9 after two
iterations against base RESID 0.034 -- the same pattern as every PCG run
since the warm-start retirement. The sidecars in
~/for_claude/PfCRT_regression show what it is: (1) the preconditioner and
the kernel operator are both Fourier multipliers, so up to the support crop
the preconditioned operator is the identity for base and replay alike, and
in the preconditioned norm they converge alike (iter2_preconditioned_resid
0.18-0.31 base, 0.26-0.45 replay); the L2 residual the summary prints
collapses for the base (the first step fits b everywhere, noise shells
included) and stays at ~b_k for the replay wherever the prior dominates
and the solution is ~0 by design -- it measures unfitted noise, not an
unconverged map. (2) P_tau = rho_mean/(tau*SSNR) with the FSC clamped at
0.001 is 1000x the density beyond the band; ml_prior_to_data_khat_l1 is
400-600 in every abinitio stage and any refinement whose FSC reaches zero
inside Nyquist (7 only in Sep07 stage 10, the one replay that ever looked
converged on the L2 number). (3) The FSC-shrunk start W_k = FSC_k is the
P_tau optimum only for a shell-isotropic operator; rho varies within a
shell by orders of magnitude and the base solution at undersampled voxels is
bounded only by the 1% floor, so (H+P)Wx_base ~ rho_mean(1-FSC)x_base(v)
there, tens of times b(v): INIT >> 1 on every anisotropically sampled
dataset, rejection correct, start pointless (the first CG direction from
zero, M^-1 b, is already the voxelwise Wiener-shrunk gridding map).
Decision (Hans): ship the closed form. reconstructor_pcg%shrink_by_ml_prior
scales the base solution's padded-lattice coefficients by
1 - P_tau*precond = (rho+floor)/(rho+floor+P_tau) voxelwise (window
converted to the solve domain and back), on the replayed operator with the
prior installed -- the diagonal-model optimum, without the global step-length
overshoot two CG iterations from zero produce -- and returns the L2 and
preconditioned residuals of the result against the replay system (one
operator application) as a diagnostic of the support coupling it leaves out.
Both execution paths (regularize_state_half, the distributed ML job) take
it; regularized_ml_initial_guess, ml_shrinkage_filter and
fsc2shrink_filter are removed; no production solve starts nonzero. The
summary line gains MRES= (final preconditioned relative residual; the last
z is now formed at exit so the final entry exists in the sidecar as
final_rel_resid_m), KIND=ml reads ITS=0 STOP=closed_form. The
regularized pair costs the raw re-read plus finalization plus ~4 FFT passes
instead of two CG iterations. What to compare on the aldolase rerun: the
shipped pair against the former 2-iteration replay (the map Hans judged
visually good) and against fsc2optlp of the _unfil pair, by FSC between
them and by eye; MRES of the closed form tells how far the diagonal optimum
sits from the coupled one. Compile and runs are Hans's.
2026-09-16 -- The NU shell walk retired; one generated ladder with the
regularized pair as its finest member for every workflow. Trigger: the
nu_refine=yes walk never let the ML-regularized volume compete for voxels
(it was the finest STATIC member and the walk challenged hard shells beyond
it), and its acceptance rule -- a full-weight shell helps cross-half
prediction only where the half-map SNR exceeds 1 -- is local FSC>0.5, which
is conservative for filtering the map and no better than the FSC-0.143
extent for setting the matching band; on aldolase it pinned the band while
the actual ceiling was the data model (no per-particle CTF or polishing).
Meanwhile every abinitio3D run used the discrete ladder plus auxiliary
competition and it works. Decision (Hans): delete the walk and densify the
static ladder instead, one implementation for abinitio3D, refine3D_auto,
refine3D and postprocess_nu. The bank is generated per box: coarse rungs
20/15/12/10/8/6 A, then fine rungs every NU_LADDER_FINE_STEP=2 Fourier
shells up to one shell coarser than the closed-form regularized pair
(ml_reg=yes), which is the finest member and competes voxelwise like any
rung; without a regularized pair the rungs are bounded at fsc/1.5
(postprocess_nu, ml_reg=no); the fine spacing widens (never truncates)
to fit NU_BANK_MAX_MEMBERS=16. Potts coordinates and the evidence
candidate masses are positions on the reference ladder 20-4 A interpolated
in log(1/res), so the smoothing prior is scale-free across boxes. The
matching handoff is the content extent of the finest label holding >=1% of
the signal voxels at it or finer: a rung's cutoff, the pair's FSC=0.143
resolution for the regularized member, no headroom (abinitio3D keeps its
own 4.5 A stage limit for the non-NU FSC=0.5 promotion only). Removed:
simple_nu_filter_extend.f90, the nu_refine key (parameters, phases, UI,
every workflow default), refine_nonuniform_filter_bank, the highres-step
sidecars, nu_static_ladder_count, the walk statistics and the majority
test, the NU BANK CAP/UNCAPPED log lines (now one NU BANK line naming the
rungs, the fine step and the finest member). Design record:
nu_refine_ml_estimator_competition.md (rewritten). Compile and the
aldolase/PfCRT A/B reruns are Hans's; the expected signature is the
regularized label populating the core, hard rungs the periphery, and the
handoff tracking the FSC=0.143 extent rather than a shell-walk frontier.
2026-09-16 -- Final reconstruction: automsk and the lag-one reference
forwarded on the direct route too. bgal refine3D_auto (native box 256 =
registration box, committed sigmas reused, so calc_final_rec took the
direct reconstruct3D route rather than bootstrap_rec3D): the shipped
PCG map ran on the sphere (rec_final_state01_pcg_support.txt:
solve_support=sphere, FSC mode "density envelope applied post hoc")
while every refinement iteration had been estimated on the density
envelope. prep_final_rec_cline forwarded automsk and vol<state> only
on the bootstrap route. Now automsk is inherited on both routes and the
direct route sets filt_mode=none and passes the last refinement volume
as vol<state> on PCG, so build_pcg_state_support derives the same
lag-one envelope and the doc reads "halves estimated on a support
envelope" like the iterations. The first-run readings of the retired-walk
bank on this bench: abinitio3D 822 s, stage-6 bank 13 rungs + MLreg (14.6%
of the mask), refine3D_auto 1040 s, registration pass moved 1.8% of
directions, FSC0.5 4.30 -> 4.03 A, MLreg ~6.5% at box 256 with the 3.63 A
rung below it at 0.02%; MRES of the closed form 0.86-1.3 at box 256 versus
~0.1 in the cropped stages. Open: the gridding regularized pair won 0% in
the abinitio final's bootstrap bank (PCG wins 6-15% at the same box), to be
checked on the gridding aux path.
2026-09-16 -- Regularized solve: maxits_ml coupled iterations from the
closed form. bgal refine3D_auto at the native box 256: the closed form's
preconditioned residual MRES read 0.86-1.3 at every iteration and 0.93 in
the abinitio final, against ~0.1 in the cropped abinitio stages, whose band
reached Nyquist (box 140 at 2.33 A/px). At the native box a third of the
shells lie beyond the band with P_tau ~1000x the data, and that is where
the diagonal and coupled answers can differ; whether they differ inside the
band (the map) or only beyond it (bookkeeping) the number cannot say. The
regularized member still won 6-7% of the mask, so nothing was blocked.
Decision (Hans): run 2 coupled iterations of the regularized system FROM
the closed form (maxits_ml, default 2, rtol=0, no start rejection,
indefinite stop falls back to the closed form). Unlike the retired from-zero
replay, the start already has the prior's spectral shape, so CG can only
move toward the coupled solution; ~2 s per half per iteration at box 256.
Diagnostics: INIT on the KIND=ml line is the closed form's L2 residual,
MRES the final one, and a CLOSED-FORM MRES a -> b line reports the FSC
between the start and the solved map (0.5/0.143 crossings and the minimum
over the pair's FSC>0.143 band). Reading rule for the rerun: band minimum
~1 with MRES down means the iterations only touched beyond-band content
and the closed form alone was adequate; band minimum well below 1 means the
closed form was leaving in-band signal on the table and the iterations
stay. Same bench rerun (abinitio3D + refine3D_auto, PCG) is Hans's.
2026-09-16 -- maxits_ml result: refinement-invisible; default 0. Same
bench rerun (7_refine3D_auto, box 256, maxits_ml=2): MRES of the
regularized half went 1.02 -> 0.29 at the bootstrap, 0.71 -> 0.49 and
0.81 -> 0.67 in the iterations (two iterations do not reach the coupled
solution either); the FSC between the closed form and the solved map stayed
= 0.965 on every in-band shell and crossed 0.5 only at 2.7-3.1 A, beyond the 3.59 A band; the regularized member's share of the mask rose 0.4%; and every iteration's FSC0.5/0.143, handoff and the final map were identical to run 6 to three decimals. Decision (Hans): default
maxits_ml=0(closed form shipped as before); the parameter and the diagnostics stay as the knob. The diagonal model is adequate for the regularized member's two jobs (competing for voxels, setting the band); the residual it leaves lives in the beyond-band shells.
2026-09-16 -- PfCRT abinitio3D regression: the merged-reference climb
needs the band ahead of FSC=0.143; headroom restored for nonuniform_lpset.
~/for_claude/PfCRT_regression/current_broken (five restarts): with the
regularized member handing off its FSC=0.143 resolution (the 2026-09-16
band rule) the NU stages crept one shell per iteration (stage 6: 9.41 ->
8.39 A over 30 iterations, bank 4 hard rungs 19.4 -> 10.0 A + regularized
pair at 9.41 A), stage 8 was carried only by its explicit 6.0 A limit and
the final map stalled at 7-8 A. The healthy run (latest2, former static
bank) at the same point: FSC=0.143 8.87 A, bank capped at fsc/1.5 = 5.86
A, the regularized pair in the 5.97 A slot winning 5.4% and the 8 A rung
15%, handoff 5.97 A, then 5.0 and 4.5 A as the FSC caught up to 4.5 A.
The staged climb is a ratchet: both halves align to one merged reference,
so its FSC=0.143 is not a gold-standard band, and matching 1.5x ahead of
it is what pulls the FSC up. bgal, Msp1 and streptavidin climb either way
(high SNR); PfCRT does not. Fix: under filt_mode=nonuniform_lpset the
regularized member sits and hands off at max(fsc/NU_BANK_FSC_HEADROOM,
NU_LPSET_BAND_FLOOR=4.5 A) (the former bank's cap and finest rung), the
hard rungs run up to that shell; under nonuniform (gold-standard
refine3D_auto) it stays at FSC=0.143 with no headroom (validated on bgal
today). One implementation, one mode-dependent resolution for the
regularized member (nu_aux_effective_resolution). PfCRT rerun is
Hans's; expected signature: stage-6 handoff ~5.9 A at FSC 8.9 A and the
final at 4.5 A as in latest2.
2026-09-17 -- PfCRT latest3 (10/10 abinitio3D restarts converge):
map quality gap is in refine3D_auto, not abinitio3D; band floor 4 A;
registration pass gated. abinitio3D with the restored lpset headroom
reaches its band floor in stage 8 on every restart (FSC=0.143 4.44-4.50 A
at the 4.5 A floor; final FSC=0.5 4.70 A) versus Jul02_very_good
(band 4.14 A from the July ladder's 4 A rung, FSC=0.5 4.63 A) -- a small,
real cost of the 4.5 A rung, so NU_LPSET_BAND_FLOOR is the reference
ladder's 4 A rung (the 2026-09-08 record already noted 4.5 A pinning the
handoff that asked for 4.14 A). The large gap is refine3D_auto: July's
started iteration 1 at 4.09 A from the abinitio poses and reached
3.61/4.03 A by iteration 3; latest3 ran the registration pass at the
startup pair's FSC=0.8 band, 8.87 A, which moved 33% of the directions
beyond the basin width (17% beyond twice it), dropped iteration 1 to
5.54/7.96 A, and the four-iteration budget ended it at 4.31/6.61 A with
B-factor -137. At that band a small asymmetric membrane protein's
orientations are not discriminable; bgal (large, D2) reassigned 1.7%.
Decision (Hans): keep the pass unconditionally -- the FSC=0.8 band is
too conservative, not the pass itself -- and set regpass_fsc=0.5
(the PfCRT startup pair's FSC=0.5 was 7.96 A against 8.87 A at 0.8),
then, agreeing that one shell finer changes nothing for a particle whose
low-resolution band is the micelle, regpass_fsc=0.143: the pass runs
at the working band, where a global search confirms a good registration
and re-basins only the misregistered particles (cost: a full-band
prob_tab over 5000 directions, 2-3x the coarse pass). A discard gate on
the reassigned fraction was drafted and withdrawn; instead (Hans) the pass
is refine=greedy: exhaustive argmax with the incumbent's direction among
the candidates, so a particle moves only to a better pose, where prob
samples the assignment from the table and re-basins at random wherever it
is flat. Rerun of latest3's refine3D_auto is Hans's; the numbers to
read are the reassigned fraction at 4.14 A and iteration 1's FSC against
July's 4.09 A.
2026-09-17 -- automsk=nu review (Hans's implementation). Kept: the
opt-in mode, the lag-one NU-evidence envelope as the gridding post-hoc FSC
mask and as the reference mask (assembly _nu_filt products, matcher
fallback), density fallback whenever the artifact is absent, incompatible,
empty or has an invalid null, envfsc=yes derived from any active
automsk, the support_kind/mask_kind plumbing and FSC MODE reading
backend= support= posthoc_mask= phase_randomization=. Changed at review:
(1) the NU envelope is never the PCG solve support -- under nu the density
envelope constrains both solves as under yes, because the evidence null of
a constrained pair is designated on the density envelope's dilation ring
at full support weight, outside any evidence envelope, so a NU-supported
solve empties its own null, invalidates the next envelope and falls back to
a density envelope derived from a map that is zero outside the NU support:
an oscillating support with no way back for excluded density; (2) the
bootstrap final-reconstruction route (box change) kept setting
filt_mode=none for the shipped map while inheriting automsk=nu, which
the new validation rejects -- it now keeps the caller's filt_mode under nu
like the direct route; (3) the 2026-09-02 PfCRT collapse rationale, removed
from the matcher comment and the rewritten automasking policy, is back in
both: nu is not a default and must not become one.
2026-09-17 -- Potts coordinate back to the label index; PfCRT map-quality
gap traced to the abinitio3D poses. (1) postprocess_nu on the Sep-11
PfCRT halves produced noise with the retired-walk code. Cause found in the
code, log pending: the 2026-09-16 Potts coordinate (position on the
reference ladder in log(1/resolution)) puts the generated fine rungs about a
tenth of a rank apart while NU_LABEL_SMOOTH_STEP_TOL=1 frees jumps of one
rank, so the smoothing prior was inert across the whole fine end -- the
label field could alternate freely between rungs 4.6-4.1 A voxel by voxel.
In refinement the regularized member wins the core and the FSC hid it; in
the evidence state, which has no regularized member, the fine cutoffs
scatter and the per-voxel sharpening passes noise. Coordinates are the
label index again in both the filter and the evidence competition; the
log-resolution geometry survives as the evidence candidate mass only.
(2) refine3D_auto on latest3 (greedy pass at 4.44 A: 6.2% reassigned,
no FSC change) plateaus at 4.03/4.50 A from iteration 1 with B -90..-100,
against the Sep-11 run's 3.93-3.98/4.14-4.25 A with B -73. The gap is
present in the BOOTSTRAP, before any refinement: gold-standard
reconstruction of the Sep-17 abinitio poses reads 4.14/4.50 A, of the
Sep-11 abinitio poses 3.93/4.09 A, from the same particles. The abinitio
poses are worse although the abinitio's own merged-reference FSC reads the
same (4.5 A band in both). Candidates, both introduced between the runs:
the inert Potts prior above (the NU-stage references' hard-rung pattern),
and the closed-form regularized pair (MRES 1.3 on PfCRT at box 300; the
Sep-11 references' core came from the two-iteration replay). A/B after the
recompile: rerun abinitio3D + refine3D_auto with the index coordinate; if
still short, maxits_ml=2 isolates the closed form.
2026-09-17 -- postprocess_nu restored on the Sep-11 PfCRT halves with the
index Potts coordinate. Even/odd run at box 300: 11 distinct evidenced
cutoffs with coherent populations (4.33 A 181k, 3.80 A 44k, 3.38/3.05 A
3-5k voxels), four evidence bands, B -49; "PfCRT back to being gorgeous"
(Hans). Confirms the 09-16 log-resolution coordinate as the cause of the
noise (and the prime suspect for the abinitio pose gap; A/B pending). Two
fixes on the way: postprocess_nu's own half-map FSC was computed on
real-space volumes (image%fsc reads Fourier coefficients) and read 0.000
A, so the bank ran unbounded to Nyquist -- harmless here (rungs beyond 3 A
won nothing) but wrong; now transformed before the FSC, so the bank is
bounded at fsc/1.5 as designed. And identical inputs (vol1 = vol2, an FSC
of 1 everywhere, the finest cutoff awarded on 1.36M voxels, a sharpened
noise ball) are refused with a message.
2026-09-18 -- Index Potts coordinate reverted for the filter competition
(PfCRT latest4). With the label index, 3/9 abinitio3D restarts reached
4.6 A (4.85-8.2 A otherwise) against 10/10 at 4.4-4.5 A with the
log-resolution coordinate (latest3). Mechanism in the logs: at FSC 8.2 A
the regularized member sits at 5.45 A but the handoff reads 7.96 A (raw
finest label 5.45 A) for the rest of the stage -- nothing finer than the
7.96 A rung holds 1% of the signal voxels, because the dense ladder puts
four to eight members between 8 A and the regularized pair and on the
index coordinate the core's jump out of the 8 A surround costs several
hinge steps instead of the one it cost on the 8-rung ladder; on PfCRT's
small core (12% envelope occupancy) the prior wins. The log-resolution
coordinate is the scale-free generalization of the old prices and is
validated by latest3, bgal, Msp1 and streptavidin; restored for the filter
competition. The evidence competition keeps the index coordinate
(separate Potts problem, separate beta; validated by the "gorgeous"
postprocess_nu on the Sep-11 halves). Correction of the 09-17 entry: the
first "ball of noise" postprocess_nu run had vol1 = vol2, so the
log-resolution coordinate was never shown to produce a noisy
postprocess_nu with correct inputs; the index change was made on a
misdiagnosis. Reruns are Hans's: abinitio3D (expect latest3 behaviour)
and postprocess_nu on the Sep-11 halves (expect unchanged).
2026-09-18 -- NU machinery restored to the ed36eb4c static ladder + aux
competition, as the only mechanism. Decision (Hans): the discrete ladder
[20,15,12,10,8,6,5,4] A capped at fsc/1.5 with the ML-regularized pair
replacing the finest retained label -- abinitio3D's machinery at commit
ed36eb4c, which produced the best PfCRT maps -- is the NU competition for
abinitio3D, refine3D_auto and postprocess_nu; nothing else. The
src/main/nu_filt submodules and simple_nu_state_filter are restored
from ed36eb4c verbatim except: the extend submodule and its interfaces,
the walk statistics type and the walk-only constants are removed (no code
path can extend the bank), the nu_refine control stays removed, the
auxiliary member is used whenever ml_reg=yes, and Hans's automsk=nu
edits (envelope selection, write_nu_evidence_envmask(mask_out, l_valid))
are kept. Gone with this: the generated dense ladder, NU_BANK_MAX_MEMBERS,
NU_LADDER_*, the log-resolution and index Potts coordinates (integer
ladder coordinates again), the lpset headroom/floor (NU_LPSET_BAND_FLOOR;
the cap provides the headroom as it always did), the content-extent
handoff. postprocess_nu passes the half-map FSC so its bank is capped like
the refinement's. Compile and the PfCRT/bgal reruns are Hans's.
2026-09-18 -- The auxiliary pair competes with the finest rung instead of
replacing it. Decision (Hans): with ml_reg=yes the ML-regularized pair
is appended as one more bank member beside the finest retained rung, and
the two compete voxel by voxel; there must be no prior penalty for
replacing a finest-rung voxel by the regularized pair -- if it wins the
unary it is included. Coupling to the ordered-label prior: the auxiliary
shares the finest rung's Potts coordinate (a boundary between two filter
shapes of the same terminal resolution is not a resolution discontinuity),
so every existing price is unchanged and the unary alone decides between
them. Side effects: the auxiliary is always included when supplied (the
ed36eb4c rule ignored it unless finer than the finest rung); the handoff
sorts labels by resolution so it needs no change, and if the auxiliary
falls below the 1% signal-voxel floor the band now drops to the finest
rung rather than to the one below it; the auxiliary's own unary margin
diagnostic now includes the finest rung. setup_nu_dmats appends the
label (own Fourier index, bwfilters column unused, filtered pair never
cached), setup_nu_candidate_coords assigns the shared coordinate.
Untested; the PfCRT abinitio3D + refine3D_auto pair against July's
3.61/3.98 A is the test.
2026-09-18 -- postprocess_nu operates on the project. Decision (Hans):
like postprocess, postprocess_nu takes projfile (+ state, mskdiam,
nthr, optional outvol), fetches the state volume from the out segment,
its _even_unfil/_odd_unfil pair (evidence input) and, when present, its
_even/_odd regularized pair, with which it first runs the refinement's
filter competition -- static ladder capped at fsc/1.5, the regularized pair
beside the finest rung -- printing the bank, the assignment table and the
matching handoff and writing the references and local-resolution map;
then the unchanged evidence sharpening. Every product carries
_pproc_nu (<vol>_pproc_nu.mrc sharpened; <vol>_ref_pproc_nu.mrc,
<vol>_even/_odd_ref_pproc_nu.mrc, <vol>_locres_pproc_nu.mrc). First
run on the Sep-11 PfCRT abinitio3D project: FSC 6.61/3.98 A, bank capped
at 2.65 A (all 8 rungs), regularized pair beside the 4 A rung (both on
shell 78, 3.981 A): rung 6.6% of the mask, regularized pair 3.9%, handoff
3.98 A; "map looks great" (Hans). The
vol1/vol2 file inputs are gone. This is the cheap test of the auxiliary
competition on any completed run directory.
2026-09-18 -- solvent prior as an opt-in SOFT real-space ridge on the replay.
Decision (Hans): "there is solvent left to flatten, no doubt about that",
but "the prior needs to be soft". A first cut refined the replay's hard
support with a Wang-type mask; with the default maxits_ml=0 that is the
closed-form shrink multiplied by a solvent mask, i.e. exactly the
post-solve masking the backend forbids, and with iterations it is still a
hard cut at a single Otsu boundary. Discarded. What ships:
pcg_solvent=yes|no (default no; refine3D/refine3D_auto/abinitio3D/
reconstruct3D; requires rec_backend=pcg; forwarded like the other
backend keys, stripped for the gridding children) with
pcg_solvent_lambda (default 1.0, relative to data_scale). On: the
regularized operator gains lambda_s (1 - w(r)) on its diagonal, w the
logistic protein weight built PER HALF from that half's own current base
map (half-independent prior, regularized pair stays gold standard) at
max(8 A, 2 x res0143) (Otsu inside the production support, width = the
solvent class's spread); maxits_ml defaults to 2 with the prior on
(parameters class, PCG_SOLVENT_MAXITS_ML; explicit 0 refused) because
the closed form cannot see a real-space term. Weight volumes written per
half (pcg_solvent_weight_stateNN_even|odd.mrc, overwritten every
iteration, never accumulated), even/odd correlation and solvent-fraction
gap logged (the half-independence check). In abinitio3D the key is withheld
through stages 3-7 and passed only to stage 8; shortened workflows never use
the prior (superseded 2026-09-22: from stage 7, one stage after
NU_FILTER_STAGE). Support, base pair, FSC oracle and NU bank inputs are untouched on
purpose: the resolution claim carries no extra
mask and the prior's effect is confined to the shipped regularized pair.
No low-pass guard on w: a ridge modulator, unlike a multiplicative
mask, injects no spectrum, and the statistic is band-limited at 2 x res
anyway. Runs under automsk=no too (sphere as support). Provenance
solvent_prior=soft lambda_rel=<x>. Off: bit-identical.
Untested; first test is the PfCRT cold-start run with pcg_solvent=yes
against its 3.98 A baseline, judged on the map (cavities, detergent
belt, skirt) rather than the FSC, then a pcg_solvent_lambda sweep
(0.3, 1, 3).
2026-09-19 -- solvent prior moved to the base solve (per-half re-solve).
Observation (Hans, several data sets): stage maps under the replay-ridge
design looked less noise-fitted but the final map looked too low-pass
filtered. Diagnosis: the on/off comparison was confounded with
maxits_ml 2 vs 0, and the coupled replay's proper P_tau attenuation
plus the classical postprocess's 2FSC/(1+FSC) double-attenuates a
regularized map (the closed form under-attenuates, hiding it; the stage
maps ship NU-filtered base rungs, hiding it). Decision (Hans): keep runs
comparable -- a separate cold solve with the prior on the base system,
its pair fed to the NU machinery, maxits_ml=0 and the closed-form
shrink as standard. What ships: prior-free base pair (operators kept)
-> its FSC sets the smoothing scale, per-half weights from the
prior-free halves -> ridge installed -> both halves solved again from
zero with the same budget on the same accumulators -> that pair is the
base pair everywhere (FSC, NU evidence, replay, B factor). NU caveat
recorded, not acted on: the NU null (dilation ring / robust bulk) is
measured on the prior'd pair; watch NU NULL SHELL GEOMETRY, the null
bias median/MAD and the assignment table for collapse. Summary lines
KIND=pre (prior-free) then KIND=base (prior'd). postprocess gained
fsc_filt=no (skip the optimal filter, low-pass at FSC=0.143 only) and
imgkind=unfil (classical route from the unfiltered pair average) for
the re-reconstruct/re-postprocess matrix on the completed runs.
2026-09-19 -- abinitio3D robustness: one bank rule for every workflow;
the matching band is the finest member of the bank. Log analysis of every
PfCRT set (record: claude/pfcrt_abinitio_band_lead_analysis.md; note that
the MATCHING LOW-PASS LIMIT (THIS ITERATION) readout is the handoff for
the NEXT iteration): with the regularized member handing off its FSC=0.143
(b9cc8e31 current_broken 0/4; 4ff3a1f6 latest5 1/9, the ed36eb4c
restoration of 09-18 had dropped the 09-16 headroom placement) the band
equals the FSC in 41-42% of stage-6 iterations, the crossing advances
about one shell per iteration and the assignment crawls or freezes; with
the member at max(fsc/1.5, 4.5) (6a41a40f Sep16_10of10) the band was
pinned in 4% of iterations, +0.47 A per iteration, 10/10 converged, and
the 4.5 A floor held stages 7-8 below their crop Nyquist (4.14/3.88 A).
July's uncapped rung handoff led by 1.55x median (p90 1.88) and froze 2/10
in stage 6. latest4 (281ca643, index Potts coordinate): the member one
prior step from the finest rung won <= 0.6% of voxels, the handoff fell
back to the rungs, 3/9. Replacement versus competition is not the
separator (replacement at FSC=0.143 failed identically, iteration 86 of
current_broken: MLreg 3.9%, band 8.62 = FSC). Stages 1-5 end alike in
Sep16 and latest5 and better than July's. Hans's reading, adopted: the
band at the FSC starves the alignment (underfitting); the objective's
sigma2 weighting, the stochastic assignment and the evidence-limited NU
reference guard against overfitting, so the 09-16 "inflated FSC" story is
withdrawn. Rule (Hans): the ladder cut at fsc/1.5; the ML-regularized pair
carries its FSC=0.143 and joins beside the finest rung the moment that is
at or beyond the ladder's finest rung at the box (setup_nu_dmats; within
the ladder the rungs compete alone, since the cut always keeps a rung
between fsc/1.5 and fsc); the finest member of the bank is the handoff
(get_nu_filter_bank_finest_lp, record_nu_alignment_lowpass_limit and
postprocess_nu), the 1% signal-voxel floor and the raw finest label are
diagnostics on the handoff line. Same code path for abinitio3D,
refine3D_auto, refine3D_states, classify3D_refs and postprocess_nu; the
interim lpset-only cap placement of the same morning was superseded before
any run. Band per FSC on the PfCRT boxes: 10.7 -> 7.96, 8.9 -> 5.97,
7.6 -> 5.97, 6.9 -> 5.01, 6.0 -> 3.98 (or the crop Nyquist 4.44/4.14),
5.0 -> 3.98, 4.03 -> 3.98, 3.93 -> 3.93 (pair admitted). Expected signature
(Hans's rerun): handoff 5.97 A at an 8.9 A FSC in the first stage-6
iteration, NU AUXILIARY MEMBER ... within the ladder ... the rungs compete
alone throughout the lpset stages on PfCRT, FSC=0.143 at the stage-6
Nyquist within ~10 iterations, overlap < 0.5 through stage 6, stages 7-8
climbing to 4.1/3.9 A. refine3D_auto on PfCRT: the pair admitted only once
the FSC reaches 3.98 A. Not changed, on record: the stage early-stop
(overlap 0.9/0.95) cannot tell a frozen assignment from convergence.
2026-09-21 -- solvent prior: estimate on the base pair, apply to the
prior'd pair; isotropic postprocess protocol; postprocess_nu names.
~/for_claude/pcg_solvent=yes (exp_gate, msp1 at ae97341c; the
streptavidin logs there are ec5527df, pre-prior, not comparable): the
_lp maps the best yet, the _pproc maps noise. Measured: the prior'd
pair was the _unfil pair, its FSC (3.64/3.43 A against 3.88/3.91 A
prior-free; even/odd weight correlation 0.971/0.996, no randomization,
stage-8 crossing pinned at the crop Nyquist in every iteration) set the
optimal filter, which stays open to FSC=0.05, and the B-factor
(-121/-115, density-windowed on top of the ridge) sharpened the
closed-form map with nothing closing it. postprocess_nu on that pair
"looks like madness": its evidence null and the NU whitening (the MAD of
even minus odd per radial shell over a support that is 80-93% solvent)
are measured where the prior removed the noise. Decisions (Hans): the
FSC is never computed from a solvent-prior'd pair; the prior must
influence every reference voxel, not only the band beyond the ladder, so
the NU label field is derived on the prior-free base pair and applied to
the prior'd pair (nonuniform_filter_state apply pair -> nu_filter_vols
per-label composition of the apply halves); the prior-free pair is the
base pair everywhere (FSC, cap, band, competition, evidence, _unfil,
start-volume handoff), the prior'd pair is _even_solvent/_odd_solvent,
the base of the replay and of the references (both PCG paths:
reduce_solve_state_pair solvent outputs, resolve_base_pair_with_solvent_prior
into the solvent pair); automsk=nu needs no special case (its null is
the base pair's). Postprocess (classical): cutoff = FSC=0.143 of the
reconstruction's FSC file (now always the base pair's curve; the _unfil
pair's own FSC computed there only when no file is given), B
from the unfiltered pair average between HPLIM_GUINIER and the cutoff
(a first version fitted the shipped regularized map: -150 on
streptavidin, a cloud of structured noise; the Wiener suppression
steepens the slope, which is what the unfil-pair estimate was always
for), sharpen, the FSC weighting 2FSC/(1+FSC) inside the passband and
the Butterworth at the cutoff (2026-09-22: with the Butterworth alone,
exp_gate at B -108 was a cloud of structured noise, bfac=0 normal, -50
under-sharpened, -75 the cloud beginning; the low-SNR shoulder between
FSC=0.5 and 0.143 passed at full weight, which the weighting holds at
0.25-0.67; streptavidin and msp1 survived on a steeper FSC; postprocess_nu
got the same weighting stretched to each voxel's evidenced cutoff, and its
B-factor from the unregularized pair when it sharpens the solvent pair); fsc_filt and the density window
retired; imgkind=unfil|solvent postprocess the pair averages with the
same cutoff (pair_stem). postprocess_nu: evidence from _unfil,
sharpening applied to the _solvent pair when present; outputs named
like postprocess with _nu in the suffix (_pproc_nu, _pproc_nu_mirr,
_locres_nu; the _ref_pproc_nu references are gone). Also on record:
the final PCG map is the 5-iteration cold solve; the gridding
reconstruction before it is bootstrap_rec3D's sigma seed, the only NU
competition in the final block (its gridding ML pair beyond the ladder
wins 0% of voxels: open since 09-18, inconsequential for the map). To
watch on the rerun: the B-factor of a solvent-flattened map, and whether
the prior'd references keep what made the exp_gate/msp1 _lp maps.
The 2026-09-22 FSC weighting narrowed 2026-09-26: never on an
ML-regularized map, sqrt(2FSC/(1+FSC)) elsewhere, Guinier fit from 10 A.
2026-09-22 -- solvent prior strength by cross-validation (pcg_solvent_lambda
auto). lambda_rel=1 means the ridge equals the low-band data diagonal,
which is strong where D(k) falls steeply (msp1, exp_gate) and weak where it
is flat (PfCRT), and the weight map decides what it can act on at all.
Decision (Hans): choose the strength per specimen by the NU objective over
the whole production support, in closed form (post-hoc shrink of the
prior-free pair against the operator's real-space diagonal) rather than by
re-solves, so it costs a few volume passes and runs every iteration. Placed
by layer: image%nu_objective/nu_objective_noise_profile (core, already
there), reconstructor_pcg%get_realspace_diagonal (operator),
estimate_solvent_prior_lambda + solvent_prior_cross_half_objective in
the sidecar (the prior's estimation module), orchestration and the
pcg_solvent_check re-solve diagnostic in the PCG strategy,
l_pcg_solvent_lambda_auto in params, {auto} in the four UIs, provenance
lambda_rel=<x> auto|set. Also on 2026-09-22: postprocess_nu takes the
stretched 2FSC/(1+FSC) weighting and the base-pair B-factor as its fixed
policy (evidence pair + FSC required, apply pair optional). First thing to
read on the reruns: the PCG SOLVENT PRIOR LAMBDA table on exp_gate, msp1
and PfCRT, and once with the check variable set on exp_gate, whether the
re-solve argmin agrees with the closed form. Same day, two follow-ups
(Hans): the prior starts one stage after the first NU stage
(PCG_SOLVENT_START_STAGE = NU_FILTER_STAGE + 1, stage 7) so the label field
applied to the prior'd pair has settled on a prior-free stage first, instead
of stage 8 only; and the controller forwards pcg_solvent_lambda to the
stage command lines only when it was given (it used to forward the default,
which would have defined the key downstream and switched the estimate off).
The re-solve check runs in both the shared-memory and the distributed path,
so an ordinary nparts run validates the closed form; it is a parameter
(pcg_solvent_check=yes, no environment variables), forwarded like
pcg_solvent, and its table carries the re-solve residuals (RESID/MRES per
half). First bgal run (2026-09-22): the prior activates in stage 7, the
closed-form curve has an interior minimum at lambda_rel 1.21-1.24 in every
stage-7/8 iteration (26-27 % below no prior) and 2.34 in the final
reconstruction; the prior'd base solve is left at RESID 0.20-0.31 (final:
0.55, MRES 2.4) against 0.04-0.06 (final: 0.027) for the prior-free solve at
the same budget. The preconditioner is 1/(rho + floor [+ ml_prior]) and
carries no counterpart of the real-space ridge; whether that is the cause
is what the residual columns of the check are for. Second bgal run with
pcg_solvent_check=yes (stages 7-8, six iterations): the re-solve residual
climbs monotonically with lambda_rel in every iteration (RESID 0.05 at 0.1,
0.21 at 1, 0.38 at 2, 0.72 at 5, above 1 -- worse than the zero start --
at 10 and 20; MRES up to 4.9), so the convergence story is established;
the closed-form and re-solve argmins nevertheless agree (both at 1.0 on the
grid in all six iterations), and the re-solve objective at the optimum is
0.77-0.82 against the closed form's 0.73-0.74, i.e. the real prior'd map
realizes less of the predicted gain, which is what an under-converged
solve looks like. Fix in the operator: the mean of the ridge over the
solve domain folded into the preconditioner diagonal
(fold_solvent_ridge_into_precond, idempotent under strength changes,
re-applied when the preconditioner is rebuilt). The check was not
forwarded to the final reconstruction (simple_final_rec copies the PCG
keys explicitly); fixed, so the final-reconstruction table (closed form
chose 2.34-2.39 there) can be read on the next run. Third bgal run, with
the ridge in the preconditioner: in-stage prior'd base RESID 0.095-0.10
(was 0.18-0.31), MRES 0.10-0.11 (was 0.4-1.0, now equal to the prior-free
solve's); final reconstruction RESID 0.048 (was 0.56), MRES 0.032 (was
2.6); no grid value ends above the zero start any more. Closed-form and
re-solve argmins agree in-stage (1.0, 6/6) and in the final reconstruction
(2.0; closed form chose 2.43), so the final-block strength is real and h
needs no box correction. The re-solve objective at the optimum now reaches
0.715-0.733 against the closed form's 0.733-0.739 (before the fix it fell
short by 4-9 points). Remaining deviation: at small lambda the re-solve
improves more than the closed form predicts (0.88 vs 0.91 at 0.1), the
known optimism of the scalar shrink about high-frequency solvent noise; it
does not move the argmin. Replay start residual from the solvent pair in
the final 0.74 (was 1.55; in-stage 0.12) -- the closed-form replay at box
256 is the next thing to look at if the final map is questioned.
2026-09-22 -- activation moved to the final stage. The stage-7/8 results
above remain the validation record, but the active abinitio3D policy now sets
PCG_SOLVENT_START_STAGE = NSTAGES: stages 6-7 remain prior-free and an
explicitly requested solvent prior is applied only in stage 8.
2026-09-26 -- postprocess applies the FSC weighting exactly once; RELION's
defaults for the weighting and the Guinier range. Observation (Hans):
after the 2026-09-22 change postprocess and postprocess_nu maps looked
excessively low-pass filtered. Diagnosis: classical postprocess sharpens
the shipped map, which with ml_reg=yes is ML-regularized on both
backends (PCG shrink_by_ml_prior, gridding add_invtausq2rho: the
factor rho/(rho + <rho>/(tau SSNR_half)), about FSC per shell, the
half-map Wiener filter), and the 2026-09-22 recipe multiplied it by
2FSC/(1+FSC) again: 0.33 of the amplitude left at FSC=0.5, 0.036 at
0.143, before the Butterworth (the same double attenuation diagnosed for
the replay on 2026-09-19). RELION (checked in its source): postprocess
reads the _unfil halves, reconstructed without the tau2 prior
(BackProjector::reconstruct(..., do_map=false, ...)), applies
sqrt(2FSC/(1+FSC)) once (zero from the first shell with FSC < 1e-4),
fits B on the weighted map from --autob_lowres 10 A, and applies no
low-pass by default. Decision (Hans): postprocess skips the weighting on
ML-regularized maps (support-provenance solve_kind=regularized, and the
new gridding_regularized written by the gridding restoration under
ml_reg=yes) and keeps B + Butterworth at FSC=0.143; every other map
(pair averages of imgkind=unfil|solvent, base/mixed solves,
unregularized gridding, foreign maps) and postprocess_nu's stretched
weighting take sqrt(2FSC/(1+FSC)) (fsc2cref, tested in the lpstages
suite); HPLIM_GUINIER 20 -> 10 A (postprocess, postprocess_nu,
sharpvol). Kept from SIMPLE: B from
the unweighted unfiltered pair up to the FSC=0.143 cutoff (conservative)
and the Butterworth at that cutoff. To check on the rerun: >>> POSTPROCESS:
ML-regularized map (solve_kind=...) on the workflow's final postprocess,
the automatic B on exp_gate against the -50 to -75 it wanted, and whether
the _pproc maps lose the over-smoothed look. The exp_gate noise cloud
was not the B-factor: see 2026-09-27.
2026-09-27 -- postprocess Butterworth sized to the Fourier shells; sharpening capped at the cutoff shell (09-28).
Observation (Hans): with the FSC weighting off on the regularized map the
exp_gate noise cloud came back on the classical path only, better than on
2026-09-22 but still there, all of it well outside the molecule.
Diagnosis: postprocess_volume_from_files allocated the Butterworth with
box entries, and apply_filter zeroes only shells beyond
size(filter), so the corners of the Fourier cube (out to
nint(sqrt(3) box/2)) kept apply_bfac's exp(-B s^2/4) against the
Butterworth's k^-8 tail. The gain there is exp(3|B|/(16 smpd^2)) times
that tail: at exp_gate's 0.822 A/pixel (cutoff shell 66 of 144) ~1e8 at
B -108, ~1e5 at -80, ~4e2 at -60; msp1 (1.073 A, shell 90) ~4e4 at -115,
streptavidin ~2e2 at -77. What was measured before: on the 2026-09-22
exp_gate _lp/_pproc the spectrum is zero (float level) from shell 68 on and
the implied B is -107.7 on every shell up to 66, so the FSC weighting
(sized to the FSC, zero below FSC 0.05) had been doing the Nyquist
truncation; the NU sharpening's filters are Nyquist-sized and never showed
it; without anything else in the solvent the corner noise is what is left
above threshold there. Fix: the Butterworth array has get_filtsz()
entries; test_filter_nyquist_support in the lpstages suite pins the
apply_filter behavior the fix relies on. Second, inside the Nyquist
sphere exp(-B s^2/4) still outgrows the order-8 Butterworth beyond about
1.5 x the cutoff at fine pixels (exp_gate, Nyquist shell: x3.4 at B -80,
x45 at -108, x0.5 at -60). Decision (Hans, 2026-09-28): cap the
sharpening gain at the cutoff shell -- there is no signal beyond the
cutoff to restore. bfac_cap_filter (simple_estimate_ssnr, tested in
the lpstages suite) is 1 up to the Butterworth's cutoff shell and
exp((B/4)(s_k^2 - s_c^2)) beyond, applied after apply_bfac for B < 0, so
every shell beyond the cutoff carries the cutoff gain exp(-B s_c^2/4)
times the Butterworth and falls as k^-8 (log line >>> POSTPROCESS: B ...
capped at the cutoff shell: gain ...). The exact exp(-B s^2/4) stays
inside the passband; beyond it the cap is shell-quantized (at most ~6 %
between neighbouring voxels at Nyquist, under a Butterworth of 1e-3).
The _lp product carries no B and is unchanged. postprocess_nu is not
capped: its stretched weighting reaches zero at the first shell where the
global FSC falls below 1e-4, as RELION's does.