diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a8595e2..3a4e1b6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -53,9 +53,9 @@ jobs: # path: docs/_build/ # --- Streamlit example deployment --- - - name: Fix Absolute Paths in Streamlit Scripts - run: | - find docs/streamlit_report/sections -type f -name "*.py" -exec sed -i 's|/home/runner/work/vuegen/vuegen/docs/||g' {} + + #- name: Fix Absolute Paths in Streamlit Scripts + # run: | + # find docs/streamlit_report/sections -type f -name "*.py" -exec sed -i 's|/home/runner/work/vuegen/vuegen/docs/||g' {} + - name: Publish Streamlit report to streamlit-example branch if: startsWith(github.ref, 'refs/tags') uses: peaceiris/actions-gh-pages@v4 diff --git a/.gitignore b/.gitignore index 07a36e9..6c57dc2 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,5 @@ docs/images/UML_diagrams/ docs/images/Graphical_abstract/ docs/images/Nfcore_module_figure docs/presentations/ -docs/example_data/Earth_microbiome_vuegen_demo_notebook_test/ -docs/vuegen_case_study_earth_microbiome_test.ipynb -test.py \ No newline at end of file +basic_example_vuegen_demo_notebook_config.yaml +earth_microbiome_vuegen_demo_notebook_config.yaml \ No newline at end of file diff --git a/docs/images/vuegen_classdiagram_noattmeth.png b/docs/images/vuegen_classdiagram_noattmeth.png index 0016c90..9b044a2 100644 Binary files a/docs/images/vuegen_classdiagram_noattmeth.png and b/docs/images/vuegen_classdiagram_noattmeth.png differ diff --git a/docs/index.md b/docs/index.md index 1aff99b..a06f429 100644 --- a/docs/index.md +++ b/docs/index.md @@ -35,7 +35,7 @@ vuegen_Chatbot_configfile ```{toctree} :maxdepth: 2 -:caption: Modules +:caption: API Reference :hidden: reference/vuegen diff --git a/docs/vuegen_basic_case_study.ipynb b/docs/vuegen_basic_case_study.ipynb index 3c17cdd..431511e 100644 --- a/docs/vuegen_basic_case_study.ipynb +++ b/docs/vuegen_basic_case_study.ipynb @@ -139,10 +139,9 @@ "outputs": [], "source": [ "# Imports\n", - "import os\n", "import yaml\n", "from vuegen import report_generator\n", - "from vuegen.utils import get_logger, load_yaml_config\n", + "from vuegen.utils import load_yaml_config\n", "\n", "if IN_COLAB:\n", " import urllib" @@ -444,7 +443,7 @@ ], "metadata": { "kernelspec": { - "display_name": "vuegen_py312", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -458,9 +457,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.9" + "version": "3.12.6" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/vuegen/quarto_reportview.py b/src/vuegen/quarto_reportview.py index cd3881b..545da41 100644 --- a/src/vuegen/quarto_reportview.py +++ b/src/vuegen/quarto_reportview.py @@ -8,7 +8,7 @@ import pandas as pd from . import report as r -from .utils import create_folder, is_url, sort_imports +from .utils import create_folder, get_relative_file_path, is_url, sort_imports class QuartoReportView(r.ReportView): @@ -365,6 +365,7 @@ def _create_yaml_header(self) -> str: r.ReportType.PDF: """ pdf: toc: false + fig-align: center margin: - bottom=40mm include-in-header: @@ -568,13 +569,13 @@ def _generate_plot_content(self, plot) -> List[str]: try: if plot.plot_type == r.PlotType.STATIC: plot_content.append( - self._generate_image_content(plot.file_path, width=950) + self._generate_image_content(plot.file_path, width="90%") ) elif plot.plot_type == r.PlotType.PLOTLY: plot_content.append(self._generate_plot_code(plot)) if self.is_report_static: plot_content.append( - f"""fig_plotly.write_image("{static_plot_path.resolve().as_posix()}")\n```\n""" + f"""fig_plotly.write_image("{static_plot_path.relative_to("quarto_report").as_posix()}")\n```\n""" ) plot_content.append(self._generate_image_content(static_plot_path)) else: @@ -583,7 +584,7 @@ def _generate_plot_content(self, plot) -> List[str]: plot_content.append(self._generate_plot_code(plot)) if self.is_report_static: plot_content.append( - f"""fig_altair.save("{static_plot_path.resolve().as_posix()}")\n```\n""" + f"""fig_altair.save("{static_plot_path.relative_to("quarto_report").as_posix()}")\n```\n""" ) plot_content.append(self._generate_image_content(static_plot_path)) else: @@ -655,8 +656,9 @@ def _generate_plot_code(self, plot, output_file="") -> str: response.raise_for_status() plot_json = response.text\n""" else: # If it's a local file + plot_rel_path = get_relative_file_path(plot.file_path, base_path="..") plot_code += f""" -with open('{(Path("..") / plot.file_path).as_posix()}', 'r') as plot_file: +with open('{plot_rel_path.as_posix()}', 'r') as plot_file: plot_json = json.load(plot_file)\n""" # Add specific code for each visualization tool if plot.plot_type == r.PlotType.PLOTLY: @@ -669,13 +671,13 @@ def _generate_plot_code(self, plot, output_file="") -> str: 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""" +fig_plotly.update_layout(autosize=False, width=950, height=400, margin=dict(b=50, t=50, l=50, r=50))\n""" elif plot.plot_type == r.PlotType.ALTAIR: 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""" +fig_altair = alt.Chart.from_json(plot_json_str).properties(width=900, height=370)\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"): @@ -734,16 +736,17 @@ def _generate_dataframe_content(self, dataframe) -> List[str]: ) # Build the file path (URL or local file) - file_path = ( - dataframe.file_path - if is_url(dataframe.file_path) - else Path("..") / dataframe.file_path - ) + if is_url(dataframe.file_path): + df_file_path = dataframe.file_path + else: + df_file_path = get_relative_file_path( + dataframe.file_path, base_path=".." + ) # Load the DataFrame using the correct function read_function = read_function_mapping[file_extension] dataframe_content.append( - f"""df = pd.{read_function.__name__}('{file_path.as_posix()}')\n""" + f"""df = pd.{read_function.__name__}('{df_file_path.as_posix()}')\n""" ) # Display the dataframe @@ -798,9 +801,10 @@ def _generate_markdown_content(self, markdown) -> List[str]: markdown_content = response.text\n""" ) else: # If it's a local file + md_rel_path = get_relative_file_path(markdown.file_path, base_path="..") markdown_content.append( f""" -with open('{(Path("..") / markdown.file_path).as_posix()}', 'r') as markdown_file: +with open('{md_rel_path.as_posix()}', 'r') as markdown_file: markdown_content = markdown_file.read()\n""" ) @@ -822,6 +826,39 @@ def _generate_markdown_content(self, markdown) -> List[str]: ) return markdown_content + def _show_dataframe(self, dataframe) -> List[str]: + """ + Appends either a static image or an interactive representation of a DataFrame to the content list. + + Parameters + ---------- + dataframe : DataFrame + The DataFrame object containing the data to display. + + Returns + ------- + list : List[str] + The list of content lines for the DataFrame. + """ + dataframe_content = [] + if self.is_report_static: + # Generate path for the DataFrame image + df_image = ( + Path(self.static_dir) / f"{dataframe.title.replace(' ', '_')}.png" + ) + dataframe_content.append( + f"df.dfi.export('{Path(df_image).relative_to('quarto_report').as_posix()}', max_rows=10, max_cols=5, table_conversion='matplotlib')\n```\n" + ) + # Use helper method to add centered image content + dataframe_content.append(self._generate_image_content(df_image)) + else: + # Append code to display the DataFrame interactively + dataframe_content.append( + """show(df, classes="display nowrap compact", lengthMenu=[3, 5, 10])\n```\n""" + ) + + return dataframe_content + def _generate_html_content(self, html) -> List[str]: """ Adds an HTML component to the report. @@ -843,14 +880,13 @@ def _generate_html_content(self, html) -> List[str]: try: # Embed the HTML in an iframe - iframe_src = ( - html.file_path - if is_url(html.file_path) - else Path("..") / html.file_path - ) + if is_url(html.file_path): + html_file_path = html.file_path + else: + html_file_path = get_relative_file_path(html.file_path, base_path="..") iframe_code = f"""