fit_annuli: plots=None renders all panels (can't disable via None) and leaks Matplotlib figures in loops
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- matplotlib, numpy, python
- Domain
- data-visualization
Research direction
Start in eddy/rotationmap.py at fit_annuli around line 534, then inspect plot_velocity_profiles, plot_model, and plot_model_residual around the referenced plotting code. Run the 30-call reproduction and compare plots=None, plots=[], and the documented options. Done means the plots argument behavior, figure lifecycle, and docstring agree without accumulating open figures.
Written by the indexing model from the issue text.
Description
Summary
In rotationmap.fit_annuli, the plots argument defaults to None, but None is
interpreted as "plot all panels" rather than "plot nothing". To suppress plotting you
have to pass plots=[], which is neither documented nor obvious. Because the plotting
helpers open figures without closing them, calling fit_annuli in a loop (e.g. a
Monte-Carlo over many maps) leaks a figure per call — triggering matplotlib's
More than 20 figures have been opened warning and growing memory unbounded.
Version
eddy 3.1.0, eddy/rotationmap.py.
Where
# eddy/rotationmap.py, fit_annuli, ~L534
plots = ['profiles', 'model', 'residual'] if plots is None else plots
plots = np.atleast_1d(plots)
if 'profiles' in plots:
self.plot_velocity_profiles(rpnts=rpnts, velo=velo, dvelo=dvelo)
if 'model' in plots:
self.plot_model(model=model)
if 'residual' in plots:
self.plot_model_residual(model=model)
Each of plot_velocity_profiles / plot_model / plot_model_residual does
fig, ax = plt.subplots() (e.g. rotationmap.py:2321) and never closes the figure.
Reproduce
import matplotlib.pyplot as plt
# rmap = some rotationmap / momentmap with a fittable map
for i in range(30):
rmap.fit_annuli(x0=0, y0=0, inc=inc, PA=PA, rbins=rbins,
fit_vrad=True, fix_vlsr=vlsr, returns='residual') # plots=None
print(len(plt.get_fignums())) # ~90 open figures (3 per call); RuntimeWarning fires at 20
Expected vs. actual
- Expected:
plots=None(the default) produces no plots — the conventional meaning of
an optionalplots/plotkwarg — and repeated calls do not accumulate figures. - Actual:
plots=Nonerenders all three panels every call, and the figures are never
closed, so a loop leaks figures and eventually warns / risks OOM.
Secondary: docstring mismatch
The docstring says:
plots (Optional[list]): Plots to generate after the fitting. Can be either of'model'
and'residual'. Default is both.
But the code default is three panels including 'profiles', and 'profiles' is a
valid (undocumented) option.
Suggested fix (your call)
- Treat a falsy
plots(None/[]/False) as no plots; if plot-by-default is
wanted, use an explicit default list instead of theNonesentinel. - Close the figures after drawing (or return them) so loop callers don't leak — or gate
plotting behind an explicitplot=True. - Update the docstring to list
'profiles'and state the actual default.
Workaround
Pass plots=[] to suppress plotting.
- Dominant language
- Python
- Stars
- 23
- Forks
- 10
- Avg merge
- 28m
- Merged PRs (30d)
- 1
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from PlanetFormationLab/eddy
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
PlanetFormationLab/eddy#36 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 78/100
PlanetFormationLab/eddy#39 ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
PlanetFormationLab/eddy#34 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
PlanetFormationLab/eddy#33 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 48/100
PlanetFormationLab/eddy#32 ·
All issues in PlanetFormationLab/eddy
Similar issues
-
New InternshipOpennew_internship
Difficulty 1/5 Under an hour Newbie friendliness 70/100
-
[BUG] Reports tab: "Unban" button tooltip shows raw `{{ip}}` placeholder instead of the IP addressOpenbug javascript ui
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
bunkerity/bunkerweb#4001 · 1 comment ·
Maintainers usually reply within 1 day
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 92/100
PedestrianDynamics/pyFDS-Evac#476 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
google/differential-privacy#516 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
adobe-fonts/source-serif#153 ·