Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 34 additions & 6 deletions pygmt/src/histogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
data_kind,
deprecate_parameter,
fmt_docstring,
is_given,
is_nonstr_iter,
kwargs_to_strings,
use_alias,
Expand Down Expand Up @@ -206,7 +207,7 @@ def histogram(
bar_offset: float | str | None = None,
cmap: str | bool = False,
pen: str | None = None,
fill: str | Pattern | None = None,
fill: str | Pattern | Literal["position", "value"] | None = None,
annot: bool = False,
annot_position: Literal["start", "end"] = "end",
annot_font: str | None = None,
Expand Down Expand Up @@ -240,7 +241,7 @@ def histogram(
$aliases
- A = horizontal
- B = frame
- C = cmap
- C = cmap, **+b**: fill
- D = annot, **+b**: annot_position, **+f**: annot_font, **+o**: annot_offset,
**+r**: annot_orientation
- E = bar_width, **+o**: bar_offset
Expand Down Expand Up @@ -271,12 +272,22 @@ def histogram(
is a file name or a 2-D sequence.
- A 1-D array of weights, one per data point, requiring that ``data`` is a 1-D
sequence of values.
$cmap
pen
Draw bar outline (or stair-case curve) using the specified pen thickness
[Default is no outline].
fill
Set color or pattern for filling bars [Default is no fill].
Set color or pattern for filling bars [Default is no fill]. Set it to one of the
two special values to fill bars by looking up the color from a CPT instead of a
constant color:

- ``"position"``: look up the color using the mid-coordinate of the bin. This is
the default when ``cmap`` is set.
Comment on lines +283 to +284

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here we write "bin", but the GMT says "bar", please see https://docs.generic-mapping-tools.org/dev/histogram.html#c:

Give a CPT. The mid-coordinate for each bar is used to look up the bar color.

I agree that "bin" makes more sense. The x-position of the bars can be changed, e.g., via bar_offset.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think "bar" represents the visual element, while "bin" represents the actual data range of a bar.

- ``"value"``: look up the color using the bin value, i.e., the bar count or
frequency.

The special values require a CPT (either the current CPT or explicitly set by
``cmap``), and can't be used with ``fill``.
$cmap
annot
If ``True``, annotate each bar with the value it represents. The remaining
``annot_*`` parameters control how the annotations look and are ignored if
Expand Down Expand Up @@ -384,6 +395,20 @@ def histogram(
required="bar_width", reason="Required when 'bar_offset' is set."
)

# "position" and "value" are special values that fill bars by values and cmap.
match fill:
case "position":
_fill_color, _fill_lookup = None, ""
case "value":
_fill_color, _fill_lookup = None, "+b"
case _:
_fill_color, _fill_lookup = fill, None # type: ignore[assignment]
if _fill_color is not None and is_given(cmap):
raise GMTParameterError(
at_most_one=["cmap", "fill"],
reason="Cannot use 'cmap' when 'fill' is a constant color or pattern.",
)

# weights can be given as a 1-D array, or as a boolean to indicate that the second
# column of data contains weights. If weights is an array, then data must be a 1-D
# sequence of values.
Expand All @@ -396,7 +421,10 @@ def histogram(

aliasdict = AliasSystem(
A=Alias(horizontal, name="horizontal"),
C=Alias(cmap, name="cmap"),
C=[
Alias(cmap, name="cmap"),
Alias(_fill_lookup, name="fill"),
],
D=_alias_option_D(
annot=annot,
annot_position=annot_position,
Expand All @@ -409,7 +437,7 @@ def histogram(
Alias(bar_offset, name="bar_offset", prefix="+o"),
],
F=Alias(center, name="center"),
G=Alias(fill, name="fill"),
G=Alias(_fill_color, name="fill"),
L=Alias(
out_range,
name="out_range",
Expand Down
3 changes: 3 additions & 0 deletions pygmt/tests/baseline/test_histogram_fill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 73 additions & 1 deletion pygmt/tests/test_histogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import numpy as np
import pandas as pd
import pytest
from pygmt import Figure
from pygmt import Figure, makecpt
from pygmt.exceptions import GMTParameterError, GMTTypeError
from pygmt.helpers import GMTTempFile
from pygmt.params import Axis
Expand Down Expand Up @@ -84,6 +84,78 @@ def test_histogram_baroffset(data):
)


@pytest.mark.mpl_image_compare(filename="test_histogram_fill.png")
def test_histogram_fill(data):
"""
Test filling bars with constant color and lookup table values.
"""
kwargs = {
"data": data,
"projection": "X5c/5c",
"region": [0, 10, 0, 8],
"series": 1,
"frame": Axis(annot=True),
}
fig = Figure()
# Constant fill
fig.histogram(fill="green", **kwargs)
fig.shift_origin(xshift=6)
# Fill bars by bin position
makecpt(cmap="viridis", series=[0, 9, 1])
fig.histogram(fill="position", **kwargs)
fig.colorbar(frame=True)
# Fill bars by bin value
fig.shift_origin(xshift=6)
makecpt(cmap="viridis", series=[0, 6, 1])
fig.histogram(fill="value", **kwargs)
fig.colorbar(frame=True)
return fig


@pytest.mark.mpl_image_compare(filename="test_histogram_fill.png")
def test_histogram_fill_old_cmap_syntax(data):
"""
Test filling bars with constant color and lookup table values.
"""
kwargs = {
"data": data,
"projection": "X5c/5c",
"region": [0, 10, 0, 8],
"series": 1,
"frame": Axis(annot=True),
}
fig = Figure()
# Constant fill
fig.histogram(fill="green", **kwargs)
fig.shift_origin(xshift=6)
# Fill bars by bin position
makecpt(cmap="viridis", series=[0, 9, 1])
fig.histogram(cmap=True, **kwargs)
fig.colorbar(frame=True)
# Fill bars by bin value
fig.shift_origin(xshift=6)
makecpt(cmap="viridis", series=[0, 6, 1])
fig.histogram(cmap="+b", **kwargs)
fig.colorbar(frame=True)
return fig


def test_histogram_fill_color_with_cmap(data):
"""
Test that a constant fill color cannot be combined with cmap.
"""
fig = Figure()
with pytest.raises(GMTParameterError):
fig.histogram(
data=data,
projection="X10c/10c",
region=[0, 9, 0, 8],
series=1,
cmap=True,
fill="green",
)


@pytest.mark.mpl_image_compare(filename="test_histogram_weights.png")
def test_histogram_weights_file(data, weights):
"""
Expand Down
Loading