Skip to content

Commit 8993247

Browse files
committed
bootstrap_rec3D bugfix
1 parent b14ea7b commit 8993247

9 files changed

Lines changed: 291 additions & 244 deletions

File tree

doc/implementation_notes/pcg_priors.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3444,6 +3444,35 @@ the acceptable-looking outputs do not validate the prior.
34443444
- `bootstrap_rec3D` imports `NU_AUTOTARGET_MIN/MAX` instead of
34453445
duplicating the bounds.
34463446

3447+
10. **Final-reconstruction stage made standalone (2026-09-07).**
3448+
- msp1 residual-pass crash reported after the 09:25 fix carried exactly
3449+
the same code addresses as the 09:18 log (0x12ac0b2
3450+
choose_and_run_strategy, 0x12b2812 refine3d_exec._omp_fn.0, 0x166a8d3
3451+
alloc_hash): same binary, i.e. the pre-fix shared-orientation race, not
3452+
a second race. Rebuild `simple_private_exec` on that machine; addr2line
3453+
on 0x12ac0b2 must no longer name the old choose_and_run_strategy line.
3454+
- Export gate: one event, the master's own THROW at the cold base solve
3455+
of the final reconstruction on the residual sigmas (dot(p,Hp)=NaN at CG
3456+
iteration 1). Its backtrace appears before the "10 PART(S) COMPLETED"
3457+
line only because stderr is unbuffered; no worker died. D is validated
3458+
finite by update_lambda_from_density, so the NaN enters through the RHS
3459+
or the preconditioner floor. The bootstrap reconstruction on the
3460+
image-power STAR (iteration N) solved; the final one on the residual
3461+
STAR (N+1) did not, so the residual groups are the suspect (scale, tiny
3462+
shells). Diagnosis needs sigma2_it_N.star vs sigma2_it_N+1.star from
3463+
the run directory.
3464+
- `bootstrap_rec3D` moved to simple_commanders_refine3D and now owns the
3465+
complete sequence: image-power seed (N), euclid ML bootstrap map,
3466+
refine=sigma residual pass against it, consolidation (N+1), final euclid
3467+
ML map on the residual sigmas; it returns vol1..N and which_iter=N+1 on
3468+
the command line. abinitio3D's calc_final_rec (takes the commander as
3469+
class(commander_base) from the abinitio commander) and refine3D_auto
3470+
call it and carry no copy. Standalone reproduction of the failing stage
3471+
on any project with 3D orientations:
3472+
`simple_exec prg=bootstrap_rec3D projfile=... pgrp=... mskdiam=...
3473+
nparts=... nthr=... rec_backend=pcg` (UI now exposes rec_backend,
3474+
maxits_pcg, rtol).
3475+
34473476
## 11. The NU machinery as the prior infrastructure
34483477

34493478
The nonuniform-regularization machinery

doc/policies/abinitio3D_policy.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,15 @@ iteration and sets `sigma_transition_ready=yes` on the stage command line. The
135135
starting reconstruction then runs as planned, and the stage's first euclid
136136
iteration initializes its workers from that STAR, emits per-particle sigma
137137
files in its own partition layout and replaces the seed with residual sigmas.
138-
The final reconstruction at original sampling seeds the same way through
139-
`bootstrap_rec3D`, then upgrades the seed with one residual sigma pass
140-
(`refine=sigma`) before the shipped euclid ML reconstruction.
138+
The final reconstruction at original sampling is one program call,
139+
`bootstrap_rec3D`, which owns the complete sequence: the same image-power
140+
seed, a euclid ML bootstrap map on it, one residual sigma pass
141+
(`refine=sigma`) against that map, consolidation of the residual groups as the
142+
next iteration and the shipped euclid ML reconstruction on them. Because the
143+
program takes any project with 3D orientations, it is also the standalone
144+
test for this stage (`simple_exec prg=bootstrap_rec3D projfile=... pgrp=...
145+
mskdiam=... nparts=... nthr=... rec_backend=...`), so failures in the final
146+
reconstruction can be reproduced in minutes rather than after a full run.
141147

142148
## 4. Low-Pass and Cropping
143149

doc/policies/refine3D_policy.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,12 @@ an empty directory, and every final reconstruction at a new sampling. Since
184184
residual pass: `refine=sigma` against the seeded map at the final sampling
185185
(no search, no volume assembly, no orientation output, alignment docs are
186186
not merged), consolidated as the next iteration, then the shipped euclid
187-
ML reconstruction runs on the residual sigmas. `bootstrap_rec3D` is now
188-
the seed plus a single euclid ML pass.
187+
ML reconstruction runs on the residual sigmas. Since 2026-09-07
188+
`bootstrap_rec3D` (module `simple_commanders_refine3D`) owns this whole
189+
sequence: seed, bootstrap map, residual pass, consolidation, final map;
190+
abinitio3D's `calc_final_rec` and refine3D_auto call it and carry no copy
191+
of the sequence. It runs standalone on any project with 3D orientations
192+
and is the test entry point for the final-reconstruction stage.
189193

190194
## 6. Reference Preparation
191195

src/main/commanders/simple/simple_commanders_abinitio.f90

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module simple_commanders_abinitio
77
use simple_procimgstk, only: shift_imgfile
88
use simple_commanders_project_core, only: commander_selection
99
use simple_commanders_reproject, only: commander_reproject
10-
use simple_commanders_refine3D, only: commander_refine3D, commander_refine3D_states
10+
use simple_commanders_refine3D, only: commander_refine3D, commander_refine3D_states, commander_bootstrap_rec3D
1111
use simple_commanders_rec, only: commander_rec3D
1212
use simple_cluster_seed, only: gen_labelling
1313
use simple_refine3D_fnames, only: refine3D_startvol_fname, refine3D_startvol_half_fname, &
@@ -40,6 +40,7 @@ subroutine exec_abinitio3D_cavgs( self, cline )
4040
! shared-mem commanders
4141
type(commander_refine3D) :: xrefine3D
4242
type(commander_rec3D) :: xrec3D
43+
type(commander_bootstrap_rec3D) :: xbootstrap_rec3D
4344
type(commander_reproject) :: xreproject
4445
! other
4546
type(string) :: stk, orig_stk, shifted_stk, stk_even, stk_odd, ext
@@ -293,7 +294,7 @@ subroutine exec_abinitio3D_cavgs( self, cline )
293294
if( params%nstates > 1 ) call conv_eo_states(work_proj%os_ptcl3D)
294295
call conv_eo(work_proj%os_ptcl3D)
295296
! calculate 3D reconstruction at original sampling
296-
call calc_final_rec(params, work_proj, work_projfile, xrec3D, xrefine3D, l_postprocess=.false.)
297+
call calc_final_rec(params, work_proj, work_projfile, xrec3D, xbootstrap_rec3D, l_postprocess=.false.)
297298
! final raw and low-pass diagnostic 3D reconstruction outputs
298299
call write_final_rec_outputs(params, work_proj, lpinfo(nstages_ini3D)%lp)
299300
! add rec_final to os_out
@@ -506,6 +507,7 @@ subroutine exec_abinitio3D( self, cline )
506507
type(commander_refine3D) :: xrefine3D
507508
type(commander_refine3D_states) :: xrefine3D_states
508509
type(commander_rec3D) :: xrec3D
510+
type(commander_bootstrap_rec3D) :: xbootstrap_rec3D
509511
! other
510512
integer, allocatable :: tmpinds(:), clsinds(:), pinds(:), cls_states(:)
511513
type(class_sample), allocatable :: clssmp(:)
@@ -973,7 +975,7 @@ subroutine exec_abinitio3D( self, cline )
973975
call ensure_multistate_particle_assignments
974976
end select
975977
! calculate 3D reconstruction at original sampling
976-
call calc_final_rec(params, spproj, params%projfile, xrec3D, xrefine3D, l_postprocess=.true.)
978+
call calc_final_rec(params, spproj, params%projfile, xrec3D, xbootstrap_rec3D, l_postprocess=.true.)
977979
! for visualization
978980
call gen_ortho_reprojs4viz(params, spproj)
979981
! final raw and low-pass diagnostic 3D reconstruction outputs

src/main/commanders/simple/simple_commanders_rec.f90

Lines changed: 0 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ module simple_commanders_rec
33
use simple_commanders_api
44
use simple_matcher_2Dprep
55
use simple_matcher_3Drec, only: calc_3Drec, calc_projdir3Drec
6-
use simple_refine3D_fnames, only: refine3D_fsc_fname, refine3D_state_halfvol_fname, refine3D_state_vol_fname
76
use simple_sigma2_files, only: load_sigma2_groups
87
implicit none
98
#include "simple_local_flags.inc"
@@ -13,11 +12,6 @@ module simple_commanders_rec
1312
procedure :: execute => exec_rec3D
1413
end type commander_rec3D
1514

16-
type, extends(commander_base) :: commander_bootstrap_rec3D
17-
contains
18-
procedure :: execute => exec_bootstrap_rec3D
19-
end type commander_bootstrap_rec3D
20-
2115
type, extends(commander_base) :: commander_rec3D_worker
2216
contains
2317
procedure :: execute => exec_rec3D_distr_worker
@@ -59,164 +53,6 @@ subroutine exec_rec3D( self, cline )
5953
if( allocated(strategy) ) deallocate(strategy)
6054
end subroutine exec_rec3D
6155

62-
subroutine exec_bootstrap_rec3D( self, cline )
63-
use simple_commanders_euclid, only: commander_calc_pspec
64-
class(commander_bootstrap_rec3D), intent(inout) :: self
65-
class(cmdline), intent(inout) :: cline
66-
type(commander_rec3D) :: xrec3D
67-
type(commander_calc_pspec) :: xcalc_pspec
68-
type(cmdline) :: cline_reg, cline_pspec
69-
type(parameters) :: params
70-
integer :: state, which_iter
71-
if( .not. cline%defined('mkdir') ) call cline%set('mkdir', 'yes')
72-
call cline%set('oritype', 'ptcl3D')
73-
if( .not. cline%defined('nstates') ) call cline%set('nstates', 1)
74-
call warn_for_forced_bootstrap_overrides(cline)
75-
call cline%set('sigma_est', 'global')
76-
if( .not. cline%defined('which_iter') ) call cline%set('which_iter', 1)
77-
if( .not. cline%defined('postprocess') ) call cline%set('postprocess', 'yes')
78-
if( .not. cline%defined('combine_eo') ) call cline%set('combine_eo', 'no')
79-
if( .not. cline%defined('envfsc') ) call cline%set('envfsc', 'no')
80-
call cline%delete('objfun')
81-
call cline%delete('ml_reg')
82-
call params%new(cline)
83-
which_iter = max(1, params%which_iter)
84-
call cline%set('which_iter', which_iter)
85-
call cline%set('mkdir', 'no') ! child reconstruct3D calls must not create nested run directories
86-
! One sigma2 basis for every bootstrap (2026-09-06): the particle
87-
! power spectra, exactly what a fresh refinement seeds from, written
88-
! as the grouped STAR of which_iter (legacy store) or the registered
89-
! canonical state. The former half-map power estimator sat on a
90-
! different basis than the residual sigmas a refinement then computes
91-
! and conditioned the euclid system markedly worse (bgal residual
92-
! 0.23 vs 0.08, refine3D_auto startup record). With the seed in hand
93-
! the reconstruction is a single euclid ML-regularized pass; callers
94-
! that ship a final map upgrade the seed with a residual pass
95-
! (simple_sigma2_bootstrap).
96-
cline_pspec = cline
97-
call cline_pspec%set('prg', 'calc_pspec')
98-
call cline_pspec%set('mkdir', 'no')
99-
call cline_pspec%set('objfun', 'euclid')
100-
call cline_pspec%set('sigma_est', 'global')
101-
call cline_pspec%set('which_iter', which_iter)
102-
call cline_pspec%delete('postprocess')
103-
call cline_pspec%delete('combine_eo')
104-
call cline_pspec%delete('rec_backend')
105-
call cline_pspec%delete('maxits_pcg')
106-
call cline_pspec%delete('rtol')
107-
call cline_pspec%delete('trail_seed')
108-
call cline_pspec%delete('outfile')
109-
write(logfhandle,'(A,I0)') '>>> BOOTSTRAP_REC3D SIGMA2 FROM PARTICLE POWER SPECTRA, ITERATION ', which_iter
110-
call xcalc_pspec%execute(cline_pspec)
111-
call cline_pspec%kill
112-
cline_reg = cline
113-
call prepare_bootstrap_rec_cline(cline_reg, l_regularized=.true.)
114-
write(logfhandle,'(A)') '>>> BOOTSTRAP_REC3D: EUCLID ML-REGULARIZED RECONSTRUCTION'
115-
call xrec3D%execute(cline_reg)
116-
call register_bootstrap_rec_outputs()
117-
do state = 1, params%nstates
118-
call cline%set('vol'//int2str(state), refine3D_state_vol_fname(state))
119-
enddo
120-
call cline_reg%kill
121-
call simple_end('**** SIMPLE_BOOTSTRAP_REC3D NORMAL STOP ****', print_simple=.false.)
122-
123-
contains
124-
125-
subroutine prepare_bootstrap_rec_cline( cline_rec, l_regularized )
126-
class(cmdline), intent(inout) :: cline_rec
127-
logical, intent(in) :: l_regularized
128-
integer :: state
129-
call cline_rec%set('prg', 'reconstruct3D')
130-
call cline_rec%set('mkdir', 'no')
131-
call cline_rec%set('oritype', params%oritype)
132-
call cline_rec%set('nstates', params%nstates)
133-
call cline_rec%set('sigma_est', 'global')
134-
call cline_rec%set('which_iter', which_iter)
135-
call cline_rec%set('trail_rec', 'no')
136-
call cline_rec%set('combine_eo', 'no')
137-
call cline_rec%delete('refine')
138-
call cline_rec%delete('update_frac')
139-
call cline_rec%delete('fillin')
140-
call cline_rec%delete('objfun_den')
141-
call cline_rec%delete('objfun_den_w')
142-
call cline_rec%delete('ufrac_trec')
143-
call cline_rec%delete('endit')
144-
call cline_rec%delete('vol_even')
145-
call cline_rec%delete('vol_odd')
146-
call cline_rec%delete('refs')
147-
call cline_rec%delete('refs_even')
148-
call cline_rec%delete('refs_odd')
149-
do state = 1, params%nstates
150-
call cline_rec%delete('vol'//int2str(state))
151-
enddo
152-
if( l_regularized )then
153-
call cline_rec%set('objfun', 'euclid')
154-
call cline_rec%set('ml_reg', 'yes')
155-
else
156-
call cline_rec%set('objfun', 'cc')
157-
call cline_rec%set('ml_reg', 'no')
158-
call cline_rec%set('postprocess', 'no')
159-
call cline_rec%set('filt_mode', 'none')
160-
call cline_rec%set('automsk', 'no')
161-
endif
162-
end subroutine prepare_bootstrap_rec_cline
163-
164-
165-
subroutine register_bootstrap_rec_outputs()
166-
type(sp_project) :: spproj
167-
type(string) :: volname, fscname
168-
integer :: state, pop
169-
character(len=16) :: imgkind
170-
call spproj%read_segment('out', params%projfile)
171-
call spproj%read_segment(params%oritype, params%projfile)
172-
select case(trim(params%oritype))
173-
case('cls3D')
174-
imgkind = 'vol_cavg'
175-
case DEFAULT
176-
imgkind = 'vol'
177-
end select
178-
do state = 1, params%nstates
179-
select case(trim(params%oritype))
180-
case('cls3D')
181-
pop = spproj%os_cls3D%get_pop(state, 'state')
182-
case DEFAULT
183-
pop = spproj%os_ptcl3D%get_pop(state, 'state')
184-
end select
185-
if( pop == 0 )cycle
186-
volname = refine3D_state_vol_fname(state)
187-
if( .not. file_exists(volname) )then
188-
call volname%kill
189-
cycle
190-
endif
191-
fscname = refine3D_fsc_fname(state)
192-
! params%box_crop/smpd_crop are the effective reconstruction
193-
! sampling resolved by params%new or explicitly pinned by
194-
! callers that must avoid staged downsampling leakage.
195-
call spproj%add_vol2os_out(volname, params%smpd_crop, state, trim(imgkind), pop=pop)
196-
if( file_exists(fscname) ) call spproj%add_fsc2os_out(fscname, state, params%box_crop)
197-
call volname%kill
198-
call fscname%kill
199-
enddo
200-
call spproj%write_segment_inside('out', params%projfile)
201-
call spproj%kill
202-
end subroutine register_bootstrap_rec_outputs
203-
204-
205-
subroutine warn_for_forced_bootstrap_overrides( cline_in )
206-
class(cmdline), intent(inout) :: cline_in
207-
type(string) :: val
208-
if( cline_in%defined('sigma_est') )then
209-
val = cline_in%get_carg('sigma_est')
210-
if( val%to_char().ne.'global' )then
211-
THROW_WARN('bootstrap_rec3D enforces sigma_est=global; ignoring input sigma_est='//val%to_char())
212-
endif
213-
call val%kill
214-
endif
215-
if( cline_in%defined('objfun') ) THROW_WARN('bootstrap_rec3D controls objfun internally; ignoring input objfun')
216-
if( cline_in%defined('ml_reg') ) THROW_WARN('bootstrap_rec3D controls ml_reg internally; ignoring input ml_reg')
217-
end subroutine warn_for_forced_bootstrap_overrides
218-
end subroutine exec_bootstrap_rec3D
219-
22056
subroutine exec_rec3D_distr_worker( self, cline )
22157
use simple_rec3D_pcg_strategy, only: execute_rec3D_pcg_worker
22258
class(commander_rec3D_worker), intent(inout) :: self

0 commit comments

Comments
 (0)