|
6 | 6 | from tempfile import TemporaryDirectory
|
7 | 7 |
|
8 | 8 | try:
|
9 |
| - from IPython.display import Image |
10 |
| -except ImportError: |
11 |
| - Image = None |
| 9 | + import IPython |
| 10 | +except KeyError: |
| 11 | + IPython = None # pylint: disable=invalid-name |
| 12 | + |
12 | 13 |
|
13 | 14 | from pygmt.clib import Session
|
14 | 15 | from pygmt.exceptions import GMTError, GMTInvalidInput
|
|
25 | 26 | # This is needed for the sphinx-gallery scraper in pygmt/sphinx_gallery.py
|
26 | 27 | SHOWED_FIGURES = []
|
27 | 28 |
|
| 29 | +# Configurations for figure display |
| 30 | +SHOW_CONFIG = { |
| 31 | + "method": "external", # Open in an external viewer by default |
| 32 | +} |
| 33 | + |
| 34 | +# Show figures in Jupyter notebooks if available |
| 35 | +if IPython: |
| 36 | + get_ipython = IPython.get_ipython() # pylint: disable=invalid-name |
| 37 | + if get_ipython and "IPKernelApp" in get_ipython.config: # Jupyter Notebook enabled |
| 38 | + SHOW_CONFIG["method"] = "notebook" |
| 39 | + |
| 40 | +# Set environment variable PYGMT_USE_EXTERNAL_DISPLAY to 'false' to disable |
| 41 | +# external display. Use it when running the tests and building the docs to |
| 42 | +# avoid popping up windows. |
| 43 | +if os.environ.get("PYGMT_USE_EXTERNAL_DISPLAY", "true").lower() == "false": |
| 44 | + SHOW_CONFIG["method"] = "none" |
| 45 | + |
28 | 46 |
|
29 | 47 | class Figure:
|
30 | 48 | """
|
@@ -235,62 +253,72 @@ def savefig(
|
235 | 253 | if show:
|
236 | 254 | launch_external_viewer(fname)
|
237 | 255 |
|
238 |
| - def show(self, dpi=300, width=500, method="static"): |
| 256 | + def show(self, dpi=300, width=500, method=None): |
239 | 257 | """
|
240 | 258 | Display a preview of the figure.
|
241 | 259 |
|
242 |
| - Inserts the preview in the Jupyter notebook output. You will need to |
243 |
| - have IPython installed for this to work. You should have it if you are |
244 |
| - using the notebook. |
| 260 | + Inserts the preview in the Jupyter notebook output if available, |
| 261 | + otherwise opens it in the default viewer for your operating system |
| 262 | + (falls back to the default web browser). |
| 263 | +
|
| 264 | + :func:`pygmt.set_display` can select the default display method |
| 265 | + (**notebook**, **external**, or **none**). |
| 266 | +
|
| 267 | + The ``method`` parameter can also override the default display method |
| 268 | + for the current figure. Parameters ``dpi`` and ``width`` can be used |
| 269 | + to control the resolution and dimension of the figure in the notebook. |
| 270 | +
|
| 271 | + Note: The external viewer can be disabled by setting the |
| 272 | + PYGMT_USE_EXTERNAL_DISPLAY environment variable to **false**. |
| 273 | + This is useful when running unit tests and building the documentation |
| 274 | + in consoles without a Graphical User Interface. |
245 | 275 |
|
246 |
| - If ``method='external'``, makes PDF preview instead and opens it in the |
247 |
| - default viewer for your operating system (falls back to the default web |
248 |
| - browser). Note that the external viewer does not block the current |
249 |
| - process, so this won't work in a script. |
| 276 | + Note that the external viewer does not block the current process. |
250 | 277 |
|
251 | 278 | Parameters
|
252 | 279 | ----------
|
253 | 280 | dpi : int
|
254 |
| - The image resolution (dots per inch). |
| 281 | + The image resolution (dots per inch) in Jupyter notebooks. |
255 | 282 | width : int
|
256 |
| - Width of the figure shown in the notebook in pixels. Ignored if |
257 |
| - ``method='external'``. |
| 283 | + The image width (in pixels) in Jupyter notebooks. |
258 | 284 | method : str
|
259 |
| - How the figure will be displayed. Options are (1) ``'static'``: PNG |
260 |
| - preview (default); (2) ``'external'``: PDF preview in an external |
261 |
| - program. |
| 285 | + How the current figure will be displayed. Options are |
262 | 286 |
|
263 |
| - Returns |
264 |
| - ------- |
265 |
| - img : IPython.display.Image |
266 |
| - Only if ``method != 'external'``. |
| 287 | + - **external**: PDF preview in an external program [default] |
| 288 | + - **notebook**: PNG preview [default in Jupyter notebooks] |
| 289 | + - **none**: Disable image preview |
267 | 290 | """
|
268 | 291 | # Module level variable to know which figures had their show method
|
269 | 292 | # called. Needed for the sphinx-gallery scraper.
|
270 | 293 | SHOWED_FIGURES.append(self)
|
271 | 294 |
|
272 |
| - if method not in ["static", "external"]: |
273 |
| - raise GMTInvalidInput("Invalid show method '{}'.".format(method)) |
274 |
| - if method == "external": |
275 |
| - pdf = self._preview(fmt="pdf", dpi=dpi, anti_alias=False, as_bytes=False) |
276 |
| - launch_external_viewer(pdf) |
277 |
| - img = None |
278 |
| - elif method == "static": |
279 |
| - png = self._preview( |
280 |
| - fmt="png", dpi=dpi, anti_alias=True, as_bytes=True, transparent=True |
| 295 | + # Set the display method |
| 296 | + if method is None: |
| 297 | + method = SHOW_CONFIG["method"] |
| 298 | + |
| 299 | + if method not in ["external", "notebook", "none"]: |
| 300 | + raise GMTInvalidInput( |
| 301 | + ( |
| 302 | + f"Invalid display method '{method}', " |
| 303 | + "should be either 'notebook', 'external', or 'none'." |
| 304 | + ) |
281 | 305 | )
|
282 |
| - if Image is None: |
| 306 | + |
| 307 | + if method in ["notebook", "none"]: |
| 308 | + if IPython is None: |
283 | 309 | raise GMTError(
|
284 |
| - " ".join( |
285 |
| - [ |
286 |
| - "Cannot find IPython.", |
287 |
| - "Make sure you have it installed", |
288 |
| - "or use 'method=\"external\"' to open in an external viewer.", |
289 |
| - ] |
| 310 | + ( |
| 311 | + "Notebook display is selected, but IPython is not available. " |
| 312 | + "Make sure you have IPython installed, " |
| 313 | + "or run the script in a Jupyter notebook." |
290 | 314 | )
|
291 | 315 | )
|
292 |
| - img = Image(data=png, width=width) |
293 |
| - return img |
| 316 | + png = self._preview(fmt="png", dpi=dpi, anti_alias=True, as_bytes=True) |
| 317 | + IPython.display.display(IPython.display.Image(data=png, width=width)) |
| 318 | + |
| 319 | + if method == "external": |
| 320 | + pdf = self._preview(fmt="pdf", dpi=dpi, anti_alias=False, as_bytes=False) |
| 321 | + launch_external_viewer(pdf) |
294 | 322 |
|
295 | 323 | def shift_origin(self, xshift=None, yshift=None):
|
296 | 324 | """
|
@@ -396,3 +424,27 @@ def _repr_html_(self):
|
396 | 424 | subplot,
|
397 | 425 | text,
|
398 | 426 | )
|
| 427 | + |
| 428 | + |
| 429 | +def set_display(method=None): |
| 430 | + """ |
| 431 | + Set the display method. |
| 432 | +
|
| 433 | + Parameters |
| 434 | + ---------- |
| 435 | + method : str or None |
| 436 | + The method to display an image. Choose from: |
| 437 | +
|
| 438 | + - **external**: PDF preview in an external program [default] |
| 439 | + - **notebook**: PNG preview [default in Jupyter notebooks] |
| 440 | + - **none**: Disable image preview |
| 441 | + """ |
| 442 | + if method in ["notebook", "external", "none"]: |
| 443 | + SHOW_CONFIG["method"] = method |
| 444 | + elif method is not None: |
| 445 | + raise GMTInvalidInput( |
| 446 | + ( |
| 447 | + f"Invalid display mode '{method}', " |
| 448 | + "should be either 'notebook', 'external' or 'none'." |
| 449 | + ) |
| 450 | + ) |
0 commit comments