Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helper function for altair exports #8

Open
timvink opened this issue Dec 8, 2021 · 1 comment
Open

Helper function for altair exports #8

timvink opened this issue Dec 8, 2021 · 1 comment
Labels
enhancement New feature or request

Comments

@timvink
Copy link
Owner

timvink commented Dec 8, 2021

altair has good support for exporting vega schemas (https://altair-viz.github.io/user_guide/saving_charts.html?highlight=to_).

Of course you could just use chart.save('chart.svg') and insert that into a mkdocs page. But you want to want update the data later on and use the same chart.

Manually copy pasting the schema to a file is a hassle. Write a helper function to:

save_mkdocs_chart(chart, name="", docs_folder="../docs", json_path="docs/assets/charts/", data_path="docs/assets/charts/data")

The docs_folders could be auto-detected by traversing upward, finding mkdocs.yml and reading the docs_dir entry (if not present then docs/).

The json_path is relative to the docs_folder and can have a default "docs/assets/charts/"

The data_path is relative to the docs_folder and can have a "docs/assets/charts/data" default. This will only work if we can access the data object in the altair chart instance, which we can then write to .csv.

@timvink timvink added the enhancement New feature or request label Dec 10, 2021
@ewellinger
Copy link

ewellinger commented Jun 1, 2023

This might need to be tweaked somewhat, but I created this helper function that roughly follows the logic you're suggesting here:

import json
from pathlib import Path

from altair import Chart
from pydantic import BaseModel, DirectoryPath, validator


class ChartParams(BaseModel):
    output_dir: DirectoryPath
    data_file: str
    plot_name: str

    @validator("data_file")
    def validate_data_file(cls, val, values):
        if "output_dir" in values:
            full_path = values["output_dir"].absolute() / val
            if not full_path.exists():
                raise ValueError("data_file does not exist")
        return val

    @validator("plot_name")
    def validate_plot_name(cls, val):
        if not val.endswith("json"):
            raise ValueError(f"plot_name must end with .json")
        return val

    @property
    def plot_path(self):
        return self.output_dir / self.plot_name


def save_chart(chart: Chart, output_dir: Path, data_file: str = "results.csv", plot_name: str = "plot.json") -> None:
    params = ChartParams(output_dir=output_dir, data_file=data_file, plot_name=plot_name)

    # Convert the plot to JSON
    plot = json.loads(chart.to_json())

    del plot["datasets"]
    plot["data"] = {"url": data_file}
    with open(params.plot_path, "w") as fo:
        json.dump(plot, fo)

This assumes you're storing the plot in the same directory as the CSV file containing the data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants