Skip to content

Commit 769ae5a

Browse files
ianhiclaude
andcommitted
Feature: Add fig.canvas.download() for programmatic downloads
- Add public download() method to Canvas class - Allows triggering downloads from Python code without clicking button - Respects all savefig rcParams like the toolbar button - Includes comprehensive docstring with examples - Add test file demonstrating programmatic usage Use cases: - Batch downloading multiple figures - Automated workflows - Custom save logic in notebooks Example: fig, ax = plt.subplots() ax.plot([1, 2, 3]) fig.canvas.download() # Triggers browser download Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 31e24d1 commit 769ae5a

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

ipympl/backend_nbagg.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,32 @@ def send_binary(self, data):
331331
# Actually send the data
332332
self.send({'data': '{"type": "binary"}'}, buffers=[data])
333333

334+
def download(self):
335+
"""
336+
Trigger a download of the figure respecting savefig rcParams.
337+
338+
This is a programmatic way to trigger the same download that happens
339+
when the user clicks the Download button in the toolbar.
340+
341+
The figure will be saved using all applicable savefig.* rcParams
342+
including format, dpi, transparent, facecolor, etc.
343+
344+
Examples
345+
--------
346+
>>> fig, ax = plt.subplots()
347+
>>> ax.plot([1, 2, 3], [1, 4, 2])
348+
>>> fig.canvas.download() # Downloads with current rcParams
349+
350+
>>> # Download as PDF
351+
>>> plt.rcParams['savefig.format'] = 'pdf'
352+
>>> fig.canvas.download()
353+
354+
>>> # Download with custom DPI
355+
>>> plt.rcParams['savefig.dpi'] = 300
356+
>>> fig.canvas.download()
357+
"""
358+
self._send_save_buffer()
359+
334360
def _send_save_buffer(self):
335361
"""Generate figure buffer respecting savefig rcParams and send to frontend."""
336362
buf = io.BytesIO()

test_programmatic_download.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
Test programmatic download using fig.canvas.download()
3+
4+
This demonstrates the new public API for triggering downloads from Python code
5+
without clicking the toolbar button.
6+
"""
7+
8+
# This would be run in a Jupyter notebook with %matplotlib ipympl
9+
import matplotlib
10+
matplotlib.use('module://ipympl.backend_nbagg')
11+
12+
import matplotlib.pyplot as plt
13+
import numpy as np
14+
15+
# Example 1: Simple programmatic download
16+
print("Example 1: Simple download")
17+
fig, ax = plt.subplots()
18+
ax.plot([1, 2, 3], [1, 4, 2])
19+
ax.set_title('Programmatic Download Test')
20+
21+
# Trigger download programmatically - no button click needed!
22+
fig.canvas.download()
23+
print(" -> Downloads as PNG (default format)")
24+
25+
# Example 2: Download as PDF
26+
print("\nExample 2: Download as PDF")
27+
plt.rcParams['savefig.format'] = 'pdf'
28+
29+
fig, ax = plt.subplots()
30+
ax.plot(np.linspace(0, 10, 100), np.sin(np.linspace(0, 10, 100)))
31+
ax.set_title('PDF Download')
32+
33+
fig.canvas.download()
34+
print(" -> Downloads as PDF")
35+
36+
# Example 3: Batch download multiple figures
37+
print("\nExample 3: Batch download 3 figures")
38+
plt.rcParams['savefig.format'] = 'png'
39+
40+
for i in range(3):
41+
fig, ax = plt.subplots()
42+
ax.plot(np.random.randn(50))
43+
ax.set_title(f'Figure {i+1}')
44+
fig.canvas.download()
45+
print(f" -> Downloaded Figure {i+1}")
46+
47+
# Example 4: Download with custom settings
48+
print("\nExample 4: Custom DPI and transparent background")
49+
plt.rcParams['savefig.dpi'] = 150
50+
plt.rcParams['savefig.transparent'] = True
51+
52+
fig, ax = plt.subplots()
53+
ax.scatter(np.random.randn(100), np.random.randn(100))
54+
ax.set_title('High-res Transparent')
55+
56+
fig.canvas.download()
57+
print(" -> Downloads as 150 DPI PNG with transparent background")
58+
59+
print("\n✅ All programmatic downloads triggered!")
60+
print("Check your Downloads folder for the files.")

0 commit comments

Comments
 (0)