├── .python-version ├── src └── feedzai_altair_theme │ ├── py.typed │ ├── __init__.py │ ├── types.py │ ├── theme.py │ └── tokens.py ├── .vscode ├── extensions.json └── settings.json ├── assets ├── logo.png ├── logo.svg ├── notebook_header.svg └── notebook_header_dark.svg ├── uv.toml ├── .gitignore ├── .editorconfig ├── .github └── workflows │ └── release.yml ├── CHANGELOG.md ├── pyproject.toml ├── README.md ├── LICENSE └── demo.ipynb /.python-version: -------------------------------------------------------------------------------- 1 | 3.10.14 2 | -------------------------------------------------------------------------------- /src/feedzai_altair_theme/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["ms-python.mypy-type-checker"] 3 | } 4 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feedzai/feedzai-altair-theme/HEAD/assets/logo.png -------------------------------------------------------------------------------- /uv.toml: -------------------------------------------------------------------------------- 1 | python-downloads = "manual" 2 | python-preference = "only-managed" 3 | required-version = ">=0.8.12" 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | .ipynb_checkpoints/ 3 | .mypy_cache/ 4 | .ruff_cache/ 5 | .venv/ 6 | dist/ 7 | 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python", 3 | "mypy-type-checker.importStrategy": "fromEnvironment" 4 | } 5 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # More info: 2 | # - https://docs.astral.sh/uv/guides/integration/github/ 3 | # - https://github.com/astral-sh/setup-uv 4 | 5 | name: Publish to PyPI 6 | 7 | on: 8 | push: 9 | tags: 10 | - "v*" 11 | 12 | jobs: 13 | build-and-publish: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v5 17 | - name: Install uv 18 | uses: astral-sh/setup-uv@v6 19 | with: 20 | version: "0.8.12" 21 | - name: Install Python 22 | run: uv python install 23 | - name: Build package 24 | run: uv build 25 | - name: Publish 26 | run: uv publish --token ${{ secrets.PYPI_API_TOKEN }} 27 | -------------------------------------------------------------------------------- /src/feedzai_altair_theme/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Feedzai 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Feedzai's theme for Altair (https://altair-viz.github.io/) charts.""" 16 | 17 | from importlib.metadata import version 18 | 19 | __version__ = version("feedzai-altair-theme") 20 | -------------------------------------------------------------------------------- /src/feedzai_altair_theme/types.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Feedzai 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Theme-related types.""" 16 | 17 | from typing import TypedDict 18 | 19 | 20 | class Categorical(TypedDict): 21 | """Categorical color scheme configurations.""" 22 | 23 | default: list[str] 24 | status: list[str] 25 | 26 | 27 | class Diverging(TypedDict): 28 | """Diverging color scheme configurations.""" 29 | 30 | bluered: list[str] 31 | tealred: list[str] 32 | greenlavender: list[str] 33 | 34 | 35 | class Sequential(TypedDict): 36 | """Sequential color scheme configurations.""" 37 | 38 | blues: list[str] 39 | greens: list[str] 40 | reds: list[str] 41 | yellows: list[str] 42 | teals: list[str] 43 | lavenders: list[str] 44 | grays: list[str] 45 | 46 | 47 | class ColorScheme(TypedDict): 48 | """Color scheme configuration.""" 49 | 50 | categorical: Categorical 51 | diverging: Diverging 52 | sequential: Sequential 53 | 54 | 55 | class Colors(TypedDict): 56 | """Colors token.""" 57 | 58 | arc: str 59 | axis: str 60 | background: str 61 | grid: str 62 | mark: str 63 | text: str 64 | schemes: ColorScheme 65 | 66 | 67 | """ 68 | Color token 69 | 70 | Colors should be ordered from lightest to darkest, where '00' is the lightest color and 71 | '60' is the darkest color. 72 | """ 73 | Color = TypedDict( 74 | "Color", 75 | {"00": str, "10": str, "20": str, "30": str, "40": str, "50": str, "60": str}, 76 | ) 77 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ### Added 10 | 11 | - Google Colab badge. 12 | - Deployment instructions. 13 | - Three new examples for the demo notebook: pie chart, strip plot, and scatterplot. 14 | - White border to scatterplot-related marks for accessibility. 15 | - Set the `circle` and `square` marks for scatterplots and remove the extra properties from the `point` mark. 16 | 17 | ### Changed 18 | 19 | - Switch to uv for package management and Ruff for linting and formatting. 20 | - Update the legacy URL parameter for the Binder demo. 21 | - Update the `path` property to `tick`, explicitly supporting this mark. 22 | 23 | ### Removed 24 | 25 | - Drop support for Python 3.7, 3.8, and 3.9; the minimum required version is now Python 3.10. 26 | - Drop support for Altair 4; the minimum required version is now [Altair 5.5.0](https://github.com/vega/altair/releases/tag/v5.5.0) with the new theme API. 27 | - Adopt the [`ThemeConfig` type](https://altair-viz.github.io/user_guide/generated/theme/altair.theme.ThemeConfig.html) and delete the custom types for the same purpose. 28 | - Clear unused theme properties. 29 | 30 | ### Fixed 31 | 32 | - Move dependency management to the notebook and fix the Binder demo. 33 | 34 | ## [1.1.2] - 2023-01-13 35 | 36 | ### Added 37 | 38 | - Document how to install the package in an environment without an Internet connection. 39 | - Changelog to `project_urls`. 40 | 41 | ## [1.1.1] - 2022-07-25 42 | 43 | ### Added 44 | 45 | - Binder badge. 46 | - PyPI badge. 47 | 48 | ### Fixed 49 | 50 | - Use absolute URLs in README because of PyPI. 51 | 52 | ## [1.1.0] - 2022-06-20 53 | 54 | ### Fixed 55 | 56 | - Add `typing-extensions` as a package dependency. 57 | 58 | ## [1.0.0] - 2022-06-02 59 | 60 | ### Added 61 | 62 | - Boilerplate to create a Python package. 63 | - Feedzai's Altair theme. 64 | - GitHub Actions workflow to publish the package to PyPI. 65 | -------------------------------------------------------------------------------- /assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/notebook_header.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /assets/notebook_header_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "feedzai-altair-theme" 3 | version = "2.0.0" 4 | description = "Feedzai's theme for Altair charts." 5 | readme = "README.md" 6 | requires-python = ">=3.10" 7 | license = "Apache-2.0" 8 | license-files = ["LICENSE"] 9 | authors = [{ name = "Feedzai", email = "oss-licenses@feedzai.com" }] 10 | classifiers = [ 11 | "Development Status :: 5 - Production/Stable", 12 | "Intended Audience :: Developers", 13 | "Intended Audience :: Information Technology", 14 | "Intended Audience :: Science/Research", 15 | "Natural Language :: English", 16 | "Operating System :: OS Independent", 17 | "Programming Language :: Python", 18 | "Programming Language :: Python :: 3", 19 | "Programming Language :: Python :: 3 :: Only", 20 | "Programming Language :: Python :: 3.10", 21 | "Programming Language :: Python :: 3.11", 22 | "Programming Language :: Python :: 3.12", 23 | "Programming Language :: Python :: 3.13", 24 | "Programming Language :: Python :: Implementation :: CPython", 25 | "Topic :: Scientific/Engineering :: Visualization", 26 | "Topic :: Utilities", 27 | "Typing :: Typed", 28 | ] 29 | keywords = ["altair", "theme", "data", "visualization"] 30 | dependencies = ["altair>=5.5.0"] 31 | 32 | # Group: https://github.com/vega/altair/blob/v5.5.0/altair/vegalite/v5/theme.py#L102 33 | [project.entry-points.'altair.vegalite.v5.theme'] 34 | feedzai = "feedzai_altair_theme.theme:feedzai" 35 | 36 | [project.urls] 37 | Changelog = "https://github.com/feedzai/feedzai-altair-theme/blob/master/CHANGELOG.md" 38 | Issues = "https://github.com/feedzai/feedzai-altair-theme/issues" 39 | Source = "https://github.com/feedzai/feedzai-altair-theme" 40 | 41 | [dependency-groups] 42 | dev = [ 43 | "jupyterlab==4.1.8", 44 | "mypy[faster-cache]==1.16.1", 45 | "ruff==0.11.2", 46 | "vega-datasets==0.9.0", 47 | ] 48 | 49 | [build-system] 50 | requires = ["uv_build==0.8.12"] 51 | build-backend = "uv_build" 52 | 53 | [tool.mypy] 54 | files = "src/feedzai_altair_theme" 55 | python_version = "3.10" 56 | 57 | check_untyped_defs = true 58 | disallow_any_generics = true 59 | disallow_subclassing_any = true 60 | disallow_untyped_decorators = true 61 | disallow_untyped_defs = true 62 | error_summary = true 63 | exclude_gitignore = true 64 | extra_checks = true 65 | follow_imports = "normal" 66 | local_partial_types = true 67 | pretty = true 68 | show_column_numbers = true 69 | show_error_context = true 70 | strict_bytes = true 71 | strict_equality = true 72 | warn_incomplete_stub = true 73 | warn_no_return = true 74 | warn_redundant_casts = true 75 | warn_return_any = true 76 | warn_unreachable = true 77 | warn_unused_ignores = true 78 | 79 | incremental = true 80 | # "The warn_unused_configs flag may be useful to debug misspelled section names.": 81 | # - https://github.com/python/mypy/blob/v1.16.1/docs/source/config_file.rst#config-file-format 82 | # - https://github.com/python/mypy/blob/v1.16.1/docs/source/config_file.rst#miscellaneous 83 | # incremental = false 84 | # warn_unused_configs = true 85 | 86 | [tool.ruff] 87 | required-version = "0.11.2" 88 | target-version = "py310" 89 | output-format = "full" 90 | preview = false 91 | line-length = 120 92 | 93 | [tool.ruff.lint] 94 | select = ["ALL"] 95 | fixable = ["ALL"] 96 | ignore = [ 97 | # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules (w/ formatter) 98 | "W191", 99 | "E111", 100 | "E114", 101 | "E117", 102 | "D206", 103 | "D300", 104 | "Q000", 105 | "Q001", 106 | "Q002", 107 | "Q003", 108 | "COM812", 109 | "COM819", 110 | "ISC001", 111 | "ISC002", 112 | ] 113 | 114 | [tool.ruff.lint.pydocstyle] 115 | convention = "numpy" 116 | 117 | [tool.ruff.lint.isort] 118 | combine-as-imports = true 119 | -------------------------------------------------------------------------------- /src/feedzai_altair_theme/theme.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Feedzai 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Altair theme configuration.""" 16 | 17 | import altair as alt 18 | 19 | from .tokens import COLORS, FONT, FONT_SIZES, OPACITIES, SPACING, STROKE_WIDTHS 20 | 21 | 22 | def feedzai() -> alt.theme.ThemeConfig: 23 | """Feedzai theme (light theme).""" 24 | return { 25 | "config": { 26 | # Guides 27 | "axis": { 28 | "domain": True, 29 | "domainColor": COLORS["axis"], 30 | "grid": False, 31 | "gridCap": "round", 32 | "gridColor": COLORS["grid"], 33 | "gridDash": [2, 4], 34 | "gridWidth": STROKE_WIDTHS["sm"], 35 | "labelColor": COLORS["axis"], 36 | "labelFont": FONT, 37 | "labelPadding": SPACING["sm"], 38 | "tickColor": COLORS["axis"], 39 | "tickOpacity": OPACITIES["md"], 40 | "tickSize": SPACING["md"], 41 | "titleColor": COLORS["text"], 42 | "titleFont": FONT, 43 | "titleFontSize": FONT_SIZES["sm"], 44 | }, 45 | "axisBand": {"domain": True, "labelPadding": SPACING["md"], "ticks": False}, 46 | "axisY": { 47 | "domain": False, 48 | "titleAlign": "left", 49 | "titleAngle": 0, 50 | "titleX": -20, 51 | "titleY": -10, 52 | }, 53 | "legend": { 54 | "labelColor": COLORS["axis"], 55 | "labelFont": FONT, 56 | "labelFontSize": FONT_SIZES["sm"], 57 | "symbolSize": 40, 58 | "titleColor": COLORS["text"], 59 | "titleFont": FONT, 60 | "titleFontSize": FONT_SIZES["sm"], 61 | "titlePadding": SPACING["md"], 62 | }, 63 | # Marks 64 | "arc": {"stroke": COLORS["arc"], "strokeWidth": STROKE_WIDTHS["md"]}, 65 | "bar": {"fill": COLORS["mark"], "stroke": None}, 66 | "circle": {"fill": COLORS["mark"], "stroke": COLORS["arc"], "strokeWidth": STROKE_WIDTHS["sm"]}, 67 | "line": {"stroke": COLORS["mark"], "strokeWidth": STROKE_WIDTHS["lg"]}, 68 | "point": {"fill": COLORS["mark"], "stroke": COLORS["arc"], "strokeWidth": STROKE_WIDTHS["sm"]}, 69 | "rect": {"fill": COLORS["mark"]}, 70 | "rule": {"stroke": COLORS["axis"]}, 71 | "square": {"fill": COLORS["mark"], "stroke": COLORS["arc"], "strokeWidth": STROKE_WIDTHS["sm"]}, 72 | "text": { 73 | "color": COLORS["text"], 74 | "font": FONT, 75 | "fontSize": FONT_SIZES["sm"], 76 | }, 77 | "tick": {"stroke": COLORS["mark"], "strokeWidth": STROKE_WIDTHS["sm"]}, 78 | # Color scales 79 | "range": { 80 | "category": COLORS["schemes"]["categorical"]["default"], 81 | "diverging": COLORS["schemes"]["diverging"]["tealred"], 82 | "heatmap": COLORS["schemes"]["sequential"]["blues"], 83 | "ramp": COLORS["schemes"]["sequential"]["blues"], 84 | }, 85 | # Chart 86 | "background": COLORS["background"], 87 | "header": { 88 | "labelColor": COLORS["text"], 89 | "labelFont": FONT, 90 | "labelFontSize": FONT_SIZES["sm"], 91 | "titleColor": COLORS["text"], 92 | "titleFont": FONT, 93 | "titleFontSize": FONT_SIZES["md"], 94 | }, 95 | "title": { 96 | "anchor": "start", 97 | "color": COLORS["text"], 98 | "font": FONT, 99 | "fontSize": FONT_SIZES["lg"], 100 | "fontWeight": "bold", 101 | "offset": SPACING["xl"], 102 | "subtitleColor": COLORS["text"], 103 | "subtitleFontSize": FONT_SIZES["md"], 104 | }, 105 | "view": { 106 | "continuousHeight": 300, 107 | "continuousWidth": 400, 108 | "stroke": None, 109 | }, 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | # feedzai-altair-theme 7 | 8 | [![PyPI](https://img.shields.io/pypi/v/feedzai-altair-theme)](https://pypi.org/project/feedzai-altair-theme/) 9 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/feedzai/feedzai-altair-theme/master?urlpath=/lab/tree/demo.ipynb) 10 | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/feedzai/feedzai-altair-theme/blob/master/demo.ipynb) 11 | 12 | Feedzai's theme for [Altair](https://github.com/altair-viz/altair) charts. 13 | 14 | ## Sneak peek 15 | 16 | ![Examples of charts with the feedzai-altair-theme applied](https://raw.githubusercontent.com/feedzai/feedzai-altair-theme/master/assets/header.svg) 17 | 18 | ## Quickstart 19 | 20 | ### Installation 21 | 22 | Via [pip](https://github.com/pypa/pip): 23 | 24 | ```bash 25 | pip install feedzai-altair-theme 26 | ``` 27 | 28 | Via [Pipenv](https://pipenv.pypa.io/): 29 | 30 | ```bash 31 | pipenv install feedzai-altair-theme 32 | ``` 33 | 34 | Via [Poetry](https://python-poetry.org/): 35 | 36 | ```bash 37 | poetry add feedzai-altair-theme 38 | ``` 39 | 40 | Via [PDM](https://pdm.fming.dev/): 41 | 42 | ```bash 43 | pdm add feedzai-altair-theme 44 | ``` 45 | 46 | Via [uv](https://docs.astral.sh/uv/): 47 | 48 | ```bash 49 | uv add feedzai-altair-theme 50 | ``` 51 | 52 | ### Usage 53 | 54 | ```python 55 | import altair as alt 56 | 57 | alt.theme.enable("feedzai") 58 | ``` 59 | 60 | You can find some example charts in the [`demo.ipynb` notebook](demo.ipynb). 61 | 62 | ## Development 63 | 64 | Assuming [uv](https://docs.astral.sh/uv/getting-started/installation/) is installed, install Python: 65 | 66 | ```bash 67 | uv python install 68 | ``` 69 | 70 | Create and activate the development environment: 71 | 72 | ```bash 73 | uv sync 74 | ``` 75 | 76 | ```bash 77 | source .venv/bin/activate 78 | ``` 79 | 80 | After implementing changes, type-check with mypy, then lint and format the code with Ruff: 81 | 82 | ```bash 83 | mypy 84 | ``` 85 | 86 | ```bash 87 | ruff check --fix 88 | ``` 89 | 90 | ```bash 91 | ruff format 92 | ``` 93 | 94 | To see the changes applied to some example charts, use the [`demo.ipynb` notebook](demo.ipynb): 95 | 96 | ```bash 97 | jupyter lab demo.ipynb 98 | ``` 99 | 100 | Once done, deactivate the development environment: 101 | 102 | ```bash 103 | deactivate 104 | ``` 105 | 106 | ## Deployment 107 | 108 | ### Bump the package version 109 | 110 | Bump the feedzai-altair-theme version using one of the following commands, according to the [Semantic Versioning](https://semver.org/) specification: 111 | 112 | ```bash 113 | uv version --bump patch 114 | ``` 115 | 116 | ```bash 117 | uv version --bump minor 118 | ``` 119 | 120 | ```bash 121 | uv version --bump major 122 | ``` 123 | 124 | Next, confirm you can build the package locally: 125 | 126 | ```bash 127 | uv build 128 | ``` 129 | 130 | ### Open a PR 131 | 132 | Once the changes are finished and the feedzai-altair-theme version is updated, open a [PR](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request). After the PR is merged, a maintainer will ensure a new package version is released. 133 | 134 | ### Release the new package version 135 | 136 | To release a new version of feedzai-altair-theme, create a new (lightweight) tag from the `master` branch, and a GitHub Actions workflow will take care of the rest: 137 | 138 | ```bash 139 | git tag "v$(uv version --short)" 140 | ``` 141 | 142 | ```bash 143 | git tag -n 144 | ``` 145 | 146 | ```bash 147 | git push origin --tags 148 | ``` 149 | 150 | ## Misc 151 | 152 | ### Install the feedzai-altair-theme package in an environment without an Internet connection 153 | 154 | #### Via repo 155 | 156 | First, download the repo and move it to your environment. Then install the package with pip (or an equivalent) by pointing to the folder path and adding the necessary flags: 157 | 158 | ```bash 159 | pip install feedzai-altair-theme/ --no-deps --no-build-isolation 160 | ``` 161 | 162 | This command assumes that the feedzai-altair-theme [dependencies](https://github.com/feedzai/feedzai-altair-theme/blob/master/pyproject.toml) and the [uv build backend](https://docs.astral.sh/uv/concepts/build-backend/) are already installed in your environment. For more information about the additional flags, check the [pip install documentation](https://pip.pypa.io/en/stable/cli/pip_install/). 163 | 164 | #### Via wheel 165 | 166 | First, download the [wheel (a.k.a. built distribution)](https://pypi.org/project/feedzai-altair-theme/#files) and move it to your environment. Then install the package with pip (or an equivalent) by pointing to the file path and adding the necessary flags after replacing ``: 167 | 168 | ```bash 169 | pip install feedzai_altair_theme--py3-none-any.whl 170 | ``` 171 | 172 | This command assumes that the feedzai-altair-theme [dependencies](https://github.com/feedzai/feedzai-altair-theme/blob/master/pyproject.toml) are already installed in your environment. 173 | -------------------------------------------------------------------------------- /src/feedzai_altair_theme/tokens.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Feedzai 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Design tokens for the theme and standalone use.""" 16 | 17 | from .types import Color, Colors 18 | 19 | FONT: str = "Roboto, Arial, sans-serif" 20 | 21 | FONT_SIZES: dict[str, int] = {"sm": 12, "md": 16, "lg": 20} 22 | 23 | OPACITIES: dict[str, float] = {"md": 0.5} 24 | 25 | STROKE_WIDTHS: dict[str, float] = {"sm": 0.5, "md": 1, "lg": 2} 26 | 27 | SPACING: dict[str, int] = {"xs": 1, "sm": 2, "md": 4, "lg": 8, "xl": 20} 28 | 29 | COLOR_PRIMITIVES: dict[str, Color] = { 30 | "blue": { 31 | "00": "#E9F1FD", 32 | "10": "#A6C4F7", 33 | "20": "#82ACF3", 34 | "30": "#4C88EE", 35 | "40": "#2770EB", 36 | "50": "#1B4EA5", 37 | "60": "#18448F", 38 | }, 39 | "red": { 40 | "00": "#FBEAEA", 41 | "10": "#EDAAAA", 42 | "20": "#E58686", 43 | "30": "#DA5252", 44 | "40": "#D32F2F", 45 | "50": "#942121", 46 | "60": "#811D1D", 47 | }, 48 | "green": { 49 | "00": "#E8F3EB", 50 | "10": "#9FCDAD", 51 | "20": "#77B98A", 52 | "30": "#3C9B58", 53 | "40": "#148636", 54 | "50": "#0E5E26", 55 | "60": "#0C5221", 56 | }, 57 | "yellow": { 58 | "00": "#FFF9E6", 59 | "10": "#FFE796", 60 | "20": "#FFDD6B", 61 | "30": "#FFCE2B", 62 | "40": "#FFC400", 63 | "50": "#B38900", 64 | "60": "#7F6202", 65 | }, 66 | "lavender": { 67 | "00": "#F5EFFD", 68 | "10": "#D4BDF5", 69 | "20": "#C2A2F1", 70 | "30": "#A87AEA", 71 | "40": "#965FE6", 72 | "50": "#6943A1", 73 | "60": "#5C3A8C", 74 | }, 75 | "teal": { 76 | "00": "#E6F6F5", 77 | "10": "#96D9D7", 78 | "20": "#6BCAC7", 79 | "30": "#2BB3AE", 80 | "40": "#00A39E", 81 | "50": "#00726F", 82 | "60": "#006360", 83 | }, 84 | "neutral": { 85 | "00": "#F0F1F6", 86 | "10": "#E1E2E7", 87 | "20": "#B3B7C4", 88 | "30": "#666F89", 89 | "40": "#4D5776", 90 | "50": "#19274E", 91 | "60": "#000F3A", 92 | }, 93 | } 94 | 95 | COLORS: Colors = { 96 | "arc": "#FFFFFF", 97 | "axis": COLOR_PRIMITIVES["neutral"]["30"], 98 | "background": "#FFFFFF", 99 | "grid": COLOR_PRIMITIVES["neutral"]["20"], 100 | "mark": COLOR_PRIMITIVES["blue"]["40"], 101 | "text": COLOR_PRIMITIVES["neutral"]["50"], 102 | "schemes": { 103 | "categorical": { 104 | "default": [ 105 | COLOR_PRIMITIVES["blue"]["40"], 106 | COLOR_PRIMITIVES["green"]["20"], 107 | COLOR_PRIMITIVES["red"]["30"], 108 | COLOR_PRIMITIVES["yellow"]["40"], 109 | COLOR_PRIMITIVES["lavender"]["30"], 110 | COLOR_PRIMITIVES["teal"]["40"], 111 | COLOR_PRIMITIVES["neutral"]["50"], 112 | ], 113 | "status": [ 114 | COLOR_PRIMITIVES["green"]["30"], 115 | COLOR_PRIMITIVES["red"]["30"], 116 | COLOR_PRIMITIVES["yellow"]["40"], 117 | ], 118 | }, 119 | "diverging": { 120 | "bluered": [ 121 | COLOR_PRIMITIVES["blue"]["60"], 122 | COLOR_PRIMITIVES["blue"]["30"], 123 | COLOR_PRIMITIVES["blue"]["10"], 124 | "#FFFFFF", 125 | COLOR_PRIMITIVES["red"]["10"], 126 | COLOR_PRIMITIVES["red"]["30"], 127 | COLOR_PRIMITIVES["red"]["60"], 128 | ], 129 | "tealred": [ 130 | COLOR_PRIMITIVES["teal"]["60"], 131 | COLOR_PRIMITIVES["teal"]["30"], 132 | COLOR_PRIMITIVES["teal"]["10"], 133 | "#FFFFFF", 134 | COLOR_PRIMITIVES["red"]["10"], 135 | COLOR_PRIMITIVES["red"]["30"], 136 | COLOR_PRIMITIVES["red"]["60"], 137 | ], 138 | "greenlavender": [ 139 | COLOR_PRIMITIVES["green"]["60"], 140 | COLOR_PRIMITIVES["green"]["30"], 141 | COLOR_PRIMITIVES["green"]["10"], 142 | "#FFFFFF", 143 | COLOR_PRIMITIVES["lavender"]["10"], 144 | COLOR_PRIMITIVES["lavender"]["30"], 145 | COLOR_PRIMITIVES["lavender"]["60"], 146 | ], 147 | }, 148 | "sequential": { 149 | "blues": [ 150 | COLOR_PRIMITIVES["blue"]["60"], 151 | COLOR_PRIMITIVES["blue"]["50"], 152 | COLOR_PRIMITIVES["blue"]["40"], 153 | COLOR_PRIMITIVES["blue"]["30"], 154 | COLOR_PRIMITIVES["blue"]["20"], 155 | COLOR_PRIMITIVES["blue"]["10"], 156 | COLOR_PRIMITIVES["blue"]["00"], 157 | ], 158 | "greens": [ 159 | COLOR_PRIMITIVES["green"]["60"], 160 | COLOR_PRIMITIVES["green"]["50"], 161 | COLOR_PRIMITIVES["green"]["40"], 162 | COLOR_PRIMITIVES["green"]["30"], 163 | COLOR_PRIMITIVES["green"]["20"], 164 | COLOR_PRIMITIVES["green"]["10"], 165 | COLOR_PRIMITIVES["green"]["00"], 166 | ], 167 | "reds": [ 168 | COLOR_PRIMITIVES["red"]["60"], 169 | COLOR_PRIMITIVES["red"]["50"], 170 | COLOR_PRIMITIVES["red"]["40"], 171 | COLOR_PRIMITIVES["red"]["30"], 172 | COLOR_PRIMITIVES["red"]["20"], 173 | COLOR_PRIMITIVES["red"]["10"], 174 | COLOR_PRIMITIVES["red"]["00"], 175 | ], 176 | "yellows": [ 177 | COLOR_PRIMITIVES["yellow"]["60"], 178 | COLOR_PRIMITIVES["yellow"]["50"], 179 | COLOR_PRIMITIVES["yellow"]["40"], 180 | COLOR_PRIMITIVES["yellow"]["30"], 181 | COLOR_PRIMITIVES["yellow"]["20"], 182 | COLOR_PRIMITIVES["yellow"]["10"], 183 | COLOR_PRIMITIVES["yellow"]["00"], 184 | ], 185 | "teals": [ 186 | COLOR_PRIMITIVES["teal"]["60"], 187 | COLOR_PRIMITIVES["teal"]["50"], 188 | COLOR_PRIMITIVES["teal"]["40"], 189 | COLOR_PRIMITIVES["teal"]["30"], 190 | COLOR_PRIMITIVES["teal"]["20"], 191 | COLOR_PRIMITIVES["teal"]["10"], 192 | COLOR_PRIMITIVES["teal"]["00"], 193 | ], 194 | "lavenders": [ 195 | COLOR_PRIMITIVES["lavender"]["60"], 196 | COLOR_PRIMITIVES["lavender"]["50"], 197 | COLOR_PRIMITIVES["lavender"]["40"], 198 | COLOR_PRIMITIVES["lavender"]["30"], 199 | COLOR_PRIMITIVES["lavender"]["20"], 200 | COLOR_PRIMITIVES["lavender"]["10"], 201 | COLOR_PRIMITIVES["lavender"]["00"], 202 | ], 203 | "grays": [ 204 | COLOR_PRIMITIVES["neutral"]["60"], 205 | COLOR_PRIMITIVES["neutral"]["50"], 206 | COLOR_PRIMITIVES["neutral"]["40"], 207 | COLOR_PRIMITIVES["neutral"]["30"], 208 | COLOR_PRIMITIVES["neutral"]["20"], 209 | COLOR_PRIMITIVES["neutral"]["10"], 210 | COLOR_PRIMITIVES["neutral"]["00"], 211 | ], 212 | }, 213 | }, 214 | } 215 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | **For commercial uses of feedzai-altair-theme please contact .** 3 | 4 | 5 | Apache License 6 | Version 2.0, January 2004 7 | http://www.apache.org/licenses/ 8 | 9 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 10 | 11 | 1. Definitions. 12 | 13 | "License" shall mean the terms and conditions for use, reproduction, 14 | and distribution as defined by Sections 1 through 9 of this document. 15 | 16 | "Licensor" shall mean the copyright owner or entity authorized by 17 | the copyright owner that is granting the License. 18 | 19 | "Legal Entity" shall mean the union of the acting entity and all 20 | other entities that control, are controlled by, or are under common 21 | control with that entity. For the purposes of this definition, 22 | "control" means (i) the power, direct or indirect, to cause the 23 | direction or management of such entity, whether by contract or 24 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 25 | outstanding shares, or (iii) beneficial ownership of such entity. 26 | 27 | "You" (or "Your") shall mean an individual or Legal Entity 28 | exercising permissions granted by this License. 29 | 30 | "Source" form shall mean the preferred form for making modifications, 31 | including but not limited to software source code, documentation 32 | source, and configuration files. 33 | 34 | "Object" form shall mean any form resulting from mechanical 35 | transformation or translation of a Source form, including but 36 | not limited to compiled object code, generated documentation, 37 | and conversions to other media types. 38 | 39 | "Work" shall mean the work of authorship, whether in Source or 40 | Object form, made available under the License, as indicated by a 41 | copyright notice that is included in or attached to the work 42 | (an example is provided in the Appendix below). 43 | 44 | "Derivative Works" shall mean any work, whether in Source or Object 45 | form, that is based on (or derived from) the Work and for which the 46 | editorial revisions, annotations, elaborations, or other modifications 47 | represent, as a whole, an original work of authorship. For the purposes 48 | of this License, Derivative Works shall not include works that remain 49 | separable from, or merely link (or bind by name) to the interfaces of, 50 | the Work and Derivative Works thereof. 51 | 52 | "Contribution" shall mean any work of authorship, including 53 | the original version of the Work and any modifications or additions 54 | to that Work or Derivative Works thereof, that is intentionally 55 | submitted to Licensor for inclusion in the Work by the copyright owner 56 | or by an individual or Legal Entity authorized to submit on behalf of 57 | the copyright owner. For the purposes of this definition, "submitted" 58 | means any form of electronic, verbal, or written communication sent 59 | to the Licensor or its representatives, including but not limited to 60 | communication on electronic mailing lists, source code control systems, 61 | and issue tracking systems that are managed by, or on behalf of, the 62 | Licensor for the purpose of discussing and improving the Work, but 63 | excluding communication that is conspicuously marked or otherwise 64 | designated in writing by the copyright owner as "Not a Contribution." 65 | 66 | "Contributor" shall mean Licensor and any individual or Legal Entity 67 | on behalf of whom a Contribution has been received by Licensor and 68 | subsequently incorporated within the Work. 69 | 70 | 2. Grant of Copyright License. Subject to the terms and conditions of 71 | this License, each Contributor hereby grants to You a perpetual, 72 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 73 | copyright license to reproduce, prepare Derivative Works of, 74 | publicly display, publicly perform, sublicense, and distribute the 75 | Work and such Derivative Works in Source or Object form. 76 | 77 | 3. Grant of Patent License. Subject to the terms and conditions of 78 | this License, each Contributor hereby grants to You a perpetual, 79 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 80 | (except as stated in this section) patent license to make, have made, 81 | use, offer to sell, sell, import, and otherwise transfer the Work, 82 | where such license applies only to those patent claims licensable 83 | by such Contributor that are necessarily infringed by their 84 | Contribution(s) alone or by combination of their Contribution(s) 85 | with the Work to which such Contribution(s) was submitted. If You 86 | institute patent litigation against any entity (including a 87 | cross-claim or counterclaim in a lawsuit) alleging that the Work 88 | or a Contribution incorporated within the Work constitutes direct 89 | or contributory patent infringement, then any patent licenses 90 | granted to You under this License for that Work shall terminate 91 | as of the date such litigation is filed. 92 | 93 | 4. Redistribution. You may reproduce and distribute copies of the 94 | Work or Derivative Works thereof in any medium, with or without 95 | modifications, and in Source or Object form, provided that You 96 | meet the following conditions: 97 | 98 | (a) You must give any other recipients of the Work or 99 | Derivative Works a copy of this License; and 100 | 101 | (b) You must cause any modified files to carry prominent notices 102 | stating that You changed the files; and 103 | 104 | (c) You must retain, in the Source form of any Derivative Works 105 | that You distribute, all copyright, patent, trademark, and 106 | attribution notices from the Source form of the Work, 107 | excluding those notices that do not pertain to any part of 108 | the Derivative Works; and 109 | 110 | (d) If the Work includes a "NOTICE" text file as part of its 111 | distribution, then any Derivative Works that You distribute must 112 | include a readable copy of the attribution notices contained 113 | within such NOTICE file, excluding those notices that do not 114 | pertain to any part of the Derivative Works, in at least one 115 | of the following places: within a NOTICE text file distributed 116 | as part of the Derivative Works; within the Source form or 117 | documentation, if provided along with the Derivative Works; or, 118 | within a display generated by the Derivative Works, if and 119 | wherever such third-party notices normally appear. The contents 120 | of the NOTICE file are for informational purposes only and 121 | do not modify the License. You may add Your own attribution 122 | notices within Derivative Works that You distribute, alongside 123 | or as an addendum to the NOTICE text from the Work, provided 124 | that such additional attribution notices cannot be construed 125 | as modifying the License. 126 | 127 | You may add Your own copyright statement to Your modifications and 128 | may provide additional or different license terms and conditions 129 | for use, reproduction, or distribution of Your modifications, or 130 | for any such Derivative Works as a whole, provided Your use, 131 | reproduction, and distribution of the Work otherwise complies with 132 | the conditions stated in this License. 133 | 134 | 5. Submission of Contributions. Unless You explicitly state otherwise, 135 | any Contribution intentionally submitted for inclusion in the Work 136 | by You to the Licensor shall be under the terms and conditions of 137 | this License, without any additional terms or conditions. 138 | Notwithstanding the above, nothing herein shall supersede or modify 139 | the terms of any separate license agreement you may have executed 140 | with Licensor regarding such Contributions. 141 | 142 | 6. Trademarks. This License does not grant permission to use the trade 143 | names, trademarks, service marks, or product names of the Licensor, 144 | except as required for reasonable and customary use in describing the 145 | origin of the Work and reproducing the content of the NOTICE file. 146 | 147 | 7. Disclaimer of Warranty. Unless required by applicable law or 148 | agreed to in writing, Licensor provides the Work (and each 149 | Contributor provides its Contributions) on an "AS IS" BASIS, 150 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 151 | implied, including, without limitation, any warranties or conditions 152 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 153 | PARTICULAR PURPOSE. You are solely responsible for determining the 154 | appropriateness of using or redistributing the Work and assume any 155 | risks associated with Your exercise of permissions under this License. 156 | 157 | 8. Limitation of Liability. In no event and under no legal theory, 158 | whether in tort (including negligence), contract, or otherwise, 159 | unless required by applicable law (such as deliberate and grossly 160 | negligent acts) or agreed to in writing, shall any Contributor be 161 | liable to You for damages, including any direct, indirect, special, 162 | incidental, or consequential damages of any character arising as a 163 | result of this License or out of the use or inability to use the 164 | Work (including but not limited to damages for loss of goodwill, 165 | work stoppage, computer failure or malfunction, or any and all 166 | other commercial damages or losses), even if such Contributor 167 | has been advised of the possibility of such damages. 168 | 169 | 9. Accepting Warranty or Additional Liability. While redistributing 170 | the Work or Derivative Works thereof, You may choose to offer, 171 | and charge a fee for, acceptance of support, warranty, indemnity, 172 | or other liability obligations and/or rights consistent with this 173 | License. However, in accepting such obligations, You may act only 174 | on Your own behalf and on Your sole responsibility, not on behalf 175 | of any other Contributor, and only if You agree to indemnify, 176 | defend, and hold each Contributor harmless for any liability 177 | incurred by, or claims asserted against, such Contributor by reason 178 | of your accepting any such warranty or additional liability. 179 | 180 | END OF TERMS AND CONDITIONS 181 | 182 | APPENDIX: How to apply the Apache License to your work. 183 | 184 | To apply the Apache License to your work, attach the following 185 | boilerplate notice, with the fields enclosed by brackets "[]" 186 | replaced with your own identifying information. (Don't include 187 | the brackets!) The text should be enclosed in the appropriate 188 | comment syntax for the file format. We also recommend that a 189 | file or class name and description of purpose be included on the 190 | same "printed page" as the copyright notice for easier 191 | identification within third-party archives. 192 | 193 | Copyright 2022 Feedzai 194 | 195 | Licensed under the Apache License, Version 2.0 (the "License"); 196 | you may not use this file except in compliance with the License. 197 | You may obtain a copy of the License at 198 | 199 | http://www.apache.org/licenses/LICENSE-2.0 200 | 201 | Unless required by applicable law or agreed to in writing, software 202 | distributed under the License is distributed on an "AS IS" BASIS, 203 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 204 | See the License for the specific language governing permissions and 205 | limitations under the License. 206 | -------------------------------------------------------------------------------- /demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "7977b298-7185-49d7-98a2-e7d183c32d1b", 6 | "metadata": {}, 7 | "source": [ 8 | "\n", 9 | " \n", 10 | " \"\"\n", 11 | "" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "id": "52e3a042-d172-4da0-9b2f-c65393dc1655", 17 | "metadata": {}, 18 | "source": [ 19 | "# `feedzai-altair-theme` demo" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "id": "756c5ca6-1fba-4767-b66f-11c38112d8ac", 25 | "metadata": {}, 26 | "source": [ 27 | "Start by getting the dependencies, if needed:" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "id": "b05a8023-92cf-4fff-89a3-8e2f56997dc7", 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "def is_binder() -> bool:\n", 38 | " \"\"\"Check if the notebook is running on Binder.\"\"\"\n", 39 | " import os\n", 40 | "\n", 41 | " return os.environ.get(\"BINDER_SERVICE_HOST\") is not None\n", 42 | "\n", 43 | "\n", 44 | "def is_colab() -> bool:\n", 45 | " \"\"\"Check if the notebook is running on Google Colab.\"\"\"\n", 46 | " try:\n", 47 | " from importlib.util import find_spec\n", 48 | "\n", 49 | " return find_spec(\"google.colab\") is not None\n", 50 | " except ModuleNotFoundError:\n", 51 | " return False\n", 52 | "\n", 53 | "\n", 54 | "if is_colab() or is_binder():\n", 55 | " %pip install feedzai-altair-theme vega-datasets==0.9.0" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "id": "ad200c67-f1f9-4984-9cdb-afa31c45f9cd", 61 | "metadata": {}, 62 | "source": [ 63 | "To use the `feedzai` theme in your Altair charts, you just need to import Altair (no need to import the `feedzai-altair-theme` package):" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "id": "499c8566-683d-4fd8-a1a2-4c947b4ed4f5", 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "import altair as alt\n", 74 | "\n", 75 | "# For the example charts in this notebook, NumPy, pandas, and the vega_datasets package are also imported:\n", 76 | "import numpy as np\n", 77 | "import pandas as pd\n", 78 | "from vega_datasets import data" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "id": "d7bfd16b-93ea-4994-8510-d183636157f4", 84 | "metadata": {}, 85 | "source": [ 86 | "By default, the theme used by Altair is the `default` theme:" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "id": "e9848138-e9b9-499b-981a-b5378242df4c", 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "alt.theme.active" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "id": "8d5e1ae3-a3ac-40a8-b5cd-174d60703aac", 102 | "metadata": {}, 103 | "source": [ 104 | "When checking all the available themes, the `feedzai` theme is one of them:" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "id": "0135b57a-aae2-4fec-8d81-a8eaad94d001", 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "alt.theme.names()" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "id": "4bae645f-756a-4a31-abb1-a60e3ef37a5c", 120 | "metadata": {}, 121 | "source": [ 122 | "To apply the `feedzai` theme to all charts on this notebook, enable it and confirm that it is the new active theme:" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": null, 128 | "id": "be101ef3-6f1b-4cd7-b900-3408814f16fd", 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "alt.theme.enable(\"feedzai\")" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "id": "94bac21a-3076-4c57-b7da-0e1f204c4d55", 139 | "metadata": {}, 140 | "outputs": [], 141 | "source": [ 142 | "alt.theme.active" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "id": "6d19e02d-e086-4548-be43-3353e4a57e05", 148 | "metadata": {}, 149 | "source": [ 150 | "Now, let's see some examples! For other examples, go to the [Example Gallery in the Altair documentation](https://altair-viz.github.io/gallery/index.html) and copy and paste the code snippet into this notebook." 151 | ] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "id": "ebd1d8e8-f1ae-46b6-aa10-387749943949", 156 | "metadata": { 157 | "tags": [] 158 | }, 159 | "source": [ 160 | "## Bar chart" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "id": "2061255e-0f90-46e7-af69-9314442f43d1", 166 | "metadata": {}, 167 | "source": [ 168 | "[Source](https://altair-viz.github.io/gallery/simple_bar_chart.html)" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": null, 174 | "id": "41e17b91-8a09-4f71-8fc0-30391bc4ce59", 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "source = pd.DataFrame(\n", 179 | " {\n", 180 | " \"a\": [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\"],\n", 181 | " \"b\": [28, 55, 43, 91, 81, 53, 19, 87, 52],\n", 182 | " }\n", 183 | ")\n", 184 | "\n", 185 | "alt.Chart(source).mark_bar(tooltip=True).encode(x=\"a:N\", y=\"b:Q\")" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "id": "00842fcd-6625-4c42-946c-6e49caaf9fcd", 191 | "metadata": {}, 192 | "source": [ 193 | "## Line chart" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "id": "7d4bc44b-9e2b-40da-a4b3-f539e5fb2965", 199 | "metadata": {}, 200 | "source": [ 201 | "[Source](https://altair-viz.github.io/gallery/multi_series_line.html)" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": null, 207 | "id": "e7780222-f19c-4808-829a-c144e4ab6a2a", 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "source = data.stocks()\n", 212 | "\n", 213 | "alt.Chart(source).mark_line().encode(\n", 214 | " x=\"date:T\",\n", 215 | " y=\"price:Q\",\n", 216 | " color=\"symbol:N\",\n", 217 | " strokeDash=\"symbol:N\",\n", 218 | ")" 219 | ] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "id": "60d23a22-b1bf-4a1e-86dd-529704289ac2", 224 | "metadata": {}, 225 | "source": [ 226 | "## Histogram" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "id": "854b5c4d-4b52-4106-9804-20b775324d99", 232 | "metadata": {}, 233 | "source": [ 234 | "[Source](https://altair-viz.github.io/gallery/simple_histogram.html)" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": null, 240 | "id": "c3620958-883b-4429-ac76-5969fd4bf594", 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "source = data.movies()\n", 245 | "\n", 246 | "alt.Chart(source).mark_bar().encode(\n", 247 | " x=alt.X(\"IMDB_Rating:Q\", bin=True),\n", 248 | " y=\"count()\",\n", 249 | ")" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "id": "cb69b118-b46b-47e2-ad3a-a84f7cb1a1c6", 255 | "metadata": {}, 256 | "source": [ 257 | "## Stacked area chart" 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "id": "061f3aee-d282-4a2f-8673-b96afd46b554", 263 | "metadata": {}, 264 | "source": [ 265 | "[Source](https://altair-viz.github.io/gallery/simple_stacked_area_chart.html)" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": null, 271 | "id": "afecaf6d-7f37-44c1-b9f9-85a386db22b5", 272 | "metadata": {}, 273 | "outputs": [], 274 | "source": [ 275 | "source = data.iowa_electricity()\n", 276 | "\n", 277 | "alt.Chart(source).mark_area().encode(x=\"year:T\", y=\"net_generation:Q\", color=\"source:N\")" 278 | ] 279 | }, 280 | { 281 | "cell_type": "markdown", 282 | "id": "115df9d5-c8ec-41c2-b15d-f3cc9ee51fc6", 283 | "metadata": { 284 | "tags": [] 285 | }, 286 | "source": [ 287 | "## Heatmap" 288 | ] 289 | }, 290 | { 291 | "cell_type": "markdown", 292 | "id": "f2e0f740-ef55-431d-9f66-ce7fd1d6ea9e", 293 | "metadata": {}, 294 | "source": [ 295 | "[Source](https://altair-viz.github.io/gallery/simple_heatmap.html)" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "id": "b628d503-2a3f-45ab-80d2-8913576241be", 302 | "metadata": {}, 303 | "outputs": [], 304 | "source": [ 305 | "x, y = np.meshgrid(range(-5, 5), range(-5, 5))\n", 306 | "z = x**2 + y**2\n", 307 | "\n", 308 | "source = pd.DataFrame({\"x\": x.ravel(), \"y\": y.ravel(), \"z\": z.ravel()})\n", 309 | "\n", 310 | "alt.Chart(source).mark_rect().encode(x=\"x:O\", y=\"y:O\", color=alt.Color(\"z:Q\", scale=alt.Scale(reverse=True)))" 311 | ] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "id": "7b8aea4d-0501-42c0-a733-89b712317973", 316 | "metadata": { 317 | "execution": { 318 | "iopub.execute_input": "2025-09-01T16:47:30.755588Z", 319 | "iopub.status.busy": "2025-09-01T16:47:30.754999Z", 320 | "iopub.status.idle": "2025-09-01T16:47:30.761018Z", 321 | "shell.execute_reply": "2025-09-01T16:47:30.759246Z", 322 | "shell.execute_reply.started": "2025-09-01T16:47:30.755546Z" 323 | } 324 | }, 325 | "source": [ 326 | "## Pie chart" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "id": "c916562e-4074-453c-b920-1e3c414317a0", 332 | "metadata": { 333 | "execution": { 334 | "iopub.execute_input": "2025-09-01T16:47:57.648610Z", 335 | "iopub.status.busy": "2025-09-01T16:47:57.648123Z", 336 | "iopub.status.idle": "2025-09-01T16:47:57.658204Z", 337 | "shell.execute_reply": "2025-09-01T16:47:57.656833Z", 338 | "shell.execute_reply.started": "2025-09-01T16:47:57.648565Z" 339 | } 340 | }, 341 | "source": [ 342 | "[Source](https://altair-viz.github.io/gallery/pie_chart.html)" 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": null, 348 | "id": "23726f0b-48f1-4287-abb3-09d1a39561a7", 349 | "metadata": {}, 350 | "outputs": [], 351 | "source": [ 352 | "source = pd.DataFrame({\"category\": [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"], \"value\": [4, 6, 10, 3, 7, 8]})\n", 353 | "\n", 354 | "alt.Chart(source).mark_arc().encode(theta=\"value\", color=\"category\")" 355 | ] 356 | }, 357 | { 358 | "cell_type": "markdown", 359 | "id": "16ea2d9f-0d97-41d6-bc6c-7b8cc060c5c6", 360 | "metadata": {}, 361 | "source": [ 362 | "## Strip plot" 363 | ] 364 | }, 365 | { 366 | "cell_type": "markdown", 367 | "id": "bc064b44-41dd-469c-86c4-df169feef51b", 368 | "metadata": {}, 369 | "source": [ 370 | "[Source](https://altair-viz.github.io/gallery/strip_plot.html)" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "id": "1d728928-8d07-4ee7-af1a-f134183e8d0d", 377 | "metadata": {}, 378 | "outputs": [], 379 | "source": [ 380 | "source = data.cars()\n", 381 | "\n", 382 | "alt.Chart(source).mark_tick().encode(x=\"Horsepower:Q\", y=\"Cylinders:O\")" 383 | ] 384 | }, 385 | { 386 | "cell_type": "markdown", 387 | "id": "d0b4574a-2065-4a91-a4eb-b1a161a96b6d", 388 | "metadata": { 389 | "execution": { 390 | "iopub.execute_input": "2025-09-01T17:05:11.945722Z", 391 | "iopub.status.busy": "2025-09-01T17:05:11.945336Z", 392 | "iopub.status.idle": "2025-09-01T17:05:11.951597Z", 393 | "shell.execute_reply": "2025-09-01T17:05:11.950440Z", 394 | "shell.execute_reply.started": "2025-09-01T17:05:11.945695Z" 395 | } 396 | }, 397 | "source": [ 398 | "## Scatterplot" 399 | ] 400 | }, 401 | { 402 | "cell_type": "markdown", 403 | "id": "c4f9bb1c-a78c-4896-a98b-61eb30306468", 404 | "metadata": {}, 405 | "source": [ 406 | "[Source](https://altair-viz.github.io/gallery/scatter_tooltips.html)" 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": null, 412 | "id": "cea2e539-de0c-4a84-a9d8-d8a875eb22b7", 413 | "metadata": {}, 414 | "outputs": [], 415 | "source": [ 416 | "source = data.cars()\n", 417 | "\n", 418 | "alt.Chart(source).mark_circle(size=60).encode(\n", 419 | " x=\"Horsepower\", y=\"Miles_per_Gallon\", color=\"Origin\", tooltip=[\"Name\", \"Origin\", \"Horsepower\", \"Miles_per_Gallon\"]\n", 420 | ").interactive()" 421 | ] 422 | }, 423 | { 424 | "cell_type": "markdown", 425 | "id": "089e662d-d1b0-411d-a04d-858fd6288cb3", 426 | "metadata": {}, 427 | "source": [ 428 | "---" 429 | ] 430 | } 431 | ], 432 | "metadata": { 433 | "kernelspec": { 434 | "display_name": "Python 3 (ipykernel)", 435 | "language": "python", 436 | "name": "python3" 437 | }, 438 | "language_info": { 439 | "codemirror_mode": { 440 | "name": "ipython", 441 | "version": 3 442 | }, 443 | "file_extension": ".py", 444 | "mimetype": "text/x-python", 445 | "name": "python", 446 | "nbconvert_exporter": "python", 447 | "pygments_lexer": "ipython3", 448 | "version": "3.10.14" 449 | } 450 | }, 451 | "nbformat": 4, 452 | "nbformat_minor": 5 453 | } 454 | --------------------------------------------------------------------------------