Skip to content

Conversation

@derollins
Copy link
Owner

PR Summary

Using a MATLAB test script that runs Python functions within it, I've tried to align the output
of the Python verison of the Nanolocz library with the output of the Python verison.

This PR substantially improves MATLAB alignment, correctness, and documentation
of the Python NanoLocz leveling pipeline, with a particular focus on mask semantics,
numerical parity, and automated routines.

Key changes

1. MATLAB-aligned mask semantics across all leveling methods

  • All masks generated by the thresholder module generate exclusion masks (True = excluded)
    where data is 'masked' or edges highlighted, this sets the interpretation for downstream functions.
  • Introduced a shared _validity_mask helper to consistently convert public
    exclusion masks (True = excluded) into internal validity masks
    (True = valid).
  • All levelling methods now use NaN-outside semantics during fitting,
    matching MATLAB behaviour more closely and eliminating subtle inconsistencies
    between methods.

2. Numerical parity improvements in core levelling routines (level.py)

  • Switched all polynomial fitting to 1-based indexing and population
    standard deviation (ddof=0)
    , matching MATLAB’s polyfit(..., mu) behaviour.
  • Reworked plane, line, med_line, med_line_y, smed_line, and
    mean_plane to:
    • Fit only over valid pixels
    • Handle low-sample fallback cases explicitly
    • Preserve excluded pixels in outputs
  • Clarified and documented MATLAB-specific behaviours such as stage gating
    (polyy > 0) and median fallback logic.

3. Correct and complete implementation of automated routines (level_auto.py)

  • Fully implemented multi-plane-edges and multi-plane-otsu, replacing
    “not yet implemented” placeholders.
  • Restored missing MATLAB steps (e.g. second histogram → plane passes) that were
    previously absent, resolving observed discrepancies.
  • Added anisotropy-gated med_line preconditioning, mirroring MATLAB’s
    adaptive behaviour.
  • Implemented MATLAB-style Gaussian histogram fitting (gauss1) for adaptive
    threshold bounds, with explicit documentation of the remaining frame-wise vs
    stack-wise difference.

4. API clean-up and consistency

  • Standardized public thresholding entry point to apply_thresholder
    (updated README and internal usage).
  • Ensured consistent function contracts across level, level_weighted,
    thresholder, and level_auto.

5. Documentation and citation improvements

  • Added a CITATION.cff file to support proper software citation.
  • Expanded and standardized module-level docstrings in level.py and
    level_auto.py, clearly documenting MATLAB alignment goals and known
    deviations.
  • Updated README to:
    • Reflect newly implemented routines
    • Clarify usage patterns
    • Include a software citation alongside the NanoLocz paper

Overall impact

This PR moves the Python NanoLocz library from “functionally similar” to
algorithmically aligned with the MATLAB reference, especially for automated
Levelling workflows. It reduces hidden numerical drift, clarifies intended
Behaviour, and makes future validation and extension much easier.

…s have beeen updated to bettter align with the matlab verison (NanoLocz library). True-False convetion has also been aligned. Docstrings at all levels have been updated to explain the alignment with matlab and where differences may remain. Expect test breakage.
…s where True reprisents the pixels to be excluded from leveling in level and level_weighted and False is valid/included pixels. Updated docstrings to reflect this too.
…were aligned with the MATLAB funciton, updated so that masks from threshold work correctly and docstrings updated.
…ing and also calculating gaussian limits and well as updateing some routines to match the matlab Nanolocz
@derollins derollins self-assigned this Jan 12, 2026
@codecov
Copy link

codecov bot commented Jan 12, 2026

Codecov Report

❌ Patch coverage is 88.41762% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.55%. Comparing base (1658c90) to head (43109f7).
⚠️ Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
src/pnanolocz_lib/thresholder.py 77.54% 42 Missing ⚠️
src/pnanolocz_lib/level.py 90.64% 13 Missing ⚠️
src/pnanolocz_lib/level_auto.py 87.20% 11 Missing ⚠️
src/pnanolocz_lib/level_weighted.py 97.51% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main       #6      +/-   ##
==========================================
- Coverage   96.64%   90.55%   -6.10%     
==========================================
  Files           5        5              
  Lines         776      942     +166     
==========================================
+ Hits          750      853     +103     
- Misses         26       89      +63     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@derollins derollins merged commit aa595b8 into main Jan 14, 2026
10 of 12 checks passed
@derollins derollins deleted the align_with_matlab branch January 14, 2026 16:46
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.

1 participant