def _renew_images(self, driver=None): """Renew thumbnail and deep zoom images. Parameters ---------- driver selenium webdriver instance, if not given a firefox instance is created using `utils.get_firefox_webdriver()` Returns ------- None """ plot = self.get_plot(thumbnail=True) # # Create a plot and save a thumbnail image in in-memory file # generate_driver = not driver if generate_driver: driver = webdriver_control.create() driver.implicitly_wait(1200) try: image = get_screenshot_as_png(plot, driver=driver, timeout=20) thumbnail_height = 400 thumbnail_width = int(image.size[0] * thumbnail_height / image.size[1]) image.thumbnail((thumbnail_width, thumbnail_height)) image_file = io.BytesIO() image.save(image_file, 'PNG') # # Remove old thumbnail # self.thumbnail.delete() # # Save the contents of in-memory file in Django image field # self.thumbnail.save( f'{self.id}/thumbnail.png', ContentFile(image_file.getvalue()), ) except RuntimeError as exc: _log.error(f"Cannot generate thumbnail for topography {self.id}. Reason: {exc}") self.thumbnail.delete() _log.warning(f"Thumbnail generation failed for topography {self.id}. Deleted old thumbnail which could be outdated.") if generate_driver: driver.close() # important to free memory if self.size_y is not None: # This is a topography (map), we need to create a Deep Zoom Image make_dzi(self.topography(), user_directory_path(self, f'{self.id}/dzi'))
def save_png(model, filename): """ Saves a bokeh model to png Arguments --------- model: bokeh.model.Model Model to save to png filename: str Filename to save to """ from bokeh.io.webdriver import webdriver_control if not state.webdriver: state.webdriver = webdriver_control.create() webdriver = state.webdriver export_png(model, filename=filename, webdriver=webdriver)
def save_png(model, filename, template=None, template_variables=None): """ Saves a bokeh model to png Arguments --------- model: bokeh.model.Model Model to save to png filename: str Filename to save to template: template file, as used by bokeh.file_html. If None will use bokeh defaults template_variables: template_variables file dict, as used by bokeh.file_html """ from bokeh.io.webdriver import webdriver_control if not state.webdriver: state.webdriver = webdriver_control.create() webdriver = state.webdriver try: if template: def get_layout_html(obj, resources, width, height): return file_html(obj, resources, title="", template=template, template_variables=template_variables, suppress_callback_warning=True, _always_new=True) old_layout_fn = bokeh.io.export.get_layout_html bokeh.io.export.get_layout_html = get_layout_html export_png(model, filename=filename, webdriver=webdriver) except Exception: raise finally: if template: bokeh.io.export.get_layout_html = old_layout_fn
def webdriver(): driver = webdriver_control.create() yield driver terminate_webdriver(driver)
def webdriver(request): driver = webdriver_control.create(request.param) try: yield driver finally: webdriver_control.terminate(driver)
def save_png(model, filename, resources=CDN, template=None, template_variables=None, timeout=5): """ Saves a bokeh model to png Arguments --------- model: bokeh.model.Model Model to save to png filename: str Filename to save to template: template file, as used by bokeh.file_html. If None will use bokeh defaults template_variables: template_variables file dict, as used by bokeh.file_html timeout: int The maximum amount of time (in seconds) to wait for """ from bokeh.io.webdriver import webdriver_control if not state.webdriver: state.webdriver = webdriver_control.create() webdriver = state.webdriver if template is None: template = r"""\ {% block preamble %} <style> html, body { box-sizing: border-box; width: 100%; height: 100%; margin: 0; border: 0; padding: 0; overflow: hidden; } </style> {% endblock %} """ try: def get_layout_html(obj, resources, width, height, **kwargs): resources = Resources.from_bokeh(resources) return file_html(obj, resources, title="", template=template, template_variables=template_variables or {}, _always_new=True) old_layout_fn = bokeh.io.export.get_layout_html bokeh.io.export.get_layout_html = get_layout_html img = get_screenshot_as_png(model, driver=webdriver, timeout=timeout, resources=resources) if img.width == 0 or img.height == 0: raise ValueError("unable to save an empty image") img.save(filename, format="png") except Exception: raise finally: if template: bokeh.io.export.get_layout_html = old_layout_fn
def _figure_data(self, plot, fmt, doc=None, as_script=False, **kwargs): """ Given a plot instance, an output format and an optional bokeh document, return the corresponding data. If as_script is True, the content will be split in an HTML and a JS component. """ model = plot.state if doc is None: doc = plot.document else: plot.document = doc for m in model.references(): m._document = None doc.theme = self.theme doc.add_root(model) # Bokeh raises warnings about duplicate tools and empty subplots # but at the holoviews level these are not issues logger = logging.getLogger(bokeh.core.validation.check.__file__) logger.disabled = True data = None if fmt == 'gif': from bokeh.io.export import get_screenshot_as_png from bokeh.io.webdriver import webdriver_control if state.webdriver is None: webdriver = webdriver_control.create() else: webdriver = state.webdriver nframes = len(plot) frames = [] for i in range(nframes): plot.update(i) img = get_screenshot_as_png(plot.state, driver=webdriver) frames.append(img) if state.webdriver is not None: webdriver.close() bio = BytesIO() duration = (1. / self.fps) * 1000 frames[0].save(bio, format='GIF', append_images=frames[1:], save_all=True, duration=duration, loop=0) bio.seek(0) data = bio.read() elif fmt == 'png': from bokeh.io.export import get_screenshot_as_png img = get_screenshot_as_png(plot.state, driver=state.webdriver) imgByteArr = BytesIO() img.save(imgByteArr, format='PNG') data = imgByteArr.getvalue() else: div = render_mimebundle(plot.state, doc, plot.comm)[0]['text/html'] if as_script and fmt in ['png', 'gif']: b64 = base64.b64encode(data).decode("utf-8") (mime_type, tag) = MIME_TYPES[fmt], HTML_TAGS[fmt] src = HTML_TAGS['base64'].format(mime_type=mime_type, b64=b64) div = tag.format(src=src, mime_type=mime_type, css='') plot.document = doc if as_script or data is None: return div else: return data