Skip to content

Commit cbe1904

Browse files
authored
Merge pull request #12 from histogrammar/1.0.x
1.0.x
2 parents c6424ea + 496b83a commit cbe1904

22 files changed

Lines changed: 577 additions & 90 deletions

docs/conf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
# Add any Sphinx extension module names here, as strings. They can be extensions
2626
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
27-
extensions = ['sphinx.ext.autodoc', 'sphinxcontrib.napoleon', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.linkcode']
27+
extensions = ['sphinx.ext.autodoc', 'sphinxcontrib.napoleon', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.linkcode']
2828

2929
# Add any paths that contain templates here, relative to this directory.
3030
templates_path = ['_templates']
@@ -47,9 +47,9 @@
4747
# built documents.
4848
#
4949
# The short X.Y version.
50-
version = "1.0.0"
50+
version = "1.0.3"
5151
# The full version, including alpha/beta/rc tags.
52-
release = "1.0.0"
52+
release = "1.0.3"
5353

5454
# The language for content autogenerated by Sphinx. Refer to documentation
5555
# for a list of supported languages.

histogrammar/defs.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,15 @@ def zero(self):
159159
raise NotImplementedError
160160

161161
def __add__(self, other):
162-
"""Add two containers of the same type. The originals are unaffected. """
162+
"""Add two containers of the same type. The originals are unaffected."""
163+
raise NotImplementedError
164+
165+
def __mul__(self, factor):
166+
"""Reweight the contents in all nested aggregators by a scalar factor, as though they had been filled with a different weight. The original is unaffected."""
167+
raise NotImplementedError
168+
169+
def __rmul__(self, factor):
170+
"""Reweight the contents in all nested aggregators by a scalar factor, as though they had been filled with a different weight. The original is unaffected."""
163171
raise NotImplementedError
164172

165173
def fill(self, datum, weight=1.0):
@@ -301,6 +309,8 @@ def fillroot(self, ttree, start=-1, end=-1, debug=False, debugOnError=True, **ex
301309
}}
302310
303311
void fillall(TTree* ttree, Long64_t start, Long64_t end) {{
312+
ttree->SetBranchStatus("*", 0);
313+
{11}
304314
init();
305315
{8}
306316
if (start < 0) start = 0;
@@ -323,7 +333,8 @@ def fillroot(self, ttree, start=-1, end=-1, debug=False, debugOnError=True, **ex
323333
"\n".join(initCode),
324334
"".join(" ttree->SetBranchAddress(" + jsonlib.dumps(key) + ", &" + n + ");\n" for n, key in inputFieldNames.items()),
325335
"".join(x for x in derivedFieldExprs.values()),
326-
"\n".join(fillCode))
336+
"\n".join(fillCode),
337+
"".join(" ttree->SetBranchStatus(\"" + key + "\", 1);\n" for key in inputFieldNames.values()))
327338

328339
if debug:
329340
print("line |")

histogrammar/primitives/average.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,20 @@ def __add__(self, other):
8787
else:
8888
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
8989

90+
@inheritdoc(Container)
91+
def __mul__(self, factor):
92+
if math.isnan(factor) or factor <= 0.0:
93+
return self.zero()
94+
else:
95+
out = self.zero()
96+
out.entries = factor * self.entries
97+
out.mean = self.mean
98+
return out.specialize()
99+
100+
@inheritdoc(Container)
101+
def __rmul__(self, factor):
102+
return self.__mul__(factor)
103+
90104
@inheritdoc(Container)
91105
def fill(self, datum, weight=1.0):
92106
self._checkForCrossReferences()

histogrammar/primitives/bag.py

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@ def __add__(self, other):
102102
else:
103103
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
104104

105+
@inheritdoc(Container)
106+
def __mul__(self, factor):
107+
if math.isnan(factor) or factor <= 0.0:
108+
return self.zero()
109+
else:
110+
out = self.zero()
111+
out.entries = factor * self.entries
112+
for value, count in self.values.items():
113+
out.values[value] = factor * count
114+
return out.specialize()
115+
116+
@inheritdoc(Container)
117+
def __rmul__(self, factor):
118+
return self.__mul__(factor)
119+
105120
@inheritdoc(Container)
106121
def fill(self, datum, weight=1.0):
107122
self._checkForCrossReferences()
@@ -224,9 +239,31 @@ def children(self):
224239

225240
@inheritdoc(Container)
226241
def toJsonFragment(self, suppressName):
227-
aslist = sorted(x for x in self.values.items() if x[0] != "nan")
228-
if "nan" in self.values:
229-
aslist.append(("nan", self.values["nan"]))
242+
if self.range == "N":
243+
aslist = sorted(x for x in self.values.items() if x[0] != "nan")
244+
if "nan" in self.values:
245+
aslist.append(("nan", self.values["nan"]))
246+
247+
elif self.range[0] == "N":
248+
class Sorter(object):
249+
def __init__(self, x):
250+
self.x = x
251+
def __lt__(self, other):
252+
for xi, yi in zip(self.x, other.x):
253+
if isinstance(xi, str) and isinstance(yi, float):
254+
return False
255+
elif isinstance(xi, float) and isinstance(yi, str):
256+
return True
257+
elif xi < yi:
258+
return True
259+
elif xi > yi:
260+
return False
261+
return False
262+
aslist = sorted((x for x in self.values.items()), key=lambda y: tuple(Sorter(z) for z in y))
263+
264+
else:
265+
aslist = sorted(x for x in self.values.items())
266+
230267
return maybeAdd({
231268
"entries": floatToJson(self.entries),
232269
"values": [{"w": floatToJson(n), "v": rangeToJson(v)} for v, n in aslist],
@@ -303,8 +340,34 @@ def __eq__(self, other):
303340
if len(self.values) != len(other.values):
304341
return False
305342

306-
one = sorted(x for x in self.values.items() if x[0] != "nan") + [("nan", self.values.get("nan"))]
307-
two = sorted(x for x in other.values.items() if x[0] != "nan") + [("nan", other.values.get("nan"))]
343+
if self.range != other.range:
344+
return False
345+
346+
if self.range == "N":
347+
one = sorted(x for x in self.values.items() if x[0] != "nan") + [("nan", self.values.get("nan"))]
348+
two = sorted(x for x in other.values.items() if x[0] != "nan") + [("nan", other.values.get("nan"))]
349+
350+
elif self.range[0] == "N":
351+
class Sorter(object):
352+
def __init__(self, x):
353+
self.x = x
354+
def __lt__(self, other):
355+
for xi, yi in zip(self.x, other.x):
356+
if isinstance(xi, str) and isinstance(yi, float):
357+
return False
358+
elif isinstance(xi, float) and isinstance(yi, str):
359+
return True
360+
elif xi < yi:
361+
return True
362+
elif xi > yi:
363+
return False
364+
return False
365+
one = sorted((x for x in self.values.items()), key=lambda y: tuple(Sorter(z) for z in y))
366+
two = sorted((x for x in other.values.items()), key=lambda y: tuple(Sorter(z) for z in y))
367+
368+
else:
369+
one = sorted(x for x in self.values.items())
370+
two = sorted(x for x in other.values.items())
308371

309372
for (v1, w1), (v2, w2) in zip(one, two):
310373
if isinstance(v1, basestring) and isinstance(v2, basestring):
@@ -334,7 +397,7 @@ def __eq__(self, other):
334397
else:
335398
return False
336399

337-
return isinstance(other, Bag) and self.quantity == other.quantity and numeq(self.entries, other.entries) and self.range == other.range
400+
return isinstance(other, Bag) and self.quantity == other.quantity and numeq(self.entries, other.entries)
338401

339402
def __ne__(self, other): return not self == other
340403

histogrammar/primitives/bin.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,24 @@ def __add__(self, other):
173173
else:
174174
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
175175

176+
@inheritdoc(Container)
177+
def __mul__(self, factor):
178+
if math.isnan(factor) or factor <= 0.0:
179+
return self.zero()
180+
else:
181+
out = self.zero()
182+
out.entries = factor * self.entries
183+
for i, v in enumerate(self.values):
184+
out.values[i] = v * factor
185+
out.overflow = self.overflow * factor
186+
out.underflow = self.underflow * factor
187+
out.nanflow = self.nanflow * factor
188+
return out.specialize()
189+
190+
@inheritdoc(Container)
191+
def __rmul__(self, factor):
192+
return self.__mul__(factor)
193+
176194
@property
177195
def num(self):
178196
"""Number of bins."""

histogrammar/primitives/categorize.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
import math
1718
import numbers
1819

1920
from histogrammar.defs import *
@@ -141,6 +142,21 @@ def __add__(self, other):
141142
else:
142143
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
143144

145+
@inheritdoc(Container)
146+
def __mul__(self, factor):
147+
if math.isnan(factor) or factor <= 0.0:
148+
return self.zero()
149+
else:
150+
out = self.zero()
151+
out.entries = factor * self.entries
152+
for k, v in self.bins.items():
153+
out.bins[k] = v * factor
154+
return out.specialize()
155+
156+
@inheritdoc(Container)
157+
def __rmul__(self, factor):
158+
return self.__mul__(factor)
159+
144160
@inheritdoc(Container)
145161
def fill(self, datum, weight=1.0):
146162
self._checkForCrossReferences()

histogrammar/primitives/centrallybin.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ def __add__(self, other):
172172
out.bins = newbins
173173
return out.specialize()
174174

175+
@inheritdoc(Container)
176+
def __mul__(self, factor):
177+
if math.isnan(factor) or factor <= 0.0:
178+
return self.zero()
179+
else:
180+
out = self.zero()
181+
out.entries = factor * self.entries
182+
out.bins = [(c, v * factor) for (c, v) in self.bins]
183+
out.nanflow = self.nanflow * factor
184+
return out.specialize()
185+
186+
@inheritdoc(Container)
187+
def __rmul__(self, factor):
188+
return self.__mul__(factor)
189+
175190
@inheritdoc(Container)
176191
def fill(self, datum, weight=1.0):
177192
self._checkForCrossReferences()

histogrammar/primitives/collection.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# limitations under the License.
1616

1717
import json
18+
import math
1819
import numbers
1920
import struct
2021

@@ -318,6 +319,21 @@ def __add__(self, other):
318319
else:
319320
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
320321

322+
@inheritdoc(Container)
323+
def __mul__(self, factor):
324+
if math.isnan(factor) or factor <= 0.0:
325+
return self.zero()
326+
else:
327+
out = self.zero()
328+
out.entries = factor * self.entries
329+
for k, v in self.pairs.items():
330+
out.pairs[k] = v * factor
331+
return out.specialize()
332+
333+
@inheritdoc(Container)
334+
def __rmul__(self, factor):
335+
return self.__mul__(factor)
336+
321337
@inheritdoc(Container)
322338
def fill(self, datum, weight=1.0):
323339
self._checkForCrossReferences()
@@ -501,6 +517,21 @@ def __add__(self, other):
501517
else:
502518
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
503519

520+
@inheritdoc(Container)
521+
def __mul__(self, factor):
522+
if math.isnan(factor) or factor <= 0.0:
523+
return self.zero()
524+
else:
525+
out = self.zero()
526+
out.entries = factor * self.entries
527+
for k, v in self.pairs.items():
528+
out.pairs[k] = v * factor
529+
return out.specialize()
530+
531+
@inheritdoc(Container)
532+
def __rmul__(self, factor):
533+
return self.__mul__(factor)
534+
504535
@inheritdoc(Container)
505536
def fill(self, datum, weight=1.0):
506537
self._checkForCrossReferences()
@@ -692,6 +723,19 @@ def __add__(self, other):
692723
else:
693724
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
694725

726+
@inheritdoc(Container)
727+
def __mul__(self, factor):
728+
if math.isnan(factor) or factor <= 0.0:
729+
return self.zero()
730+
else:
731+
out = Index(*[x * factor for x in self.values])
732+
out.entries = factor * self.entries
733+
return out.specialize()
734+
735+
@inheritdoc(Container)
736+
def __rmul__(self, factor):
737+
return self.__mul__(factor)
738+
695739
@inheritdoc(Container)
696740
def fill(self, datum, weight=1.0):
697741
self._checkForCrossReferences()
@@ -890,6 +934,19 @@ def __add__(self, other):
890934
else:
891935
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
892936

937+
@inheritdoc(Container)
938+
def __mul__(self, factor):
939+
if math.isnan(factor) or factor <= 0.0:
940+
return self.zero()
941+
else:
942+
out = Branch(*[x * factor for x in self.values])
943+
out.entries = factor * self.entries
944+
return out.specialize()
945+
946+
@inheritdoc(Container)
947+
def __rmul__(self, factor):
948+
return self.__mul__(factor)
949+
893950
@inheritdoc(Container)
894951
def fill(self, datum, weight=1.0):
895952
self._checkForCrossReferences()

histogrammar/primitives/count.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
import math
1718
import numbers
1819
import re
1920
import struct
@@ -82,6 +83,24 @@ def __add__(self, other):
8283
else:
8384
raise ContainerException("cannot add {0} and {1}".format(self.name, other.name))
8485

86+
@inheritdoc(Container)
87+
def __mul__(self, factor):
88+
if self.transform != identity or \
89+
not callable(self.transform.expr) or \
90+
(hasattr(self.transform.expr, "func_code") and self.transform.expr.func_code.co_code != identity.expr.func_code.co_code) or \
91+
(hasattr(self.transform.expr, "__code__") and self.transform.expr.__code__.co_code != identity.expr.__code__.co_code):
92+
raise ContainerException("Cannot scalar-multiply Count with a non-identity transform.")
93+
elif math.isnan(factor) or factor <= 0.0:
94+
return self.zero()
95+
else:
96+
out = self.zero()
97+
out.entries = factor * self.entries
98+
return out.specialize()
99+
100+
@inheritdoc(Container)
101+
def __rmul__(self, factor):
102+
return self.__mul__(factor)
103+
85104
@inheritdoc(Container)
86105
def fill(self, datum, weight=1.0):
87106
self._checkForCrossReferences()

0 commit comments

Comments
 (0)