Skip to content

Align the data and residuals axes in plots with residuals - #270

Merged
henrikjacobsenfys merged 1 commit into
developfrom
fix/residual-axis-alignment
Oct 20, 2026
Merged

henrikjacobsenfys merged 1 commit into
developfrom
fix/residual-axis-alignment

Conversation

@henrikjacobsenfys

@henrikjacobsenfys henrikjacobsenfys commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Problem

With analysis.plot_data_and_model(plot_residuals=True) the x axes of the data panel and the residuals panel did not line up: the residuals axis started further right than the data axis.

slicerplot_with_residuals drew the residuals in a second Matplotlib figure placed in the widget's bottom bar. plopp runs tight_layout() on each figure independently, so each axis' left margin followed its own y tick labels and y label (10⁻¹ / [dimensionless] vs 0.4 / Residuals [dimensionless]). Both Analysis and Analysis1d go through this function.

Fix

Both panels are now two axes of one Matplotlib figure (sharex=True, height ratio 2:1), passed to plopp via ax= (SlicerPlot(..., ax=main_ax) and pp.linefigure(..., ax=res_ax)). plopp supports several plopp figures sharing one Matplotlib figure and links their home buttons.

Behaviour changes:

  • The axes share x limits, scale and zoom/pan, so the main plot's logX button now applies to the residuals too.
  • The residuals panel hides its own logX/logY buttons: logX is shared, and a log y axis does not suit residuals, which can be negative.
  • figsize now sizes the whole figure. The default (6, 6) keeps the previous 6×4 + 6×2 proportions. Before, a user figsize only resized the main panel.

Measured with the ipympl backend: before, the axes' left edges were at 77.6 px and 87.6 px; after, both span 87.6 → 585.0 px with identical x limits.

Tests

In tests/unit/easydynamics/utils/test_plotting.py:

  • A mocked test checking that both panels share one figure and its x axis, that figsize is passed through (default and custom), and that the residuals' log buttons are hidden.
  • A regression test that renders for real under the ipympl backend (switched in for the test, as in the integration tests) with panels whose y tick labels differ in width, and asserts identical on-screen axis edges and x limits.

The new tests fail on the old code and pass with the fix. pixi run check passes.

Fixes #269

🤖 Generated with Claude Code

slicerplot_with_residuals drew the residuals in a second Matplotlib
figure below the main one. Each figure was tight_layout'ed on its own,
so the axes' left edges depended on each panel's y tick label and y
label widths and did not line up.

Draw both panels as two axes of one figure with a shared x axis, so
they are laid out together and share x limits, scale and zoom. figsize
now sizes the whole figure, and the residuals panel hides its log
buttons, since logX is shared and logY does not suit residuals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@henrikjacobsenfys henrikjacobsenfys added the [scope] bug Bug report or fix (major.minor.PATCH) label Oct 19, 2026
@codecov

codecov Bot commented Oct 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.18%. Comparing base (762b081) to head (2c1033a).
⚠️ Report is 6 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #270      +/-   ##
===========================================
+ Coverage    98.15%   98.18%   +0.03%     
===========================================
  Files           60       60              
  Lines         6066     6067       +1     
  Branches      1022     1022              
===========================================
+ Hits          5954     5957       +3     
+ Misses          58       57       -1     
+ Partials        54       53       -1     
Flag Coverage Δ
unittests 98.18% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/easydynamics/utils/plotting.py 94.11% <100.00%> (+6.23%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@henrikjacobsenfys henrikjacobsenfys added the [priority] medium Normal/default priority label Oct 19, 2026
@henrikjacobsenfys
henrikjacobsenfys merged commit 8ddc07e into develop Oct 20, 2026
35 checks passed
henrikjacobsenfys added a commit that referenced this pull request Oct 20, 2026
* update pixi (#266)

* Adding Chudley-Elliott Jump Diffusion Model (#246)

* Add ChudleyElliotJumpDiffusion model and corresponding tests

* Enhance ChudleyElliotJumpDiffusion model documentation and tests; all checks passed

* Fix: replace Chudley-Elliot with Chudley-Elliott (propegated from spelling mistake in Mantid documentation)

* Fix: Add missing ChudleyElliottJumpDiffusion to public API and module exports

* Fix: Improve test clarity and update unit handling in ChudleyElliottJumpDiffusion tests

* Fix: Implement minimum width for residence time in ChudleyElliottJumpDiffusion model and update tests

* Fix: Update error handling in ChudleyElliottJumpDiffusion model and improve test assertions

* chore: pixi update and linting

* Add jump diffusion tutorials and Chudley-Elliott citation

- Add Jump Translational and Chudley-Elliott sections to
  diffusion_model.ipynb, with subheaders for each model
- Name the models in the Diffusion model entry of the tutorials index
- Add the Chudley and Elliott (1961) reference and "See also the
  tutorials" to the ChudleyElliottJumpDiffusion docstring
- Remove the tutorials TODO (#273)

* Speed up StretchedExponential evaluation (#268)

* Speed up StretchedExponential quadrature 3-4x

Evaluate the exp-sinh quadrature in cache-sized blocks with in-place
temporaries, and drop nodes whose decaying exponent provably underflows
exp to exactly zero. Results are unchanged to rounding and stay bitwise
independent of block boundaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Interpolate the StretchedExponential profile by default

Add an interpolate flag (default True) that evaluates G_beta from a
cached cubic-spline table of log(G / G(0)) on y = asinh(w / w_ref)
instead of running the quadrature at every energy. Tables are cached
per beta and grow on a fixed lattice, so fits stay smooth under
finite-difference Jacobian steps. Accuracy is ~1e-7 of the peak for all
beta; interpolate=False keeps the ~1e-11 quadrature.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add example, run pixi update

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Allow plotting parameters against Q^2 (#271)

* Allow plotting parameters against Q^2

Analysis.plot_parameters and ParameterAnalysis.plot take an x_axis
argument ('Q' or 'Q^2'). The values at each Q are unchanged; only the
plotted coordinate is transformed, via the shared add_x_axis_coord
helper and its Q_AXIS_TRANSFORMS table, so further axes are one entry.

Closes #205

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Show the Lorentzian width against Q^2 in tutorial 1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Align the data and residuals axes in plots with residuals (#270)

slicerplot_with_residuals drew the residuals in a second Matplotlib
figure below the main one. Each figure was tight_layout'ed on its own,
so the axes' left edges depended on each panel's y tick label and y
label widths and did not line up.

Draw both panels as two axes of one figure with a shared x axis, so
they are laid out together and share x limits, scale and zoom. figsize
now sizes the whole figure, and the residuals panel hides its log
buttons, since logX is shared and logY does not suit residuals.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: easyscience[bot] <2476259+easyscience[bot]@users.noreply.github.com>
Co-authored-by: Henrik Jacobsen <henrik.jacobsen.fys@gmail.com>
Co-authored-by: mark <191927387+markbujehein@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[priority] medium Normal/default priority [scope] bug Bug report or fix (major.minor.PATCH)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant