0
# Indexing and Operations
1
2
Advanced indexing capabilities for accessing and modifying histogram data with locators, rebinning, and flow bin management. These tools provide flexible ways to slice, dice, and manipulate histogram data.
3
4
## Capabilities
5
6
### Locator Classes
7
8
Flexible indexing objects for accessing specific bins or regions.
9
10
```python { .api }
11
class Locator:
12
"""Base class for histogram locators."""
13
14
def __init__(self, offset: int = 0):
15
"""
16
Parameters:
17
- offset: Additional offset to apply
18
"""
19
20
def __add__(self, offset: int):
21
"""Add offset to locator."""
22
23
def __sub__(self, offset: int):
24
"""Subtract offset from locator."""
25
26
class loc(Locator):
27
"""Locate bin by value."""
28
29
def __init__(self, value, offset: int = 0):
30
"""
31
Parameters:
32
- value: Value to locate
33
- offset: Additional bin offset
34
"""
35
36
def __call__(self, axis) -> int:
37
"""Get bin index for this value on the given axis."""
38
39
class at:
40
"""Locate bin by direct index."""
41
42
def __init__(self, value: int):
43
"""
44
Parameters:
45
- value: Direct bin index
46
"""
47
48
def __call__(self, axis) -> int:
49
"""Return the direct index."""
50
```
51
52
### Flow Bin Locators
53
54
Special locators for underflow and overflow bins.
55
56
```python { .api }
57
class Underflow(Locator):
58
"""Locate underflow bin."""
59
60
def __call__(self, axis) -> int:
61
"""Return underflow bin index (-1)."""
62
63
class Overflow(Locator):
64
"""Locate overflow bin."""
65
66
def __call__(self, axis) -> int:
67
"""Return overflow bin index (len(axis))."""
68
69
# Pre-created instances
70
underflow: Underflow
71
overflow: Overflow
72
```
73
74
### Rebinning Operations
75
76
Combine adjacent bins to reduce histogram resolution.
77
78
```python { .api }
79
class rebin:
80
"""Rebinning operation for histogram slicing."""
81
82
def __init__(
83
self,
84
factor_or_axis=None,
85
/,
86
*,
87
factor: int = None,
88
groups = None,
89
edges = None,
90
axis = None
91
):
92
"""
93
Create rebinning operation.
94
95
Parameters:
96
- factor_or_axis: Rebinning factor (int) or new axis definition
97
- factor: Rebinning factor (combine this many bins into one)
98
- groups: List of integers specifying custom groupings
99
- edges: New edge positions for rebinning
100
- axis: New axis definition to rebin to
101
"""
102
103
def group_mapping(self, axis):
104
"""Get the grouping mapping for the given axis."""
105
106
def axis_mapping(self, axis):
107
"""Get the axis mapping for rebinning."""
108
```
109
110
### Histogram Indexing
111
112
Access and modify histogram data using various indexing patterns.
113
114
```python { .api }
115
# Histogram indexing supports:
116
# - Integer indices: hist[5]
117
# - Slice objects: hist[10:20]
118
# - Locators: hist[bh.loc(2.5)]
119
# - Complex expressions: hist[{0: bh.rebin(2), 1: slice(10, 20)}]
120
121
def __getitem__(self, index):
122
"""
123
Get histogram data or sub-histogram.
124
125
Parameters:
126
- index: Index expression (int, slice, locator, dict, etc.)
127
128
Returns:
129
Histogram, accumulator, or scalar depending on indexing
130
"""
131
132
def __setitem__(self, index, value):
133
"""
134
Set histogram data.
135
136
Parameters:
137
- index: Index expression
138
- value: Value(s) to set
139
"""
140
```
141
142
### Slicing Utilities
143
144
Helper functions for advanced slicing operations.
145
146
```python { .api }
147
def Slicer():
148
"""
149
Returns np.s_ for backward compatibility.
150
Prefer using np.s_ directly.
151
"""
152
return np.s_
153
```
154
155
### Complex Indexing Examples
156
157
Advanced indexing patterns for multi-dimensional histograms.
158
159
```python { .api }
160
# Dictionary-based indexing for multi-dimensional histograms
161
# {axis_index: operation} format
162
# Examples:
163
# hist[{0: slice(10, 20)}] # Slice first axis
164
# hist[{0: bh.rebin(2), 1: bh.loc(5.0)}] # Rebin axis 0, locate on axis 1
165
# hist[{1: bh.overflow}] # Include overflow on axis 1
166
```
167
168
## Usage Examples
169
170
### Basic Indexing
171
172
```python
173
import boost_histogram as bh
174
import numpy as np
175
176
# Create and fill histogram
177
hist = bh.Histogram(bh.axis.Regular(100, 0, 10))
178
data = np.random.normal(5, 2, 1000)
179
hist.fill(data)
180
181
# Direct bin access
182
bin_5 = hist[5] # Get contents of bin 5
183
print(f"Bin 5 content: {bin_5}")
184
185
# Slice access
186
subhist = hist[10:20] # Get bins 10-19 as new histogram
187
values_slice = hist.values()[10:20] # Get values directly
188
189
# Flow bin access
190
hist_with_flow = bh.Histogram(bh.axis.Regular(50, 0, 10))
191
hist_with_flow.fill([-1, 0, 5, 15]) # Some values in flow bins
192
193
underflow_count = hist_with_flow[bh.underflow]
194
overflow_count = hist_with_flow[bh.overflow]
195
```
196
197
### Value-Based Locators
198
199
```python
200
# Create histogram with regular axis
201
hist = bh.Histogram(bh.axis.Regular(100, 0, 10))
202
hist.fill(np.random.uniform(0, 10, 1000))
203
204
# Locate by value
205
bin_at_25 = hist[bh.loc(2.5)] # Find bin containing value 2.5
206
bin_near_75 = hist[bh.loc(7.5) + 1] # Bin after the one containing 7.5
207
208
# Slice by values with offset
209
subset = hist[bh.loc(2.0):bh.loc(8.0)] # Histogram from value 2.0 to 8.0
210
```
211
212
### Rebinning Operations
213
214
```python
215
# Create fine-grained histogram
216
hist = bh.Histogram(bh.axis.Regular(100, 0, 10))
217
hist.fill(np.random.exponential(2, 5000))
218
219
# Rebin by factor of 5 (combine every 5 bins)
220
rebinned = hist[bh.rebin(5)]
221
print(f"Original bins: {hist.size}, Rebinned: {rebinned.size}")
222
223
# Custom rebinning with groups
224
# Combine first 10 bins into 1, next 20 into 2, rest into individual bins
225
groups = [10, 10, 10] + [1] * 70 # Total must equal original bin count
226
custom_rebin = hist[bh.rebin(groups=groups)]
227
228
# Rebin to specific edges
229
new_edges = [0, 1, 2, 5, 10] # 4 bins with irregular spacing
230
edge_rebin = hist[bh.rebin(edges=new_edges)]
231
```
232
233
### Multi-Dimensional Indexing
234
235
```python
236
# Create 2D histogram
237
hist2d = bh.Histogram(
238
bh.axis.Regular(50, 0, 5),
239
bh.axis.Regular(50, 0, 5)
240
)
241
242
# Fill with correlated data
243
x = np.random.uniform(0, 5, 2000)
244
y = x + np.random.normal(0, 0.5, 2000)
245
hist2d.fill(x, y)
246
247
# Dictionary-based indexing
248
# Project onto y-axis by summing over all x
249
y_projection = hist2d[{0: sum}]
250
251
# Rebin first axis and slice second axis
252
modified = hist2d[{0: bh.rebin(2), 1: slice(10, 40)}]
253
254
# Select specific ranges on each axis
255
corner = hist2d[{0: slice(0, 10), 1: slice(40, 50)}]
256
257
# Combine locators and rebinning
258
complex_slice = hist2d[{
259
0: bh.loc(2.5):bh.loc(3.5), # Values between 2.5 and 3.5 on x
260
1: bh.rebin(5) # Rebin y-axis by factor 5
261
}]
262
```
263
264
### Flow Bin Management
265
266
```python
267
# Create histogram with flow bins enabled
268
hist = bh.Histogram(bh.axis.Regular(20, 0, 10, underflow=True, overflow=True))
269
270
# Fill with data including out-of-range values
271
data = np.random.normal(5, 3, 1000) # Some values outside [0, 10]
272
hist.fill(data)
273
274
# Access flow bins
275
underflow_content = hist[bh.underflow]
276
overflow_content = hist[bh.overflow]
277
278
# Include flow bins in operations
279
total_with_flow = hist.sum(flow=True)
280
values_with_flow = hist.values(flow=True)
281
282
# Create view including flow bins
283
full_projection = hist[{0: slice(None)}].values(flow=True)
284
285
print(f"Underflow: {underflow_content}")
286
print(f"Overflow: {overflow_content}")
287
print(f"Total (no flow): {hist.sum()}")
288
print(f"Total (with flow): {total_with_flow}")
289
```
290
291
### Advanced Slicing Patterns
292
293
```python
294
# 3D histogram for complex slicing
295
hist3d = bh.Histogram(
296
bh.axis.Regular(20, 0, 10), # x
297
bh.axis.Regular(20, 0, 10), # y
298
bh.axis.Regular(20, 0, 10) # z
299
)
300
301
# Fill with 3D data
302
x = np.random.uniform(0, 10, 5000)
303
y = np.random.uniform(0, 10, 5000)
304
z = np.random.uniform(0, 10, 5000)
305
hist3d.fill(x, y, z)
306
307
# Complex multi-axis operations
308
result = hist3d[{
309
0: bh.rebin(2), # Rebin x-axis
310
1: bh.loc(5.0):bh.loc(7.0), # Slice y between 5 and 7
311
2: bh.overflow # Include only overflow in z
312
}]
313
314
# Sequential slicing
315
temp = hist3d[{0: slice(5, 15)}] # First operation
316
final = temp[{1: bh.rebin(2)}] # Second operation
317
318
# Integration patterns
319
xy_projection = hist3d[{2: sum}] # Integrate over z
320
x_profile = hist3d[{1: sum, 2: sum}] # Integrate over y and z
321
```
322
323
### Setting Histogram Values
324
325
```python
326
# Create empty histogram
327
hist = bh.Histogram(bh.axis.Regular(10, 0, 10))
328
329
# Set individual bins
330
hist[0] = 5.0
331
hist[bh.loc(2.5)] = 10.0
332
333
# Set ranges
334
hist[3:7] = [1, 2, 3, 4] # Set bins 3-6
335
hist[bh.loc(7.0):bh.loc(9.0)] = 15.0 # Set range by value
336
337
# Set with numpy arrays
338
import numpy as np
339
hist[:] = np.arange(10) # Set all bins to 0, 1, 2, ..., 9
340
341
# Multi-dimensional setting
342
hist2d = bh.Histogram(bh.axis.Regular(5, 0, 5), bh.axis.Regular(5, 0, 5))
343
hist2d[{0: 2, 1: 3}] = 42.0 # Set specific 2D bin
344
345
# Set slices in 2D
346
hist2d[{0: slice(1, 4), 1: 2}] = [10, 20, 30] # Set row of bins
347
```