Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

WIP classify to rgba #211

Merged
merged 25 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e36a113
add classify rgb function
knaaptime May 14, 2024
bec1919
alpha
knaaptime Jun 19, 2024
6070e8c
move to util; add test
knaaptime Jul 2, 2024
1f7434e
CI: ensure 3.9 envs are compatible (#218)
martinfleis Jun 26, 2024
4de91bb
CI: doctest only on ubuntu latest (#219)
martinfleis Jun 26, 2024
0fad7cd
CI: test against Python 3.12 (#220)
martinfleis Jun 26, 2024
aab5ddd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 2, 2024
8e9ac98
[pre-commit.ci] pre-commit autoupdate (#221)
pre-commit-ci[bot] Jul 2, 2024
f1f4add
plot histogram
knaaptime Jun 19, 2024
d780b2f
reorder args
knaaptime Jun 19, 2024
ce219a0
despine optional; add comments
knaaptime Jun 19, 2024
171a566
warn not raise if sns missing
knaaptime Jun 19, 2024
394bd67
martins improvements
knaaptime Jun 26, 2024
918ff1c
simplify args
knaaptime Jun 26, 2024
815a75f
mpl not pandas in docstring
knaaptime Jun 26, 2024
e668c8e
linewidth
knaaptime Jun 26, 2024
447df21
add tests
knaaptime Jun 26, 2024
c89ef62
pytestmpl
knaaptime Jun 26, 2024
5ff49da
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 26, 2024
46fee1e
rm unused kwarg logic
knaaptime Jun 26, 2024
bfefddf
forgot color
knaaptime Jun 26, 2024
e85b810
Merge branch 'main' of github.com:pysal/mapclassify into classify
knaaptime Jul 3, 2024
d8805db
kwargs no k
knaaptime Jul 3, 2024
cb9d014
document kwargs
knaaptime Jul 3, 2024
0f64631
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mapclassify/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import contextlib
from importlib.metadata import PackageNotFoundError, version

from . import util
from ._classify_API import classify
from .classifiers import (
CLASSIFIERS,
Expand Down
17 changes: 17 additions & 0 deletions mapclassify/tests/test_rgba.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import geopandas
import numpy as np
from mapclassify.util import get_rgba

world = geopandas.read_file(
"https://naciscdn.org/naturalearth/110m/cultural/ne_110m_admin_0_countries.zip"
)


def test_rgba():
colors = get_rgba(world.area, cmap="viridis")[0]
assert colors == [
np.float64(68.08602),
np.float64(1.24287),
np.float64(84.000825),
np.float64(255.0),
]
73 changes: 73 additions & 0 deletions mapclassify/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from ._classify_API import classify as _classify


def get_rgba(
values,
classifier="quantiles",
cmap="viridis",
alpha=1,
nan_color=[255, 255, 255, 255],
**kwargs,
):
"""Convert array of values into RGBA colors using a colormap and classifier.

Parameters
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kwargs should probably be mentioned here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, i'm always unsure what to do in the docstrings when there's a catchall

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always mention where are they passed to.

----------
values : list-like
array of input values
classifier : str, optional
string description of a mapclassify classifier, by default "quantiles"
cmap : str, optional
name of matplotlib colormap to use, by default "viridis"
alpha : float
alpha parameter that defines transparency. Should be in the range [0,1]
nan_color : list, optional
RGBA color to fill NaN values, by default [255, 255, 255, 255]
kwargs : dict
additional keyword arguments are passed to `mapclassify.classify`

Returns
-------
numpy.array
array of lists with each list containing four values that define a color using
RGBA specification.
"""
try:
import pandas as pd
from matplotlib import cm
from matplotlib.colors import Normalize
except ImportError as e:
raise ImportError("This function requires pandas and matplotlib") from e
if not (alpha <= 1) and (alpha >= 0):
raise ValueError("alpha must be in the range [0,1]")

Check warning on line 42 in mapclassify/util.py

View check run for this annotation

Codecov / codecov/patch

mapclassify/util.py#L42

Added line #L42 was not covered by tests
if not pd.api.types.is_list_like(nan_color) and not len(nan_color) == 4:
raise ValueError("`nan_color` must be list-like of 4 values: (R,G,B,A)")

Check warning on line 44 in mapclassify/util.py

View check run for this annotation

Codecov / codecov/patch

mapclassify/util.py#L44

Added line #L44 was not covered by tests

# only operate on non-NaN values
v = pd.Series(values, dtype=object)
legit_indices = v[~v.isna()].index.values

# transform (non-NaN) values into class bins
bins = _classify(v.dropna().values, scheme=classifier, **kwargs).yb

# create a normalizer using the data's range (not strictly 1-k...)
norm = Normalize(min(bins), max(bins))

# map values to colors
n_cmap = cm.ScalarMappable(norm=norm, cmap=cmap)

# create array of RGB values (lists of 4) of length n
vals = [n_cmap.to_rgba(i, alpha=alpha) for i in bins]

# convert decimals to whole numbers
rgbas = []
for val in vals:
# convert each value in the array of lists
rgbas.append([i * 255 for i in val])

# replace non-nan values with colors
colors = pd.Series(rgbas, index=legit_indices)
v.update(colors)
v = v.fillna(f"{nan_color}").apply(list)

return v.values