bin and hist accept a bin-edge outer coord when the combine_bins fast path applies, whereas the C++ implementation rejects such input with
BinEdgeError: Requested binning in dimension 'strain' but input contains a bin-edge coordinate with no corresponding event-coordinate. Provide an event coordinate or convert the bin-edge coordinate to a non-edge coordinate.
The fast path was introduced in 2022 and routes around that check, so which semantics apply depends on whether _can_operate_on_bins happens to return True. What the fast path does instead depends on how many dims are flattened:
- one flattened dim:
_combine_bins builds DataArray(var_bins.size(), coords=coords), where the coord has one value too many. The subsequent flatten is a mere rename, so the coord survives and its first N values are used, one per input bin — i.e. the bin's left edge. No error, silently different from the reference implementation.
- more than one flattened dim:
flatten drops the bin-edge coord and binning fails later with a confusing KeyError: "Expected 'y' in <scipp.Dict.keys {}>."
Reproducer for both:
import scipp as sc
# One flattened dim: silently succeeds
da = sc.data.table_xyz(100).bin(x=5)
da.coords['s'] = sc.linspace('x', 0.0, 1.0, 6, unit='m') # bin-edge over 'x'
da.bin(s=sc.linspace('s', 0.0, 1.0, 3, unit='m'))
# Two flattened dims: KeyError
da = sc.data.table_xyz(100).bin(x=2, y=3)
del da.bins.coords['y']
da.bin(y=2, dim=da.dims)
Both should raise BinEdgeError. Tests are marked xfail in tests/binning_test.py.
Fixing this is a user-visible break: docs/user-guide/binned-data/filtering.ipynb relies on the silent left-edge behavior and needs to pass a non-edge coord instead.
binandhistaccept a bin-edge outer coord when thecombine_binsfast path applies, whereas the C++ implementation rejects such input withThe fast path was introduced in 2022 and routes around that check, so which semantics apply depends on whether
_can_operate_on_binshappens to returnTrue. What the fast path does instead depends on how many dims are flattened:_combine_binsbuildsDataArray(var_bins.size(), coords=coords), where the coord has one value too many. The subsequentflattenis a mere rename, so the coord survives and its first N values are used, one per input bin — i.e. the bin's left edge. No error, silently different from the reference implementation.flattendrops the bin-edge coord and binning fails later with a confusingKeyError: "Expected 'y' in <scipp.Dict.keys {}>."Reproducer for both:
Both should raise
BinEdgeError. Tests are markedxfailintests/binning_test.py.Fixing this is a user-visible break:
docs/user-guide/binned-data/filtering.ipynbrelies on the silent left-edge behavior and needs to pass a non-edge coord instead.