Skip to content

Add F.plot(...) for one-line PyVista field visualization#1176

Open
RemDelaporteMathurin with Copilot wants to merge 23 commits into
mainfrom
copilot/basic-functionality-plotting-fields
Open

Add F.plot(...) for one-line PyVista field visualization#1176
RemDelaporteMathurin with Copilot wants to merge 23 commits into
mainfrom
copilot/basic-functionality-plotting-fields

Conversation

Copilot AI commented Jun 23, 2026

Copy link
Copy Markdown

Description

Summary

This PR adds a lightweight plotting API for species fields so users can generate PyVista visuals in one line, including multi-species and subdomain-aware cases.

  • API surface
    • Added public F.plot(...) entrypoint (src/festim/plot.py, exported via src/festim/__init__.py).
  • Core behavior
    • Supports single species and list input (auto subplot layout).
    • Supports subdomain=... for mixed-domain/discontinuous workflows.
    • Supports filename=... for screenshot output and show_edges=True shortcut.
    • Forwards extra mesh args via **kwargs to plotter.add_mesh(...).
  • Robustness
    • Clear errors for invalid field types, missing post-processing solutions, and missing optional pyvista dependency.
  • Tests
    • Added focused unit tests in test/test_plot.py covering API behavior, edge cases, and error paths.

Related Issues

Handled by automatic issue linking in the PR system.

Motivation and Context

Plotting fields with PyVista currently requires repetitive boilerplate (vtk_mesh, grid wiring, plotter setup). This change introduces a small wrapper to make field visualization immediate while preserving control through optional arguments.

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 🔨 Code refactoring (no functional changes, no API changes)
  • 📝 Documentation update
  • ✅ Test update (adding missing tests or correcting existing tests)
  • 🔧 Build/CI configuration change

Testing

  • All existing tests pass locally (pytest)
  • I have added new tests that prove my fix is effective or that my feature works

Code Quality Checklist

  • My code follows the code style of this project (Ruff formatted: ruff format .)
  • My code passes linting checks (ruff check .)
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas

Documentation

  • I have updated the documentation accordingly (if applicable)
  • I have added docstrings to new functions/classes following the project conventions

Breaking Changes

None.

Screenshots/Examples

import festim as F

H = F.Species("H")
D = F.Species("D")

F.plot(H)                              # default quick view
F.plot(H, subdomain=vol1)              # mixed-domain: specific subdomain
F.plot([H, D], show_edges=True)        # automatic subplots
F.plot(H, filename="concentration.png")  # save screenshot

Additional Notes

This PR keeps scope intentionally narrow: one public plotting helper plus focused tests around that API surface.

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.65517% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.68%. Comparing base (9a6407b) to head (4a4d206).

Files with missing lines Patch % Lines
src/festim/plotting.py 89.47% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1176      +/-   ##
==========================================
- Coverage   94.76%   94.68%   -0.09%     
==========================================
  Files          46       47       +1     
  Lines        3534     3592      +58     
==========================================
+ Hits         3349     3401      +52     
- Misses        185      191       +6     

☔ View full report in Codecov by Harness.
📢 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.

Copilot AI changed the title [WIP] Add basic functionality for plotting fields with pyvista Add F.plot(...) for one-line PyVista field visualization Jun 23, 2026
@RemDelaporteMathurin RemDelaporteMathurin marked this pull request as ready for review June 24, 2026 13:03
@RemDelaporteMathurin

Copy link
Copy Markdown
Collaborator

@ck768 @jhdark @hhy2022 would one of you mind having a look at these modifications?

Comment thread src/festim/plotting.py
Comment on lines +70 to +75
try:
import pyvista
except ImportError as import_error:
raise ImportError(
"pyvista is required for plotting. Install it with `pip install pyvista`."
) from import_error

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.

We're already importing pyvista in the conda env; maybe we could just make it a requirement in the pyproject.toml as well, and add it to the festim-feedstock conda recipe too?

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.

which conda env? as in it's a dependency inthe FESTIM conda-forge recipe?

Comment thread src/festim/plotting.py Outdated
Comment thread src/festim/plotting.py
Comment on lines +23 to +37
else:
if field.post_processing_solution is not None:
raise ValueError(
"Problem seems to be HydrogenTransportProblem but a subdomain"
" was provided."
)
if not field.subdomain_to_post_processing_solution:
raise ValueError(
f"Species {field.name} has no subdomain post-processing solutions."
)
if subdomain not in field.subdomain_to_post_processing_solution:
raise ValueError(
f"Species {field.name} has no post-processing solution on subdomain "
f"{subdomain}."
)

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.

We could write some quick, simple tests to make sure these get raised, and that errors are not raised beforehand elsewhere

Comment thread src/festim/plotting.py
return field.subdomain_to_post_processing_solution[subdomain]


def _make_ugrid(solution, pyvista_module, name="c"):

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.

Even its a hidden method, could use some doc strings

Comment thread src/festim/plotting.py Outdated
raise TypeError("field must be of type festim.Species or a list of festim.Species")


def _get_solution(field: Species, subdomain=None):

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.

Doc strings

Comment thread src/festim/plotting.py
DEFAULT_TITLE_FONT_SIZE = 12


def _normalize_fields(field: Species | list[Species]) -> list[Species]:

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.

Doc strings

@jhdark jhdark 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.

Just some minor changes from me

Comment thread src/festim/plotting.py

from festim.species import Species

DEFAULT_TITLE_FONT_SIZE = 12

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.

This is only used in one place, dont think its needed

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 would keep it here as 1. we may use it in other places 2. it helps keep the "config" variables easily accessible

Co-authored-by: James Dark <65899899+jhdark@users.noreply.github.com>
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.

3 participants