diff --git a/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/6_plotly_plot_R.json b/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/6_plotly_plot_R.json new file mode 100644 index 0000000..ab2989b --- /dev/null +++ b/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/6_plotly_plot_R.json @@ -0,0 +1,81 @@ +{ + "visdat": { + "ac2421aa47": ["function () ", "plotlyVisDat"] + }, + "cur_data": "ac2421aa47", + "attrs": { + "ac2421aa47": { + "x": {}, + "y": {}, + "mode": "markers", + "alpha_stroke": 1, + "sizes": [10, 100], + "spans": [1, 20], + "type": "scatter" + } + }, + "layout": { + "margin": { + "b": 40, + "l": 60, + "t": 25, + "r": 10 + }, + "xaxis": { + "domain": [0, 1], + "automargin": true, + "title": "mpg" + }, + "yaxis": { + "domain": [0, 1], + "automargin": true, + "title": "hp" + }, + "hovermode": "closest", + "showlegend": false + }, + "source": "A", + "config": { + "modeBarButtonsToAdd": ["hoverclosest", "hovercompare"], + "showSendToCloud": false + }, + "data": [ + { + "x": [21, 21, 22.800000000000001, 21.399999999999999, 18.699999999999999, 18.100000000000001, 14.300000000000001, 24.399999999999999, 22.800000000000001, 19.199999999999999, 17.800000000000001, 16.399999999999999, 17.300000000000001, 15.199999999999999, 10.4, 10.4, 14.699999999999999, 32.399999999999999, 30.399999999999999, 33.899999999999999, 21.5, 15.5, 15.199999999999999, 13.300000000000001, 19.199999999999999, 27.300000000000001, 26, 30.399999999999999, 15.800000000000001, 19.699999999999999, 15, 21.399999999999999], + "y": [110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 180, 205, 215, 230, 66, 52, 65, 97, 150, 150, 245, 175, 66, 91, 113, 264, 175, 335, 109], + "mode": "markers", + "type": "scatter", + "marker": { + "color": "rgba(31,119,180,1)", + "line": { + "color": "rgba(31,119,180,1)" + } + }, + "error_y": { + "color": "rgba(31,119,180,1)" + }, + "error_x": { + "color": "rgba(31,119,180,1)" + }, + "line": { + "color": "rgba(31,119,180,1)" + }, + "xaxis": "x", + "yaxis": "y", + "frame": null + } + ], + "highlight": { + "on": "plotly_click", + "persistent": false, + "dynamic": false, + "selectize": false, + "opacityDim": 0.20000000000000001, + "selected": { + "opacity": 1 + }, + "debounce": 0 + }, + "shinyEvents": ["plotly_hover", "plotly_click", "plotly_selected", "plotly_relayout", "plotly_brushed", "plotly_brushing", "plotly_clickannotation", "plotly_doubleclick", "plotly_deselect", "plotly_afterplot", "plotly_sunburstclick"], + "base_url": "https://plot.ly" +} diff --git a/src/vuegen/quarto_reportview.py b/src/vuegen/quarto_reportview.py index b0aee2c..c7083e1 100644 --- a/src/vuegen/quarto_reportview.py +++ b/src/vuegen/quarto_reportview.py @@ -571,14 +571,25 @@ def _generate_plot_code(self, plot, output_file="") -> str: else: # If it's a local file plot_code += f""" with open('{(Path("..") / plot.file_path).as_posix()}', 'r') as plot_file: - plot_json = plot_file.read()\n""" + plot_json = json.load(plot_file)\n""" # Add specific code for each visualization tool if plot.plot_type == r.PlotType.PLOTLY: plot_code += """ -fig_plotly = pio.from_json(plot_json) +# Keep only 'data' and 'layout' sections +plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']}\n +# Remove 'frame' section in 'data' +plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])]\n +# Convert JSON to string +plot_json_str = json.dumps(plot_json)\n +# Create the plotly plot +fig_plotly = pio.from_json(plot_json_str) fig_plotly.update_layout(width=950, height=500)\n""" elif plot.plot_type == r.PlotType.ALTAIR: - plot_code += """fig_altair = alt.Chart.from_json(plot_json).properties(width=900, height=400)""" + plot_code += """ +# Convert JSON to string +plot_json_str = json.dumps(plot_json)\n +# Create the plotly plot +fig_altair = alt.Chart.from_json(plot_json_str).properties(width=900, height=400)\n""" elif plot.plot_type == r.PlotType.INTERACTIVE_NETWORK: # Generate the HTML embedding for interactive networks if is_url(plot.file_path) and plot.file_path.endswith(".html"): @@ -866,8 +877,16 @@ def _generate_component_imports(self, component: r.Component) -> List[str]: # Dictionary to hold the imports for each component type components_imports = { "plot": { - r.PlotType.ALTAIR: ["import altair as alt", "import requests"], - r.PlotType.PLOTLY: ["import plotly.io as pio", "import requests"], + r.PlotType.ALTAIR: [ + "import altair as alt", + "import requests", + "import json", + ], + r.PlotType.PLOTLY: [ + "import plotly.io as pio", + "import requests", + "import json", + ], }, "dataframe": [ "import pandas as pd", diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index 63f7553..74d5d24 100644 --- a/src/vuegen/streamlit_reportview.py +++ b/src/vuegen/streamlit_reportview.py @@ -570,7 +570,13 @@ def _generate_plot_code(self, plot) -> str: # Add specific code for each visualization tool if plot.plot_type == r.PlotType.PLOTLY: - plot_code += "st.plotly_chart(plot_json, use_container_width=True)\n" + plot_code += """ +# Keep only 'data' and 'layout' sections +plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']} + +# Remove 'frame' section in 'data' +plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])] +st.plotly_chart(plot_json, use_container_width=True)\n""" elif plot.plot_type == r.PlotType.ALTAIR: plot_code += """ @@ -987,5 +993,3 @@ def _generate_component_imports(self, component: r.Component) -> List[str]: # Return the list of import statements return component_imports - - return component_imports