From 98903333209dc8b87e7811f2015663afd0f5976a Mon Sep 17 00:00:00 2001 From: Caitlin H <69856275+chaedri@users.noreply.github.com> Date: Fri, 30 Jul 2021 15:19:21 -0400 Subject: [PATCH] jupyter: Add temporary files for non-interactive display (#1727) * Write display-related files to a temporary directory for non-interactive displays in Jupyter Notebooks. * Named files are not suitable as we need to write to them from different processes. * The option remains to write the display to a PNG when provided a path and filename. * Adds renderer parameter to GrassRenderer. --- doc/notebooks/jupyter_integration.ipynb | 4 +-- python/grass/jupyter/display.py | 36 ++++++++++++++++++------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/doc/notebooks/jupyter_integration.ipynb b/doc/notebooks/jupyter_integration.ipynb index e537e8ae218..9c6dcb73c63 100644 --- a/doc/notebooks/jupyter_integration.ipynb +++ b/doc/notebooks/jupyter_integration.ipynb @@ -89,9 +89,7 @@ "outputs": [], "source": [ "# Demonstration of GrassRenderer for non-interactive map display\n", - "\n", - "# Create an instance of GrassRenderer\n", - "r = gj.GrassRenderer(height=540, filename = \"streams_maps.png\")\n", + "r = gj.GrassRenderer(height=540)\n", "\n", "# Add a raster and vector to the map\n", "r.run(\"d.rast\", map=\"elevation\")\n", diff --git a/python/grass/jupyter/display.py b/python/grass/jupyter/display.py index 970db44c6f9..188bd206301 100644 --- a/python/grass/jupyter/display.py +++ b/python/grass/jupyter/display.py @@ -13,8 +13,8 @@ import os import shutil -from pathlib import Path from IPython.display import Image +import tempfile import grass.script as gs @@ -41,8 +41,15 @@ class GrassRenderer: """ def __init__( - self, env=None, width=600, height=400, filename="map.png", text_size=12 + self, + height=400, + width=600, + filename=None, + env=None, + text_size=12, + renderer="cairo", ): + """Creates an instance of the GrassRenderer class. :param int height: height of map in pixels @@ -53,24 +60,35 @@ def __init__( :param renderer: GRASS renderer driver (options: cairo, png, ps, html) """ + # Copy Environment if env: self._env = env.copy() else: self._env = os.environ.copy() - + # Environment Settings self._env["GRASS_RENDER_WIDTH"] = str(width) self._env["GRASS_RENDER_HEIGHT"] = str(height) self._env["GRASS_RENDER_TEXT_SIZE"] = str(text_size) - self._env["GRASS_RENDER_IMMEDIATE"] = "cairo" - self._env["GRASS_RENDER_FILE"] = str(filename) + self._env["GRASS_RENDER_IMMEDIATE"] = renderer self._env["GRASS_RENDER_FILE_READ"] = "TRUE" - self._legend_file = Path(filename).with_suffix(".grass_vector_legend") - self._env["GRASS_LEGEND_FILE"] = str(self._legend_file) + # Create PNG file for map + # If not user-supplied, we will write it to a map.png in a + # temporary directory that we can delete later. We need + # this temporary directory for the legend anyways so we'll + # make it now + self._tmpdir = tempfile.TemporaryDirectory() - self._filename = filename + if filename: + self._filename = filename + else: + self._filename = os.path.join(self._tmpdir.name, "map.png") + # Set environment var for file + self._env["GRASS_RENDER_FILE"] = self._filename - self.run("d.erase") + # Create Temporary Legend File + self._legend_file = os.path.join(self._tmpdir.name, "legend.txt") + self._env["GRASS_LEGEND_FILE"] = str(self._legend_file) def run(self, module, **kwargs): """Run modules from "d." GRASS library"""