Source code for alphatwirl.binning.Round
# Tai Sakuma <tai.sakuma@cern.ch>
import math
import collections
import logging
from .ReturnTrue import ReturnTrue
##__________________________________________________________________||
[docs]class Round(object):
def __init__(self, width = 1, aboundary = None,
min = None, underflow_bin = None,
max = None, overflow_bin = None,
valid = ReturnTrue()):
self.width = width
self.aboundary = aboundary
self.halfWidth = self.width/2 if self.width % 2 == 0 else float(self.width)/2
if aboundary is None: aboundary = self.halfWidth
self.boundaries = collections.deque([aboundary - width, aboundary, aboundary + width])
self.min = min
self.underflow_bin = underflow_bin
self.max = max
self.overflow_bin = overflow_bin
self.valid = valid
def __repr__(self):
return '{}(width = {!r}, aboundary = {!r}, min = {!r}, underflow_bin = {!r}, max = {!r}, overflow_bin = {!r}, valid = {!r})'.format(
self.__class__.__name__,
self.width,
self.aboundary,
self.min,
self.underflow_bin,
self.max,
self.overflow_bin,
self.valid
)
def __call__(self, val):
return self._lower_boundary(val)
def _lower_boundary(self, val):
if not self.valid(val):
return None
if self.min is not None:
if not self.min <= val:
return self.underflow_bin
if self.max is not None:
if not val < self.max:
return self.overflow_bin
if math.isinf(val):
logger = logging.getLogger(__name__)
logger.warning('val = {}. will return {}'.format(val, None))
return None
self._update_boundaries(val)
bin = self.boundaries[0]
for b in self.boundaries:
if b <= val:
bin = b
else:
break
return bin
def _update_boundaries(self, val):
while val < self.boundaries[0]:
self.boundaries.appendleft(self.boundaries[0] - self.width)
while val > self.boundaries[-1]:
self.boundaries.append(self.boundaries[-1] + self.width)
[docs] def next(self, bin):
return self._next_lower_boundary(bin)
def _next_lower_boundary(self, bin):
bin = self._lower_boundary(bin)
if bin is None:
return None
if bin == self.underflow_bin:
return self._lower_boundary(self.min)
if bin == self.overflow_bin:
return self.overflow_bin
self._update_boundaries(bin)
return self._lower_boundary(bin + self.width*1.001)
##__________________________________________________________________||