Skip to content
This repository has been archived by the owner on May 2, 2022. It is now read-only.

Commit

Permalink
Merge branch 'v0.9.x-20170408-01-Round' into v0.9.x
Browse files Browse the repository at this point in the history
  • Loading branch information
TaiSakuma committed Apr 8, 2017
2 parents 7664832 + fedeaac commit 17661e3
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 108 deletions.
67 changes: 28 additions & 39 deletions alphatwirl/binning/Round.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,35 @@
# Tai Sakuma <tai.sakuma@cern.ch>

import math
import collections
import logging

##__________________________________________________________________||
def returnTrue(x): return True

##__________________________________________________________________||
class Round(object):
def __init__(self, width = 1, aBoundary = None,
def __init__(self, width = 1, aboundary = None,
min = None, underflow_bin = None,
max = None, overflow_bin = None,
valid = returnTrue, retvalue = 'lowedge'
):

supportedRetvalues = ('center', 'lowedge')
if retvalue not in supportedRetvalues:
raise ValueError("The retvalue '%s' is not supported! " % (retvalue, ) + "Supported values are '" + "', '".join(supportedRetvalues) + "'")
valid = returnTrue):

self.width = width
self.aBoundary = aBoundary
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 = [aBoundary - width, aBoundary, aBoundary + width]
self.lowedge = (retvalue == 'lowedge')
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(
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.aboundary,
self.min,
self.underflow_bin,
self.max,
Expand All @@ -43,6 +38,9 @@ def __repr__(self):
)

def __call__(self, val):
return self._lower_boundary(val)

def _lower_boundary(self, val):

if not self.valid(val):
return None
Expand All @@ -60,52 +58,43 @@ def __call__(self, val):
logger.warning('val = {}. will return {}'.format(val, None))
return None

self._updateBoundaries(val)
bin = self.boundaries[0]

for b in self.boundaries[1:]:
if b <= val: bin = b
else: break
self._update_boundaries(val)

if not self.lowedge:
bin += self.halfWidth
bin = self.boundaries[0]
for b in self.boundaries:
if b <= val:
bin = b
else:
break

return bin

def _updateBoundaries(self, val):
def _update_boundaries(self, val):

while val < self.boundaries[0]:
self.boundaries.insert(0, self.boundaries[0] - self.width)
self.boundaries.appendleft(self.boundaries[0] - self.width)

while val > self.boundaries[-1]:
self.boundaries.append(self.boundaries[-1] + self.width)

def next(self, bin):
return self._next_lower_boundary(bin)

bin = self.__call__(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.__call__(self.min)
return self._lower_boundary(self.min)

if bin == self.overflow_bin:
return self.overflow_bin

self._updateBoundaries(bin)
self._updateBoundaries(bin + self.width)

nbin = self.boundaries[0]

for b in self.boundaries[1:]:
if b <= bin: nbin = b
else: break

ret = self.boundaries[self.boundaries.index(nbin) + 1]

if not self.lowedge:
ret += self.halfWidth
self._update_boundaries(bin)

return ret
return self._lower_boundary(bin + self.width*1.001)

##__________________________________________________________________||
15 changes: 7 additions & 8 deletions alphatwirl/binning/RoundLog.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,25 @@ def returnTrue(x): return True

##__________________________________________________________________||
class RoundLog(object):
def __init__(self, width = 0.1, aBoundary = 1,
def __init__(self, width = 0.1, aboundary = 1,
min = None, underflow_bin = None,
max = None, overflow_bin = None,
valid = returnTrue,
retvalue = 'lowedge',
):
self._round = Round(width = width, aBoundary = math.log10(aBoundary), retvalue = retvalue)
valid = returnTrue):

self._round = Round(width = width, aboundary = math.log10(aboundary))
self.width = width
self.aBoundary = aBoundary
self.aboundary = aboundary
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(
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.aboundary,
self.min,
self.underflow_bin,
self.max,
Expand Down
73 changes: 25 additions & 48 deletions tests/unit/binning/test_Round.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
class TestRound(unittest.TestCase):

def test_init(self):
Round(retvalue = 'center')
Round(retvalue = 'lowedge')
self.assertRaises(ValueError, Round, retvalue = 'yyy')
obj = Round()

def test__repr(self):
obj = Round()
Expand Down Expand Up @@ -57,77 +55,34 @@ def test_call_decimal_width(self):
self.assertAlmostEqual( -0.055, obj( -0.048))
self.assertAlmostEqual( -0.015, obj( -0.015))

def test_center(self):
obj = Round(retvalue = 'center')
self.assertEqual( 1.0, obj( 0.51))
self.assertEqual( 1.0, obj( 1.41))
self.assertEqual( 105.0, obj( 104.6 ))
self.assertEqual( -0.0, obj( -0.4 ))
self.assertEqual( -1.0, obj( -0.51 ))
self.assertEqual( -1.0, obj( -1.4 ))
self.assertEqual( -1.0, obj( -1.5 ))

obj = Round(0.02, 0.005, retvalue = 'center')
self.assertAlmostEqual( 0.015, obj( 0.005))
self.assertAlmostEqual( 0.035, obj( 0.025))
self.assertAlmostEqual( 0.075, obj( 0.081))
self.assertAlmostEqual( -0.045, obj( -0.048))
self.assertAlmostEqual( -0.005, obj( -0.015))

def test_onBoundary(self):
obj = Round()
self.assertEqual( -1.5, obj( -1.5))
self.assertEqual( -0.5, obj( -0.5))
self.assertEqual( 0.5, obj( 0.5))
self.assertEqual( 1.5, obj( 1.5))

obj = Round(retvalue = 'center')
self.assertEqual( -1, obj( -1.5))
self.assertEqual( 0, obj( -0.5))
self.assertEqual( 1, obj( 0.5))
self.assertEqual( 2, obj( 1.5))

obj = Round(0.02, 0.005)
self.assertEqual( -0.035, obj( -0.035))
self.assertEqual( -0.015, obj( -0.015))
self.assertEqual( 0.005, obj( 0.005))
self.assertEqual( 0.025, obj( 0.025))
self.assertEqual( 0.045, obj( 0.045))

obj = Round(0.02, 0.005, retvalue = 'center')
self.assertAlmostEqual( -0.025, obj( -0.035))
self.assertAlmostEqual( -0.005, obj( -0.015))
self.assertAlmostEqual( 0.015, obj( 0.005))
self.assertAlmostEqual( 0.035, obj( 0.025))
self.assertAlmostEqual( 0.055, obj( 0.045))

def test_next(self):
obj = Round()
self.assertEqual( -0.5, obj.next( -1.5))
self.assertEqual( 0.5, obj.next( -0.5))
self.assertEqual( 1.5, obj.next( 0.5))
self.assertEqual( 2.5, obj.next( 1.5))

obj = Round(retvalue = 'center')
self.assertEqual( 0, obj.next( -1))
self.assertEqual( 1, obj.next( 0))
self.assertEqual( 2, obj.next( 1))
self.assertEqual( 3, obj.next( 2))

obj = Round(0.02, 0.005)
self.assertEqual( -0.015, obj.next( -0.035))
self.assertEqual( 0.005, obj.next( -0.015))
self.assertEqual( 0.025, obj.next( 0.005))
self.assertEqual( 0.045, obj.next( 0.025))
self.assertEqual( 0.065, obj.next( 0.045))

obj = Round(0.02, 0.005, retvalue = 'center')
self.assertAlmostEqual( -0.005, obj.next( -0.025))
self.assertAlmostEqual( 0.015, obj.next( -0.005))
self.assertAlmostEqual( 0.035, obj.next( 0.015))
self.assertAlmostEqual( 0.055, obj.next( 0.035))
self.assertAlmostEqual( 0.075, obj.next( 0.055))

def test_valid(self):
obj = Round(valid = lambda x: x >= 0)
self.assertEqual( 0.5, obj( 1))
Expand Down Expand Up @@ -155,15 +110,37 @@ def test_max(self):
self.assertEqual( None, obj( 150))
self.assertEqual( None, obj( 500))

self.assertEqual( None, obj.next(140)) # the next to the last bin is
# the overflow bin

def test_max_overflow_bin(self):
obj = Round(10, 100, max = 150, overflow_bin = 150)
self.assertEqual( 100, obj( 100))
self.assertEqual( 150, obj( 150))
self.assertEqual( 150, obj( 500))
self.assertEqual( 140, obj( 149)) # the last bin
self.assertEqual( 150, obj( 150)) # overflow
self.assertEqual( 150, obj( 500)) # overflow

self.assertEqual( 150, obj.next(140)) # the next to the last
# bin is the overflow
# bin

self.assertEqual( 150, obj.next(150)) # the next to the overflow
# bin is the overflow bin

def test_max_overflow_bin_999(self):
obj = Round(10, 100, max = 150, overflow_bin = 999)
self.assertEqual( 100, obj( 100))
self.assertEqual( 140, obj( 149)) # the last bin
self.assertEqual( 999, obj( 150)) # overflow
self.assertEqual( 999, obj( 500)) # overflow

self.assertEqual( 999, obj.next(140)) # the next to the last
# bin is the overflow
# bin

self.assertEqual( 999, obj.next(999)) # the next to the overflow
# bin is the overflow bin

def test_inf(self):
obj = Round(10, 100)
self.assertIsNone(obj(float('inf')))
Expand Down
18 changes: 5 additions & 13 deletions tests/unit/binning/test_RoundLog.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,19 @@
class TestRoundLog(unittest.TestCase):

def test_init(self):
RoundLog(retvalue = 'center')
RoundLog(retvalue = 'lowedge')
self.assertRaises(ValueError, RoundLog, retvalue = 'yyy')
obj = RoundLog()

def test_call(self):
obj = RoundLog()
self.assertAlmostEqual( 1.9952623149688, obj( 2))
self.assertAlmostEqual( 19.952623149688, obj( 20))
self.assertAlmostEqual( 199.52623149688, obj( 200))

def test_call_center(self):
obj = RoundLog(retvalue = 'center')
self.assertAlmostEqual( 2.23872113856834, obj( 2))
self.assertAlmostEqual( 22.3872113856834, obj( 20))
self.assertAlmostEqual( 223.872113856834, obj( 200))

def test_next(self):
obj = RoundLog(retvalue = 'center')
self.assertAlmostEqual( 2.818382931264, obj.next(2.23872113856834))
self.assertAlmostEqual( 28.18382931264, obj.next(22.3872113856834))
self.assertAlmostEqual( 281.8382931264, obj.next(223.872113856834))
obj = RoundLog()
self.assertAlmostEqual( 2.51188643150958, obj.next(2.23872113856834))
self.assertAlmostEqual( 25.11886431509581, obj.next(22.3872113856834))
self.assertAlmostEqual( 251.18864315095848, obj.next(223.872113856834))

def test_call_zero(self):
obj = RoundLog()
Expand Down

0 comments on commit 17661e3

Please sign in to comment.