Skip to content

Commit 58bd962

Browse files
authored
Merge pull request cms-nanoAOD#64 from cms-nanoAOD/reduceMantissa2
Introduce limited precision for floats in post proc output
2 parents 2012f6f + ed43ffa commit 58bd962

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

interface/ReduceMantissa.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef reducemantissa_h
2+
#define reducemantissa_h
3+
4+
class ReduceMantissaToNbitsRounding {
5+
public:
6+
ReduceMantissaToNbitsRounding(int bits) :
7+
shift(23-bits), mask((0xFFFFFFFF >> (shift)) << (shift)),
8+
test(1 << (shift-1)), maxn((1<<bits)-2) {
9+
assert(bits <= 23); // "max mantissa size is 23 bits"
10+
}
11+
float operator()(float f) const {
12+
constexpr uint32_t low23 = (0x007FFFFF); // mask to keep lowest 23 bits = mantissa
13+
constexpr uint32_t hi9 = (0xFF800000); // mask to keep highest 9 bits = the rest
14+
union { float flt; uint32_t i32; } conv;
15+
conv.flt=f;
16+
if (conv.i32 & test) { // need to round
17+
uint32_t mantissa = (conv.i32 & low23) >> shift;
18+
if (mantissa < maxn) mantissa++;
19+
conv.i32 = (conv.i32 & hi9) | (mantissa << shift);
20+
} else {
21+
conv.i32 &= mask;
22+
}
23+
return conv.flt;
24+
}
25+
private:
26+
const int shift;
27+
const uint32_t mask, test, maxn;
28+
};
29+
30+
31+
#endif

python/postprocessing/framework/output.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
_rootBranchType2PythonArray = { 'b':'B', 'B':'b', 'i':'I', 'I':'i', 'F':'f', 'D':'d', 'l':'L', 'L':'l', 'O':'B' }
88

99
class OutputBranch:
10-
def __init__(self, tree, name, rootBranchType, n=1, lenVar=None, title=None):
10+
def __init__(self, tree, name, rootBranchType, n=1, lenVar=None, title=None, limitedPrecision=False):
1111
n = int(n)
1212
self.buff = array(_rootBranchType2PythonArray[rootBranchType], n*[0. if rootBranchType in 'FD' else 0])
1313
self.lenVar = lenVar
1414
self.n = n
15+
self.precision = ROOT.ReduceMantissaToNbitsRounding(limitedPrecision) if limitedPrecision and rootBranchType=='F' else lambda x : x
1516
#check if a branch was already there
1617
existingBranch = tree.GetBranch(name)
1718
if (existingBranch):
@@ -31,9 +32,9 @@ def fill(self, val):
3132
if len(self.buff) < len(val): # realloc
3233
self.buff = array(self.buff.typecode, max(len(val),2*len(self.buff))*[0. if self.buff.typecode in 'fd' else 0])
3334
self.branch.SetAddress(self.buff)
34-
for i,v in enumerate(val): self.buff[i] = v
35+
for i,v in enumerate(val): self.buff[i] = self.precision(v)
3536
elif self.n == 1:
36-
self.buff[0] = val
37+
self.buff[0] = self.precision(val)
3738
else:
3839
if len(val) != self.n: raise RuntimeError("Mismatch in filling branch %s of fixed length %d with %d values (%s)" % (self.Branch.GetName(),self.n,len(val),val))
3940
for i,v in enumerate(val): self.buff[i] = v
@@ -44,10 +45,10 @@ def __init__(self, tfile, ttree, intree):
4445
self._tree = ttree
4546
self._intree = intree
4647
self._branches = {}
47-
def branch(self, name, rootBranchType, n=1, lenVar=None, title=None):
48+
def branch(self, name, rootBranchType, n=1, lenVar=None, title=None,limitedPrecision=False):
4849
if (lenVar != None) and (lenVar not in self._branches): #and (not self._tree.GetBranch(lenVar)):
4950
self._branches[lenVar] = OutputBranch(self._tree, lenVar, "i")
50-
self._branches[name] = OutputBranch(self._tree, name, rootBranchType, n=n, lenVar=lenVar, title=title)
51+
self._branches[name] = OutputBranch(self._tree, name, rootBranchType, n=n, lenVar=lenVar, title=title,limitedPrecision=limitedPrecision)
5152
return self._branches[name]
5253
def fillBranch(self, name, val):
5354
br = self._branches[name]

src/classes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#include "PhysicsTools/NanoAODTools/interface/PyJetResolutionScaleFactorWrapper.h"
33
#include "PhysicsTools/NanoAODTools/interface/PyJetParametersWrapper.h"
44
#include "PhysicsTools/NanoAODTools/interface/WeightCalculatorFromHistogram.h"
5+
#include "PhysicsTools/NanoAODTools/interface/ReduceMantissa.h"
56

67
PyJetResolutionWrapper jetRes;
78
PyJetResolutionScaleFactorWrapper jetResScaleFactor;
89
PyJetParametersWrapper jetParams;
910
WeightCalculatorFromHistogram wcalc;
11+
ReduceMantissaToNbitsRounding red(12);

src/classes_def.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
<class name="PyJetResolutionScaleFactorWrapper"/>
55
<class name="PyJetParametersWrapper"/>
66
<class name="WeightCalculatorFromHistogram"/>
7+
<class name="ReduceMantissaToNbitsRounding"/>
78
</selection>
89
</lcgdict>

0 commit comments

Comments
 (0)