From 08bea0265d6aafd0f61cf60017c5cdfb963eb28b Mon Sep 17 00:00:00 2001 From: enryh Date: Sat, 1 Mar 2025 16:12:34 +0100 Subject: [PATCH 1/8] :bug: copyright symbol not recognized on Windows - use ASCI complient spelling - maybe unicode symbols could be used? --- src/vuegen/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vuegen/utils.py b/src/vuegen/utils.py index e407d34..d82cbaf 100644 --- a/src/vuegen/utils.py +++ b/src/vuegen/utils.py @@ -810,7 +810,7 @@ def generate_footer() -> str: VueGen - | © 2025 + | Copyright 2025 Multiomics Network Analytics Group (MoNA) """ From 1d44ebab9125e3b79a37f392e89b5232ed2d6e2c Mon Sep 17 00:00:00 2001 From: enryh Date: Sat, 1 Mar 2025 16:14:20 +0100 Subject: [PATCH 2/8] :bug: save streamlit report files with Posix path for each component, section etc --- src/vuegen/config_manager.py | 4 +++- src/vuegen/streamlit_reportview.py | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/vuegen/config_manager.py b/src/vuegen/config_manager.py index 4832b08..f671601 100644 --- a/src/vuegen/config_manager.py +++ b/src/vuegen/config_manager.py @@ -63,7 +63,9 @@ def _create_component_config_fromfile(self, file_path: Path) -> Dict[str, str]: # Add title, file path, and description component_config["title"] = self._create_title_fromdir(file_path.name) - component_config["file_path"] = str(file_path.resolve()) + component_config["file_path"] = ( + file_path.resolve().as_posix() + ) # ! needs to be posix for all OS support component_config["description"] = "" component_config["caption"] = "" diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index 85d9a62..4139146 100644 --- a/src/vuegen/streamlit_reportview.py +++ b/src/vuegen/streamlit_reportview.py @@ -1,5 +1,6 @@ import os import subprocess +from pathlib import Path from typing import List import pandas as pd @@ -106,9 +107,9 @@ def generate_report( for subsection in section.subsections: subsection_name_var = subsection.title.replace(" ", "_") - subsection_file_path = os.path.join( - section_name_var, subsection_name_var + ".py" - ) + subsection_file_path = ( + Path(section_name_var) / f"{subsection_name_var}.py" + ).as_posix() # Make sure it's Posix Paths # Create a Page object for each subsection and add it to the home page content report_manag_content.append( @@ -274,7 +275,7 @@ def _generate_home_section( # Add the home page to the report manager content report_manag_content.append( - f"homepage = st.Page('Home/Homepage.py', title='Homepage')" + f"homepage = st.Page('Home/Homepage.py', title='Homepage')" # ! here Posix Path is hardcoded ) report_manag_content.append(f"sections_pages['Home'] = [homepage]\n") self.report.logger.info("Home page added to the report manager content.") From 7eec0ea3e4cb0455c64e9436b645a7845d901f30 Mon Sep 17 00:00:00 2001 From: sayalaruano Date: Mon, 3 Mar 2025 10:39:09 +0100 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=90=9B=20Fix(quarto=5Freportview.py):?= =?UTF-8?q?=20Replace=20copyright=20symbol=20in=20quarto=20reports=20for?= =?UTF-8?q?=20Windows=20compatibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...icrobiome_vuegen_demo_notebook_config.yaml | 98 +++++++++---------- src/vuegen/quarto_reportview.py | 6 +- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml b/docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml index c7847d5..f6c4a91 100644 --- a/docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml +++ b/docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml @@ -21,30 +21,30 @@ sections: description: '' components: - title: Metadata Random Subset - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/1_metadata_random_subset.csv + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/1_metadata_random_subset.csv description: '' caption: '' - component_type: DATAFRAME - file_format: CSV + component_type: dataframe + file_format: csv delimiter: ',' - title: Animal Samples Map - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/2_animal_samples_map.png + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/2_animal_samples_map.png description: '' caption: '' - component_type: PLOT - plot_type: STATIC + component_type: plot + plot_type: static - title: Plant Samples Map - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/3_plant_samples_map.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/3_plant_samples_map.json description: '' caption: '' - component_type: PLOT - plot_type: PLOTLY + component_type: plot + plot_type: plotly - title: Saline Samples Map - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/4_saline_samples_map.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/4_saline_samples_map.json description: '' caption: '' - component_type: PLOT - plot_type: ALTAIR + component_type: plot + plot_type: altair - title: Metagenomics description: '' subsections: @@ -52,66 +52,66 @@ sections: description: '' components: - title: Alpha Diversity Host Associated Samples - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/1_alpha_diversity/1_alpha_diversity_host_associated_samples.png + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/1_alpha_diversity/1_alpha_diversity_host_associated_samples.png description: '' caption: '' - component_type: PLOT - plot_type: STATIC + component_type: plot + plot_type: static - title: Alpha Diversity Free Living Samples - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/1_alpha_diversity/2_alpha_diversity_free_living_samples.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/1_alpha_diversity/2_alpha_diversity_free_living_samples.json description: '' caption: '' - component_type: PLOT - plot_type: PLOTLY + component_type: plot + plot_type: plotly - title: Average Copy Number description: '' components: - title: Average Copy Number Emp Ontology Level2 - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/2_average_copy_number/1_average_copy_number_emp_ontology_level2.png + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/2_average_copy_number/1_average_copy_number_emp_ontology_level2.png description: '' caption: '' - component_type: PLOT - plot_type: STATIC + component_type: plot + plot_type: static - title: Average Copy Number Emp Ontology Level3 - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/2_average_copy_number/2_average_copy_number_emp_ontology_level3.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/2_average_copy_number/2_average_copy_number_emp_ontology_level3.json description: '' caption: '' - component_type: PLOT - plot_type: PLOTLY + component_type: plot + plot_type: plotly - title: Nestedness description: '' components: - title: Nestedness Random Subset - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/1_nestedness_random_subset.csv + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/1_nestedness_random_subset.csv description: '' caption: '' - component_type: DATAFRAME - file_format: CSV + component_type: dataframe + file_format: csv delimiter: ',' - title: All Samples - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/2_all_samples.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/2_all_samples.json description: '' caption: '' - component_type: PLOT - plot_type: PLOTLY + component_type: plot + plot_type: plotly - title: Plant Samples - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/3_plant_samples.json + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/3_plant_samples.json description: '' caption: '' - component_type: PLOT - plot_type: PLOTLY + component_type: plot + plot_type: plotly - title: Animal Samples - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/4_animal_samples.png + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/4_animal_samples.png description: '' caption: '' - component_type: PLOT - plot_type: STATIC + component_type: plot + plot_type: static - title: Non Saline Samples - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/5_non_saline_samples.png + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/5_non_saline_samples.png description: '' caption: '' - component_type: PLOT - plot_type: STATIC + component_type: plot + plot_type: static - title: Network Analysis description: '' subsections: @@ -119,22 +119,22 @@ sections: description: '' components: - title: Phyla Counts Subset - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/1_phyla_counts_subset.csv + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/1_phyla_counts_subset.csv description: '' caption: '' - component_type: DATAFRAME - file_format: CSV + component_type: dataframe + file_format: csv delimiter: ',' - title: Phyla Correlation Network With 0.5 Threshold Edgelist - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/2_phyla_correlation_network_with_0.5_threshold_edgelist.csv + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/2_phyla_correlation_network_with_0.5_threshold_edgelist.csv description: '' caption: '' - component_type: PLOT - plot_type: INTERACTIVE_NETWORK - csv_network_format: EDGELIST + component_type: plot + plot_type: interactive_network + csv_network_format: edgelist - title: Phyla Correlation Network With 0.5 Threshold - file_path: example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/3_phyla_correlation_network_with_0.5_threshold.png + file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/3_phyla_correlation_network_with_0.5_threshold.png description: '' caption: '' - component_type: PLOT - plot_type: STATIC + component_type: plot + plot_type: static diff --git a/src/vuegen/quarto_reportview.py b/src/vuegen/quarto_reportview.py index 600174d..3ddc52f 100644 --- a/src/vuegen/quarto_reportview.py +++ b/src/vuegen/quarto_reportview.py @@ -227,7 +227,7 @@ def _create_yaml_header(self) -> str: VueGen - | © 2025 Multiomics Network Analytics Group (MoNA) + | Copyright 2025 Multiomics Network Analytics Group (MoNA) """, r.ReportType.PDF: """ pdf: @@ -273,7 +273,7 @@ def _create_yaml_header(self) -> str: VueGen - | © 2025 Multiomics Network Analytics Group (MoNA) + | Copyright 2025 Multiomics Network Analytics Group (MoNA) """, r.ReportType.PPTX: """ pptx: @@ -304,7 +304,7 @@ def _create_yaml_header(self) -> str: VueGen - | © 2025 Multiomics Network Analytics Group (MoNA) + | Copyright 2025 Multiomics Network Analytics Group (MoNA) """, } # Create a key based on the report type and format From dd4f9611df45ca58f45d9e1a2f41ffd8ed7a9206 Mon Sep 17 00:00:00 2001 From: sayalaruano Date: Mon, 3 Mar 2025 11:26:41 +0100 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=8E=A8=20Style(streamlit=5Freportview?= =?UTF-8?q?.py):=20use=20Papth=20lib=20for=20all=20paths=20in=20the=20stre?= =?UTF-8?q?amlit=20reports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vuegen/report.py | 2 +- src/vuegen/streamlit_reportview.py | 36 +++++++++++++----------------- src/vuegen/utils.py | 25 +++++---------------- 3 files changed, 21 insertions(+), 42 deletions(-) diff --git a/src/vuegen/report.py b/src/vuegen/report.py index 8564a1d..be2315d 100644 --- a/src/vuegen/report.py +++ b/src/vuegen/report.py @@ -382,7 +382,7 @@ def create_and_save_pyvis_network(self, G: nx.Graph, output_file: str) -> Networ net.show_buttons(filter_=["physics"]) # Save the network as an HTML file - net.save_graph(output_file) + net.save_graph(str(output_file)) self.logger.info(f"PyVis network created and saved as: {output_file}.") return net diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index 4139146..eaa0c60 100644 --- a/src/vuegen/streamlit_reportview.py +++ b/src/vuegen/streamlit_reportview.py @@ -15,8 +15,8 @@ class StreamlitReportView(r.WebAppReportView): """ BASE_DIR = "streamlit_report" - SECTIONS_DIR = os.path.join(BASE_DIR, "sections") - STATIC_FILES_DIR = os.path.join(BASE_DIR, "static") + SECTIONS_DIR = Path(BASE_DIR) / "sections" + STATIC_FILES_DIR = Path(BASE_DIR) / "static" REPORT_MANAG_SCRIPT = "report_manager.py" def __init__( @@ -94,7 +94,7 @@ def generate_report( # Create a folder for each section subsection_page_vars = [] section_name_var = section.title.replace(" ", "_") - section_dir_path = os.path.join(output_dir, section_name_var) + section_dir_path = Path(output_dir) / section_name_var if create_folder(section_dir_path): self.report.logger.debug( @@ -130,7 +130,7 @@ def generate_report( # Write the navigation and general content to a Python file with open( - os.path.join(output_dir, self.REPORT_MANAG_SCRIPT), "w" + Path(output_dir) / self.REPORT_MANAG_SCRIPT, "w" ) as nav_manager: nav_manager.write("\n".join(report_manag_content)) self.report.logger.info( @@ -163,7 +163,7 @@ def run_report(self, output_dir: str = SECTIONS_DIR) -> None: [ "streamlit", "run", - os.path.join(output_dir, self.REPORT_MANAG_SCRIPT), + Path(output_dir) / self.REPORT_MANAG_SCRIPT, ], check=True, ) @@ -181,12 +181,12 @@ def run_report(self, output_dir: str = SECTIONS_DIR) -> None: 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)}" + f"streamlit run {Path(output_dir) / self.REPORT_MANAG_SCRIPT}" ) msg = ( f"\nAll the scripts to build the Streamlit app are available at: {output_dir}\n\n" f"To run the Streamlit app, use the following command:\n\n" - f"\tstreamlit run {os.path.join(output_dir, self.REPORT_MANAG_SCRIPT)}" + f"\tstreamlit run {Path(output_dir) / self.REPORT_MANAG_SCRIPT}" ) print(msg) @@ -243,7 +243,7 @@ def _generate_home_section( try: # Create folder for the home page - home_dir_path = os.path.join(output_dir, "Home") + home_dir_path = Path(output_dir) / "Home" if create_folder(home_dir_path): self.report.logger.debug(f"Created home directory: {home_dir_path}") else: @@ -268,7 +268,7 @@ def _generate_home_section( home_content.append("st.markdown(footer, unsafe_allow_html=True)\n") # Write the home page content to a Python file - home_page_path = os.path.join(home_dir_path, "Homepage.py") + home_page_path = Path(home_dir_path) / "Homepage.py" with open(home_page_path, "w") as home_page: home_page.write("\n".join(home_content)) self.report.logger.info(f"Home page content written to '{home_page_path}'.") @@ -309,11 +309,7 @@ def _generate_sections(self, output_dir: str) -> None: ) try: # Create subsection file - subsection_file_path = os.path.join( - output_dir, - section_name_var, - subsection.title.replace(" ", "_") + ".py", - ) + subsection_file_path = Path(output_dir) / section_name_var / f"{subsection.title.replace(' ', '_')}.py" # Generate content and imports for the subsection subsection_content, subsection_imports = ( @@ -461,9 +457,7 @@ def _generate_plot_content( networkx_graph, html_plot_file = networkx_graph else: # Otherwise, create and save a new pyvis network from the netowrkx graph - html_plot_file = os.path.join( - static_dir, f"{plot.title.replace(' ', '_')}.html" - ) + html_plot_file = Path(static_dir) / f"{plot.title.replace(' ', '_')}.html" pyvis_graph = plot.create_and_save_pyvis_network( networkx_graph, html_plot_file ) @@ -532,7 +526,7 @@ def _generate_plot_code(self, plot) -> str: plot_json = json.loads(response.text)\n""" else: # If it's a local file plot_code = f""" -with open('{os.path.join(plot.file_path)}', 'r') as plot_file: +with open('{Path(plot.file_path)}', 'r') as plot_file: plot_json = json.load(plot_file)\n""" # Add specific code for each visualization tool @@ -585,7 +579,7 @@ def _generate_dataframe_content(self, dataframe) -> List[str]: try: # Check if the file extension matches any DataFrameFormat value - file_extension = os.path.splitext(dataframe.file_path)[1].lower() + file_extension = Path(dataframe.file_path).suffix.lower() if not any( file_extension == fmt.value_with_dot for fmt in r.DataFrameFormat ): @@ -675,7 +669,7 @@ def _generate_markdown_content(self, markdown) -> List[str]: else: # If it's a local file markdown_content.append( f""" -with open('{os.path.join("..", markdown.file_path)}', 'r') as markdown_file: +with open('{Path("..") / markdown.file_path}', 'r') as markdown_file: markdown_content = markdown_file.read()\n""" ) # Code to display md content @@ -735,7 +729,7 @@ def _generate_html_content(self, html) -> List[str]: # If it's a local file html_content.append( f""" -with open('{os.path.join("..", html.file_path)}', 'r', encoding='utf-8') as html_file: +with open('{Path("..") / html.file_path}', 'r', encoding='utf-8') as html_file: html_content = html_file.read()\n""" ) diff --git a/src/vuegen/utils.py b/src/vuegen/utils.py index d82cbaf..d11f103 100644 --- a/src/vuegen/utils.py +++ b/src/vuegen/utils.py @@ -24,27 +24,20 @@ ## CHECKS -def check_path(filepath: str) -> bool: +def check_path(filepath: Path) -> bool: """ Checks if the given file or folder path exists. Parameters --------- - filepath : str + filepath : Path The file or folder path to check. Returns ------- bool True if the path exists, False otherwise. - - Raises - ------ - AssertionError - If the filepath is not a valid string. """ - # Assert that the filepath is a string - assert isinstance(filepath, str), f"Filepath must be a string: {filepath}" # Check if the path exists return os.path.exists(os.path.abspath(filepath)) @@ -87,13 +80,13 @@ def assert_enum_value( ) -def is_url(filepath: str) -> bool: +def is_url(filepath: Path) -> bool: """ Check if the provided path is a valid URL. Parameters ---------- - filepath : str + filepath : Path The filepath to check. Returns @@ -102,17 +95,9 @@ def is_url(filepath: str) -> bool: True if the input path is a valid URL, meaning it contains both a scheme (e.g., http, https, ftp) and a network location (e.g., example.com). Returns False if either the scheme or the network location is missing or invalid. - - Raises - ------ - AssertionError - If the filepath is not a valid string. """ - # Assert that the filepath is a string - assert isinstance(filepath, str), f"Filepath must be a string: {filepath}" - # Parse the url and return validation - parsed_url = urlparse(filepath) + parsed_url = urlparse(str(filepath)) return bool(parsed_url.scheme and parsed_url.netloc) From 6a73ea66265842927639b80e09c1af70db1181e1 Mon Sep 17 00:00:00 2001 From: sayalaruano Date: Mon, 3 Mar 2025 12:21:57 +0100 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=8E=A8=20Style(quarto=5Freportview.py?= =?UTF-8?q?):=20use=20Path=20lib=20for=20all=20paths=20in=20the=20quarto?= =?UTF-8?q?=20reports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vuegen/quarto_reportview.py | 38 ++++++++++++++------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/vuegen/quarto_reportview.py b/src/vuegen/quarto_reportview.py index 3ddc52f..52c8be9 100644 --- a/src/vuegen/quarto_reportview.py +++ b/src/vuegen/quarto_reportview.py @@ -16,7 +16,7 @@ class QuartoReportView(r.ReportView): """ BASE_DIR = "quarto_report" - STATIC_FILES_DIR = os.path.join(BASE_DIR, "static") + STATIC_FILES_DIR = Path(BASE_DIR) / "static" def __init__(self, report: r.Report, report_type: r.ReportType): super().__init__(report=report, report_type=report_type) @@ -125,7 +125,7 @@ def generate_report( # Write the navigation and general content to a Python file with open( - os.path.join(output_dir, f"{self.BASE_DIR}.qmd"), "w" + Path(output_dir) / f"{self.BASE_DIR}.qmd", "w" ) as quarto_report: quarto_report.write(yaml_header) quarto_report.write( @@ -156,7 +156,7 @@ def run_report(self, output_dir: str = BASE_DIR) -> None: """ try: subprocess.run( - ["quarto", "render", os.path.join(output_dir, f"{self.BASE_DIR}.qmd")], + ["quarto", "render", Path(output_dir) / f"{self.BASE_DIR}.qmd"], check=True, ) if self.report_type == r.ReportType.JUPYTER: @@ -164,7 +164,7 @@ def run_report(self, output_dir: str = BASE_DIR) -> None: [ "quarto", "convert", - os.path.join(output_dir, f"{self.BASE_DIR}.qmd"), + Path(output_dir) / f"{self.BASE_DIR}.qmd", ], check=True, ) @@ -413,13 +413,9 @@ def _generate_plot_content( # Define plot path if is_report_static: - static_plot_path = os.path.join( - static_dir, f"{plot.title.replace(' ', '_')}.png" - ) + static_plot_path = Path(static_dir) / f"{plot.title.replace(' ', '_')}.png" else: - html_plot_file = os.path.join( - static_dir, f"{plot.title.replace(' ', '_')}.html" - ) + html_plot_file = Path(static_dir) / f"{plot.title.replace(' ', '_')}.html" # Add content for the different plot types try: @@ -431,7 +427,7 @@ def _generate_plot_content( plot_content.append(self._generate_plot_code(plot)) if is_report_static: plot_content.append( - f"""fig_plotly.write_image("{os.path.abspath(static_plot_path)}")\n```\n""" + f"""fig_plotly.write_image("{static_plot_path.resolve()}")\n```\n""" ) plot_content.append(self._generate_image_content(static_plot_path)) else: @@ -440,7 +436,7 @@ def _generate_plot_content( plot_content.append(self._generate_plot_code(plot)) if is_report_static: plot_content.append( - f"""fig_altair.save("{os.path.abspath(static_plot_path)}")\n```\n""" + f"""fig_altair.save("{static_plot_path.resolve()}")\n```\n""" ) plot_content.append(self._generate_image_content(static_plot_path)) else: @@ -513,7 +509,7 @@ def _generate_plot_code(self, plot, output_file="") -> str: plot_json = response.text\n""" else: # If it's a local file plot_code += f""" -with open('{os.path.join("..", plot.file_path)}', 'r') as plot_file: +with open('{Path("..") / plot.file_path}', 'r') as plot_file: plot_json = plot_file.read()\n""" # Add specific code for each visualization tool if plot.plot_type == r.PlotType.PLOTLY: @@ -527,7 +523,7 @@ def _generate_plot_code(self, plot, output_file="") -> str: if is_url(plot.file_path) and plot.file_path.endswith(".html"): iframe_src = output_file else: - iframe_src = os.path.join("..", output_file) + iframe_src = Path("..") / output_file # Embed the HTML file in an iframe plot_code = f""" @@ -573,7 +569,7 @@ def _generate_dataframe_content(self, dataframe, is_report_static) -> List[str]: } try: # Check if the file extension matches any DataFrameFormat value - file_extension = os.path.splitext(dataframe.file_path)[1].lower() + file_extension = Path(dataframe.file_path).suffix.lower() if not any( file_extension == fmt.value_with_dot for fmt in r.DataFrameFormat ): @@ -585,7 +581,7 @@ def _generate_dataframe_content(self, dataframe, is_report_static) -> List[str]: file_path = ( dataframe.file_path if is_url(dataframe.file_path) - else os.path.join("..", dataframe.file_path) + else Path("..") / dataframe.file_path ) # Load the DataFrame using the correct function @@ -648,7 +644,7 @@ def _generate_markdown_content(self, markdown) -> List[str]: else: # If it's a local file markdown_content.append( f""" -with open('{os.path.join("..", markdown.file_path)}', 'r') as markdown_file: +with open('{Path("..") / markdown.file_path}', 'r') as markdown_file: markdown_content = markdown_file.read()\n""" ) @@ -694,7 +690,7 @@ def _generate_html_content(self, html) -> List[str]: iframe_src = ( html.file_path if is_url(html.file_path) - else os.path.join("..", html.file_path) + else Path("..") / html.file_path ) iframe_code = f"""
@@ -769,11 +765,9 @@ def _show_dataframe( dataframe_content = [] if is_report_static: # Generate path for the DataFrame image - df_image = os.path.join( - static_dir, f"{dataframe.title.replace(' ', '_')}.png" - ) + df_image = Path(static_dir) / f"{dataframe.title.replace(' ', '_')}.png" dataframe_content.append( - f"df.dfi.export('{os.path.abspath(df_image)}', max_rows=10, max_cols=5)\n```\n" + f"df.dfi.export('{Path(df_image).resolve()}', max_rows=10, max_cols=5)\n```\n" ) # Use helper method to add centered image content dataframe_content.append(self._generate_image_content(df_image)) From 904d8fd4b68719063d843e17c11c614762cdc651 Mon Sep 17 00:00:00 2001 From: sayalaruano Date: Mon, 3 Mar 2025 12:24:48 +0100 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=90=9B=20Fix:=20correct=20terminal=20?= =?UTF-8?q?message=20after=20execution?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vuegen/utils.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/vuegen/utils.py b/src/vuegen/utils.py index d11f103..41fa4e7 100644 --- a/src/vuegen/utils.py +++ b/src/vuegen/utils.py @@ -734,22 +734,20 @@ def print_completion_message(report_type: str): Prints a formatted completion message after report generation. """ border = "─" * 65 # Creates a separator line - print(f"\n{border}\n🎉 Pipeline Execution Complete! 🎉\n") - if report_type == "streamlit": print( """🚀 Streamlit Report Generated! 📂 All scripts to build the Streamlit app are available at: - nf_container_results/streamlit_report/sections + streamlit_report/sections ▶️ To run the Streamlit app, use the following command: - streamlit run nf_container_results/streamlit_report/sections/report_manager.py + streamlit run streamlit_report/sections/report_manager.py ✨ You can extend the report by adding new files to the input directory or updating the config file. 🛠️ Advanced users can modify the Python scripts directly in: - nf_container_results/streamlit_report/sections + streamlit_report/sections """ ) else: @@ -757,12 +755,12 @@ def print_completion_message(report_type: str): f"""🚀 {report_type.capitalize()} Report Generated! 📂 Your {report_type} report is available at: - nf_container_results/quarto_report + quarto_report ✨ You can extend the report by adding new files to the input directory or updating the config file. 🛠️ Advanced users can modify the report template directly in: - nf_container_results/quarto_report/quarto_report.qmd + quarto_report/quarto_report.qmd """ ) From 5e583a6d1b00e2e1d6e619cf25d7dc650c243cff Mon Sep 17 00:00:00 2001 From: sayalaruano Date: Mon, 3 Mar 2025 12:26:24 +0100 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=8E=A8=20Style:=20add=20black=20forma?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vuegen/quarto_reportview.py | 4 +--- src/vuegen/streamlit_reportview.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/vuegen/quarto_reportview.py b/src/vuegen/quarto_reportview.py index 52c8be9..1dfd75d 100644 --- a/src/vuegen/quarto_reportview.py +++ b/src/vuegen/quarto_reportview.py @@ -124,9 +124,7 @@ def generate_report( report_formatted_imports = "\n".join(report_unique_imports) # Write the navigation and general content to a Python file - with open( - Path(output_dir) / f"{self.BASE_DIR}.qmd", "w" - ) as quarto_report: + with open(Path(output_dir) / f"{self.BASE_DIR}.qmd", "w") as quarto_report: quarto_report.write(yaml_header) quarto_report.write( f"""\n```{{python}} diff --git a/src/vuegen/streamlit_reportview.py b/src/vuegen/streamlit_reportview.py index eaa0c60..1a9bb76 100644 --- a/src/vuegen/streamlit_reportview.py +++ b/src/vuegen/streamlit_reportview.py @@ -129,9 +129,7 @@ def generate_report( ) # Write the navigation and general content to a Python file - with open( - Path(output_dir) / self.REPORT_MANAG_SCRIPT, "w" - ) as nav_manager: + with open(Path(output_dir) / self.REPORT_MANAG_SCRIPT, "w") as nav_manager: nav_manager.write("\n".join(report_manag_content)) self.report.logger.info( f"Created app navigation script: {self.REPORT_MANAG_SCRIPT}" @@ -309,7 +307,11 @@ def _generate_sections(self, output_dir: str) -> None: ) try: # Create subsection file - subsection_file_path = Path(output_dir) / section_name_var / f"{subsection.title.replace(' ', '_')}.py" + subsection_file_path = ( + Path(output_dir) + / section_name_var + / f"{subsection.title.replace(' ', '_')}.py" + ) # Generate content and imports for the subsection subsection_content, subsection_imports = ( @@ -457,7 +459,9 @@ def _generate_plot_content( networkx_graph, html_plot_file = networkx_graph else: # Otherwise, create and save a new pyvis network from the netowrkx graph - html_plot_file = Path(static_dir) / f"{plot.title.replace(' ', '_')}.html" + html_plot_file = ( + Path(static_dir) / f"{plot.title.replace(' ', '_')}.html" + ) pyvis_graph = plot.create_and_save_pyvis_network( networkx_graph, html_plot_file ) From 0bf86fc88b16ab05c6a1b88c7c26f0f5003e5995 Mon Sep 17 00:00:00 2001 From: sayalaruano Date: Mon, 3 Mar 2025 12:37:07 +0100 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=93=9D=20Docs:=20remove=20yaml=20file?= =?UTF-8?q?=20example=20from=20the=20EMP=20folder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...icrobiome_vuegen_demo_notebook_config.yaml | 140 ------------------ 1 file changed, 140 deletions(-) delete mode 100644 docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml diff --git a/docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml b/docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml deleted file mode 100644 index f6c4a91..0000000 --- a/docs/example_data/Earth_microbiome_vuegen_demo_notebook/Earth_microbiome_vuegen_demo_notebook_config.yaml +++ /dev/null @@ -1,140 +0,0 @@ -report: - title: Earth Microbiome Vuegen Demo Notebook - description: "The Earth Microbiome Project (EMP) is a systematic attempt to characterize\ - \ global microbial taxonomic and functional diversity for the benefit of the planet\ - \ and humankind. \n It aimed to sample the Earth\u2019s microbial communities\ - \ at an unprecedented scale in order to advance our understanding of the organizing\ - \ biogeographic principles that govern microbial community structure. \n The\ - \ EMP dataset is generated from samples that individual researchers have compiled\ - \ and contributed to the EMP. \n The result is both a reference database giving\ - \ global context to DNA sequence data and a framework for incorporating data from\ - \ future studies, fostering increasingly complete characterization of Earth\u2019\ - s microbial diversity.\n \n You can find more information about the Earth Microbiome\ - \ Project at https://earthmicrobiome.org/ and in the [original article](https://www.nature.com/articles/nature24621).\n" - graphical_abstract: '' - logo: '' -sections: -- title: Exploratory Data Analysis - description: '' - subsections: - - title: Sample Exploration - description: '' - components: - - title: Metadata Random Subset - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/1_metadata_random_subset.csv - description: '' - caption: '' - component_type: dataframe - file_format: csv - delimiter: ',' - - title: Animal Samples Map - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/2_animal_samples_map.png - description: '' - caption: '' - component_type: plot - plot_type: static - - title: Plant Samples Map - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/3_plant_samples_map.json - description: '' - caption: '' - component_type: plot - plot_type: plotly - - title: Saline Samples Map - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/1_Exploratory_data_analysis/1_sample_exploration/4_saline_samples_map.json - description: '' - caption: '' - component_type: plot - plot_type: altair -- title: Metagenomics - description: '' - subsections: - - title: Alpha Diversity - description: '' - components: - - title: Alpha Diversity Host Associated Samples - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/1_alpha_diversity/1_alpha_diversity_host_associated_samples.png - description: '' - caption: '' - component_type: plot - plot_type: static - - title: Alpha Diversity Free Living Samples - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/1_alpha_diversity/2_alpha_diversity_free_living_samples.json - description: '' - caption: '' - component_type: plot - plot_type: plotly - - title: Average Copy Number - description: '' - components: - - title: Average Copy Number Emp Ontology Level2 - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/2_average_copy_number/1_average_copy_number_emp_ontology_level2.png - description: '' - caption: '' - component_type: plot - plot_type: static - - title: Average Copy Number Emp Ontology Level3 - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/2_average_copy_number/2_average_copy_number_emp_ontology_level3.json - description: '' - caption: '' - component_type: plot - plot_type: plotly - - title: Nestedness - description: '' - components: - - title: Nestedness Random Subset - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/1_nestedness_random_subset.csv - description: '' - caption: '' - component_type: dataframe - file_format: csv - delimiter: ',' - - title: All Samples - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/2_all_samples.json - description: '' - caption: '' - component_type: plot - plot_type: plotly - - title: Plant Samples - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/3_plant_samples.json - description: '' - caption: '' - component_type: plot - plot_type: plotly - - title: Animal Samples - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/4_animal_samples.png - description: '' - caption: '' - component_type: plot - plot_type: static - - title: Non Saline Samples - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/2_Metagenomics/3_nestedness/5_non_saline_samples.png - description: '' - caption: '' - component_type: plot - plot_type: static -- title: Network Analysis - description: '' - subsections: - - title: Phyla Association Networks - description: '' - components: - - title: Phyla Counts Subset - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/1_phyla_counts_subset.csv - description: '' - caption: '' - component_type: dataframe - file_format: csv - delimiter: ',' - - title: Phyla Correlation Network With 0.5 Threshold Edgelist - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/2_phyla_correlation_network_with_0.5_threshold_edgelist.csv - description: '' - caption: '' - component_type: plot - plot_type: interactive_network - csv_network_format: edgelist - - title: Phyla Correlation Network With 0.5 Threshold - file_path: /Users/asaru/Documents/DTU/MoNA/vuegen/docs/example_data/Earth_microbiome_vuegen_demo_notebook/3_Network_analysis/1_phyla_association_networks/3_phyla_correlation_network_with_0.5_threshold.png - description: '' - caption: '' - component_type: plot - plot_type: static