Skip to content

Commit c3c5064

Browse files
committed
🐛 Fix: add code to handle plotly plots generated with R in streamlit and quarto reports
1 parent 99e38d9 commit c3c5064

File tree

4 files changed

+275
-8
lines changed

4 files changed

+275
-8
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
report:
2+
title: Basic Example Vuegen Demo Notebook
3+
description: 'A general description of the report.
4+
5+
'
6+
graphical_abstract: ''
7+
logo: ''
8+
sections:
9+
- title: Plots
10+
description: ''
11+
subsections:
12+
- title: Interactive Plots
13+
description: 'Optional description for section.
14+
15+
'
16+
components:
17+
- title: Top Species Plot By Biome Plotly
18+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/1_top_species_plot_by_biome_plotly.json
19+
description: ''
20+
caption: ''
21+
component_type: plot
22+
plot_type: plotly
23+
- title: Multiline Plot Altair
24+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/2_multiline_plot_altair.json
25+
description: ''
26+
caption: ''
27+
component_type: plot
28+
plot_type: altair
29+
- title: Pie Plot Countries Plotly
30+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/3_pie_plot_countries_plotly.json
31+
description: ''
32+
caption: ''
33+
component_type: plot
34+
plot_type: plotly
35+
- title: Pie Plots Biomes Plotly
36+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/4_pie_plots_biomes_plotly.json
37+
description: ''
38+
caption: ''
39+
component_type: plot
40+
plot_type: plotly
41+
- title: Saline Metagenomics Samples Map Altair
42+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/5_saline_metagenomics_samples_map_altair.json
43+
description: ''
44+
caption: ''
45+
component_type: plot
46+
plot_type: altair
47+
- title: Plotly Plot R
48+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/6_plotly_plot_R.json
49+
description: ''
50+
caption: ''
51+
component_type: plot
52+
plot_type: plotly
53+
- title: Description
54+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/1_Interactive_plots/description.md
55+
description: ''
56+
caption: ''
57+
component_type: markdown
58+
- title: Static Plots
59+
description: ''
60+
components:
61+
- title: Number Samples Per Study
62+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/2_Static_plots/1_number_samples_per_study.png
63+
description: ''
64+
caption: ''
65+
component_type: plot
66+
plot_type: static
67+
- title: Animal Metagenomics Samples Map
68+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/2_Static_plots/2_animal_metagenomics_samples_map.png
69+
description: ''
70+
caption: ''
71+
component_type: plot
72+
plot_type: static
73+
- title: Alpha Diversity Host Associated Samples
74+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/1_Plots/2_Static_plots/3_alpha_diversity_host_associated_samples.png
75+
description: ''
76+
caption: ''
77+
component_type: plot
78+
plot_type: static
79+
- title: Dataframes
80+
description: ''
81+
subsections:
82+
- title: All Formats
83+
description: ''
84+
components:
85+
- title: Phyla Correlation Network Csv
86+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/2_Dataframes/1_All_formats/1_phyla_correlation_network_csv.csv
87+
description: ''
88+
caption: ''
89+
component_type: dataframe
90+
file_format: csv
91+
delimiter: ','
92+
- title: Abundance Table Example Xls
93+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/2_Dataframes/1_All_formats/2_abundance_table_example_xls.xls
94+
description: ''
95+
caption: ''
96+
component_type: dataframe
97+
file_format: xls
98+
- title: Sample Info Example Txt
99+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/2_Dataframes/1_All_formats/3_sample_info_example_txt.txt
100+
description: ''
101+
caption: ''
102+
component_type: dataframe
103+
file_format: txt
104+
delimiter: \t
105+
- title: Sample Info Example Parquet
106+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/2_Dataframes/1_All_formats/4_sample_info_example_parquet.parquet
107+
description: ''
108+
caption: ''
109+
component_type: dataframe
110+
file_format: parquet
111+
- title: Networks
112+
description: ''
113+
subsections:
114+
- title: Interactive Networks
115+
description: 'Optional description for subsection.
116+
117+
'
118+
components:
119+
- title: Man Example
120+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/3_Networks/1_Interactive_networks/1_man_example.graphml
121+
description: ''
122+
caption: ''
123+
component_type: plot
124+
plot_type: interactive_network
125+
- title: Description
126+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/3_Networks/1_Interactive_networks/description.md
127+
description: ''
128+
caption: ''
129+
component_type: markdown
130+
- title: Static Networks
131+
description: ''
132+
components:
133+
- title: Phyla Correlation Network
134+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/3_Networks/2_Static_networks/1_phyla_correlation_network.png
135+
description: ''
136+
caption: ''
137+
component_type: plot
138+
plot_type: static
139+
- title: Html
140+
description: ''
141+
subsections:
142+
- title: All Html
143+
description: ''
144+
components:
145+
- title: Plot
146+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/4_Html/1_All_html/1_plot.html
147+
description: ''
148+
caption: ''
149+
component_type: html
150+
- title: Ckg Network
151+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/4_Html/1_All_html/2_ckg_network.html
152+
description: ''
153+
caption: ''
154+
component_type: plot
155+
plot_type: interactive_network
156+
- title: Multiqc Report
157+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/4_Html/1_All_html/3_multiqc_report.html
158+
description: ''
159+
caption: ''
160+
component_type: html
161+
- title: Markdown
162+
description: ''
163+
subsections:
164+
- title: All Markdown
165+
description: ''
166+
components:
167+
- title: Readme
168+
file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Basic_example_vuegen_demo_notebook/5_Markdown/1_All_markdown/README.md
169+
description: ''
170+
caption: ''
171+
component_type: markdown
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"visdat": {
3+
"ac2421aa47": ["function () ", "plotlyVisDat"]
4+
},
5+
"cur_data": "ac2421aa47",
6+
"attrs": {
7+
"ac2421aa47": {
8+
"x": {},
9+
"y": {},
10+
"mode": "markers",
11+
"alpha_stroke": 1,
12+
"sizes": [10, 100],
13+
"spans": [1, 20],
14+
"type": "scatter"
15+
}
16+
},
17+
"layout": {
18+
"margin": {
19+
"b": 40,
20+
"l": 60,
21+
"t": 25,
22+
"r": 10
23+
},
24+
"xaxis": {
25+
"domain": [0, 1],
26+
"automargin": true,
27+
"title": "mpg"
28+
},
29+
"yaxis": {
30+
"domain": [0, 1],
31+
"automargin": true,
32+
"title": "hp"
33+
},
34+
"hovermode": "closest",
35+
"showlegend": false
36+
},
37+
"source": "A",
38+
"config": {
39+
"modeBarButtonsToAdd": ["hoverclosest", "hovercompare"],
40+
"showSendToCloud": false
41+
},
42+
"data": [
43+
{
44+
"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],
45+
"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],
46+
"mode": "markers",
47+
"type": "scatter",
48+
"marker": {
49+
"color": "rgba(31,119,180,1)",
50+
"line": {
51+
"color": "rgba(31,119,180,1)"
52+
}
53+
},
54+
"error_y": {
55+
"color": "rgba(31,119,180,1)"
56+
},
57+
"error_x": {
58+
"color": "rgba(31,119,180,1)"
59+
},
60+
"line": {
61+
"color": "rgba(31,119,180,1)"
62+
},
63+
"xaxis": "x",
64+
"yaxis": "y",
65+
"frame": null
66+
}
67+
],
68+
"highlight": {
69+
"on": "plotly_click",
70+
"persistent": false,
71+
"dynamic": false,
72+
"selectize": false,
73+
"opacityDim": 0.20000000000000001,
74+
"selected": {
75+
"opacity": 1
76+
},
77+
"debounce": 0
78+
},
79+
"shinyEvents": ["plotly_hover", "plotly_click", "plotly_selected", "plotly_relayout", "plotly_brushed", "plotly_brushing", "plotly_clickannotation", "plotly_doubleclick", "plotly_deselect", "plotly_afterplot", "plotly_sunburstclick"],
80+
"base_url": "https://plot.ly"
81+
}

src/vuegen/quarto_reportview.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -571,14 +571,25 @@ def _generate_plot_code(self, plot, output_file="") -> str:
571571
else: # If it's a local file
572572
plot_code += f"""
573573
with open('{(Path("..") / plot.file_path).as_posix()}', 'r') as plot_file:
574-
plot_json = plot_file.read()\n"""
574+
plot_json = json.load(plot_file)\n"""
575575
# Add specific code for each visualization tool
576576
if plot.plot_type == r.PlotType.PLOTLY:
577577
plot_code += """
578-
fig_plotly = pio.from_json(plot_json)
578+
# Keep only 'data' and 'layout' sections
579+
plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']}\n
580+
# Remove 'frame' section in 'data'
581+
plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])]\n
582+
# Convert JSON to string
583+
plot_json_str = json.dumps(plot_json)\n
584+
# Create the plotly plot
585+
fig_plotly = pio.from_json(plot_json_str)
579586
fig_plotly.update_layout(width=950, height=500)\n"""
580587
elif plot.plot_type == r.PlotType.ALTAIR:
581-
plot_code += """fig_altair = alt.Chart.from_json(plot_json).properties(width=900, height=400)"""
588+
plot_code += """
589+
# Convert JSON to string
590+
plot_json_str = json.dumps(plot_json)\n
591+
# Create the plotly plot
592+
fig_altair = alt.Chart.from_json(plot_json_str).properties(width=900, height=400)\n"""
582593
elif plot.plot_type == r.PlotType.INTERACTIVE_NETWORK:
583594
# Generate the HTML embedding for interactive networks
584595
if is_url(plot.file_path) and plot.file_path.endswith(".html"):
@@ -866,8 +877,8 @@ def _generate_component_imports(self, component: r.Component) -> List[str]:
866877
# Dictionary to hold the imports for each component type
867878
components_imports = {
868879
"plot": {
869-
r.PlotType.ALTAIR: ["import altair as alt", "import requests"],
870-
r.PlotType.PLOTLY: ["import plotly.io as pio", "import requests"],
880+
r.PlotType.ALTAIR: ["import altair as alt", "import requests", "import json"],
881+
r.PlotType.PLOTLY: ["import plotly.io as pio", "import requests", "import json"],
871882
},
872883
"dataframe": [
873884
"import pandas as pd",

src/vuegen/streamlit_reportview.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,13 @@ def _generate_plot_code(self, plot) -> str:
570570

571571
# Add specific code for each visualization tool
572572
if plot.plot_type == r.PlotType.PLOTLY:
573-
plot_code += "st.plotly_chart(plot_json, use_container_width=True)\n"
573+
plot_code += """
574+
# Keep only 'data' and 'layout' sections
575+
plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']}
576+
577+
# Remove 'frame' section in 'data'
578+
plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])]
579+
st.plotly_chart(plot_json, use_container_width=True)\n"""
574580

575581
elif plot.plot_type == r.PlotType.ALTAIR:
576582
plot_code += """
@@ -987,5 +993,3 @@ def _generate_component_imports(self, component: r.Component) -> List[str]:
987993

988994
# Return the list of import statements
989995
return component_imports
990-
991-
return component_imports

0 commit comments

Comments
 (0)