├── .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 |
9 |
--------------------------------------------------------------------------------
/assets/notebook_header.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/notebook_header_dark.svg:
--------------------------------------------------------------------------------
1 |
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 | [](https://pypi.org/project/feedzai-altair-theme/)
9 | [](https://mybinder.org/v2/gh/feedzai/feedzai-altair-theme/master?urlpath=/lab/tree/demo.ipynb)
10 | [](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 | 
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 |
--------------------------------------------------------------------------------