diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,1944 +1,1950 @@ +2019-06-06 Andy Buckley + + * Add xEdges and yEdges methods to the 2D Histo and Profile classes, in C++ and Python. + + * Remove @property attributes from Python xEdges methods. More to come... + 2019-05-26 Andy Buckley * Fix Python3/argparse attribute access bug in yodamerge. 2019-05-09 Andy Buckley * Release 1.7.5 2019-05-06 Andy Buckley * Convert bin/* scripts to use Python3-compatible argparse rather than old optparse. 2019-05-02 Christian Gutschow * Fix Histo1D::integralRange to include the second-argument bin content as described in the docstring. 2019-04-29 Andy Buckley * Fix Python3 StringIO import compatibility -- thanks to Tom Neep for the patch! 2019-03-05 Andy Buckley * Add -m/-M filtering to yodadiff. 2019-02-27 Andy Buckley * Fix HistoBin2D printing in Python interface. 2019-02-17 Jon Butterworth * Protect yodamerge against zero-valued (?!) ScaledBy attributes. 2018-12-10 Andy Buckley * Release 1.7.4 2018-11-16 Christian Gutschow * Roll out sameBinning methods for Profile1D and Profile2D. 2018-11-08 Christian Gutschow * Add sameBinning methods for Histo1D and Histo2D. 2018-11-08 Andy Buckley * Remove debug couts from single-AO Writer::write() function. * Add --ignore-missing and --ignore-new flags to yodadiff. * Tidy up point-comparison output of yodadiff. 2018-10-13 Christian Gutschow * Fix additional weighting in yodamerge 2018-09-24 Andy Buckley * Release 1.7.3 2018-09-12 Louie Corpe * Fix bug in multi-err point reader which was not parsing Variations correctly, and a minor typo where the err- was duplicated for the additional columns. 2018-09-06 Andy Buckley * Fix missing y and z components of Point2D and Point3D equality testing. 2018-09-04 Andy Buckley * Add array accessors of x,y,zMins/Mids/Maxs/Vals/Errs, etc. to Python Histo2D and Profile2D. 2018-08-30 Andy Buckley * Update embedded yaml-cpp to v0.6.0. * Convert xyzMin/Max properties to functions in the Python interfaces. * Return numpy arrays if possible in Python interface array methods. 2018-08-23 Andy Buckley * Release 1.7.2 * Add missing bin(i) method to Python Profile1D interface. 2018-08-22 Andy Buckley * Avoid const-overloading clash for binAt functions. 2018-08-14 Chris Gutschow * Merge Graeme Watt's modifications to yodadiff. 2018-08-14 Andy Buckley * Release 1.7.1 2018-08-08 Andy Buckley * yodadiff now supports quiet (-q) and list (-l) modes. 2018-06-01 Louie Corpe * Point1,2,3D now support multiple error sources for the highest dimension. * Scatter1,2,3D now read in/out with additional columns for the extra error sources, with a variations() method to check with sources are available 2018-05-02 Andy Buckley * StringUtils.h: Replace std::ptr_fun (removed in C++17) with a lambda function. Thanks to Stefan Richter. 2018-04-30 Andy Buckley * Add "-" = stdin/stdout recognition to C++ IO functions. * Convert remaining Python read/write methods to use the C++ IO functions. * Convert Python read/write methods with filename arguments to use the gzip-aware IO functions. 2018-04-27 Andy Buckley * Fix missing lock=false flag initialisation in Histo2D constructor from a Bins vector. * Improve axis locking error messages. 2017-12-21 Andy Buckley * Version 1.7.0 release 2017-12-11 Andy Buckley * Add Nentries printout to yodals -v 2017-09-18 Andy Buckley * Patches for ROOT conversion from Robert Hatcher -- thanks! 2017-09-16 Andy Buckley * Add YODA format version annotation, at version 2, and update YODA reader to use version info and multiline YAML EOF marker. * Write YODA annotations in YAML with a --- YAML break-line. 2017-09-14 Andy Buckley * Enable compressed writing from Python. 2017-09-13 Andy Buckley * Remove UNUSED macro in favour of anonymous args. * Enable zipped writing... but only works from C++ so far. 2017-09-11 Andy Buckley * Add HistoBin2D::area(), and provide a default normto=1.0 argument on the Python Histo2D.normalize() method. 2017-09-04 Andy Buckley * Change license explicitly to GPLv3, cf. MCnet3 agreement. * Parse YODA format AO headers as YAML (restriction to single-line dict entries for now). 2017-08-24 Andy Buckley * Use a slightly enhanced fast numeric parser in ReaderYODA (taken from LHAPDF, originally inspired by Gavin Salam). * Add an UNSCALE spec option to yodascale, to undo ScaledBy effects. 2017-08-19 Andy Buckley * Add optional zlib support via zstr -- massive thanks to Dmitry Kalinkin for the lovely patch! 2017-08-16 Andy Buckley * Fix setVal(i, x) numbered-axis methods on Point2D and Point3D: switch break statements were missing. * Explicitly load all ROOT objects as a list rather than generator. Patch from Dmitry Kalinkin. 2017-07-24 Andy Buckley * Improvements to yodaplot, including two operating modes: the default CMP mode is suitable for plotting histos by path, from raw .yoda files. * Update yoda.plotting functions to treat plot-keys as args and AO annotations via case-insensitive keys. * Add annotationsDict to the Python AO interface. * Add AO as an alias for AnalysisObject. 2017-07-23 Andy Buckley * Add parallel/compatibility yoda1 package to aid eventual transition to YODA v2. 2017-07-22 Andy Buckley * Add x,y,zMins and Maxs to all 1D data types and scatters (and x,yMin/Max to the scatters) -- Python interface only. * Rework some of the yoda.plotting tools, making it a bit more compatible with user-scripted matplotlib. 2017-07-18 Andy Buckley * Add convenience aliases H1D, H2D, P1D, P2D, and S1D, S2D, S3D for the HistoXD, ProfileXD, and ScatterXD classes respectively. 2017-07-08 Andy Buckley * Add xyVals/Errs and other 'bin array property' accessors to the Python Histo1D and Profile1D types: important for connection to matplotlib. 2017-06-28 Andy Buckley * Use Python natsort library to sort yodals output if available. 2017-06-18 Andy Buckley * Version 1.6.7 release. 2017-05-12 Andy Buckley * pyext/yoda/rootcompat.pyx: Fix ordering of TH1 vs. TProfile conversion -- TProfile *is* a TH1, so we have to test for the more specific type-match first. Thanks to Dmitry Kalinkin for the patch. 2017-05-02 Andy Buckley * Add static Reader methods to match the Writer ones. 2017-02-23 Andy Buckley * Fix Histo2D and Profile2D total distribution reading from YODA format. 2017-02-19 Holger Schulz * Convert TH1F to TH1D in root2flat. Much simpler than duplicating the TH1D stuff in pyext. 2016-12-13 Andy Buckley * Version 1.6.6 release. 2016-12-12 Holger Schulz * Bugfixes in Cython bins accessors for Histo2D. 2016-11-17 Leif Lonnblad * Fixed warning messages about the obsoleteness of AIDA so that the scripts actually still work. 2016-09-28 Andy Buckley * Version 1.6.5 release, for the benefit of ROOT fans. * Fix handling of --enable/disable-root configure options. 2016-09-26 David Grellscheid * Improvements to Cython version testing. 2016-09-25 Andy Buckley * Version 1.6.4 release. 2016-09-20 David Grellscheid * Remove aliases for @property functions. They were scheduled for removal anyway, and don't work with Cython >= 24. 2016-09-06 Andy Buckley * Update configure scripts to use newer (Py3-safe) Python testing macros. 2016-08-09 Andy Buckley * Version 1.6.3 release! 2016-07-22 Andy Buckley * Add 'add' modes for scatter combination to yodamerge. * Fix yodamerge scatter averaging to use the first AO. 2016-07-21 Andy Buckley * Add --type-mismatch-mode flag and fallback logic to yodamerge. * Fix yodamerge logic to handle cases where an AO only appears once. 2016-07-19 Andy Buckley * Deprecate flat2yoda script and add warning output to it and the AIDA conversion scripts. * Add a convenience yoda2yoda script. 2016-07-14 Andy Buckley * Try to build PyROOT interface by default, if root-config is found. 2016-07-11 Andy Buckley * Remove accidentally remaining reference to Boost flags in yoda-config. 2016-07-06 Andy Buckley * Version 1.6.2 release! 2016-07-05 Andy Buckley * Pass the toNewScatter3D() scalebyarea flag to the called toScatter3D() functions. 2016-06-06 Andy Buckley * Re-enable the disabled-for-some-reason Scatter1D combineWith Python mappings. 2016-04-28 Andy Buckley * Version 1.6.1 release! * Add a unit test for annotation handling correctness. * Fix numerical precision of string storage of floating-point attributes. * Fix a bug in use of the replacement for lexical_cast. 2016-04-20 Andy Buckley * Version 1.6.0 release! 2016-04-16 Andy Buckley * Extend SFINAE craziness to allow writing of any object (e.g. smart pointer) that can be dereferenced to something that has AnalysisObject as its base class... and also to any container of them! Amazing what you can do with C++11! 2016-04-14 Andy Buckley * Add a few consts to the arguments in Scatter error setting via pairs. * Fix double-writing of minus errors in WriterYODA for Scatter1D and Scatter3D. Thanks to Graeme Watt for the report and fix. 2016-04-12 Andy Buckley * Remove Boost dependency and require C++11 compilation. 2016-04-08 Andy Buckley * Add a --guess-prefix flag to yoda-config, cf. fastjet-config. 2015-12-20 Andy Buckley * Change AO uncomputable division and mkScatter operations to return/set NaN rather than 0 -- behaviour change requires new major version series 1.6. 2016-03-09 Andy Buckley * Version 1.5.9! (oh no, we're out of convenient version number space!!) 2016-03-08 Andy Buckley * Add abs function to eq calculation in yodadiff. 2016-02-29 Andy Buckley * Remove blocking of builds against ROOT6 -- it works fine. 2016-02-16 Andy Buckley * Add a --add option to yodamerge, for simple histo stacking. Thanks to Chris Gutschow for the patch, although my spidey sense is tingling... 2015-12-21 Andy Buckley * Version 1.5.8! * Add a rebinning unit test, pytest-rebin. * Add optional range arguments to rebinBy methods, allowing block rebinnings to be applied only within a range of (original) bin indices. * Add missing root.py submodule file. Oops! 2015-12-20 Andy Buckley * Convert linspace to use multiplication rather than repeated addition to construct edge values, reducing precision errors. Thanks to Holger Schulz for the suggestion. 2015-12-15 Andy Buckley * Add xEdges() methods to Axis1D and the Histo1D and Profile1D that use it. The returned edge lists are finite only, i.e. they do not contain the +-inf values on the ends of the internal BinSearcher edges. 2015-12-13 Andy Buckley * Version 1.5.7! * Extend batch-adding in ReaderYODA to include Scatter types. * Add a match_aos function to Python, for filtering AO lists/dicts on path patterns and anti-patterns. 2015-12-12 Andy Buckley * Add a flag to yoda2root to change whether the conversion is to 'proper' types or to (more robustly) TGraphAsymmErrors objects. * Fix accidental use of S2D_MODE flag where S1D_MODE should have been used, in yodamerge. Thanks again to Radek Podskubka. * Allow new rebinTo() merging to restrict to a subset of the bin range, merging the outside bins into the overflow distributions. 2015-12-11 Andy Buckley * Add a rebinTo() method on Axis1D, allowing rebinning to a new given set of bin edges. Add an explicitly named rebinBy(), and overloaded rebin() aliases for both, and pass through to Histo1D and Profile1D APIs. Plus other internal tweaks to binning functionality... anticipating/fuelling the fundamental rewrite. 2015-12-10 Andy Buckley * Improve ReaderYODA to use temporary bin containers, to minimise calling sort when adding bins to histos. A quick test suggests this has sped up big file reading by a factor of 30 or so!!! * Add missing addBins() operators (only in C++ so far) to Histo and Profile classes. * Fix Counter::numEntries to return an unsigned long rather than double. Thanks to Radek Podskubka for the bug discovery and detective work. * Improve sortedvector to insert new elements into the sorted position, rather than resorting the whole vector. This should be a bit more efficient, but I think the asymptotic complexity is the same. Might help a bit with reading big data files. 2015-12-04 Andy Buckley * Add yoda.HAS_ROOT_SUPPORT flag, for API user convenience. 2015-11-22 Andy Buckley * Version 1.5.6! * Make AO path setting and retrieval prepend a leading slash if it is missing (unless the path is completely empty). 2015-11-21 Andy Buckley * Add root2yoda conversion script. * Deprecating yoda.to_root() in favour of yoda.root module, which contains to_root and to_yoda functions, as well as a ROOT file walking function. 2015-11-17 Andy Buckley * Map ROOT-to-YODA (as scatter) functions to Python. Phew. * Map new to-ROOT functions, including TGraph ones, to Python. 2015-11-16 Andy Buckley * ROOTCnv.h: Add toScatter3D ROOT->YODA, and toNew* YODA->ROOT conversion routines. * ROOTCnv.h: Fix bug in toTH2D(const Histo2D& h) as used with ROOT6. Thanks to Tim Martin. 2015-11-05 Andy Buckley * Fix double-dealloc in new Point class hierarchy Python mapping. 2015-10-23 Andy Buckley * Make the version() function inline, and the numerical constants static. * Change the default plotting backend to MPL rather than the much slower PGF. 2015-10-09 Andy Buckley * Reinstate __getitem__ special methods for Scatters in Python. * Provide dim() methods/attributes for the Point and Bin base classes. * Rename set*Err to set*Errs for the asymmetric variants. Plural aliases are also provided for the symm case. 2015-10-08 Andy Buckley * Pass std::pairs by reference in Point*D error setting functions. * Add Point base class with generic accessors to Point*D properties via an integer axis ID argument. 2015-10-07 Andy Buckley * Version 1.5.5 release. * Counter.pyx: Typo fix in sumW mapping. * yodamerge: Re-add checking for non-emptiness before merging, in case the empty ones are missing a ScaledBy attribute. Won't normally apply to Profiles, since they don't usually get normalised, but we might as well include them in the vetoing since empty histos don't contribute to the merging. Added a command-line option to disable this heuristic since in very strange situations a null sumW does not mean no fills. 2015-10-06 Andy Buckley * Version 1.5.4 release. * ReaderYODA: Typo fixes in Counter filling of sumW and Scatter3D reader state flag. * yodamerge: add merging heuristics for Scatter1D and Scatter3D (needs unification) 2015-10-05 Andy Buckley * yodamerge: add a fix for empty-in-all-runs histo merging; thanks to Daniel Rauch. 2015-10-04 Andy Buckley * Adding dim() function and corresponding Python attribute to AnalysisObject. * Map Counter arithmetic operations into Python. * Map Counter mkScatter() into Python (as bound method). * Add a YODA::version() function, mapped into Python and used to set the yoda.__version__ variable. 2015-10-01 Andy Buckley * Expose the yoda.plot() Python function in a way that doesn't automatically induce a dependence on matplotlib. 2015-09-30 Andy Buckley * Fix yodals to work with Counters. 2015-09-23 Andy Buckley * Version 1.5.3 release. * Update Boost version requirement to 1.48, due to use of type_traits/has_dereference, and add a check for that feature's header. 2015-09-19 Andy Buckley * Further improvements to handling leading _multiple_ # marks on YODA format BEGIN lines. 2015-09-11 Andy Buckley * Version 1.5.2 release. * Tolerate leading # symbols without separating whitespace on BEGIN lines in YODA format parsing. * Further improvements to handling LowStatsErrors in YODA format writing. * Fix shadowed variables that made ReaderYODA unhappy. 2015-09-03 Andy Buckley * Version 1.5.1 release. * Fix bugs in Python wrapper for Point3D. 2015-08-28 Peter Richardson * Catch LowStatsError when writing multiple histograms so only the histogram with the problem is not written 2015-08-28 Andy Buckley * Version 1.5.0 release. 2015-08-24 Andy Buckley * Improve protection of efficiency calculation against the weird world of general weighted events. 2015-08-17 Andy Buckley * Add some protection against calling matplotlib's legend() method if there are no valid labels to display, to suppress an MPL warning message when using yoda.plot(). 2015-08-12 Andy Buckley * Fix cut & paste typo, and add LowStatsError catching in Profile division. 2015-08-11 Andy Buckley * Replace old Spirit-based ReaderYODA with the new hand-rolled one. * Adding filling of Histo1D, Profile1D, Histo2D and Profile2D in new ReaderYODA. More hacking of Axis and Histo/Profile interfaces... needs clean-up, and infinite binning implementation. 2015-08-07 Andy Buckley * Convert the ReaderFLAT parser to also use a simple hand-written parser rather than Spirit. 2015-08-04 Andy Buckley * Add methods for Counter, Axis and Histo1D internal state access/setting, mainly for new persistency. NEEDS PRE-RELEASE TESTING!!! 2015-07-30 Andy Buckley * Remove # markers from YODA format BEGIN/END output. The parser will continue to accept them. 2015-07-29 Andy Buckley * Add SFINAE trait magic to restrict write(RANGE) functions to accepting iterables. Also generalising to allow either container-of-objects or container-of-pointers args by providing a writeBody(AO*) function to complement writeBody(AO&). Based on a patch from Lukas Heinrich. * Add configuration of output streams to throw exceptions on bad/fail state (based on patch from Lukas Heinrich). 2015-07-01 Andy Buckley * 1.4.0 release. 2015-06-30 Andy Buckley * More tweaks to yodamerge: adding control of S2D merging strategy, and now performing weighted normalized histo merges without reference to an absolute normalization. * Change yodamerge norm-detection heuristic to just look for a ScaledBy attribute rather than fuzzily compare norms. 2015-06-26 Andy Buckley * Removing add, subtract, and divide functions and operators on Scatter types, and re-implementing Histo and Profile divide functions explicitly rather than via mkScatter. Also removed from the Python interface. The combine() methods remain. 2015-06-24 Andy Buckley * Adding workaround versions of binAt to all the Python histo types (for some reason the direct mapping that works for bin(i) produces a compile error for binAt(x) :-/ 2015-06-23 Andy Buckley * Renaming, tidying, completing, etc. the Python-mapped methods on Bin1D and Bin2D. * Rename Python Histo2D mean, variance, etc. pair-returning methods to xyMean, xyVariance, etc., to distinguish from Profile2D mean, variance, etc. * Add Python mappings of all the methods below. * Add full set of {x,y}{Mean,Variance,StdDev,StdErr,RMS} to 1D and 2D binned distributions. * Add optional includeoverflows=True argument to all binned AO numEntries and effNumEntries. * Fix type of numEntries to always be unsigned long. 2015-06-18 Andy Buckley * Fix typos in Point3D Python mapping (accidentally trying to get the ptr via _Point2D rather than _Point3D). 2015-06-13 Andy Buckley * Adding an AnalysisObject::name() method, to return the last part of the path. Mapped into a Python property. * Adding an optional usestddev argument to mkScatter for profile types, so the error bars can represent distribution width rather than uncertainty on the mean. Mapped to Python. 2015-06-08 Andy Buckley * Adding unpatterns arguments to Python read functions, and auto-conversion from single strings and re.compile()d strs. 2015-06-04 Andy Buckley * Add binAt(x,y) and binIndexAt(iglobal) Python methods for 2D histos. Still want a way to get and pass a pair of bin indices, I think. * Adding includeoverflows optional args for Histo1D (eff)numEntries. * Adding Rename Histo1D integral() methods as integral(), integralRange(), and integralTo(), and mapping to Python. 2015-06-02 Andy Buckley * Adding missing binAt and binIndexAt methods to Histo1D and Profile1D, plus other minor Python mapping tweaks. * Add a regex pattern match optional argument to the IO.read() Python functions, for pre-emptive filtering. 2015-03-27 Andy Buckley * Fix a harmless possibility to raise an FPE exception in the BinSearcher. Thanks to Leif Lonnblad for the discovery, debug and patch! 2015-03-19 Andy Buckley * Bump version for 1.3.1 release. 2015-03-06 Andy Buckley * Adding usefocus optional argument to some mkScatter functions, plus the Python bindings. * Cleaning up some Python mappings of 2D histogram bin classes. * Removing mappings of bin-level fill and scale operations in Python. * Fix formatting and error handling in Python Bin and Dbn __repr__ methods. * Add a -i/--in-place option pair on yodascale. 2015-02-05 Andy Buckley * Convert script matching options to use re search rather than match. * Adding matching options and verbose option to yodals. 2015-01-27 Andy Buckley * Improvements and additions to ROOTCnv.h routines, particularly to TProfile creation: thanks to Roman Lysak for advice. 2015-01-16 Andy Buckley * Add convenience YODA/YODA.h header. 2015-01-15 Andy Buckley * yodascale now uses PointMatcher and can normalize or multiply to abs values or ref histos/bin ranges. 2015-01-05 Andy Buckley * Adding yoda.matcher Python sub-package with PointMatcher functionality. To be used in Professor 2.0 and in yodascale. * Adding 'scat2' type to yodahist. * Add match/unmatch args to all conversion scripts, via a new Python yoda.script_helpers function. * Script updates, improved docstrings, and improved tab completion. 2014-12-10 Andy Buckley * Add a yoda.plotting sub-module, based on matplotlib. 2014-12-03 Andy Buckley * Small build improvements: cleaning test1.root from the yoda2root test, and adding a make target & flag file for mktemplates in pyext/yoda to make sure that it only gets run once. 2014-11-25 Andy Buckley * Handle overflow filling in binned types without invoking an exception. * Change inRange to have non-fuzzy comparison behaviour. 2014-11-11 Andy Buckley * Improving/adding __div__ functions in Python for all binned types. * Add std:: prefix to isinf() calls in BinSearcher.h. 2014-09-30 Andy Buckley * 1.3.0 release! * Use numEntries() rather than effNumEntries() when checking consistency of inputs to efficiency() calculations -- the effNumEntries of a set can be smaller than that of a strict subset, surprisingly! 2014-09-17 Andy Buckley * Small improvements to yodahist and yodaplot behaviours/UIs. * Adding setX/Y/Z(val, err) methods to Point3D. * Add an efficiency method for 2D histos. * Hide fill and fillBin methods from Python mappings of bin types. 2014-09-01 Andy Buckley * YODA 1.2.1 release! 2014-08-29 Andy Buckley * Hide non-const access to bin objects from histogram users: avoids potential for inconsistency between total dbns and in-range bins. * Bug in BinSearcher fixed by Peter Richardson: constructor arguments were passed in the wrong order when constructing a LinEstimator in cases where log binning wouldn't be allowed. 2014-08-26 Andy Buckley * Add protection against / characters in histo names in yoda2root (thanks to Will Bell for the report and suggested patch). 2014-08-17 Andy Buckley * Add +=, -=, *-, /=, ++ and -- operators to Counter, along with an (implicit) constructor from a double -- all for user convenience so Counter can be used in lieu of a simple number. 2014-08-15 Andy Buckley * YODA 1.2.0 release! * Permit +-inf values to be filled into histograms; NaN fills will still explicitly throw an exception. * Add unit tests for Counter, Scatter1D, and Scatter2D, including persistency. * Adding YODA and FLAT format I/O for Scatter1D and Counter (as far as currently possible -- FLAT Counter can't be read due to a #item ambiguity, just like the one between the YODA format Point3D and ProfileBin1D). To be continued... 2014-08-14 Andy Buckley * Python mappings for Dbn0D and Counter, and other improvements. * Adding val() and err() methods to Counter, and errW() and relErrW() to all DbnXD types. * Adding Scatter1D and Point1D types, with conversion from Counter supported. Both Counter and Scatter1D still need to be supported by YODA persistency. 2014-08-11 Andy Buckley * Add ROOT version checking to configure. Thanks to Michael Grosse for the report/request. 2014-08-05 Andy Buckley * Remove all methods not specific about the axis to which they refer, e.g. Histo1D::mean -> xMean. Also remove all related aliases (a nightmare to maintain) and low/highEdge and midpoint functions: use the proper xMin/Max/Mid from now on. This is a significant compatibility breaking API change (and the decision was not taken lightly) so will require a 2nd digit version change. * Lots of adding xMin/Max etc. functions to C++ and Python bin/histo classes. * Compiler pickiness fixes in BinSearcher. * Improvement to linspace, avoiding fuzzyEquals and again making sure that the end value is exact. 2014-07-23 Andy Buckley * Fix to logspace: make sure that start and end values are exact, not the result of exp(log(x)). * Clean-up, minor improvements, and adding a test for BinSearcher and friends. 2014-07-19 Andy Buckley * Various consistency improvements and minor bugfixes to Python mapping utils and Dbn and Bin objects. * Fix Axis2D::reset, which was resetting the total dbn and outflows, but not the bins!!! Thanks to Ewen Gillies for the report. 2014-07-18 Andy Buckley * Add scaleX,Y,Z and scaleXYZ to Point and Scatter classes, and deprecate less explicit/consistent Scatter2D/3D.scale method. 2014-07-17 Andy Buckley * yodascale now writes out rescaled histograms and profiles rather than scatters. * A few more improvements on Point2D/3D, adding x,y,zMin/Max function mappings. * Add first version of a yodascale script, based on code from Simone Amoroso. 2014-07-16 Andy Buckley * More Scatter and 2D histo interface improvement. * Remove 'return *this' from Scatter2D/3D add and combine methods. * Add unit test checks for 1D and 2D mkScatter functions. * Improve Scatter2D/3D C++ and Python interfaces. * Add Scatter3D Python mapping. 2014-07-15 Andy Buckley * Add auto-parsing of yes/no/on/off/true/false as bools in the Python ao.annotation() function. * Add parsing of yodaplot styles from command line args and analysis object annotations. 2014-07-12 Andy Buckley * Fix infinite recursions in Python wrappers for Point2D and Point3D, and make the Python Point3D interface more standard. * Add yodaplot script for basic plotting, using pgfplots as a backend. 2014-07-10 Andy Buckley * Add mkScatter(Scatter2D) and mkScatter(Scatter3D) functions and Python mappings: this allows all AOs to be used as args to mkScatter(...) without needing to check if they already are scatters. 2014-07-02 Andy Buckley * Set y value and/or error to 0 in mkScatter(Histo1D) if an exception is thrown when calculating the appropriate values. Need an optional param to control this error handling behaviour between set-zero and skip-bin? 2014-07-01 Andy Buckley * Add exception translation to the mkScatter functions. * Add -m/-M match/unmatch options to yodacnv -- useful for filtering histogram file contents in a YODA->YODA conversion. 2014-06-24 Andy Buckley * Don't complain about merge assumptions if there is only one object with that path name to be 'merged' 2014-06-17 Andy Buckley * Adding explicit int cast in Python wrapping of numEntries functions. 2014-06-13 Andy Buckley * Adding yodals script to list data file contents. 2014-06-11 David Grellscheid * pyext/yoda/Makefile.am: 'make distcheck' and out-of-source builds should work now. 2014-06-10 Andy Buckley * Fix use of the install command for bash completion installation on Macs. 2014-06-06 Andy Buckley * YODA 1.1.0 release. Middle version number change to reflect API changes w.r.t 1.0.6. * Adding unit tests against ref data for yodamerge in make check. 2014-06-04 Andy Buckley * Fix silly typos in yodamerge which somehow made it past "make check" testing :-( 2014-06-02 Andy Buckley * YODA 1.0.7 release. DO NOT USE: prefer 1.1.0, above. 2014-05-30 Andy Buckley * Removing 'foreach' macro definition and using raw BOOST_FOREACH instead until C++11 is allowed. * Adding pytest-p1d and pytest-p2d tests, and FLAT writing/reading in pytests. * Tweaking WriterFLAT and adding ReaderFLAT functionality for 2D histos and profiles. 2014-05-30 Holger Schulz * Some basic (FLAT) write-out capability for 2D histos 2014-05-29 Andy Buckley * Improvements to the yodahist script, including support for 2D histograms and input files. * Adding bin edges constructors for all 1D and 2D histos in Python. 2014-05-22 Andy Buckley * Improvements to Profile2D and Point2D interfaces in Python. * Add a single-file at a time yodacnv multi-format converter script (thanks to Andrii Verbytskyi for the suggestion). 2014-05-19 Andy Buckley * Typo fixes in Profile2D YODA-format parsing: 2D histo tests now pass! * Adding Python tests for Histo2D and Profile2D. * Adding a YODA/Predicates.h header and using it in Axis2D bin edge construction. * Enabling Profile2D writing in various Writers, and a bit of IO code tidying. 2014-05-17 Andy Buckley * Disable writing out of Histo2D and Profile2D outflows for now, while they are redesigned, and get 2D I/O working for the in-range part. 2014-05-14 Andy Buckley * Mapping the divide and efficiency functions into the Python interface as class methods, including the __div__ special function. 2014-05-13 Andy Buckley * Add the AnalysisObject::type() method back in Python (even though type(ao) is more Pythonic, this may be useful) 2014-05-06 Andy Buckley * Add Profile2D YODA format writing, note need for Scatter format change, add sumXY storage to both 2D histo types. 2014-05-03 Andy Buckley * Adding YODA reader functionality for Histo2D and Profile2D, but without outflows support yet. 2014-04-25 Andy Buckley * Adding simple command line yodahist script for quick 1D histogramming from plain text files, with weight support. More development to come! * Mapping linspace, logspace and a few stat functions into Python. 2014-04-24 Andy Buckley * Fixes, script installation, and detailed numerical comparisons in yodadiff. 2014-04-17 Andy Buckley * Change AnalysisObject::annotations to return the list of annotation keys rather than the map, since the previous behaviour mapped very badly into Python. 2014-04-16 Andy Buckley * Add special case handling for 2-arg use of x2y scripts where the second arg is -, for stdin. This will be treated as writing out to stdout, not converting two files one of which is stdin. 2014-04-15 Andy Buckley * Adding a more portable version of getline to be used in the YODA file parsing to avoid falling over on DOS-produced input files. 2014-04-14 Andy Buckley * Adding the namespace protection workaround for Boost described at http://www.boost.org/doc/libs/1_55_0/doc/html/foreach.html 2014-04-13 Andy Buckley * Adding an assumed-equal-run-size, ratio-like merging heuristic for Scatter2Ds to yodamerge, and renaming the --normalize-all flag to --assume-normalized. * Adding and installing a pkg-config data file for YODA. * Rationalising (and fixing?) the yodamerge logic re. user & normalization scalings, and making way for a Scatter2D merging heuristic. 2014-03-10 Andy Buckley * YODA 1.0.6 release. 2014-03-06 Andy Buckley * Improvements to AnalysisObject annotation handling in Python. * Adding rescaling arguments to yodamerge (and scale function to Python Scatter2D). * Better documentation and consistency of Histo and Profile Python wrappers, and removing some inappropriate attributes. * Adding clone() and newclone() functions to all analysis object classes. 2014-02-28 Andy Buckley * Cython mapping improvements, esp. adding numPoints/numBins functions and better Scatter2D __repr__. * Adding mapping of the mkScatter functions into Python (as methods on Histo1D and Profile1D rather than the original free functions, at least for now: some Python type-identifying boilerplate is needed to make a single mkScatter function work in Python) 2014-02-27 Leif Lönnblad * Minor modifications to BinSearcher to avoid NaN's. The NaN's were treated correctly before, but better to avoid them all together. 2014-02-27 Andy Buckley * Adding the generated pyext/yoda/rootcompat.cpp to the tarball and sorting out the ROOT/Cython interface conditionals a bit more sanely. Thanks to Oldrich Kepka for the bug report. * Protecting yodamerge against input histograms with zero integrals (thanks to Christian Bierlich for the bug report). 2014-02-14 Frank Siegert * Fix race condition with mktemplates. 2014-02-12 David Grellscheid * Fix bug in mktemplates code (thanks to Christian Johnson for the bug report). 2014-02-09 Andy Buckley * Adding explicit include/generated dir creation to Python extension build (thanks to Christian Johnson for the bug report). 2014-02-06 Andy Buckley * 1.0.5 release! 2014-02-05 Andy Buckley * Adding patches to ReaderFLAT and ReaderYODA use of Boost Spirit which reduce the Boost version requirement from 1.47 -> 1.41. Thanks to Andrii Verbytskyi for the patch. * Protect against invalid prefix value if the --prefix configure option is unused. 2014-02-04 Andy Buckley * Adding copy assignment operators where missing, based on an implementation in AnalysisObject which only copies rvalue paths and titles if they are non-null. 2014-02-03 Andy Buckley * Improving (i.e. increasing) bin edge overlap tolerance: 1e-10 relative was too tight. 2014-01-31 Andy Buckley * Adding x/yMid etc. methods on Bin1D and 2D, and more related Python API improvements. 2014-01-28 Andy Buckley * Adding missing fillBin methods to 1D and 2D Histo/Profile Python classes. * Fixed yodamerge default output file name treatment. * Avoid computing an unrecoverable error in Histo1D.__repr__ * Clean-ups and API improvements in Python IO functions. * Adding more sumW,W2 and (eff)NumEntries attrs to Python objects. 2013-12-17 Andy Buckley * Improved argument handling for x2y scripts. 2013-11-16 Andy Buckley * Fix to build the Cython rootcompt extension .cpp on request. 2013-11-14 Andy Buckley * Adding flags for the C++11 or C++0x standard if supported, cf. Rivet. 2013-10-24 Andy Buckley * YODA 1.0.4 release. * Supporting zsh completion via bash completion compatibility. 2013-10-21 Andy Buckley * Removing unused internal iterator typedefs from Writer functions. 2013-10-18 Andy Buckley * Adding a yodaenv.sh sourceable script to help with environment setup. * Remove Scatters from being handled by yodamerge by blocking the __add__ method fallback. 2013-10-09 Andy Buckley * Improvements to yoda-config and command-line completion, for the Rivet 2.0.0 release. 2013-10-09 Andy Buckley * Version 1.0.3 release. 2013-10-04 Andy Buckley * Cython mapping improvements. * Adding some improved heuristics and a --normalize-all option to yodamerge. Frank S is now happy again ;-) 2013-10-01 Andy Buckley * Adding operator +, -, +=, -= Python mappings wherever possible for Histo1/2D, Profile1/2D, and Scatter2D. 2013-09-26 Andy Buckley * Cython is no longer needed by tarball users. 2013-09-25 Andy Buckley * Unset path of returned histogram if those of the args to add() and subtract() are difference. 2013-09-24 Andy Buckley * Python mapping improvements. 2013-09-23 Andy Buckley * Add the -avoid-version flag to libtool. * Adding more add and subtract special methods in Python. 2013-09-22 Andy Buckley * mkScatter schanged to use histo midpoints rather than focuses by default for the point x value. 2013-08-14 Andy Buckley * Version 1.0.2. * Some exception message improvements and improving the protection of cosmetic mean calculations in WriterYODA. 2013-07-12 Andy Buckley * Adding ROOT detection in configure and otherwise updating Dave's rootcompat module so that it'll compile. There might be an inconvenient ROOT version dependency in the signature of one of the PyROOT API functions that is used as a shim :-( 2013-06-17 Andy Buckley * Adding yoda.m4 from James Robinson. 2013-06-06 Hendrik Hoeth * Improve "==" operator in Axis1D and Axis2D 2013-06-06 Andy Buckley * Adding fillBin() methods to all 1D and 2D histos, and noting that Bin types need a back-link to their axis to maintain consistency. * Release of version 1.0.1 2013-06-05 Andy Buckley * Change the divide(Scatter, Scatter) behaviours to use the midpoint of the num/denom bins rather than mean of foci for the output point position (and hence errors, too). * Adding a toIntegralEfficiencyHisto function. * Adding another Histo1D::integral() function, this time from 0 -> i, maybe including the underflow. 2013-06-04 Andy Buckley * Updating the Cython version requirement to 0.18 2013-06-03 Andy Buckley * Adding relErr functions to 1D and 2D histo and profile bins, and being careful about div by zero. * Improvements in error treatment in division (better handling of zeros). * Renaming merge-histos to yodamerge and installing it (and improving the usage string a bit). 2013-05-31 Andy Buckley * Adding the Counter type, and ability to output it from the YODA writer. * Adding numEntries and effNumEntries methods to 1D and 2D Histo and Profile classes. * Adding Dbn0D and using it to implement Dbn1D. 2013-05-30 Andy Buckley * Fixing several nasty errors in argument ordering for Point{1,2,3}D construction in Scatter addPoint functions. * Adding abs(...) to the returned Dbn1D::variance(), to avoid problems when negative weights produce negative variance. No, we don't like this either: is there a more correct way? * Fixing the efficiency(Histo1D, Histo1D) implementation, cf. http://root.cern.ch/phpBB3/viewtopic.php?t=3753 * Adding mkScatter(Profile2D) 2013-05-29 Hendrik Hoeth * Adding a reader for FLAT files and a flat2yoda converter 2013-05-27 Andy Buckley * Adding a yoda-completion file for bash. 2013-05-17 Andy Buckley * Mapping HistoBin1D.relErr in Python. * Adding a non-const points() accessor to Scatter2D. 2013-05-13 Andy Buckley * Adding combined value+error setX/Y functions on Point2D. * Adding HistoBin1D::relErr() 2013-04-23 Andy Buckley * Adding Python output handling for single AOs and to be able to use a "-" filename to mean stdout. 2013-04-12 Andy Buckley * Releasing version 1.0.0 -- it seems stable enough. 2013-04-10 Andy Buckley * Being more careful about adding -Wno-* flags to the C++ compiler used to built the Cython extension lib. 2013-03-22 Andy Buckley * Removing the use of svn:external to pull in Boost macros and using a minimal local set instead. * Using the nice Boost-finding macros from https://github.com/tsuna/boost.m4 and tidying up configure.ac 2013-03-15 Andy Buckley * Re-organising the C++ side of the auto-format I/O functions, into a new IO header and separated from the Reader.h and Writer.h. I'm tempted to say that users shouldn't really NEED to ever directly touch the Reader and Writer objects... * Adding auto-format read and write functions. I will probably change the API. Python mappings have been provided, but the string workarounds were too much of a pain with Cython 0.16 so I have updated the Cython version requirement to 0.17 where it is automatic and hence much cleaner. 2013-03-08 Andy Buckley * Making the x2y converter scripts write a copy into the *current* directory if only the input is specified. 2013-03-05 Andy Buckley * Removing Plot entirely from YODA: it was an anomaly only added to make plot file generation easy, but this is now done better via StringIO (in new compare-histos/rivet-cmphistos). * Removing the Plot from Cython... and soon from YODA itself: we'll do this stuff manually and less hackily. * Make Cython automatically add a copy of the original call signature to each function's docstring. 2013-03-04 Andy Buckley * Adding Plot mapping to Cython and improving the AO annotations handling in Python. * Adding PLOT section writing to WriterFLAT (and WriterYODA, although that might be a bad idea...) * Adding aida2yoda and aida2flat converter scripts. 2013-02-02 David Mallows * Adding support for Python >= 2.4 (was Python >= 2.6) * Fixing miscellaneous warnings on GCC 4.1 2013-01-30 Andy Buckley * Adding a points() method to the Python Scatter2D wrapper. * Adding a virtual destructor to Bin. 2012-12-30 Andy Buckley * Adding support for Boost.Range arguments and file format autodetection in Writer. 2012-11-24 Andy Buckley * Bump version to 0.6beta0 * Adding more ROOT converters. Who knows how to make TProfiles from scratch, but Histo1D and Scatter2D are covered, which should be enough to get started with, at least. 2012-11-16 Andy Buckley * Adding yoda-config 2012-11-16 Hendrik Hoeth * Adding WriterFLAT and yoda2flat 2012-11-16 Andy Buckley * Adding YODA/ROOTCnv.h. for data object converter functions. Two (untested) functions added for TH1 -> YODA. * Adding toIntegralHisto(Histo1D&) function. 2012-11-15 Dave Mallows * Commited numerous changes to Axis2D. Axis2D now uses BinSearcher as with Axis1D. 2012-11-15 Andy Buckley * Improving division and efficiency treatments, and allowing arbitrary f(x), f(y), and flip transformations on Scatter2D. 2012-11-14 Andy Buckley * Converting linspace, logspace, and their usage to place the nbins argument first. 2012-08-07 Andy Buckley * Removing unused (beyond 2nd order) sumWXYZ counter from Dbn3D. 2012-08-07 Dave Mallows * Converted Axis1D to use new Utils/BinSearcher. 2012-08-02 Dave Mallows * Heavily refactored Cython bindings * HistoBin1D, ProfileBin1D etc. now inherit from Bin1D[DBN] * Temporarily removed Histo2D, Profile2D and Scatter3D mappings. 2012-07-23 Andy Buckley * Installing scripts from bin dir, and making the yoda2aida interface nicer. * Adding Cython mappings for Dbn3D and Profile2D, and other fixes/improvements. 2012-07-22 Andy Buckley * Adding Cython mappings for Scatter3D and ProfileBin2D. * Fixing more crap code legacy from old 2D plot implementation, this time in Scatter3D. 2012-07-19 Andy Buckley * Adding stdErr for Histo2D + Python mapping, and more Cython improvements. * Adding path/title-only AO constructors and making nice Python constructor for Histo2D. * Cython mapping improvements & additions for Point3D + Scatter3D. * Removing mixed symm/asymm constructors on Point*D & Scatter*D classes. 2012-07-12 Andy Buckley * Reintroducing Profile2D and Scatter3D. * Adding axis locking to Axis2D. * Supporting Histo2D in WriterYODA. 2012-07-02 Andy Buckley * More incremental progress toward a working 2D bin hash mechanism. 2012-05-03 Andy Buckley * Adding nice constructor behaviours to the Histo1D and Profile2D Python interfaces, and adding the mkScatter operation for Profile1D. * Adding more default constructors for analysis objects, to allow member variable and STL container use without pointers. 2012-05-02 Andy Buckley * A much simplified and more robust rewrite of the Axis1D class, just using STL map in place of the hand-written bin edge caching. * Improvements (I hope) to the binary search in Axis1D, and providing an experimental default constructor for Histo1D. 2011-12-08 Hendrik Hoeth * ReaderYODA can now parse Histo1D and Profile1D flat files 2011-12-08 Andy Buckley * Adding a Utils::ndarray object and using it to implement a general Scatter system, with generalised Point and Error to boot. 2011-12-07 Hendrik Hoeth * Lots of cleanup 2011-12-07 Andy Buckley * Mapping the Dbn1D and Dbn2D classes into Python. * Adding an outflows() accessor to Histo2D. * Writing out total dbn lines for Histo1D and Profile1D in the YODA format, and now writing out the 'cross-terms' for Profile1D, too. * Properly adding Dbn1D accessors for Histo1D. * Updating the Cython mappings to provide the totalDbn() methods and add a placeholder mapping for Dbn2D. Completed mappings are needed for Dbn{1,2,3}D and the Profile types. * Adding totalDbn() accessors to data types. 2011-12-06 Andy Buckley * Making Histo1D/2D::scaleW() write a ScaledBy annotation. * Adding annotation-fetching methods with a default return value argument to AnalysisObject. * Adding normalize() methods to Histo1D/2D. * Adding weighted RMS calculating methods to Dbn1D, Dbn2D and Bin1D/2D. 2011-09-03 Dave Mallows * Fixed ReaderAIDA: x-value and low y-error interchanged when filling Scatter2D. * Changed to Cython for Python bindings: Swig bindings were in need of serious amounts of work. Cython should provide a means to provide more Pythonic bindings to YODA. A minimal subset of ReaderAIDA, Scatter2D and Point2D have been wrapped. * Modified configure.ac, Makefile.am and pyext/Makefile.am to reflect change to Cython. Added cython.m4 from python-efl (Part of the enlightenment project; LGPL) 2011-08-31 Dave Mallows * Fixed python tests by installing python extension to pyext/build 2011-08-23 Andy Buckley * Adding rebinning interface to Histo1D and Profile1D, and adding a test (and a new test feature for output message formatting) * Adding first implementation of 1D bin merging to Axis1D. 2011-08-22 Andy Buckley * Adding copy constructors and assignment operators to Histo1D, Profile1D, and Scatter2D, and their respective bins/points. * Remove use of sign(weight) in filling sum(w2) -- I think this was an historical attempt based on a scaling axiom which turned out to be inappropriate. * Reworking the Bin1D inheritance and composition design so that all bin types store a single distribution object -- a Dbn1D for histo bins and a Dbn2D for profile bins. 2011-08-18 Andy Buckley * Removing the Profile1D -> ProfileBin1D friendship. This is very heartening -- the fewer friend declarations we need, the more indication that the class structure is not pathological! (Or that we've just made everything public... but we haven't) 2011-08-15 Andy Buckley * Inlining all functions in HistoBin1D, ProfileBin1D, and HistoBin2D. * Converting Dbn2D to be composed of two Dbn1Ds and a cross-term. Also tidying the interfaces of the 2D classes and the scaleX/Y methods throughout, and adding Doxygen comments. 2011-08-12 Andy Buckley * Adding proper Doxygen structures and full descriptive comments to Dbn2D. * Adding the persistency state-setting constructors for Profile1D and Dbn2D. * Inlining lots of methods on Dbn1D. Same should be done for Dbn2D, but first it needs to be reimplemented in terms of two Dbn1Ds + the cross-term. 2011-08-11 Andy Buckley * Various typo fixes and comments relating to persistency constructors, Histo2D slicing, etc. * Changing the HistoBin1D state-setting constructors (aargh, these should *not* have already existed) to take Dbn1D as an argument rather than a long list of doubles. 2011-08-01 Andy Buckley * Adding tests to check that implicit construction of Weights objects from literal doubles and ints works. 2011-07-28 Andy Buckley * Bumping version number to 0.4.0beta0 -- there have been substantial changes recently and YODA is now in a state where it should be interesting for outsiders to start playing with it. * Templating the Axis1D on the distribution type to be used for total and under/overflow statistics: Profile1D now has Dbn2D objects handling its total and overflow statistics. 2011-07-26 Andy Buckley * Added a Histo1D::integral(index1, index2) method. Not sure how or if to extend this to Profile1D. * Implementing incomplete Scatter2D operator+ and operator- functions. 2011-07-25 Andy Buckley * Adding a Weights class, designed to seamlessly replace double-type weights and weighted moments with a named and vectorised form. 2011-07-19 Andy Buckley * Add Profile1D and Scatter2D division operators. * Add xMin/xMax synonyms to the Axis1D, cf. the bins. 2011-07-18 Andy Buckley * Add a first stab at a Histo1D/Histo1D division operator. 2011-07-10 Andy Buckley * Add construction of Histo1Ds from Profile1D and Histo1D, and construction of Profile1Ds from those and Scatter2D. 2011-07-07 Andy Buckley * Add construction of a Histo1D from Scatter2D. 2011-06-15 Andy Buckley * Making the AIDA reader work, including reading of annotations and a few tweaks to the simple type persistency system. Test histo 1b updated. 2011-06-12 Andy Buckley * Removing Histo1D::area * Filling and using under/overflow and total db on Histo1D, and adding boolean arg to integral, sumW, etc. * Fixing for C++ change in behaviour of std::make_pair * Adding addAnnotation, and mapping annotations to Python. 2011-02-22 Andy Buckley * Use distutils rather than setuptools for the Python interface build. * Renaming Bin, HistoBin and ProfileBin to be Bin1D, HistoBin1D, ProfileBin1D. Bin is now a top-level abstract class with minimal functionality to be shared between 1D and 2D bins. 2011-01-12 Andy Buckley * Type annotations in mkScatter * Added many vector constructors and addPoint functions to Scatter2D. 2011-01-11 Andy Buckley * Add lexical_cast support to annotation get and set functions. * Write out annotations in AIDA format, and copy annotations in mkScatter -- using a new AnalysisObject::setAnnotations method. * Convert DPS output to use interim Scatter construction * Make (unused) yoda.plot subpackage. * Write out annotations in YODA format. * Make Scatter2D representations of Histo1D and Profile1D. * Write out Scatter2D objects in AIDA and YODA formats. * Make Scatter2D and Point2D work. Add a few extra methods... evolution and tweaking required. 2011-01-10 Andy Buckley * Add Boost checks and header includes. Not used yet. * Hide Utils:: content from Doxygen and nvector -> Utils::nvector. * Removing unused YAML stuff: we aren't going that way for persistency anymore. * Renaming Axis -> Axis1D * Removing dead-end templated Scatter stuff. * Move (generated) config files into the Config subdir. * Move sortedvector and indexedset into the Utils dir. * Move the "utils" directory and namespace to "Utils" * Put the Doxyfile under configure control by moving it to Doxyfile.in and using the @PACKAGE_VERSION@ token. * Make Doxygen find the .icc file and hide functions with name _* and in the YAML namespace. * Removing the Binning argument and enum in favour of explicit bin edge vectors, possibly produced explicitly via the MathUtils linspace and logspace functions, or the new Axis::mkBinEdgesLin/Log alias functions. * Fixed Axis, Histo1D and Profile1D constructors, by adding a path argument, passing the path and title args to the AnalysisObject base constructor properly. * Removed several old and unused files such as Tree.h 2011-01-09 Andy Buckley * Updating copyright comments to be valid into 2011. * Persistency fixes, and changing the interface to use the annotated path. * Using annotations for path and title. * Adding tests of collection and iterator range AO writing. * Adding static write functions on Writer*.h implementations to avoid needing to make an explicit Writer object via the create() functions. * Rename Exception.h -> Exceptions.h * Added AnnotationError. * Re-enable persistency of collections with begin/end iterators. 2011-01-08 Andy Buckley * Enabling quiet compilation. * More annotation functionality. 2011-01-07 Andy Buckley * Sorting out autoheaders to be more useful. * Rewriting AIDA writer to use DPS representation (no reloading) for Histo1D and Profile1D objects. * Adding persistency system hooks, since RTTI just sucks too much. * Renaming test files to have more meaningful names. 2010-12-10 Andy Buckley * Some tweaks to Axis, Bin, etc. to use the sortedvector. Seems to be working! (I must be checking it wrongly...) * Adding another candidate object for the axis bin container: a sorted extension to STL std::vector with an insert method. This will do as a development placeholder: a proper sorted & indexed container may be substituted later. * Fix test code: titles are no longer given as histogram constructor arguments. 2010-11-21 Andy Buckley * Adding indexed set for holding bins on axes. Still not sure it's what we want, as (I just realised) STL sets are iterator-immutable because they are self-keyed and changes to elements would also change their sorting. 2010-09-19 Andy Buckley * Restarting ChangeLog contributions! Many changes in the huge time since last update... activity on YODA has renewed and we have a better picture of the distinctive features we require. New idea: named weight vector filling, allowing "parallel" histograms for various event weight variations. I/O remains an awkward issue, especially since the classes are now much richer than they used to be, and don't know about paths. Output can be easily put on top: not an issue... and we can probably do something with pickling. But reading in from C++? 2008-09-16 Andy Buckley * Moved duplicate Histo1D/Profile1D code on to Axis, making Axis a templated class at the same time. 2008-09-12 Andy Buckley * Started work on a little plotting tool, initially for Herwig++ parton pT cut testing, but incrementally enhancing it to be a command-line quick plotter seems like a good idea. * Added some more test programs... working towards a proper test suite. * Added "no path & title" constructors - you don't always want to write out the histo, since sometimes it's just a good way to gather statistics. * Fixed YODA mapping to allow use of vectors of bins as Python lists. * Added Profile1D functionality. * Fixed Dbn1D to use sign(weight) as part of the "w**2" measure, so that negative weights behave themselves. 2008-05-23 Andy Buckley * Added Dbn1D class to centralise the calculation of statistics from unbounded, unbinned, weighted distributions. 2008-05-15 Andy Buckley * Added Profile1D class. * Fixed NaN errors from zero weights. 2008-04-14 Andy Buckley * Python SWIG interface now compiles and can be used: the subtlety that was breaking it was that SWIG has to be prodded in pretty non-obvious ways to make std::vectors of classes without default (no-arg) constructors. See http://osdir.com/ml/programming.swig/2004-04/msg00011.html for about the only reference to this to be found anywhere! * Basic AIDA writer now available - it doesn't yet output all the necessary information though, especially not for merging parallel runs. diff --git a/include/YODA/Axis2D.h b/include/YODA/Axis2D.h --- a/include/YODA/Axis2D.h +++ b/include/YODA/Axis2D.h @@ -1,666 +1,685 @@ #ifndef YODA_Axis2D_h #define YODA_Axis2D_h #include "YODA/AnalysisObject.h" #include "YODA/Exceptions.h" #include "YODA/Bin.h" #include "YODA/Utils/MathUtils.h" #include "YODA/Utils/Predicates.h" #include "YODA/Utils/BinSearcher.h" #include #include namespace YODA { /// @brief 2D bin container /// /// This class handles most of the low-level operations on an axis of bins /// arranged in a 2D grid (including gaps). template class Axis2D { public: /// Typedefs //@{ /// Bin type typedef BIN2D Bin; /// A vector containing 2D bins. Not used for searching. typedef typename std::vector Bins; // Distinguishing between single edges and edge pairs (and pairs of pairs) is useful typedef std::vector Edges; typedef std::pair EdgePair1D; typedef std::pair EdgePair2D; typedef std::vector EdgePair2Ds; // Outflow distribution lists: see outflow(int, int) typedef std::vector Outflow; typedef std::vector Outflows; //@} /// @name Constructors //@{ // Empty constructor Axis2D() : _locked(false) { reset(); } /// A constructor with specified x and y axis bin cuts. Axis2D(const Edges& xedges, const Edges& yedges) : _locked(false) { addBins(xedges, yedges); reset(); } /// Constructor accepting X/Y ranges and number of bins /// on each of the axis. Both axes are divided linearly. Axis2D(size_t nbinsX, const std::pair& rangeX, size_t nbinsY, const std::pair& rangeY) : _locked(false) { addBins(linspace(nbinsX, rangeX.first, rangeX.second), linspace(nbinsY, rangeY.first, rangeY.second)); reset(); } /// Constructor accepting a list of bins Axis2D(const Bins& bins) : _locked(false) { addBins(bins); reset(); } /// State-setting constructor for persistency Axis2D(const Bins& bins, const DBN& totalDbn, const Outflows& outflows) : _dbn(totalDbn), _outflows(outflows), _locked(false) // Does this make sense? { if (_outflows.size() != 8) { throw Exception("Axis2D outflow containers must have exactly 8 elements"); } addBins(bins); } void reset() { _dbn.reset(); _outflows.assign(8, Outflow()); for (Bin& bin : _bins) bin.reset(); _locked = false; } /// Get the number of bins. size_t numBins() const { return _bins.size(); } /// Get the number of bins on the x-axis. This is only sensible for /// perfectly regular gridded bins. For irregular binnings, this is /// the number of cuts that were necessary to grid the data. size_t numBinsX() const { return _nx; } /// Get the number of bins on the y-axis. This is only sensible for /// perfectly regular gridded bins. For irregular binnings, this is /// the number of cuts that were necessary to grid the data. size_t numBinsY() const { return _ny; } //@} // /// @name Statistics accessor functions //@{ /// @brief Get the outflow by x-index and y-index (non-const version) /// /// Indices are -1 = below range, 0 = in range, +1 = above range, e.g. (+1, /// -1) is in the "bottom right" position by being greater than the greatest /// x-edge and less than the lowest y-edge. /// Outflow& outflow(int ix, int iy) { return _outflows[_outflowIndex(ix, iy)]; } /// @brief Get the outflow by x-index and y-index (const version) /// /// Indices are -1 = below range, 0 = in range, +1 = above range, e.g. (+1, /// -1) is in the "bottom right" position by being greater than the greatest /// x-edge and less than the lowest y-edge. /// const Outflow& outflow(int ix, int iy) const { return _outflows[_outflowIndex(ix, iy)]; } /// Scale each bin as if the entire x-axis had been scaled by this factor. void scaleX(double xscale) { scaleXY(xscale, 1.0); } /// Scale each bin as if the entire y-axis had been scaled by this factor. void scaleY(double yscale) { scaleXY(1.0, yscale); } /// Scale each bin as if the entire x and y-axes had been scaled by /// their respective factors. void scaleXY(double sx, double sy) { _dbn.scaleXY(sx, sy); /// @todo Reinstate when C++11 allowed in API // for (Outflow& outflow : _outflows) // for (DBN& dbn : outflow) // dbn.scaleXY(sx, sy); for (size_t io = 0; io < _outflows.size(); ++io) { Outflow& outflow = _outflows[io]; for (size_t id = 0; id < outflow.size(); ++id) { DBN& dbn = outflow[id]; dbn.scaleXY(sx, sy); } } /// @todo Reinstate when C++11 allowed in API // for (Bin& bin : _bins) // bin.scaleXY(sx, sy); for (size_t ib = 0; ib < _bins.size(); ++ib) _bins[ib].scaleXY(sx, sy); _updateAxis(_bins); } /// Rescale as if all fill weights had been different by factor @a /// scalefactor. void scaleW(double scalefactor) { _dbn.scaleW(scalefactor); /// @todo Reinstate when C++11 allowed in API // for (Outflow& outflow : _outflows) // for (DBN& dbn : outflow) // dbn.scaleW(scalefactor); for (size_t io = 0; io < _outflows.size(); ++io) { Outflow& outflow = _outflows[io]; for (size_t id = 0; id < outflow.size(); ++id) { DBN& dbn = outflow[id]; dbn.scaleW(scalefactor); } } /// @todo Reinstate when C++11 allowed in API // for (Bin& bin : _bins) // bin.scaleW(scalefactor); for (size_t ib = 0; ib < _bins.size(); ++ib) _bins[ib].scaleW(scalefactor); _updateAxis(_bins); } /// Remove the bin at the given index. If many bins need to be /// removed, prefer eraseBins(vector[size_t] &) over many calls to this, /// as recreating the binhash is comparatively expensive. void eraseBin(size_t i) { if (i >= numBins()) throw RangeError("Bin index is out of range"); // Temporarily unlock the axis during the update _bins.erase(_bins.begin() + i); _updateAxis(_bins); } /// Erase a rectangle of bins. void eraseBins(const size_t from, const size_t to) { if (from >= numBins()) throw RangeError("Initial bin index is out of range"); if (from >= numBins()) throw RangeError("Final bin index is out of range"); Bin& fromBin = bin(from); Bin& toBin = bin(to); eraseBins(std::make_pair(fromBin.xMin(), toBin.xMax()), std::make_pair(fromBin.yMin(), toBin.yMax())); } /// Erase bins in an x- and y-range. Any bins which lie entirely within the /// region are deleted. If any part of the bin lies outside this /// range, the bin remains, so this has similar behaviour to select /// tools in vector graphics GUI packages. /// /// @todo How to test this? void eraseBins(const std::pair& xrange, const std::pair& yrange) { size_t xiLow = _binSearcherX.index(xrange.first) - 1; size_t xiHigh = _binSearcherX.index(xrange.second) - 1; size_t yiLow = _binSearcherY.index(yrange.first) - 1; size_t yiHigh = _binSearcherY.index(yrange.second) - 1; /// @todo Beware the specialisation problems with vector... std::vector deleteMask(numBins(), false); for (size_t yi = yiLow; yi < yiHigh; yi++) { for (size_t xi = xiLow; xi < xiHigh; xi++) { ssize_t i = _indexes[_index(_nx, xi, yi)]; if (i == -1 || deleteMask[i]) continue; if (bin(i).fitsInside(xrange, yrange)) deleteMask[i] = true; } } // Now we just update eraseBins(deleteMask); } /// Erase using a vector, where true represents that a bin /// will be deleted, and false means it will be kept. void eraseBins(const std::vector& deleteMask) { Bins newBins; for (size_t i = 0; i < numBins(); i++) if (!deleteMask[i]) newBins.push_back(bins(i)); _update(newBins); } /// Merge together the bin range with indices from @a from to @a to, inclusive. /// Merge a series of bins, between the bins identified by indices @a from and @a to void mergeBins(size_t from, size_t to) { // Correctness checking if (from >= numBins()) throw RangeError("Initial merge index is out of range"); if (to >= numBins()) throw RangeError("Final merge index is out of range"); if (from > to) throw RangeError("Final bin must be greater than or equal to initial bin"); if (_gapInRange(from, to)) throw RangeError("Bin ranges containing gaps cannot be merged"); if (from == to) return; // nothing to be done Bin& b = bin(from); for (size_t i = from + 1; i <= to; ++i) b.merge(_bins[i]); eraseBins(from+1, to); } /// Rebin with the same rebinning factor @a n in x and y void rebin(unsigned int n) { rebinXY(n, n); } /// Rebin with separate rebinning factors @a nx, @a ny in x and y void rebinXY(unsigned int nx, unsigned int ny) { rebinX(nx); rebinY(ny); } /// Rebin in x by factor @a nx void rebinX(unsigned int nx) { /// @todo WRITE THIS! } /// Rebin in y by factor @a ny void rebinY(unsigned int ny) { /// @todo WRITE THIS! } /// Set the axis lock state /// @todo Remove? Should not be public void _setLock(bool locked) { _locked = locked; } /// @todo Add xMins, xMaxs, xMids, xFoci, and y-versions /// Return the lowest-valued bin edge along the x-axis double xMin() const { return _xRange.first; } /// Return the highest-valued bin edge along the x-axis double xMax() const { return _xRange.second; } /// Return the lowest-valued bin edge along the y-axis double yMin() const { return _yRange.first; } /// Return the highest-valued bin edge along the y-axis double yMax() const { return _yRange.second; } + /// Return all the NbinX+1 bin edges on the x-axis + /// + /// @note This only returns the finite edges, i.e. -inf and +inf are removed + /// @todo Make the +-inf stripping controllable by a default-valued bool arg + std::vector xEdges() const { + std::vector rtn(_binSearcherX.edges().begin()+1, _binSearcherX.edges().end()-1); + return rtn; + } + + /// Return all the NbinY+1 bin edges on the y-axis + /// + /// @note This only returns the finite edges, i.e. -inf and +inf are removed + /// @todo Make the +-inf stripping controllable by a default-valued bool arg + std::vector yEdges() const { + std::vector rtn(_binSearcherY.edges().begin()+1, _binSearcherY.edges().end()-1); + return rtn; + } + + /// Add a bin, providing its x- and y- edge ranges void addBin(EdgePair1D xrange, EdgePair1D yrange) { _checkUnlocked(); Bins newBins = _bins; newBins.push_back(Bin(xrange, yrange)); _updateAxis(newBins); } /// Add a pre-made bin void addBin(const Bin& bin) { _checkUnlocked(); Bins newBins = _bins; newBins.push_back(bin); _updateAxis(newBins); } /// Add a vector of pre-made bins void addBins(const Bins& bins) { if (bins.size() == 0) return; _checkUnlocked(); Bins newBins = _bins; /// @todo Reinstate when C++11 allowed in API // for (const Bin& b : bins) // newBins.push_back(b); for (size_t ib = 0; ib < bins.size(); ++ib) newBins.push_back(bins[ib]); _updateAxis(newBins); } /// Add a contiguous set of bins to an axis, via their list of edges void addBins(const std::vector& xedges, const std::vector& yedges) { if (xedges.size() == 0) return; if (yedges.size() == 0) return; _checkUnlocked(); Bins newBins = _bins; for (size_t xi = 0; xi < xedges.size()-1; xi++) { for (size_t yi = 0; yi < yedges.size()-1; yi++) { const std::pair xx = std::make_pair(xedges[xi], xedges[xi+1]); const std::pair yy = std::make_pair(yedges[yi], yedges[yi+1]); // std::cout << "New bin with edges: [(" << xx.first << "," << xx.second << "), " << yy.first << "," << yy.second << ")]" << std::endl; newBins.push_back(Bin(xx, yy)); } } _updateAxis(newBins); } /// Access bin by index Bin& bin(size_t i) { return _bins[i]; } /// Access bin by index (const) const Bin& bin(size_t i) const { return _bins[i]; } /// Get the bin index of the bin containing point (x, y). int binIndexAt(double x, double y) const { size_t xi = _binSearcherX.index(x) - 1; size_t yi = _binSearcherY.index(y) - 1; if (xi > _nx) return -1; if (yi > _ny) return -1; return _indexes[_index(_nx, xi, yi)]; } /// Get the bin containing point (x, y). Bin& binAt(double x, double y) { const int ret = binIndexAt(x, y); if (ret == -1) throw RangeError("No bin found!!"); return bin(ret); } /// Get the bin containing point (x, y) (const). const Bin& binAt(double x, double y) const { const int ret = binIndexAt(x, y); if (ret == -1) throw RangeError("No bin found!!"); return bin(ret); } /// Return the total distribution (non-const) DBN& totalDbn() { return _dbn; } /// Return the total distribution (const) const DBN& totalDbn() const { return _dbn; } /// Set the total distribution: CAREFUL! void setTotalDbn(const DBN& dbn) { _dbn = dbn; } /// Return the bins vector (non-const) Bins& bins() { return _bins; } /// Return the bins vector (const) const Bins& bins() const { return _bins; } /// Equality operator (on binning only) /// @todo Change as discussed below if we expose the Axis classes for direct use // (DM: Doesn't this break the semantics of equality? As it's used only // rarely, isn't there a real case for having a "binningsCompatible" or // similar method?) bool operator == (const Axis2D& other) const { if (numBins() != other.numBins()) return false; for (size_t i = 0; i < numBins(); i++) if (!(fuzzyEquals(bin(i).xMin(), other.bin(i).xMin()) && fuzzyEquals(bin(i).xMax(), other.bin(i).xMax()) && fuzzyEquals(bin(i).yMin(), other.bin(i).yMin()) && fuzzyEquals(bin(i).yMax(), other.bin(i).yMax()))) return false; return true; } /// Non-equality operator bool operator != (const Axis2D& other) const { return ! operator == (other); } /// Addition operator Axis2D& operator += (const Axis2D& toAdd) { if (*this != toAdd) { throw LogicError("YODA::Axis2D: Cannot add axes with different binnings."); } for (size_t i = 0; i < bins().size(); ++i) { bin(i) += toAdd.bin(i); } _dbn += toAdd._dbn; return *this; } /// Subtraction operator Axis2D& operator -= (const Axis2D& toSubtract) { if (*this != toSubtract) { throw LogicError("YODA::Axis2D: Cannot add axes with different binnings."); } for (size_t i = 0; i < bins().size(); ++i) { bin(i) -= toSubtract.bin(i); } _dbn -= toSubtract._dbn; return *this; } private: void _checkUnlocked(void) { // Ensure that axis is not locked if (_locked) throw LockError("Attempting to update a locked 2D axis"); } /// Detect if there is a binning gap in the given bin index range /// @todo WRITE THIS! bool _gapInRange(size_t from, size_t to) { Bin& toBin = bin(to); Bin& fromBin = bin(from); return true; } void _updateAxis(Bins& bins) { // Deal with the case that there are no bins supplied (who called that?!) if (bins.size() == 0) { _binSearcherX = Utils::BinSearcher(); _binSearcherY = Utils::BinSearcher(); _nx = 0; _ny = 0; _xRange = std::make_pair(0, 0); _yRange = std::make_pair(0, 0); } // Sort the bins std::sort(bins.begin(), bins.end()); // Create the edges std::vector xedges, yedges, xwidths, ywidths; for (const Bin& bin : bins) { xedges.push_back(bin.xMin()); xedges.push_back(bin.xMax()); xwidths.push_back(bin.xWidth()); yedges.push_back(bin.yMin()); yedges.push_back(bin.yMax()); ywidths.push_back(bin.yWidth()); } // Sort the edges and widths std::sort(xedges.begin(), xedges.end()); std::sort(yedges.begin(), yedges.end()); std::sort(xwidths.begin(), xwidths.end()); std::sort(ywidths.begin(), ywidths.end()); // Obtain the median widths as a typical scale for uniqueness comparisons const double medianxwidth = xwidths[ (xwidths.size()-1)/2 ]; const double medianywidth = ywidths[ (ywidths.size()-1)/2 ]; // Uniqueify the bin edges in the x- and y-cut vectors, with some numerical fuzziness xedges.resize(std::unique(xedges.begin(), xedges.end(), CmpFloats(1e-3, medianxwidth)) - xedges.begin()); yedges.resize(std::unique(yedges.begin(), yedges.end(), CmpFloats(1e-3, medianywidth)) - yedges.begin()); const size_t nx = xedges.size(); const size_t ny = yedges.size(); const size_t N = nx * ny; //std::cout << "Unique Axis2D edge list sizes: nx = " << nx << ", ny = " << ny << std::endl; assert(bins.size() <= (nx-1)*(ny-1) && "Input bins vector size must agree with computed number of unique bins"); // Create a sea of indices, starting with an all-gaps configuration std::vector indexes(N, -1); // Iterate through bins and find out which Utils::BinSearcher xSearcher(xedges); Utils::BinSearcher ySearcher(yedges); for (size_t i = 0; i < bins.size(); ++i) { Bin& bin = bins[i]; // std::cout << "Bin #" << i << " edges: " // << "[(" << bin.xMin() << "," << bin.xMax() << "), " // << "(" << bin.yMin() << "," << bin.yMax() << ")] " << std::endl; const size_t xiMin= xSearcher.index(bin.xMin()) - 1; const size_t xiMax= xSearcher.index(bin.xMax()) - 1; const size_t yiMin = ySearcher.index(bin.yMin()) - 1; const size_t yiMax = ySearcher.index(bin.yMax()) - 1; // std::cout << "Sub-bin range indices: x = " << xiMin << ".." << xiMax << ", y = " << yiMin << ".." << yiMax << std::endl; // Loop over sub-bins in the edge list and assign indices / detect overlaps for (size_t xi = xiMin; xi < xiMax; xi++) { for (size_t yi = yiMin; yi < yiMax; yi++) { const size_t ii = _index(nx, xi, yi); if (indexes[ii] != -1) { std::stringstream ss; ss << "Bin edges overlap! Bin #" << i << " with edges " << "[(" << bin.xMin() << "," << bin.xMax() << "), " << "(" << bin.yMin() << "," << bin.yMax() << ")] " << "overlaps bin #" << indexes[ii] << " in sub-bin #" << ii; throw RangeError(ss.str()); } indexes[ii] = i; } } } // Job's a good'n - let's change our class. _nx = nx; _ny = ny; _xRange = std::make_pair(xedges.front(), xedges.back()); _yRange = std::make_pair(yedges.front(), yedges.back()); _indexes = indexes; _bins = bins; _binSearcherX = xSearcher; _binSearcherY = ySearcher; } /// Definition of global bin ID in terms of x and y bin IDs static size_t _index(size_t nx, size_t x, size_t y) { return y * nx + x; } /// @brief Get the outflow array index by x-index and y-index /// /// Indices are -1 = below range, 0 = in range, +1 = above range, e.g. (+1, /// -1) is in the "bottom right" position by being greater than the greatest /// x-edge and less than the lowest y-edge. static size_t _outflowIndex(int ix, int iy) { if (ix == 0 || iy == 0) throw UserError("The in-range (0,0) index pair is not a valid outflow specifier"); ix += 1; iy += 1; if (ix > 2 || iy > 2) throw UserError("Outflow index out of range: valid indices are -1, 0, 1"); size_t rtn = 3*ix + iy; // uncorrected for (0,0) index offset if (rtn > 4) rtn -= 1; // offset correction (note that raw rtn == 4 is not possible) return rtn; } /// @name Data structures //@{ /// Bins vector Bins _bins; /// Total distribution DBN _dbn; // Outflows Outflows _outflows; // Binsearcher, for searching bins Utils::BinSearcher _binSearcherX; Utils::BinSearcher _binSearcherY; EdgePair1D _xRange; EdgePair1D _yRange; // Mapping from bin-searcher indices to bin indices (allowing gaps) std::vector _indexes; // Necessary for bounds checking and indexing size_t _nx; size_t _ny; /// Whether modifying bin edges is permitted bool _locked; //@} }; } #endif diff --git a/include/YODA/Profile2D.h b/include/YODA/Profile2D.h --- a/include/YODA/Profile2D.h +++ b/include/YODA/Profile2D.h @@ -1,456 +1,467 @@ // -*- C++ -*- // // This file is part of YODA -- Yet more Objects for Data Analysis // Copyright (C) 2008-2018 The YODA collaboration (see AUTHORS for details) // #ifndef YODA_Profile2D_h #define YODA_Profile2D_h #include "YODA/AnalysisObject.h" #include "YODA/ProfileBin2D.h" #include "YODA/Dbn3D.h" #include "YODA/Axis2D.h" #include "YODA/Scatter3D.h" #include "YODA/Exceptions.h" #include #include namespace YODA { // Forward declarations class Histo2D; class Scatter3D; /// Convenience typedef typedef Axis2D Profile2DAxis; /// A two-dimensional profile histogram. class Profile2D : public AnalysisObject { public: /// Convenience typedefs typedef Profile2DAxis Axis; typedef Axis::Bins Bins; typedef ProfileBin2D Bin; typedef Axis::Outflows Outflows; typedef std::tuple FillType; typedef std::tuple BinType; typedef std::shared_ptr Ptr; /// @name Constructors //@{ /// Default constructor Profile2D(const std::string& path="", const std::string& title="") : AnalysisObject("Profile2D", path, title), _axis() { } /// Constructor giving range and number of bins Profile2D(size_t nbinsX, double lowerX, double upperX, size_t nbinsY, double lowerY, double upperY, const std::string& path="", const std::string& title="") : AnalysisObject("Profile2D", path, title), _axis(nbinsX, std::make_pair(lowerX, upperX), nbinsY, std::make_pair(lowerY, upperY)) { } /// Constructor giving explicit bin edges in the direction of X and Y Profile2D(const std::vector& xedges, const std::vector& yedges, const std::string& path="", const std::string& title="") : AnalysisObject("Profile2D", path, title), _axis(xedges, yedges) { } /// Constructor accepting an explicit collection of bins. Profile2D(const std::vector& bins, const std::string& path="", const std::string& title="") : AnalysisObject("Profile2D", path, title), _axis(bins) { } /// A copy constructor with optional new path /// @todo Also allow title setting from the constructor? Profile2D(const Profile2D& p, const std::string& path=""); /// A constructor from a Scatter3D's binning, with optional new path /// @todo Also allow title setting from the constructor? Profile2D(const Scatter3D& s, const std::string& path=""); /// Constructor from a Histo2D's binning, with optional new path /// @todo Also allow title setting from the constructor? Profile2D(const Histo2D& h, const std::string& path=""); /// @brief State-setting constructor /// /// Mainly intended for internal persistency use. Profile2D(const std::vector& bins, const Dbn3D& totalDbn, const Outflows& outflows, const std::string& path="", const std::string& title="") : AnalysisObject("Profile2D", path, title), _axis(bins, totalDbn, outflows) { } /// Assignment operator Profile2D& operator = (const Profile2D& p2) { AnalysisObject::operator = (p2); //< AO treatment of paths etc. _axis = p2._axis; return *this; } /// Make a copy on the stack Profile2D clone() const { return Profile2D(*this); } /// Make a copy on the heap, via 'new' Profile2D* newclone() const { return new Profile2D(*this); } //@} /// Fill dimension of this data object size_t dim() const { return 2; } /// @name Modifiers //@{ /// Fill histo by value and weight virtual void fill(double x, double y, double z, double weight=1.0, double fraction=1.0); virtual void fill(const FillType & xs, double weight=1.0, double fraction=1.0) { fill(std::get<0>(xs), std::get<1>(xs), std::get<2>(xs), weight, fraction); } /// Fill histo x-y bin i with the given z value and weight virtual void fillBin(size_t i, double z, double weight=1.0, double fraction=1.0); /// @brief Reset the histogram /// /// Keep the binning but reset the statistics void reset() { _axis.reset(); } /// Rescale as if all fill weights had been different by a @a scalefactor void scaleW(double scalefactor) { /// @todo Is this ScaledBy annotation needed? setAnnotation("ScaledBy", annotation("ScaledBy", 1.0) * scalefactor); _axis.scaleW(scalefactor); } /// Rescale as if all z values had been different by factor @a scalefactor. void scaleZ(double scalefactor) { _axis.totalDbn().scaleZ(scalefactor); /// @todo Need to rescale overflows too, when they exist. // _axis.overflow().scaleZ(scalefactor); // _axis.underflow().scaleZ(scalefactor); for (size_t i = 0; i < bins().size(); ++i) bin(i).scaleZ(scalefactor); } /// @todo TODO // /// Merge together the bin range with indices from @a from to @a to, inclusive // void mergeBins(size_t from, size_t to) { // _axis.mergeBins(from, to); // } /// @todo TODO // /// Merge every group of n bins, starting from the LHS // void rebin(size_t n) { // throw "IMPLEMENT!"; // //_axis.rebin(n); // } // /// @brief Bin addition operator // /// // /// Add a bin to the axis, described by its x and y ranges. void addBin(Axis::EdgePair1D xrange, Axis::EdgePair1D yrange) { _axis.addBin(xrange, yrange); } // /// @brief Bin addition operator // /// // /// Add a bin to the axis, possibly pre-populated void addBin(const Bin& bin) { _axis.addBin(bin); } /// @brief Bins addition operator /// /// Add multiple bins from edge cuts without resetting void addBins(const Axis::Edges& xcuts, const Axis::Edges& ycuts) { _axis.addBins(xcuts, ycuts); } /// @brief Bins addition operator /// /// Add multiple bins without resetting void addBins(const Bins& bins) { _axis.addBins(bins); } /// check if binning is the same as different Profile2D bool sameBinning(const Profile2D& p2) { return _axis == p2._axis; } /// @todo TODO // /// @brief Bin addition operator // /// // /// Add a set of bins delimiting coordinates of which are contained // /// in binLimits vector. // void addBin(const std::vector& binLimits) { // _axis.addBin(binLimits); // } void eraseBin(size_t index) { _axis.eraseBin(index); } //@} /// @name Bin accessors //@{ + /// All bin edges on this histo's x axis + /// + /// @note This only returns the finite edges, i.e. -inf and +inf are removed + /// @todo Make the +-inf stripping controllable by a default-valued bool arg + const std::vector xEdges() const { return _axis.xEdges(); } + + /// All bin edges on this histo's y axis + /// + /// @note This only returns the finite edges, i.e. -inf and +inf are removed + /// @todo Make the +-inf stripping controllable by a default-valued bool arg + const std::vector yEdges() const { return _axis.yEdges(); } + /// @todo Add xMins, xMaxs, xMids, xFoci, and y-versions - /// Low x edge of this histo's axis double xMin() const { return _axis.xMin(); } /// High x edge of this histo's axis double xMax() const { return _axis.xMax(); } /// Low y edge of this histo's axis double yMin() const { return _axis.yMin(); } /// High y edge of this histo's axis double yMax() const { return _axis.yMax(); } /// Access the bin vector (non-const) std::vector& bins() { return _axis.bins(); } /// Access the bin vector (const) const std::vector& bins() const { return _axis.bins(); } /// Access a bin by index (non-const) ProfileBin2D& bin(size_t index) { return _axis.bins()[index]; } /// Access a bin by index (const) const ProfileBin2D& bin(size_t index) const { return _axis.bins()[index]; } /// Access a bin index by coordinate int binIndexAt(double x, double y) { return _axis.binIndexAt(x, y); } int binIndexAt(const BinType& t) { return _axis.binIndexAt(std::get<0>(t), std::get<1>(t)); } /// Access a bin by coordinate (const) const ProfileBin2D& binAt(double x, double y) const { return _axis.binAt(x, y); } const ProfileBin2D& binAt(const BinType& t) const { return _axis.binAt(std::get<0>(t), std::get<1>(t)); } /// Number of bins of this axis (not counting under/over flow) size_t numBins() const { return _axis.bins().size(); } /// Number of bins along the x axis size_t numBinsX() const { return _axis.numBinsX(); } /// Number of bins along the y axis size_t numBinsY() const { return _axis.numBinsY(); } /// Access summary distribution, including gaps and overflows (non-const version) Dbn3D& totalDbn() { return _axis.totalDbn(); } /// Access summary distribution, including gaps and overflows (const version) const Dbn3D& totalDbn() const { return _axis.totalDbn(); } /// Set summary distribution, including gaps and overflows void setTotalDbn(const Dbn3D& dbn) { _axis.setTotalDbn(dbn); } // /// @brief Access an outflow (non-const) // /// // /// Two indices are used, for x and y: -1 = underflow, 0 = in-range, and +1 = overflow. // /// (0,0) is not a valid overflow index pair, since it is in range for both x and y. // Dbn3D& outflow(int ix, int iy) { // return _axis.outflow(ix, iy); // } // /// @brief Access an outflow (const) // /// // /// Two indices are used, for x and y: -1 = underflow, 0 = in-range, and +1 = overflow. // /// (0,0) is not a valid overflow index pair, since it is in range for both x and y. // const Dbn3D& outflow(int ix, int iy) const { // return _axis.outflow(ix, iy); // } //@} /// @name Whole histo data //@{ /// Get the number of fills (fractional fills are possible) double numEntries(bool includeoverflows=true) const; /// Get the effective number of fills double effNumEntries(bool includeoverflows=true) const; /// Get sum of weights in histo double sumW(bool includeoverflows=true) const; /// Get the sum of squared weights in histo double sumW2(bool includeoverflows=true) const; /// Get the mean x double xMean(bool includeoverflows=true) const; /// Get the mean y double yMean(bool includeoverflows=true) const; /// Get the variance in x double xVariance(bool includeoverflows=true) const; /// Get the variance in y double yVariance(bool includeoverflows=true) const; /// Get the standard deviation in x double xStdDev(bool includeoverflows=true) const { return std::sqrt(xVariance(includeoverflows)); } /// Get the standard deviation in y double yStdDev(bool includeoverflows=true) const { return std::sqrt(yVariance(includeoverflows)); } /// Get the standard error on double xStdErr(bool includeoverflows=true) const; /// Get the standard error on double yStdErr(bool includeoverflows=true) const; /// Get the RMS in x double xRMS(bool includeoverflows=true) const; /// Get the RMS in y double yRMS(bool includeoverflows=true) const; //@} /// @name Adding and subtracting histograms //@{ /// Add another profile to this one Profile2D& operator += (const Profile2D& toAdd) { if (hasAnnotation("ScaledBy")) rmAnnotation("ScaledBy"); _axis += toAdd._axis; return *this; } /// Subtract another profile from this one Profile2D& operator -= (const Profile2D& toSubtract) { if (hasAnnotation("ScaledBy")) rmAnnotation("ScaledBy"); _axis -= toSubtract._axis; return *this; } inline bool operator == (const Profile2D& other){ return _axis == other._axis; } inline bool operator != (const Profile2D& other){ return ! operator == (other); } //@}- protected: /// Access a bin by coordinate (non-const) ProfileBin2D& _binAt(double x, double y) { return _axis.binAt(x, y); } private: /// @name Bin data //@{ /// The bins contained in this profile histogram Axis2D _axis; //@} }; /// Convenience typedef typedef Profile2D P2D; /// @name Combining profile histos: global operators //@{ /// Add two profile histograms inline Profile2D add(const Profile2D& first, const Profile2D& second) { Profile2D tmp = first; if (first.path() != second.path()) tmp.setPath(""); tmp += second; return tmp; } /// Add two profile histograms inline Profile2D operator + (const Profile2D& first, const Profile2D& second) { return add(first,second); } /// Subtract two profile histograms inline Profile2D subtract(const Profile2D& first, const Profile2D& second) { Profile2D tmp = first; if (first.path() != second.path()) tmp.setPath(""); tmp -= second; return tmp; } /// Subtract two profile histograms inline Profile2D operator - (const Profile2D& first, const Profile2D& second) { return subtract(first,second); } /// Divide two profile histograms Scatter3D divide(const Profile2D& numer, const Profile2D& denom); /// Divide two profile histograms inline Scatter3D operator / (const Profile2D& numer, const Profile2D& denom) { return divide(numer, denom); } //@} } #endif diff --git a/pyext/yoda/declarations.pxd b/pyext/yoda/declarations.pxd --- a/pyext/yoda/declarations.pxd +++ b/pyext/yoda/declarations.pxd @@ -1,1419 +1,1426 @@ from libcpp.map cimport map from libcpp.pair cimport pair from libcpp.vector cimport vector from libcpp cimport bool from libcpp.string cimport string from cython.operator cimport dereference as deref cdef extern from "YODA/Config/YodaConfig.h" namespace "YODA": string version() # Import the error handling C++ routine cdef extern from "errors.hh": # Have a look in errors.cpp for implementation specifics void yodaerr "translate_yoda_error" () ctypedef map[string, string] Annotations ctypedef double (*dbl_dbl_fptr) (double) -ctypedef map[string, pair[double,double]] errMap +ctypedef map[string, pair[double,double]] errMap # Math utils {{{ cdef extern from "YODA/Utils/MathUtils.h" namespace "YODA": # bool isZero(double a, double tolerance) # bool fuzzyEquals(double a, double b, double tolerance) # bool fuzzyGtrEquals(double a, double b, double tolerance) # bool fuzzyLessEquals(double a, double b, double tolerance) vector[double] linspace(size_t nbins, double start, double end) vector[double] logspace(size_t nbins, double start, double end) int index_between(double&, vector[double]& binedges) double mean(vector[int]& sample) double covariance(vector[int]& sample1, vector[int]& sample2) double correlation(vector[int]& sample1, vector[int]& sample2) # }}} # Dbn0D {{{ cdef extern from "YODA/Dbn0D.h" namespace "YODA": cdef cppclass Dbn0D: Dbn0D () Dbn0D (Dbn0D) void fill(double weight, double fraction) void reset() void scaleW(double) # Raw distribution running sums unsigned long numEntries() except +yodaerr double effNumEntries() except +yodaerr double sumW() except +yodaerr double sumW2() except +yodaerr double errW() except +yodaerr double relErrW() except +yodaerr Dbn0D operator+ (Dbn0D) Dbn0D operator- (Dbn0D) # TODO: += and -= operators #}}} Dbn0D # Dbn1D {{{ cdef extern from "YODA/Dbn1D.h" namespace "YODA": cdef cppclass Dbn1D: Dbn1D () Dbn1D (Dbn1D) void fill(double val, double weight, double fraction) void reset() void scaleW(double) void scaleX(double) double errW() except +yodaerr double relErrW() except +yodaerr double xMean() except +yodaerr double xVariance() except +yodaerr double xStdDev() except +yodaerr double xStdErr() except +yodaerr double xRMS() except +yodaerr # Raw distribution running sums unsigned long numEntries() except +yodaerr double effNumEntries() except +yodaerr double sumW() except +yodaerr double sumW2() except +yodaerr double sumWX() except +yodaerr double sumWX2() except +yodaerr Dbn1D operator+ (Dbn1D) Dbn1D operator- (Dbn1D) # TODO: += and -= operators #}}} Dbn1D # Dbn2D {{{ cdef extern from "YODA/Dbn2D.h" namespace "YODA": cdef cppclass Dbn2D: Dbn2D () Dbn2D (Dbn2D) void fill(double x, double y, double weight, double fraction) except +yodaerr void reset() except +yodaerr void scaleW(double) except +yodaerr void scaleX(double) except +yodaerr void scaleY(double) except +yodaerr void scaleXY(double, double) except +yodaerr double errW() except +yodaerr double relErrW() except +yodaerr double xMean() except +yodaerr double xVariance() except +yodaerr double xStdDev() except +yodaerr double xStdErr() except +yodaerr double xRMS() except +yodaerr double yMean() except +yodaerr double yVariance() except +yodaerr double yStdDev() except +yodaerr double yStdErr() except +yodaerr double yRMS() except +yodaerr # Raw distribution running sums unsigned long numEntries() except +yodaerr double effNumEntries() except +yodaerr double sumW() except +yodaerr double sumW2() except +yodaerr double sumWX() except +yodaerr double sumWX2() except +yodaerr double sumWY() except +yodaerr double sumWY2() except +yodaerr double sumWXY() except +yodaerr # Operators void flipXY() except +yodaerr Dbn1D transformX() except +yodaerr Dbn1D transformY() except +yodaerr Dbn2D operator + (Dbn2D) Dbn2D operator - (Dbn2D) # TODO: += and -= operators #}}} Dbn2D # Dbn3D {{{ cdef extern from "YODA/Dbn3D.h" namespace "YODA": cdef cppclass Dbn3D: Dbn3D () Dbn3D (Dbn3D) void fill(double x, double y, double z, double weight, double fraction) void reset() void scaleW(double) void scaleX(double) void scaleY(double) void scaleZ(double) # void scaleXY(double, double) # void scaleYZ(double, double) # void scaleXZ(double, double) void scaleXYZ(double, double, double) double errW() except +yodaerr double relErrW() except +yodaerr double xMean() double xVariance() double xStdDev() double xStdErr() double xRMS() double yMean() double yVariance() double yStdDev() double yStdErr() double yRMS() double zMean() double zVariance() double zStdDev() double zStdErr() double zRMS() # Raw distribution running sums unsigned long numEntries() double effNumEntries() double sumW() double sumW2() double sumWX() double sumWX2() double sumWY() double sumWY2() double sumWZ() double sumWZ2() double sumWXY() double sumWXZ() double sumWYZ() double sumWXYZ() # Operators void flipXY() void flipXZ() void flipYZ() Dbn1D transformX() Dbn1D transformY() Dbn1D transformZ() Dbn3D operator + (Dbn3D) Dbn3D operator - (Dbn3D) # TODO: += and -= operators #}}} Dbn3D # Point {{{ cdef extern from "YODA/Point.h" namespace "YODA": cdef cppclass Point: int dim() except +yodaerr double val(size_t i) except +yodaerr void setVal(size_t i, double val) except +yodaerr pair[double,double] errs(size_t i) except +yodaerr pair[double,double] errs(size_t i, string source) except +yodaerr double errMinus(size_t i) except +yodaerr double errMinus(size_t i, string source) except +yodaerr void setErrMinus(size_t i, double eminus) except +yodaerr void setErrMinus(size_t i, double eminus, string source) except +yodaerr double errPlus(size_t i) except +yodaerr double errPlus(size_t i, string source) except +yodaerr void setErrPlus(size_t i, double eplus) except +yodaerr void setErrPlus(size_t i, double eplus, string source) except +yodaerr double errAvg(size_t i) except +yodaerr double errAvg(size_t i, string source) except +yodaerr void setErr(size_t i, double e) except +yodaerr void setErr(size_t i, double e, string source) except +yodaerr # void setErrs(size_t i, double e) except +yodaerr # void setErrs(size_t i, double eminus, double eplus) except +yodaerr void setErrs(size_t i, pair[double,double]& e) except +yodaerr void setErrs(size_t i, pair[double,double]& e, string source) except +yodaerr # void set(size_t i, double val, double e) except +yodaerr # void set(size_t i, double val, double eminus, double eplus) except +yodaerr void set(size_t i, double val, pair[double,double]& e) except +yodaerr void set(size_t i, double val, pair[double,double]& e, string source) except +yodaerr - + errMap errMap() except +yodaerr #}}} Point # Point1D {{{ cdef extern from "YODA/Point1D.h" namespace "YODA": cdef cppclass Point1D(Point): Point1D () except +yodaerr Point1D (Point1D p) except +yodaerr Point1D (double x, double exminus, double explus) except +yodaerr Point1D (double x, double exminus, double explus, string source) except +yodaerr double x() except +yodaerr void setX(double x) except +yodaerr pair[double,double] xErrs() except +yodaerr pair[double,double] xErrs(string source) except +yodaerr void setXErrs(pair[double, double]&) except +yodaerr void setXErrs(pair[double, double]&, string source) except +yodaerr double xErrAvg() except +yodaerr double xErrAvg(string source) except +yodaerr double xMin() except +yodaerr double xMin(string source) except +yodaerr double xMax() except +yodaerr double xMax(string source) except +yodaerr void scaleX(double) except +yodaerr bool operator == (Point1D) except +yodaerr bool operator != (Point1D b) except +yodaerr bool operator < (Point1D b) except +yodaerr bool operator <= (Point1D b) except +yodaerr bool operator > (Point1D b) except +yodaerr bool operator >= (Point1D b) except +yodaerr # }}} Point1D # Point2D {{{ cdef extern from "YODA/Point2D.h" namespace "YODA": cdef cppclass Point2D(Point): Point2D () except +yodaerr Point2D (Point2D p) except +yodaerr Point2D (double x, double y, double exminus, double explus, double eyminus, double eyplus) except +yodaerr Point2D (double x, double y, double exminus, double explus, double eyminus, double eyplus, string source) except +yodaerr double x() except +yodaerr double y() except +yodaerr void setX(double x) except +yodaerr void setY(double y) except +yodaerr pair[double,double] xy() except +yodaerr void setXY(pair[double,double]&) except +yodaerr pair[double,double] xErrs() except +yodaerr pair[double,double] yErrs() except +yodaerr pair[double,double] yErrs(string source) except +yodaerr void setXErrs(pair[double, double]&) except +yodaerr void setYErrs(pair[double, double]&) except +yodaerr void setYErrs(pair[double, double]&, string source) except +yodaerr double xErrAvg() except +yodaerr double yErrAvg() except +yodaerr double yErrAvg(string source) except +yodaerr double xMin() except +yodaerr double xMax() except +yodaerr double yMin() except +yodaerr double yMin(string source) except +yodaerr double yMax() except +yodaerr double yMax(string source) except +yodaerr void scaleX(double) except +yodaerr void scaleY(double) except +yodaerr void scaleXY(double, double) except +yodaerr #void scale(double, double) except +yodaerr bool operator == (Point2D) except +yodaerr bool operator != (Point2D b) except +yodaerr bool operator < (Point2D b) except +yodaerr bool operator <= (Point2D b) except +yodaerr bool operator > (Point2D b) except +yodaerr bool operator >= (Point2D b) except +yodaerr # }}} Point2D # Point3D {{{ cdef extern from "YODA/Point3D.h" namespace "YODA": cdef cppclass Point3D(Point): Point3D () except +yodaerr Point3D (Point3D& p) except +yodaerr Point3D (double x, double y, double z, double exminus, double explus, double eyminus, double eyplus, double ezminus, double ezplus) except +yodaerr Point3D (double x, double y, double z, double exminus, double explus, double eyminus, double eyplus, double ezminus, double ezplus, string source) except +yodaerr double x() except +yodaerr double y() except +yodaerr double z() except +yodaerr void setX(double x) except +yodaerr void setY(double y) except +yodaerr void setZ(double z) except +yodaerr pair[double,double] xErrs() except +yodaerr pair[double,double] yErrs() except +yodaerr pair[double,double] zErrs() except +yodaerr pair[double,double] zErrs(string source) except +yodaerr void setXErrs(pair[double, double]&) except +yodaerr void setYErrs(pair[double, double]&) except +yodaerr void setZErrs(pair[double, double]&) except +yodaerr void setZErrs(pair[double, double]&, string source) except +yodaerr double xErrAvg() double yErrAvg() double zErrAvg() double zErrAvg(string source) double xMin() except +yodaerr double xMax() except +yodaerr double yMin() except +yodaerr double yMax() except +yodaerr double zMin() except +yodaerr double zMin(string source) except +yodaerr double zMax() except +yodaerr double zMax(string source) except +yodaerr void scaleX(double) except +yodaerr void scaleY(double) except +yodaerr void scaleZ(double) except +yodaerr void scaleXYZ(double, double, double) except +yodaerr #void scale(double, double, double) except +yodaerr bool operator == (Point3D b) bool operator != (Point3D b) bool operator < (Point3D b) bool operator <= (Point3D b) bool operator > (Point3D b) bool operator >= (Point3D b) #}}} Point3D # Bin {{{ cdef extern from "YODA/Bin.h" namespace "YODA": cdef cppclass Bin: int dim() except +yodaerr unsigned long numEntries() except +yodaerr double effNumEntries() except +yodaerr double sumW() except +yodaerr double sumW2() except +yodaerr # }}} Bin #Bin1D {{{ cdef extern from "YODA/Bin1D.h" namespace "YODA": cdef cppclass Bin1D[DBN](Bin): Bin1D(pair[double, double] edges) except +yodaerr Bin1D(pair[double, double] edges, DBN dbn) except +yodaerr Bin1D(Bin1D) except +yodaerr # THIS IS A CYTHON LIMITATION... DO NOT CALL THIS Bin1D() # (DO NOT CALL THIS DO NOT CALL THIS) ### ################################################# #We're fine as long as we don't try to instantiate these from Python # void scaleW(double scale) except +yodaerr # void scaleX(double scale) except +yodaerr void reset() except +yodaerr pair[double, double] edges() except +yodaerr double xMin() except +yodaerr double xMax() except +yodaerr double xMid() except +yodaerr double xWidth() except +yodaerr double xFocus() except +yodaerr # x statistics double xMean() except +yodaerr double xVariance() except +yodaerr double xStdDev() except +yodaerr double xStdErr() except +yodaerr double xRMS() except +yodaerr # raw statistics double sumWX() except +yodaerr double sumWX2() except +yodaerr void merge (Bin1D&) except +yodaerr Bin1D operator + (Bin1D&) Bin1D operator - (Bin1D&) ctypedef Bin1D[Dbn1D] Bin1D_Dbn1D ctypedef Bin1D[Dbn2D] Bin1D_Dbn2D ctypedef Bin1D[Dbn3D] Bin1D_Dbn3D #}}} Bin1D # Bin2D {{{ cdef extern from "YODA/Bin2D.h" namespace "YODA": cdef cppclass Bin2D[DBN](Bin): Bin2D(pair[double, double] xedges, pair[double, double] yedges) except+ Bin2D(Bin2D bin) except +yodaerr # CYTHON HACK DO NOT CALL THIS IT DOES NOT EXIST Bin2D() # (DO NOT CALL DO NOT CALL) ################################################ # void scaleW(double scale) except +yodaerr # void scaleXY(double, double) except +yodaerr void reset() except +yodaerr pair[double, double] xEdges() except +yodaerr pair[double, double] yEdges() except +yodaerr double xMin() except +yodaerr double yMin() except +yodaerr double xMax() except +yodaerr double yMax() except +yodaerr double xMid() except +yodaerr double yMid() except +yodaerr double xWidth() except +yodaerr double yWidth() except +yodaerr double area() except +yodaerr double xFocus() except +yodaerr double yFocus() except +yodaerr pair[double, double] xyFocus() except +yodaerr pair[double, double] xyMid() except +yodaerr # x statistics double xMean() except +yodaerr double xVariance() except +yodaerr double xStdDev() except +yodaerr double xStdErr() except +yodaerr double xRMS() except +yodaerr double yMean() except +yodaerr double yVariance() except +yodaerr double yStdDev() except +yodaerr double yStdErr() except +yodaerr double yRMS() except +yodaerr # Raw statistics double sumWX() except +yodaerr double sumWY() except +yodaerr double sumWXY() except +yodaerr double sumWX2() except +yodaerr double sumWY2() except +yodaerr #void merge(Bin2D) except +yodaerr Bin2D operator + (Bin2D) Bin2D operator - (Bin2D) int adjacentTo(Bin2D) except +yodaerr ctypedef Bin2D[Dbn2D] Bin2D_Dbn2D ctypedef Bin2D[Dbn3D] Bin2D_Dbn3D # }}} Bin2D # HistoBin1D {{{ cdef extern from "YODA/HistoBin1D.h" namespace "YODA": cdef cppclass HistoBin1D(Bin1D_Dbn1D): HistoBin1D(double lowedge, double highedge) except +yodaerr HistoBin1D(HistoBin1D) except +yodaerr # void fill(double x, double weight, double fraction) except +yodaerr # void fillBin(double weight, double fraction) except +yodaerr double area() except +yodaerr double height() except +yodaerr double areaErr() except +yodaerr double heightErr() except +yodaerr double relErr() except +yodaerr HistoBin1D operator+(HistoBin1D) HistoBin1D operator-(HistoBin1D) #}}} HistoBin1D cdef extern from "merge.hh": void HistoBin1D_iadd_HistoBin1D "cython_iadd" (HistoBin1D*, HistoBin1D*) void HistoBin1D_isub_HistoBin1D "cython_isub" (HistoBin1D*, HistoBin1D*) # void HistoBin1D_imul_dbl "cython_imul_dbl" (HistoBin1D*, double) # void HistoBin1D_idiv_dbl "cython_idiv_dbl" (HistoBin1D*, double) HistoBin1D* HistoBin1D_add_HistoBin1D "cython_add" (HistoBin1D*, HistoBin1D*) HistoBin1D* HistoBin1D_sub_HistoBin1D "cython_sub" (HistoBin1D*, HistoBin1D*) HistoBin1D* HistoBin1D_div_HistoBin1D "cython_div" (HistoBin1D*, HistoBin1D*) # HistoBin2D {{{ cdef extern from "YODA/HistoBin2D.h" namespace "YODA": cdef cppclass HistoBin2D(Bin2D_Dbn2D): HistoBin2D(double xmin, double xmax, double ymin, double ymax) except +yodaerr HistoBin2D(HistoBin2D) except +yodaerr # void fill(double x, double y, double weight, double fraction) except +yodaerr # void fillBin(double weight, double fraction) except +yodaerr void reset() # Accessors double volume() except +yodaerr double volumeErr() except +yodaerr double height() except +yodaerr double heightErr() except +yodaerr double relErr() except +yodaerr HistoBin2D operator+(HistoBin2D) HistoBin2D operator-(HistoBin2D) #Bin2D_Dbn2D merge(HistoBin2D b) #}}} HistoBin2D # ProfileBin1D {{{ cdef extern from "YODA/ProfileBin1D.h" namespace "YODA": cdef cppclass ProfileBin1D(Bin1D_Dbn2D): ProfileBin1D(ProfileBin1D) except +yodaerr ProfileBin1D(double, double) except +yodaerr #void fill(double x, double y, double weight, double fraction) except +yodaerr #void fillBin(double y, double weight, double fraction) except +yodaerr void reset() except +yodaerr double mean() except +yodaerr double stdDev() except +yodaerr double variance() except +yodaerr double stdErr() except +yodaerr double rms() except +yodaerr double sumWY() except +yodaerr double sumWY2() except +yodaerr ProfileBin1D operator + (ProfileBin1D) ProfileBin1D operator - (ProfileBin1D) # void scaleY(double) except +yodaerr # }}} ProfileBin1D cdef extern from "merge.hh": void ProfileBin1D_iadd_ProfileBin1D "cython_iadd" (ProfileBin1D*, ProfileBin1D*) void ProfileBin1D_isub_ProfileBin1D "cython_isub" (ProfileBin1D*, ProfileBin1D*) # void ProfileBin1D_imul_dbl "cython_imul_dbl" (ProfileBin1D*, double) # void ProfileBin1D_idiv_dbl "cython_idiv_dbl" (ProfileBin1D*, double) ProfileBin1D* ProfileBin1D_add_ProfileBin1D "cython_add" (ProfileBin1D*, ProfileBin1D*) ProfileBin1D* ProfileBin1D_sub_ProfileBin1D "cython_sub" (ProfileBin1D*, ProfileBin1D*) ProfileBin1D* ProfileBin1D_div_ProfileBin1D "cython_div" (ProfileBin1D*, ProfileBin1D*) # ProfileBin2D {{{ cdef extern from "YODA/ProfileBin2D.h" namespace "YODA": cdef cppclass ProfileBin2D(Bin2D_Dbn3D): ProfileBin2D (ProfileBin2D h) except +yodaerr ProfileBin2D (double, double, double, double) except +yodaerr # void fill(double x, double y, double z, double weight, double fraction) except +yodaerr # void fillBin(double z, double weight, double fraction) except +yodaerr double mean() except +yodaerr double stdDev() except +yodaerr double variance() except +yodaerr double stdErr() except +yodaerr double rms() except +yodaerr double sumWZ() except +yodaerr double sumWZ2() except +yodaerr ProfileBin2D operator + (ProfileBin2D) ProfileBin2D operator - (ProfileBin2D) # void scaleZ(double) except +yodaerr # }}} ProfileBin2D # AnalysisObject {{{ cdef extern from "YODA/AnalysisObject.h" namespace "YODA": cdef cppclass AnalysisObject: # Constructors AnalysisObject(string type, string path, string title) except +yodaerr AnalysisObject(string type, string path, AnalysisObject ao, string title) except +yodaerr AnalysisObject() #AnalysisObject* newclone() except +yodaerr ## String used in automatic type determination string type() except +yodaerr ## Data object fill- or plot-space dimension int dim() except +yodaerr ## Annotations vector[string] annotations() except +yodaerr bool hasAnnotation(string key) except +yodaerr string annotation(string key) except +yodaerr string annotation(string key, string default) except +yodaerr void setAnnotation(string, string) except +yodaerr void rmAnnotation(string name) except +yodaerr void clearAnnotations() except +yodaerr ## Standard annotations string title() except +yodaerr void setTitle(string title) except +yodaerr string path() except +yodaerr void setPath(string title) except +yodaerr string name() except +yodaerr # }}} AnalysisObject cdef extern from "YODA/Utils/sortedvector.h" namespace "YODA::Utils": cdef cppclass sortedvector[T](vector): sortedvector(vector[T]) except +yodaerr void insert(T) except +yodaerr # TODO: forward declarations for bin-copying constructors # Counter {{{ cdef extern from "YODA/Counter.h" namespace "YODA": cdef cppclass Counter(AnalysisObject): Counter() except +yodaerr Counter(string path, string title) except +yodaerr #Counter(Dbn0D dbn, string path, string title) except +yodaerr Counter(Counter c, string path) Counter clone() except +yodaerr Counter* newclone() except +yodaerr void reset() except +yodaerr void fill(double weight, double fraction) except +yodaerr unsigned long numEntries() except +yodaerr double effNumEntries() except +yodaerr double sumW() except +yodaerr double sumW2() except +yodaerr double val() except +yodaerr double err() except +yodaerr double relErr() except +yodaerr void scaleW(double) except +yodaerr # operator += (Counter) # operator -= (Counter) Scatter1D Counter_div_Counter "divide" (const Counter&, const Counter&) except +yodaerr Scatter1D Counter_eff_Counter "efficiency" (const Counter&, const Counter&) except +yodaerr cdef extern from "merge.hh": void Counter_iadd_Counter "cython_iadd" (Counter*, Counter*) void Counter_isub_Counter "cython_isub" (Counter*, Counter*) # void Counter_imul_dbl "cython_imul_dbl" (Counter*, double) # void Counter_idiv_dbl "cython_idiv_dbl" (Counter*, double) Counter* Counter_add_Counter "cython_add" (Counter*, Counter*) Counter* Counter_sub_Counter "cython_sub" (Counter*, Counter*) #Counter* Counter_div_Counter "cython_div" (Counter*, Counter*) cdef extern from "YODA/Scatter1D.h" namespace "YODA": Scatter1D mkScatter_Counter "YODA::mkScatter" (const Counter&) except +yodaerr #}}} Counter # Scatter1D {{{ cdef extern from "YODA/Scatter1D.h" namespace "YODA": cdef cppclass Scatter1D(AnalysisObject): Scatter1D() except +yodaerr Scatter1D(string path, string title) except +yodaerr Scatter1D(sortedvector[Point1D], string path, string title) except +yodaerr Scatter1D(vector[double], vector[double], vector[pair[double, double]], vector[pair[double, double]]) except +yodaerr Scatter1D(Scatter1D p, string path) Scatter1D clone() except +yodaerr Scatter1D* newclone() except +yodaerr void reset() except +yodaerr size_t numPoints() except +yodaerr # TODO: have to ignore exception handling on ref-returning methods until Cython bug is fixed vector[Point1D]& points() #except +yodaerr Point1D& point(size_t index) #except +yodaerr void addPoint(const Point1D&) #except +yodaerr void addPoint(double) #except +yodaerr void addPoint(double, const pair[double, double]&) #except +yodaerr void addPoints(const sortedvector[Point1D]&) #except +yodaerr void combineWith(const Scatter1D&) #except +yodaerr void combineWith(const vector[Scatter1D]&) #except +yodaerr void scaleX(double) except +yodaerr - + vector[string] variations() except +yodaerr void Scatter1D_transformX "YODA::transformX" (Scatter1D&, dbl_dbl_fptr) #}}} Scatter1D # cdef extern from "merge.hh": # Scatter2D* Scatter2D_add_Scatter2D "cython_add" (Scatter2D*, Scatter2D*) # Scatter2D* Scatter2D_sub_Scatter2D "cython_sub" (Scatter2D*, Scatter2D*) cdef extern from "YODA/Scatter1D.h" namespace "YODA": Scatter1D mkScatter_Scatter1D "YODA::mkScatter" (const Scatter1D&) except +yodaerr # Scatter2D {{{ cdef extern from "YODA/Scatter2D.h" namespace "YODA": cdef cppclass Scatter2D(AnalysisObject): Scatter2D() except +yodaerr Scatter2D(string path, string title) except +yodaerr Scatter2D(sortedvector[Point2D], string path, string title) except +yodaerr Scatter2D(vector[double], vector[double], vector[pair[double, double]], vector[pair[double, double]]) except +yodaerr Scatter2D(Scatter2D p, string path) Scatter2D clone() except +yodaerr Scatter2D* newclone() except +yodaerr void reset() except +yodaerr size_t numPoints() except +yodaerr # TODO: have to ignore exception handling on ref-returning methods until Cython bug is fixed vector[Point2D]& points() #except +yodaerr Point2D& point(size_t index) #except +yodaerr void addPoint(const Point2D&) #except +yodaerr void addPoint(double, double) #except +yodaerr void addPoint(double, double, const pair[double, double]&, const pair[double, double]&) #except +yodaerr void addPoints(const sortedvector[Point2D]&) #except +yodaerr void combineWith(const Scatter2D&) #except +yodaerr void combineWith(const vector[Scatter2D]&) #except +yodaerr void scaleX(double) except +yodaerr void scaleY(double) except +yodaerr void scaleXY(double, double) except +yodaerr #void scale(double, double) except +yodaerr vector[string] variations() except +yodaerr void Scatter2D_transformX "YODA::transformX" (Scatter2D&, dbl_dbl_fptr) void Scatter2D_transformY "YODA::transformY" (Scatter2D&, dbl_dbl_fptr) #}}} Scatter2D # cdef extern from "merge.hh": # Scatter2D* Scatter2D_add_Scatter2D "cython_add" (Scatter2D*, Scatter2D*) # Scatter2D* Scatter2D_sub_Scatter2D "cython_sub" (Scatter2D*, Scatter2D*) cdef extern from "YODA/Scatter2D.h" namespace "YODA": Scatter2D mkScatter_Scatter2D "YODA::mkScatter" (const Scatter2D&) except +yodaerr # Scatter3D {{{ cdef extern from "YODA/Scatter3D.h" namespace "YODA": cdef cppclass Scatter3D(AnalysisObject): Scatter3D() except +yodaerr Scatter3D(string path, string title) except +yodaerr Scatter3D(sortedvector[Point3D], string path, string title) except +yodaerr Scatter3D(vector[double], vector[double], vector[pair[double, double]], vector[pair[double, double]], vector[pair[double, double]]) except +yodaerr Scatter3D(Scatter3D p, string path) Scatter3D clone() except +yodaerr Scatter3D* newclone() except +yodaerr void reset() except +yodaerr size_t numPoints() except +yodaerr # TODO: have to ignore exception handling on ref-returning methods until Cython bug is fixed sortedvector[Point3D]& points() #except +yodaerr Point3D& point(size_t index) #except +yodaerr void addPoint(const Point3D&) #except +yodaerr void addPoint(double, double, double) #except +yodaerr void addPoint(double, double, double, const pair[double, double]&, const pair[double, double]&, const pair[double, double]&) #except +yodaerr void addPoints(const sortedvector[Point3D]&) #except +yodaerr void combineWith(const Scatter3D&) #except +yodaerr void combineWith(const vector[Scatter3D]&) #except +yodaerr void scaleX(double) except +yodaerr void scaleY(double) except +yodaerr void scaleZ(double) except +yodaerr void scaleXYZ(double, double, double) except +yodaerr #void scale(double, double, double) except +yodaerr - + vector[string] variations() except +yodaerr void Scatter3D_transformX "YODA::transformX" (Scatter3D&, dbl_dbl_fptr) void Scatter3D_transformY "YODA::transformY" (Scatter3D&, dbl_dbl_fptr) void Scatter3D_transformZ "YODA::transformZ" (Scatter3D&, dbl_dbl_fptr) #}}} Scatter3D # cdef extern from "merge.hh": # Scatter3D* Scatter3D_add_Scatter3D "cython_add" (Scatter3D*, Scatter3D*) # Scatter3D* Scatter3D_sub_Scatter3D "cython_sub" (Scatter3D*, Scatter3D*) cdef extern from "YODA/Scatter3D.h" namespace "YODA": Scatter3D mkScatter_Scatter3D "YODA::mkScatter" (const Scatter3D&) except +yodaerr # Histo1D#{{{ cdef extern from "YODA/Histo1D.h" namespace "YODA": cdef cppclass Histo1D(AnalysisObject): Histo1D() except +yodaerr Histo1D(string path, string title) except +yodaerr Histo1D(size_t nbins, double lower, double upper, string path, string title) except +yodaerr Histo1D(vector[double] binedges, string path, string title) except +yodaerr Histo1D(vector[Bin] bins, string path, string title) except +yodaerr Histo1D(Histo1D h, string path) except +yodaerr #Histo1D(Profile1D p, string path) #Histo1D(Scatter2D p, string path) Histo1D clone() except +yodaerr Histo1D* newclone() except +yodaerr void reset() except +yodaerr void fill(double x, double weight, double fraction) except +yodaerr void fillBin(size_t i, double weight, double fraction) except +yodaerr void scaleW(double s) except +yodaerr void normalize(double normto, bool includeoverflows) except +yodaerr void mergeBins(size_t, size_t) except +yodaerr void rebinBy(unsigned int n, size_t begin, size_t end) except +yodaerr void rebinTo(vector[double] edges) except +yodaerr void addBin(double, double) except +yodaerr void addBins(vector[double] edges) except +yodaerr void eraseBin(size_t index) except +yodaerr + vector[double] xEdges() except +yodaerr + double xMin() except +yodaerr double xMax() except +yodaerr - vector[double] xEdges() except +yodaerr size_t numBins() except +yodaerr vector[HistoBin1D]& bins() int binIndexAt(double x) except +yodaerr const HistoBin1D& bin(size_t ix) const HistoBin1D& binAt(double x) except +yodaerr # TODO: Some Cython mapping problem? Dbn1D& totalDbn() Dbn1D& underflow() Dbn1D& overflow() # Whole histo data double integral(bool) double integralTo(int, bool) double integralRange(int, int) unsigned long numEntries(bool) double effNumEntries(bool) double sumW(bool) double sumW2(bool) double xMean(bool) double xVariance(bool) double xStdDev(bool) double xStdErr(bool) double xRMS(bool) # operator == (Histo1D) # operator != (Histo1D) operator + (Histo1D) operator - (Histo1D) operator / (Histo1D) Scatter2D Histo1D_toIntegral "toIntegralHisto" (const Histo1D& h, bool includeunderflow) except +yodaerr Scatter2D Histo1D_toIntegralEff "toIntegralEfficiencyHisto" (const Histo1D& h, bool includeunderflow, bool includeoverflow) except +yodaerr Scatter2D Histo1D_div_Histo1D "divide" (const Histo1D&, const Histo1D&) except +yodaerr Scatter2D Histo1D_eff_Histo1D "efficiency" (const Histo1D&, const Histo1D&) except +yodaerr cdef extern from "merge.hh": void Histo1D_iadd_Histo1D "cython_iadd" (Histo1D*, Histo1D*) void Histo1D_isub_Histo1D "cython_isub" (Histo1D*, Histo1D*) # void Histo1D_imul_dbl "cython_imul_dbl" (Histo1D*, double) # void Histo1D_idiv_dbl "cython_idiv_dbl" (Histo1D*, double) Histo1D* Histo1D_add_Histo1D "cython_add" (Histo1D*, Histo1D*) Histo1D* Histo1D_sub_Histo1D "cython_sub" (Histo1D*, Histo1D*) Histo1D* Histo1D_div_Histo1D "cython_div" (Histo1D*, Histo1D*) cdef extern from "YODA/Scatter2D.h" namespace "YODA": Scatter2D mkScatter_Histo1D "YODA::mkScatter" (const Histo1D&, bool) except +yodaerr #}}} Histo1D # Histo2D {{{ cdef extern from "YODA/Histo2D.h" namespace "YODA": cdef cppclass Histo2D(AnalysisObject): Histo2D() except +yodaerr Histo2D(string path, string title) except +yodaerr Histo2D(size_t nBinsX, double lowerX, double upperX, size_t nBinsY, double lowerY, double upperY, string path, string title) except +yodaerr Histo2D(vector[double] xedges, vector[double] yedges, string path, string title) except +yodaerr Histo2D(Histo2D, string path) #Histo2D(Profile1D p, string path) #Histo2D(Scatter2D p, string path) Histo2D clone() except +yodaerr Histo2D* newclone() except +yodaerr # TODO: add missing functions and enable refs + exceptions when Cython allows void reset() except +yodaerr void fill(double x, double y, double weight, double fraction) except +yodaerr void fillBin(size_t i, double weight, double fraction) except +yodaerr void normalize(double normto, bool includeoverflows) except +yodaerr void scaleW(double scalefactor) except +yodaerr void scaleXY(double, double) # void mergeBins(size_t, size_t) except +yodaerr # void rebin(unsigned int n) except +yodaerr size_t numBins() except +yodaerr size_t numBinsX() except +yodaerr size_t numBinsY() except +yodaerr vector[HistoBin2D]& bins() #except +yodaerr int binIndexAt(double x, double y) except +yodaerr const HistoBin2D& bin(size_t ix) #except +yodaerr const HistoBin2D& binAt(double x, double y) #except +yodaerr void addBin(const pair[double, double]&, const pair[double, double]&) void addBins(const vector[HistoBin2D]&) void addBin(double, double) except +yodaerr void addBins(const vector[double]& edges) except +yodaerr # void eraseBin(size_t index) except +yodaerr + vector[double] xEdges() except +yodaerr + vector[double] yEdges() except +yodaerr + double xMin() except +yodaerr double xMax() except +yodaerr double yMin() except +yodaerr double yMax() except +yodaerr # Dbn2D& outflow(int, int) #except +yodaerr # Whole histo data Dbn2D& totalDbn() #except +yodaerr double integral(bool) unsigned long numEntries(bool) double effNumEntries(bool) double sumW(bool) double sumW2(bool) double xMean(bool) double yMean(bool) double xVariance(bool) double yVariance(bool) double xStdDev(bool) double yStdDev(bool) double xStdErr(bool) double yStdErr(bool) double xRMS(bool) double yRMS(bool) # operator == (Histo2D) # operator != (Histo2D) operator + (Histo2D) operator - (Histo2D) operator / (Histo2D) Scatter3D Histo2D_div_Histo2D "divide" (const Histo2D&, const Histo2D&) except +yodaerr Scatter3D Histo2D_eff_Histo2D "efficiency" (const Histo2D&, const Histo2D&) except +yodaerr cdef extern from "merge.hh": void Histo2D_iadd_Histo2D "cython_iadd" (Histo2D*, Histo2D*) void Histo2D_isub_Histo2D "cython_isub" (Histo2D*, Histo2D*) # void Histo2D_imul_dbl "cython_imul_dbl" (Histo2D*, double) # void Histo2D_idiv_dbl "cython_idiv_dbl" (Histo2D*, double) Histo2D* Histo2D_add_Histo2D "cython_add" (Histo2D*, Histo2D*) Histo2D* Histo2D_sub_Histo2D "cython_sub" (Histo2D*, Histo2D*) Histo2D* Histo2D_div_Histo2D "cython_div" (Histo2D*, Histo2D*) cdef extern from "YODA/Scatter3D.h" namespace "YODA": Scatter3D mkScatter_Histo2D "YODA::mkScatter" (const Histo2D&, bool) except +yodaerr # Histo2D }}} # Profile1D {{{ cdef extern from "YODA/Profile1D.h" namespace "YODA": cdef cppclass Profile1D(AnalysisObject): Profile1D() except +yodaerr Profile1D(string path, string title) except +yodaerr Profile1D(size_t nxbins, double xlower, double xupper, string path, string title) except +yodaerr Profile1D(vector[double] xbinedges, string path, string title) except +yodaerr Profile1D(Profile1D p, string path) except +yodaerr Profile1D(Scatter2D s, string path) except +yodaerr #Profile1D(Histo1D p, string path) Profile1D clone() except +yodaerr Profile1D* newclone() except +yodaerr void reset() except +yodaerr void fill(double x, double y, double weight, double fraction) except +yodaerr void fillBin(size_t i, double y, double weight, double fraction) except +yodaerr void scaleW(double s) except +yodaerr void scaleY(double s) except +yodaerr void mergeBins(size_t, size_t) except +yodaerr void rebinBy(unsigned int n, size_t begin, size_t end) except +yodaerr void rebinTo(vector[double] edges) except +yodaerr void addBin(double, double) except +yodaerr void addBins(vector[double] edges) except +yodaerr # TODO: void eraseBin(size_t index) except +yodaerr + vector[double] xEdges() except +yodaerr + double xMin() except +yodaerr double xMax() except +yodaerr - vector[double] xEdges() except +yodaerr - size_t numBins() except +yodaerr vector[ProfileBin1D] bins() #except +yodaerr int binIndexAt(double x) except +yodaerr const ProfileBin1D& bin(size_t ix) #except +yodaerr const ProfileBin1D& binAt(double x) #except +yodaerr # The trick here is to treat these not as references. # I suppose when you think about it, it makes sense Dbn2D& totalDbn() Dbn2D& underflow() Dbn2D& overflow() unsigned long numEntries(bool) double effNumEntries(bool) double sumW(bool) double sumW2(bool) double xMean(bool) double xVariance(bool) double xStdDev(bool) double xStdErr(bool) double xRMS(bool) operator + (Profile1D) operator - (Profile1D) operator / (Profile1D) Scatter2D Profile1D_div_Profile1D "divide" (const Profile1D&, const Profile1D&) except +yodaerr cdef extern from "merge.hh": void Profile1D_iadd_Profile1D "cython_iadd" (Profile1D*, Profile1D*) void Profile1D_isub_Profile1D "cython_isub" (Profile1D*, Profile1D*) # void Profile1D_imul_dbl "cython_imul_dbl" (Profile1D*, double) # void Profile1D_idiv_dbl "cython_idiv_dbl" (Profile1D*, double) Profile1D* Profile1D_add_Profile1D "cython_add" (Profile1D*, Profile1D*) Profile1D* Profile1D_sub_Profile1D "cython_sub" (Profile1D*, Profile1D*) Profile1D* Profile1D_div_Profile1D "cython_div" (Profile1D*, Profile1D*) cdef extern from "YODA/Scatter2D.h" namespace "YODA": Scatter2D mkScatter_Profile1D "YODA::mkScatter" (const Profile1D&, bool, bool) except +yodaerr #}}} Profile1D # Profile2D {{{ cdef extern from "YODA/Profile2D.h" namespace "YODA": cdef cppclass Profile2D(AnalysisObject): Profile2D() except +yodaerr Profile2D(string path, string title) except +yodaerr Profile2D(size_t nbinsX, double lowerX, double upperX, size_t nbinsY, double lowerY, double upperY, string path, string title) except +yodaerr Profile2D(vector[double] xedges, vector[double] yedges, string path, string title) except +yodaerr Profile2D(Profile2D p, string path) except +yodaerr #Profile2D(Scatter3D s, string path) except +yodaerr #Profile2D(Histo2D p, string path) Profile2D clone() except +yodaerr Profile2D* newclone() except +yodaerr # TODO: add missing functions and enable refs + exceptions when Cython allows void reset() except +yodaerr void fill(double x, double y, double z, double weight, double fraction) except +yodaerr void fillBin(size_t i, double z, double weight, double fraction) except +yodaerr void scaleW(double s) except +yodaerr void scaleXY(double, double) # void mergeBins(size_t, size_t) except +yodaerr # void rebin(unsigned int n) except +yodaerr size_t numBins() except +yodaerr size_t numBinsX() except +yodaerr size_t numBinsY() except +yodaerr vector[ProfileBin2D]& bins() #except +yodaerr int binIndexAt(double x, double y) except +yodaerr const ProfileBin2D& bin(size_t ix) #except +yodaerr const ProfileBin2D& binAt(double x, y) #except +yodaerr void addBin(const pair[double, double]&, const pair[double, double]&) except +yodaerr void addBins(const vector[double]&, const vector[double]&) except +yodaerr # void eraseBin(size_t index) except +yodaerr + vector[double] xEdges() except +yodaerr + vector[double] yEdges() except +yodaerr + double xMin() except +yodaerr double xMax() except +yodaerr double yMin() except +yodaerr double yMax() except +yodaerr # Dbn3D& outflow(int, int) #except +yodaerr # Whole histo data Dbn3D& totalDbn() #except +yodaerr unsigned long numEntries(bool) double effNumEntries(bool) double sumW(bool) double sumW2(bool) double xMean(bool) double yMean(bool) double xVariance(bool) double yVariance(bool) double xStdDev(bool) double yStdDev(bool) double xStdErr(bool) double yStdErr(bool) double xRMS(bool) double yRMS(bool) operator + (Profile2D) operator - (Profile2D) operator / (Profile2D) Scatter3D Profile2D_div_Profile2D "divide" (const Profile2D&, const Profile2D&) except +yodaerr cdef extern from "merge.hh": void Profile2D_iadd_Profile2D "cython_iadd" (Profile2D*, Profile2D*) void Profile2D_isub_Profile2D "cython_isub" (Profile2D*, Profile2D*) # void Profile2D_imul_dbl "cython_imul_dbl" (Profile2D*, double) # void Profile2D_idiv_dbl "cython_idiv_dbl" (Profile2D*, double) Profile2D* Profile2D_add_Profile2D "cython_add" (Profile2D*, Profile2D*) Profile2D* Profile2D_sub_Profile2D "cython_sub" (Profile2D*, Profile2D*) Profile2D* Profile2D_div_Profile2D "cython_div" (Profile2D*, Profile2D*) cdef extern from "YODA/Scatter3D.h" namespace "YODA": Scatter3D mkScatter_Profile2D "YODA::mkScatter" (const Profile2D&, bool, bool) except +yodaerr #}}} Profile2D # Streams {{{ cdef extern from "" namespace "std": cdef cppclass istringstream: istringstream() string& str(string&) cdef cppclass ostringstream: ostringstream() string& str() cdef extern from "YODA/IO.h" namespace "YODA": void IO_read_from_file "YODA::read" (string&, vector[AnalysisObject*]&) except +yodaerr cdef extern from "YODA/Reader.h" namespace "YODA": cdef cppclass Reader: void read(istringstream&, vector[AnalysisObject*]&) except +yodaerr void read_from_file "YODA::Reader::read" (string&, vector[AnalysisObject*]&) except +yodaerr cdef extern from "YODA/ReaderYODA.h" namespace "YODA": Reader& ReaderYODA_create "YODA::ReaderYODA::create" () cdef extern from "YODA/ReaderFLAT.h" namespace "YODA": Reader& ReaderFLAT_create "YODA::ReaderFLAT::create" () cdef extern from "YODA/ReaderAIDA.h" namespace "YODA": Reader& ReaderAIDA_create "YODA::ReaderAIDA::create" () cdef extern from "YODA/Reader.h" namespace "YODA": Reader& Reader_create "YODA::mkReader" (string& filename) cdef extern from "YODA/IO.h" namespace "YODA": void IO_write_to_file "YODA::write" (string&, vector[AnalysisObject*]&) except +yodaerr cdef extern from "YODA/Writer.h" namespace "YODA": cdef cppclass Writer: void write(ostringstream&, vector[AnalysisObject*]&) except +yodaerr void write_to_file "YODA::Writer::write" (string&, vector[AnalysisObject*]&) except +yodaerr cdef extern from "YODA/WriterYODA.h" namespace "YODA": Writer& WriterYODA_create "YODA::WriterYODA::create" () cdef extern from "YODA/WriterFLAT.h" namespace "YODA": Writer& WriterFLAT_create "YODA::WriterFLAT::create" () cdef extern from "YODA/WriterAIDA.h" namespace "YODA": Writer& WriterAIDA_create "YODA::WriterAIDA::create" () cdef extern from "YODA/Reader.h" namespace "YODA": Writer& Writer_create "YODA::mkWriter" (string& filename) # Streams }}} # Axis1D {{{ cdef extern from "YODA/Axis1D.h" namespace "YODA": cdef cppclass Axis1D[BIN1D, DBN]: Axis1D() except +yodaerr Axis1D(vector[double] binedges) except +yodaerr Axis1D(size_t, double, double) except +yodaerr Axis1D(vector[BIN1D] bins) except +yodaerr void addBin(double, double) except +yodaerr size_t numBins() except +yodaerr vector[BIN1D]& bins() double xMin() except +yodaerr double xMax() except +yodaerr vector[double] xEdges() except +yodaerr long getBinIndex(double) void reset() DBN& totalDbn() DBN& underflow() DBN& overflow() void eraseBin(size_t index) except +yodaerr void mergeBins(size_t, size_t) except +yodaerr # Axis1D }}} # Axis2D {{{ cdef extern from "YODA/Axis2D.h" namespace "YODA": cdef cppclass Axis2D[BIN2D, DBN]: Axis2D() except +yodaerr Axis2D(vector[double], vector[double]) except +yodaerr Axis2D(size_t, pair[double, double], size_t, pair[double, double]) except +yodaerr Axis2D(vector[BIN2D] bins) except +yodaerr void addBin(pair[double, double], pair[double, double]) except +yodaerr size_t numBins() except +yodaerr vector[BIN2D]& bins() double xMin() except +yodaerr double xMax() except +yodaerr double yMin() except +yodaerr double yMax() except +yodaerr long getBinIndex(double, double) void reset() DBN& totalDbn() # TODO: reinstate DBN& outflow(int, int) void eraseBin(size_t index) except +yodaerr void mergeBins(size_t, size_t) except +yodaerr # Axis2D }}} diff --git a/pyext/yoda/include/Histo2D.pyx b/pyext/yoda/include/Histo2D.pyx --- a/pyext/yoda/include/Histo2D.pyx +++ b/pyext/yoda/include/Histo2D.pyx @@ -1,491 +1,502 @@ cimport util cdef class Histo2D(AnalysisObject): """ 2D histogram. Complete histogramming is supported, including uniform/regular binning, variable-width bininng, unbinned gaps in the covered range, and outflows (under/overflows around all edges and corners). Rebinning by integer factors, or by explicit merging of contiguous bins is also supported, but in development. Rescaling of weights and/or the x axis is permitted in-place: the result is still a valid Histo2D. Binning-compatible 2D histograms may be divided, resulting in a Scatter3D since further fills would not be meaningful. Several sets of arguments are tried by the constructor in the following order. Histo2D(path="", title=""). Construct a histogram with optional path and title but no bins. Histo2D(nxbins, xlow, xhigh, nybins, ylow, yhigh, path="", title=""). Construct a histogram with nxbins on the x axis and nybins on the y axis, distributed linearly between the respective low--high limits. """ cdef inline c.Histo2D* h2ptr(self) except NULL: return self.ptr() def __init__(self, *args, **kwargs): util.try_loop([self.__init2, self.__init4, self.__init8], *args, **kwargs) def __init2(Histo2D self, path="", title=""): path = path.encode('utf-8') title = title.encode('utf-8') cutil.set_owned_ptr(self, new c.Histo2D(path, title)) def __init4(Histo2D self, xedges, yedges, path="", title=""): path = path.encode('utf-8') title = title.encode('utf-8') # TODO: Do some type-checking and allow iterables of HistoBin2D as well? cutil.set_owned_ptr(self, new c.Histo2D(xedges, yedges, path, title)) def __init8(Histo2D self, nxbins, xlow, xhigh, nybins, ylow, yhigh, path="", title=""): path = path.encode('utf-8') title = title.encode('utf-8') cutil.set_owned_ptr(self, new c.Histo2D(nxbins, xlow, xhigh, nybins, ylow, yhigh, path, title)) def __len__(self): "Number of bins" return self.numBins def __getitem__(self, py_ix): "Direct access to bins" cdef size_t i = cutil.pythonic_index(py_ix, self.h2ptr().numBins()) return cutil.new_borrowed_cls(HistoBin2D, & self.h2ptr().bins().at(i), self) def __repr__(self): return "<%s '%s' %d bins, sumw=%.2g>" % (self.__class__.__name__, self.path, len(self.bins), self.sumW()) def reset(self): """None -> None. Reset the histogram but leave the bin structure.""" self.h2ptr().reset() def clone(self): """None -> Histo2D. Clone this Profile2D.""" return cutil.new_owned_cls(Histo2D, self.h2ptr().newclone()) def fill(self, double x, double y, weight=1.0, fraction=1.0): """(x,y,[w]) -> None. Fill with given x,y values and optional weight.""" self.h2ptr().fill(x, y, weight, fraction) def fillBin(self, size_t i, weight=1.0, fraction=1.0): """(i,[w]) -> None. Fill bin i and optional weight.""" self.h2ptr().fillBin(i, weight, fraction) @property def totalDbn(self): """() -> Dbn2D The Dbn2D representing the total distribution.""" return cutil.new_borrowed_cls(Dbn2D, &self.h2ptr().totalDbn(), self) # TODO: reinstate # def outflow(self, ix, iy): # """(ix,iy) -> Dbn2D # The Dbn2D representing the ix,iy outflow distribution.""" # return cutil.new_borrowed_cls(Dbn2D, &self.h2ptr().outflow(ix, iy), self) def integral(self, includeoverflows=True): """([bool]) -> float Histogram integral, optionally excluding the overflows.""" return self.h2ptr().integral(includeoverflows) def numEntries(self, includeoverflows=True): """([bool]) -> float Number of times this histogram was filled, optionally excluding overflows.""" return self.h2ptr().numEntries(includeoverflows) def effNumEntries(self, includeoverflows=True): """([bool]) -> float Effective number of times this histogram was filled, computed from weights and optionally excluding overflows.""" return self.h2ptr().effNumEntries(includeoverflows) def sumW(self, includeoverflows=True): """([bool]) -> float Sum of weights filled into this histogram.""" return self.h2ptr().sumW(includeoverflows) def sumW2(self, includeoverflows=True): """([bool]) -> float Sum of squared weights filled into this histogram.""" return self.h2ptr().sumW2(includeoverflows) def xMean(self, includeoverflows=True): """([bool]) -> float Mean x of the histogram, optionally excluding the overflows.""" return self.h2ptr().xMean(includeoverflows) def yMean(self, includeoverflows=True): """([bool]) -> float Mean y of the histogram, optionally excluding the overflows.""" return self.h2ptr().yMean(includeoverflows) def xyMean(self, includeoverflows=True): """([bool]) -> (float,float) Mean (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xMean(includeoverflows), self.yMean(includeoverflows)) def xVariance(self, includeoverflows=True): """([bool]) -> float Variance in x of the histogram, optionally excluding the overflows.""" return self.h2ptr().xVariance(includeoverflows) def yVariance(self, includeoverflows=True): """([bool]) -> float Variance in y of the histogram, optionally excluding the overflows.""" return self.h2ptr().yVariance(includeoverflows) def xyVariance(self, includeoverflows=True): """([bool]) -> (float,float) Variances in (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xVariance(includeoverflows), self.yVariance(includeoverflows)) def xStdDev(self, includeoverflows=True): """([bool]) -> float Standard deviation in x of the histogram, optionally excluding the overflows.""" return self.h2ptr().xStdDev(includeoverflows) def yStdDev(self, includeoverflows=True): """([bool]) -> float Standard deviation in y of the histogram, optionally excluding the overflows.""" return self.h2ptr().yStdDev(includeoverflows) def xyStdDev(self, includeoverflows=True): """([bool]) -> (float,float) Standard deviations in (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xStdDev(includeoverflows), self.yStdDev(includeoverflows)) def xStdErr(self, includeoverflows=True): """([bool]) -> float Standard error on the mean x of the histogram, optionally excluding the overflows.""" return self.h2ptr().xStdErr(includeoverflows) def yStdErr(self, includeoverflows=True): """([bool]) -> float Standard error on the mean y of the histogram, optionally excluding the overflows.""" return self.h2ptr().yStdErr(includeoverflows) def xyStdErr(self, includeoverflows=True): """([bool]) -> (float,float) Standard errors on the mean (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xStdErr(includeoverflows), self.yStdErr(includeoverflows)) def xRMS(self, includeoverflows=True): """([bool]) -> float RMS in x of the histogram, optionally excluding the overflows.""" return self.h2ptr().xRMS(includeoverflows) def yRMS(self, includeoverflows=True): """([bool]) -> float RMS in y of the histogram, optionally excluding the overflows.""" return self.h2ptr().yRMS(includeoverflows) def xyRMS(self, includeoverflows=True): """([bool]) -> (float,float) RMS in (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xRMS(includeoverflows), self.yRMS(includeoverflows)) def scaleW(self, w): """(float) -> None. Rescale the weights in this histogram by the factor w.""" self.h2ptr().scaleW(w) def normalize(self, double normto=1.0, bint includeoverflows=True): """(float, bool) -> None. Normalize the histogram.""" self.h2ptr().normalize(normto, includeoverflows) @property def xMin(self): """Low x edge of the histo.""" return self.h2ptr().xMin() @property def xMax(self): """High x edge of the histo.""" return self.h2ptr().xMax() @property def yMin(self): """Low y edge of the histo.""" return self.h2ptr().yMin() @property def yMax(self): """High y edge of the histo.""" return self.h2ptr().yMax() @property def numBins(self): """() -> int Number of bins (not including overflows).""" return self.h2ptr().numBins() @property def numBinsX(self): """() -> int Number of bins (edges) along the x axis.""" return self.h2ptr().numBinsX() @property def numBinsY(self): """() -> int Number of bins (edges) along the y axis.""" return self.h2ptr().numBinsY() @property def bins(self): """Access the ordered bins list.""" return [self.bin(i) for i in xrange( self.h2ptr().numBins())] def bin(self, i): """Get the i'th bin""" # cdef size_t ii = cutil.pythonic_index(i, self.h2ptr().numBins()) return cutil.new_borrowed_cls(HistoBin2D, & self.h2ptr().bin(i), self) # TODO: it's more intuitive to have an index for each axis # def bin(self, i, j): # """Get the (i,j)'th bin""" # # cdef size_t ii = cutil.pythonic_index(i, self.h2ptr().numBins()) # # cdef size_t jj = cutil.pythonic_index(j, self.h2ptr().numBins()) # return cutil.new_borrowed_cls(HistoBin2D, & self.h2ptr().bin(i,j), self) def binIndexAt(self, x, y): """Get the bin index pair containing position (x,y)""" return self.h2ptr().binIndexAt(x, y) def binAt(self, x, y): """Get the bin containing position (x,y)""" # TODO: what's the problem with this direct mapping? Produces compile error re. no default constructor... #return cutil.new_borrowed_cls(HistoBin2D, & self.h2ptr().binAt(x,y), self) # TODO: need out-of-range check to return None? return self.bin(self.binIndexAt(x,y)) def addBin(self, xlow, xhigh, ylow, yhigh): """Add a bin.""" self.h2ptr().addBin(pair[double, double](xlow, xhigh), pair[double, double](ylow, yhigh)) return self def addBins(self, bounds): """Add several bins.""" # TODO: simplify / make consistent for xlow, xhigh, ylow, yhigh in bounds: self.h2ptr().addBin(pair[double, double](xlow, xhigh), pair[double, double](ylow, yhigh)) # def mergeBins(self, size_t a, size_t b): # self.h2ptr().mergeBins(a, b) # def rebin(self, int n): # self.h2ptr().rebin(n) def mkScatter(self, usefocus=False): """None -> Scatter3D. Convert this Histo2D to a Scatter3D, with y representing bin heights (not sumW) and height errors.""" cdef c.Scatter3D s3 = c.mkScatter_Histo2D(deref(self.h2ptr()), usefocus) return cutil.new_owned_cls(Scatter3D, s3.newclone()) def divideBy(self, Histo2D h, efficiency=False): """Histo2D -> Scatter3D Divide this histogram by Histo2D h, returning a Scatter3D. The optional 'efficiency' argument, if set True, will use a binomial efficiency treatment of the errors. """ # if type(h) is not Histo2D: # raise ValueError("Histograms must be of the same type to be divided") # TODO: allow dividing profiles by histos, etc.? (But then what do the errors mean? Add in quad?) cdef c.Scatter3D s if not efficiency: s = c.Histo2D_div_Histo2D(deref(self.h2ptr()), deref(h.h2ptr())) else: s = c.Histo2D_eff_Histo2D(deref(self.h2ptr()), deref(h.h2ptr())) return cutil.new_owned_cls(Scatter3D, s.newclone()) def __iadd__(Histo2D self, Histo2D other): c.Histo2D_iadd_Histo2D(self.h2ptr(), other.h2ptr()) return self def __isub__(Histo2D self, Histo2D other): c.Histo2D_isub_Histo2D(self.h2ptr(), other.h2ptr()) return self def __add__(Histo2D self, Histo2D other): h = Histo2D() cutil.set_owned_ptr(h, c.Histo2D_add_Histo2D(self.h2ptr(), other.h2ptr())) return h def __sub__(Histo2D self, Histo2D other): h = Histo2D() cutil.set_owned_ptr(h, c.Histo2D_sub_Histo2D(self.h2ptr(), other.h2ptr())) return h def __div__(Histo2D self, Histo2D other): return self.divideBy(other) def __truediv__(Histo2D self, Histo2D other): return self.divideBy(other) ## Functions for array-based plotting, chi2 calculations, etc. # def sumWs(self): # """All sumWs of the histo.""" # return [b.sumW for b in self.bins] def _mknp(self, xs): try: import numpy return numpy.array(xs) except ImportError: return xs + def xEdges(self): + """All x edges of the histo.""" + return self._mknp(self.h2ptr().xEdges()) + + def xMins(self): + """All x low edges of the histo.""" + return self._mknp([b.xMin for b in self.bins]) + def xMins(self): """All x low edges of the histo.""" return self._mknp([b.xMin for b in self.bins]) def xMaxs(self): """All x high edges of the histo.""" return self._mknp([b.xMax for b in self.bins]) def xMids(self): """All x bin midpoints of the histo.""" return self._mknp([b.xMid for b in self.bins]) def xFoci(self): """All x bin foci of the histo.""" return self._mknp([b.xFocus for b in self.bins]) def xVals(self, foci=False): return self.xFoci() if foci else self.xMids() def xErrs(self, foci=False): if foci: return [(b.xFocus-b.xMin, b.xMax-b.xFocus) for b in self.bins] else: return [(b.xMid-b.xMin, b.xMax-b.xMid) for b in self.bins] # def xMin(self): # """Lowest x value.""" # return min(self.xMins()) # def xMax(self): # """Highest x value.""" # return max(self.xMaxs()) + def yEdges(self): + """All y edges of the histo.""" + return self._mknp(self.h2ptr().yEdges()) def yMins(self): """All y low edges of the histo.""" return self._mknp([b.yMin for b in self.bins]) def yMaxs(self): """All y high edges of the histo.""" return self._mknp([b.yMax for b in self.bins]) def yMids(self): """All y bin midpoints of the histo.""" return self._mknp([b.yMid for b in self.bins]) def yFoci(self): """All y bin foci of the histo.""" return self._mknp([b.yFocus for b in self.bins]) def yVals(self, foci=False): return self.yFoci() if foci else self.yMids() def yErrs(self, foci=False): if foci: return [(b.yFocus-b.yMin, b.yMax-b.yFocus) for b in self.bins] else: return [(b.yMid-b.yMin, b.yMax-b.yMid) for b in self.bins] # def yMin(self): # """Lowest y value.""" # return min(self.yMins()) # def yMax(self): # """Highest y value.""" # return max(self.yMaxs()) def heights(self): """All y heights of the histo.""" return self._mknp([b.height for b in self.bins]) def volumes(self): """All areas of the histo.""" return self._mknp([b.area for b in self.bins]) def zVals(self, vol=False): return self.volumes() if vol else self.heights() def heightErrs(self): #, asymm=False): """All height errors of the histo. TODO: asymm arg / heightErrsMinus/Plus? """ return self._mknp([b.heightErr for b in self.bins]) def volumeErrs(self): #, asymm=False): """All volume errors of the histo. TODO: asymm arg / areaErrsMinus/Plus? """ # Use symmetrised errors by default, or return a list of (-,+) pairs if asymm is requested.""" # if asymm: # pass #else: return self._mknp([b.volumeErr for b in self.bins]) def zErrs(self, vol=False): return self.volErrs() if vol else self.heightErrs() def zMins(self, area=False): zs = self.zVals(area) es = self.zErrs(area) return self._mknp([z-e for (z,e) in zip(zs,es)]) def zMaxs(self, area=False): zs = self.zVals(area) es = self.zErrs(area) return self._mknp([z+e for (z,e) in zip(zs,es)]) def zMin(self, area=False): """Lowest z value.""" return min(self.zMins(area)) def zMax(self, area=False): """Highest z value.""" return max(self.zMaxs(area)) ## Convenience alias H2D = Histo2D diff --git a/pyext/yoda/include/Profile2D.pyx b/pyext/yoda/include/Profile2D.pyx --- a/pyext/yoda/include/Profile2D.pyx +++ b/pyext/yoda/include/Profile2D.pyx @@ -1,467 +1,475 @@ cimport util cdef class Profile2D(AnalysisObject): """ 2D profile histogram, used to measure mean values of a z variable, binned in x and y. Complete histogramming is supported, including uniform/regular binning, variable-width bininng, unbinned gaps in the covered range, and outflows (under/overflows around all edges and corners). Rebinning by integer factors, or by explicit merging of contiguous bins is also supported, but in development. Rescaling of weights and/or the x axis is permitted in-place: the result is still a valid Histo2D. Binning-compatible 1D histograms may be divided, resulting in a Scatter3D since further fills would not be meaningful. Several sets of arguments are tried by the constructor in the following order. Histo2D(path="", title=""). Construct a histogram with optional path and title but no bins. Histo2D(nxbins, xlow, xhigh, nybins, ylow, yhigh, path="", title=""). Construct a histogram with nxbins on the x axis and nybins on the y axis, distributed linearly between the respective low--high limits. NOT YET FINISHED: please contact the YODA authors if you require extra functionality. """ cdef inline c.Profile2D* p2ptr(self) except NULL: return self.ptr() def __init__(self, *args, **kwargs): util.try_loop([self.__init2, self.__init4, self.__init8], *args, **kwargs) def __init2(Profile2D self, path="", title=""): path = path.encode('utf-8') title = title.encode('utf-8') cutil.set_owned_ptr(self, new c.Profile2D(path, title)) def __init4(Profile2D self, xedges, yedges, path="", title=""): path = path.encode('utf-8') title = title.encode('utf-8') # TODO: Do some type-checking and allow iterables of ProfileBin2D as well? cutil.set_owned_ptr(self, new c.Profile2D(xedges, yedges, path, title)) def __init8(Profile2D self, nxbins, xlow, xhigh, nybins, ylow, yhigh, path="", title=""): path = path.encode('utf-8') title = title.encode('utf-8') cutil.set_owned_ptr(self, new c.Profile2D(nxbins, xlow, xhigh, nybins, ylow, yhigh, path, title)) def __len__(self): return self.p2ptr().numBins() def __getitem__(self, py_ix): "Direct access to bins" cdef size_t i = cutil.pythonic_index(py_ix, self.p2ptr().numBins()) return cutil.new_borrowed_cls(ProfileBin2D, & self.p2ptr().bins().at(i), self) def __repr__(self): return "<%s '%s' %d bins, sumw=%0.2g>" % (self.__class__.__name__, self.path, len(self.bins), self.sumW()) def reset(self): """None -> None. Reset the histogram but leave the bin structure.""" self.p2ptr().reset() def clone(self): """None -> Profile2D. Clone this Profile2D.""" return cutil.new_owned_cls(Profile2D, self.p2ptr().newclone()) def fill(self, double x, double y, double z, double weight=1.0, double fraction=1.0): """(x,y,z,[w]) -> None. Fill with given x,y & z values and optional weight and fill fraction.""" self.p2ptr().fill(x, y, z, weight, fraction) def fillBin(self, size_t i, double z, double weight=1.0, double fraction=1.0): """(i,z,[w]) -> None. Fill bin i with value z and optional weight and fill fraction.""" self.p2ptr().fillBin(i, z, weight, fraction) @property def totalDbn(self): """() -> Dbn3D The Dbn3D representing the total distribution.""" return cutil.new_borrowed_cls( Dbn3D, new c.Dbn3D(self.p2ptr().totalDbn()), self) # TODO: reinstate # def outflow(self, ix, iy): # """(ix,iy) -> Dbn3D # The Dbn3D representing the ix,iy outflow distribution.""" # return cutil.new_borrowed_cls( # Dbn3D, new c.Dbn3D(self.p2ptr().outflow(ix, iy)), self) def numEntries(self, includeoverflows=True): """([bool]) -> float Number of times this histogram was filled, optionally excluding the overflows.""" return self.p2ptr().numEntries(includeoverflows) def effNumEntries(self, includeoverflows=True): """([bool]) -> float Effective number of times this histogram was filled, computed from weights and optionally excluding the overflows.""" return self.p2ptr().effNumEntries(includeoverflows) def sumW(self, includeoverflows=True): """([bool]) -> float Sum of weights filled into this histogram.""" return self.p2ptr().sumW(includeoverflows) def sumW2(self, includeoverflows=True): """([bool]) -> float Sum of squared weights filled into this histogram.""" return self.p2ptr().sumW2(includeoverflows) def xMean(self, includeoverflows=True): """([bool]) -> float Mean x of the histogram, optionally excluding the overflows.""" return self.p2ptr().xMean(includeoverflows) def yMean(self, includeoverflows=True): """([bool]) -> float Mean y of the histogram, optionally excluding the overflows.""" return self.p2ptr().yMean(includeoverflows) def xyMean(self, includeoverflows=True): """([bool]) -> (float,float) Mean (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xMean(includeoverflows), self.yMean(includeoverflows)) def xVariance(self, includeoverflows=True): """([bool]) -> float Variance in x of the histogram, optionally excluding the overflows.""" return self.p2ptr().xVariance(includeoverflows) def yVariance(self, includeoverflows=True): """([bool]) -> float Variance in y of the histogram, optionally excluding the overflows.""" return self.p2ptr().yVariance(includeoverflows) def xyVariance(self, includeoverflows=True): """([bool]) -> (float,float) Variances in (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xVariance(includeoverflows), self.yVariance(includeoverflows)) def xStdDev(self, includeoverflows=True): """([bool]) -> float Standard deviation in x of the histogram, optionally excluding the overflows.""" return self.p2ptr().xStdDev(includeoverflows) def yStdDev(self, includeoverflows=True): """([bool]) -> float Standard deviation in y of the histogram, optionally excluding the overflows.""" return self.p2ptr().yStdDev(includeoverflows) def xyStdDev(self, includeoverflows=True): """([bool]) -> (float,float) Standard deviations in (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xStdDev(includeoverflows), self.yStdDev(includeoverflows)) def xStdErr(self, includeoverflows=True): """([bool]) -> float Standard error on the mean x of the histogram, optionally excluding the overflows.""" return self.p2ptr().xStdErr(includeoverflows) def yStdErr(self, includeoverflows=True): """([bool]) -> float Standard error on the mean y of the histogram, optionally excluding the overflows.""" return self.p2ptr().yStdErr(includeoverflows) def xyStdErr(self, includeoverflows=True): """([bool]) -> (float,float) Standard errors on the mean (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xStdErr(includeoverflows), self.yStdErr(includeoverflows)) def xRMS(self, includeoverflows=True): """([bool]) -> float RMS in x of the histogram, optionally excluding the overflows.""" return self.p2ptr().xRMS(includeoverflows) def yRMS(self, includeoverflows=True): """([bool]) -> float RMS in y of the histogram, optionally excluding the overflows.""" return self.p2ptr().yRMS(includeoverflows) def xyRMS(self, includeoverflows=True): """([bool]) -> (float,float) RMS in (x,y) of the histogram, optionally excluding the overflows.""" return util.XY(self.xRMS(includeoverflows), self.yRMS(includeoverflows)) def scaleW(self, w): """(float) -> None. Rescale the weights in this histogram by the factor w.""" self.p2ptr().scaleW(w) def scaleZ(self, double f): """(float) -> None. Scale the z-direction (profiled value) in this histogram by the factor f.""" self.p1ptr().scaleZ(f) @property def xMin(self): """Low x edge of the histo.""" return self.p2ptr().xMin() @property def xMax(self): """High x edge of the histo.""" return self.p2ptr().xMax() @property def yMin(self): """Low y edge of the histo.""" return self.p2ptr().yMin() @property def yMax(self): """High y edge of the histo.""" return self.p2ptr().yMax() @property def numBins(self): """() -> int Number of bins (not including overflows).""" return self.p2ptr().numBins() @property def numBinsX(self): """() -> int Number of bins (edges) along the x axis.""" return self.p2ptr().numBinsX() @property def numBinsY(self): """() -> int Number of bins (edges) along the y axis.""" return self.p2ptr().numBinsY() @property def bins(self): """Access the ordered bins list.""" return list(self) def bin(self, i): """Get the i'th bin""" # cdef size_t ii = cutil.pythonic_index(i, self.p2ptr().numBins()) return cutil.new_borrowed_cls(ProfileBin2D, & self.p2ptr().bin(i), self) # TODO: it's more intuitive to have an index for each axis # def bin(self, i, j): # """Get the (i,j)'th bin""" # # cdef size_t ii = cutil.pythonic_index(i, self.p2ptr().numBins()) # # cdef size_t jj = cutil.pythonic_index(j, self.p2ptr().numBins()) # return cutil.new_borrowed_cls(ProfileBin2D, & self.p2ptr().bin(i,j), self) def binIndexAt(self, x, y): """Get the bin index pair containing position (x,y)""" return self.p2ptr().binIndexAt(x, y) def binAt(self, x, y): """Get the bin containing position (x,y)""" # TODO: what's the problem with this direct mapping? Produces compile error re. no default constructor... #return cutil.new_borrowed_cls(ProfileBin2D, & self.p2ptr().binAt(x,y), self) # TODO: need out-of-range check to return None? return self.bin(self.binIndexAt(x,y)) def addBin(self, double xlow, double xhigh, double ylow, double yhigh): """Add a bin.""" self.p2ptr().addBin(pair[double, double](xlow, xhigh), pair[double, double](ylow, yhigh)) return self def addBins(self, xcuts, ycuts): """Add several bins.""" # TODO: simplify / make consistent cdef vector[double] _xcuts cdef vector[double] _ycuts for x in xcuts: _xcuts.push_back(x) for y in ycuts: _ycuts.push_back(y) self.p2ptr().addBins(_xcuts, _ycuts) return self # def mergeBins(self, size_t a, size_t b): # self.p2ptr().mergeBins(a, b) # def rebin(self, int n): # self.p2ptr().rebin(n) def mkScatter(self, usefocus=False, usestddev=False): """None -> Scatter3D. Convert this Profile2D to a Scatter3D, with z representing mean bin y values and their standard errors.""" cdef c.Scatter3D s3 = c.mkScatter_Profile2D(deref(self.p2ptr()), usefocus, usestddev) return cutil.new_owned_cls(Scatter3D, s3.newclone()) def divideBy(self, Profile2D h): cdef c.Scatter3D s = c.Profile2D_div_Profile2D(deref(self.p2ptr()), deref(h.p2ptr())) return cutil.new_owned_cls(Scatter3D, s.newclone()) def __iadd__(Profile2D self, Profile2D other): c.Profile2D_iadd_Profile2D(self.p2ptr(), other.p2ptr()) return self def __isub__(Profile2D self, Profile2D other): c.Profile2D_isub_Profile2D(self.p2ptr(), other.p2ptr()) return self def __add__(Profile2D self, Profile2D other): h = Profile2D() cutil.set_owned_ptr(h, c.Profile2D_add_Profile2D(self.p2ptr(), other.p2ptr())) return h def __sub__(Profile2D self, Profile2D other): h = Profile2D() cutil.set_owned_ptr(h, c.Profile2D_sub_Profile2D(self.p2ptr(), other.p2ptr())) return h def __div__(Profile2D self, Profile2D other): return self.divideBy(other) def __truediv__(Profile2D self, Profile2D other): return self.divideBy(other) # def sumWs(self): # """All sumWs of the histo.""" # return [b.sumW for b in self.bins] def _mknp(self, xs): try: import numpy return numpy.array(xs) except ImportError: return xs + def xEdges(self): + """All x edges of the histo.""" + return self._mknp(self.p2ptr().xEdges()) + def xMins(self): """All x low edges of the histo.""" return self._mknp([b.xMin for b in self.bins]) def xMaxs(self): """All x high edges of the histo.""" return self._mknp([b.xMax for b in self.bins]) def xMids(self): """All x bin midpoints of the histo.""" return self._mknp([b.xMid for b in self.bins]) def xFoci(self): """All x bin foci of the histo.""" return self._mknp([b.xFocus for b in self.bins]) def xVals(self, foci=False): return self.xFoci() if foci else self.xMids() def xErrs(self, foci=False): if foci: return [(b.xFocus-b.xMin, b.xMax-b.xFocus) for b in self.bins] else: return [(b.xMid-b.xMin, b.xMax-b.xMid) for b in self.bins] # def xMin(self): # """Lowest x value.""" # return min(self.xMins()) # def xMax(self): # """Highest x value.""" # return max(self.xMaxs()) + def yEdges(self): + """All y edges of the histo.""" + return self._mknp(self.p2ptr().yEdges()) + def yMins(self): """All y low edges of the histo.""" return self._mknp([b.yMin for b in self.bins]) def yMaxs(self): """All y high edges of the histo.""" return self._mknp([b.yMax for b in self.bins]) def yMids(self): """All y bin midpoints of the histo.""" return self._mknp([b.yMid for b in self.bins]) def yFoci(self): """All y bin foci of the histo.""" return self._mknp([b.yFocus for b in self.bins]) def yVals(self, foci=False): return self.yFoci() if foci else self.yMids() def yErrs(self, foci=False): if foci: return [(b.yFocus-b.yMin, b.yMax-b.yFocus) for b in self.bins] else: return [(b.yMid-b.yMin, b.yMax-b.yMid) for b in self.bins] # def yMin(self): # """Lowest y value.""" # return min(self.yMins()) # def yMax(self): # """Highest y value.""" # return max(self.yMaxs()) def zMeans(self): """All y heights of the histo.""" return self._mknp([b.height for b in self.bins]) def zVals(self): return self.zMeans() def zStdErrs(self): """All standard errors on the z means.""" return self._mknp([b.zStdErr for b in self.bins]) def zStdDevs(self): """All standard deviations on the z means.""" return self._mknp([b.zStdDev for b in self.bins]) def zErrs(self, sd=False): return self.zStdDevs() if sd else self.zStdErrs() def zMins(self, sd=False): zs = self.zVals() es = self.zErrs(sd) return self._mknp([z-e for (z,e) in zip(zs,es)]) def zMaxs(self, sd=False): zs = self.zVals() es = self.zErrs(sd) return self._mknp([z+e for (z,e) in zip(zs,es)]) def zMin(self, sd=False): """Lowest z value.""" return min(self.zMins(sd)) def zMax(self, sd=False): """Highest z value.""" return max(self.zMaxs(sd)) ## Convenience alias P2D = Profile2D