rang 0.2.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.
rang/__init__.py ADDED
@@ -0,0 +1,192 @@
1
+ """Rang, color palettes from Persian art.
2
+
3
+ Palettes are stored as a ramp of hex colors plus a pick order. Asking for a
4
+ few colors returns a well separated subset, asking for more than the palette
5
+ holds interpolates along the ramp.
6
+ """
7
+
8
+ import operator
9
+
10
+ from ._palettes import PALETTES
11
+
12
+ __version__ = "0.2.0"
13
+ __all__ = ["rang", "cmap", "list_palettes", "source", "colorblind_friendly",
14
+ "register", "registered_name", "set_palette", "PALETTES"]
15
+
16
+
17
+ def list_palettes(colorblind_only=False):
18
+ """Names of the available palettes, sorted."""
19
+ names = sorted(PALETTES)
20
+ if colorblind_only:
21
+ names = [n for n in names if PALETTES[n]["colorblind"]]
22
+ return names
23
+
24
+
25
+ def _get(name):
26
+ if name not in PALETTES:
27
+ raise KeyError(f"Unknown palette {name!r}. "
28
+ f"Available: {', '.join(sorted(PALETTES))}")
29
+ return PALETTES[name]
30
+
31
+
32
+ def _hex_to_rgb(h):
33
+ h = h.lstrip("#")
34
+ return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
35
+
36
+
37
+ def _positive_integer(value):
38
+ if isinstance(value, bool):
39
+ raise TypeError("n must be an integer")
40
+ try:
41
+ value = operator.index(value)
42
+ except TypeError as exc:
43
+ raise TypeError("n must be an integer") from exc
44
+ if value < 1:
45
+ raise ValueError("n must be at least 1")
46
+ return value
47
+
48
+
49
+ def _check_direction(direction):
50
+ if direction not in (1, -1):
51
+ raise ValueError("direction must be 1 or -1")
52
+
53
+
54
+ def _interpolate(colors, n):
55
+ if n == 1:
56
+ return [colors[0]]
57
+ rgbs = [_hex_to_rgb(c) for c in colors]
58
+ out = []
59
+ for i in range(n):
60
+ t = i * (len(colors) - 1) / (n - 1)
61
+ j = min(int(t), len(colors) - 2)
62
+ f = t - j
63
+ rgb = tuple(round(a + (b - a) * f) for a, b in zip(rgbs[j], rgbs[j + 1]))
64
+ out.append("#{:02x}{:02x}{:02x}".format(*rgb))
65
+ return out
66
+
67
+
68
+ def rang(name, n=None, kind=None, direction=1, override_order=False):
69
+ """Return a list of hex colors from a palette.
70
+
71
+ Parameters
72
+ ----------
73
+ name : palette name, see list_palettes()
74
+ n : how many colors, defaults to the full palette
75
+ kind : "discrete" or "continuous". Defaults to discrete while n fits the
76
+ palette and continuous beyond that.
77
+ direction : 1 for the stored order, -1 to reverse
78
+ override_order : take the first n ramp colors instead of the stored
79
+ pick order
80
+ """
81
+ pal = _get(name)
82
+ colors, order = list(pal["colors"]), list(pal["order"])
83
+ if n is None:
84
+ n = len(colors)
85
+ n = _positive_integer(n)
86
+ _check_direction(direction)
87
+ if kind is None:
88
+ kind = "continuous" if n > len(colors) else "discrete"
89
+ if kind not in ("discrete", "continuous"):
90
+ raise ValueError("kind must be 'discrete' or 'continuous'")
91
+
92
+ if kind == "discrete":
93
+ if n > len(colors):
94
+ raise ValueError(f"{name} holds {len(colors)} colors, "
95
+ f"use kind='continuous' for more")
96
+ out = colors[:n] if override_order else [c for c, r in zip(colors, order) if r <= n]
97
+ else:
98
+ out = _interpolate(colors, n)
99
+ return out[::-1] if direction == -1 else out
100
+
101
+
102
+ def cmap(name, n=None, kind="continuous", direction=1):
103
+ """A matplotlib colormap built from the palette.
104
+
105
+ Parameters
106
+ ----------
107
+ name : palette name, see list_palettes()
108
+ n : leave empty for a smooth colormap. Give a number to get that many
109
+ fixed steps instead, which suits classified rasters and choropleths.
110
+ kind : how the n steps are chosen. "continuous" samples evenly along the
111
+ ramp and is what ordered data usually wants. "discrete" follows the
112
+ stored pick order, which is meant for categories.
113
+ direction : 1 for the stored order, -1 to reverse
114
+
115
+ Needs matplotlib, which installs with `pip install rang[plots]`.
116
+ """
117
+ _check_direction(direction)
118
+ from matplotlib.colors import LinearSegmentedColormap, ListedColormap
119
+
120
+ if n is None:
121
+ colors = list(_get(name)["colors"])
122
+ if direction == -1:
123
+ colors = colors[::-1]
124
+ return LinearSegmentedColormap.from_list(name, colors)
125
+
126
+ colors = rang(name, n, kind, direction=direction)
127
+ return ListedColormap(colors, name=f"{name}_{len(colors)}")
128
+
129
+
130
+ def registered_name(name, reverse=False):
131
+ """The matplotlib lookup name for a palette, such as 'rang:Kashan'."""
132
+ _get(name)
133
+ return f"rang:{name}{'_r' if reverse else ''}"
134
+
135
+
136
+ def register(force=False):
137
+ """Add every palette to matplotlib's colormap registry.
138
+
139
+ After calling this, any library that accepts a colormap name works with
140
+ Rang without knowing Rang exists. That covers xarray, geopandas,
141
+ rioxarray, seaborn and plain matplotlib.
142
+
143
+ import rang
144
+ rang.register()
145
+ data.plot(cmap="rang:Termeh")
146
+
147
+ Each palette registers twice, once forward and once reversed with an
148
+ "_r" suffix, matching the matplotlib convention.
149
+
150
+ Calling this again is safe and quiet. Names already in the registry are
151
+ left alone unless force is True, which replaces them.
152
+
153
+ Returns the list of Rang names in the registry.
154
+ """
155
+ import matplotlib
156
+
157
+ names = []
158
+ for key in PALETTES:
159
+ for reverse in (False, True):
160
+ lookup = registered_name(key, reverse)
161
+ names.append(lookup)
162
+ if lookup in matplotlib.colormaps:
163
+ if not force:
164
+ continue
165
+ matplotlib.colormaps.unregister(lookup)
166
+ matplotlib.colormaps.register(
167
+ cmap(key, direction=-1 if reverse else 1), name=lookup
168
+ )
169
+ return names
170
+
171
+
172
+ def set_palette(name, n=None, direction=1):
173
+ """Use a palette for the default line and patch colors in matplotlib.
174
+
175
+ Sets the axes property cycle, so plots drawn afterwards pick up the
176
+ palette without naming a color on every call. Returns the colors used.
177
+ """
178
+ import matplotlib.pyplot as plt
179
+
180
+ colors = rang(name, n, direction=direction)
181
+ plt.rcParams["axes.prop_cycle"] = plt.cycler(color=colors)
182
+ return colors
183
+
184
+
185
+ def source(name):
186
+ """Provenance of the artwork behind a palette."""
187
+ return dict(_get(name)["source"])
188
+
189
+
190
+ def colorblind_friendly(name):
191
+ """Stored separation flag based on Rang's cutoff of 8."""
192
+ return bool(_get(name)["colorblind"])
rang/_palettes.py ADDED
@@ -0,0 +1,14 @@
1
+ """Palette data written by tools/build.py. Edit palettes/*.json instead."""
2
+
3
+ PALETTES = {
4
+ "Kashan": {'colors': ('#7f3020', '#ab4a47', '#c07049', '#c59b46', '#ccac7e', '#e2cfb1', '#8a9463', '#345f72', '#1a3b45'), 'order': (3, 6, 4, 8, 7, 1, 9, 5, 2), 'colorblind': False, 'persian': 'کاشان', 'pronunciation': 'kah-SHAHN', 'source': {'title': 'Silk Kashan Carpet', 'artist': '', 'date': '16th century', 'geography': 'Made in Iran, probably Kashan', 'medium': 'Silk (warp, weft and pile), asymmetrically knotted pile', 'museum': 'The Metropolitan Museum of Art, New York', 'department': 'Islamic Art', 'accession': '58.46', 'credit': 'Gift of Mrs. Douglas M. Moffat, 1958', 'url': 'https://www.metmuseum.org/art/collection/search/451470', 'image': 'https://images.metmuseum.org/CRDImages/is/original/DT5450.jpg', 'card_image': 'sources/kashan/card.jpg', 'public_domain': True}},
5
+ "Golestan": {'colors': ('#432f2c', '#ae6259', '#b57f86', '#b5b5ac', '#cbb11c', '#9a9a68', '#45939c', '#577ab1', '#333a80'), 'order': (4, 5, 8, 6, 1, 7, 3, 9, 2), 'colorblind': True, 'persian': 'گلستان', 'pronunciation': 'goh-leh-STAHN, Persian for rose garden', 'source': {'title': 'Hunting-scene tile panel at Golestan Palace', 'artist': '', 'date': 'photographed 2018', 'geography': 'Tehran, Iran', 'medium': 'Glazed polychrome tilework', 'site': 'Golestan Palace, UNESCO World Heritage Site', 'reference_label': 'Site reference', 'url': 'https://whc.unesco.org/en/list/1422/', 'image': 'sources/golestan/tilework.jpg', 'context_image': 'sources/golestan/palace.jpg', 'context_caption': 'The panel in place at the palace, with a resident cat', 'credit': 'Photo by Mohsen Tahmasebi Nasab, 2018', 'public_domain': False, 'rights': 'Copyright Mohsen Tahmasebi Nasab, all rights reserved'}},
6
+ "Termeh": {'colors': ('#e5f0ee', '#c8dfe3', '#a9ccd7', '#7fb5c1', '#5d95a8', '#3e738e', '#274e68'), 'order': (1, 7, 5, 6, 3, 4, 2), 'colorblind': False, 'persian': 'ترمه', 'pronunciation': 'tehr-MEH', 'source': {'title': 'Termeh cloth with boteh motifs', 'artist': '', 'date': 'photographed 2026', 'geography': 'Iran', 'medium': 'Textile', 'site': 'Yazd textile tradition', 'reference_label': 'Tradition reference', 'url': 'https://asia-archive.si.edu/object/S2017.14/', 'image': 'sources/termeh/cloth.jpg', 'context_image': 'sources/termeh/setting.jpg', 'context_caption': 'Termeh at rest, a draped cloth, runners and a covered chest', 'credit': 'Photo by Mohsen Tahmasebi Nasab, 2026', 'public_domain': False, 'rights': 'Copyright Mohsen Tahmasebi Nasab, all rights reserved'}},
7
+ "Khatam": {'colors': ('#1c110b', '#542020', '#8d310e', '#bf480d', '#b27a3c', '#c58c51', '#d9a545', '#dbba94', '#e5c870'), 'order': (1, 6, 5, 3, 8, 4, 7, 9, 2), 'colorblind': False, 'persian': 'خاتم', 'pronunciation': 'khaw-TAM', 'source': {'title': 'Khatam panel with brass stars', 'citation': 'Khatam panel with brass stars.', 'artist': '', 'date': '2026', 'geography': 'Iran', 'medium': 'Wood, bone and brass marquetry', 'site': 'Khatam marquetry tradition', 'reference_label': 'Craft history', 'url': 'https://www.iranicaonline.org/articles/isfahan-xiii-crafts/', 'image': 'sources/khatam/inlay.jpg', 'context_image': 'sources/khatam/bazaar.jpg', 'context_caption': 'A handicraft shop in the Isfahan bazaar, 2018, khatam boxes stacked in front of minakari enamel and metalwork', 'credit': 'Photos by Mohsen Tahmasebi Nasab, 2018 and 2026', 'public_domain': False, 'rights': 'Copyright Mohsen Tahmasebi Nasab, all rights reserved'}},
8
+ "Nasir": {'colors': ('#261410', '#3b1261', '#4027e1', '#518ffd', '#74ecf9', '#50a877', '#6dd96f', '#ebc05c', '#f04a23'), 'order': (1, 7, 3, 5, 2, 8, 9, 4, 6), 'colorblind': False, 'persian': 'نصیر', 'pronunciation': 'nah-SEER, from Nasir al-Mulk Mosque in Shiraz', 'source': {'title': 'Stained-glass window at Nasir al-Mulk Mosque', 'artist': 'Tpmehdi', 'date': '2018', 'geography': 'Shiraz, Iran', 'medium': 'Digital photograph', 'site': 'Nasir al-Mulk Mosque', 'reference_label': 'Wikimedia Commons source', 'url': 'https://commons.wikimedia.org/wiki/File:DSC_0277-%D9%85%D8%B3%D8%AC%D8%AF_%D9%86%D8%B5%DB%8C%D8%B1%D8%A7%D9%84%D9%85%D9%84%DA%A9.jpg', 'image': 'sources/nasir/window.jpg', 'context_image': 'sources/nasir/interior.jpg', 'context_caption': 'Sunlight and stained glass reflected across the prayer hall of Nasir al-Mulk Mosque', 'context_url': 'https://commons.wikimedia.org/wiki/File:Nasir_al-_mulk_mosque%2C_Shiraz.jpg', 'context_credit': 'Photograph by MohammadReza Domiri Ganji, 2013', 'context_rights': 'Licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)', 'credit': 'Photograph by Tpmehdi, 2018', 'public_domain': False, 'rights': 'Licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). Rang gallery images use cropped and resized adaptations'}},
9
+ "Mina": {'colors': ('#581c1d', '#984946', '#c19498', '#e7f2f6', '#9ecaee', '#56adee', '#4090a2', '#193caa', '#07187b'), 'order': (5, 3, 7, 1, 6, 9, 4, 8, 2), 'colorblind': True, 'persian': 'مینا', 'pronunciation': 'mee-NAH, Persian for enamel', 'source': {'title': 'Lidded enamel vessel', 'artist': '', 'date': 'photographed 2026', 'geography': 'Iran', 'medium': 'Painted enamel on metal', 'site': 'Persian enamelwork tradition', 'reference_label': 'Craft history', 'url': 'https://www.iranicaonline.org/articles/enamel/', 'image': 'sources/mina/piece.jpg', 'context_image': 'sources/mina/context.jpg', 'context_caption': 'Minakari enamelware displayed in an Isfahan shop', 'context_url': 'https://commons.wikimedia.org/wiki/File:Iranian_vitreous_enamel_(cropped).JPG', 'context_credit': 'Photograph by Wikimedia Commons user مانفی, 2012. Cropped by Joalbertine, 2020', 'context_rights': 'Licensed under [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)', 'credit': 'Photo by Mohsen Tahmasebi Nasab, 2026', 'public_domain': False, 'rights': 'Copyright Mohsen Tahmasebi Nasab, all rights reserved'}},
10
+ "Rostan": {'colors': ('#4b241e', '#603d34', '#883c3e', '#aa3a41', '#d63d3b', '#d26c55', '#d98665', '#c0947d', '#d2b6a1'), 'order': (1, 9, 5, 8, 3, 7, 4, 6, 2), 'colorblind': False, 'persian': 'رستن', 'pronunciation': 'rohs-TAN, from the Persian title Az In Gooneh Rostan', 'source': {'title': 'Growing in thus Way', 'note': "The English title follows the wording on the artist's official website", 'citation': 'Growing in thus Way, 1972, 140 x 140 cm.', 'artist': 'Iran Darroudi', 'artist_url': 'https://www.irandarroudi.com/en/biography', 'date': '1972', 'dimensions': '140 x 140 cm', 'geography': 'Iran', 'medium': 'Painting', 'site': 'Iran Darroudi official website', 'reference_label': 'Official artwork page', 'url': 'https://www.irandarroudi.com/en/paints', 'image': 'sources/rostan/growing-in-thus-way.jpg', 'credit': 'Artwork by Iran Darroudi', 'public_domain': False, 'rights': 'Copyright Iran Darroudi, all rights reserved. This low-resolution reference image is included for identification and commentary only', 'preserve_aspect': True}},
11
+ "Shahnameh": {'colors': ('#41356f', '#4b3d97', '#798cb8', '#6d866a', '#596956', '#d4b96b', '#d5c9b7', '#b0472c', '#a6373e'), 'order': (1, 8, 4, 7, 5, 6, 2, 3, 9), 'colorblind': False, 'persian': 'شاهنامه', 'pronunciation': 'shah-nah-MEH, Persian for Book of Kings', 'source': {'title': 'The Wedding of Siyavush and Farangis, Folio 185v from the Shahnama of Shah Tahmasp', 'citation': 'The Wedding of Siyavush and Farangis, folio 185v from the Shahnama of Shah Tahmasp, ca. 1525-30.', 'artist': "Painting attributed to Qasim ibn 'Ali, workshop directed by Mir Musavvir", 'date': 'ca. 1525-30', 'dimensions': 'painting 28.9 x 18.4 cm, page 47.3 x 32.1 cm', 'geography': 'Made in Iran, Tabriz', 'medium': 'Opaque watercolor, ink, silver and gold on paper', 'museum': 'The Metropolitan Museum of Art, New York', 'department': 'Islamic Art', 'accession': '1970.301.28', 'credit': 'Gift of Arthur A. Houghton Jr., 1970', 'url': 'https://www.metmuseum.org/art/collection/search/452137', 'image': 'sources/shahnameh/folio.jpg', 'download_url': 'https://images.metmuseum.org/CRDImages/is/original/DP107144.jpg', 'public_domain': True}},
12
+ "Gilas": {'colors': ('#58463f', '#598fb6', '#964765', '#b8715b', '#d8c723'), 'order': (1, 3, 5, 4, 2), 'colorblind': True, 'persian': 'گیلاس', 'pronunciation': 'gee-LAAS, Persian for cherry', 'source': {'title': 'Taste of Cherry promotional poster', 'note': 'Poster for the 1997 film directed by Abbas Kiarostami', 'citation': 'Taste of Cherry promotional poster, 1997.', 'date': '1997', 'geography': 'Iran', 'medium': 'Printed film poster', 'site': 'Wikipedia', 'reference_label': 'Poster file page', 'url': 'https://en.wikipedia.org/wiki/File:Tasteofcherryposter.jpg', 'image': 'sources/gilas/poster.jpg', 'credit': 'Promotional poster for Taste of Cherry', 'public_domain': False, 'rights': 'Copyrighted film poster, all rights reserved. Wikipedia uses its copy under a fair-use rationale that does not grant a reuse license. This 220-pixel reference is included for identification and commentary only', 'preserve_aspect': True}},
13
+ "Iwan": {'colors': ('#efbf15', '#b99241', '#6897b7', '#2e89ab', '#3263ac', '#0e37ae', '#0412cc', '#150c7d', '#06055a'), 'order': (1, 5, 3, 7, 4, 9, 6, 8, 2), 'colorblind': False, 'persian': 'ایوان', 'pronunciation': 'ee-VAHN, Persian for a vaulted hall open on one side', 'source': {'title': 'Entrance iwan of the Shah Mosque', 'citation': 'Entrance of the Shah Mosque of Isfahan, 2020.', 'artist': 'Farzan95, Farzan Dehbashi', 'date': '2020', 'geography': 'Isfahan, Iran', 'medium': 'Digital photograph', 'site': 'Wikimedia Commons', 'reference_label': 'Photograph and license record', 'url': 'https://commons.wikimedia.org/wiki/File:Shah_mosque_of_isfahan.jpg', 'image': 'sources/iwan/entrance.jpg', 'context_image': 'sources/iwan/iwan.jpg', 'context_caption': 'Looking up into the tiled entrance iwan of the Shah Mosque', 'context_url': 'https://commons.wikimedia.org/wiki/File:Mezquita_Shah,_Isfah%C3%A1n,_Ir%C3%A1n,_2016-09-20,_DD_64.jpg', 'context_credit': 'Photograph by Diego Delso, 2016', 'context_rights': 'Licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)', 'credit': 'Photograph by Farzan95, 2020', 'public_domain': False, 'rights': 'Licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). Rang gallery images use resized adaptations', 'preserve_aspect': True}},
14
+ }
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.4
2
+ Name: rang
3
+ Version: 0.2.0
4
+ Summary: Color palettes from Persian art for plots and maps
5
+ Author: Mohsen Tahmasebi Nasab
6
+ Maintainer: Mohsen Tahmasebi Nasab
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/mohsennasab/Rang
9
+ Project-URL: Source, https://github.com/mohsennasab/Rang
10
+ Project-URL: Documentation, https://github.com/mohsennasab/Rang#readme
11
+ Project-URL: Issues, https://github.com/mohsennasab/Rang/issues
12
+ Keywords: color,palette,colormap,matplotlib,persian art,visualization,cartography
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Scientific/Engineering :: Visualization
24
+ Classifier: Topic :: Multimedia :: Graphics
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ License-File: LICENSE-CC0.txt
29
+ Provides-Extra: plots
30
+ Requires-Dist: matplotlib>=3.7; extra == "plots"
31
+ Dynamic: license-file
32
+
33
+ # rang for Python
34
+
35
+ Color palettes from Persian art. Part of the [Rang](https://github.com/mohsennasab/Rang)
36
+ project, which also packages the palettes for R, ArcGIS Pro, QGIS, GeoLibre
37
+ and HEC-RAS.
38
+
39
+ ```
40
+ pip install rang
41
+ ```
42
+
43
+ The package has no required dependencies. The matplotlib helpers need
44
+ matplotlib, which you can pull in at the same time:
45
+
46
+ ```
47
+ pip install "rang[plots]"
48
+ ```
49
+
50
+ ## Colors
51
+
52
+ ```python
53
+ import rang
54
+
55
+ rang.list_palettes() # available names
56
+ rang.rang("Kashan") # all nine colors, ramp order
57
+ rang.rang("Kashan", 4) # four well separated colors
58
+ rang.rang("Kashan", 30, "continuous") # interpolated ramp
59
+ rang.source("Kashan") # the artwork behind the palette
60
+ ```
61
+
62
+ Discrete requests use the stored separation order. Continuous requests
63
+ interpolate through the source ramp in sRGB.
64
+
65
+ ## matplotlib
66
+
67
+ ```python
68
+ rang.cmap("Termeh") # smooth colormap
69
+ rang.cmap("Termeh", 6) # six fixed steps, for classified data
70
+ rang.cmap("Termeh", direction=-1) # reversed
71
+
72
+ rang.set_palette("Golestan") # default colors for lines and bars
73
+ ```
74
+
75
+ `register()` adds every palette to the matplotlib registry under a `rang:`
76
+ name. Do this once and any library that accepts a colormap name will take a
77
+ Rang palette, including xarray, geopandas, rioxarray and seaborn.
78
+
79
+ ```python
80
+ rang.register()
81
+
82
+ plt.imshow(data, cmap="rang:Iwan")
83
+ plt.imshow(data, cmap="rang:Iwan_r") # every palette also registers reversed
84
+ ```
85
+
86
+ Calling `register()` again is safe and quiet.
87
+
88
+ ## Picking a palette
89
+
90
+ Termeh, Iwan, Khatam and Rostan run steadily from light to dark or dark to
91
+ light, which is what depth, elevation and rainfall maps need. Kashan,
92
+ Golestan and Mina move from a warm side through a light center to a cool
93
+ side. Nasir, Shahnameh and Gilas jump around in brightness, so they suit
94
+ categories rather than measured quantities.
95
+
96
+ Each palette page in the repository shows sample plots and the color vision
97
+ checks.
98
+
99
+ ## License
100
+
101
+ The package software is available under the MIT License. To the extent that
102
+ copyright or database rights apply, the Rang palette definitions are
103
+ dedicated to the public domain under CC0 1.0 Universal. Photographs and
104
+ third-party data are covered by the notices in the main repository.
@@ -0,0 +1,8 @@
1
+ rang/__init__.py,sha256=kTt3kZ7fSX0a15kLTrMaCpp7lZp32XqC1D4lAUEp9rQ,6273
2
+ rang/_palettes.py,sha256=E7imRd7M9InV-eQctLTVP2-zhyGfthracodNtQJDwSQ,10466
3
+ rang-0.2.0.dist-info/licenses/LICENSE,sha256=VgPDfcrx_-uvFDwGNj8eBPJksKRC5m3JJqtFW3mn1yE,1079
4
+ rang-0.2.0.dist-info/licenses/LICENSE-CC0.txt,sha256=TVrtvpIdefraxaP34SEsKVpdBKSHKCP48pPXX_FfwW8,470
5
+ rang-0.2.0.dist-info/METADATA,sha256=1gwwtaYI3ZixaumX3y89VskuOSRcPsBUVUsB8BAPIFQ,3728
6
+ rang-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
7
+ rang-0.2.0.dist-info/top_level.txt,sha256=h9ZZxDnR_bq-sP2n-Hzusbh-dOVnkERdJDa0Qt1sm_A,5
8
+ rang-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohsen Tahmasebi Nasab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ Rang palette data under CC0 1.0 Universal
2
+
3
+ To the extent possible under law, Mohsen Tahmasebi Nasab has waived all
4
+ copyright and related or neighboring rights in the Rang palette names, color
5
+ values, descriptions, and ordering.
6
+
7
+ This dedication applies only to the palette data. The Python software remains
8
+ licensed under the MIT License in LICENSE.
9
+
10
+ The complete CC0 1.0 Universal legal code is available at:
11
+ https://creativecommons.org/publicdomain/zero/1.0/legalcode
@@ -0,0 +1 @@
1
+ rang