plothist 1.4.0__py3-none-any.whl → 1.5.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.
Files changed (64) hide show
  1. plothist/_version.py +2 -2
  2. plothist/comparison.py +111 -105
  3. plothist/examples/1d_hist/1d_comparison_asymmetry.py +37 -0
  4. plothist/examples/1d_hist/1d_comparison_difference.py +40 -0
  5. plothist/examples/1d_hist/1d_comparison_efficiency.py +37 -0
  6. plothist/examples/1d_hist/1d_comparison_only_efficiency.py +33 -0
  7. plothist/examples/1d_hist/1d_comparison_pull.py +37 -0
  8. plothist/examples/1d_hist/1d_comparison_ratio.py +37 -0
  9. plothist/examples/1d_hist/1d_comparison_relative_difference.py +37 -0
  10. plothist/examples/1d_hist/1d_comparison_split_ratio.py +37 -0
  11. plothist/examples/1d_hist/1d_elt1.py +38 -0
  12. plothist/examples/1d_hist/1d_elt1_stacked.py +45 -0
  13. plothist/examples/1d_hist/1d_elt2.py +33 -0
  14. plothist/examples/1d_hist/1d_hist_simple.py +28 -0
  15. plothist/examples/1d_hist/1d_int_category.py +41 -0
  16. plothist/examples/1d_hist/1d_profile.py +33 -0
  17. plothist/examples/1d_hist/1d_side_by_side.py +58 -0
  18. plothist/examples/1d_hist/1d_str_category.py +41 -0
  19. plothist/examples/1d_hist/README.rst +4 -0
  20. plothist/examples/2d_hist/2d_hist_correlations.py +65 -0
  21. plothist/examples/2d_hist/2d_hist_simple.py +28 -0
  22. plothist/examples/2d_hist/2d_hist_simple_discrete_colormap.py +42 -0
  23. plothist/examples/2d_hist/2d_hist_uneven.py +28 -0
  24. plothist/examples/2d_hist/2d_hist_with_projections.py +36 -0
  25. plothist/examples/2d_hist/README.rst +4 -0
  26. plothist/examples/README.rst +7 -0
  27. plothist/examples/advanced/1d_comparison_advanced.py +87 -0
  28. plothist/examples/advanced/1d_side_by_side_with_numbers.py +81 -0
  29. plothist/examples/advanced/README.rst +4 -0
  30. plothist/examples/advanced/asymmetry_comparison_advanced.py +133 -0
  31. plothist/examples/advanced/model_examples_flatten2D.py +86 -0
  32. plothist/examples/func_1d/README.rst +4 -0
  33. plothist/examples/func_1d/fct_1d.py +27 -0
  34. plothist/examples/func_1d/fct_1d_stacked.py +42 -0
  35. plothist/examples/model_ex/README.rst +4 -0
  36. plothist/examples/model_ex/model_all_comparisons.py +103 -0
  37. plothist/examples/model_ex/model_all_comparisons_no_model_unc.py +115 -0
  38. plothist/examples/model_ex/model_examples_pull.py +56 -0
  39. plothist/examples/model_ex/model_examples_pull_no_model_unc.py +59 -0
  40. plothist/examples/model_ex/model_examples_stacked.py +74 -0
  41. plothist/examples/model_ex/model_examples_stacked_unstacked.py +60 -0
  42. plothist/examples/model_ex/model_examples_unstacked.py +57 -0
  43. plothist/examples/model_ex/model_with_stacked_and_unstacked_function_components.py +50 -0
  44. plothist/examples/model_ex/model_with_stacked_and_unstacked_histograms_components.py +69 -0
  45. plothist/examples/model_ex/ratio_data_vs_model_with_stacked_and_unstacked_function_components.py +61 -0
  46. plothist/examples/utility/README.rst +4 -0
  47. plothist/examples/utility/add_text_example.py +39 -0
  48. plothist/examples/utility/color_palette_hists.py +94 -0
  49. plothist/examples/utility/color_palette_squares.py +100 -0
  50. plothist/examples/utility/matplotlib_vs_plothist_style.py +63 -0
  51. plothist/histogramming.py +60 -39
  52. plothist/plothist_style.py +54 -57
  53. plothist/plotters.py +207 -194
  54. plothist/test_helpers.py +43 -0
  55. plothist/variable_registry.py +46 -30
  56. {plothist-1.4.0.dist-info → plothist-1.5.0.dist-info}/METADATA +1 -1
  57. plothist-1.5.0.dist-info/RECORD +63 -0
  58. plothist/scripts/__init__.py +0 -3
  59. plothist/scripts/make_examples.py +0 -209
  60. plothist-1.4.0.dist-info/RECORD +0 -17
  61. plothist-1.4.0.dist-info/entry_points.txt +0 -2
  62. {plothist-1.4.0.dist-info → plothist-1.5.0.dist-info}/WHEEL +0 -0
  63. {plothist-1.4.0.dist-info → plothist-1.5.0.dist-info}/licenses/AUTHORS.md +0 -0
  64. {plothist-1.4.0.dist-info → plothist-1.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,63 @@
1
+ """
2
+ Default style: matplotlib vs plothist
3
+ =====================================
4
+
5
+ Illustration of the difference between matplotlib and plothist default styles.
6
+ """
7
+
8
+ import matplotlib.pyplot as plt
9
+ import numpy as np
10
+ from plothist_utils import get_dummy_data
11
+
12
+ df = get_dummy_data()
13
+
14
+ figs = []
15
+
16
+ for style in ["matplotlib", "plothist"]:
17
+ if style == "matplotlib":
18
+ plt.style.use("default")
19
+ plt.rcParams["font.family"] = "DejaVu Sans"
20
+ else:
21
+ # No need to set the style if we use plothist, just importing it is enough
22
+ # Here we set the style because the matplotlib style was set before
23
+ from plothist import set_style
24
+
25
+ set_style("default")
26
+
27
+ # Create a figure with subplots
28
+ fig, (ax1, ax2) = plt.subplots(
29
+ 2, 1, figsize=(6, 5.4), sharex=True, gridspec_kw={"height_ratios": [4, 1]}
30
+ )
31
+
32
+ # Plot histograms in the first subplot (ax1)
33
+ hist_0, bins, _ = ax1.hist(
34
+ df["variable_0"], bins=20, histtype="step", linewidth=1.2, label="h1"
35
+ )
36
+ h1 = ax1.hist(
37
+ df["variable_1"], bins=bins, histtype="step", linewidth=1.2, label="h2"
38
+ )
39
+ ax1.set_ylabel("Entries")
40
+ ax1.legend()
41
+
42
+ # Calculate the ratio of histogram values and plot in the second subplot (ax2)
43
+ with np.errstate(divide="ignore", invalid="ignore"):
44
+ ratio = hist_0 / h1[0] # Divide bin values of variable_0 by variable_1
45
+ bin_centers = 0.5 * (bins[:-1] + bins[1:]) # Calculate bin centers
46
+
47
+ # Create fake error bars for the ratio
48
+ ax2.plot(bin_centers, ratio, marker="|", linestyle="", markersize=15, color="black")
49
+ ax2.plot(bin_centers, ratio, marker="o", linestyle="", markersize=4, color="black")
50
+
51
+ ax2.axhline(y=1, color="black", linestyle="--", linewidth=0.8)
52
+ ax2.set_xlabel("Variable")
53
+ ax2.set_ylabel("Ratio")
54
+
55
+ ax1.set_xlim(-10, 10)
56
+ ax2.set_xlim(-10, 10)
57
+ ax2.set_ylim(0, 2)
58
+
59
+ fig.subplots_adjust(hspace=0.15)
60
+
61
+ fig.savefig(f"{style}_example.svg", bbox_inches="tight")
62
+
63
+ figs.append(fig)
plothist/histogramming.py CHANGED
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import warnings
4
+ from collections.abc import Sequence
5
+ from typing import Callable
4
6
 
5
7
  import boost_histogram as bh
6
8
  import numpy as np
@@ -15,17 +17,23 @@ class RangeWarning(Warning):
15
17
  warnings.filterwarnings("always", category=RangeWarning)
16
18
 
17
19
 
18
- def create_axis(bins, range=None, data=None, overflow=False, underflow=False):
20
+ def create_axis(
21
+ bins: int | list[float] | np.ndarray,
22
+ range: tuple[float | str, float | str] | None = None,
23
+ data: list[float] | np.ndarray | None = None,
24
+ overflow: bool = False,
25
+ underflow: bool = False,
26
+ ) -> bh.axis.Regular | bh.axis.Variable:
19
27
  """
20
28
  Create an axis object for histogram binning based on the input data and parameters.
21
29
 
22
30
  Parameters
23
31
  ----------
24
- bins : int or array-like
32
+ bins : int or list[float]
25
33
  The number of bins or bin edges for the axis.
26
- range : None or tuple, optional
27
- The range of the axis. If None, it will be determined based on the data.
28
- data : array-like, optional
34
+ range : None or tuple[float | str, float | str], optional
35
+ The range of the axis. If None, it will be determined based on the data. Default is None.
36
+ data : list[float] or np.ndarray, optional
29
37
  The input data for determining the axis range. Default is None.
30
38
  overflow : bool, optional
31
39
  Whether to include an overflow bin. If False, the upper edge of the last bin is inclusive. Default is False.
@@ -52,19 +60,16 @@ def create_axis(bins, range=None, data=None, overflow=False, underflow=False):
52
60
  if data is None:
53
61
  data = np.array([])
54
62
 
55
- try:
56
- N = len(bins)
57
- except TypeError:
58
- N = 1
63
+ is_variable_bins = isinstance(bins, (list, np.ndarray))
59
64
 
60
- if N > 1:
65
+ if is_variable_bins:
61
66
  if range is not None:
62
67
  warnings.warn(
63
68
  f"Custom binning -> ignore supplied range ({range}).", stacklevel=2
64
69
  )
65
70
  return bh.axis.Variable(bins, underflow=underflow, overflow=overflow)
66
71
 
67
- if bins <= 0:
72
+ if isinstance(bins, int) and bins <= 0:
68
73
  raise ValueError(f"Number of bins must be positive, but got {bins}.")
69
74
 
70
75
  # Inspired from np.histograms
@@ -74,8 +79,8 @@ def create_axis(bins, range=None, data=None, overflow=False, underflow=False):
74
79
  "Cannot use 'min'/'max' range values with empty data. "
75
80
  "Please supply a range or provide data."
76
81
  )
77
- x_min = min(data) if range[0] == "min" else range[0]
78
- x_max = max(data) if range[1] == "max" else range[1]
82
+ x_min = min(data) if range[0] == "min" else float(range[0])
83
+ x_max = max(data) if range[1] == "max" else float(range[1])
79
84
  if x_min > x_max:
80
85
  raise ValueError(
81
86
  f"Range of [{x_min}, {x_max}] is not valid. Max must be larger than min."
@@ -84,10 +89,10 @@ def create_axis(bins, range=None, data=None, overflow=False, underflow=False):
84
89
  raise ValueError(f"Range of [{x_min}, {x_max}] is not finite.")
85
90
  elif len(data) == 0:
86
91
  # handle empty arrays. Can't determine range, so use 0-1.
87
- x_min, x_max = 0, 1
92
+ x_min, x_max = 0.0, 1.0
88
93
  else:
89
- x_min = min(data)
90
- x_max = max(data)
94
+ x_min = float(min(data))
95
+ x_max = float(max(data))
91
96
  if not (np.isfinite(x_min) and np.isfinite(x_max)):
92
97
  raise ValueError(f"Autodetected range of [{x_min}, {x_max}] is not finite.")
93
98
 
@@ -99,30 +104,35 @@ def create_axis(bins, range=None, data=None, overflow=False, underflow=False):
99
104
  return bh.axis.Regular(bins, x_min, x_max, underflow=underflow, overflow=overflow)
100
105
 
101
106
 
102
- def make_hist(data=None, bins=50, range=None, weights=1):
107
+ def make_hist(
108
+ data: list[float] | np.ndarray | None = None,
109
+ bins: int | list[float] | np.ndarray = 50,
110
+ range: tuple[float | str, float | str] | None = None,
111
+ weights: float | list[float] | np.ndarray = 1,
112
+ ) -> bh.Histogram:
103
113
  """
104
114
  Create a histogram object and fill it with the provided data.
105
115
 
106
116
  Parameters
107
117
  ----------
108
- data : array-like, optional
118
+ data : list[float] or np.ndarray, optional
109
119
  1D array-like data used to fill the histogram (default is None).
110
120
  If None is provided, an empty histogram is returned.
111
- bins : int or tuple, optional
121
+ bins : int or list[float], optional
112
122
  Binning specification for the histogram (default is 50).
113
123
  If an integer, it represents the number of bins.
114
- If a tuple, it should be the explicit list of all bin edges.
115
- range : tuple, optional
124
+ If a list, it should be the explicit list of all bin edges.
125
+ range : tuple[float | str, float | str], optional
116
126
  The range of values to consider for the histogram bins (default is None).
117
127
  If None, the range is determined from the data.
118
- weights : float or array-like, optional
128
+ weights : float or list[float] or np.ndarray, optional
119
129
  Weight(s) to apply to the data points (default is 1).
120
130
  If a float, a single weight is applied to all data points.
121
131
  If an array-like, weights are applied element-wise.
122
132
 
123
133
  Returns
124
134
  -------
125
- histogram : boost_histogram.Histogram
135
+ histogram : bh.Histogram
126
136
  The filled histogram object.
127
137
 
128
138
  Warns
@@ -160,31 +170,38 @@ def make_hist(data=None, bins=50, range=None, weights=1):
160
170
  return h
161
171
 
162
172
 
163
- def make_2d_hist(data=None, bins=(10, 10), range=(None, None), weights=1):
173
+ def make_2d_hist(
174
+ data: list[np.ndarray] | np.ndarray | None = None,
175
+ bins: Sequence[int | Sequence[float]] | None = None,
176
+ range: tuple[
177
+ tuple[float | str, float | str] | None, tuple[float | str, float | str] | None
178
+ ] = (None, None),
179
+ weights: float | list[float] | np.ndarray = 1,
180
+ ) -> bh.Histogram:
164
181
  """
165
182
  Create a 2D histogram object and fill it with the provided data.
166
183
 
167
184
  Parameters
168
185
  ----------
169
- data : array-like, optional
186
+ data : list[np.ndarray] or np.ndarray, optional
170
187
  2D array-like data used to fill the histogram (default is None).
171
188
  If None is provided, an empty histogram is returned.
172
- bins : tuple, optional
173
- Binning specification for each dimension of the histogram (default is (10, 10)).
189
+ bins : Sequence[int | Sequence[float]], optional
190
+ Binning specification for each dimension of the histogram (if None, it will be set to [50, 50]).
174
191
  Each element of the tuple represents the number of bins for the corresponding dimension.
175
192
  Also support explicit bin edges specification (for non-constant bin size).
176
- range : tuple, optional
193
+ range : tuple[tuple[float | str, float | str] | None, tuple[float | str, float | str] | None], optional
177
194
  The range of values to consider for each dimension of the histogram (default is (None, None)).
178
195
  If None, the range is determined from the data for that dimension.
179
196
  The tuple should have the same length as the data.
180
- weights : float or array-like, optional
197
+ weights : float or list[float] or np.ndarray, optional
181
198
  Weight(s) to apply to the data points (default is 1).
182
199
  If a float, a single weight is applied to all data points.
183
200
  If an array-like, weights are applied element-wise.
184
201
 
185
202
  Returns
186
203
  -------
187
- histogram : boost_histogram.Histogram
204
+ histogram : bh.Histogram
188
205
  The filled 2D histogram object.
189
206
 
190
207
  Raises
@@ -203,6 +220,8 @@ def make_2d_hist(data=None, bins=(10, 10), range=(None, None), weights=1):
203
220
  raise ValueError("data should have two components, x and y")
204
221
  if len(data[0]) != len(data[1]):
205
222
  raise ValueError("x and y must have the same length.")
223
+ if bins is None:
224
+ bins = [50, 50]
206
225
 
207
226
  x_axis = create_axis(bins[0], range[0], data[0])
208
227
  y_axis = create_axis(bins[1], range[1], data[1])
@@ -236,13 +255,13 @@ def make_2d_hist(data=None, bins=(10, 10), range=(None, None), weights=1):
236
255
  return h
237
256
 
238
257
 
239
- def _check_counting_histogram(hist):
258
+ def _check_counting_histogram(hist: bh.Histogram) -> None:
240
259
  """
241
260
  Check that the histogram is a counting histogram.
242
261
 
243
262
  Parameters
244
263
  ----------
245
- hist : boost_histogram.Histogram
264
+ hist : bh.Histogram
246
265
  The histogram to check.
247
266
 
248
267
  Raise
@@ -257,7 +276,9 @@ def _check_counting_histogram(hist):
257
276
  )
258
277
 
259
278
 
260
- def _make_hist_from_function(func, ref_hist):
279
+ def _make_hist_from_function(
280
+ func: Callable[[np.ndarray], np.ndarray], ref_hist: bh.Histogram
281
+ ) -> bh.Histogram:
261
282
  """
262
283
  Create a histogram from a function and a reference histogram.
263
284
  The returned histogram has the same binning as the reference histogram and
@@ -265,14 +286,14 @@ def _make_hist_from_function(func, ref_hist):
265
286
 
266
287
  Parameters
267
288
  ----------
268
- func : function
289
+ func : Callable[[np.ndarray], np.ndarray]
269
290
  1D function. The function should support vectorization (i.e. accept a numpy array as input).
270
- ref_hist : boost_histogram.Histogram
291
+ ref_hist : bh.Histogram
271
292
  The reference 1D histogram to use for the binning.
272
293
 
273
294
  Returns
274
295
  -------
275
- hist : boost_histogram.Histogram
296
+ hist : bh.Histogram
276
297
  The histogram filled with the function.
277
298
 
278
299
  Raises
@@ -290,18 +311,18 @@ def _make_hist_from_function(func, ref_hist):
290
311
  return hist
291
312
 
292
313
 
293
- def flatten_2d_hist(hist):
314
+ def flatten_2d_hist(hist: bh.Histogram) -> bh.Histogram:
294
315
  """
295
316
  Flatten a 2D histogram into a 1D histogram.
296
317
 
297
318
  Parameters
298
319
  ----------
299
- hist : Histogram object
320
+ hist : bh.Histogram
300
321
  The 2D histogram to be flattened.
301
322
 
302
323
  Returns
303
324
  -------
304
- Histogram object
325
+ bh.Histogram
305
326
  The flattened 1D histogram.
306
327
 
307
328
  Raises
@@ -1,13 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
- from importlib.resources import files
4
-
5
3
  import matplotlib as mpl
6
4
  import matplotlib.pyplot as plt
7
5
  import numpy as np
8
6
 
9
7
 
10
- def set_style(style="default"):
8
+ def set_style(style: str = "default") -> None:
11
9
  """
12
10
  Set the plothist style.
13
11
 
@@ -32,22 +30,21 @@ def set_style(style="default"):
32
30
  available_styles = ["default"]
33
31
 
34
32
  if style in available_styles:
35
- style_file = files("plothist").joinpath(f"{style}_style.mplstyle")
36
- plt.style.use(style_file)
33
+ plt.style.use(f"plothist.{style}_style")
37
34
  else:
38
35
  raise ValueError(f"{style} not in the available styles: {available_styles}")
39
36
 
40
37
 
41
38
  def cubehelix_palette(
42
- ncolors=7,
43
- start=1.5,
44
- rotation=1.5,
45
- gamma=1.0,
46
- hue=0.8,
47
- lightest=0.8,
48
- darkest=0.3,
49
- reverse=True,
50
- ):
39
+ ncolors: int = 7,
40
+ start: float = 1.5,
41
+ rotation: float = 1.5,
42
+ gamma: float = 1.0,
43
+ hue: float = 0.8,
44
+ lightest: float = 0.8,
45
+ darkest: float = 0.3,
46
+ reverse: bool = True,
47
+ ) -> list[tuple[float, float, float]]:
51
48
  """
52
49
  Make a sequential palette from the cubehelix system, in which the perceived brightness is linearly increasing.
53
50
  This code is adapted from seaborn, which implements equation (2) of reference [1] below.
@@ -75,10 +72,9 @@ def cubehelix_palette(
75
72
 
76
73
  Returns
77
74
  -------
78
- list of RGB tuples
75
+ list[tuple[float, float, float]]
79
76
  The generated palette of colors represented as a list of RGB tuples.
80
77
 
81
-
82
78
  References
83
79
  ----------
84
80
  [1] Green, D. A. (2011). "A colour scheme for the display of astronomical
@@ -119,7 +115,9 @@ def cubehelix_palette(
119
115
  return pal
120
116
 
121
117
 
122
- def get_color_palette(cmap, N):
118
+ def get_color_palette(
119
+ cmap: str, N: int
120
+ ) -> list[str] | list[tuple[float, float, float]]:
123
121
  """
124
122
  Get N different colors from a chosen colormap.
125
123
 
@@ -132,8 +130,9 @@ def get_color_palette(cmap, N):
132
130
 
133
131
  Returns
134
132
  -------
135
- list
136
- A list of RGB color tuples sampled from the colormap.
133
+ list[str] or list[tuple[float, float, float]]
134
+ A list of colors. If "ggplot" is selected, returns a list of hex color strings.
135
+ Otherwise, returns a list of RGB color tuples.
137
136
 
138
137
  References
139
138
  ----------
@@ -174,7 +173,7 @@ def get_color_palette(cmap, N):
174
173
  return plt_cmap(np.linspace(0, 1, N))
175
174
 
176
175
 
177
- def set_fitting_ylabel_fontsize(ax):
176
+ def set_fitting_ylabel_fontsize(ax: plt.Axes) -> float:
178
177
  """
179
178
  Get the suitable font size for a ylabel text that fits within the plot's y-axis limits.
180
179
 
@@ -190,9 +189,8 @@ def set_fitting_ylabel_fontsize(ax):
190
189
  """
191
190
  ylabel_fontsize = ax.yaxis.get_label().get_fontsize()
192
191
 
193
- # Check if renderer is available
194
- if ax.figure.canvas.get_renderer() is None:
195
- ax.figure.canvas.draw()
192
+ # Force renderer to be initialized
193
+ ax.figure.canvas.draw()
196
194
 
197
195
  while (
198
196
  ax.yaxis.get_label()
@@ -214,14 +212,14 @@ def set_fitting_ylabel_fontsize(ax):
214
212
 
215
213
 
216
214
  def add_text(
217
- text,
218
- x="left",
219
- y="top",
220
- fontsize=12,
221
- white_background=False,
222
- ax=None,
215
+ text: str,
216
+ x: float | str = "left",
217
+ y: float | str = "top",
218
+ fontsize: int = 12,
219
+ white_background: bool = False,
220
+ ax: plt.Axes | None = None,
223
221
  **kwargs,
224
- ):
222
+ ) -> None:
225
223
  """
226
224
  Add text to an axis.
227
225
 
@@ -229,9 +227,9 @@ def add_text(
229
227
  ----------
230
228
  text : str
231
229
  The text to add.
232
- x : float, optional
230
+ x : float | str, optional
233
231
  Horizontal position of the text in unit of the normalized x-axis length. The default is value "left", which is an alias for 0.0. Other aliases are "right", "left_in", "right_in", "right_out".
234
- y : float, optional
232
+ y : float | str, optional
235
233
  Vertical position of the text in unit of the normalized y-axis length. The default is value "top", which is an alias for 1.01. Other aliases are "top_in", "bottom_in", "top_out"="top", "bottom_out"="bottom".
236
234
  fontsize : int, optional
237
235
  Font size, by default 12.
@@ -279,14 +277,14 @@ def add_text(
279
277
  }
280
278
 
281
279
  if isinstance(x, str):
282
- x = x_values.get(x)
283
- if x is None:
284
- raise ValueError(f"{x} not a float or a valid position")
280
+ if x not in x_values:
281
+ raise ValueError(f"{x!r} is not a valid x position.")
282
+ x = x_values[x]
285
283
 
286
284
  if isinstance(y, str):
287
- y = y_values.get(y)
288
- if y is None:
289
- raise ValueError(f"{y} not a float or a valid position")
285
+ if y not in y_values:
286
+ raise ValueError(f"{y!r} is not a valid y position.")
287
+ y = y_values[y]
290
288
 
291
289
  t = ax.text(
292
290
  x,
@@ -303,19 +301,19 @@ def add_text(
303
301
 
304
302
 
305
303
  def add_luminosity(
306
- collaboration,
307
- x="right",
308
- y="top",
309
- fontsize=12,
310
- is_data=True,
311
- lumi="",
312
- lumi_unit="fb",
313
- preliminary=False,
314
- two_lines=False,
315
- white_background=False,
316
- ax=None,
304
+ collaboration: str,
305
+ x: float | str = "right",
306
+ y: float | str = "top",
307
+ fontsize: int = 12,
308
+ is_data: bool = True,
309
+ lumi: int | str = "",
310
+ lumi_unit: str = "fb",
311
+ preliminary: bool = False,
312
+ two_lines: bool = False,
313
+ white_background: bool = False,
314
+ ax: plt.Axes | None = None,
317
315
  **kwargs,
318
- ):
316
+ ) -> None:
319
317
  """
320
318
  Add the collaboration name and the integrated luminosity (or "Simulation").
321
319
 
@@ -323,17 +321,17 @@ def add_luminosity(
323
321
  ----------
324
322
  collaboration : str
325
323
  Collaboration name.
326
- x : float, optional
324
+ x : float | str, optional
327
325
  Horizontal position of the text in unit of the normalized x-axis length. The default is value "right", which is an alias for 1.0. Can take other aliases such as "left", "left_in", "right_in", "right_out".
328
- y : float, optional
326
+ y : float | str, optional
329
327
  Vertical position of the text in unit of the normalized y-axis length. The default is value "top", which is an alias for 1.01. Can take other aliases such as "top_in", "bottom_in", "top_out"="top", "bottom_out"="bottom".
330
328
  fontsize : int, optional
331
329
  Font size, by default 12.
332
330
  is_data : bool, optional
333
331
  If True, plot integrated luminosity. If False, plot "Simulation", by default True.
334
- lumi : int/string, optional
332
+ lumi : int | str, optional
335
333
  Integrated luminosity. If empty, do not plot luminosity. Default value is empty.
336
- lumi_unit : string, optional
334
+ lumi_unit : str, optional
337
335
  Integrated luminosity unit. Default value is fb. The exponent is automatically -1.
338
336
  preliminary : bool, optional
339
337
  If True, print "preliminary", by default False.
@@ -383,7 +381,7 @@ def add_luminosity(
383
381
  )
384
382
 
385
383
 
386
- def plot_reordered_legend(ax, order, **kwargs):
384
+ def plot_reordered_legend(ax: plt.Axes, order: list[int], **kwargs) -> None:
387
385
  """
388
386
  Reorder the legend handlers and labels on the given Matplotlib axis based
389
387
  on the specified order and plot the reordered legend.
@@ -392,7 +390,7 @@ def plot_reordered_legend(ax, order, **kwargs):
392
390
  ----------
393
391
  ax : matplotlib.axes.Axes
394
392
  The Matplotlib Axes object on which the legend is to be reordered.
395
- order : list of int
393
+ order : list[int]
396
394
  A list of integers specifying the new order of the legend items.
397
395
  The integers refer to the indices of the current legend items.
398
396
  kwargs : dict, optional
@@ -418,7 +416,6 @@ def plot_reordered_legend(ax, order, **kwargs):
418
416
  To reorder the legend so that 'Line 2' comes first, use:
419
417
 
420
418
  >>> plot_reordered_legend(ax, [1, 0])
421
-
422
419
  """
423
420
 
424
421
  # Extract the original handlers and labels