Skip to content

Commit 57a1ead

Browse files
committed
Merge branch 'main' into test_all_os
2 parents c88875f + 4939f02 commit 57a1ead

File tree

14 files changed

+347
-103
lines changed

14 files changed

+347
-103
lines changed

.github/workflows/cdci.yml

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ jobs:
7474
- name: quarto pdf report
7575
run: |
7676
cd docs
77-
vuegen -dir example_data/Earth_microbiome_vuegen_demo_notebook -rt pdf
78-
vuegen -c example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml -rt pdf
77+
vuegen -dir example_data/Earth_microbiome_vuegen_demo_notebook -rt pdf -qt_checks
78+
vuegen -c example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml -rt pdf -qt_checks
7979
- name: quarto docx report
8080
run: |
8181
cd docs
@@ -169,13 +169,32 @@ jobs:
169169
with:
170170
name: vuegen_gui_${{ matrix.os.label }}
171171
path: gui/dist/
172-
- name: Upload Executable to a GitHub Release
173-
if: startsWith(github.ref, 'refs/tags')
172+
- name: Upload MacOS Executable to a GitHub Release)
173+
if: startsWith(matrix.os.runner, 'macos') && startsWith(github.ref, 'refs/tags')
174174
env:
175175
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
176176
run: |
177-
TAG_NAME=${GITHUB_REF#refs/tags/}
178-
cp
179-
gh release upload "$TAG_NAME" gui/dist/vuegen_gui.*#vuegen_gui_${{ matrix.os.label }}
177+
echo GITHUB_REF_NAME $GITHUB_REF_NAME
178+
echo "Uploading vuegen_gui_${{ matrix.os.label }} to release $GITHUB_REF_NAME"
179+
echo "Available files in build folder: gui/dist/"
180+
cd gui/dist/
181+
ls -lh
182+
echo "Zip .app folder"
183+
zip -r vuegen_gui_${{ matrix.os.label }}.zip vuegen_gui.app/
184+
echo "Uploading..."
185+
gh release upload $GITHUB_REF_NAME vuegen_gui_${{ matrix.os.label }}.zip
186+
# .app is folder that needs to be zipped
187+
- name: Upload Windows Executable to a GitHub Release
188+
if: startsWith(matrix.os.runner, 'windows') && startsWith(github.ref, 'refs/tags')
189+
env:
190+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
191+
run: |
192+
echo "GITHUB_REF_NAME in env $env:GITHUB_REF_NAME"
193+
$GITHUB_REF_NAME = $env:GITHUB_REF_NAME
194+
echo "Uploading vuegen_gui_${{ matrix.os.label }} to release $GITHUB_REF_NAME"
195+
echo "Available files in build folder: gui/dist/"
196+
ls gui/dist/
197+
echo "Uploading..."
198+
gh release upload $GITHUB_REF_NAME gui/dist/vuegen_gui.exe#vuegen_gui_${{ matrix.os.label }}.exe
180199
# https://cli.github.com/manual/gh_release_upload
181-
# either .app or .exe depending on the OS
200+
# .exe is a single file already

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ logs/
118118
vuegen/logs/
119119
streamlit_report/
120120
quarto_report/
121+
output_docker/
121122

122123
# VS Code
123124
.DS_Store

README.md

Lines changed: 77 additions & 39 deletions
Large diffs are not rendered by default.
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+
}

docs/images/vuegen_logo.png

-6 Bytes
Loading

docs/images/vuegen_logo.svg

Lines changed: 11 additions & 20 deletions
Loading

gui/app.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
# from vuegen.__main__ import main
3838
from vuegen.report import ReportType
39-
from vuegen.utils import get_logger, print_completion_message
39+
from vuegen.utils import get_completion_message, get_logger
4040

4141
customtkinter.set_appearance_mode("system")
4242
customtkinter.set_default_color_theme("dark-blue")
@@ -159,6 +159,7 @@ def inner():
159159
kwargs["logger"].info("logfile: %s", log_file)
160160
kwargs["logger"].debug("sys.path: %s", sys.path)
161161
kwargs["logger"].debug("PATH (in app): %s ", os.environ["PATH"])
162+
kwargs["quarto_checks"] = True # for gui check local quarto installation
162163
report_dir, gen_config_path = report_generator.get_report(**kwargs)
163164
kwargs["logger"].info("Report generated at %s", report_dir)
164165
messagebox.showinfo(
@@ -169,7 +170,7 @@ def inner():
169170
f"\n\nConfiguration file at:\n{gen_config_path}",
170171
)
171172
global hash_config_app # ! fix this
172-
print_completion_message(report_type.get())
173+
get_completion_message(report_type.get())
173174
if hash(yaml.dump(config_app)) != hash_config_app:
174175
with open(config_file, "w", encoding="utf-8") as f:
175176
yaml.dump(config_app, f)

src/vuegen/__main__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pathlib import Path
33

44
from vuegen import report_generator
5-
from vuegen.utils import get_logger, get_parser, print_completion_message
5+
from vuegen.utils import get_completion_message, get_logger, get_parser
66

77

88
def main():
@@ -14,7 +14,9 @@ def main():
1414
config_path = args.config
1515
dir_path = args.directory
1616
report_type = args.report_type
17+
output_dir = args.output_directory
1718
streamlit_autorun = args.streamlit_autorun
19+
quarto_cheks = args.quarto_checks
1820

1921
# Determine the report name for logger suffix
2022
if config_path:
@@ -38,18 +40,21 @@ def main():
3840
# Initialize logger
3941
logger, logfile = get_logger(f"{logger_suffix}")
4042
logger.info("logfile: %s", logfile)
43+
4144
# Generate the report
4245
_, _ = report_generator.get_report(
4346
report_type=report_type,
4447
logger=logger,
4548
config_path=config_path,
4649
dir_path=dir_path,
50+
output_dir=output_dir,
4751
streamlit_autorun=streamlit_autorun,
52+
quarto_checks=quarto_cheks,
4853
)
4954

5055
# Print completion message
5156
# ! Could use now report_dir and config_path as information
52-
print_completion_message(report_type)
57+
print(get_completion_message(report_type, config_path))
5358

5459

5560
if __name__ == "__main__":

src/vuegen/quarto_reportview.py

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,14 @@ class QuartoReportView(r.ReportView):
2020
BASE_DIR = Path("quarto_report")
2121
STATIC_FILES_DIR = BASE_DIR / "static"
2222

23-
def __init__(self, report: r.Report, report_type: r.ReportType):
23+
def __init__(
24+
self,
25+
report: r.Report,
26+
report_type: r.ReportType,
27+
quarto_checks: bool = False,
28+
):
2429
super().__init__(report=report, report_type=report_type)
30+
self.quarto_checks = quarto_checks
2531
self.BUNDLED_EXECUTION = False
2632
self.quarto_path = "quarto"
2733
# self.env_vars = os.environ.copy()
@@ -186,11 +192,15 @@ def run_report(self, output_dir: str = BASE_DIR) -> None:
186192
self.report.logger.info(
187193
f"Running '{self.report.title}' '{self.report_type}' report with {args!r}"
188194
)
189-
if self.report_type in [
190-
r.ReportType.PDF,
191-
r.ReportType.DOCX,
192-
r.ReportType.ODT,
193-
]:
195+
if (
196+
self.report_type
197+
in [
198+
r.ReportType.PDF,
199+
r.ReportType.DOCX,
200+
r.ReportType.ODT,
201+
]
202+
and self.quarto_checks
203+
):
194204
subprocess.run(
195205
[self.quarto_path, "install", "tinytex", "--no-prompt"],
196206
check=True,
@@ -204,11 +214,17 @@ def run_report(self, output_dir: str = BASE_DIR) -> None:
204214
args,
205215
check=True,
206216
)
207-
out_path = file_path_to_qmd.with_suffix(f".{self.report_type.lower()}")
208-
if self.report_type in [r.ReportType.REVEALJS, r.ReportType.JUPYTER]:
217+
if self.report_type == r.ReportType.REVEALJS:
218+
out_path = file_path_to_qmd.with_name(
219+
f"{file_path_to_qmd.stem}_revealjs.html"
220+
)
221+
elif self.report_type == r.ReportType.JUPYTER:
209222
out_path = file_path_to_qmd.with_suffix(".html")
223+
else:
224+
out_path = file_path_to_qmd.with_suffix(f".{self.report_type.lower()}")
210225
if not out_path.exists():
211226
raise FileNotFoundError(f"Report file could not be created: {out_path}")
227+
212228
if self.report_type == r.ReportType.JUPYTER:
213229
args = [self.quarto_path, "convert", str(file_path_to_qmd)]
214230
subprocess.run(
@@ -571,14 +587,25 @@ def _generate_plot_code(self, plot, output_file="") -> str:
571587
else: # If it's a local file
572588
plot_code += f"""
573589
with open('{(Path("..") / plot.file_path).as_posix()}', 'r') as plot_file:
574-
plot_json = plot_file.read()\n"""
590+
plot_json = json.load(plot_file)\n"""
575591
# Add specific code for each visualization tool
576592
if plot.plot_type == r.PlotType.PLOTLY:
577593
plot_code += """
578-
fig_plotly = pio.from_json(plot_json)
594+
# Keep only 'data' and 'layout' sections
595+
plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']}\n
596+
# Remove 'frame' section in 'data'
597+
plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])]\n
598+
# Convert JSON to string
599+
plot_json_str = json.dumps(plot_json)\n
600+
# Create the plotly plot
601+
fig_plotly = pio.from_json(plot_json_str)
579602
fig_plotly.update_layout(width=950, height=500)\n"""
580603
elif plot.plot_type == r.PlotType.ALTAIR:
581-
plot_code += """fig_altair = alt.Chart.from_json(plot_json).properties(width=900, height=400)"""
604+
plot_code += """
605+
# Convert JSON to string
606+
plot_json_str = json.dumps(plot_json)\n
607+
# Create the plotly plot
608+
fig_altair = alt.Chart.from_json(plot_json_str).properties(width=900, height=400)\n"""
582609
elif plot.plot_type == r.PlotType.INTERACTIVE_NETWORK:
583610
# Generate the HTML embedding for interactive networks
584611
if is_url(plot.file_path) and plot.file_path.endswith(".html"):
@@ -834,7 +861,7 @@ def _show_dataframe(
834861
# Generate path for the DataFrame image
835862
df_image = Path(static_dir) / f"{dataframe.title.replace(' ', '_')}.png"
836863
dataframe_content.append(
837-
f"df.dfi.export('{Path(df_image).resolve().as_posix()}', max_rows=10, max_cols=5)\n```\n"
864+
f"df.dfi.export('{Path(df_image).resolve().as_posix()}', max_rows=10, max_cols=5, table_conversion='matplotlib')\n```\n"
838865
)
839866
# Use helper method to add centered image content
840867
dataframe_content.append(self._generate_image_content(df_image))
@@ -866,8 +893,16 @@ def _generate_component_imports(self, component: r.Component) -> List[str]:
866893
# Dictionary to hold the imports for each component type
867894
components_imports = {
868895
"plot": {
869-
r.PlotType.ALTAIR: ["import altair as alt", "import requests"],
870-
r.PlotType.PLOTLY: ["import plotly.io as pio", "import requests"],
896+
r.PlotType.ALTAIR: [
897+
"import altair as alt",
898+
"import requests",
899+
"import json",
900+
],
901+
r.PlotType.PLOTLY: [
902+
"import plotly.io as pio",
903+
"import requests",
904+
"import json",
905+
],
871906
},
872907
"dataframe": [
873908
"import pandas as pd",

0 commit comments

Comments
 (0)