diff --git a/README.md b/README.md index 3f83f87..97ac14d 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ pip install -e path/to/vuegen # specify location pip install -e . # in case you pwd is in the vuegen directory ``` -### Quatro installation +### Quarto installation -Install quatro with vueguen if you don't have it globally installed. +Install quarto with vueguen if you don't have it globally installed. ```bash pip install -e ".[quarto]" # specify location @@ -65,12 +65,20 @@ Test your quarto installation by running the following command: quarto check ``` - ## Execution +Run VueGen using a configuration file with the following command: + +```bash +python vuegen/main.py --config docs/example_data/MicW2Graph/report_config_micw2graph.yaml --report_type streamlit +``` + +By default, the `streamlit_autorun` argument is set to False, but you can use it in case you want to automatically run the streamlit app. + +It's also possible to provide a directory instead of a configuration file: + ```bash -cd docs -python vuegen/main.py --config example_data/MicW2Graph/report_config_micw2graph.yaml --report_type streamlit +python vuegen/main.py --directory docs/example_data/MicW2Graph/ --report_type streamlit ``` The current report types are streamlit, html, pdf, docx, odt, revealjs, pptx, and jupyter. diff --git a/docs/example_data/MicW2Graph/MicW2Graph_config.yaml b/docs/example_data/MicW2Graph/MicW2Graph_config.yaml index cd2cc51..9e81392 100644 --- a/docs/example_data/MicW2Graph/MicW2Graph_config.yaml +++ b/docs/example_data/MicW2Graph/MicW2Graph_config.yaml @@ -13,23 +13,23 @@ sections: - component_type: plot plot_type: plotly title: Top Species Plot Biome Plotly - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/1_top_species_plot_biome_plotly.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/1_top_species_plot_biome_plotly.json description: '' - component_type: plot plot_type: altair title: Multilineplot Altair - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/2_multilineplot_altair.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/2_multilineplot_altair.json description: '' - component_type: dataframe file_format: csv delimiter: ',' title: Abundance Data Allbiomes - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/3_abundance_data_allbiomes.csv + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/3_abundance_data_allbiomes.csv description: '' - component_type: dataframe file_format: xls title: Abundance Data Allbiomes - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/4_abundance_data_allbiomes.xls + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/1_Abundance_data/4_abundance_data_allbiomes.xls description: '' - title: Sample Data description: '' @@ -37,35 +37,35 @@ sections: - component_type: plot plot_type: plotly title: Pie Plot Countries Plotly - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/1_pie_plot_countries_plotly.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/1_pie_plot_countries_plotly.json description: '' - component_type: plot plot_type: plotly title: Pie Plots Biomes Plotly - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/2_pie_plots_biomes_plotly.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/2_pie_plots_biomes_plotly.json description: '' - component_type: plot plot_type: static title: Number Samples Per Study - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/3_number_samples_per_study.png + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/3_number_samples_per_study.png description: '' - component_type: dataframe file_format: parquet title: Sample Info Allbiomes - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/4_sample_info_allbiomes.parquet + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/4_sample_info_allbiomes.parquet description: '' - component_type: dataframe file_format: txt delimiter: \t title: Sample Info Allbiomes - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/5_sample_info_allbiomes.txt + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/2_Sample_data/5_sample_info_allbiomes.txt description: '' - title: Extra Info description: '' components: - component_type: markdown title: Test Md - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/1_Exploratory_Data_Analysis/3_Extra_info/1_test_md.md + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/1_Exploratory_Data_Analysis/3_Extra_info/1_test_md.md description: '' - title: Microbial Association Networks description: '' @@ -76,7 +76,7 @@ sections: - component_type: plot plot_type: interactive_network title: Man Example - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/2_Microbial_Association_Networks/1_Network_visualization1/1_man_example.graphml + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/2_Microbial_Association_Networks/1_Network_visualization1/1_man_example.graphml description: '' - title: Network Visualization2 description: '' @@ -85,7 +85,7 @@ sections: plot_type: interactive_network csv_network_format: edgelist title: Man Example Edgelist - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/2_Microbial_Association_Networks/2_Network_visualization2/1_man_example_edgelist.csv + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/2_Microbial_Association_Networks/2_Network_visualization2/1_man_example_edgelist.csv description: '' - title: Network Visualization3 description: '' @@ -93,7 +93,7 @@ sections: - component_type: plot plot_type: interactive_network title: Man Example - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/2_Microbial_Association_Networks/3_Network_visualization3/1_man_example.cyjs + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/2_Microbial_Association_Networks/3_Network_visualization3/1_man_example.cyjs description: '' - title: Network Visualization4 description: '' @@ -101,5 +101,5 @@ sections: - component_type: plot plot_type: interactive_network title: Ckg Network - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/example_data/MicW2Graph/2_Microbial_Association_Networks/4_Network_visualization4/1_ckg_network.html + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/MicW2Graph/2_Microbial_Association_Networks/4_Network_visualization4/1_ckg_network.html description: '' diff --git a/docs/images/vuegen_logo.png b/docs/images/vuegen_logo.png index 9df29f4..c753e09 100644 Binary files a/docs/images/vuegen_logo.png and b/docs/images/vuegen_logo.png differ diff --git a/docs/images/vuegen_logo.svg b/docs/images/vuegen_logo.svg index 0cf4b98..a1df622 100644 --- a/docs/images/vuegen_logo.svg +++ b/docs/images/vuegen_logo.svg @@ -6,15 +6,15 @@ id="Layer_1" x="0px" y="0px" - viewBox="0 0 3360.4924 2927.5279" + viewBox="0 0 350.00011 300.00003" xml:space="preserve" sodipodi:docname="vuegen_logo.svg" inkscape:version="1.3.2 (091e20e, 2023-11-25)" - inkscape:export-filename="../../../../../../Downloads/vuegen_logo.png" + inkscape:export-filename="vuegen_logo.png" inkscape:export-xdpi="100" inkscape:export-ydpi="100" - width="889.13mm" - height="774.57501mm" + width="350" + height="300" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" @@ -28,13 +28,13 @@ inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" - inkscape:zoom="0.15856682" - inkscape:cx="1589.2354" - inkscape:cy="1645.9938" - inkscape:window-width="1440" + inkscape:zoom="0.89698939" + inkscape:cx="146.04409" + inkscape:cy="124.86212" + inkscape:window-width="1200" inkscape:window-height="847" - inkscape:window-x="0" - inkscape:window-y="25" + inkscape:window-x="1201" + inkscape:window-y="52" inkscape:window-maximized="0" inkscape:current-layer="g410" showgrid="true" @@ -59,7 +59,7 @@ diff --git a/vuegen/config_manager.py b/vuegen/config_manager.py index 7d8484c..4a01336 100644 --- a/vuegen/config_manager.py +++ b/vuegen/config_manager.py @@ -211,7 +211,6 @@ def _create_sect_config_fromdir(self, section_dir_path: Path) -> Dict[str, Union return section_config - def _resolve_base_dir(self, base_dir: str) -> Path: """ Resolves the provided base directory to an absolute path from the root, accounting for relative paths. @@ -234,11 +233,10 @@ def _resolve_base_dir(self, base_dir: str) -> Path: # Make sure the resolved base directory exists if not base_dir_path.is_dir(): - raise ValueError(f"Base directory '{base_dir}' does not exist or is not a directory.") + raise ValueError(f"Base directory '{base_dir}' does not exist or is not a directory. {project_dir} {base_dir_path}") return base_dir_path - def create_yamlconfig_fromdir(self, base_dir: str) -> Tuple[Dict[str, Union[str, List[Dict]]], Path]: """ Generates a YAML-compatible config file from a directory. It also returns the resolved folder path. diff --git a/vuegen/main.py b/vuegen/main.py index 1890a10..1bd593a 100644 --- a/vuegen/main.py +++ b/vuegen/main.py @@ -7,12 +7,11 @@ # Parse command-line arguments args = get_args(prog_name="VueGen") - # Determine the configuration file path or directory + # Determine the vuegen arguments config_path = args.config dir_path = args.directory - - # Report type report_type = args.report_type + streamlit_autorun = args.streamlit_autorun # Determine the report name for logger suffix if config_path: @@ -21,14 +20,14 @@ report_name = Path(dir_path).name # Define logger suffix based on report type and name - logger_suffix = f"{report_type}_report_{report_name}" + logger_suffix = f"{report_type}_report_{str(report_name)}" # Initialize logger logger = get_logger(f"{logger_suffix}") # Generate the report - report_generator.get_report(config_path = config_path, + report_generator.get_report(report_type = report_type, + logger = logger, + config_path = config_path, dir_path = dir_path, - report_type = report_type, - logger = logger) - + streamlit_autorun = streamlit_autorun) \ No newline at end of file diff --git a/vuegen/quarto_reportview.py b/vuegen/quarto_reportview.py index f23b188..3dd5623 100644 --- a/vuegen/quarto_reportview.py +++ b/vuegen/quarto_reportview.py @@ -1,6 +1,7 @@ import os import subprocess from typing import List +from pathlib import Path import networkx as nx import pandas as pd @@ -498,18 +499,15 @@ def _generate_image_content(self, image_path: str, alt_text: str = "", width: in Returns ------- str - The formatted HTML image content. + The formatted image content. """ if is_url(image_path): src = image_path else: - src = os.path.abspath(image_path) + src = Path(image_path).resolve() - # Return the HTML content - return f""" -
-{alt_text} -
\n""" + # Return the image content + return f"""![](/{src}){{fig-alt={alt_text} width={width} height={height}}}\n""" def _show_dataframe(self, dataframe, is_report_static, static_dir: str = STATIC_FILES_DIR) -> List[str]: """ diff --git a/vuegen/report_generator.py b/vuegen/report_generator.py index d21a4b4..c6cf752 100644 --- a/vuegen/report_generator.py +++ b/vuegen/report_generator.py @@ -7,7 +7,7 @@ from .utils import assert_enum_value, load_yaml_config, write_yaml_config -def get_report(report_type: str, logger: logging.Logger, config_path: str = None, dir_path: str = None) -> None: +def get_report(report_type: str, logger: logging.Logger, config_path: str = None, dir_path: str = None, streamlit_autorun: bool = False) -> None: """ Generate and run a report based on the specified engine. @@ -21,6 +21,8 @@ def get_report(report_type: str, logger: logging.Logger, config_path: str = None Path to the YAML configuration file. dir_path : str, optional Path to the directory from which to generate the configuration file. + streamlit_autorun : bool, optional + Whether to automatically run the Streamlit report after generation (default is False). Raises ------ @@ -47,16 +49,17 @@ def get_report(report_type: str, logger: logging.Logger, config_path: str = None # Create and run ReportView object based on its type if report_type == ReportType.STREAMLIT: st_report = StreamlitReportView( - report=report, - report_type=report_type + report = report, + report_type = report_type, + streamlit_autorun = streamlit_autorun ) st_report.generate_report() st_report.run_report() else: quarto_report = QuartoReportView( - report=report, - report_type=report_type + report = report, + report_type = report_type ) quarto_report.generate_report() quarto_report.run_report() diff --git a/vuegen/streamlit_reportview.py b/vuegen/streamlit_reportview.py index aa1bec4..c54dad1 100644 --- a/vuegen/streamlit_reportview.py +++ b/vuegen/streamlit_reportview.py @@ -18,8 +18,9 @@ class StreamlitReportView(r.WebAppReportView): STATIC_FILES_DIR = os.path.join(BASE_DIR, 'static') REPORT_MANAG_SCRIPT = 'report_manager.py' - def __init__(self, report: r.Report, report_type: r.ReportType): + def __init__(self, report: r.Report, report_type: r.ReportType, streamlit_autorun: bool = False): super().__init__(report = report, report_type = report_type) + self.streamlit_autorun = streamlit_autorun def generate_report(self, output_dir: str = SECTIONS_DIR, static_dir: str = STATIC_FILES_DIR) -> None: """ @@ -113,14 +114,20 @@ def run_report(self, output_dir: str = SECTIONS_DIR) -> None: output_dir : str, optional The folder where the report was generated (default is SECTIONS_DIR). """ - self.report.logger.info(f"Running '{self.report.title}' {self.report_type} report.") - try: - subprocess.run(["streamlit", "run", os.path.join(output_dir, self.REPORT_MANAG_SCRIPT)], check=True) - except KeyboardInterrupt: - print("Streamlit process interrupted.") - except subprocess.CalledProcessError as e: - self.report.logger.error(f"Error running Streamlit report: {str(e)}") - raise + if self.streamlit_autorun: + self.report.logger.info(f"Running '{self.report.title}' {self.report_type} report.") + try: + subprocess.run(["streamlit", "run", os.path.join(output_dir, self.REPORT_MANAG_SCRIPT)], check=True) + except KeyboardInterrupt: + print("Streamlit process interrupted.") + except subprocess.CalledProcessError as e: + self.report.logger.error(f"Error running Streamlit report: {str(e)}") + raise + else: + # If autorun is False, print instructions for manual execution + self.report.logger.info(f"All the scripts to build the Streamlit app are available at {output_dir}") + self.report.logger.info(f"To run the Streamlit app, use the following command:") + self.report.logger.info(f"streamlit run {os.path.join(output_dir, self.REPORT_MANAG_SCRIPT)}") def _format_text(self, text: str, type: str, level: int = 1, color: str = '#000000', text_align: str = 'center') -> str: """ diff --git a/vuegen/utils.py b/vuegen/utils.py index e63992b..c8a9471 100644 --- a/vuegen/utils.py +++ b/vuegen/utils.py @@ -185,16 +185,23 @@ def get_args(prog_name: str, others: dict = {}) -> argparse.Namespace: parser.add_argument( "-dir", "--directory", - type=str, - default=None, - help="Path to the directory from which the YAML config will be inferred." + type = str, + default = None, + help = "Path to the directory from which the YAML config will be inferred." ) parser.add_argument( "-rt", "--report_type", - type=str, - default='streamlit', # this is not a valid default - help="Type of the report to generate (streamlit, html, pdf, docx, odt, revealjs, pptx, or jupyter)." + type = str, + default = None, + help = "Type of the report to generate (streamlit, html, pdf, docx, odt, revealjs, pptx, or jupyter)." + ) + parser.add_argument( + "-st_autorun", + "--streamlit_autorun", + action = "store_true", # Automatically sets True if the flag is passed + default = False, + help = "Automatically run the Streamlit app after report generation." ) # Parse arguments