Skip to content

Conversation

@jank324
Copy link
Member

@jank324 jank324 commented Dec 9, 2025

Description

All plotting functions in Segment now accept an optional axes or figure object. If they are passed on, they use it, otherwise they create one themselves. Either way, they return the axes or figure they used.

Motivation and Context

  • I have raised an issue to propose this change (required for new features and bug fixes)

Closes #601.

This is the interface used by Seaborn and makes it very convenient to use these functions on their own, or to fill already created plots. It also improves compatibility with other interactive Python editors (see #601).

Types of changes

  • 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 change)
  • Documentation (update in the documentation)

Checklist

  • I have updated the changelog accordingly (required).
  • My change requires a change to the documentation.
  • I have updated the tests accordingly (required for a bug fix or a new feature).
  • I have updated the documentation accordingly.
  • I have reformatted the code and checked that formatting passes (required).
  • I have have fixed all issues found by flake8 (required).
  • I have ensured that all pytest tests pass (required).
  • I have run pytest on a machine with a CUDA GPU and made sure all tests pass (required).
  • I have checked that the documentation builds (required).

Note: We are using a maximum length of 88 characters per line.

@jank324 jank324 linked an issue Dec 9, 2025 that may be closed by this pull request
@jank324 jank324 added the enhancement New feature or request label Dec 9, 2025
@jank324 jank324 requested review from Hespe and Copilot December 9, 2025 10:40
@jank324 jank324 marked this pull request as ready for review December 9, 2025 10:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR standardizes the plotting interface for all Segment plot functions to accept optional axes or figure objects and return the axes/figure they used, following a pattern similar to Seaborn. This improves compatibility with interactive Python editors and makes the functions more flexible.

Key Changes

  • Modified parameter order to move optional ax/fig/axx/axy parameters to the end for better consistency
  • All plot functions now return the figure or axes object they used
  • Enhanced docstrings to document the new optional parameters and return values

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.

File Description
cheetah/accelerator/segment.py Updated five plotting methods (plot_mean_and_std, plot_overview, plot_beam_attrs_over_lattice, plot_twiss, plot_twiss_over_lattice) to accept optional figure/axes parameters and return the figure/axes used
CHANGELOG.md Added entry documenting the new plotting interface feature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

vector_idx: tuple | None = None,
figsize=(8, 4),
fig: matplotlib.figure.Figure | None = None,
) -> None:
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The return type annotation is None, but the function now returns a matplotlib.figure.Figure object. This should be updated to matplotlib.figure.Figure.

Suggested change
) -> None:
) -> matplotlib.figure.Figure:

Copilot uses AI. Check for mistakes.
incoming: Beam,
figsize=(8, 4),
fig: matplotlib.figure.Figure | None = None,
) -> None:
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The return type annotation is None, but the function now returns a matplotlib.figure.Figure object. This should be updated to matplotlib.figure.Figure.

Suggested change
) -> None:
) -> matplotlib.figure.Figure:

Copilot uses AI. Check for mistakes.
Comment on lines +827 to +828
if fig is None:
fig = plt.figure(figsize=figsize)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The figsize parameter is only used when creating a new figure (fig is None). If a user provides an existing fig, the figsize parameter will be silently ignored. Consider either:

  1. Documenting that figsize is ignored when fig is provided
  2. Raising a warning or error if both fig and a non-default figsize are provided
  3. Removing figsize from the parameter list and documenting that users should create their figure with the desired size if they want to customize it

Copilot uses AI. Check for mistakes.
Comment on lines +896 to +897
if fig is None:
fig = plt.figure(figsize=figsize)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The figsize parameter is only used when creating a new figure (fig is None). If a user provides an existing fig, the figsize parameter will be silently ignored. Consider either:

  1. Documenting that figsize is ignored when fig is provided
  2. Raising a warning or error if both fig and a non-default figsize are provided
  3. Removing figsize from the parameter list and documenting that users should create their figure with the desired size if they want to customize it

Copilot uses AI. Check for mistakes.
axx.set_xlabel("s (m)")
axy.set_ylabel("y (m)")

return fig
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The function returns fig unconditionally, but fig is only defined when axx is None or axy is None. When existing axes are passed in, fig will be undefined, causing a NameError.

Consider one of these approaches:

  1. Return a tuple of (fig, axx, axy) or (axx, axy) instead of just the figure
  2. Store fig = None before the conditional and return it (allowing None as a return value)
  3. Get the figure from the axes: fig = axx.get_figure() when axes are provided

Copilot uses AI. Check for mistakes.
vector_idx: tuple | None = None,
axx: plt.Axes | None = None,
axy: plt.Axes | None = None,
) -> None:
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The return type annotation is None, but the function now returns a matplotlib.figure.Figure object. This should be updated to matplotlib.figure.Figure or matplotlib.figure.Figure | None depending on the intended behavior when axes are provided.

Suggested change
) -> None:
) -> plt.Figure | None:

Copilot uses AI. Check for mistakes.
resolution: float | None = None,
vector_idx: tuple | None = None,
fig: matplotlib.figure.Figure | None = None,
) -> None:
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The return type annotation is None, but the function now returns a matplotlib.figure.Figure object. This should be updated to matplotlib.figure.Figure.

Suggested change
) -> None:
) -> matplotlib.figure.Figure:

Copilot uses AI. Check for mistakes.
vector_idx: tuple | None = None,
axx: plt.Axes | None = None,
axy: plt.Axes | None = None,
) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Missing returntype

resolution: float | None = None,
vector_idx: tuple | None = None,
fig: matplotlib.figure.Figure | None = None,
) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Returntype

figsize=(8, 4),
resolution: float | None = None,
vector_idx: tuple | None = None,
figsize=(8, 4),
Copy link
Member

Choose a reason for hiding this comment

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

Is the figsize argument still relevant if we return the created figure at the end?

vector_idx: tuple | None = None,
figsize=(8, 4),
fig: matplotlib.figure.Figure | None = None,
) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Returntype

Comment on lines +884 to +886
figsize=(8, 4),
fig: matplotlib.figure.Figure | None = None,
) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Same comment about figsize and the return type as above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

plot_overview only supports jupyter

3 participants