diff --git a/.travis.yml b/.travis.yml index 26e6d76..c17af7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ addons: packages: - python-numpy - python3-numpy + - python-setuptools install: - pip install --upgrade pip diff --git a/README.md b/README.md index 5fbdf52..d8da817 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Python implementation of Histogrammar ===================================== +[![DOI](https://zenodo.org/badge/doi/10.5281/zenodo.61418.svg)](http://dx.doi.org/10.5281/zenodo.61418) + See [histogrammar.org](http://histogrammar.org) for a complete introduction to Histogrammar. This is a pure Python implementation for Python versions 2.6, 2.7, and 3.4. diff --git a/setup.py b/setup.py index 74ff44a..e5c2f44 100644 --- a/setup.py +++ b/setup.py @@ -15,30 +15,28 @@ # limitations under the License. import sys -from distutils.core import setup -from distutils.cmd import Command +from setuptools import setup, find_packages import histogrammar.version -class TestCommand(Command): - user_options = [] - def initialize_options(self): pass - def finalize_options(self): pass - def run(self): - import sys, subprocess - if sys.version_info[0] == 2 and sys.version_info[1] == 6: - args = ["-c", "import unittest; from test.testbasic import *; from test.testnumpy import *; from test.testrootcling import *; from test.testgpu import *; unittest.main()"] - else: - args = ["-m", "unittest", "-v", "test.testbasic", "test.testnumpy", "test.testrootcling", "test.testgpu"] - raise SystemExit(subprocess.call([sys.executable] + args)) - -setup(name="Histogrammar", - version=histogrammar.version.__version__, - scripts=["scripts/hgwatch"], - description="Composable histogram primitives for distributed data reduction.", - author="Jim Pivarski (DIANA-HEP)", - author_email="pivarski@fnal.gov", - url="https://github.com/diana-hep/histogrammar", - cmdclass={"test": TestCommand}, - packages=["histogrammar", "histogrammar.primitives", "histogrammar.plot", "histogrammar.pycparser", "histogrammar.pycparser.ply"], +setup(name = "Histogrammar", + version = histogrammar.version.__version__, + packages = find_packages(), + scripts = ["scripts/hgwatch"], + description = "Composable histogram primitives for distributed data reduction.", + author = "Jim Pivarski (DIANA-HEP)", + author_email = "pivarski@fnal.gov", + url = "http://histogrammar.org", + license = "Apache Software License v2", + test_suite = "tests", + install_requires = [], + tests_require = [], + classifiers = ["Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: Apache Software License", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Scientific/Engineering :: Mathematics", + "Topic :: Scientific/Engineering :: Physics", + ], ) diff --git a/test/specification.py b/test/specification.py deleted file mode 100644 index a0f6754..0000000 --- a/test/specification.py +++ /dev/null @@ -1,535 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2016 DIANA-HEP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from histogrammar import * - -def fill(container, datum, weight): - if isinstance(container, Count): - Count_fill(container, datum, weight) - elif isinstance(container, Sum): - Sum_fill(container, datum, weight) - elif isinstance(container, Average): - Average_fill(container, datum, weight) - elif isinstance(container, Deviate): - Deviate_fill(container, datum, weight) - elif isinstance(container, Minimize): - Minimize_fill(container, datum, weight) - elif isinstance(container, Maximize): - Maximize_fill(container, datum, weight) - elif isinstance(container, Bag): - Bag_fill(container, datum, weight) - elif isinstance(container, Bin): - Bin_fill(container, datum, weight) - elif isinstance(container, SparselyBin): - SparselyBin_fill(container, datum, weight) - elif isinstance(container, CentrallyBin): - CentrallyBin_fill(container, datum, weight) - elif isinstance(container, IrregularlyBin): - IrregularlyBin_fill(container, datum, weight) - elif isinstance(container, Categorize): - Categorize_fill(container, datum, weight) - elif isinstance(container, Fraction): - Fraction_fill(container, datum, weight) - elif isinstance(container, Stack): - Stack_fill(container, datum, weight) - elif isinstance(container, Select): - Select_fill(container, datum, weight) - elif isinstance(container, Label): - Label_fill(container, datum, weight) - elif isinstance(container, UntypedLabel): - UntypedLabel_fill(container, datum, weight) - elif isinstance(container, Index): - Index_fill(container, datum, weight) - elif isinstance(container, Branch): - Branch_fill(container, datum, weight) - else: - raise Exception - -def combine(one, two): - if isinstance(one, Count) and isinstance(two, Count): - return Count_combine(one, two) - elif isinstance(one, Sum) and isinstance(two, Sum): - return Sum_combine(one, two) - elif isinstance(one, Average) and isinstance(two, Average): - return Average_combine(one, two) - elif isinstance(one, Deviate) and isinstance(two, Deviate): - return Deviate_combine(one, two) - elif isinstance(one, Minimize) and isinstance(two, Minimize): - return Minimize_combine(one, two) - elif isinstance(one, Maximize) and isinstance(two, Maximize): - return Maximize_combine(one, two) - elif isinstance(one, Bag) and isinstance(two, Bag): - return Bag_combine(one, two) - elif isinstance(one, Bin) and isinstance(two, Bin): - return Bin_combine(one, two) - elif isinstance(one, SparselyBin) and isinstance(two, SparselyBin): - return SparselyBin_combine(one, two) - elif isinstance(one, CentrallyBin) and isinstance(two, CentrallyBin): - return CentrallyBin_combine(one, two) - elif isinstance(one, IrregularlyBin) and isinstance(two, IrregularlyBin): - return IrregularlyBin_combine(one, two) - elif isinstance(one, Categorize) and isinstance(two, Categorize): - return Categorize_combine(one, two) - elif isinstance(one, Fraction) and isinstance(two, Fraction): - return Fraction_combine(one, two) - elif isinstance(one, Stack) and isinstance(two, Stack): - return Stack_combine(one, two) - elif isinstance(one, Select) and isinstance(two, Select): - return Select_combine(one, two) - elif isinstance(one, Label) and isinstance(two, Label): - return Label_combine(one, two) - elif isinstance(one, UntypedLabel) and isinstance(two, UntypedLabel): - return UntypedLabel_combine(one, two) - elif isinstance(one, Index) and isinstance(two, Index): - return Index_combine(one, two) - elif isinstance(one, Branch) and isinstance(two, Branch): - return Branch_combine(one, two) - else: - raise Exception - -# Literally copied from histogrammar-docs/specification/index.md -# keep up to date! - -def Count_fill(counting, datum, weight): - if weight > 0.0: - counting.entries += counting.transform(weight) - -def Count_combine(one, two): - out = Count.ed(one.entries + two.entries) - out.transform = one.transform - return out - -def Sum_fill(summing, datum, weight): - if weight > 0.0: - q = summing.quantity(datum) - summing.entries += weight - summing.sum += q * weight - -def Sum_combine(one, two): - out = Sum.ed(one.entries + two.entries, one.sum + two.sum) - out.quantity = one.quantity - return out - -def Average_fill(averaging, datum, weight): - if weight > 0.0: - q = averaging.quantity(datum) - if averaging.entries == 0.0: - averaging.mean = 0.0 # make it not NaN (has no weight in total) - averaging.entries += weight - - if math.isnan(averaging.mean) or math.isnan(q): - averaging.mean = float("nan") - - elif math.isinf(averaging.mean) or math.isinf(q): - if math.isinf(averaging.mean) and math.isinf(q) and averaging.mean * q < 0.0: - averaging.mean = float("nan") # opposite-sign infinities is bad - elif math.isinf(q): - averaging.mean = q # mean becomes infinite with sign of q - else: - pass # mean is already infinite - if math.isinf(averaging.entries) or math.isnan(averaging.entries): - averaging.mean = float("nan") # non-finite denominator is bad - - else: # handle finite case - delta = q - averaging.mean - shift = delta * weight / averaging.entries - averaging.mean += shift - -def Average_combine(one, two): - entries = one.entries + two.entries - if one.entries == 0.0: - mean = two.mean - elif two.entries == 0.0: - mean = one.mean - else: - mean = (one.entries*one.mean + two.entries*two.mean)/entries - out = Average.ed(entries, mean) - out.quantity = one.quantity - return out - -def Deviate_fill(deviating, datum, weight): - if weight > 0.0: - q = deviating.quantity(datum) - if deviating.entries == 0.0: - deviating.mean = 0.0 # make it not NaN (has no weight in total) - deviating.variance = 0.0 - varianceTimesEntries = deviating.variance * deviating.entries - deviating.entries += weight - - if math.isnan(deviating.mean) or math.isnan(q): - deviating.mean = float("nan") - varianceTimesEntries = float("nan") - - elif math.isinf(deviating.mean) or math.isinf(q): - if math.isinf(deviating.mean) and math.isinf(q) and deviating.mean * q < 0.0: - deviating.mean = float("nan") # opposite-sign infinities is bad - elif math.isinf(q): - deviating.mean = q # mean becomes infinite with sign of q - else: - pass # mean and variance are already infinite - if math.isinf(deviating.entries) or math.isnan(deviating.entries): - deviating.mean = float("nan") # non-finite denominator is bad - - # any infinite value makes the variance NaN - varianceTimesEntries = float("nan") - - else: # handle finite case - delta = q - deviating.mean - shift = delta * weight / deviating.entries - deviating.mean += shift - varianceTimesEntries += weight * delta * (q - deviating.mean) - - deviating.variance = varianceTimesEntries / deviating.entries - -def Deviate_combine(one, two): - entries = one.entries + two.entries - if one.entries == 0.0: - mean = two.mean - varianceTimesEntries = two.variance * two.entries - elif two.entries == 0.0: - mean = one.mean - varianceTimesEntries = one.variance * one.entries - else: - mean = (one.entries*one.mean + two.entries*two.mean) / entries - varianceTimesEntries = one.entries*one.variance + two.entries*two.variance \ - + one.entries*one.mean*one.mean + two.entries*two.mean*two.mean \ - - 2.0*mean*(one.entries*one.mean + two.entries*two.mean) \ - + entries*mean*mean - - if entries == 0.0: - variance = varianceTimesEntries - else: - variance = varianceTimesEntries / entries - - out = Deviate.ed(entries, mean, variance) - out.quantity = one.quantity - return out - -def Minimize_fill(minimizing, datum, weight): - if weight > 0.0: - q = minimizing.quantity(datum) - minimizing.entries += weight - if math.isnan(minimizing.min) or q < minimizing.min: - minimizing.min = q - -def Minimize_combine(one, two): - entries = one.entries + two.entries - if math.isnan(one.min): - min = two.min - elif math.isnan(two.min): - min = one.min - elif one.min < two.min: - min = one.min - else: - min = two.min - out = Minimize.ed(entries, min) - out.quantity = one.quantity - return out - -def Maximize_fill(maximizing, datum, weight): - if weight > 0.0: - q = maximizing.quantity(datum) - maximizing.entries += weight - if math.isnan(maximizing.max) or q > maximizing.max: - maximizing.max = q - -def Maximize_combine(one, two): - entries = one.entries + two.entries - if math.isnan(one.max): - max = two.max - elif math.isnan(two.max): - max = one.max - elif one.max > two.max: - max = one.max - else: - max = two.max - out = Maximize.ed(entries, max) - out.quantity = one.quantity - return out - -def Bag_fill(bagging, datum, weight): - if weight > 0.0: - q = bagging.quantity(datum) - if bagging.range == "N": - if math.isnan(q): # something to avoid NaN != NaN - q = "nan" # (handling is more complex in type-safe languages) - elif bagging.range[0] == "N": - q = tuple("nan" if math.isnan(qi) else qi for qi in q) - bagging.entries += weight - if q in bagging.values: - bagging.values[q] += weight - else: - bagging.values[q] = weight - -def Bag_combine(one, two): - if one.range != two.range: - raise Exception - entries = one.entries + two.entries - values = {} - for v in set(one.values.keys()).union(set(two.values.keys())): - if v in one.values and v in two.values: - values[v] = one.values[v] + two.values[v] - elif v in one.values: - values[v] = one.values[v] - elif v in two.values: - values[v] = two.values[v] - return Bag.ed(entries, values, one.range) - -def Bin_fill(binning, datum, weight): - if weight > 0.0: - q = binning.quantity(datum) - if math.isnan(q): - fill(binning.nanflow, datum, weight) - elif q < binning.low: - fill(binning.underflow, datum, weight) - elif q >= binning.high: - fill(binning.overflow, datum, weight) - else: - bin = int(math.floor(binning.num * \ - (q - binning.low) / (binning.high - binning.low))) - fill(binning.values[bin], datum, weight) - binning.entries += weight - -def Bin_combine(one, two): - if one.num != two.num or one.low != two.low or one.high != two.high: - raise Exception - entries = one.entries + two.entries - values = [combine(x, y) for x, y in zip(one.values, two.values)] - underflow = combine(one.underflow, two.underflow) - overflow = combine(one.overflow, two.overflow) - nanflow = combine(one.nanflow, two.nanflow) - return Bin.ed(one.low, one.high, entries, values, underflow, overflow, nanflow) - -def SparselyBin_fill(sparselybinning, datum, weight): - if weight > 0.0: - q = sparselybinning.quantity(datum) - if math.isnan(q): - fill(sparselybinning.nanflow, datum, weight) - else: - softbin = (q - sparselybinning.origin) / sparselybinning.binWidth - - if softbin <= -(2**63 - 1): - bin = -(2**63 - 1) - elif softbin >= (2**63 - 1): - bin = (2**63 - 1) - else: - bin = int(math.floor(softbin)) - - if bin not in sparselybinning.bins: - sparselybinning.bins[bin] = sparselybinning.value.copy() - - fill(sparselybinning.bins[bin], datum, weight) - - sparselybinning.entries += weight - -def SparselyBin_combine(one, two): - if one.binWidth != two.binWidth or one.origin != two.origin or one.contentType != two.contentType: - raise Exception - entries = one.entries + two.entries - contentType = one.contentType - bins = {} - for key in set(one.bins.keys()).union(set(two.bins.keys())): - if key in one.bins and key in two.bins: - bins[key] = combine(one.bins[key], two.bins[key]) - elif key in one.bins: - bins[key] = one.bins[key].copy() - elif key in two.bins: - bins[key] = two.bins[key].copy() - nanflow = combine(one.nanflow, two.nanflow) - return SparselyBin.ed(one.binWidth, entries, contentType, \ - bins, nanflow, one.origin) - -def CentrallyBin_fill(centrallybinning, datum, weight): - if weight > 0.0: - q = centrallybinning.quantity(datum) - if math.isnan(q): - fill(centrallybinning.nanflow, datum, weight) - else: - for index in range(len(centrallybinning.bins)): - if index == len(centrallybinning.bins) - 1: - break - thisCenter = centrallybinning.bins[index][0] - nextCenter = centrallybinning.bins[index + 1][0] - if q < (thisCenter + nextCenter)/2.0: - break - fill(centrallybinning.bins[index][1], datum, weight) - centrallybinning.entries += weight - -def CentrallyBin_combine(one, two): - if set(one.centers) != set(two.centers): - raise Exception - entries = one.entries + two.entries - bins = [] - for c1, v1 in one.bins: - v2 = [v for c2, v in two.bins if c1 == c2][0] - bins.append((c1, combine(v1, v2))) - - nanflow = combine(one.nanflow, two.nanflow) - return CentrallyBin.ed(entries, bins, nanflow) - -def IrregularlyBin_fill(irregularlybinning, datum, weight): - if weight > 0.0: - q = irregularlybinning.quantity(datum) - if math.isnan(q): - fill(irregularlybinning.nanflow, datum, weight) - else: - lowEdges = irregularlybinning.bins - highEdges = list(irregularlybinning.bins[1:]) + [(float("nan"), None)] - for (low, sub), (high, _) in zip(lowEdges, highEdges): - if q >= low and not q >= high: # include high endpoint only for the last bin - fill(sub, datum, weight) - break - irregularlybinning.entries += weight - -def IrregularlyBin_combine(one, two): - if one.thresholds != two.thresholds: - raise Exception - entries = one.entries + two.entries - bins = [(c, combine(v1, v2)) for (c, v1), (_, v2) in zip(one.bins, two.bins)] - nanflow = combine(one.nanflow, two.nanflow) - return IrregularlyBin.ed(entries, bins, nanflow) - -def Categorize_fill(categorizing, datum, weight): - if weight > 0.0: - q = categorizing.quantity(datum) - if q not in categorizing.bins: - categorizing.bins[q] = categorizing.value.copy() - fill(categorizing.bins[q], datum, weight) - categorizing.entries += weight - -def Categorize_combine(one, two): - if one.contentType != two.contentType: - raise Exception - entries = one.entries + two.entries - contentType = one.contentType - bins = {} - for key in set(one.bins.keys()).union(set(two.bins.keys())): - if key in one.bins and key in two.bins: - bins[key] = combine(one.bins[key], two.bins[key]) - elif key in one.bins: - bins[key] = one.bins[key].copy() - elif key in two.bins: - bins[key] = two.bins[key].copy() - return Categorize.ed(entries, contentType, bins) - -def Fraction_fill(fractioning, datum, weight): - if weight > 0.0: - w = weight * fractioning.quantity(datum) - fill(fractioning.denominator, datum, weight) - if w > 0.0: - fill(fractioning.numerator, datum, w) - fractioning.entries += weight - -def Fraction_combine(one, two): - entries = one.entries + two.entries - numerator = combine(one.numerator, two.numerator) - denominator = combine(one.denominator, two.denominator) - return Fraction.ed(entries, numerator, denominator) - -def Stack_fill(stacking, datum, weight): - if weight > 0.0: - q = stacking.quantity(datum) - if math.isnan(q): - fill(stacking.nanflow, datum, weight) - else: - for threshold, sub in stacking.bins: - if q >= threshold: - fill(sub, datum, weight) - stacking.entries += weight - -def Stack_combine(one, two): - if [c for c, v in one.bins] != [c for c, v in two.bins]: - raise Exception - entries = one.entries + two.entries - bins = [] - for (c, v1), (_, v2) in zip(one.bins, two.bins): - bins.append((c, combine(v1, v2))) - nanflow = combine(one.nanflow, two.nanflow) - return Stack.ed(entries, bins, nanflow) - -def Select_fill(selecting, datum, weight): - if weight > 0.0: - w = weight * selecting.quantity(datum) - if w > 0.0: - fill(selecting.cut, datum, w) - selecting.entries += weight - -def Select_combine(one, two): - entries = one.entries + two.entries - cut = combine(one.cut, two.cut) - return Select.ed(entries, cut) - -def Label_fill(labeling, datum, weight): - if weight > 0.0: - for _, v in labeling.pairs.items(): - fill(v, datum, weight) - labeling.entries += weight - -def Label_combine(one, two): - if set(one.pairs.keys()) != set(two.pairs.keys()): - raise Exception - entries = one.entries + two.entries - pairs = {} - for l, v1 in one.pairs.items(): - v2 = two.pairs[l] - pairs[l] = combine(v1, v2) - return Label.ed(entries, pairs) - -def UntypedLabel_fill(untypedlabeling, datum, weight): - if weight > 0.0: - for _, v in untypedlabeling.pairs.items(): - fill(v, datum, weight) - untypedlabeling.entries += weight - -def UntypedLabel_combine(one, two): - if set(one.pairs.keys()) != set(two.pairs.keys()): - raise Exception - entries = one.entries + two.entries - pairs = {} - for l, v1 in one.pairs.items(): - v2 = two.pairs[l] - pairs[l] = combine(v1, v2) - return UntypedLabel.ed(entries, pairs) - -def Index_fill(indexing, datum, weight): - if weight > 0.0: - for v in indexing.values: - fill(v, datum, weight) - indexing.entries += weight - -def Index_combine(one, two): - if len(one.values) != len(two.values): - raise Exception - entries = one.entries + two.entries - values = [] - for v1, v2 in zip(one.values, two.values): - values.append(combine(v1, v2)) - return Index.ed(entries, values) - -def Branch_fill(branching, datum, weight): - if weight > 0.0: - for v in branching.values: - fill(v, datum, weight) - branching.entries += weight - -def Branch_combine(one, two): - if len(one.values) != len(two.values): - raise Exception - entries = one.entries + two.entries - values = [] - for v1, v2 in zip(one.values, two.values): - values.append(combine(v1, v2)) - return Branch.ed(entries, values) diff --git a/test/Event.cxx b/tests/Event.cxx similarity index 100% rename from test/Event.cxx rename to tests/Event.cxx diff --git a/test/Event.h b/tests/Event.h similarity index 100% rename from test/Event.h rename to tests/Event.h diff --git a/test/Event.root b/tests/Event.root similarity index 100% rename from test/Event.root rename to tests/Event.root diff --git a/test/__init__.py b/tests/__init__.py similarity index 100% rename from test/__init__.py rename to tests/__init__.py diff --git a/test/big.root b/tests/big.root similarity index 100% rename from test/big.root rename to tests/big.root diff --git a/test/flat.root b/tests/flat.root similarity index 100% rename from test/flat.root rename to tests/flat.root diff --git a/test/testbasic.py b/tests/testbasic.py similarity index 96% rename from test/testbasic.py rename to tests/testbasic.py index da84200..685ec03 100644 --- a/test/testbasic.py +++ b/tests/testbasic.py @@ -104,7 +104,48 @@ def checkName(self, x): repr(x) def runTest(self): - pass + self.testCount() + self.testCountWithFilter() + self.testSum() + self.testSumWithFilter() + self.testSumWithWeightingFactor() + self.testSumStringFunctions() + self.testSumWithFilterStringFunctions() + self.testSumWithWeightingFactorStringFunctions() + self.testAverage() + self.testAverageWithFilter() + self.testAverageWithWeightingFactor() + self.testDeviate() + self.testDeviateWithFilter() + self.testDeviateWithWeightingFactor() + self.testMinimize() + self.testMaximize() + self.testBag() + self.testBin() + self.testBinWithSum() + self.testHistogram() + self.testPlotHistogram() + self.testPlotProfileErr() + self.testPlotStack() + self.testSparselyBin() + self.testCentrallyBin() + self.testFraction() + self.testFractionSum() + self.testFractionHistogram() + self.testStack() + self.testStackWithSum() + self.testIrregularlyBin() + self.testIrregularlyBinSum() + self.testCategorize() + self.testLabel() + self.testLabelDifferentCuts() + self.testUntypedLabel() + self.testUntypedLabelDifferenCuts() + self.testUntypedLabelMultipleTypes() + self.testIndex() + self.testIndexDifferentCuts() + self.testBranch() + # self.testAggregate() ################################################################ Count diff --git a/test/testgpu.py b/tests/testgpu.py similarity index 98% rename from test/testgpu.py rename to tests/testgpu.py index 6cadad7..6bb5071 100644 --- a/test/testgpu.py +++ b/tests/testgpu.py @@ -24,7 +24,7 @@ from distutils import spawn from histogrammar import * -from test.testnumpy import makeSamples +from tests.testnumpy import makeSamples tolerance = 1e-5 util.relativeTolerance = tolerance @@ -44,7 +44,22 @@ class TestGPU(unittest.TestCase): nvcc = spawn.find_executable("nvcc") def runTest(self): - pass + self.testCount() + self.testSum() + self.testAverage() + self.testDeviate() + self.testMinimize() + self.testMaximize() + self.testBin() + self.testCentrallyBin() + self.testIrregularlyBin() + self.testStack() + self.testFraction() + self.testSelect() + self.testLabel() + self.testUntypedLabel() + self.testIndex() + self.testBranch() SIZE = 10000 HOLES = 100 diff --git a/test/testnumpy.py b/tests/testnumpy.py similarity index 96% rename from test/testnumpy.py rename to tests/testnumpy.py index fbc43da..88d05af 100644 --- a/test/testnumpy.py +++ b/tests/testnumpy.py @@ -23,8 +23,6 @@ from histogrammar import * -import test.specification - tolerance = 1e-12 util.relativeTolerance = tolerance util.absoluteTolerance = tolerance @@ -83,7 +81,34 @@ def makeSamples(SIZE, HOLES): class TestNumpy(unittest.TestCase): def runTest(self): - pass + self.testSum() + self.testAverage() + self.testDeviate() + self.testMinimize() + self.testMaximize() + self.testBin() + self.testBinTrans() + self.testBinAverage() + self.testBinDeviate() + self.testSparselyBin() + self.testSparselyBinTrans() + self.testSparselyBinAverage() + self.testSparselyBinDeviate() + self.testCentrallyBin() + self.testCentrallyBinTrans() + self.testCentrallyBinAverage() + self.testCentrallyBinDeviate() + self.testCategorize() + self.testCategorizeTrans() + self.testFractionBin() + self.testStackBin() + self.testIrregularlyBinBin() + self.testSelectBin() + self.testLabelBin() + self.testUntypedLabelBin() + self.testIndexBin() + self.testBranchBin() + self.testBag() SIZE = 10000 HOLES = 100 @@ -107,8 +132,6 @@ def compare(self, name, hnp, npdata, hpy, pydata): hnp3 = hnp.copy() hpy2 = hpy.copy() hpy3 = hpy.copy() - hpy4 = hpy.copy() - hpy5 = hpy.copy() startTime = time.time() hnp.fill.numpy(npdata) @@ -145,14 +168,6 @@ def compare(self, name, hnp, npdata, hpy, pydata): d = float(d) h.fill(d) - for h in [hpy4, hpy5, hpy5]: - for d in pydata: - if isinstance(d, numpy.unicode_): - d = str(d) - else: - d = float(d) - test.specification.fill(h, d, 1.0) - assert (hpy + hpy) == hpy3 assert (hpy + hpy2) == hpy3 assert (hpy2 + hpy) == hpy3 @@ -170,11 +185,6 @@ def compare(self, name, hnp, npdata, hpy, pydata): assert Factory.fromJson((hnp + hnp2).toJson()) == Factory.fromJson((hpy + hpy2).toJson()) assert Factory.fromJson(hnp3.toJson()) == Factory.fromJson(hpy3.toJson()) - assert hpy2 == hpy4 - assert hpy3 == hpy5 - assert test.specification.combine(hpy2, hpy2) == test.specification.combine(hpy3, hpy3.zero()) - assert test.specification.combine(hpy2, hpy2) == test.specification.combine(hpy3.zero(), hpy3) - # Warmup: apparently, Numpy does some dynamic optimization that needs to warm up... if empty is not None: Sum(lambda x: x["empty"]).fill.numpy(data) diff --git a/test/testrootcling.py b/tests/testrootcling.py similarity index 97% rename from test/testrootcling.py rename to tests/testrootcling.py index fa15f2e..d418038 100644 --- a/test/testrootcling.py +++ b/tests/testrootcling.py @@ -40,13 +40,13 @@ class TestRootCling(unittest.TestCase): try: import ROOT - ROOT.gInterpreter.AddIncludePath("test/Event.h") - ROOT.gInterpreter.ProcessLine(".L test/Event.cxx") - tfileFlat = ROOT.TFile("test/flat.root") + ROOT.gInterpreter.AddIncludePath("tests/Event.h") + ROOT.gInterpreter.ProcessLine(".L tests/Event.cxx") + tfileFlat = ROOT.TFile("tests/flat.root") ttreeFlat = tfileFlat.Get("simple") - tfileBig = ROOT.TFile("test/big.root") + tfileBig = ROOT.TFile("tests/big.root") ttreeBig = tfileBig.Get("big") - # tfileEvent = ROOT.TFile("test/Event.root") + # tfileEvent = ROOT.TFile("tests/Event.root") # ttreeEvent = tfileEvent.Get("T") for row in ttreeFlat: @@ -59,6 +59,41 @@ class TestRootCling(unittest.TestCase): except ImportError: pass + def runTest(self): + self.testTiming() + self.testAAACount() + self.testAAASum() + self.testAAABin() + self.testAAASelect() + self.testSum() + self.testAverage() + self.testDeviate() + self.testMinimize() + self.testMaximize() + self.testBin() + self.testBinTrans() + self.testBinAverage() + self.testBinDeviate() + self.testSparselyBin() + self.testSparselyBinTrans() + self.testSparselyBinAverage() + self.testSparselyBinDeviate() + self.testCentrallyBin() + self.testCentrallyBinTrans() + self.testCentrallyBinAverage() + self.testCentrallyBinDeviate() + self.testCategorize() + self.testCategorizeTrans() + self.testFractionBin() + self.testStackBin() + self.testIrregularlyBinBin() + self.testSelectBin() + self.testLabelBin() + self.testUntypedLabelBin() + self.testIndexBin() + self.testBranchBin() + self.testBag() + ################################################################ Timing def testTiming(self): diff --git a/test/testspec.py b/tests/testspec.py similarity index 92% rename from test/testspec.py rename to tests/testspec.py index 930f46b..73e90f1 100644 --- a/test/testspec.py +++ b/tests/testspec.py @@ -18,7 +18,10 @@ import math import sys import unittest -import urllib2 +try: + from urllib2 import urlopen +except ImportError: + from urllib.request import urlopen from histogrammar import * import histogrammar.version @@ -44,12 +47,12 @@ def compare(self, x, y, name): def runTest(self): sys.stdout.write("Downloading expected results, generated by specification {0}...\n".format(histogrammar.version.specification)) try: - testdata = json.load(urllib2.urlopen("http://histogrammar.org/test/{0}/test-data.json".format(histogrammar.version.specification))) + testdata = json.load(urlopen("http://histogrammar.org/test/{0}/test-data.json".format(histogrammar.version.specification))) except Exception as err: sys.stdout.write("could not download http://histogrammar.org/test/{0}/test-data.json\nbecause of {1}: {2}\n".format(histogrammar.version.specification, err.__class__.__name__, str(err))) return try: - testresults = json.load(urllib2.urlopen("http://histogrammar.org/test/{0}/test-results.json".format(histogrammar.version.specification))) + testresults = json.load(urlopen("http://histogrammar.org/test/{0}/test-results.json".format(histogrammar.version.specification))) except Exception as err: sys.stdout.write("could not download http://histogrammar.org/test/{0}/test-results.jsonbecause of {1}: {2}\n\n".format(histogrammar.version.specification, err.__class__.__name__, str(err))) return