plotform 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plotform/__init__.py +53 -0
- plotform/api.py +47 -0
- plotform/assets/fonts/PlotformMono-OFL.txt +93 -0
- plotform/assets/fonts/PlotformMono-Regular.ttf +0 -0
- plotform/assets/fonts/PlotformMono-TRADEMARKS.md +17 -0
- plotform/assets/fonts/PlotformSans-OFL.txt +93 -0
- plotform/assets/fonts/PlotformSans-Rounded.ttf +0 -0
- plotform/assets/fonts/PlotformSans-TRADEMARKS.md +17 -0
- plotform/assets/fonts/README.md +30 -0
- plotform/colorbar_utils.py +75 -0
- plotform/fonts.py +56 -0
- plotform/legend_utils.py +199 -0
- plotform/palette.py +103 -0
- plotform/rounded.py +519 -0
- plotform/theme.py +168 -0
- plotform/three_d.py +40 -0
- plotform-0.1.0.dist-info/METADATA +267 -0
- plotform-0.1.0.dist-info/RECORD +21 -0
- plotform-0.1.0.dist-info/WHEEL +5 -0
- plotform-0.1.0.dist-info/licenses/LICENSE +24 -0
- plotform-0.1.0.dist-info/top_level.txt +1 -0
plotform/__init__.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Plotform: a minimalist Matplotlib theme and plotting toolkit."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import version as _distribution_version
|
|
4
|
+
|
|
5
|
+
from .api import annotate, bar, barh, colorbar, legend
|
|
6
|
+
from .fonts import MONO_FONT, SANS_FONT
|
|
7
|
+
from .palette import (
|
|
8
|
+
AXIS,
|
|
9
|
+
BASE_COLORS,
|
|
10
|
+
CORAL,
|
|
11
|
+
DIVERGING_CMAP,
|
|
12
|
+
GRID,
|
|
13
|
+
INK,
|
|
14
|
+
MUTED,
|
|
15
|
+
MUTED_AXIS,
|
|
16
|
+
PRIMARY,
|
|
17
|
+
SCALAR_CMAP,
|
|
18
|
+
SCALAR_STOPS,
|
|
19
|
+
SEQUENTIAL_CMAP,
|
|
20
|
+
WHITE,
|
|
21
|
+
get_palette,
|
|
22
|
+
)
|
|
23
|
+
from .theme import apply_theme, theme
|
|
24
|
+
from .three_d import style_3d
|
|
25
|
+
|
|
26
|
+
__version__ = _distribution_version("plotform")
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"AXIS",
|
|
30
|
+
"BASE_COLORS",
|
|
31
|
+
"CORAL",
|
|
32
|
+
"DIVERGING_CMAP",
|
|
33
|
+
"GRID",
|
|
34
|
+
"INK",
|
|
35
|
+
"MONO_FONT",
|
|
36
|
+
"MUTED",
|
|
37
|
+
"MUTED_AXIS",
|
|
38
|
+
"PRIMARY",
|
|
39
|
+
"SANS_FONT",
|
|
40
|
+
"SCALAR_CMAP",
|
|
41
|
+
"SCALAR_STOPS",
|
|
42
|
+
"SEQUENTIAL_CMAP",
|
|
43
|
+
"WHITE",
|
|
44
|
+
"annotate",
|
|
45
|
+
"apply_theme",
|
|
46
|
+
"bar",
|
|
47
|
+
"barh",
|
|
48
|
+
"colorbar",
|
|
49
|
+
"get_palette",
|
|
50
|
+
"legend",
|
|
51
|
+
"style_3d",
|
|
52
|
+
"theme",
|
|
53
|
+
]
|
plotform/api.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Native-style convenience names for Plotform helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .colorbar_utils import capsule_colorbar
|
|
6
|
+
from .legend_utils import pill_legend
|
|
7
|
+
from .rounded import add_pill, rounded_bar, rounded_barh
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _axes(ax=None):
|
|
11
|
+
if ax is not None:
|
|
12
|
+
return ax
|
|
13
|
+
from matplotlib import pyplot as plt
|
|
14
|
+
|
|
15
|
+
return plt.gca()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def legend(ax=None, **kwargs):
|
|
19
|
+
"""Create a pill legend, using the current axes when ``ax`` is omitted."""
|
|
20
|
+
return pill_legend(_axes(ax), **kwargs)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def bar(*args, ax=None, **kwargs):
|
|
24
|
+
"""Draw rounded bars with native ``plt.bar``-style argument order."""
|
|
25
|
+
return rounded_bar(_axes(ax), *args, **kwargs)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def barh(*args, ax=None, **kwargs):
|
|
29
|
+
"""Draw horizontal rounded bars with native ``plt.barh``-style order."""
|
|
30
|
+
return rounded_barh(_axes(ax), *args, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def colorbar(mappable, *, fig=None, ax=None, **kwargs):
|
|
34
|
+
"""Create a capsule colorbar, using the current figure/axes by default."""
|
|
35
|
+
if fig is None:
|
|
36
|
+
from matplotlib import pyplot as plt
|
|
37
|
+
|
|
38
|
+
fig = plt.gcf()
|
|
39
|
+
return capsule_colorbar(fig, _axes(ax), mappable, **kwargs)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def annotate(text, xy, *, ax=None, **kwargs):
|
|
43
|
+
"""Add a capsule annotation with native ``Axes.annotate`` argument order."""
|
|
44
|
+
return add_pill(_axes(ax), xy[0], xy[1], text, **kwargs)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
__all__ = ["annotate", "bar", "barh", "colorbar", "legend"]
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2025 The Google Sans Code Project Authors (github.com/googlefonts/googlesans-code)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://openfontlicense.org
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Google Sans Code Trademarks
|
|
2
|
+
===========================
|
|
3
|
+
|
|
4
|
+
Google commissioned the Google Sans fonts collection, including Google Sans Code, as 'work for hire' and owns all rights to these works.
|
|
5
|
+
However, Google also does not include within the Open Font License ([OFL.txt](OFL.txt)) any Reserved Font Names (RFNs) within the copyright statement.
|
|
6
|
+
|
|
7
|
+
“Google”, “Google Sans” and “Google Sans Code” are trademarks of Google LLC.
|
|
8
|
+
|
|
9
|
+
Use of any version of this Font Software does not allow you to use the “Google” trademark on its own or as part of any other trademarks, terms, or source identifiers.
|
|
10
|
+
|
|
11
|
+
The “Google Sans Code” trademark may be used in connection with the Original Font Software version or Modified Font Software, but such use may only be in connection with the Original Font Software and in no way may be used in a manner that may imply any affiliation with or sponsorship by Google LLC.
|
|
12
|
+
|
|
13
|
+
The “Google Sans Code” trademark may not be incorporated as part of your company name, product name, domain name, or social media profile without permission.
|
|
14
|
+
|
|
15
|
+
The “Google Sans Code” trademark should not be combined with other trademarks, terms, or source identifiers, and may not be modified without permission.
|
|
16
|
+
|
|
17
|
+
For example, Modified Versions of the Font Software may use the Google mark in a Github repo fork that is used to contribute a Pull Request to the [github.com/googlefonts/googlesans-code](https://github.com/googlefonts/googlesans-code) repo.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2015 The Google Sans Flex Authors (https://github.com/googlefonts/googlesans-flex)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://openfontlicense.org
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Google Sans Flex Trademarks
|
|
2
|
+
===========================
|
|
3
|
+
|
|
4
|
+
Google commissioned the Google Sans fonts collection, including Google Sans Flex, as 'work for hire' and owns all rights to these works.
|
|
5
|
+
However, Google also does not include within the Open Font License ([OFL.txt](OFL.txt)) any Reserved Font Names (RFNs) within the copyright statement.
|
|
6
|
+
|
|
7
|
+
“Google”, “Google Sans” and “Google Sans Flex” are trademarks of Google LLC.
|
|
8
|
+
|
|
9
|
+
Use of any version of this Font Software does not allow you to use the “Google” trademark on its own or as part of any other trademarks, terms, or source identifiers.
|
|
10
|
+
|
|
11
|
+
The “Google”, “Google Sans” or “Google Sans Flex” trademarks may be used in connection with the Original Font Software version or Modified Font Software, but such use may only be in connection with the Original Font Software and in no way may be used in a manner that may imply any affiliation with or sponsorship by Google LLC.
|
|
12
|
+
|
|
13
|
+
The “Google”, “Google Sans” or “Google Sans Flex” trademarks may not be incorporated as part of your company name, product name, domain name, or social media profile without permission.
|
|
14
|
+
|
|
15
|
+
The “Google”, “Google Sans” or “Google Sans Flex” trademarks should not be combined with other trademarks, terms, or source identifiers, and may not be modified without permission.
|
|
16
|
+
|
|
17
|
+
For example, Modified Versions of the Font Software may use the Google mark in a Github repo fork that is used to contribute a Pull Request to the [github.com/googlefonts/googlesans-flex](https://github.com/googlefonts/googlesans-flex) repo.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Bundled font attributions
|
|
2
|
+
|
|
3
|
+
Plotform includes derived, static font instances so plots render consistently
|
|
4
|
+
without requiring system-wide font installation or variable-font axis support.
|
|
5
|
+
|
|
6
|
+
## Plotform Sans
|
|
7
|
+
|
|
8
|
+
- Source: **Google Sans Flex**, Google Sans Flex Authors
|
|
9
|
+
- Upstream: https://github.com/googlefonts/googlesans-flex
|
|
10
|
+
- Downloaded from: https://github.com/google/fonts/tree/main/ofl/googlesansflex
|
|
11
|
+
- Modification: instantiated with `ROND=100`; weight and every other variable
|
|
12
|
+
axis were left at their source defaults. The font was then renamed to avoid
|
|
13
|
+
collision with separately installed Google fonts.
|
|
14
|
+
- Result: `PlotformSans-Rounded.ttf`, regular weight 400
|
|
15
|
+
- License: `PlotformSans-OFL.txt` (SIL Open Font License 1.1)
|
|
16
|
+
- Trademark notice: `PlotformSans-TRADEMARKS.md`
|
|
17
|
+
|
|
18
|
+
## Plotform Mono
|
|
19
|
+
|
|
20
|
+
- Source: **Google Sans Code**, Google Sans Code Project Authors
|
|
21
|
+
- Upstream: https://github.com/googlefonts/googlesans-code
|
|
22
|
+
- Downloaded from: https://github.com/google/fonts/tree/main/ofl/googlesanscode
|
|
23
|
+
- Modification: instantiated at the source default weight and renamed.
|
|
24
|
+
- Result: `PlotformMono-Regular.ttf`, regular weight 400
|
|
25
|
+
- License: `PlotformMono-OFL.txt` (SIL Open Font License 1.1)
|
|
26
|
+
- Trademark notice: `PlotformMono-TRADEMARKS.md`
|
|
27
|
+
|
|
28
|
+
Run `python tools/prepare_fonts.py` from the repository root to regenerate these
|
|
29
|
+
assets from Google Fonts. The generated documents and figures are not subject
|
|
30
|
+
to the font software license; the font files themselves remain under the OFL.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Vertical capsule tracks for continuous scalar colorbars."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from matplotlib.patches import PathPatch
|
|
6
|
+
from matplotlib.path import Path
|
|
7
|
+
from matplotlib.transforms import IdentityTransform
|
|
8
|
+
|
|
9
|
+
from .palette import INK
|
|
10
|
+
from .rounded import capsule_path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DisplayCapsulePatch(PathPatch):
|
|
14
|
+
"""An invisible display-space capsule used to clip colorbar artists."""
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
super().__init__(
|
|
18
|
+
capsule_path(0, 0, 1, 1),
|
|
19
|
+
facecolor="none",
|
|
20
|
+
edgecolor="none",
|
|
21
|
+
transform=IdentityTransform(),
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def get_path(self) -> Path:
|
|
25
|
+
ax = getattr(self, "axes", None)
|
|
26
|
+
if ax is None:
|
|
27
|
+
return capsule_path(0, 0, 1, 1)
|
|
28
|
+
bounds = ax.bbox
|
|
29
|
+
return capsule_path(bounds.x0, bounds.y0, bounds.width, bounds.height)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def capsule_colorbar(fig, ax, mappable, **kwargs):
|
|
33
|
+
"""Create a vertical colorbar whose visible gradient is an exact capsule.
|
|
34
|
+
|
|
35
|
+
Tick marks and numeric labels remain outside the track. Additional keyword
|
|
36
|
+
arguments are forwarded to ``Figure.colorbar``. The returned Colorbar has a
|
|
37
|
+
``capsule_patch`` attribute for inspection and advanced customization.
|
|
38
|
+
"""
|
|
39
|
+
if kwargs.get("orientation", "vertical") != "vertical":
|
|
40
|
+
raise ValueError("capsule_colorbar currently supports vertical orientation only")
|
|
41
|
+
kwargs["orientation"] = "vertical"
|
|
42
|
+
colorbar = fig.colorbar(mappable, ax=ax, **kwargs)
|
|
43
|
+
cax = colorbar.ax
|
|
44
|
+
|
|
45
|
+
clip = DisplayCapsulePatch()
|
|
46
|
+
clip.set_clip_on(False)
|
|
47
|
+
cax.add_patch(clip)
|
|
48
|
+
for artist in (*cax.images, *cax.collections):
|
|
49
|
+
artist.set_clip_path(clip)
|
|
50
|
+
if getattr(colorbar, "solids", None) is not None:
|
|
51
|
+
colorbar.solids.set_clip_path(clip)
|
|
52
|
+
|
|
53
|
+
if getattr(colorbar, "outline", None) is not None:
|
|
54
|
+
colorbar.outline.set_visible(False)
|
|
55
|
+
for spine in cax.spines.values():
|
|
56
|
+
spine.set_visible(False)
|
|
57
|
+
cax.patch.set_visible(False)
|
|
58
|
+
cax.yaxis.set_ticks_position("right")
|
|
59
|
+
cax.yaxis.set_label_position("right")
|
|
60
|
+
cax.tick_params(
|
|
61
|
+
axis="y",
|
|
62
|
+
which="both",
|
|
63
|
+
direction="out",
|
|
64
|
+
length=3,
|
|
65
|
+
width=0.8,
|
|
66
|
+
colors=INK,
|
|
67
|
+
labelcolor=INK,
|
|
68
|
+
pad=5,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
colorbar.capsule_patch = clip
|
|
72
|
+
return colorbar
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
__all__ = ["capsule_colorbar"]
|
plotform/fonts.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Registration and verification of the bundled theme fonts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from matplotlib import font_manager
|
|
8
|
+
|
|
9
|
+
SANS_FONT = "Plotform Sans"
|
|
10
|
+
MONO_FONT = "Plotform Mono"
|
|
11
|
+
FONT_DIR = Path(__file__).resolve().parent / "assets" / "fonts"
|
|
12
|
+
FONT_FILES = ("PlotformSans-Rounded.ttf", "PlotformMono-Regular.ttf")
|
|
13
|
+
|
|
14
|
+
_registered = False
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def font_paths() -> dict[str, Path]:
|
|
18
|
+
"""Return the expected bundled font paths by family name."""
|
|
19
|
+
return {
|
|
20
|
+
SANS_FONT: FONT_DIR / FONT_FILES[0],
|
|
21
|
+
MONO_FONT: FONT_DIR / FONT_FILES[1],
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def register_fonts(*, verify: bool = True) -> dict[str, Path]:
|
|
26
|
+
"""Register bundled fonts with Matplotlib without modifying the OS.
|
|
27
|
+
|
|
28
|
+
Returns the resolved font files. With ``verify=True``, a missing or invalid
|
|
29
|
+
font raises instead of silently falling back to a system font.
|
|
30
|
+
"""
|
|
31
|
+
global _registered
|
|
32
|
+
|
|
33
|
+
paths = font_paths()
|
|
34
|
+
missing = [str(path) for path in paths.values() if not path.is_file()]
|
|
35
|
+
if missing:
|
|
36
|
+
raise FileNotFoundError("Bundled theme fonts are missing: " + ", ".join(missing))
|
|
37
|
+
|
|
38
|
+
if not _registered:
|
|
39
|
+
for path in paths.values():
|
|
40
|
+
font_manager.fontManager.addfont(str(path))
|
|
41
|
+
_registered = True
|
|
42
|
+
|
|
43
|
+
if verify:
|
|
44
|
+
resolved: dict[str, Path] = {}
|
|
45
|
+
for family in (SANS_FONT, MONO_FONT):
|
|
46
|
+
properties = font_manager.FontProperties(family=family)
|
|
47
|
+
found = Path(font_manager.findfont(properties, fallback_to_default=False)).resolve()
|
|
48
|
+
expected = paths[family].resolve()
|
|
49
|
+
if found != expected:
|
|
50
|
+
raise RuntimeError(
|
|
51
|
+
f"Matplotlib resolved {family!r} to {found}, expected {expected}"
|
|
52
|
+
)
|
|
53
|
+
resolved[family] = found
|
|
54
|
+
return resolved
|
|
55
|
+
|
|
56
|
+
return paths
|