diff --git a/glue_plotly/html_exporters/bqplot/histogram.py b/glue_plotly/html_exporters/bqplot/histogram.py index 496394c..57c3388 100644 --- a/glue_plotly/html_exporters/bqplot/histogram.py +++ b/glue_plotly/html_exporters/bqplot/histogram.py @@ -6,11 +6,11 @@ from plotly.offline import plot import plotly.graph_objs as go -from .base import PlotlyBaseBqplotExport +from ...jupyter_base_export_tool import JupyterBaseExportTool @viewer_tool -class PlotlyHistogramBqplotExport(PlotlyBaseBqplotExport): +class PlotlyHistogramBqplotExport(JupyterBaseExportTool): tool_id = 'save:bqplot_plotlyhist' def save_figure(self, filepath): diff --git a/glue_plotly/html_exporters/bqplot/image.py b/glue_plotly/html_exporters/bqplot/image.py index df5bfcc..6697c71 100644 --- a/glue_plotly/html_exporters/bqplot/image.py +++ b/glue_plotly/html_exporters/bqplot/image.py @@ -7,11 +7,11 @@ import plotly.graph_objs as go from plotly.subplots import make_subplots -from .base import PlotlyBaseBqplotExport +from ...jupyter_base_export_tool import JupyterBaseExportTool @viewer_tool -class PlotlyImageBqplotExport(PlotlyBaseBqplotExport): +class PlotlyImageBqplotExport(JupyterBaseExportTool): tool_id = 'save:bqplot_plotlyimage2d' def save_figure(self, filepath): diff --git a/glue_plotly/html_exporters/bqplot/profile.py b/glue_plotly/html_exporters/bqplot/profile.py index c72b0c6..49b6faf 100644 --- a/glue_plotly/html_exporters/bqplot/profile.py +++ b/glue_plotly/html_exporters/bqplot/profile.py @@ -6,11 +6,11 @@ from plotly.offline import plot import plotly.graph_objs as go -from .base import PlotlyBaseBqplotExport +from ...jupyter_base_export_tool import JupyterBaseExportTool @viewer_tool -class PlotlyProfileBqplotExport(PlotlyBaseBqplotExport): +class PlotlyProfileBqplotExport(JupyterBaseExportTool): tool_id = 'save:bqplot_plotlyprofile' def save_figure(self, filepath): diff --git a/glue_plotly/html_exporters/bqplot/scatter2d.py b/glue_plotly/html_exporters/bqplot/scatter2d.py index c175fab..9374f34 100644 --- a/glue_plotly/html_exporters/bqplot/scatter2d.py +++ b/glue_plotly/html_exporters/bqplot/scatter2d.py @@ -6,11 +6,11 @@ from plotly.offline import plot import plotly.graph_objs as go -from .base import PlotlyBaseBqplotExport +from ...jupyter_base_export_tool import JupyterBaseExportTool @viewer_tool -class PlotlyScatter2DBqplotExport(PlotlyBaseBqplotExport): +class PlotlyScatter2DBqplotExport(JupyterBaseExportTool): tool_id = 'save:bqplot_plotly2d' def save_figure(self, filepath): diff --git a/glue_plotly/html_exporters/bqplot/base.py b/glue_plotly/jupyter_base_export_tool.py similarity index 93% rename from glue_plotly/html_exporters/bqplot/base.py rename to glue_plotly/jupyter_base_export_tool.py index d65b5bb..1082be6 100644 --- a/glue_plotly/html_exporters/bqplot/base.py +++ b/glue_plotly/jupyter_base_export_tool.py @@ -7,14 +7,16 @@ from ipywidgets import HBox, Layout # noqa from IPython.display import display # noqa from ipyfilechooser import FileChooser # noqa +from glue_plotly import PLOTLY_LOGO -from glue_plotly import PLOTLY_LOGO # noqa +__all__ = ["JupyterBaseExportTool"] -class PlotlyBaseBqplotExport(Tool): +class JupyterBaseExportTool(Tool): + icon = PLOTLY_LOGO - action_text = 'Save Plotly HTML page' - tool_tip = 'Save Plotly HTML page' + action_text = "Save Plotly HTML page" + tool_tip = "Save Plotly HTML page" def activate(self): file_chooser = FileChooser(getcwd()) diff --git a/glue_plotly/viewers/common/tools.py b/glue_plotly/viewers/common/tools.py index 34dfb80..592c74b 100644 --- a/glue_plotly/viewers/common/tools.py +++ b/glue_plotly/viewers/common/tools.py @@ -4,6 +4,13 @@ from glue.config import viewer_tool from glue.core.subset import PolygonalROI, RectangularROI, XRangeROI, YRangeROI from glue.viewers.common.tool import CheckableTool, Tool +from glue_plotly.jupyter_base_export_tool import JupyterBaseExportTool + +import plotly.graph_objects as go +import ipyvuetify as v # noqa +from ipywidgets import HBox, Layout # noqa +from IPython.display import display # noqa +from ipyfilechooser import FileChooser # noqa class PlotlyDragMode(CheckableTool): @@ -252,3 +259,29 @@ def activate(self): def deactivate(self): self.viewer.figure.update_layout(hovermode=False) + + +@viewer_tool +class PlotlySaveTool(JupyterBaseExportTool): + + icon = 'glue_filesave' + tool_id = 'plotly:save' + action_text = 'Save as interactive HTML' + tool_tip = 'Save as interactive HTML' + + def save_figure(self, filepath): + if not filepath: + return + + # We restrict things like modebar and axis functionality in + # the viewer so that we can enable/disable them via tools. + # For the HTML export, we want to re-enable these. + # We clone the viewer figure so that we don't modify the viewer itself. + figure = go.Figure(self.viewer.figure) + for setting in ('modebar', 'dragmode', 'newselection'): + figure.update_layout({setting: None}) + for ax in ('x', 'y', 'z'): + attr = f"{ax}axis" + if hasattr(figure.layout, attr): + getattr(figure.layout, attr).update(fixedrange=False) + figure.write_html(filepath) diff --git a/glue_plotly/viewers/histogram/viewer.py b/glue_plotly/viewers/histogram/viewer.py index 1d617e7..075be2d 100644 --- a/glue_plotly/viewers/histogram/viewer.py +++ b/glue_plotly/viewers/histogram/viewer.py @@ -15,7 +15,9 @@ @viewer_registry("plotly_histogram") class PlotlyHistogramView(PlotlyBaseView): - tools = ['plotly:home', 'plotly:zoom', 'plotly:pan', 'plotly:xrange', 'plotly:hover'] + tools = ['plotly:save', 'plotly:home', + 'plotly:zoom', 'plotly:pan', + 'plotly:xrange', 'plotly:hover'] allow_duplicate_data = False allow_duplicate_subset = False diff --git a/glue_plotly/viewers/scatter/viewer.py b/glue_plotly/viewers/scatter/viewer.py index b1e0da7..4074fd3 100644 --- a/glue_plotly/viewers/scatter/viewer.py +++ b/glue_plotly/viewers/scatter/viewer.py @@ -19,8 +19,11 @@ @viewer_registry("plotly_scatter") class PlotlyScatterView(PlotlyBaseView): - tools = ['plotly:home', 'plotly:zoom', 'plotly:pan', 'plotly:xrange', - 'plotly:yrange', 'plotly:rectangle', 'plotly:lasso', 'plotly:hover'] + tools = ['plotly:save', 'plotly:home', + 'plotly:zoom', 'plotly:pan', + 'plotly:xrange', 'plotly:yrange', + 'plotly:rectangle', 'plotly:lasso', + 'plotly:hover'] allow_duplicate_data = False allow_duplicate_subset = False