From 2b54a3d25764e188839549c1055ee2bb43525aed Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Wed, 9 Sep 2026 17:27:43 +0800 Subject: [PATCH 1/2] Figure.histogram: Add parameters to annote bars --- pygmt/src/histogram.py | 89 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 9 deletions(-) diff --git a/pygmt/src/histogram.py b/pygmt/src/histogram.py index 539527fa071..276242980c4 100644 --- a/pygmt/src/histogram.py +++ b/pygmt/src/histogram.py @@ -19,11 +19,61 @@ from pygmt.params import Axis, Frame +def _alias_option_D( # ruff: ignore[invalid-function-name] + annot: bool = False, + annot_position: Literal["top", "bottom"] = "top", + annot_font: str | None = None, + annot_offset: float | str | None = None, + annot_orientation: Literal["horizontal", "vertical"] = "horizontal", +): + """ + Helper function to build the -D option for the histogram module. + + >>> def parse(**kwargs): + ... return AliasSystem(D=_alias_option_D(**kwargs)).get("D") + + >>> parse(annot=False) + >>> parse(annot=True) + '' + >>> parse( + ... annot=True, + ... annot_position="bottom", + ... annot_font="12p,Helvetica-Bold", + ... annot_offset="6p", + ... annot_orientation="vertical", + ... ) + '+b+f12p,Helvetica-Bold+o6p+r' + + >>> # annot_* parameters are ignored if annot is not set + >>> parse(annot_position="top") + """ + # Ignore any annot_* parameters if annot is not set. + if not annot: + return Alias(False, name="annot") + + # If annot is set, return a list of Alias objects for the annot_* parameters. + return [ + Alias( + annot_position, + name="annot_position", + mapping={"top": "", "bottom": "+b"}, + ), + Alias(annot_font, name="annot_font", prefix="+f"), + Alias(annot_offset, name="annot_offset", prefix="+o"), + Alias( + annot_orientation, + name="annot_orientation", + mapping={"horizontal": "", "vertical": "+r"}, + ), + ] + + @fmt_docstring # TODO(PyGMT>=0.22.0): Remove the deprecated "extreme" parameter. +# TODO(PyGMT>=0.22.0): Remove the deprecated "annotate" parameter. @deprecate_parameter("extreme", "out_range", "0.20.0", remove_version="0.22.0") +@deprecate_parameter("annotate", "annot", "0.20.0", remove_version="0.22.0") @use_alias( - D="annotate", F="center", N="distribution", T="series", @@ -44,6 +94,11 @@ def histogram( cmap: str | bool = False, pen: str | None = None, fill: str | None = None, + annot: bool = False, + annot_position: Literal["top", "bottom"] = "top", + annot_font: str | None = None, + annot_offset: float | str | None = None, + annot_orientation: Literal["horizontal", "vertical"] = "horizontal", horizontal: bool = False, out_range: Literal["first", "last", "both"] | None = None, stairs: bool = False, @@ -68,6 +123,8 @@ def histogram( - A = horizontal - B = frame - C = cmap + - D = annot, **+b**: annot_position, **+f**: annot_font, **+o**: annot_offset, + **+r**: annot_orientation - E = bar_width, **+o**: bar_offset - G = fill - J = projection @@ -93,14 +150,21 @@ def histogram( [Default is no outline]. fill Set color or pattern for filling bars [Default is no fill]. - annotate : bool or str - [**+b**][**+f**\ *font*][**+o**\ *off*][**+r**]. - Annotate each bar with the count it represents. Append any of the - following modifiers: Use **+b** to place the labels beneath the bars - instead of above; use **+f** to change to another font than the default - annotation font; use **+o** to change the offset between bar and - label [Default is ``"6p"``]; use **+r** to rotate the labels from - horizontal to vertical. + annot + If ``True``, annotate each bar with the value it represents. The remaining + ``annot_*`` parameters control how the annotations look and are ignored if + ``annot`` is not set. + annot_position + Position of the annotations relative to the bars. Valid values are ``"top"`` and + ``"bottom"`` [Default is ``"top"``]. + annot_font + Font of the annotations [Default is :gmt-term:`FONT_ANNOT_PRIMARY`]. + annot_offset + Offset between a bar and its annotation, with an optional + :ref:`dimension unit ` [Default is ``"6p"``]. + annot_orientation + Orientation of the annotations. Valid values are ``"horizontal"`` and + ``"vertical"`` [Default is ``"horizontal"``]. bar_width Use an alternative histogram bar width than the default set via ``series``. Give either an alternative width in data units, or the user may append a @@ -175,6 +239,13 @@ def histogram( aliasdict = AliasSystem( A=Alias(horizontal, name="horizontal"), C=Alias(cmap, name="cmap"), + D=_alias_option_D( + annot=annot, + annot_position=annot_position, + annot_font=annot_font, + annot_offset=annot_offset, + annot_orientation=annot_orientation, + ), E=[ Alias(bar_width, name="bar_width"), Alias(bar_offset, name="bar_offset", prefix="+o"), From 5f527aa1d2226dc6893d3f42f5d9e1bada05a04d Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Wed, 16 Sep 2026 16:48:20 +0800 Subject: [PATCH 2/2] Update histogram tutorial --- examples/tutorials/advanced/cartesian_histograms.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/tutorials/advanced/cartesian_histograms.py b/examples/tutorials/advanced/cartesian_histograms.py index 3999b2386ba..1dfce44eb53 100644 --- a/examples/tutorials/advanced/cartesian_histograms.py +++ b/examples/tutorials/advanced/cartesian_histograms.py @@ -202,7 +202,7 @@ # To create a histogram showing the cumulative values set ``cumulative=True``. Here, the # bars of the cumulative histogram are filled with a :class:`pygmt.params.Pattern` via # the ``fill`` parameter. Annotate each bar with the counts it represents using the -# ``annotate`` parameter. +# ``annot`` parameter. fig = pygmt.Figure() @@ -220,8 +220,7 @@ fill="red3", pen="1p,darkgray,solid", histtype=0, - # Annotate each bar with the counts it represents - annotate=True, + annot=True, ) fig.shift_origin(xshift="w+1c") @@ -241,10 +240,9 @@ fill=Pattern(8, bgcolor="white", fgcolor="black"), pen="1p,darkgray,solid", histtype=0, - # Show cumulative counts - cumulative=True, - # Offset ("+o") the label by 10 points in negative y-direction - annotate="+o-10p", + cumulative=True, # Show cumulative counts + annot=True, + annot_offset="-10p", # Offset the annotations by 10 points in negative y-direction ) fig.show()