Skip to content

Fix: timestep loop calculation in error map plotting - #582

Closed
Debadri-das wants to merge 1 commit into
mllam:mainfrom
Debadri-das:fix/520-timestep-loop
Closed

Fix: timestep loop calculation in error map plotting #582
Debadri-das wants to merge 1 commit into
mllam:mainfrom
Debadri-das:fix/520-timestep-loop

Conversation

@Debadri-das

@Debadri-das Debadri-das commented Apr 4, 2026

Copy link
Copy Markdown

Describe your changes

This PR fixes the example-plotting semantics in ARModel.plot_examples() for ensemble / probabilistic predictions.

Summary of the problem

The current plotting path in ARModel.plot_examples() was written for deterministic predictions with per-example shape:

  • (pred_steps, num_grid_nodes, d_f)

That assumption is embedded in how the method:

  • converts tensors to xarray.DataArray
  • indexes time=t_i - 1 during plotting
  • passes 2D spatial slices to vis.plot_prediction()

After the ensemble export work in #521, prediction tensors can now carry an additional ensemble dimension, e.g.:

  • (B, S, T, N, F)

At that point, the example-plotting path no longer has well-defined semantics. The current two-panel plotting interface (Ground Truth vs Prediction) expects a single deterministic prediction field at each lead time, but an ensemble prediction carries multiple members for the same time step.

In other words, the problem is not just that the tensor is “larger”; the problem is that the plotting contract is now ambiguous:

  • should plot_examples() plot one member?
  • all members?
  • an ensemble aggregate?
  • or fail explicitly?

Without resolving that ambiguity, the plotting path forwards data that still contains ensemble structure into code that expects a scalar spatial field, leading to misaligned indexing and eventual failure in plotting.

What this PR changes

This PR defines the semantics of the existing two-panel example plotting path for ensemble predictions by collapsing ensemble forecasts to their ensemble mean before plotting.

Concretely, the fix does the following inside ARModel.plot_examples():

  • detects when the prediction tensor includes an ensemble dimension
  • reduces ensemble predictions from (B, S, T, N, F) to (B, T, N, F) using the ensemble mean
  • preserves the target tensor as the deterministic ground truth field
  • keeps the downstream DataArray conversion and vis.plot_prediction() interface unchanged
  • ensures that time indexing in the plotting loop continues to operate over true lead-time slices rather than over ensemble-structured tensors

Why ensemble mean is the right default here

The current example-plotting utility is a simple two-panel qualitative visualization:

  • left panel: Ground Truth
  • right panel: Prediction

That interface is built around comparing one deterministic forecast field against one target field at each time step.

Using the ensemble mean is the most conservative and compatible way to preserve that interface for probabilistic predictions because:

  1. it yields a deterministic field with the same shape the plotting utilities already expect
  2. it keeps the visualization contract unchanged for existing users
  3. it avoids introducing new UI or semantic questions (e.g. member selection, spread panels, quantiles, uncertainty maps) into a narrow bug-fix PR
  4. it provides a stable default summary of the ensemble while leaving richer ensemble diagnostics for separate visualization tools or future work

Scope of this PR

This PR is intentionally narrow.

It fixes only the semantic mismatch in ARModel.plot_examples() caused by ensemble predictions entering a deterministic plotting path.

It does not attempt to:

  • redesign ensemble visualization in the project
  • add member-wise plotting
  • add spread / uncertainty diagnostics
  • change the external interface of vis.plot_prediction()
  • address unrelated multidimensional reduction issues outside the plotting semantics decision

This means the PR is narrower than:

This PR is specifically about making the existing example plotting path meaningful and stable when predictions carry an ensemble dimension.

Motivation and context

Once 4D/5D ensemble support is introduced into the prediction/export pipeline, evaluation-time plotting becomes a natural follow-up integration point.

plot_examples() is one of the first places where deterministic assumptions surface clearly, because its plotting contract is qualitative and tightly coupled to “one field per lead time.” If that contract is not updated, the code can construct ensemble-aware tensors successfully but still fail during example visualization.

By collapsing to ensemble mean inside plot_examples(), this PR keeps the current plotting workflow operational while making the chosen semantics explicit, minimal, and easy to test.

Test coverage

This PR includes a focused regression test covering the intended semantics:

  • ensemble-shaped predictions are reduced before plotting
  • the prediction artifact used/saved by the example plotting path corresponds to the ensemble mean
  • the plotting pipeline remains compatible with the existing deterministic two-panel interface

Dependencies

No new dependencies are required.

This change uses only the existing project stack:

  • torch
  • numpy
  • xarray
  • existing plotting/test infrastructure

Issue Link

addresses #579

Type of change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📖 Documentation (Addition or improvements to documentation)

Checklist before requesting a review

  • My branch is up-to-date with the target branch - if not update your fork with the changes from the target branch (use pull with --rebase option if possible).
  • I have performed a self-review of my code
  • For any new/modified functions/classes I have added docstrings that clearly describe its purpose, expected inputs and returned values
  • I have placed in-line comments to clarify the intent of any hard-to-understand passages of my code
  • I have updated the README to cover introduced code changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have given the PR a name that clearly describes the change, written in imperative form (context).
  • I have requested a reviewer and an assignee (assignee is responsible for merging). This applies only if you have write access to the repo, otherwise feel free to tag a maintainer to add a reviewer and assignee.

Checklist for reviewers

Each PR comes with its own improvements and flaws. The reviewer should check the following:

  • the code is readable
  • the code is well tested
  • the code is documented (including return types and parameters)
  • the code is easy to maintain

Author checklist after completed review

  • I have added a line to the CHANGELOG describing this change, in a section reflecting type of change (add section where missing):
  • added: when you have added new functionality
  • changed: when default behaviour of the code has been changed
  • fixes: when your contribution fixes a bug
  • maintenance: when your contribution is relates to repo maintenance, e.g. CI/CD or documentation

Checklist for assignee

  • PR is up to date with the base branch
  • the tests pass
  • (if the PR is not just maintenance/bugfix) the PR is assigned to the next milestone. If it is not, propose it for a future milestone.
  • author has added an entry to the changelog (and designated the change as added, changed, fixed or maintenance)
  • Once the PR is ready to be merged, squash commits and merge the PR.

Changes prediction horizon loop to use len(time_slice) instead of enumerating over zipped predictions and targets, preventing indexing errors on ensemble dimensions.

Co-authored-by: GitHub Copilot
@kshirajahere

kshirajahere commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

@Debadri-das i m closely working on this issue and have already created a PR on ur fork for it, just waiting on a merger of ur PR :)

@Debadri-das

Debadri-das commented Apr 5, 2026

Copy link
Copy Markdown
Author

@kshirajahere I’ve merged Debadri-das#1 on my fork, so the stacked change is unblocked now. Feel free to proceed with the next upstream step. You can suggest fixes in this PR too. Thanks.

@Debadri-das Debadri-das closed this Apr 5, 2026
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