Skip to content

Whitening filter rework#359

Merged
McHaillet merged 13 commits into
SBC-Utrecht:mainfrom
McHaillet:whitening-filter-rework
Jul 16, 2026
Merged

Whitening filter rework#359
McHaillet merged 13 commits into
SBC-Utrecht:mainfrom
McHaillet:whitening-filter-rework

Conversation

@McHaillet

@McHaillet McHaillet commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Main things happening here is a rework of whitening filter estimation:

  • it now happens in small patches of size max(template.shape[0], 64) that are tiled over the tomogram
  • this allows rejection of patches with very high variance that likely contain gold beads or other contamination and don't contribute a correct estimate of the power spectrum
  • the power spectrum calculation now includes a tilt mask so that regions of the missing wedge and other 0 data areas are taken into account in calculating the power spectrum, which should give a more accurate estimate

Side things:

  • 1D support for reduced_radial_grid, and bandpass, lowpass and highpass filters
  • changed the interpolation in profile_to_weighting to ensure nyquist frequency is always the last interpolated values + explicitly zero the DC component

This is an example of the old and new whitening filter. Main things to note is that its a lot smoother due to the small patch size and averaging over patches. The new filter also more strongly up weights high frequencies, owing to the better estimate from the tilt mask:

whitening_filter

McHaillet and others added 6 commits July 15, 2026 14:40
- Support 1D shapes in radial_reduced_grid/create_gaussian_*_pass so the
  bandpass filter chain can be applied directly to a 1D radial profile.
- Replace radial_average/power_spectrum_profile with estimate_whitening_filter,
  which estimates the noise power spectrum on overlapping, windowed, mean-
  subtracted patches, masked to only the Fourier voxels actually sampled by
  the tilt series (via create_wedge with CTF/dose stripped from the
  metadata), rejecting the highest-variance patches and returning an
  already-transformed whitening filter (1/sqrt, DC zeroed, high-frequency
  tapered, normalized).
- Wire TMJob to call estimate_whitening_filter directly instead of manually
  transforming a raw power spectrum profile.
- Fix an off-by-one in profile_to_weighting's map_coordinates interpolation
  that rolled the near-Nyquist weights off toward 0, and zero the DC
  component of the returned weighting.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Use max(template_shape[0], 64) instead of a fixed 64 so larger template
boxes get a correspondingly larger estimation patch, still clamped to the
smallest search region dimension.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replace the hand-rolled fftfreq/rfftfreq radial-distance computation with
radial_reduced_grid, matching the normalized-frequency convention already
used by the bandpass filters, CTF, and wedge in this module. This also
fixes a small inconsistency for odd patch sizes, where the fftfreq-based
Nyquist normalization diverged from radial_reduced_grid's convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Match the numpydoc formatting used elsewhere in weights.py: single-line
opening summary, single spaces after periods, Optional[type] for None
defaults, and no trailing periods on single-sentence parameter entries.
No behavior change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@McHaillet
McHaillet requested a review from sroet July 15, 2026 14:06
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

File Coverage Missing
All files 95%
src/pytom_tm/extract.py 98% 315-319
src/pytom_tm/io.py 89% 26 46 62 98 130-136 157-161 168 187 224 229 276-278 348 524-532 557
src/pytom_tm/parallel.py 97% 15-16
src/pytom_tm/plotting.py 33% 35-43 47-50 53-69 76-77 97-102 118-126 132-149 164-172 176-193 197-205 209-216 222 228 233 280 303-385 393 396
src/pytom_tm/weights.py 97% 61 303-307 556 561 566 825
tests/test_angles.py 96% 66-67

Minimum allowed coverage is 94%

Generated by 🐒 cobertura-action against a226ded

@sroet sroet left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a nice improvement

I do have quite some comments and questions, and you're missing some coverage.

Comment thread src/pytom_tm/tmjob.py
Comment thread src/pytom_tm/weights.py Outdated
Comment thread src/pytom_tm/weights.py Outdated
Comment thread src/pytom_tm/weights.py Outdated
Comment thread src/pytom_tm/tmjob.py Outdated
Comment thread src/pytom_tm/weights.py Outdated
Comment thread src/pytom_tm/weights.py Outdated
Comment thread src/pytom_tm/weights.py
Comment thread src/pytom_tm/weights.py Outdated
Comment thread src/pytom_tm/weights.py Outdated
McHaillet and others added 2 commits July 16, 2026 11:24
Co-authored-by: Sander Roet <sanderroet@hotmail.com>
- Reject non-cubic templates with a clear error (tmjob.py)
- Use keyword arguments for estimate_whitening_filter call
- Use int steps instead of float in radial_reduced_grid's np.arange calls
- Drop the unused exclude/focus-mask parameter from estimate_whitening_filter
- Fix step rounding to avoid Python's banker's rounding
- Simplify patch rejection: drop the silent auto-turnoff fallback, raise
  RuntimeError only when zero patches survive
- Correct _patch_slices axis naming to match pytom's internal xyz convention
- Raise instead of silently leaving NaNs when too few radial shells are valid
- Add/extend tests for the above, including previously uncovered branches
  (_masked_radial's new error path and the statistic="mean" code path)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@McHaillet

Copy link
Copy Markdown
Collaborator Author

Addressed all the comments!

@McHaillet
McHaillet requested a review from sroet July 16, 2026 10:37
@McHaillet

Copy link
Copy Markdown
Collaborator Author

Merged the radial_grid rework into this now!

@sroet sroet left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small comment left (assuming all changed lines are hit by tests now). Will not need another round of review

Comment thread src/pytom_tm/weights.py Outdated
Co-authored-by: Sander Roet <sanderroet@hotmail.com>
@McHaillet
McHaillet merged commit 27f5d68 into SBC-Utrecht:main Jul 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants