Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,1833 +1,1840 @@
+2018-06-01 Louie Corpe <lcorpe@cern.ch>
+
+ * 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 <andy.buckley@cern.ch>
* StringUtils.h: Replace std::ptr_fun (removed in C++17) with a lambda function. Thanks to Stefan Richter.
2018-04-30 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Fix missing lock=false flag initialisation in Histo2D constructor from a Bins vector.
* Improve axis locking error messages.
2017-12-21 Andy Buckley <andy.buckley@cern.ch>
* Version 1.7.0 release
2017-12-11 Andy Buckley <andy.buckley@cern.ch>
* Add Nentries printout to yodals -v
2017-09-18 Andy Buckley <andy.buckley@cern.ch>
* Patches for ROOT conversion from Robert Hatcher -- thanks!
2017-09-16 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Enable compressed writing from Python.
2017-09-13 Andy Buckley <andy.buckley@cern.ch>
* Remove UNUSED macro in favour of anonymous args.
* Enable zipped writing... but only works from C++ so far.
2017-09-11 Andy Buckley <andy.buckley@cern.ch>
* Add HistoBin2D::area(), and provide a default normto=1.0
argument on the Python Histo2D.normalize() method.
2017-09-04 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add optional zlib support via zstr -- massive thanks to Dmitry
Kalinkin for the lovely patch!
2017-08-16 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add parallel/compatibility yoda1 package to aid eventual transition to YODA v2.
2017-07-22 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add convenience aliases H1D, H2D, P1D, P2D, and S1D, S2D, S3D
for the HistoXD, ProfileXD, and ScatterXD classes respectively.
2017-07-08 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Use Python natsort library to sort yodals output if available.
2017-06-18 Andy Buckley <andy.buckley@cern.ch>
* Version 1.6.7 release.
2017-05-12 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add static Reader methods to match the Writer ones.
2017-02-23 Andy Buckley <andy.buckley@cern.ch>
* Fix Histo2D and Profile2D total distribution reading from YODA format.
2017-02-19 Holger Schulz <holger.schulz@durham.ac.uk>
* Convert TH1F to TH1D in root2flat. Much simpler than duplicating
the TH1D stuff in pyext.
2016-12-13 Andy Buckley <andy.buckley@cern.ch>
* Version 1.6.6 release.
2016-12-12 Holger Schulz <holger.schulz@durham.ac.uk>
* Bugfixes in Cython bins accessors for Histo2D.
2016-11-17 Leif Lonnblad <leif.lonnblad@thep.lu.se>
* Fixed warning messages about the obsoleteness of AIDA so that the scripts actually still work.
2016-09-28 Andy Buckley <andy.buckley@cern.ch>
* Version 1.6.5 release, for the benefit of ROOT fans.
* Fix handling of --enable/disable-root configure options.
2016-09-26 David Grellscheid <david.grellscheid@durham.ac.uk>
* Improvements to Cython version testing.
2016-09-25 Andy Buckley <andy.buckley@cern.ch>
* Version 1.6.4 release.
2016-09-20 David Grellscheid <david.grellscheid@durham.ac.uk>
* Remove aliases for @property functions. They were scheduled for
removal anyway, and don't work with Cython >= 24.
2016-09-06 Andy Buckley <andy.buckley@cern.ch>
* Update configure scripts to use newer (Py3-safe) Python testing
macros.
2016-08-09 Andy Buckley <andy.buckley@cern.ch>
* Version 1.6.3 release!
2016-07-22 Andy Buckley <andy.buckley@cern.ch>
* Add 'add' modes for scatter combination to yodamerge.
* Fix yodamerge scatter averaging to use the first AO.
2016-07-21 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Deprecate flat2yoda script and add warning output to it and the AIDA conversion scripts.
* Add a convenience yoda2yoda script.
2016-07-14 Andy Buckley <andy.buckley@cern.ch>
* Try to build PyROOT interface by default, if root-config is found.
2016-07-11 Andy Buckley <andy.buckley@cern.ch>
* Remove accidentally remaining reference to Boost flags in yoda-config.
2016-07-06 Andy Buckley <andy.buckley@cern.ch>
* Version 1.6.2 release!
2016-07-05 Andy Buckley <andy.buckley@cern.ch>
* Pass the toNewScatter3D() scalebyarea flag to the called toScatter3D() functions.
2016-06-06 Andy Buckley <andy.buckley@cern.ch>
* Re-enable the disabled-for-some-reason Scatter1D combineWith Python mappings.
2016-04-28 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Version 1.6.0 release!
2016-04-16 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Remove Boost dependency and require C++11 compilation.
2016-04-08 Andy Buckley <andy.buckley@cern.ch>
* Add a --guess-prefix flag to yoda-config, cf. fastjet-config.
2015-12-20 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Version 1.5.9! (oh no, we're out of convenient version number space!!)
2016-03-08 Andy Buckley <andy.buckley@cern.ch>
* Add abs function to eq calculation in yodadiff.
2016-02-29 Andy Buckley <andy.buckley@cern.ch>
* Remove blocking of builds against ROOT6 -- it works fine.
2016-02-16 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add yoda.HAS_ROOT_SUPPORT flag, for API user convenience.
2015-11-22 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Fix double-dealloc in new Point class hierarchy Python mapping.
2015-10-23 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* yodamerge: add a fix for empty-in-all-runs histo merging; thanks
to Daniel Rauch.
2015-10-04 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Expose the yoda.plot() Python function in a way that doesn't
automatically induce a dependence on matplotlib.
2015-09-30 Andy Buckley <andy.buckley@cern.ch>
* Fix yodals to work with Counters.
2015-09-23 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Further improvements to handling leading _multiple_ # marks on
YODA format BEGIN lines.
2015-09-11 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Version 1.5.1 release.
* Fix bugs in Python wrapper for Point3D.
2015-08-28 Peter Richardson <Peter.Richardson@durham.ac.uk>
* Catch LowStatsError when writing multiple histograms so only the
histogram with the problem is not written
2015-08-28 Andy Buckley <andy.buckley@cern.ch>
* Version 1.5.0 release.
2015-08-24 Andy Buckley <andy.buckley@cern.ch>
* Improve protection of efficiency calculation against the weird
world of general weighted events.
2015-08-17 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Fix cut & paste typo, and add LowStatsError catching in Profile division.
2015-08-11 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Convert the ReaderFLAT parser to also use a simple hand-written parser rather than Spirit.
2015-08-04 Andy Buckley <andy.buckley@cern.ch>
* Add methods for Counter, Axis and Histo1D internal state
access/setting, mainly for new persistency. NEEDS PRE-RELEASE TESTING!!!
2015-07-30 Andy Buckley <andy.buckley@cern.ch>
* Remove # markers from YODA format BEGIN/END output. The parser
will continue to accept them.
2015-07-29 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 1.4.0 release.
2015-06-30 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Fix typos in Point3D Python mapping (accidentally trying to get
the ptr via _Point2D rather than _Point3D).
2015-06-13 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Adding unpatterns arguments to Python read functions, and
auto-conversion from single strings and re.compile()d strs.
2015-06-04 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Bump version for 1.3.1 release.
2015-03-06 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Convert script matching options to use re search rather than match.
* Adding matching options and verbose option to yodals.
2015-01-27 Andy Buckley <andy.buckley@cern.ch>
* Improvements and additions to ROOTCnv.h routines, particularly
to TProfile creation: thanks to Roman Lysak for advice.
2015-01-16 Andy Buckley <andy.buckley@cern.ch>
* Add convenience YODA/YODA.h header.
2015-01-15 Andy Buckley <andy.buckley@cern.ch>
* yodascale now uses PointMatcher and can normalize or multiply to
abs values or ref histos/bin ranges.
2015-01-05 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add a yoda.plotting sub-module, based on matplotlib.
2014-12-03 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Handle overflow filling in binned types without invoking an exception.
* Change inRange to have non-fuzzy comparison behaviour.
2014-11-11 Andy Buckley <andy.buckley@cern.ch>
* Improving/adding __div__ functions in Python for all binned types.
* Add std:: prefix to isinf() calls in BinSearcher.h.
2014-09-30 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* YODA 1.2.1 release!
2014-08-29 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add protection against / characters in histo names in yoda2root
(thanks to Will Bell for the report and suggested patch).
2014-08-17 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Add ROOT version checking to configure. Thanks to Michael Grosse
for the report/request.
2014-08-05 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Don't complain about merge assumptions if there is only one
object with that path name to be 'merged'
2014-06-17 Andy Buckley <andy.buckley@cern.ch>
* Adding explicit int cast in Python wrapping of numEntries functions.
2014-06-13 Andy Buckley <andy.buckley@cern.ch>
* Adding yodals script to list data file contents.
2014-06-11 David Grellscheid <David.Grellscheid@durham.ac.uk>
* pyext/yoda/Makefile.am: 'make distcheck' and out-of-source
builds should work now.
2014-06-10 Andy Buckley <andy.buckley@cern.ch>
* Fix use of the install command for bash completion installation on Macs.
2014-06-06 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Fix silly typos in yodamerge which somehow made it past "make check" testing :-(
2014-06-02 Andy Buckley <andy.buckley@cern.ch>
* YODA 1.0.7 release. DO NOT USE: prefer 1.1.0, above.
2014-05-30 Andy Buckley <andy.buckley@cern.ch>
* 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 <hschulz@physik.hu-berlin.de>
* Some basic (FLAT) write-out capability for 2D histos
2014-05-29 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Mapping the divide and efficiency functions into the Python
interface as class methods, including the __div__ special
function.
2014-05-13 Andy Buckley <andy.buckley@cern.ch>
* Add the AnalysisObject::type() method back in Python (even
though type(ao) is more Pythonic, this may be useful)
2014-05-06 Andy Buckley <andy.buckley@cern.ch>
* Add Profile2D YODA format writing, note need for Scatter format
change, add sumXY storage to both 2D histo types.
2014-05-03 Andy Buckley <andy.buckley@cern.ch>
* Adding YODA reader functionality for Histo2D and Profile2D, but
without outflows support yet.
2014-04-25 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Fixes, script installation, and detailed numerical comparisons
in yodadiff.
2014-04-17 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* YODA 1.0.6 release.
2014-03-06 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <Leif.Lonnblad@thep.lu.se>
* 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 <andy.buckley@cern.ch>
* 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 <frank.siegert@cern.ch>
* Fix race condition with mktemplates.
2014-02-12 David Grellscheid <david.grellscheid@dur.ac.uk>
* Fix bug in mktemplates code (thanks to Christian Johnson for the bug report).
2014-02-09 Andy Buckley <andy.buckley@cern.ch>
* Adding explicit include/generated dir creation to Python
extension build (thanks to Christian Johnson for the bug report).
2014-02-06 Andy Buckley <andy.buckley@cern.ch>
* 1.0.5 release!
2014-02-05 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Improving (i.e. increasing) bin edge overlap tolerance: 1e-10 relative was too tight.
2014-01-31 Andy Buckley <andy.buckley@cern.ch>
* Adding x/yMid etc. methods on Bin1D and 2D, and more related Python API improvements.
2014-01-28 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Improved argument handling for x2y scripts.
2013-11-16 Andy Buckley <andy.buckley@cern.ch>
* Fix to build the Cython rootcompt extension .cpp on request.
2013-11-14 Andy Buckley <andy.buckley@cern.ch>
* Adding flags for the C++11 or C++0x standard if supported, cf. Rivet.
2013-10-24 Andy Buckley <andy.buckley@cern.ch>
* YODA 1.0.4 release.
* Supporting zsh completion via bash completion compatibility.
2013-10-21 Andy Buckley <andy.buckley@cern.ch>
* Removing unused internal iterator typedefs from Writer functions.
2013-10-18 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Improvements to yoda-config and command-line completion, for the
Rivet 2.0.0 release.
2013-10-09 Andy Buckley <andy.buckley@cern.ch>
* Version 1.0.3 release.
2013-10-04 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Adding operator +, -, +=, -= Python mappings wherever possible
for Histo1/2D, Profile1/2D, and Scatter2D.
2013-09-26 Andy Buckley <andy.buckley@cern.ch>
* Cython is no longer needed by tarball users.
2013-09-25 Andy Buckley <andy.buckley@cern.ch>
* Unset path of returned histogram if those of the args to add()
and subtract() are difference.
2013-09-24 Andy Buckley <andy.buckley@cern.ch>
* Python mapping improvements.
2013-09-23 Andy Buckley <andy.buckley@cern.ch>
* Add the -avoid-version flag to libtool.
* Adding more add and subtract special methods in Python.
2013-09-22 Andy Buckley <andy.buckley@cern.ch>
* mkScatter schanged to use histo midpoints rather than focuses by
default for the point x value.
2013-08-14 Andy Buckley <andy.buckley@cern.ch>
* Version 1.0.2.
* Some exception message improvements and improving the protection
of cosmetic mean calculations in WriterYODA.
2013-07-12 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Adding yoda.m4 from James Robinson.
2013-06-06 Hendrik Hoeth <hendrik.hoeth@cern.ch>
* Improve "==" operator in Axis1D and Axis2D
2013-06-06 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Updating the Cython version requirement to 0.18
2013-06-03 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <hendrik.hoeth@cern.ch>
* Adding a reader for FLAT files and a flat2yoda converter
2013-05-27 Andy Buckley <andy.buckley@cern.ch>
* Adding a yoda-completion file for bash.
2013-05-17 Andy Buckley <andy.buckley@cern.ch>
* Mapping HistoBin1D.relErr in Python.
* Adding a non-const points() accessor to Scatter2D.
2013-05-13 Andy Buckley <andy.buckley@cern.ch>
* Adding combined value+error setX/Y functions on Point2D.
* Adding HistoBin1D::relErr()
2013-04-23 Andy Buckley <andy.buckley@cern.ch>
* Adding Python output handling for single AOs and to be able to
use a "-" filename to mean stdout.
2013-04-12 Andy Buckley <andy.buckley@cern.ch>
* Releasing version 1.0.0 -- it seems stable enough.
2013-04-10 Andy Buckley <andy.buckley@cern.ch>
* Being more careful about adding -Wno-* flags to the C++ compiler
used to built the Cython extension lib.
2013-03-22 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Making the x2y converter scripts write a copy into the *current*
directory if only the input is specified.
2013-03-05 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <dave.mallows@gmail.com>
* Adding support for Python >= 2.4 (was Python >= 2.6)
* Fixing miscellaneous warnings on GCC 4.1
2013-01-30 Andy Buckley <andy.buckley@cern.ch>
* Adding a points() method to the Python Scatter2D wrapper.
* Adding a virtual destructor to Bin.
2012-12-30 Andy Buckley <andy.buckley@cern.ch>
* Adding support for Boost.Range arguments and file format autodetection in Writer.
2012-11-24 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Adding yoda-config
2012-11-16 Hendrik Hoeth <hendrik.hoeth@cern.ch>
* Adding WriterFLAT and yoda2flat
2012-11-16 Andy Buckley <andy.buckley@cern.ch>
* 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 <dave.mallows@gmail.com>
* Commited numerous changes to Axis2D. Axis2D now uses BinSearcher as
with Axis1D.
2012-11-15 Andy Buckley <andy.buckley@cern.ch>
* Improving division and efficiency treatments, and allowing
arbitrary f(x), f(y), and flip transformations on Scatter2D.
2012-11-14 Andy Buckley <andy.buckley@cern.ch>
* Converting linspace, logspace, and their usage to place the nbins argument first.
2012-08-07 Andy Buckley <andy.buckley@cern.ch>
* Removing unused (beyond 2nd order) sumWXYZ counter from Dbn3D.
2012-08-07 Dave Mallows <dave.mallows@gmail.com>
* Converted Axis1D to use new Utils/BinSearcher.
2012-08-02 Dave Mallows <dave.mallows@gmail.com>
* Heavily refactored Cython bindings
* HistoBin1D, ProfileBin1D etc. now inherit from Bin1D[DBN]
* Temporarily removed Histo2D, Profile2D and Scatter3D mappings.
2012-07-23 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* Reintroducing Profile2D and Scatter3D.
* Adding axis locking to Axis2D.
* Supporting Histo2D in WriterYODA.
2012-07-02 Andy Buckley <andy.buckley@cern.ch>
* More incremental progress toward a working 2D bin hash mechanism.
2012-05-03 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <hendrik.hoeth@cern.ch>
* ReaderYODA can now parse Histo1D and Profile1D flat files
2011-12-08 Andy Buckley <andy.buckley@cern.ch>
* Adding a Utils::ndarray object and using it to implement a
general Scatter<N> system, with generalised Point<N> and Error<N>
to boot.
2011-12-07 Hendrik Hoeth <hendrik.hoeth@cern.ch>
* Lots of cleanup
2011-12-07 Andy Buckley <andy.buckley@cern.ch>
* 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 <andy.buckley@cern.ch>
* 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 <dave.mallows@gmail.com>
* 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 <dave.mallows@gmail.com>
* Fixed python tests by installing python extension to pyext/build
2011-08-23 Andy Buckley <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* Adding tests to check that implicit construction of Weights
objects from literal doubles and ints works.
2011-07-28 Andy Buckley <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* Add Profile1D and Scatter2D division operators.
* Add xMin/xMax synonyms to the Axis1D, cf. the bins.
2011-07-18 Andy Buckley <andy@insectnation.org>
* Add a first stab at a Histo1D/Histo1D division operator.
2011-07-10 Andy Buckley <andy@insectnation.org>
* Add construction of Histo1Ds from Profile1D and Histo1D, and
construction of Profile1Ds from those and Scatter2D.
2011-07-07 Andy Buckley <andy@insectnation.org>
* Add construction of a Histo1D from Scatter2D.
2011-06-15 Andy Buckley <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* Type annotations in mkScatter
* Added many vector constructors and addPoint functions to
Scatter2D.
2011-01-11 Andy Buckley <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* Enabling quiet compilation.
* More annotation functionality.
2011-01-07 Andy Buckley <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* 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 <andy@insectnation.org>
* Moved duplicate Histo1D/Profile1D code on to Axis, making Axis a
templated class at the same time.
2008-09-12 Andy Buckley <andy@insectnation.org>
* 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 <andy@insectnation.org>
* Added Dbn1D class to centralise the calculation of statistics
from unbounded, unbinned, weighted distributions.
2008-05-15 Andy Buckley <andy@insectnation.org>
* Added Profile1D class.
* Fixed NaN errors from zero weights.
2008-04-14 Andy Buckley <andy@insectnation.org>
* 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/bin/yodamerge b/bin/yodamerge
--- a/bin/yodamerge
+++ b/bin/yodamerge
@@ -1,285 +1,296 @@
#! /usr/bin/env python
"""\
%prog [-o outfile] <yodafile1>[:<scale1>] <yodafile2>[:<scale1>] ...
e.g. %prog run1.yoda run2.yoda run3.yoda (unweighted merging of three runs)
or %prog run1.yoda:2.0 run2.yoda:3.142 (weighted merging of two runs)
Merge analysis objects from multiple YODA files, combining the statistics of
objects whose names are found in multiple files. May be used either to merge
disjoint collections of data objects, or to combine multiple statistically
independent runs of the same data objects into one high-statistics run. Optional
scaling parameters may be given to rescale the weights of the objects on a
per-file basis before merging.
By default the output is written to stdout since we can't guess what would be
a good automatic filename choice! Use the -o option to provide an output filename.
IMPORTANT!
This script is not meant to handle all run merging situations or data objects:
there are limitations to what can be inferred from data objects alone. If you
need to do something more complex than the common cases handled by this script,
please write your own script / program to load and process the data objects.
SCATTERS (E.G. HISTOGRAM RATIOS) CAN'T BE MERGED
Note that 'scatter' data objects, as opposed to histograms, cannot be merged
by this tool since they do not preserve sufficient statistical
information. The canonical example of this is a ratio plot: there are
infinitely many combinations of numerator and denominator which could give the
same ratio, and the result does not indicate anything about which of those
infinite inputs is right (or the effects of correlations in the division).
If you need to merge Scatter2D objects, you can write your own Python script
or C++ program using the YODA interface, and apply whatever case-specific
treatment is appropriate. By default the first such copy encountered will be
returned as the 'merged' output, with no actual merging having been done.
NORMALIZED, UNNORMALIZED, OR A MIX?
An important detail in histogram merging is whether a statistical treatment
for normalized or unnormalized histograms should be used: in the former case
the normalization scaling must be undone *before* the histograms are added
together, and then re-applied afterwards. This script examines the ScaledBy
attribute each histograms to determine if it has been normalized. We make the
assumption that if ScaledBy exists (i.e. h.scaleW has been called) then the
histogram is normalized and we normalize the resulting merged histogram to the
weighted average of input norms; if there is no ScaledBy, we assume that the
histogram is not normalised.
This is not an infallible approach, but we believe is more robust than heuristics
to determine whether norms are sufficiently close to be considered equal.
In complicated situations you will again be better off writing your own
script or program to do the merging: the merging machinery of this script is
available directly in the yoda Python module.
See the source of this script (e.g. use 'less `which %prog`) for more discussion.
"""
# MORE NOTES
#
# If all the input histograms with a particular path are found to have the same
# normalization, and they have ScaledBy attributes indicating that a histogram
# weight scaling has been applied in producing the input histograms, each
# histogram in that group will be first unscaled by their appropriate factor, then
# merged, and then re-normalized to the target value. Otherwise the weights from
# each histogram copy will be directly added together with no attempt to guess an
# appropriate normalization. The normalization guesses (and they are guesses --
# see below) are made *before* application of the per-file scaling arguments.
#
# IMPORTANT: note from the above that this script can't work out what to do
# re. scaling and normalization of output histograms from the input data files
# alone. It may be possible (although unlikely) that input histograms have the
# same normalization but are meant to be added directly. It may also be the case
# (and much more likely) that histograms which should be normalized to a common
# value will not trigger the appropriate treatment due to e.g. statistical
# fluctuations in each run's calculation of a cross-section used in the
# normalization. And anything more complex than a global scaling (e.g. calculation
# of a ratio or asymmetry) cannot be handled at all with a post-hoc scaling
# treatment. The --assume-normalized command line option will force all histograms
# to be treated as if they are normalized in the input, which can be useful if
# you know that all the output histograms are indeed of this nature. If they are
# not, it will go wrong: you have been warned!
#
# Please use this script as a template if you need to do something more specific.
#
# NOTE: there are many possible desired behaviours when merging runs, depending on
# the factors above as well as whether the files being merged are of homogeneous
# type, heterogeneous type, or a combination of both. It is tempting, therefore,
# to add a large number of optional command-line parameters to this script, to
# handle these cases. Experience from Rivet 1.x suggests that this is a bad idea:
# if a problem is of programmatic complexity then a command-line interface which
# attempts to solve it in general is doomed to both failure and unusability. Hence
# we will NOT add extra arguments for applying different merging weights or
# strategies based on analysis object path regexes, auto-identifying 'types' of
# run, etc., etc.: if you need to merge data files in such complex ways, please
# use this script as a template around which to write logic that satisfies your
# particular requirements.
import yoda, optparse, sys, math
parser = optparse.OptionParser(usage=__doc__)
parser.add_option("-o", "--output", default="-", dest="OUTPUT_FILE", metavar="PATH",
help="write output to specified path")
parser.add_option("--s1d-mode", "--s1dmode", default="assume_mean", dest="S1D_MODE", metavar="MODE",
help="choose strategy for combining Scatter1D objects: one of 'first', 'combine', 'assume_mean', 'add'")
parser.add_option("--s2d-mode", "--s2dmode", default="assume_mean", dest="S2D_MODE", metavar="MODE",
help="choose strategy for combining Scatter2D objects: one of 'first', 'combine', 'assume_mean', 'add'")
parser.add_option("--s3d-mode", "--s3dmode", default="assume_mean", dest="S3D_MODE", metavar="MODE",
help="choose strategy for combining Scatter3D objects: one of 'first', 'combine', 'assume_mean', 'add'")
parser.add_option("--type-mismatch-mode", default="scatter", dest="TYPE_MISMATCH_MODE", metavar="MODE",
help="choose strategy for combining objects whose types mismatch: one of 'first', 'scatter'")
parser.add_option("--add", "--stack", action="store_true", default=False, dest="STACK",
help="force simple stacking (also forces all scatter modes to 'add')")
parser.add_option("--no-veto-empty", action="store_false", default=True, dest="VETO_EMPTY",
help="disable the removal of empty (sumW=0) data objects _before_ applying merge heuristics. You probably want the default!")
parser.add_option("--assume-normalized", action="store_true", default=False, dest="ASSUME_NORMALIZED",
help="DEPRECATED, AND DOES NOTHING. This option _used_ to bypass the detection heuristic for unnormalized histograms")
opts, fileargs = parser.parse_args()
## Include scatters in "add" mode
if opts.STACK:
opts.S1D_MODE = "add"
opts.S2D_MODE = "add"
opts.S3D_MODE = "add"
## Put the incoming objects into a dict from each path to a list of histos and scalings
analysisobjects_in = {}
for fa in fileargs:
filename, scale = fa, 1.0
if ":" in fa:
try:
filename, scale = fa.rsplit(":", 1)
scale = float(scale)
except:
sys.stderr.write("Error processing arg '%s' with file:scale format\n" % fa)
aos = yoda.read(filename)
for aopath, ao in aos.items():
ao.setAnnotation("yodamerge_scale", scale)
analysisobjects_in.setdefault(aopath, []).append(ao)
analysisobjects_out = {}
for p, aos in analysisobjects_in.items():
## Identify the canonical aotype being handled from the type of the first entry in aos
aotype = type(aos[0])
## Check that types match, and just output the first one if they don't
if not all(type(ao) is aotype for ao in aos):
msg = "WARNING: cannot merge mismatched analysis object types for path %s: " % p
scatter_fail = False
if opts.TYPE_MISMATCH_MODE == "scatter":
saos = []
for ao in aos:
sao = ao.mkScatter()
sao.setAnnotation("yodamerge_scale", ao.annotation("yodamerge_scale"))
saos.append(sao)
saotype = type(saos[0])
msg += "converting to %ss" % saotype.__name__
if all(type(sao) is saotype for sao in saos):
sys.stderr.write(msg + "\n")
aos = saos
aotype = saotype
else:
msg += "... failed, "
scatter_fail = True
if opts.TYPE_MISMATCH_MODE == "first" or scatter_fail:
sys.stderr.write(msg + "returning first object\n")
analysisobjects_out[p] = aos[0]
continue
## Remove empty fillable data objects, to avoid gotchas where e.g. histos are normalised and hence
## ScaledBy should be set... but isn't because the emptiness blocked rescaling to finite area
if opts.VETO_EMPTY:
# TODO: Add a Fillable interface/ABC and use that for the type matching
if aotype in (yoda.Counter, yoda.Histo1D, yoda.Histo2D, yoda.Profile1D, yoda.Profile2D):
aos_nonzero = [ao for ao in aos if ao.sumW() != 0] #< possible that this doesn't mean no fills :-/
## Just output the first histo if they are all empty
if not aos_nonzero:
analysisobjects_out[p] = aos[0]
continue
## Reset aos to only contain non-empty ones
aos = aos_nonzero
## Counter, Histo and Profile (i.e. Fillable) merging
# TODO: Add a Fillable interface/ABC and use that for the type matching
if aotype in (yoda.Counter, yoda.Histo1D, yoda.Histo2D, yoda.Profile1D, yoda.Profile2D):
## Identify a target rescaling factor from the 1/scalefactor-weighted norms of each run
rescale = None
if len(aos) > 1 and opts.STACK:
pass # we're in dumb stacking mode
elif all("ScaledBy" in ao.annotations for ao in aos):
rescale = 1.0 / sum(float(ao.annotation("yodamerge_scale"))/float(ao.annotation("ScaledBy")) for ao in aos)
elif all("ScaledBy" not in ao.annotations for ao in aos):
pass
else:
sys.stderr.write("WARNING: Abandoning normalized merge of path %s because some but not all inputs have ScaledBy attributes\n" % p)
## Now that the normalization-identifying heuristic is done, apply user scalings and undo the normalization scaling if appropriate
for ao in aos:
ao.scaleW( float(ao.annotation("yodamerge_scale")) )
if rescale:
ao.scaleW( 1.0/float(ao.annotation("ScaledBy")) )
## Make a copy of the (scaled & unnormalized) first object as the basis for the output
## and merge for histograms (including weights, normalization, and user scaling)
ao_out = aos[0].clone()
ao_out.rmAnnotation("yodamerge_scale")
for ao in aos[1:]:
ao_out += ao
if rescale:
ao_out.scaleW(rescale)
## Merge for Scatters, assuming equal run sizes, and applying user scaling
else:
## Make a copy of the first object as the basis for merging (suitable for all Scatter types)
ao_out = aos[0].clone()
ao_out.rmAnnotation("yodamerge_scale")
## If there's only one object, there's no need to do any combining
if len(aos) == 1:
pass
elif aotype in (yoda.Scatter1D,yoda.Scatter2D,yoda.Scatter3D):
## Retrieve dimensionality of the Scatter*D object
dim=ao_out.dim
SND_MODE=getattr(opts,"S%dD_MODE" % dim)
axis=['','x','y','z']
## Use asymptotic mean+stderr convergence statistics
if SND_MODE in ("assume_mean", "add"):
msg = "WARNING: Scatter%dD %s merge assumes asymptotic statistics and equal run sizes" % (dim, p)
if any(float(ao.annotation("yodamerge_scale")) != 1.0 for ao in aos):
msg += " (+ user scaling)"
sys.stderr.write(msg + "\n")
npoints = len(ao_out.points)
for i in range(npoints):
- val_i = ep_i = em_i = scalesum = 0.0
+ val_i = scalesum = 0.0
+ ep_i = {} # will hold the values of the multiple error sources
+ em_i = {} # will hold the values of the multiple error sources
for ao in aos:
scale = float(ao.annotation("yodamerge_scale"))
+ variations=ao.variations()
scalesum += scale
val_i += scale * ao.points[i].val(dim)
- ep_i += (scale * ao.points[i].errs(dim)[0])**2
- em_i += (scale * ao.points[i].errs(dim)[1])**2
- ep_i = math.sqrt(ep_i)
- em_i = math.sqrt(em_i)
+ for var in variations:
+ if not var in ep_i.keys():
+ ep_i[var]=0.
+ em_i[var]=0.
+ ep_i[var] += (scale * ao.points[i].errs(dim,var)[0])**2
+ em_i[var] += (scale * ao.points[i].errs(dim,var)[1])**2
+ for var in ep_i.keys():
+ ep_i[var] = math.sqrt(ep_i[var])
+ em_i[var] = math.sqrt(em_i[var])
if SND_MODE == "assume_mean":
val_i /= scalesum
- ep_i /= scalesum
- em_i /= scalesum
+ for var in ep_i.keys():
+ ep_i[var] /= scalesum
+ em_i[var] /= scalesum
setattr(ao_out.points[i],'%s' % axis[dim], val_i)
- setattr(ao_out.points[i],'%sErrs' % axis[dim], (ep_i, em_i))
+ for var in ep_i.keys():
+ #setattr(ao_out.points[i],'set%sErrs' % axis[dim].upper(), ((ep_i[var], em_i[var]),var))
+ ao_out.points[i].setErrs(dim , (ep_i[var], em_i[var]),var)
## Add more points to the output scatter
elif SND_MODE == "combine":
for ao in aos[1:]:
ao_out.combineWith(ao)
## Just return the first AO unmodified & unmerged
elif SND_MODE == "first":
pass
else:
raise Exception("Unknown Scatter%dD merging mode:" % dim + opts.SND_MODE)
## Other data types (just warn, and write out the first object)
else:
sys.stderr.write("WARNING: Analysis object %s of type %s cannot be merged\n" % (p, str(aotype)))
## Put the output AO into the output dict
analysisobjects_out[p] = ao_out
## Write output
yoda.writeYODA(analysisobjects_out, opts.OUTPUT_FILE)
diff --git a/include/YODA/Point1D.h b/include/YODA/Point1D.h
--- a/include/YODA/Point1D.h
+++ b/include/YODA/Point1D.h
@@ -1,357 +1,355 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#ifndef YODA_POINT1D_H
#define YODA_POINT1D_H
#include "YODA/Point.h"
#include "YODA/Exceptions.h"
#include "YODA/Utils/MathUtils.h"
#include <utility>
namespace YODA {
/// A 1D data point to be contained in a Scatter1D
class Point1D : public Point {
public:
/// @name Constructors
//@{
// Default constructor
Point1D() { }
/// Constructor from values with optional symmetric errors
Point1D(double x, double ex=0.0, std::string source="")
: _x(x)
{
_ex[source] = std::make_pair(ex, ex);
}
/// Constructor from values with explicit asymmetric errors
Point1D(double x, double exminus, double explus, std::string source="")
: _x(x)
{
_ex[source] = std::make_pair(exminus, explus);
}
/// Constructor from values with asymmetric errors
Point1D(double x, const std::pair<double,double>& ex, std::string source="")
: _x(x)
{
_ex[source] = ex;
}
/// Copy constructor
Point1D(const Point1D& p)
: _x(p._x), _ex(p._ex)
{ }
/// Copy assignment
Point1D& operator = (const Point1D& p) {
_x = p._x;
_ex = p._ex;
return *this;
}
//@}
public:
/// Space dimension of the point
size_t dim() { return 1; }
/// @name Value accessors
//@{
/// Get x value
double x() const { return _x; }
/// Set x value
void setX(double x) { _x = x; }
/// @todo Uniform "coords" accessor across all Scatters: returning fixed-size tuple?
//@}
/// @name x error accessors
//@{
/// Get x-error values
const std::pair<double,double>& xErrs( std::string source="") const {
if (!_ex.count(source)) throw RangeError("xErrs has no such key: "+source);
return _ex.at(source);
}
/// Get negative x-error value
double xErrMinus( std::string source="") const {
if (!_ex.count(source)) throw RangeError("xErrs has no such key: "+source);
return _ex.at(source).first;
}
/// Get positive x-error value
double xErrPlus( std::string source="") const {
if (!_ex.count(source)) throw RangeError("xErrs has no such key: "+source);
return _ex.at(source).second;
}
/// Get average x-error value
double xErrAvg( std::string source="") const {
if (!_ex.count(source)) throw RangeError("xErrs has no such key: "+source);
return (_ex.at(source).first + _ex.at(source).second)/2.0;
}
/// Set negative x error
void setXErrMinus(double exminus, std::string source="") {
- if (!_ex.count(source))_ex[source] = std::make_pair(0.,0.);
+ if (!_ex.count(source)) _ex[source] = std::make_pair(0.,0.);
_ex.at(source).first = exminus;
}
/// Set positive x error
void setXErrPlus(double explus, std::string source="") {
- if (!_ex.count(source))_ex[source] = std::make_pair(0.,0.);
+ if (!_ex.count(source)) _ex[source] = std::make_pair(0.,0.);
_ex.at(source).second = explus;
}
/// Set symmetric x error
void setXErr(double ex, std::string source="") {
setXErrMinus(ex, source);
setXErrPlus(ex, source);
}
/// Set symmetric x error (alias)
void setXErrs(double ex, std::string source="") {
setXErr(ex, source);
}
/// Set asymmetric x error
void setXErrs(double exminus, double explus, std::string source="") {
setXErrMinus(exminus, source);
setXErrPlus(explus, source);
}
/// Set asymmetric x error
void setXErrs(const std::pair<double,double>& ex, std::string source="") {
_ex[source] = ex;
}
/// Get value minus negative x-error
- /// @todo Remove (or extend) when multiple errors are supported
double xMin(std::string source="") const {
if (!_ex.count(source)) throw RangeError("xErrs has no such key: "+source);
return _x - _ex.at(source).first;
}
/// Get value plus positive x-error
- /// @todo Remove (or extend) when multiple errors are supported
double xMax(std::string source="") const {
if (!_ex.count(source)) throw RangeError("xErrs has no such key: "+source);
return _x + _ex.at(source).second;
}
//@}
/// @name Combined x value and error setters
//@{
/// Set x value and symmetric error
void setX(double x, double ex, std::string source="") {
setX(x);
setXErr(ex, source);
}
/// Set x value and asymmetric error
void setX(double x, double exminus, double explus, std::string source="") {
setX(x);
setXErrs(exminus, explus, source);
}
/// Set x value and asymmetric error
void setX(double x, std::pair<double,double>& ex, std::string source="") {
setX(x);
setXErrs(ex, source);
}
//@}
// @name Manipulations
//@{
/// Scaling of x axis
void scaleX(double scalex) {
setX(x()*scalex);
for (const auto &source : _ex){
setXErrs(xErrMinus()*scalex, xErrPlus()*scalex, source.first);
}
}
//@}
/// @name Integer axis accessor equivalents
//@{
/// Get the point value for direction @a i
double val(size_t i) const {
if (i == 0 || i > 1) throw RangeError("Invalid axis int, must be in range 1..dim");
return x();
}
/// Set the point value for direction @a i
void setVal(size_t i, double val) {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setX(val);
}
/// Get error map for direction @a i
const std::map< std::string, std::pair<double,double>> & errMap() const {
return _ex;
}
/// Get error values for direction @a i
const std::pair<double,double>& errs(size_t i, std::string source="") const {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
return xErrs(source);
}
/// Get negative error value for direction @a i
double errMinus(size_t i, std::string source="") const {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
return xErrMinus(source);
}
/// Get positive error value for direction @a i
double errPlus(size_t i, std::string source="") const {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
return xErrPlus(source);
}
/// Get average error value for direction @a i
double errAvg(size_t i, std::string source="") const {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
return xErrAvg(source);
}
/// Set negative error for direction @a i
void setErrMinus(size_t i, double eminus, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setXErrMinus(eminus, source);
}
/// Set positive error for direction @a i
void setErrPlus(size_t i, double eplus, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setXErrPlus(eplus, source);
}
/// Set symmetric error for direction @a i
void setErr(size_t i, double e, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setXErr(e, source);
}
/// Set asymmetric error for direction @a i
void setErrs(size_t i, double eminus, double eplus, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setXErrs(eminus, eplus, source);
}
/// Set asymmetric error for direction @a i
void setErrs(size_t i, std::pair<double,double>& e, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setXErrs(e, source);
}
/// Set value and symmetric error for direction @a i
void set(size_t i, double val, double e, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setX(val, e, source);
}
/// Set value and asymmetric error for direction @a i
void set(size_t i, double val, double eminus, double eplus, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setX(val, eminus, eplus, source);
}
/// Set value and asymmetric error for direction @a i
void set(size_t i, double val, std::pair<double,double>& e, std::string source="") {
if (i != 1) throw RangeError("Invalid axis int, must be in range 1..dim");
setX(val, e, source);
}
//@}
protected:
/// @name Value and error variables
//@{
double _x;
// a map of the errors for each source. Nominal stored under ""
// to ensure backward compatibility
std::map< std::string, std::pair<double,double> > _ex;
//@}
};
/// @name Comparison operators
//@{
/// Equality test of x characteristics only
inline bool operator==(const YODA::Point1D& a, const YODA::Point1D& b) {
const bool same_val = YODA::fuzzyEquals(a.x(), b.x());
const bool same_eminus = YODA::fuzzyEquals(a.xErrMinus(), b.xErrMinus());
const bool same_eplus = YODA::fuzzyEquals(a.xErrPlus(), b.xErrPlus());
return same_val && same_eminus && same_eplus;
}
/// Equality test of x characteristics only
inline bool operator != (const YODA::Point1D& a, const YODA::Point1D& b) {
return !(a == b);
}
/// Less-than operator used to sort bins by x-ordering
inline bool operator < (const YODA::Point1D& a, const YODA::Point1D& b) {
if (!YODA::fuzzyEquals(a.x(), b.x())) {
return a.x() < b.x();
}
if (!YODA::fuzzyEquals(a.xErrMinus(), b.xErrMinus())) {
return a.xErrMinus() < b.xErrMinus();
}
if (!YODA::fuzzyEquals(a.xErrPlus(), b.xErrPlus())) {
return a.xErrPlus() < b.xErrPlus();
}
return false;
}
/// Less-than-or-equals operator used to sort bins by x-ordering
inline bool operator <= (const YODA::Point1D& a, const YODA::Point1D& b) {
if (a == b) return true;
return a < b;
}
/// Greater-than operator used to sort bins by x-ordering
inline bool operator > (const YODA::Point1D& a, const YODA::Point1D& b) {
return !(a <= b);
}
/// Greater-than-or-equals operator used to sort bins by x-ordering
inline bool operator >= (const YODA::Point1D& a, const YODA::Point1D& b) {
return !(a < b);
}
//@}
}
#endif
diff --git a/include/YODA/Point2D.h b/include/YODA/Point2D.h
--- a/include/YODA/Point2D.h
+++ b/include/YODA/Point2D.h
@@ -1,548 +1,558 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#ifndef YODA_POINT2D_H
#define YODA_POINT2D_H
#include "YODA/Point.h"
#include "YODA/Exceptions.h"
#include "YODA/Utils/MathUtils.h"
#include <utility>
namespace YODA {
/// A 2D data point to be contained in a Scatter2D
class Point2D : public Point {
public:
/// @name Constructors
//@{
// Default constructor
Point2D() { }
/// Constructor from values with optional symmetric errors
Point2D(double x, double y, double ex=0.0, double ey=0.0, std::string source="")
: _x(x), _y(y)
{
_ex = std::make_pair(ex, ex);
_ey[source] = std::make_pair(ey, ey);
}
/// Constructor from values with explicit asymmetric errors
Point2D(double x, double y,
double exminus,
double explus,
double eyminus,
double eyplus, std::string source="")
: _x(x), _y(y)
{
_ex = std::make_pair(exminus, explus);
_ey[source] = std::make_pair(eyminus, eyplus);
}
// /// Constructor from values with symmetric errors on x and asymmetric errors on y
// Point2D(double x, double y, double ex, const std::pair<double,double>& ey)
// : _x(x), _y(y), _ey(ey)
// {
// _ex = std::make_pair(ex, ex);
// }
// /// Constructor from values with asymmetric errors on x and symmetric errors on y
// Point2D(double x, double y, const std::pair<double,double>& ex, double ey)
// : _x(x), _y(y), _ex(ex)
// {
// _ey = std::make_pair(ey, ey);
// }
/// Constructor from values with asymmetric errors on both x and y
Point2D(double x, double y, const std::pair<double,double>& ex, const std::pair<double,double>& ey, std::string source="")
: _x(x), _y(y)
{
_ex = ex;
_ey[source] = ey;
- }
+ }
/// Copy constructor
Point2D(const Point2D& p)
: _x(p._x), _y(p._y)
{
_ex = p._ex;
_ey = p._ey;
- }
+ }
/// Copy assignment
Point2D& operator = (const Point2D& p) {
_x = p._x;
_y = p._y;
_ex = p._ex;
_ey = p._ey;
return *this;
}
//@}
public:
/// Space dimension of the point
size_t dim() { return 2; }
/// @name Value accessors
//@{
/// Get x value
double x() const { return _x; }
/// Set x value
void setX(double x) { _x = x; }
/// Get y value
double y() const { return _y; }
/// Set y value
void setY(double y) { _y = y; }
/// @todo Uniform "coords" accessor across all Scatters: returning fixed-size tuple?
/// Get x,y value pair
std::pair<double,double> xy() const { return std::make_pair(_x, _y); }
/// Set x and y values
void setXY(double x, double y) { setX(x); setY(y); }
/// Set x and y values
void setXY(const std::pair<double,double>& xy) { setX(xy.first); setY(xy.second); }
//@}
/// @name x error accessors
//@{
- /// Get error map for direction @a i
- const std::map< std::string, std::pair<double,double>> & errMap() const {
- return _ey;
- }
/// Get x-error values
const std::pair<double,double>& xErrs() const {
return _ex;
}
/// Get negative x-error value
double xErrMinus() const {
return _ex.first;
}
/// Get positive x-error value
double xErrPlus() const {
return _ex.second;
}
/// Get average x-error value
double xErrAvg() const {
return (_ex.first + _ex.second)/2.0;
}
/// Set negative x error
void setXErrMinus(double exminus) {
_ex.first = exminus;
}
/// Set positive x error
void setXErrPlus(double explus) {
_ex.second = explus;
}
/// Set symmetric x error
void setXErr(double ex) {
setXErrMinus(ex);
setXErrPlus(ex);
}
/// Set symmetric x error (alias)
void setXErrs(double ex) {
setXErr(ex);
}
/// Set asymmetric x error
void setXErrs(double exminus, double explus) {
setXErrMinus(exminus);
setXErrPlus(explus);
}
/// Set asymmetric x error
void setXErrs(const std::pair<double,double>& ex) {
_ex = ex;
}
/// Get value minus negative x-error
/// @todo Remove (or extend) when multiple errors are supported
+ /// No: doesn't need to change since (for now) we only store multiple
+ /// errors for the highest dimentsion
double xMin() const {
return _x - _ex.first;
}
/// Get value plus positive x-error
/// @todo Remove (or extend) when multiple errors are supported
+ /// No: doesn't need to change since (for now) we only store multiple
+ /// errors for the highest dimentsion
double xMax() const {
return _x + _ex.second;
}
//@}
/// @name y error accessors
//@{
/// Get y-error values
const std::pair<double,double>& yErrs(std::string source="") const {
+ if (!_ey.count(source)) throw RangeError("yErrs has no such key: "+source);
return _ey.at(source);
}
/// Get negative y-error value
double yErrMinus(std::string source="") const {
+ if (!_ey.count(source)) throw RangeError("yErrs has no such key: "+source);
return _ey.at(source).first;
}
/// Get positive y-error value
double yErrPlus(std::string source="") const {
+ if (!_ey.count(source)) throw RangeError("yErrs has no such key: "+source);
return _ey.at(source).second;
}
/// Get average y-error value
double yErrAvg(std::string source="") const {
+ if (!_ey.count(source)) throw RangeError("yErrs has no such key: "+source);
return (_ey.at(source).first + _ey.at(source).second)/2.0;
}
/// Set negative y error
void setYErrMinus(double eyminus, std::string source="") {
+ if (!_ey.count(source)) _ey[source] = std::make_pair(0.,0.);
_ey.at(source).first = eyminus;
}
/// Set positive y error
void setYErrPlus(double eyplus, std::string source="") {
+ if (!_ey.count(source)) _ey[source] = std::make_pair(0.,0.);
_ey.at(source).second = eyplus;
}
/// Set symmetric y error
void setYErr(double ey, std::string source="") {
setYErrMinus(ey, source );
setYErrPlus(ey, source );
}
/// Set symmetric y error (alias)
void setYErrs(double ey, std::string source="") {
setYErr(ey, source);
}
/// Set asymmetric y error
void setYErrs(double eyminus, double eyplus, std::string source="") {
setYErrMinus(eyminus, source);
setYErrPlus(eyplus, source );
}
/// Set asymmetric y error
void setYErrs(const std::pair<double,double>& ey, std::string source="") {
- _ey.at(source) = ey;
+ _ey[source] = ey;
}
/// Get value minus negative y-error
- /// @todo Remove (or extend) when multiple errors are supported
double yMin(std::string source="") const {
+ if (!_ey.count(source)) throw RangeError("yErrs has no such key: "+source);
return _y - _ey.at(source).first;
}
/// Get value plus positive y-error
- /// @todo Remove (or extend) when multiple errors are supported
double yMax(std::string source="") const {
+ if (!_ey.count(source)) throw RangeError("yErrs has no such key: "+source);
return _y + _ey.at(source).second;
}
//@}
- /// @todo Support multiple errors
/// @name Combined x/y value and error setters
//@{
/// Set x value and symmetric error
void setX(double x, double ex) {
setX(x);
setXErrs(ex);
}
/// Set x value and asymmetric error
void setX(double x, double exminus, double explus) {
setX(x);
setXErrs(exminus, explus);
}
/// Set x value and asymmetric error
void setX(double x, std::pair<double,double>& ex) {
setX(x);
setXErrs(ex);
}
/// Set y value and symmetric error
void setY(double y, double ey, std::string source="") {
setY(y);
setYErrs(ey, source);
}
/// Set y value and asymmetric error
void setY(double y, double eyminus, double eyplus, std::string source="") {
setY(y);
setYErrs(eyminus, eyplus, source);
}
/// Set y value and asymmetric error
void setY(double y, std::pair<double,double>& ey, std::string source="") {
setY(y);
setYErrs(ey, source);
}
//@}
// @name Manipulations
//@{
/// Scaling of x axis
void scaleX(double scalex) {
setX(x()*scalex);
setXErrs(xErrMinus()*scalex, xErrPlus()*scalex);
}
/// Scaling of y axis
void scaleY(double scaley) {
setY(y()*scaley);
- for (const auto &source : _ey){
- setYErrs(yErrMinus()*scaley, yErrPlus()*scaley, source.first);
- }
+ for (const auto &source : _ey){
+ setYErrs(yErrMinus()*scaley, yErrPlus()*scaley, source.first);
+ }
}
/// Scaling of both axes
void scaleXY(double scalex, double scaley) {
scaleX(scalex);
scaleY(scaley);
}
/// Scaling of both axes
/// @deprecated Use scaleXY
void scale(double scalex, double scaley) {
scaleXY(scalex, scaley);
}
//@}
/// @name Integer axis accessor equivalents
//@{
/// Get the point value for direction @a i
double val(size_t i) const {
switch (i) {
case 1: return x();
case 2: return y();
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set the point value for direction @a i
void setVal(size_t i, double val) {
switch (i) {
case 1: setX(val); break;
case 2: setY(val); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
+
+ /// Get error map for direction @a i
+ const std::map< std::string, std::pair<double,double>> & errMap() const {
+ return _ey;
+ }
/// Get error values for direction @a i
const std::pair<double,double>& errs(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrs();
case 2: return yErrs(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Get negative error value for direction @a i
double errMinus(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrMinus();
case 2: return yErrMinus(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Get positive error value for direction @a i
double errPlus(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrPlus();
case 2: return yErrPlus(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Get average error value for direction @a i
double errAvg(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrAvg();
case 2: return yErrAvg(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set negative error for direction @a i
void setErrMinus(size_t i, double eminus, std::string source="") {
switch (i) {
case 1: setXErrMinus(eminus); break;
case 2: setYErrMinus(eminus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set positive error for direction @a i
void setErrPlus(size_t i, double eplus, std::string source="") {
switch (i) {
case 1: setXErrPlus(eplus); break;
case 2: setYErrPlus(eplus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set symmetric error for direction @a i
void setErr(size_t i, double e, std::string source="") {
switch (i) {
case 1: setXErrs(e); break;
case 2: setYErrs(e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set asymmetric error for direction @a i
void setErrs(size_t i, double eminus, double eplus, std::string source="") {
switch (i) {
case 1: setXErrs(eminus, eplus); break;
case 2: setYErrs(eminus, eplus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set asymmetric error for direction @a i
void setErrs(size_t i, std::pair<double,double>& e, std::string source="") {
switch (i) {
case 1: setXErrs(e); break;
case 2: setYErrs(e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set value and symmetric error for direction @a i
void set(size_t i, double val, double e, std::string source="") {
switch (i) {
case 1: setX(val, e); break;
case 2: setY(val, e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set value and asymmetric error for direction @a i
void set(size_t i, double val, double eminus, double eplus, std::string source="") {
switch (i) {
case 1: setX(val, eminus, eplus); break;
case 2: setY(val, eminus, eplus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set value and asymmetric error for direction @a i
void set(size_t i, double val, std::pair<double,double>& e, std::string source="") {
switch (i) {
case 1: setX(val, e); break;
case 2: setY(val, e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
//@}
protected:
/// @name Value and error variables
//@{
double _x;
double _y;
std::pair<double,double> _ex;
- //std::pair<double,double> _ey;
- //std::map< std::string, std::pair<double,double> > _ex;
- std::map< std::string, std::pair<double,double> > _ey;
+ // a map of the errors for each source. Nominal stored under ""
+ // to ensure backward compatibility
+ std::map< std::string, std::pair<double,double> > _ey;
//@}
};
/// @name Comparison operators
//@{
/// Equality test of x characteristics only
/// @todo Need to add y comparisons, too
inline bool operator==(const YODA::Point2D& a, const YODA::Point2D& b) {
const bool same_val = YODA::fuzzyEquals(a.x(), b.x());
const bool same_eminus = YODA::fuzzyEquals(a.xErrMinus(), b.xErrMinus());
const bool same_eplus = YODA::fuzzyEquals(a.xErrPlus(), b.xErrPlus());
return same_val && same_eminus && same_eplus;
}
/// Equality test of x characteristics only
inline bool operator != (const YODA::Point2D& a, const YODA::Point2D& b) {
return !(a == b);
}
/// Less-than operator used to sort bins by x-ordering
inline bool operator < (const YODA::Point2D& a, const YODA::Point2D& b) {
if (!YODA::fuzzyEquals(a.x(), b.x())) {
return a.x() < b.x();
}
if (!YODA::fuzzyEquals(a.xErrMinus(), b.xErrMinus())) {
return a.xErrMinus() < b.xErrMinus();
}
if (!YODA::fuzzyEquals(a.xErrPlus(), b.xErrPlus())) {
return a.xErrPlus() < b.xErrPlus();
}
return false;
}
/// Less-than-or-equals operator used to sort bins by x-ordering
inline bool operator <= (const YODA::Point2D& a, const YODA::Point2D& b) {
if (a == b) return true;
return a < b;
}
/// Greater-than operator used to sort bins by x-ordering
inline bool operator > (const YODA::Point2D& a, const YODA::Point2D& b) {
return !(a <= b);
}
/// Greater-than-or-equals operator used to sort bins by x-ordering
inline bool operator >= (const YODA::Point2D& a, const YODA::Point2D& b) {
return !(a < b);
}
//@}
}
#endif
diff --git a/include/YODA/Point3D.h b/include/YODA/Point3D.h
--- a/include/YODA/Point3D.h
+++ b/include/YODA/Point3D.h
@@ -1,654 +1,666 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#ifndef YODA_POINT3D_H
#define YODA_POINT3D_H
#include "YODA/Point.h"
#include "YODA/Exceptions.h"
#include "YODA/Utils/MathUtils.h"
#include <utility>
namespace YODA {
/// A 3D data point to be contained in a Scatter3D
class Point3D : public Point {
public:
/// @name Constructors
//@{
// Default constructor
Point3D() { }
/// Constructor from values with optional symmetric errors
Point3D(double x, double y, double z, double ex=0.0, double ey=0.0, double ez=0.0, std::string source="")
: _x(x), _y(y), _z(z)
{
_ex = std::make_pair(ex, ex);
_ey = std::make_pair(ey, ey);
_ez[source] = std::make_pair(ez, ez);
}
/// Constructor from values with explicit asymmetric errors
Point3D(double x, double y, double z,
double exminus,
double explus,
double eyminus,
double eyplus,
double ezminus,
double ezplus, std::string source="")
: _x(x), _y(y), _z(z)
{
_ex = std::make_pair(exminus, explus);
_ey = std::make_pair(eyminus, eyplus);
+ _ez[source] = std::make_pair(ezminus, ezplus);
}
/// Constructor from asymmetric errors given as vectors
Point3D(double x, double y, double z,
const std::pair<double,double>& ex,
const std::pair<double,double>& ey,
const std::pair<double,double>& ez, std::string source="")
: _x(x), _y(y), _z(z),
_ex(ex), _ey(ey)
{
_ez[source] = ez;
- }
+ }
/// Copy constructor
Point3D(const Point3D& p)
: _x(p._x), _y(p._y), _z(p._z),
_ex(p._ex), _ey(p._ey), _ez(p._ez)
{ }
/// Copy assignment
Point3D& operator = (const Point3D& p) {
_x = p._x;
_y = p._y;
_z = p._z;
_ex = p._ex;
_ey = p._ey;
_ez = p._ez;
return *this;
}
//@}
public:
/// Space dimension of the point
size_t dim() { return 3; }
/// @name Value and error accessors
//@{
/// Get x value
double x() const { return _x; }
/// Set x value
void setX(double x) { _x = x; }
/// Get y value
double y() const { return _y; }
/// Set y value
void setY(double y) { _y = y; }
/// Get z value
double z() const { return _z;}
/// Set z value
void setZ(double z) { _z = z;}
/// @todo Uniform "coords" accessor across all Scatters: returning fixed-size tuple?
// /// Get x,y,z value tuple
// triple<double,double,double> xyz() const { return std::triple(_x, _y, _z); }
/// Set x, y and z values
void setXYZ(double x, double y, double z) { setX(x); setY(y); setZ(z); }
// /// Set x and y values
// void setXY(triple<double,double,double> xyz) { setX(xy.first); setY(xy.second); setZ(xy.third); }
//@}
/// @name x error accessors
//@{
/// Get x-error values
const std::pair<double,double>& xErrs() const {
return _ex;
}
/// Get negative x-error value
double xErrMinus() const {
return _ex.first;
}
/// Get positive x-error value
double xErrPlus() const {
return _ex.second;
}
/// Get average x-error value
double xErrAvg() const {
return (_ex.first + _ex.second)/2.0;
}
/// Set negative x error
void setXErrMinus(double exminus) {
_ex.first = exminus;
}
/// Set positive x error
void setXErrPlus(double explus) {
_ex.second = explus;
}
/// Set symmetric x error
void setXErr(double ex) {
setXErrMinus(ex);
setXErrPlus(ex);
}
/// Set symmetric x error (alias)
void setXErrs(double ex) {
setXErr(ex);
}
/// Set asymmetric x error
void setXErrs(double exminus, double explus) {
setXErrMinus(exminus);
setXErrPlus(explus);
}
/// Set asymmetric x error
void setXErrs(const std::pair<double,double>& ex) {
_ex = ex;
}
/// Get value minus negative x-error
double xMin() const {
return _x - _ex.first;
}
/// Get value plus positive x-error
double xMax() const {
return _x + _ex.second;
}
//@}
/// @name y error accessors
//@{
/// Get y-error values
const std::pair<double,double>& yErrs() const {
return _ey;
}
/// Get negative y-error value
double yErrMinus() const {
return _ey.first;
}
/// Get positive y-error value
double yErrPlus() const {
return _ey.second;
}
/// Get average y-error value
double yErrAvg() const {
return (_ey.first + _ey.second)/2.0;
}
/// Set negative y error
void setYErrMinus(double eyminus) {
_ey.first = eyminus;
}
/// Set positive y error
void setYErrPlus(double eyplus) {
_ey.second = eyplus;
}
/// Set symmetric y error
void setYErr(double ey) {
setYErrMinus(ey);
setYErrPlus(ey);
}
/// Set symmetric y error (alias)
void setYErrs(double ey) {
setYErr(ey);
}
/// Set asymmetric y error
void setYErrs(double eyminus, double eyplus) {
setYErrMinus(eyminus);
setYErrPlus(eyplus);
}
/// Set asymmetric y error
void setYErrs(const std::pair<double,double>& ey) {
_ey = ey;
}
/// Get value minus negative y-error
double yMin() const {
return _y - _ey.first;
}
/// Get value plus positive y-error
double yMax() const {
return _y + _ey.second;
}
//@}
/// @name z error accessors
//@{
- /// Get error map for direction @a i
- const std::map< std::string, std::pair<double,double>> & errMap() const {
- return _ez;
- }
/// Get z-error values
const std::pair<double,double>& zErrs( std::string source="") const {
+ if (!_ez.count(source)) throw RangeError("zErrs has no such key: "+source);
return _ez.at(source);
}
/// Get negative z-error value
double zErrMinus( std::string source="") const {
+ if (!_ez.count(source)) throw RangeError("zErrs has no such key: "+source);
return _ez.at(source).first;
}
/// Get positive z-error value
double zErrPlus( std::string source="") const {
+ if (!_ez.count(source)) throw RangeError("zErrs has no such key: "+source);
return _ez.at(source).second;
}
/// Get average z-error value
double zErrAvg( std::string source="") const {
+ if (!_ez.count(source)) throw RangeError("zErrs has no such key: "+source);
return (_ez.at(source).first + _ez.at(source).second)/2.0;
}
/// Set negative z error
void setZErrMinus(double ezminus, std::string source="") {
+ if (!_ez.count(source)) _ez[source] = std::make_pair(0.,0.);
_ez.at(source).first = ezminus;
}
/// Set positive z error
void setZErrPlus(double ezplus, std::string source="") {
+ if (!_ez.count(source)) _ez[source] = std::make_pair(0.,0.);
_ez.at(source).second = ezplus;
}
/// Set symmetric z error
void setZErr(double ez, std::string source="") {
setZErrMinus(ez, source);
setZErrPlus(ez, source);
}
/// Set symmetric z error (alias)
void setZErrs(double ez, std::string source="") {
setZErr(ez, source);
}
/// Set asymmetric z error
void setZErrs(double ezminus, double ezplus, std::string source="") {
setZErrMinus(ezminus, source);
setZErrPlus(ezplus, source);
}
/// Set asymmetric z error
void setZErrs(const std::pair<double,double>& ez, std::string source="") {
_ez[source] = ez;
}
/// Get value minus negative z-error
double zMin( std::string source="") const {
+ if (!_ez.count(source)) throw RangeError("zErrs has no such key: "+source);
return _z - _ez.at(source).first;
}
/// Get value plus positive z-error
double zMax( std::string source="") const {
+ if (!_ez.count(source)) throw RangeError("zErrs has no such key: "+source);
return _z + _ez.at(source).second;
}
//@}
/// @name Combined x/y value and error setters
//@{
/// Set x value and symmetric error
void setX(double x, double ex) {
setX(x);
setXErrs(ex);
}
/// Set x value and asymmetric error
void setX(double x, double exminus, double explus) {
setX(x);
setXErrs(exminus, explus);
}
/// Set x value and asymmetric error
void setX(double x, std::pair<double,double>& ex) {
setX(x);
setXErrs(ex);
}
/// Set y value and symmetric error
void setY(double y, double ey) {
setY(y);
setYErrs(ey);
}
/// Set y value and asymmetric error
void setY(double y, double eyminus, double eyplus) {
setY(y);
setYErrs(eyminus, eyplus);
}
/// Set y value and asymmetric error
void setY(double y, std::pair<double,double>& ey) {
setY(y);
setYErrs(ey);
}
/// Set z value and symmetric error
void setZ(double z, double ez, std::string source="") {
setZ(z);
setZErrs(ez, source);
}
/// Set z value and asymmetric error
void setZ(double z, double ezminus, double ezplus, std::string source="") {
setZ(z);
setZErrs(ezminus, ezplus, source);
}
/// Set z value and asymmetric error
void setZ(double z, std::pair<double,double>& ez, std::string source="") {
setZ(z);
setZErrs(ez, source);
}
//@}
// @name Manipulations
//@{
/// Scaling of x axis
void scaleX(double scalex) {
setX(x()*scalex);
setXErrs(xErrMinus()*scalex, xErrPlus()*scalex);
}
/// Scaling of y axis
void scaleY(double scaley) {
setY(y()*scaley);
setYErrs(yErrMinus()*scaley, yErrPlus()*scaley);
}
/// Scaling of z axis
void scaleZ(double scalez) {
setZ(z()*scalez);
- for (const auto &source : _ez){
+ for (const auto &source : _ez){
setZErrs(zErrMinus()*scalez, zErrPlus()*scalez, source.first);
- }
+ }
}
/// Scaling of all three axes
void scaleXYZ(double scalex, double scaley, double scalez) {
scaleX(scalex);
scaleY(scaley);
scaleZ(scalez);
}
/// Scaling of both axes
/// @deprecated Use scaleXYZ
void scale(double scalex, double scaley, double scalez) {
scaleXYZ(scalex, scaley, scalez);
}
//@}
/// @name Integer axis accessor equivalents
//@{
/// Get the point value for direction @a i
double val(size_t i) const {
switch (i) {
case 1: return x();
case 2: return y();
case 3: return z();
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set the point value for direction @a i
void setVal(size_t i, double val) {
switch (i) {
case 1: setX(val); break;
case 2: setY(val); break;
case 3: setZ(val); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
+
+ /// Get error map for direction @a i
+ const std::map< std::string, std::pair<double,double>> & errMap() const {
+ return _ez;
+ }
/// Get error values for direction @a i
const std::pair<double,double>& errs(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrs();
case 2: return yErrs();
case 3: return zErrs(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Get negative error value for direction @a i
double errMinus(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrMinus();
case 2: return yErrMinus();
case 3: return zErrMinus(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Get positive error value for direction @a i
double errPlus(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrPlus();
case 2: return yErrPlus();
case 3: return zErrPlus(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Get average error value for direction @a i
double errAvg(size_t i, std::string source="") const {
switch (i) {
case 1: return xErrAvg();
case 2: return yErrAvg();
case 3: return zErrAvg(source);
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set negative error for direction @a i
void setErrMinus(size_t i, double eminus, std::string source="") {
switch (i) {
case 1: setXErrMinus(eminus); break;
case 2: setYErrMinus(eminus); break;
case 3: setZErrMinus(eminus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set positive error for direction @a i
void setErrPlus(size_t i, double eplus, std::string source="") {
switch (i) {
case 1: setXErrPlus(eplus); break;
case 2: setYErrPlus(eplus); break;
case 3: setZErrPlus(eplus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set symmetric error for direction @a i
void setErr(size_t i, double e, std::string source="") {
switch (i) {
case 1: setXErrs(e); break;
case 2: setYErrs(e); break;
case 3: setZErrs(e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set asymmetric error for direction @a i
void setErrs(size_t i, double eminus, double eplus, std::string source="") {
switch (i) {
case 1: setXErrs(eminus, eplus); break;
case 2: setYErrs(eminus, eplus); break;
case 3: setZErrs(eminus, eplus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set asymmetric error for direction @a i
void setErrs(size_t i, std::pair<double,double>& e, std::string source="") {
switch (i) {
case 1: setXErrs(e); break;
case 2: setYErrs(e); break;
case 3: setZErrs(e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set value and symmetric error for direction @a i
void set(size_t i, double val, double e, std::string source="") {
switch (i) {
case 1: setX(val, e); break;
case 2: setY(val, e); break;
case 3: setZ(val, e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set value and asymmetric error for direction @a i
void set(size_t i, double val, double eminus, double eplus, std::string source="") {
switch (i) {
case 1: setX(val, eminus, eplus); break;
case 2: setY(val, eminus, eplus); break;
case 3: setZ(val, eminus, eplus, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
/// Set value and asymmetric error for direction @a i
void set(size_t i, double val, std::pair<double,double>& e, std::string source="") {
switch (i) {
case 1: setX(val, e); break;
case 2: setY(val, e); break;
case 3: setZ(val, e, source); break;
default: throw RangeError("Invalid axis int, must be in range 1..dim");
}
}
//@}
protected:
/// @name Value and error variables
//@{
double _x;
double _y;
double _z;
std::pair<double,double> _ex;
std::pair<double,double> _ey;
+ // a map of the errors for each source. Nominal stored under ""
+ // to ensure backward compatibility
std::map< std::string, std::pair<double,double> >_ez;
//@}
};
/// @name Comparison operators
//@{
/// Equality operator
inline bool operator==(const Point3D& a, const YODA::Point3D& b) {
const bool same_val = fuzzyEquals(a.x(), b.x()) && fuzzyEquals(a.y(), b.y());
const bool same_eminus = fuzzyEquals(a.xErrMinus(), b.xErrMinus()) &&
fuzzyEquals(a.yErrMinus(), b.yErrMinus());
const bool same_eplus = fuzzyEquals(a.xErrPlus(), b.xErrPlus()) &&
fuzzyEquals(a.yErrPlus(), b.yErrPlus());
return same_val && same_eminus && same_eplus;
}
/// Inequality operator
inline bool operator != (const Point3D& a, const YODA::Point3D& b) {
return !(a == b);
}
/// Less-than operator used to sort bins by x-first ordering
inline bool operator < (const Point3D& a, const YODA::Point3D& b) {
if (! fuzzyEquals(a.x(), b.x())) {
return a.x() < b.x();
}
if (!fuzzyEquals(a.y(), b.y())) {
return a.y() < b.y();
}
if (! fuzzyEquals(a.xErrMinus(), b.xErrMinus())) {
return a.xErrMinus() < b.xErrMinus();
}
if (!fuzzyEquals(a.yErrMinus(), b.yErrMinus())) {
return a.yErrMinus() < b.yErrMinus();
}
if (! fuzzyEquals(a.xErrPlus(), b.xErrPlus())) {
return a.xErrPlus() < b.xErrPlus();
}
if (!fuzzyEquals(a.yErrPlus(), b.yErrPlus())) {
return a.yErrPlus() < b.yErrPlus();
}
return false;
}
/// Less-than-or-equals operator
inline bool operator <= (const Point3D& a, const YODA::Point3D& b) {
if (a == b) return true;
return a < b;
}
/// Greater-than operator
inline bool operator > (const Point3D& a, const YODA::Point3D& b) {
return !(a <= b);
}
/// Greater-than-or-equals operator
inline bool operator >= (const Point3D& a, const YODA::Point3D& b) {
return !(a < b);
}
//@}
}
#endif
diff --git a/include/YODA/Scatter1D.h b/include/YODA/Scatter1D.h
--- a/include/YODA/Scatter1D.h
+++ b/include/YODA/Scatter1D.h
@@ -1,354 +1,334 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#ifndef YODA_SCATTER1D_H
#define YODA_SCATTER1D_H
#include "YODA/AnalysisObject.h"
#include "YODA/Point1D.h"
#include "YODA/Utils/sortedvector.h"
#include <utility>
#include <memory>
#include "yaml-cpp/yaml.h"
#ifdef YAML_NAMESPACE
#define YAML YAML_NAMESPACE
#endif
namespace YODA {
// Forward declarations
class Counter;
/// A very generic data type which is just a collection of 1D data points with errors
class Scatter1D : public AnalysisObject {
public:
/// Type of the native Point1D collection
typedef Point1D Point;
typedef Utils::sortedvector<Point1D> Points;
typedef std::shared_ptr<Scatter1D> Ptr;
/// @name Constructors
//@{
/// Empty constructor
Scatter1D(const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter1D", path, title)
- {
- updateVariations(_points);
- }
+ { }
/// Constructor from a set of points
Scatter1D(const Points& points,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter1D", path, title),
_points(points)
- {
- updateVariations(_points);
- }
+ { }
/// Constructor from a vector of x values with no errors
Scatter1D(const std::vector<double>& x,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter1D", path, title)
{
for (size_t i = 0; i < x.size(); ++i) addPoint(x[i]);
- updateVariations(_points);
}
/// Constructor from vectors of x values with symmetric errors
Scatter1D(const std::vector<double>& x, const std::vector<double>& ex,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter1D", path, title)
{
if (x.size() != ex.size()) throw UserError("x and ex vectors must have same length");
for (size_t i = 0; i < x.size(); ++i) addPoint(x[i], ex[i]);
- updateVariations(_points);
}
/// Constructor from x values with asymmetric errors
Scatter1D(const std::vector<double>& x, const std::vector<std::pair<double,double> >& ex,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter1D", path, title)
{
if (x.size() != ex.size()) throw UserError("x and ex vectors must have same length");
for (size_t i = 0; i < x.size(); ++i) addPoint(Point1D(x[i], ex[i]));
- updateVariations(_points);
}
/// Constructor from values with completely explicit asymmetric errors
Scatter1D(const std::vector<double>& x,
const std::vector<double>& exminus,
const std::vector<double>& explus,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter1D", path, title)
{
if (x.size() != exminus.size()) throw UserError("x and ex vectors must have same length");
if (exminus.size() != explus.size()) throw UserError("ex plus and minus vectors must have same length");
for (size_t i = 0; i < x.size(); ++i) addPoint(Point1D(x[i], exminus[i], explus[i]));
- updateVariations(_points);
}
/// Copy constructor with optional new path
/// @todo Also allow title setting from the constructor?
Scatter1D(const Scatter1D& s1, const std::string& path="")
: AnalysisObject("Scatter1D", (path.size() == 0) ? s1.path() : path, s1, s1.title()),
_points(s1._points)
{
for ( auto &ann : annotations()){
setAnnotation(ann, annotation(ann));
}
}
/// Assignment operator
Scatter1D& operator = (const Scatter1D& s1) {
AnalysisObject::operator = (s1); //< AO treatment of paths etc.
_points = s1._points;
return *this;
}
/// Make a copy on the stack
Scatter1D clone() const {
return Scatter1D(*this);
}
/// Make a copy on the heap, via 'new'
Scatter1D* newclone() const {
return new Scatter1D(*this);
}
//@}
/// Dimension of this data object
size_t dim() const { return 1; }
/// @name Modifiers
//@{
/// Clear all points
void reset() {
_points.clear();
}
/// Scaling of x axis
void scaleX(double scalex) {
for (Point1D& p : _points) p.scaleX(scalex);
}
//@}
///////////////////////////////////////////////////
/// Get the list of variations stored in the points
- const std::vector<std::string> variations() const;
+ const std::vector<std::string> variations() const ;
/// @name Point accessors
//@{
/// Number of points in the scatter
size_t numPoints() const {
return _points.size();
}
/// Get the collection of points (non-const)
Points& points() {
return _points;
}
/// Get the collection of points (const)
const Points& points() const {
return _points;
}
/// Get a reference to the point with index @a index (non-const)
Point1D& point(size_t index) {
if (index >= numPoints()) throw RangeError("There is no point with this index");
return _points.at(index);
}
/// Get a reference to the point with index @a index (const)
const Point1D& point(size_t index) const {
if (index >= numPoints()) throw RangeError("There is no point with this index");
return _points.at(index);
}
//@}
/// @name Point inserters
//@{
/// Insert a new point
void addPoint(const Point1D& pt) {
_points.insert(pt);
- updateVariations(_points);
}
/// Insert a new point, defined as the x value and no errors
void addPoint(double x) {
_points.insert(Point1D(x));
- updateVariations(_points);
}
/// Insert a new point, defined as the x value and symmetric errors
void addPoint(double x, double ex) {
_points.insert(Point1D(x, ex));
- updateVariations(_points);
}
/// Insert a new point, defined as the x value and an asymmetric error pair
void addPoint(double x, const std::pair<double,double>& ex) {
_points.insert(Point1D(x, ex));
- updateVariations(_points);
}
/// Insert a new point, defined as the x value and explicit asymmetric errors
void addPoint(double x, double exminus, double explus) {
_points.insert(Point1D(x, exminus, explus));
- updateVariations(_points);
}
/// Insert a collection of new points
void addPoints(const Points& pts) {
for (const Point1D& pt : pts) addPoint(pt);
}
//@}
/// @name Combining sets of scatter points
//@{
/// @todo Better name? Make this the add operation?
void combineWith(const Scatter1D& other) {
addPoints(other.points());
- updateVariations(_points);
}
/// @todo Better name? Make this the add operation?
/// @todo Convert/extend to accept a Range or generic
void combineWith(const std::vector<Scatter1D>& others) {
for (const Scatter1D& s : others) combineWith(s);
}
//@}
/// Equality operator
bool operator == (const Scatter1D& other) {
return _points == other._points;
}
/// Non-equality operator
bool operator != (const Scatter1D& other) {
return ! operator == (other);
}
//////////////////////////////////
-
- /// @name Update the annotation which holds the names of the variations (the OR of the variations of all points)
- //@{
-
- void updateVariations( Points& points);
- //@}
private:
Points _points;
};
/// Convenience typedef
typedef Scatter1D S1D;
/// @name Combining scatters by merging sets of points
//@{
inline Scatter1D combine(const Scatter1D& a, const Scatter1D& b) {
Scatter1D rtn = a;
rtn.combineWith(b);
return rtn;
}
inline Scatter1D combine(const std::vector<Scatter1D>& scatters) {
Scatter1D rtn;
rtn.combineWith(scatters);
return rtn;
}
//@}
//////////////////////////////////
/// @name Conversion functions from other data types
//@{
/// Make a Scatter1D representation of a Histo1D
Scatter1D mkScatter(const Counter& c);
/// Make a Scatter1D representation of... erm, a Scatter1D!
/// @note Mainly exists to allow mkScatter to be called on any AnalysisObject type
inline Scatter1D mkScatter(const Scatter1D& s) {
return Scatter1D(s);
}
//@}
/////////////////////////////////
/// @name Transforming operations on Scatter1D
//@{
/// @brief Apply transformation fx(x) to all values and error positions (operates in-place on @a s)
///
/// fx should be a function which takes double x -> double newx
template<typename FNX>
inline void transformX(Scatter1D& s, FNX fx) {
for (size_t i = 0; i < s.numPoints(); ++i) {
Point1D& p = s.point(i);
const double newx = fx(p.x());
const double fx_xmin = fx(p.xMin());
const double fx_xmax = fx(p.xMax());
// Deal with possible inversions of min/max ordering under the transformation
const double newxmin = std::min(fx_xmin, fx_xmax);
const double newxmax = std::max(fx_xmin, fx_xmax);
// Set new point x values
p.setX(newx);
/// @todo Be careful about transforms which could switch around min and max errors, or send both in the same direction!
p.setXErrMinus(newx - newxmin);
p.setXErrPlus(newxmax - newx);
}
}
//@}
}
#endif
diff --git a/include/YODA/Scatter2D.h b/include/YODA/Scatter2D.h
--- a/include/YODA/Scatter2D.h
+++ b/include/YODA/Scatter2D.h
@@ -1,412 +1,425 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#ifndef YODA_SCATTER2D_H
#define YODA_SCATTER2D_H
#include "YODA/AnalysisObject.h"
#include "YODA/Point2D.h"
#include "YODA/Utils/sortedvector.h"
#include <utility>
#include <memory>
+#include "yaml-cpp/yaml.h"
+#ifdef YAML_NAMESPACE
+#define YAML YAML_NAMESPACE
+#endif
namespace YODA {
// Forward declarations
class Histo1D;
class Profile1D;
/// A very generic data type which is just a collection of 2D data points with errors
class Scatter2D : public AnalysisObject {
public:
/// Type of the native Point2D collection
typedef Point2D Point;
typedef Utils::sortedvector<Point2D> Points;
typedef std::shared_ptr<Scatter2D> Ptr;
/// @name Constructors
//@{
/// Empty constructor
Scatter2D(const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter2D", path, title)
{ }
/// Constructor from a set of points
Scatter2D(const Points& points,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter2D", path, title),
_points(points)
{ }
/// Constructor from a vector of values with no errors
Scatter2D(const std::vector<double>& x, const std::vector<double>& y,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter2D", path, title)
{
if (x.size() != y.size()) throw UserError("x and y vectors must have same length");
for (size_t i = 0; i < x.size(); ++i) addPoint(x[i], y[i]);
}
/// Constructor from vectors of values with symmetric errors on x and y
Scatter2D(const std::vector<double>& x, const std::vector<double>& y,
const std::vector<double>& ex, const std::vector<double>& ey,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter2D", path, title)
{
if (x.size() != y.size()) throw UserError("x and y vectors must have same length");
if (x.size() != ex.size()) throw UserError("x and ex vectors must have same length");
if (y.size() != ey.size()) throw UserError("y and ey vectors must have same length");
for (size_t i = 0; i < x.size(); ++i) addPoint(x[i], y[i], ex[i], ey[i]);
}
/// Constructor from values with asymmetric errors on both x and y
Scatter2D(const std::vector<double>& x, const std::vector<double>& y,
const std::vector<std::pair<double,double> >& ex, const std::vector<std::pair<double,double> >& ey,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter2D", path, title)
{
if (x.size() != y.size()) throw UserError("x and y vectors must have same length");
if (x.size() != ex.size()) throw UserError("x and ex vectors must have same length");
if (y.size() != ey.size()) throw UserError("y and ey vectors must have same length");
for (size_t i = 0; i < x.size(); ++i) addPoint(Point2D(x[i], y[i], ex[i], ey[i]));
}
/// Constructor from values with completely explicit asymmetric errors
Scatter2D(const std::vector<double>& x, const std::vector<double>& y,
const std::vector<double>& exminus, const std::vector<double>& explus,
const std::vector<double>& eyminus, const std::vector<double>& eyplus,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter2D", path, title)
{
if (x.size() != y.size()) throw UserError("x and y vectors must have same length");
if (x.size() != exminus.size()) throw UserError("x and ex vectors must have same length");
if (y.size() != eyminus.size()) throw UserError("y and ey vectors must have same length");
if (exminus.size() != explus.size()) throw UserError("ex plus and minus vectors must have same length");
if (eyminus.size() != eyplus.size()) throw UserError("ey plus and minus vectors must have same length");
for (size_t i = 0; i < x.size(); ++i) addPoint(Point2D(x[i], y[i], exminus[i], explus[i], eyminus[i], eyplus[i]));
}
/// Copy constructor with optional new path
/// @todo Also allow title setting from the constructor?
Scatter2D(const Scatter2D& s2, const std::string& path="")
: AnalysisObject("Scatter2D", (path.size() == 0) ? s2.path() : path, s2, s2.title()),
_points(s2._points)
- { }
+ {
+ for ( auto &ann : annotations()){
+ setAnnotation(ann, annotation(ann));
+ }
+ }
/// Assignment operator
Scatter2D& operator = (const Scatter2D& s2) {
AnalysisObject::operator = (s2); //< AO treatment of paths etc.
_points = s2._points;
return *this;
}
/// Make a copy on the stack
Scatter2D clone() const {
return Scatter2D(*this);
}
/// Make a copy on the heap, via 'new'
Scatter2D* newclone() const {
return new Scatter2D(*this);
}
//@}
/// Dimension of this data object
size_t dim() const { return 2; }
/// @name Modifiers
//@{
/// Clear all points
void reset() {
_points.clear();
}
/// Scaling of x axis
void scaleX(double scalex) {
for (Point2D& p : _points) p.scaleX(scalex);
}
/// Scaling of y axis
void scaleY(double scaley) {
for (Point2D& p : _points) p.scaleY(scaley);
}
/// Scaling of both axes
void scaleXY(double scalex, double scaley) {
for (Point2D& p : _points) p.scaleXY(scalex, scaley);
}
/// Scaling of both axes
/// @deprecated Use scaleXY
void scale(double scalex, double scaley) {
scaleXY(scalex, scaley);
}
//@}
///////////////////////////////////////////////////
+ /// Get the list of variations stored in the points
+ const std::vector<std::string> variations() const;
/// @name Point accessors
//@{
/// Number of points in the scatter
size_t numPoints() const {
return _points.size();
}
/// Get the collection of points (non-const)
Points& points() {
return _points;
}
/// Get the collection of points (const)
const Points& points() const {
return _points;
}
/// Get a reference to the point with index @a index (non-const)
Point2D& point(size_t index) {
if (index >= numPoints()) throw RangeError("There is no point with this index");
return _points.at(index);
}
/// Get a reference to the point with index @a index (const)
const Point2D& point(size_t index) const {
if (index >= numPoints()) throw RangeError("There is no point with this index");
return _points.at(index);
}
//@}
/// @name Point inserters
//@{
/// Insert a new point
void addPoint(const Point2D& pt) {
_points.insert(pt);
}
/// Insert a new point, defined as the x/y value pair and no errors
void addPoint(double x, double y) {
_points.insert(Point2D(x, y));
}
/// Insert a new point, defined as the x/y value pair and symmetric errors
void addPoint(double x, double y,
double ex, double ey) {
_points.insert(Point2D(x, y, ex, ey));
}
/// Insert a new point, defined as the x/y value pair and asymmetric error pairs
void addPoint(double x, double y,
const std::pair<double,double>& ex, const std::pair<double,double>& ey) {
_points.insert(Point2D(x, y, ex, ey));
}
/// Insert a new point, defined as the x/y value pair and asymmetric errors
void addPoint(double x, double y,
double exminus, double explus,
double eyminus, double eyplus) {
_points.insert(Point2D(x, y, exminus, explus, eyminus, eyplus));
}
/// Insert a collection of new points
void addPoints(const Points& pts) {
for (const Point2D& pt : pts) addPoint(pt);
}
//@}
/// @name Combining sets of scatter points
//@{
/// @todo Better name? Make this the add operation?
void combineWith(const Scatter2D& other) {
addPoints(other.points());
//return *this;
}
/// @todo Better name? Make this the add operation?
/// @todo Convert/extend to accept a Range or generic
void combineWith(const std::vector<Scatter2D>& others) {
for (const Scatter2D& s : others) combineWith(s);
//return *this;
}
//@}
/// Equality operator
bool operator == (const Scatter2D& other) {
return _points == other._points;
}
/// Non-equality operator
bool operator != (const Scatter2D& other) {
return ! operator == (other);
}
+
+ //////////////////////////////////
+
private:
Points _points;
};
/// Convenience typedef
typedef Scatter2D S2D;
/// @name Combining scatters by merging sets of points
//@{
inline Scatter2D combine(const Scatter2D& a, const Scatter2D& b) {
Scatter2D rtn = a;
rtn.combineWith(b);
return rtn;
}
inline Scatter2D combine(const std::vector<Scatter2D>& scatters) {
Scatter2D rtn;
rtn.combineWith(scatters);
return rtn;
}
//@}
//////////////////////////////////
/// @name Conversion functions from other data types
//@{
/// Make a Scatter2D representation of a Histo1D
///
/// Optional @c usefocus argument can be used to position the point at the bin
/// focus rather than geometric midpoint.
Scatter2D mkScatter(const Histo1D& h, bool usefocus=false);
/// Make a Scatter2D representation of a Profile1D
///
/// Optional @c usefocus argument can be used to position the point at the bin
/// focus rather than geometric midpoint. Optional @c usestddev argument can
/// be used to draw the y-distribution sigma rather than the standard error on
/// the mean as the y-error bar size.
Scatter2D mkScatter(const Profile1D& p, bool usefocus=false, bool usestddev=false);
/// Make a Scatter2D representation of... erm, a Scatter2D!
/// @note Mainly exists to allow mkScatter to be called on any AnalysisObject type
inline Scatter2D mkScatter(const Scatter2D& s) { return Scatter2D(s); }
// /// @note The usefocus arg is just for consistency and has no effect for Scatter -> Scatter
// inline Scatter2D mkScatter(const Scatter2D& s, bool) { return mkScatter(s); }
//@}
//////////////////////////////////
/// @name Transforming operations on Scatter2D
//@{
/// @brief Apply transformation fx(x) to all values and error positions (operates in-place on @a s)
///
/// fx should be a function which takes double x -> double newx
template<typename FNX>
inline void transformX(Scatter2D& s, FNX fx) {
for (size_t i = 0; i < s.numPoints(); ++i) {
Point2D& p = s.point(i);
const double newx = fx(p.x());
const double fx_xmin = fx(p.xMin());
const double fx_xmax = fx(p.xMax());
// Deal with possible inversions of min/max ordering under the transformation
const double newxmin = std::min(fx_xmin, fx_xmax);
const double newxmax = std::max(fx_xmin, fx_xmax);
// Set new point x values
p.setX(newx);
/// @todo Be careful about transforms which could switch around min and max errors, or send both in the same direction!
p.setXErrMinus(newx - newxmin);
p.setXErrPlus(newxmax - newx);
}
}
/// @brief Apply transformation fy(y) to all values and error positions (operates in-place on @a s)
///
/// fy should be a function which takes double y -> double newy
template<typename FNY>
inline void transformY(Scatter2D& s, FNY fy) {
for (size_t i = 0; i < s.numPoints(); ++i) {
Point2D& p = s.point(i);
const double newy = fy(p.y());
const double fy_ymin = fy(p.yMin());
const double fy_ymax = fy(p.yMax());
// Deal with possible inversions of min/max ordering under the transformation
const double newymin = std::min(fy_ymin, fy_ymax);
const double newymax = std::max(fy_ymin, fy_ymax);
// Set new point y values
p.setY(newy);
/// @todo Be careful about transforms which could switch around min and max errors, or send both in the same direction!
p.setYErrMinus(newy - newymin);
p.setYErrPlus(newymax - newy);
}
}
/// @todo Add external scale, scaleX, scaleY functions
/// Exchange the x and y axes (operates in-place on @a s)
inline void flip(Scatter2D& s) {
for (size_t i = 0; i < s.numPoints(); ++i) {
Point2D& p = s.point(i);
const double newx = p.y();
const double newy = p.x();
const double newxmin = p.yMin();
const double newxmax = p.yMax();
const double newymin = p.xMin();
const double newymax = p.xMax();
p.setX(newx);
p.setY(newy);
/// @todo Be careful about transforms which could switch around min and max errors, or send both in the same direction!
p.setXErrMinus(newx - newxmin);
p.setXErrPlus(newxmax - newx);
p.setYErrMinus(newy - newymin);
p.setYErrPlus(newymax - newy);
}
}
//@}
}
#endif
diff --git a/include/YODA/Scatter3D.h b/include/YODA/Scatter3D.h
--- a/include/YODA/Scatter3D.h
+++ b/include/YODA/Scatter3D.h
@@ -1,423 +1,440 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#ifndef YODA_SCATTER3D_H
#define YODA_SCATTER3D_H
#include "YODA/AnalysisObject.h"
#include "YODA/Point3D.h"
#include "YODA/Utils/sortedvector.h"
#include <utility>
#include <memory>
+#include "yaml-cpp/yaml.h"
+#ifdef YAML_NAMESPACE
+#define YAML YAML_NAMESPACE
+#endif
namespace YODA {
// Forward declarations
class Histo2D;
class Profile2D;
/// A very generic data type which is just a collection of 3D data points with errors
class Scatter3D : public AnalysisObject {
public:
/// Types of the native Point3D collection
typedef Point3D Point;
typedef Utils::sortedvector<Point3D> Points;
typedef std::shared_ptr<Scatter3D> Ptr;
/// @name Constructors
//@{
/// Empty constructor
Scatter3D(const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter3D", path, title)
- { }
+ { }
/// Constructor from a set of points
Scatter3D(const Points& points,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter3D", path, title),
_points(points)
{
std::sort(_points.begin(), _points.end());
}
/// Constructor from vectors of values with no errors
Scatter3D(const std::vector<double>& x,
- const std::vector<double>& y,
- const std::vector<double>& z,
+ const std::vector<double>& y,
+ const std::vector<double>& z,
const std::string& path="",
- const std::string& title="")
+ const std::string& title="")
: AnalysisObject("Scatter3D", path, title)
{
if (x.size() != y.size() || y.size() != z.size()) {
throw RangeError("There are different numbers of x, y, and z values in the provided vectors.");
}
const std::pair<double,double> nullerr = std::make_pair(0.0, 0.0);
for (size_t i = 0; i < x.size(); ++i) {
addPoint(Point3D(x[i], y[i], z[i], nullerr, nullerr, nullerr));
}
std::sort(_points.begin(), _points.end());
}
/// Constructor from vectors of values with asymmetric errors on both x and y
Scatter3D(const std::vector<double>& x, const std::vector<double>& y, const std::vector<double>& z,
const std::vector<std::pair<double,double> >& ex, const std::vector<std::pair<double,double> >& ey, const std::vector<std::pair<double,double> >& ez,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter3D", path, title)
{
if (x.size() != y.size() || y.size() != z.size()) {
throw RangeError("There are different numbers of x, y, and z values in the provided vectors.");
}
if (x.size() != ex.size() || y.size() != ey.size() || z.size() != ez.size()) {
throw RangeError("The sizes of the provided error vectors don't match the corresponding x, y, or z value vectors.");
}
for (size_t i = 0; i < x.size(); ++i) {
addPoint(Point3D(x[i], y[i], z[i], ex[i], ey[i], ez[i]));
}
std::sort(_points.begin(), _points.end());
}
/// Constructor from vectors of values with completely explicit asymmetric errors
Scatter3D(const std::vector<double>& x, const std::vector<double>& y, const std::vector<double> z,
const std::vector<double>& exminus,
const std::vector<double>& explus,
const std::vector<double>& eyminus,
const std::vector<double>& eyplus,
const std::vector<double>& ezminus,
const std::vector<double>& ezplus,
const std::string& path="", const std::string& title="")
: AnalysisObject("Scatter3D", path, title)
{
if(x.size() != y.size() || y.size() != z.size() ||
x.size() != exminus.size() || x.size() != explus.size() ||
y.size() != eyminus.size() || y.size() != eyplus.size() ||
z.size() != ezminus.size() || z.size() != ezplus.size())
throw RangeError("There are either different amounts of points on x/y/z vectors or not every of these vectors has properly defined error vectors!");
for (size_t i = 0; i < x.size(); ++i) {
addPoint(Point3D(x[i], y[i], z[i], exminus[i], explus[i], eyminus[i], eyplus[i], ezminus[i], ezplus[i]));
}
std::sort(_points.begin(), _points.end());
}
/// Copy constructor with optional new path
/// @todo Also allow title setting from the constructor?
Scatter3D(const Scatter3D& s3, const std::string& path="")
: AnalysisObject("Scatter3D", (path.size() == 0) ? s3.path() : path, s3, s3.title()),
_points(s3._points)
- { }
+ {
+ for ( auto &ann : annotations()){
+ setAnnotation(ann, annotation(ann));
+ }
+ }
/// Assignment operator
Scatter3D& operator = (const Scatter3D& s3) {
AnalysisObject::operator = (s3); //< AO treatment of paths etc.
_points = s3._points;
return *this;
}
/// Make a copy on the stack
Scatter3D clone() const {
return Scatter3D(*this);
}
/// Make a copy on the heap, via 'new'
Scatter3D* newclone() const {
return new Scatter3D(*this);
}
//@}
/// Dimension of this data object
size_t dim() const { return 3; }
/// @name Modifiers
//@{
/// Clear all points
void reset() {
_points.clear();
}
/// Scaling of x axis
void scaleX(double scalex) {
for (Point3D& p : _points) p.scaleX(scalex);
}
/// Scaling of y axis
void scaleY(double scaley) {
for (Point3D& p : _points) p.scaleY(scaley);
}
/// Scaling of z axis
void scaleZ(double scalez) {
for (Point3D& p : _points) p.scaleZ(scalez);
}
/// Scaling of all three axes
void scaleXYZ(double scalex, double scaley, double scalez) {
for (Point3D& p : _points) p.scaleXYZ(scalex, scaley, scalez);
}
/// Scaling of all three axes
/// @deprecated Use scaleXYZ
void scale(double scalex, double scaley, double scalez) {
scaleXYZ(scalex, scaley, scalez);
}
//@}
+ ///////////////////////////////////////////////////
+
+ /// Get the list of variations stored in the points
+ const std::vector<std::string> variations() const;
+
/// @name Point accessors
//@{
/// Number of points in the scatter
size_t numPoints() const {
return _points.size();
}
/// Get the collection of points (non-const)
Points& points() {
return _points;
}
/// Get the collection of points (const)
const Points& points() const {
return _points;
}
/// Get a reference to the point with index @a index
Point3D& point(size_t index) {
if (index >= numPoints()) throw RangeError("There is no point with this index");
return _points.at(index);
}
/// Get the point with index @a index (const version)
const Point3D& point(size_t index) const {
if (index >= numPoints()) throw RangeError("There is no point with such index!");
return _points.at(index);
}
//@}
/// @name Point inserters
//@{
/// Insert a new point
void addPoint(const Point3D& pt) {
_points.insert(pt);
}
/// Insert a new point, defined as the x/y/z value triplet and no errors
void addPoint(double x, double y, double z) {
_points.insert(Point3D(x, y, z));
}
/// Insert a new point, defined as the x/y/z value triplet and symmetric errors
void addPoint(double x, double y, double z,
double ex, double ey, double ez) {
_points.insert(Point3D(x, y, z, ex, ey, ez));
}
/// Insert a new point, defined as the x/y/z value triplet and asymmetric error pairs
void addPoint(double x, double y, double z,
const std::pair<double,double>& ex, const std::pair<double,double>& ey, const std::pair<double,double>& ez) {
_points.insert(Point3D(x, y, z, ex, ey, ez));
}
/// Insert a new point, defined as the x/y/z value triplet and asymmetric errors
void addPoint(double x, double y, double z,
double exminus, double explus,
double eyminus, double eyplus,
double ezminus, double ezplus) {
_points.insert(Point3D(x, y, z, exminus, explus, eyminus, eyplus, ezminus, ezplus));
}
/// Insert a collection of new points
void addPoints(const Points& pts) {
for (const Point3D& pt : pts) addPoint(pt);
}
//@}
/// @todo Better name?
void combineWith(const Scatter3D& other) {
addPoints(other.points());
//return *this;
}
/// @todo Better name?
/// @todo Convert to accept a Range or generic
void combineWith(const std::vector<Scatter3D>& others) {
for (const Scatter3D& s : others) combineWith(s);
}
/// Equality operator
bool operator == (const Scatter3D& other) {
return _points == other._points;
}
/// Non-equality operator
bool operator != (const Scatter3D& other) {
return ! operator == (other);
}
+
+ //////////////////////////////////
+
+
private:
Points _points;
};
/// Convenience typedef
typedef Scatter3D S3D;
/// @name Combining scatters by merging sets of points
//@{
inline Scatter3D combine(const Scatter3D& a, const Scatter3D& b) {
Scatter3D rtn = a;
rtn.combineWith(b);
return rtn;
}
inline Scatter3D combine(const std::vector<Scatter3D>& scatters) {
Scatter3D rtn;
rtn.combineWith(scatters);
return rtn;
}
//@}
//////////////////////////////////
/// @name Conversion functions from other data types
//@{
/// Make a Scatter3D representation of a Histo2D
///
/// Optional @c usefocus argument can be used to position the point at the bin
/// focus rather than geometric midpoint.
Scatter3D mkScatter(const Histo2D& h, bool usefocus=false);
/// Make a Scatter3D representation of a Profile2D
///
/// Optional @c usefocus argument can be used to position the point at the bin
/// focus rather than geometric midpoint. Optional @c usestddev argument can
/// be used to draw the distribution sigma rather than the standard error on
/// the mean as the z-error bar size.
Scatter3D mkScatter(const Profile2D& p, bool usefocus=false, bool usestddev=false);
/// Make a Scatter3D representation of... erm, a Scatter3D!
/// @note Mainly exists to allow mkScatter to be called on any AnalysisObject type
inline Scatter3D mkScatter(const Scatter3D& s) { return Scatter3D(s); }
// /// @note The usefocus arg is just for consistency and has no effect for Scatter -> Scatter
//inline Scatter3D mkScatter(const Scatter3D& s, bool) { return mkScatter(s); }
//@}
/////////////////////////////////
/// @name Transforming operations on Scatter3D
//@{
/// @brief Apply transformation fx(x) to all values and error positions (operates in-place on @a s)
///
/// fx should be a function which takes double x -> double newx
template<typename FNX>
inline void transformX(Scatter3D& s, FNX fx) {
for (size_t i = 0; i < s.numPoints(); ++i) {
Point3D& p = s.point(i);
const double newx = fx(p.x());
const double fx_xmin = fx(p.xMin());
const double fx_xmax = fx(p.xMax());
// Deal with possible inversions of min/max ordering under the transformation
const double newxmin = std::min(fx_xmin, fx_xmax);
const double newxmax = std::max(fx_xmin, fx_xmax);
// Set new point x values
p.setX(newx);
/// @todo Be careful about transforms which could switch around min and max errors, or send both in the same direction!
p.setXErrMinus(newx - newxmin);
p.setXErrPlus(newxmax - newx);
}
}
/// @brief Apply transformation fy(y) to all values and error positions (operates in-place on @a s)
///
/// fy should be a function which takes double y -> double newy
template<typename FNY>
inline void transformY(Scatter3D& s, FNY fy) {
for (size_t i = 0; i < s.numPoints(); ++i) {
Point3D& p = s.point(i);
const double newy = fy(p.y());
const double fy_ymin = fy(p.yMin());
const double fy_ymax = fy(p.yMax());
// Deal with possible inversions of min/max ordering under the transformation
const double newymin = std::min(fy_ymin, fy_ymax);
const double newymax = std::max(fy_ymin, fy_ymax);
// Set new point y values
p.setY(newy);
/// @todo Be careful about transforms which could switch around min and max errors, or send both in the same direction!
p.setYErrMinus(newy - newymin);
p.setYErrPlus(newymax - newy);
}
}
/// @brief Apply transformation fz(z) to all values and error positions (operates in-place on @a s)
///
/// fz should be a function which takes double z -> double newz
template<typename FNZ>
inline void transformZ(Scatter3D& s, FNZ fz) {
for (size_t i = 0; i < s.numPoints(); ++i) {
Point3D& p = s.point(i);
const double newz = fz(p.z());
const double fz_zmin = fz(p.zMin());
const double fz_zmax = fz(p.zMax());
// Deal with possible inversions of min/max ordering under the transformation
const double newzmin = std::min(fz_zmin, fz_zmax);
const double newzmax = std::max(fz_zmin, fz_zmax);
// Set new point z values
p.setZ(newz);
/// @todo Be careful about transforms which could switch around min and max errors, or send both in the same direction!
p.setZErrMinus(newz - newzmin);
p.setZErrPlus(newzmax - newz);
}
}
/// @todo Add external scale, scaleX, scaleY, scaleZ functions
//@}
}
#endif
diff --git a/pyext/yoda/declarations.pxd b/pyext/yoda/declarations.pxd
--- a/pyext/yoda/declarations.pxd
+++ b/pyext/yoda/declarations.pxd
@@ -1,1399 +1,1419 @@
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
# 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
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
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
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
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 "<sstream>" 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/Point.pyx b/pyext/yoda/include/Point.pyx
--- a/pyext/yoda/include/Point.pyx
+++ b/pyext/yoda/include/Point.pyx
@@ -1,124 +1,133 @@
cimport util
cdef class Point(util.Base):
"""
A generic point with errors, used by the Scatter classes.
"""
cdef c.Point* pptr(self) except NULL:
return <c.Point*> self.ptr()
def __dealloc__(self):
cdef c.Point *p = self.pptr()
if self._deallocate:
del p
# def __init__(self):
# cutil.set_owned_ptr(self, new c.Point())
# def copy(self):
# return cutil.new_owned_cls(Point, new c.Point(deref(self.pptr())))
# TODO: add clone() as mapping to (not yet existing) C++ newclone()?
@property
def dim(self):
"""None -> int
Space dimension of the point (should match containing Scatter)"""
return self.pptr().dim()
def val(self, i):
"""int -> float
Value on axis i"""
return self.pptr().val(i)
def setVal(self, i, val):
"""(int, float) -> None
Value on axis i"""
self.pptr().setVal(i, val)
def errs(self, i, source=""):
"""int -> float
Errors on axis i"""
if source==None: source=""
return util.read_error_pair(self.pptr().errs(i,source))
def setErr(self, i, e, source=""):
"""(int, float) -> None
Set symmetric errors on axis i"""
if source==None: source=""
+ print "LC DEBUG setErr ", e, source
self.pptr().setErr(i, e, source)
- def setErrs(self, i, *es, source=""):
+ def setErrs(self, i, *es):
"""(int, float) -> None
(int, [float, float]) -> None
(int, float, float) -> None
Set asymmetric errors on axis i"""
+ source=None
+ es=list(es)
+ if type(es[-1]) is str:
+ source=es[-1]
+ es=es[:-1]
+ else:
+ pass
+ errs = es
if source==None: source=""
- errs = es
- if len(es) == 1:
- if not hasattr(es[0], "__iter__"):
- self.setErr(es[0], source)
- errs = es[0]
+ if len(errs) == 1:
+ if not hasattr(errs[0], "__iter__"):
+ self.setErr(i,errs[0], source)
+ return
+ errs=errs[0]
# assert len(errs) == 2:
- self.pptr().setErrs(i, errs, source)
+ self.pptr().setErrs(i, tuple(errs), source)
def errMinus(self, i, source=""):
"""int -> float
Minus error on axis i"""
if source==None: source=""
return self.pptr().errMinus(i ,source)
def setErrMinus(self, i, e, source=""):
"""(int, float) -> None
Set minus error on axis i"""
if source==None: source=""
self.pptr().setErrMinus(i, e, source)
def errPlus(self, i, source=""):
"""int -> float
Plus error on axis i"""
if source==None: source=""
return self.pptr().errPlus(i, source)
def setErrPlus(self, i, e, source=""):
"""(int, float) -> None
Set plus error on axis i"""
if source==None: source=""
self.pptr().setErrPlus(i, e, source)
def errAvg(self, i, source=""):
"""int -> float
Average error on axis i"""
if source==None: source=""
return self.pptr().errAvg(i, source)
def set(self, i, val, *es, source=""):
"""(int, float, float) -> None
(int, float, [float, float]) -> None
(int, float, float, float) -> None
Set value and errors on axis i"""
errs = es
if source==None: source=""
if len(es) == 1:
if hasattr(es[0], "__iter__"):
errs = [es[0], es[0]]
else:
errs = es[0]
# assert len(errs) == 2:
self.pptr().set(i, val, errs, source)
def errMap(self):
"""None -> {string: [float,float]}
error map of this point"""
return self.pptr().errMap()
# def __repr__(self):
# return '<Point(x=%g)>' % self.x
diff --git a/pyext/yoda/include/Point2D.pyx b/pyext/yoda/include/Point2D.pyx
--- a/pyext/yoda/include/Point2D.pyx
+++ b/pyext/yoda/include/Point2D.pyx
@@ -1,134 +1,141 @@
cimport util
cdef class Point2D(Point):
"""
A 2D point with errors, used by the Scatter2D class.
"""
cdef c.Point2D* p2ptr(self) except NULL:
return <c.Point2D*> self.ptr()
- def __init__(self, x=0, y=0, xerrs=0, yerrs=0):
+ def __init__(self, x=0, y=0, xerrs=0, yerrs=0, source=""):
+ if source==None: source=""
cutil.set_owned_ptr(self, new c.Point2D())
self.x = x
self.y = y
self.xErrs = xerrs
- self.yErrs = yerrs
+ self.setYErrs(yerrs,source)
def copy(self):
return cutil.new_owned_cls(Point2D, new c.Point2D(deref(self.p2ptr())))
# TODO: add clone() as mapping to (not yet existing) C++ newclone()?
+ def setYErrs(self, val, source):
+ if source==None: source=""
+ self.p2ptr().setYErrs(util.read_symmetric(val))
property x:
"""x coordinate"""
def __get__(self):
return self.p2ptr().x()
def __set__(self, x):
self.p2ptr().setX(x)
property y:
"""y coordinate"""
def __get__(self):
return self.p2ptr().y()
def __set__(self, y):
self.p2ptr().setY(y)
property xy:
"""x and y coordinates as a tuple"""
def __get__(self):
return util.XY(self.x, self.y)
def __set__(self, val):
self.x, self.y = val
# TODO: How does this fit into the multi-error API? Still useful, but just reports first errs... how to get _all_ +- err pairs?
+ # LC: This is fine because preserntly only the highest dimension supports multi-errors
property xErrs:
"""The x errors"""
def __get__(self):
return util.read_error_pair(self.p2ptr().xErrs())
def __set__(self, val):
self.p2ptr().setXErrs(util.read_symmetric(val))
# TODO: How does this fit into the multi-error API? Still useful, but just reports first errs... how to get _all_ +- err pairs?
+ # LC: I think it's Ok to leave this like this, for most users the nominal is what they want anyway,
+ # and for those who want multi-errs, they can set using a method eg setErrs(dim,(ed,eu),source) and access using errs(dim,(ed,eu),source)
property yErrs:
"""The y errors"""
def __get__(self):
return util.read_error_pair(self.p2ptr().yErrs())
def __set__(self, val):
self.p2ptr().setYErrs(util.read_symmetric(val))
@property
def xMin(self):
"""The minimum x position, i.e. lowest error"""
return self.p2ptr().xMin()
@property
def xMax(self):
"""The maximum x position, i.e. highest error"""
return self.p2ptr().xMax()
@property
def yMin(self):
"""The minimum y position, i.e. lowest error"""
return self.p2ptr().yMin()
@property
def yMax(self):
"""The maximum y position, i.e. highest error"""
return self.p2ptr().yMax()
property xErrAvg:
def __get__(self):
return self.p2ptr().xErrAvg()
property yErrAvg:
def __get__(self):
return self.p2ptr().yErrAvg()
def scaleX(self, a):
"""(float) -> None
Scale the x values and errors by factor a."""
self.p2ptr().scaleX(a)
def scaleY(self, a):
"""(float) -> None
Scale the y values and errors by factor a."""
self.p2ptr().scaleY(a)
def scaleXY(self, x=1.0, y=1.0):
"""
(float=1, float=1) -> None
Scale the point coordinates by the given factors.
"""
self.p2ptr().scaleXY(x, y)
# TODO: remove
def scale(self, x=1.0, y=1.0):
"""
(float=1, float=1) -> None
DEPRECATED! Use scaleXY
Scale the point coordinates by the given factors.
"""
self.p2ptr().scaleXY(x, y)
def __repr__(self):
return '<Point2D(x=%g, y=%g)>' % (self.x, self.y)
def __richcmp__(Point2D self, Point2D other, int op):
if op == 0:
return deref(self.p2ptr()) < deref(other.p2ptr())
elif op == 1:
return deref(self.p2ptr()) <= deref(other.p2ptr())
elif op == 2:
return deref(self.p2ptr()) == deref(other.p2ptr())
elif op == 3:
return deref(self.p2ptr()) != deref(other.p2ptr())
elif op == 4:
return deref(self.p2ptr()) > deref(other.p2ptr())
elif op == 5:
return deref(self.p2ptr()) >= deref(other.p2ptr())
diff --git a/pyext/yoda/include/Point3D.pyx b/pyext/yoda/include/Point3D.pyx
--- a/pyext/yoda/include/Point3D.pyx
+++ b/pyext/yoda/include/Point3D.pyx
@@ -1,169 +1,178 @@
cimport util
cdef class Point3D(Point):
"""
A 3D point with errors, used by the Scatter3D class.
"""
cdef c.Point3D* p3ptr(self) except NULL:
return <c.Point3D*> self.ptr()
- def __init__(self, x=0, y=0, z=0, xerrs=0, yerrs=0, zerrs=0):
+ def __init__(self, x=0, y=0, z=0, xerrs=0, yerrs=0, zerrs=0, source=""):
+ if source==None: source=""
cutil.set_owned_ptr(self, new c.Point3D())
self.xyz = x, y, z
self.xErrs = xerrs
self.yErrs = yerrs
- self.zErrs = zerrs
+ self.setZErrs(zerrs,source)
def copy(self):
return cutil.new_owned_cls(Point3D, new c.Point3D(deref(self.p3ptr())))
+
+ def setZErrs(self, val, source):
+ if source==None: source=""
+ self.p3ptr().setZErrs(util.read_symmetric(val))
property x:
"""x coordinate"""
def __get__(self):
return self.p3ptr().x()
def __set__(self, x):
self.p3ptr().setX(x)
property y:
"""y coordinate"""
def __get__(self):
return self.p3ptr().y()
def __set__(self, y):
self.p3ptr().setY(y)
property z:
"""y coordinate"""
def __get__(self):
return self.p3ptr().z()
def __set__(self, z):
self.p3ptr().setZ(z)
property xyz:
def __get__(self):
return util.XYZ(self.x, self.y, self.z)
def __set__(self, val):
self.x, self.y, self.z = val
# TODO: How does this fit into the multi-error API? Still useful, but just reports first errs... how to get _all_ +- err pairs?
+ # LC: This is fine because preserntly only the highest dimension supports multi-errors
property xErrs:
def __get__(self):
return util.read_error_pair(self.p3ptr().xErrs())
def __set__(self, val):
self.p3ptr().setXErrs(util.read_symmetric(val))
# TODO: How does this fit into the multi-error API? Still useful, but just reports first errs... how to get _all_ +- err pairs?
+ # LC: This is fine because preserntly only the highest dimension supports multi-errors
property yErrs:
def __get__(self):
return util.read_error_pair(self.p3ptr().yErrs())
def __set__(self, val):
self.p3ptr().setYErrs(util.read_symmetric(val))
# TODO: How does this fit into the multi-error API? Still useful, but just reports first errs... how to get _all_ +- err pairs?
+ # LC: I think it's Ok to leave this like this, for most users the nominal is what they want anyway,
+ # and for those who want multi-errs, they can set using a method eg setErrs(dim,(ed,eu),source) and access using errs(dim,(ed,eu),source)
property zErrs:
def __get__(self):
return util.read_error_pair(self.p3ptr().zErrs())
def __set__(self, val):
self.p3ptr().setZErrs(util.read_symmetric(val))
@property
def xMin(self):
"""The minimum x position, i.e. lowest error"""
return self.p3ptr().xMin()
@property
def xMax(self):
"""The maximum x position, i.e. highest error"""
return self.p3ptr().xMax()
@property
def yMin(self):
"""The minimum y position, i.e. lowest error"""
return self.p3ptr().yMin()
@property
def yMax(self):
"""The maximum y position, i.e. highest error"""
return self.p3ptr().yMax()
@property
def zMin(self):
"""The minimum z position, i.e. lowest error"""
return self.p3ptr().zMin()
@property
def zMax(self):
"""The maximum z position, i.e. highest error"""
return self.p3ptr().zMax()
property xErrAvg:
def __get__(self):
return self.p3ptr().xErrAvg()
property yErrAvg:
def __get__(self):
return self.p3ptr().yErrAvg()
property zErrAvg:
def __get__(self):
return self.p3ptr().zErrAvg()
def scaleX(self, ax):
"""
(float) -> None
Scale the x point coordinates by the given factor.
"""
self.p3ptr().scaleX(ax)
def scaleY(self, ay):
"""
(float) -> None
Scale the y point coordinates by the given factor.
"""
self.p3ptr().scaleY(ay)
def scaleZ(self, az):
"""
(float) -> None
Scale the z point coordinates by the given factor.
"""
self.p3ptr().scaleZ(az)
def scaleXYZ(self, ax=1.0, ay=1.0, az=1.0):
"""
(float=1.0, float=1.0, float=1.0) -> None
Scale the point coordinates by the given factors.
"""
self.p3ptr().scaleXYZ(ax, ay, az)
# TODO: remove
def scaleXYZ(self, ax=1.0, ay=1.0, az=1.0):
"""
(double=1.0, double=1.0, double=1.0) -> None
DEPRECATED: USE scaleXYZ
Scale the point coordinates by the given factors.
"""
self.scaleXYZ(ax, ay, az)
# TODO: transformX,Y,Z
def __repr__(self):
return '<Point3D(x=%g, y=%g, z=%g)>' % (self.x, self.y, self.z)
def __richcmp__(Point3D self, Point3D other, int op):
if op == 0:
return deref(self.p3ptr()) < deref(other.p3ptr())
elif op == 1:
return deref(self.p3ptr()) <= deref(other.p3ptr())
elif op == 2:
return deref(self.p3ptr()) == deref(other.p3ptr())
elif op == 3:
return deref(self.p3ptr()) != deref(other.p3ptr())
elif op == 4:
return deref(self.p3ptr()) > deref(other.p3ptr())
elif op == 5:
return deref(self.p3ptr()) >= deref(other.p3ptr())
diff --git a/pyext/yoda/include/Scatter2D.pyx b/pyext/yoda/include/Scatter2D.pyx
--- a/pyext/yoda/include/Scatter2D.pyx
+++ b/pyext/yoda/include/Scatter2D.pyx
@@ -1,210 +1,217 @@
cimport util
cdef class Scatter2D(AnalysisObject):
"""
2D scatter plot, i.e. a collection of Point2D objects with positions and errors.
Constructor calling idioms:
Scatter2D(path="", title="")
Create a new empty scatter, with optional path and title.
Scatter2D(points, path="", title=""):
Create a new empty scatter from an iterable of points, with optional path
and title.
TODO: more documentation!
"""
cdef inline c.Scatter2D* s2ptr(self) except NULL:
return <c.Scatter2D*> self.ptr()
def __init__(self, *args, **kwargs):
util.try_loop([self.__init_2, self.__init_3], *args, **kwargs)
def __init_2(self, path="", title=""):
path = path.encode('utf-8')
title = title.encode('utf-8')
cutil.set_owned_ptr(self, new c.Scatter2D(<string>path, <string>title))
def __init_3(self, points, path="", title=""):
self.__init_2(path, title)
self.addPoints(points)
def clone(self):
"""() -> Scatter2D.
Clone this Scatter2D."""
return cutil.new_owned_cls(Scatter2D, self.s2ptr().newclone())
def __repr__(self):
return "<%s '%s' %d points>" % (self.__class__.__name__, self.path, len(self.points))
@property
def numPoints(self):
"""() -> int
Number of points in this scatter."""
return self.s2ptr().numPoints()
def __len__(self):
return self.numPoints
@property
def points(self):
"""Access the ordered list of points."""
return [self.point(i) for i in xrange(self.numPoints)]
def point(self, size_t i):
"""Access the i'th point."""
return cutil.new_borrowed_cls(Point2D, &self.s2ptr().point(i), self)
def __getitem__(self, py_ix):
cdef size_t i = cutil.pythonic_index(py_ix, self.s2ptr().numPoints())
return cutil.new_borrowed_cls(Point2D, &self.s2ptr().point(i), self)
def addPoint(self, *args, **kwargs):
"""Add a new point.
Provide either a single yoda.Point2D object, or the
four args: x, y, xerrs=0, yerrs=0.
"""
try:
self.__addPoint_point(*args, **kwargs)
except TypeError:
self.__addPoint_explicit(*args, **kwargs)
def __addPoint_explicit(self, x, y, xerrs=0, yerrs=0):
self.__addPoint_point(Point2D(x, y, xerrs, yerrs))
def __addPoint_point(self, Point2D p):
self.s2ptr().addPoint(p.p2ptr()[0])
def addPoints(self, iterable):
"""Add several new points."""
for row in iterable:
+ try:
self.addPoint(*row)
+ except TypeError:
+ self.addPoint(row)
def combineWith(self, others):
"""Try to add points from other Scatter2Ds into this one."""
cdef Scatter2D other
try:
# Can we type it as a Scatter2D?
other = others
except TypeError:
# Could be an iterable...
for other in others:
self.s2ptr().combineWith(deref(other.s2ptr()))
else:
self.s2ptr().combineWith(deref(other.s2ptr()))
def mkScatter(self):
"""None -> Scatter2D.
Make a new Scatter2D. Exists to allow mkScatter calls on any AnalysisObject,
even if it already is a scatter."""
cdef c.Scatter2D s2 = c.mkScatter_Scatter2D(deref(self.s2ptr()))
return cutil.new_owned_cls(Scatter2D, s2.newclone())
def scaleX(self, a):
"""(float) -> None
Scale the x values and errors of the points in this scatter by factor a."""
self.s2ptr().scaleX(a)
def scaleY(self, a):
"""(float) -> None
Scale the y values and errors of the points in this scatter by factor a."""
self.s2ptr().scaleY(a)
def scaleXY(self, ax=1.0, ay=1.0):
"""(float=1, float=1) -> None
Scale the values and errors of the points in this scatter by factors ax, ay."""
self.s2ptr().scaleXY(ax, ay)
# TODO: remove
def scale(self, ax=1.0, ay=1.0):
"""(float=1, float=1) -> None
DEPRECATED: USE scaleXY
Scale the values and errors of the points in this scatter by factors ax, ay."""
self.scaleXY(ax, ay)
def transformX(self, f):
"""(fn) -> None
Transform the x values and errors of the points in this scatter by function f."""
import ctypes
try:
callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f)
except:
raise RuntimeError("Callback is not of type (double) -> double")
fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0]
c.Scatter2D_transformX(deref(self.s2ptr()), fptr)
def transformY(self, f):
"""(fn) -> None
Transform the y values and errors of the points in this scatter by function f."""
import ctypes
try:
callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f)
except:
raise RuntimeError("Callback is not of type (double) -> double")
fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0]
c.Scatter2D_transformY(deref(self.s2ptr()), fptr)
+ def variations(self):
+ """None -> vector[string]
+ Get the list of variations stored in the poins of the Scatter"""
+ return self.s2ptr().variations()
# # TODO: remove?
# def __add__(Scatter2D self, Scatter2D other):
# return cutil.new_owned_cls(Scatter2D, c.Scatter2D_add_Scatter2D(self.s2ptr(), other.s2ptr()))
# # TODO: remove?
# def __sub__(Scatter2D self, Scatter2D other):
# return cutil.new_owned_cls(Scatter2D, c.Scatter2D_sub_Scatter2D(self.s2ptr(), other.s2ptr()))
def xVals(self):
return [p.x for p in self.points]
def xMins(self):
"""All x low values."""
return [p.xMin for p in self.points]
def xMaxs(self):
"""All x high values."""
return [p.xMax for p in self.points]
@property
def xMin(self):
"""Lowest x value."""
return min(self.xMins())
@property
def xMax(self):
"""Highest x value."""
return max(self.xMaxs())
def yVals(self):
return [p.y for p in self.points]
def yMins(self):
"""All y low values."""
return [p.yMin for p in self.points]
def yMaxs(self):
"""All y high values."""
return [p.yMax for p in self.points]
@property
def yMin(self):
"""Lowest x value."""
return min(self.yMins())
@property
def yMax(self):
"""Highest y value."""
return max(self.yMaxs())
## Convenience alias
S2D = Scatter2D
diff --git a/pyext/yoda/include/Scatter3D.pyx b/pyext/yoda/include/Scatter3D.pyx
--- a/pyext/yoda/include/Scatter3D.pyx
+++ b/pyext/yoda/include/Scatter3D.pyx
@@ -1,248 +1,255 @@
cimport util
cdef class Scatter3D(AnalysisObject):
"""
3D scatter plot, i.e. a collection of Point3D objects with positions and errors.
Constructor calling idioms:
Scatter3D(path="", title="")
Create a new empty scatter, with optional path and title.
Scatter3D(points, path="", title=""):
Create a new empty scatter from an iterable of points, with optional path
and title.
TODO: more documentation!
"""
cdef inline c.Scatter3D* s3ptr(self) except NULL:
return <c.Scatter3D*> self.ptr()
def __init__(self, *args, **kwargs):
util.try_loop([self.__init_2, self.__init_3], *args, **kwargs)
def __init_2(self, path="", title=""):
path = path.encode('utf-8')
title = title.encode('utf-8')
cutil.set_owned_ptr(self, new c.Scatter3D(<string>path, <string>title))
def __init_3(self, points, char* path="", char* title=""):
self.__init_2(path, title)
self.addPoints(points)
def clone(self):
"""() -> Scatter3D.
Clone this Scatter3D."""
return cutil.new_owned_cls(Scatter3D, self.s3ptr().newclone())
def __repr__(self):
return "<%s '%s' %d points>" % (self.__class__.__name__, self.path, len(self.points))
@property
def numPoints(self):
"""() -> int
Number of points in this scatter."""
return self.s3ptr().numPoints()
def __len__(self):
return self.numPoints
@property
def points(self):
"""Access the ordered list of points."""
return [self.point(i) for i in xrange(self.numPoints)]
def point(self, size_t i):
"""Access the i'th point."""
return cutil.new_borrowed_cls(Point3D, &self.s3ptr().point(i), self)
def __getitem__(self, py_ix):
cdef size_t i = cutil.pythonic_index(py_ix, self.s3ptr().numPoints())
return cutil.new_borrowed_cls(Point3D, &self.s3ptr().point(i), self)
def addPoint(self, *args, **kwargs):
"""Add a new point.
Provide either a single yoda.Point3D object, or the
3-6 args: x, y, z, xerrs=0, yerrs=0, zerrs=0.
"""
try:
self.__addPoint_point(*args, **kwargs)
except TypeError:
self.__addPoint_explicit(*args, **kwargs)
def __addPoint_explicit(self, x, y, z, xerrs=0, yerrs=0, zerrs=0):
self.__addPoint_point(Point3D(x, y, z, xerrs, yerrs, zerrs))
def __addPoint_point(self, Point3D p):
self.s3ptr().addPoint(p.p3ptr()[0])
def addPoints(self, iterable):
"""Add several new points."""
for row in iterable:
+ try:
self.addPoint(*row)
+ except TypeError:
+ self.addPoint(row)
def combineWith(self, others):
"""Try to add points from other Scatter3Ds into this one."""
cdef Scatter3D other
try:
# Can we type it as a Scatter3D?
other = others
except TypeError:
# Could be an iterable...
for other in others:
self.s3ptr().combineWith(deref(other.s3ptr()))
else:
self.s3ptr().combineWith(deref(other.s3ptr()))
def mkScatter(self):
"""None -> Scatter3D.
Make a new Scatter3D. Exists to allow mkScatter calls on any AnalysisObject,
even if it already is a scatter."""
cdef c.Scatter3D s3 = c.mkScatter_Scatter3D(deref(self.s3ptr()))
return cutil.new_owned_cls(Scatter3D, s3.newclone())
def scaleX(self, a):
"""(float) -> None
Scale the x values and errors of the points in this scatter by factor a."""
self.s3ptr().scaleX(a)
def scaleY(self, a):
"""(float) -> None
Scale the y values and errors of the points in this scatter by factor a."""
self.s3ptr().scaleY(a)
def scaleZ(self, a):
"""(float) -> None
Scale the z values and errors of the points in this scatter by factor a."""
self.s3ptr().scaleZ(a)
def scaleXYZ(self, ax=1, ay=1, az=1):
"""(float=1, float=1, float=1) -> None
Scale the values and errors of the points in this scatter by factors ax, ay, az."""
self.s3ptr().scaleXYZ(ax, ay, az)
# TODO: remove
def scale(self, ax=1, ay=1, az=1):
"""(float=1, float=1, float=1) -> None
DEPRECATED: USE scaleXYZ
Scale the values and errors of the points in this scatter by factors ax, ay, az."""
self.scaleXYZ(ax, ay, az)
def transformX(self, f):
"""(fn) -> None
Transform the x values and errors of the points in this scatter by function f."""
import ctypes
try:
callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f)
except:
raise RuntimeError("Callback is not of type (double) -> double")
fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0]
c.Scatter3D_transformX(deref(self.s3ptr()), fptr)
def transformY(self, f):
"""(fn) -> None
Transform the y values and errors of the points in this scatter by function f."""
import ctypes
try:
callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f)
except:
raise RuntimeError("Callback is not of type (double) -> double")
fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0]
c.Scatter3D_transformY(deref(self.s3ptr()), fptr)
def transformZ(self, f):
"""(fn) -> None
Transform the z values and errors of the points in this scatter by function f."""
import ctypes
try:
callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f)
except:
raise RuntimeError("Callback is not of type (double) -> double")
fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0]
c.Scatter3D_transformZ(deref(self.s3ptr()), fptr)
# # TODO: remove?
# def __add__(Scatter3D self, Scatter3D other):
# return cutil.new_owned_cls(Scatter3D, c.Scatter3D_add_Scatter3D(self.s3ptr(), other.s3ptr()))
# # TODO: remove?
# def __sub__(Scatter3D self, Scatter3D other):
# return cutil.new_owned_cls(Scatter3D, c.Scatter3D_sub_Scatter3D(self.s3ptr(), other.s3ptr()))
+ def variations(self):
+ """None -> vector[string]
+ Get the list of variations stored in the poins of the Scatter"""
+ return self.s3ptr().variations()
def xVals(self):
return [p.x for p in self.points]
def xMins(self):
"""All x low values."""
return [p.xMin for p in self.points]
def xMaxs(self):
"""All x high values."""
return [p.xMax for p in self.points]
@property
def xMin(self):
"""Lowest x value."""
return min(self.xMins())
@property
def xMax(self):
"""Highest x value."""
return max(self.xMaxs())
def yVals(self):
return [p.y for p in self.points]
def yMins(self):
"""All x low values."""
return [p.yMin for p in self.points]
def yMaxs(self):
"""All x high values."""
return [p.yMax for p in self.points]
@property
def yMin(self):
"""Lowest x value."""
return min(self.yMins())
@property
def yMax(self):
"""Highest y value."""
return max(self.yMaxs())
def zVals(self):
return [p.z for p in self.points]
def zMins(self):
"""All z low values."""
return [p.zMin for p in self.points]
def zMaxs(self):
"""All z high values."""
return [p.zMax for p in self.points]
@property
def zMin(self):
"""Lowest z value."""
return min(self.zMins())
@property
def zMax(self):
"""Highest z value."""
return max(self.zMaxs())
## Convenience alias
S3D = Scatter3D
diff --git a/src/ReaderYODA.cc b/src/ReaderYODA.cc
--- a/src/ReaderYODA.cc
+++ b/src/ReaderYODA.cc
@@ -1,527 +1,550 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#include "YODA/ReaderYODA.h"
#include "YODA/Utils/StringUtils.h"
#include "YODA/Utils/getline.h"
#include "YODA/Exceptions.h"
#include "YODA/Config/DummyConfig.h"
#include "YODA/Counter.h"
#include "YODA/Histo1D.h"
#include "YODA/Histo2D.h"
#include "YODA/Profile1D.h"
#include "YODA/Profile2D.h"
#include "YODA/Scatter1D.h"
#include "YODA/Scatter2D.h"
#include "YODA/Scatter3D.h"
#include "yaml-cpp/yaml.h"
#ifdef YAML_NAMESPACE
#define YAML YAML_NAMESPACE
#endif
#ifdef HAVE_LIBZ
#define _XOPEN_SOURCE 700
#include "zstr/zstr.hpp"
#endif
#include <iostream>
#include <cstring>
using namespace std;
namespace YODA {
/// Singleton creation function
Reader& ReaderYODA::create() {
static ReaderYODA _instance;
return _instance;
}
namespace {
/// Fast ASCII tokenizer, extended from FastIStringStream by Gavin Salam.
class aistringstream {
public:
// Constructor from char*
aistringstream(const char* line=0) { reset(line); }
// Constructor from std::string
aistringstream(const string& line) { reset(line); }
// Re-init to new line as char*
void reset(const char* line=0) {
_next = const_cast<char*>(line);
_new_next = _next;
_error = false;
}
// Re-init to new line as std::string
void reset(const string& line) { reset(line.c_str()); }
// Tokenizing stream operator (forwards to specialisations)
template<class T>
aistringstream& operator >> (T& value) {
_get(value);
if (_new_next == _next) _error = true; // handy error condition behaviour!
_next = _new_next;
return *this;
}
// Allow use of operator>> in a while loop
operator bool() const { return !_error; }
private:
void _get(double& x) { x = std::strtod(_next, &_new_next); }
void _get(float& x) { x = std::strtof(_next, &_new_next); }
void _get(int& i) { i = std::strtol(_next, &_new_next, 10); } // force base 10!
void _get(long& i) { i = std::strtol(_next, &_new_next, 10); } // force base 10!
void _get(unsigned int& i) { i = std::strtoul(_next, &_new_next, 10); } // force base 10!
void _get(long unsigned int& i) { i = std::strtoul(_next, &_new_next, 10); } // force base 10!
void _get(string& x) {
/// @todo If _next and _new_next become null?
while (std::isspace(*_next)) _next += 1;
_new_next = _next;
while (!std::isspace(*_new_next)) _new_next += 1;
x = string(_next, _new_next-_next);
}
char *_next, *_new_next;
bool _error;
};
}
void ReaderYODA::read(istream& stream_, vector<AnalysisObject*>& aos) {
#ifdef HAVE_LIBZ
// NB. zstr auto-detects if file is deflated or plain-text
zstr::istream stream(stream_);
#else
istream& stream = stream_;
#endif
// Data format parsing states, representing current data type
/// @todo Extension to e.g. "bar" or multi-counter or binned-value types, and new formats for extended Scatter types
enum Context { NONE, //< outside any data block
SCATTER1D, SCATTER2D, SCATTER3D,
COUNTER,
HISTO1D, HISTO2D,
PROFILE1D, PROFILE2D };
/// State of the parser: line number, line, parser context, and pointer(s) to the object currently being assembled
unsigned int nline = 0;
string s;
Context context = NONE;
//
AnalysisObject* aocurr = NULL; //< Generic current AO pointer
vector<HistoBin1D> h1binscurr; //< Current H1 bins container
vector<HistoBin2D> h2binscurr; //< Current H2 bins container
vector<ProfileBin1D> p1binscurr; //< Current P1 bins container
vector<ProfileBin2D> p2binscurr; //< Current P2 bins container
vector<Point1D> pt1scurr; //< Current Point1Ds container
vector<Point2D> pt2scurr; //< Current Point2Ds container
vector<Point3D> pt3scurr; //< Current Point3Ds container
Counter* cncurr = NULL;
Histo1D* h1curr = NULL;
Histo2D* h2curr = NULL;
Profile1D* p1curr = NULL;
Profile2D* p2curr = NULL;
Scatter1D* s1curr = NULL;
Scatter2D* s2curr = NULL;
Scatter3D* s3curr = NULL;
std::vector<std::string> variationscurr;
string annscurr;
// Loop over all lines of the input file
aistringstream aiss;
bool in_anns = false;
string fmt = "1";
//int nfmt = 1;
while (Utils::getline(stream, s)) {
nline += 1;
// CLEAN LINES IF NOT IN ANNOTATION MODE
if (!in_anns) {
// Trim the line
Utils::itrim(s);
// Ignore blank lines
if (s.empty()) continue;
// Ignore comments (whole-line only, without indent, and still allowed for compatibility on BEGIN/END lines)
if (s.find("#") == 0 && s.find("BEGIN") == string::npos && s.find("END") == string::npos) continue;
}
// STARTING A NEW CONTEXT
if (context == NONE) {
// We require a BEGIN line to start a context
if (s.find("BEGIN ") == string::npos) {
stringstream ss;
ss << "Unexpected line in YODA format parsing when BEGIN expected: '" << s << "' on line " << nline;
throw ReadError(ss.str());
}
// Remove leading #s from the BEGIN line if necessary
while (s.find("#") == 0) s = Utils::trim(s.substr(1));
// Split into parts
vector<string> parts;
istringstream iss(s); string tmp;
while (iss >> tmp) parts.push_back(tmp);
// Extract context from BEGIN type
if (parts.size() < 2 || parts[0] != "BEGIN") {
stringstream ss;
ss << "Unexpected BEGIN line structure when BEGIN expected: '" << s << "' on line " << nline;
throw ReadError(ss.str());
}
// Second part is the context name
const string ctxstr = parts[1];
// Get block path if possible
const string path = (parts.size() >= 3) ? parts[2] : "";
// Set the new context and create a new AO to populate
/// @todo Use the block format version for (occasional, careful) format evolution
if (Utils::startswith(ctxstr, "YODA_COUNTER")) {
context = COUNTER;
cncurr = new Counter(path);
aocurr = cncurr;
} else if (Utils::startswith(ctxstr, "YODA_SCATTER1D")) {
context = SCATTER1D;
s1curr = new Scatter1D(path);
aocurr = s1curr;
} else if (Utils::startswith(ctxstr, "YODA_SCATTER2D")) {
context = SCATTER2D;
s2curr = new Scatter2D(path);
aocurr = s2curr;
} else if (Utils::startswith(ctxstr, "YODA_SCATTER3D")) {
context = SCATTER3D;
s3curr = new Scatter3D(path);
aocurr = s3curr;
} else if (Utils::startswith(ctxstr, "YODA_HISTO1D")) {
context = HISTO1D;
h1curr = new Histo1D(path);
aocurr = h1curr;
} else if (Utils::startswith(ctxstr, "YODA_HISTO2D")) {
context = HISTO2D;
h2curr = new Histo2D(path);
aocurr = h2curr;
} else if (Utils::startswith(ctxstr, "YODA_PROFILE1D")) {
context = PROFILE1D;
p1curr = new Profile1D(path);
aocurr = p1curr;
} else if (Utils::startswith(ctxstr, "YODA_PROFILE2D")) {
context = PROFILE2D;
p2curr = new Profile2D(path);
aocurr = p2curr;
}
// cout << aocurr->path() << " " << nline << " " << context << endl;
// Get block format version if possible (assume version=1 if none found)
const size_t vpos = ctxstr.find_last_of("V");
fmt = vpos != string::npos ? ctxstr.substr(vpos+1) : "1";
// cout << fmt << endl;
// From version 2 onwards, use the in_anns state from BEGIN until ---
if (fmt != "1") in_anns = true;
} else { //< not a BEGIN line
// Throw error if a BEGIN line is found
if (s.find("BEGIN ") != string::npos) ///< @todo require pos = 0 from fmt=V2
throw ReadError("Unexpected BEGIN line in YODA format parsing before ending current BEGIN..END block");
// FINISHING THE CURRENT CONTEXT
// Clear/reset context and register AO
/// @todo Throw error if mismatch between BEGIN (context) and END types
if (s.find("END ") != string::npos) { ///< @todo require pos = 0 from fmt=V2
switch (context) {
case COUNTER:
break;
case HISTO1D:
h1curr->addBins(h1binscurr);
h1binscurr.clear();
break;
case HISTO2D:
h2curr->addBins(h2binscurr);
h2binscurr.clear();
break;
case PROFILE1D:
p1curr->addBins(p1binscurr);
p1binscurr.clear();
break;
case PROFILE2D:
p2curr->addBins(p2binscurr);
p2binscurr.clear();
break;
case SCATTER1D:
s1curr->addPoints(pt1scurr);
pt1scurr.clear();
break;
case SCATTER2D:
s2curr->addPoints(pt2scurr);
pt2scurr.clear();
break;
case SCATTER3D:
s3curr->addPoints(pt3scurr);
pt3scurr.clear();
break;
case NONE:
break;
}
// Set all annotations
try {
// YAML::Node anns = YAML::Load(annscurr);
istringstream iss(annscurr);
YAML::Parser parser(iss);
YAML::Node anns;
parser.GetNextDocument(anns);
for (YAML::Iterator it = anns.begin(); it != anns.end(); ++it) {
string key, val;
it.first() >> key;
YAML::Emitter em;
+ em << YAML::Flow ;
em << it.second();
val = em.c_str();
// cout << "@@@ '" << key << "', '" << val << "'" << endl;
- aocurr->setAnnotation(key, val);
+ // The Variations annotation is just a placeholder to help collect the right columns
+ // Don't want to be saving it to the actual AO, since the method variations()
+ // provides the info that's needed without needing to keep the annotation up to date
+ if (!(key.find("Variations") != string::npos)) aocurr->setAnnotation(key, val);
}
} catch (...) {
/// @todo Is there a case for just giving up on these annotations, printing the error msg, and keep going? As an option?
const string err = "Problem during annotation parsing of YAML block:\n'''\n" + annscurr + "\n'''";
// cerr << err << endl;
throw ReadError(err);
}
annscurr.clear();
variationscurr.clear();
in_anns = false;
// Put this AO in the completed stack
aos.push_back(aocurr);
// Clear all current-object pointers
aocurr = nullptr;
cncurr = nullptr;
h1curr = nullptr; h2curr = nullptr;
p1curr = nullptr; p2curr = nullptr;
s1curr = nullptr; s2curr = nullptr; s3curr = nullptr;
context = NONE;
continue;
}
// ANNOTATIONS PARSING
if (fmt == "1") {
// First convert to one-key-per-line YAML syntax
const size_t ieq = s.find("=");
if (ieq != string::npos) s.replace(ieq, 1, ": ");
const size_t ico = s.find(":");
if (ico != string::npos) {
annscurr += (annscurr.empty() ? "" : "\n") + s;
continue;
}
} else if (in_anns) {
if (s == "---") {
in_anns = false;
} else {
annscurr += (annscurr.empty() ? "" : "\n") + s;
// in order to handle multi-error points in scatters, we need to know which variations are stored, if any
// can't wait until we process the annotations at the end, since need to know when filling points
// this is a little inelegant tough...
- if (s.find("variations") != string::npos) {
+ if (s.find("Variations") != string::npos) {
istringstream iss(s);
YAML::Parser parser(iss);
YAML::Node anns;
parser.GetNextDocument(anns);
for (YAML::Iterator it = anns.begin(); it != anns.end(); ++it) {
for (YAML::Iterator it2 = it.second().begin(); it2 != it.second().end(); ++it2) {
string val;
*it2 >> val;
variationscurr.push_back(val);
}
}
}
}
continue;
}
// DATA PARSING
aiss.reset(s);
// double sumw(0), sumw2(0), sumwx(0), sumwx2(0), sumwy(0), sumwy2(0), sumwz(0), sumwz2(0), sumwxy(0), sumwxz(0), sumwyz(0), n(0);
switch (context) {
case COUNTER:
{
double sumw(0), sumw2(0), n(0);
aiss >> sumw >> sumw2 >> n;
cncurr->setDbn(Dbn0D(n, sumw, sumw2));
}
break;
case HISTO1D:
{
string xoflow1, xoflow2; double xmin(0), xmax(0);
double sumw(0), sumw2(0), sumwx(0), sumwx2(0), n(0);
/// @todo Improve/factor this "bin" string-or-float parsing... esp for mixed case of 2D overflows
/// @todo When outflows are treated as "infinity bins" and don't require a distinct type, string replace under/over -> -+inf
if (s.find("Total") != string::npos || s.find("Underflow") != string::npos || s.find("Overflow") != string::npos) {
aiss >> xoflow1 >> xoflow2;
} else {
aiss >> xmin >> xmax;
}
// The rest is the same for overflows and in-range bins
aiss >> sumw >> sumw2 >> sumwx >> sumwx2 >> n;
const Dbn1D dbn(n, sumw, sumw2, sumwx, sumwx2);
if (xoflow1 == "Total") h1curr->setTotalDbn(dbn);
else if (xoflow1 == "Underflow") h1curr->setUnderflow(dbn);
else if (xoflow1 == "Overflow") h1curr->setOverflow(dbn);
// else h1curr->addBin(HistoBin1D(std::make_pair(xmin,xmax), dbn));
else h1binscurr.push_back(HistoBin1D(std::make_pair(xmin,xmax), dbn));
}
break;
case HISTO2D:
{
string xoflow1, xoflow2, yoflow1, yoflow2; double xmin(0), xmax(0), ymin(0), ymax(0);
double sumw(0), sumw2(0), sumwx(0), sumwx2(0), sumwy(0), sumwy2(0), sumwxy(0), n(0);
/// @todo Improve/factor this "bin" string-or-float parsing... esp for mixed case of 2D overflows
/// @todo When outflows are treated as "infinity bins" and don't require a distinct type, string replace under/over -> -+inf
if (s.find("Total") != string::npos) {
aiss >> xoflow1 >> xoflow2; // >> yoflow1 >> yoflow2;
} else if (s.find("Underflow") != string::npos || s.find("Overflow") != string::npos) {
throw ReadError("2D histogram overflow syntax is not yet defined / handled");
} else {
aiss >> xmin >> xmax >> ymin >> ymax;
}
// The rest is the same for overflows and in-range bins
aiss >> sumw >> sumw2 >> sumwx >> sumwx2 >> sumwy >> sumwy2 >> sumwxy >> n;
const Dbn2D dbn(n, sumw, sumw2, sumwx, sumwx2, sumwy, sumwy2, sumwxy);
if (xoflow1 == "Total") h2curr->setTotalDbn(dbn);
// else if (xoflow1 == "Underflow") p1curr->setUnderflow(dbn);
// else if (xoflow1 == "Overflow") p1curr->setOverflow(dbn);
else {
assert(xoflow1.empty());
// h2curr->addBin(HistoBin2D(std::make_pair(xmin,xmax), std::make_pair(ymin,ymax), dbn));
h2binscurr.push_back(HistoBin2D(std::make_pair(xmin,xmax), std::make_pair(ymin,ymax), dbn));
}
}
break;
case PROFILE1D:
{
string xoflow1, xoflow2; double xmin(0), xmax(0);
double sumw(0), sumw2(0), sumwx(0), sumwx2(0), sumwy(0), sumwy2(0), n(0);
/// @todo Improve/factor this "bin" string-or-float parsing... esp for mixed case of 2D overflows
/// @todo When outflows are treated as "infinity bins" and don't require a distinct type, string replace under/over -> -+inf
if (s.find("Total") != string::npos || s.find("Underflow") != string::npos || s.find("Overflow") != string::npos) {
aiss >> xoflow1 >> xoflow2;
} else {
aiss >> xmin >> xmax;
}
// The rest is the same for overflows and in-range bins
aiss >> sumw >> sumw2 >> sumwx >> sumwx2 >> sumwy >> sumwy2 >> n;
const double DUMMYWXY = 0;
const Dbn2D dbn(n, sumw, sumw2, sumwx, sumwx2, sumwy, sumwy2, DUMMYWXY);
if (xoflow1 == "Total") p1curr->setTotalDbn(dbn);
else if (xoflow1 == "Underflow") p1curr->setUnderflow(dbn);
else if (xoflow1 == "Overflow") p1curr->setOverflow(dbn);
// else p1curr->addBin(ProfileBin1D(std::make_pair(xmin,xmax), dbn));
else p1binscurr.push_back(ProfileBin1D(std::make_pair(xmin,xmax), dbn));
}
break;
case PROFILE2D:
{
string xoflow1, xoflow2, yoflow1, yoflow2; double xmin(0), xmax(0), ymin(0), ymax(0);
double sumw(0), sumw2(0), sumwx(0), sumwx2(0), sumwy(0), sumwy2(0), sumwz(0), sumwz2(0), sumwxy(0), sumwxz(0), sumwyz(0), n(0);
/// @todo Improve/factor this "bin" string-or-float parsing... esp for mixed case of 2D overflows
/// @todo When outflows are treated as "infinity bins" and don't require a distinct type, string replace under/over -> -+inf
if (s.find("Total") != string::npos) {
aiss >> xoflow1 >> xoflow2; // >> yoflow1 >> yoflow2;
} else if (s.find("Underflow") != string::npos || s.find("Overflow") != string::npos) {
throw ReadError("2D profile overflow syntax is not yet defined / handled");
} else {
aiss >> xmin >> xmax >> ymin >> ymax;
}
// The rest is the same for overflows and in-range bins
aiss >> sumw >> sumw2 >> sumwx >> sumwx2 >> sumwy >> sumwy2 >> sumwz >> sumwz2 >> sumwxy >> sumwxz >> sumwyz >> n;
const Dbn3D dbn(n, sumw, sumw2, sumwx, sumwx2, sumwy, sumwy2, sumwz, sumwz2, sumwxy, sumwxz, sumwyz);
if (xoflow1 == "Total") p2curr->setTotalDbn(dbn);
// else if (xoflow1 == "Underflow") p2curr->setUnderflow(dbn);
// else if (xoflow1 == "Overflow") p2curr->setOverflow(dbn);
else {
assert(xoflow1.empty());
// p2curr->addBin(ProfileBin2D(std::make_pair(xmin,xmax), std::make_pair(ymin,ymax), dbn));
p2binscurr.push_back(ProfileBin2D(std::make_pair(xmin,xmax), std::make_pair(ymin,ymax), dbn));
}
}
break;
case SCATTER1D:
{
double x(0), exm(0), exp(0);
aiss >> x >> exm >> exp;
// set nominal point
Point1D thispoint=Point1D(x, exm, exp);
// check if we stored variations of this point
if (variationscurr.size()>0){
// for each variation, store the alt errors.
// start at 1 since we have already filled nominal !
for (unsigned int ivar=1; ivar<variationscurr.size(); ivar++){
std::string thisvariation=variationscurr[ivar];
aiss >> exm >> exp;
thispoint.setXErrs(exm,exp,thisvariation);
}
}
- // s1curr->addPoint(Point1D(x, exm, exp));
pt1scurr.push_back(thispoint);
}
break;
case SCATTER2D:
{
double x(0), y(0), exm(0), exp(0), eym(0), eyp(0);
- /// @todo Need to improve this format for multi-err points
aiss >> x >> exm >> exp >> y >> eym >> eyp;
- // s2curr->addPoint(Point2D(x, y, exm, exp, eym, eyp));
- pt2scurr.push_back(Point2D(x, y, exm, exp, eym, eyp));
+ // set nominal point
+ Point2D thispoint=Point2D(x, y, exm, exp, eym, eyp);
+ // check if we stored variations of this point
+ if (variationscurr.size()>0){
+ // for each variation, store the alt errors.
+ // start at 1 since we have already filled nominal !
+ for (unsigned int ivar=1; ivar<variationscurr.size(); ivar++){
+ std::string thisvariation=variationscurr[ivar];
+ aiss >> eym >> eyp;
+ thispoint.setYErrs(eym,eyp,thisvariation);
+ }
+ }
+ pt2scurr.push_back(thispoint);
}
break;
case SCATTER3D:
{
double x(0), y(0), z(0), exm(0), exp(0), eym(0), eyp(0), ezm(0), ezp(0);
- /// @todo Need to improve this format for multi-err points
aiss >> x >> exm >> exp >> y >> eym >> eyp >> z >> ezm >> ezp;
- // s3curr->addPoint(Point3D(x, y, z, exm, exp, eym, eyp, ezm, ezp));
- pt3scurr.push_back(Point3D(x, y, z, exm, exp, eym, eyp, ezm, ezp));
+ // set nominal point
+ Point3D thispoint=Point3D(x, y, z, exm, exp, eym, eyp, ezm, ezp);
+ // check if we stored variations of this point
+ if (variationscurr.size()>0){
+ // for each variation, store the alt errors.
+ // start at 1 since we have already filled nominal !
+ for (unsigned int ivar=1; ivar<variationscurr.size(); ivar++){
+ std::string thisvariation=variationscurr[ivar];
+ aiss >> ezm >> ezp;
+ thispoint.setZErrs(ezm,ezp,thisvariation);
+ }
+ }
+ pt3scurr.push_back(thispoint);
}
break;
default:
throw ReadError("Unknown context in YODA format parsing: how did this happen?");
}
// cout << "AO CONTENT " << nline << endl;
// cout << " " << xmin << " " << xmax << " " << ymin << " " << ymax << " / '" << xoflow1 << "' '" << xoflow2 << "' '" << yoflow1 << "' '" << yoflow2 << "'" << endl;
// cout << " " << sumw << " " << sumw2 << " " << sumwx << " " << sumwx2 << " " << sumwy << " " << sumwy2 << " " << sumwz << " " << sumwz2 << " " << sumwxy << " " << sumwxz << " " << sumwyz << " " << n << endl;
// cout << " " << x << " " << y << " " << z << " " << exm << " " << exp << " " << eym << " " << eyp << " " << ezm << " " << ezp << endl;
}
}
}
}
diff --git a/src/Scatter1D.cc b/src/Scatter1D.cc
--- a/src/Scatter1D.cc
+++ b/src/Scatter1D.cc
@@ -1,53 +1,30 @@
#include "YODA/Scatter1D.h"
#include "YODA/Counter.h"
#include <sstream>
namespace YODA {
/// Make a Scatter1D representation of a Histo1D
Scatter1D mkScatter(const Counter& c) {
Scatter1D rtn;
for (const std::string& a : c.annotations())
rtn.setAnnotation(a, c.annotation(a));
rtn.setAnnotation("Type", c.type()); // might override the copied ones
rtn.addPoint(c.val(), c.err());
return rtn;
}
- /// Update the annotation which holds the names of the variations
- void Scatter1D::updateVariations(Scatter1D::Points& points){
- std::vector<std::string> variations;
- YAML::Node variationsYAML;
- for (auto &point : points){
+ const std::vector<std::string> Scatter1D::variations() const {
+ std::vector<std::string> vecvariations;
+ for (auto &point : this->_points){
for (auto &it : point.errMap()){
//if the variation is not already in the vector, add it !
- if (std::find(variations.begin(), variations.end(), it.first) == variations.end()){
- variations.push_back(it.first);
+ if (std::find(vecvariations.begin(), vecvariations.end(), it.first) == vecvariations.end()){
+ vecvariations.push_back(it.first);
}
}
}
- YAML::Emitter out;
- out << YAML::Flow ;
- out << variations;
- this->setAnnotation("variations",(std::string) out.c_str());
- }
-
- /// Access the names of the variations as a vector of strings
- const std::vector<std::string> Scatter1D::variations() const {
- std::vector<std::string> vecvariations;
- if (this->hasAnnotation("variations")){
- std::string annvariations = this->annotation("variations");
- std::istringstream iss(annvariations);
- YAML::Parser parser(iss);
- YAML::Node anns;
- parser.GetNextDocument(anns);
- for (YAML::Iterator it = anns.begin(); it != anns.end(); ++it) {
- std::string val;
- *it >> val;
- vecvariations.push_back(val);
- }
- }
return vecvariations;
}
}
diff --git a/src/Scatter2D.cc b/src/Scatter2D.cc
--- a/src/Scatter2D.cc
+++ b/src/Scatter2D.cc
@@ -1,72 +1,85 @@
#include "YODA/Scatter2D.h"
#include "YODA/Histo1D.h"
#include "YODA/Profile1D.h"
+#include <sstream>
namespace YODA {
/// Make a Scatter2D representation of a Histo1D
Scatter2D mkScatter(const Histo1D& h, bool usefocus) {
Scatter2D rtn;
for (const std::string& a : h.annotations())
rtn.setAnnotation(a, h.annotation(a));
rtn.setAnnotation("Type", h.type()); // might override the copied ones
for (const HistoBin1D& b : h.bins()) {
const double x = usefocus ? b.xFocus() : b.xMid();
const double ex_m = x - b.xMin();
const double ex_p = b.xMax() - x;
double y;
try {
y = b.height();
} catch (const Exception&) { // LowStatsError or WeightError
y = std::numeric_limits<double>::quiet_NaN();
}
double ey;
try {
ey = b.heightErr();
} catch (const Exception&) { // LowStatsError or WeightError
ey = std::numeric_limits<double>::quiet_NaN();
}
const Point2D pt(x, y, ex_m, ex_p, ey, ey);
rtn.addPoint(pt);
}
assert(h.numBins() == rtn.numPoints());
return rtn;
}
/// Make a Scatter2D representation of a Profile1D
Scatter2D mkScatter(const Profile1D& p, bool usefocus, bool usestddev) {
Scatter2D rtn;
for (const std::string& a : p.annotations())
rtn.setAnnotation(a, p.annotation(a));
rtn.setAnnotation("Type", p.type());
for (const ProfileBin1D& b : p.bins()) {
const double x = usefocus ? b.xFocus() : b.xMid();
const double ex_m = x - b.xMin();
const double ex_p = b.xMax() - x;
double y;
try {
y = b.mean();
} catch (const Exception&) { // LowStatsError or WeightError
y = std::numeric_limits<double>::quiet_NaN();
}
double ey;
try {
ey = usestddev ? b.stdDev() : b.stdErr(); ///< Control y-error scheme via usestddev arg
} catch (const Exception&) { // LowStatsError or WeightError
ey = std::numeric_limits<double>::quiet_NaN();
}
const Point2D pt(x, y, ex_m, ex_p, ey, ey);
rtn.addPoint(pt);
}
assert(p.numBins() == rtn.numPoints());
return rtn;
}
-
+
+ const std::vector<std::string> Scatter2D::variations() const {
+ std::vector<std::string> vecvariations;
+ for (auto &point : this->_points){
+ for (auto &it : point.errMap()){
+ //if the variation is not already in the vector, add it !
+ if (std::find(vecvariations.begin(), vecvariations.end(), it.first) == vecvariations.end()){
+ vecvariations.push_back(it.first);
+ }
+ }
+ }
+ return vecvariations;
+ }
}
diff --git a/src/Scatter3D.cc b/src/Scatter3D.cc
--- a/src/Scatter3D.cc
+++ b/src/Scatter3D.cc
@@ -1,108 +1,122 @@
#include "YODA/Scatter3D.h"
#include "YODA/Histo2D.h"
#include "YODA/Profile2D.h"
#include "YODA/Exceptions.h"
+#include <sstream>
namespace YODA {
Scatter3D mkScatter(const Histo2D& h, bool usefocus) {
Scatter3D rtn;
for (const std::string& a : h.annotations())
rtn.setAnnotation(a, h.annotation(a));
rtn.setAnnotation("Type", h.type());
for (size_t i = 0; i < h.numBins(); ++i) {
const HistoBin2D& b = h.bin(i);
/// SAME FOR ALL 2D BINS
double x = b.xMid();
if (usefocus) {
try {
x = b.xFocus();
} catch (const LowStatsError& lse) {
x = b.xMid();
}
}
const double exminus = x - b.xMin();
const double explus = b.xMax() - x;
double y = b.yMid();
if (usefocus) {
try {
y = b.yFocus();
} catch (const LowStatsError& lse) {
y = b.yMid();
}
}
const double eyminus = y - b.yMin();
const double eyplus = b.yMax() - y;
/// END SAME FOR ALL 2D BINS
const double z = b.height();
const double ez = b.heightErr();
rtn.addPoint(x, y, z, exminus, explus, eyminus, eyplus, ez, ez);
}
return rtn;
}
Scatter3D mkScatter(const Profile2D& h, bool usefocus, bool usestddev) {
Scatter3D rtn;
for (const std::string& a : h.annotations())
rtn.setAnnotation(a, h.annotation(a));
rtn.setAnnotation("Type", h.type());
for (size_t i = 0; i < h.numBins(); ++i) {
const ProfileBin2D& b = h.bin(i);
/// SAME FOR ALL 2D BINS
double x = b.xMid();
if (usefocus) {
try {
x = b.xFocus();
} catch (const LowStatsError& lse) {
x = b.xMid();
}
}
const double exminus = x - b.xMin();
const double explus = b.xMax() - x;
double y = b.yMid();
if (usefocus) {
try {
y = b.yFocus();
} catch (const LowStatsError& lse) {
y = b.yMid();
}
}
const double eyminus = y - b.yMin();
const double eyplus = b.yMax() - y;
/// END SAME FOR ALL 2D BINS
double z;
try {
z = b.mean();
} catch (const LowStatsError& lse) {
z = std::numeric_limits<double>::quiet_NaN();
}
double ez;
try {
ez = usestddev ? b.stdDev() : b.stdErr(); ///< Control z-error scheme via usestddev arg
} catch (const LowStatsError& lse) {
ez = std::numeric_limits<double>::quiet_NaN();
}
rtn.addPoint(x, y, z, exminus, explus, eyminus, eyplus, ez, ez);
}
return rtn;
}
-
+
+
+ const std::vector<std::string> Scatter3D::variations() const {
+ std::vector<std::string> vecvariations;
+ for (auto &point : this->_points){
+ for (auto &it : point.errMap()){
+ //if the variation is not already in the vector, add it !
+ if (std::find(vecvariations.begin(), vecvariations.end(), it.first) == vecvariations.end()){
+ vecvariations.push_back(it.first);
+ }
+ }
+ }
+ return vecvariations;
+ }
}
diff --git a/src/Writer.cc b/src/Writer.cc
--- a/src/Writer.cc
+++ b/src/Writer.cc
@@ -1,126 +1,126 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#include "YODA/Writer.h"
#include "YODA/WriterYODA.h"
#include "YODA/WriterAIDA.h"
#include "YODA/WriterFLAT.h"
#include "YODA/Config/BuildConfig.h"
#ifdef HAVE_LIBZ
#define _XOPEN_SOURCE 700
#include "zstr/zstr.hpp"
#endif
#include <iostream>
#include <typeinfo>
#include <sstream>
using namespace std;
namespace YODA {
Writer& mkWriter(const string& name) {
// Determine the format from the string (a file or file extension)
const size_t lastdot = name.find_last_of(".");
string fmt = Utils::toLower(lastdot == string::npos ? name : name.substr(lastdot+1));
const bool compress = (fmt == "gz");
cout << "***" << compress << endl;
if (compress) {
#ifndef HAVE_LIBZ
throw UserError("YODA was compiled without zlib support: can't write " + name);
#endif
const size_t lastbutonedot = (lastdot == string::npos) ? string::npos : name.find_last_of(".", lastdot-1);
fmt = Utils::toLower(lastbutonedot == string::npos ? name : name.substr(lastbutonedot+1));
}
// Create the appropriate Writer
Writer* w = nullptr;
if (Utils::startswith(fmt, "yoda")) w = &WriterYODA::create();
if (Utils::startswith(fmt, "aida")) w = &WriterAIDA::create();
if (Utils::startswith(fmt, "dat" )) w = &WriterFLAT::create(); ///< @todo Improve/remove... .ydat?
if (Utils::startswith(fmt, "flat")) w = &WriterFLAT::create();
if (!w) throw UserError("Format cannot be identified from string '" + name + "'");
w->useCompression(compress);
return *w;
}
void Writer::write(const std::string& filename, const AnalysisObject& ao) {
std::vector<const AnalysisObject*> vec{&ao};
write(filename, vec);
}
// Canonical writer function, including compression handling
void Writer::write(ostream& stream, const vector<const AnalysisObject*>& aos) {
std::unique_ptr<std::ostream> zos;
std::ostream* os = &stream;
// Wrap the stream if needed
if (_compress) {
#ifdef HAVE_LIBZ
// Doesn't work to always create zstr wrapper: have to only create if compressing :-/
// zstr::ostream zstream(stream);
// ostream& os = _compress ? zstream : stream;
os = new zstr::ostream(stream);
zos.reset(os);
#else
throw UserError("YODA was compiled without zlib support: can't write to a compressed stream");
#endif
}
// Write the data components
/// @todo Remove the head/body/foot distinction?
writeHead(*os);
bool first = true;
for (const AnalysisObject* aoptr : aos) {
try {
if (!first) *os << "\n"; //< blank line between items
writeBody(*os, aoptr);
first = false;
} catch (const LowStatsError& ex) {
/// @todo Why specifically LowStatsError?
std::cerr << "LowStatsError in writing AnalysisObject " << aoptr->title() << ":\n" << ex.what() << "\n";
}
}
writeFoot(*os);
*os << flush;
}
void Writer::writeBody(ostream& stream, const AnalysisObject* ao) {
if (!ao) throw WriteError("Attempting to write a null AnalysisObject*");
writeBody(stream, *ao);
}
void Writer::writeBody(ostream& stream, const AnalysisObject& ao) {
const string aotype = ao.type();
if (aotype == "Counter") {
writeCounter(stream, dynamic_cast<const Counter&>(ao));
} else if (aotype == "Histo1D") {
writeHisto1D(stream, dynamic_cast<const Histo1D&>(ao));
} else if (aotype == "Histo2D") {
writeHisto2D(stream, dynamic_cast<const Histo2D&>(ao));
} else if (aotype == "Profile1D") {
writeProfile1D(stream, dynamic_cast<const Profile1D&>(ao));
} else if (aotype == "Profile2D") {
writeProfile2D(stream, dynamic_cast<const Profile2D&>(ao));
} else if (aotype == "Scatter1D") {
- writeScatter1D(stream, dynamic_cast<const Scatter1D&>(ao));
+ writeScatter1D(stream, dynamic_cast<const Scatter1D&>(ao));
} else if (aotype == "Scatter2D") {
writeScatter2D(stream, dynamic_cast<const Scatter2D&>(ao));
} else if (aotype == "Scatter3D") {
writeScatter3D(stream, dynamic_cast<const Scatter3D&>(ao));
} else if (aotype[0] == '_') {
// Skip writing AO types with underscore prefixes (needed e.g. for Rivet wrappers)
// maybe write a comment line in the output
} else {
ostringstream oss;
oss << "Unrecognised analysis object type " << aotype << " in Writer::write";
throw Exception(oss.str());
}
}
}
diff --git a/src/WriterYODA.cc b/src/WriterYODA.cc
--- a/src/WriterYODA.cc
+++ b/src/WriterYODA.cc
@@ -1,308 +1,379 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2017 The YODA collaboration (see AUTHORS for details)
//
#include "YODA/WriterYODA.h"
#include <iostream>
#include <iomanip>
using namespace std;
namespace YODA {
/// Singleton creation function
Writer& WriterYODA::create() {
static WriterYODA _instance;
_instance.setPrecision(6);
return _instance;
}
// Format version:
// - V1/empty = make-plots annotations style
// - V2 = YAML annotations
static const int YODA_FORMAT_VERSION = 2;
// Version-formatting helper function
inline string _iotypestr(const string& baseiotype) {
ostringstream os;
os << "YODA_" << Utils::toUpper(baseiotype) << "_V" << YODA_FORMAT_VERSION;
return os.str();
}
void WriterYODA::_writeAnnotations(std::ostream& os, const AnalysisObject& ao) {
os << scientific << setprecision(_precision);
for (const string& a : ao.annotations()) {
if (a.empty()) continue;
/// @todo Write out floating point annotations as scientific notation
os << a << ": " << ao.annotation(a) << "\n";
}
os << "---\n";
}
void WriterYODA::writeCounter(std::ostream& os, const Counter& c) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("COUNTER") << " " << c.path() << "\n";
_writeAnnotations(os, c);
os << "# sumW\t sumW2\t numEntries\n";
os << c.sumW() << "\t" << c.sumW2() << "\t" << c.numEntries() << "\n";
os << "END " << _iotypestr("COUNTER") << "\n";
os.flags(oldflags);
}
void WriterYODA::writeHisto1D(std::ostream& os, const Histo1D& h) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("HISTO1D") << " " << h.path() << "\n";
_writeAnnotations(os, h);
try {
//if ( h.totalDbn().effNumEntries() > 0 ) {
os << "# Mean: " << h.xMean() << "\n";
os << "# Area: " << h.integral() << "\n";
} catch (LowStatsError& e) {
//
}
os << "# ID\t ID\t sumw\t sumw2\t sumwx\t sumwx2\t numEntries\n";
os << "Total \tTotal \t";
os << h.totalDbn().sumW() << "\t" << h.totalDbn().sumW2() << "\t";
os << h.totalDbn().sumWX() << "\t" << h.totalDbn().sumWX2() << "\t";
os << h.totalDbn().numEntries() << "\n";
os << "Underflow\tUnderflow\t";
os << h.underflow().sumW() << "\t" << h.underflow().sumW2() << "\t";
os << h.underflow().sumWX() << "\t" << h.underflow().sumWX2() << "\t";
os << h.underflow().numEntries() << "\n";
os << "Overflow\tOverflow\t";
os << h.overflow().sumW() << "\t" << h.overflow().sumW2() << "\t";
os << h.overflow().sumWX() << "\t" << h.overflow().sumWX2() << "\t";
os << h.overflow().numEntries() << "\n";
os << "# xlow\t xhigh\t sumw\t sumw2\t sumwx\t sumwx2\t numEntries\n";
for (const HistoBin1D& b : h.bins()) {
os << b.xMin() << "\t" << b.xMax() << "\t";
os << b.sumW() << "\t" << b.sumW2() << "\t";
os << b.sumWX() << "\t" << b.sumWX2() << "\t";
os << b.numEntries() << "\n";
}
os << "END " << _iotypestr("HISTO1D") << "\n";
os.flags(oldflags);
}
void WriterYODA::writeHisto2D(std::ostream& os, const Histo2D& h) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("HISTO2D") << " " << h.path() << "\n";
_writeAnnotations(os, h);
try {
//if ( h.totalDbn().numEntries() > 0 )
os << "# Mean: (" << h.xMean() << ", " << h.yMean() << ")\n";
os << "# Volume: " << h.integral() << "\n";
} catch (LowStatsError& e) {
//
}
os << "# ID\t ID\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwxy\t numEntries\n";
// Total distribution
const Dbn2D& td = h.totalDbn();
os << "Total \tTotal \t";
os << td.sumW() << "\t" << td.sumW2() << "\t";
os << td.sumWX() << "\t" << td.sumWX2() << "\t";
os << td.sumWY() << "\t" << td.sumWY2() << "\t";
os << td.sumWXY() << "\t";
os << td.numEntries() << "\n";
// Outflows
/// @todo Disabled for now, reinstate with a *full* set of outflow info to allow marginalisation
os << "# 2D outflow persistency not currently supported until API is stable\n";
// for (int ix = -1; ix <= 1; ++ix) {
// for (int iy = -1; iy <= 1; ++iy) {
// if (ix == 0 && iy == 0) continue;
// os << "Outflow\t" << ix << ":" << iy << "\t";
// const Dbn2D& d = h.outflow(ix, iy);
// os << d.sumW() << "\t" << d.sumW2() << "\t";
// os << d.sumWX() << "\t" << d.sumWX2() << "\t";
// os << d.sumWY() << "\t" << d.sumWY2() << "\t";
// os << d.sumWXY() << "\t";
// os << d.numEntries() << "\n";
// }
// }
// Bins
os << "# xlow\t xhigh\t ylow\t yhigh\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwxy\t numEntries\n";
for (const HistoBin2D& b : h.bins()) {
os << b.xMin() << "\t" << b.xMax() << "\t";
os << b.yMin() << "\t" << b.yMax() << "\t";
os << b.sumW() << "\t" << b.sumW2() << "\t";
os << b.sumWX() << "\t" << b.sumWX2() << "\t";
os << b.sumWY() << "\t" << b.sumWY2() << "\t";
os << b.sumWXY() << "\t";
os << b.numEntries() << "\n";
}
os << "END " << _iotypestr("HISTO2D") << "\n";
os.flags(oldflags);
}
void WriterYODA::writeProfile1D(std::ostream& os, const Profile1D& p) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("PROFILE1D") << " " << p.path() << "\n";
_writeAnnotations(os, p);
os << "# ID\t ID\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t numEntries\n";
os << "Total \tTotal \t";
os << p.totalDbn().sumW() << "\t" << p.totalDbn().sumW2() << "\t";
os << p.totalDbn().sumWX() << "\t" << p.totalDbn().sumWX2() << "\t";
os << p.totalDbn().sumWY() << "\t" << p.totalDbn().sumWY2() << "\t";
os << p.totalDbn().numEntries() << "\n";
os << "Underflow\tUnderflow\t";
os << p.underflow().sumW() << "\t" << p.underflow().sumW2() << "\t";
os << p.underflow().sumWX() << "\t" << p.underflow().sumWX2() << "\t";
os << p.underflow().sumWY() << "\t" << p.underflow().sumWY2() << "\t";
os << p.underflow().numEntries() << "\n";
os << "Overflow\tOverflow\t";
os << p.overflow().sumW() << "\t" << p.overflow().sumW2() << "\t";
os << p.overflow().sumWX() << "\t" << p.overflow().sumWX2() << "\t";
os << p.overflow().sumWY() << "\t" << p.overflow().sumWY2() << "\t";
os << p.overflow().numEntries() << "\n";
os << "# xlow\t xhigh\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t numEntries\n";
for (const ProfileBin1D& b : p.bins()) {
os << b.xMin() << "\t" << b.xMax() << "\t";
os << b.sumW() << "\t" << b.sumW2() << "\t";
os << b.sumWX() << "\t" << b.sumWX2() << "\t";
os << b.sumWY() << "\t" << b.sumWY2() << "\t";
os << b.numEntries() << "\n";
}
os << "END " << _iotypestr("PROFILE1D") << "\n";
os.flags(oldflags);
}
void WriterYODA::writeProfile2D(std::ostream& os, const Profile2D& p) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("PROFILE2D") << " " << p.path() << "\n";
_writeAnnotations(os, p);
os << "# sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwz\t sumwz2\t sumwxy\t numEntries\n";
// Total distribution
const Dbn3D& td = p.totalDbn();
os << "Total \tTotal \t";
os << td.sumW() << "\t" << td.sumW2() << "\t";
os << td.sumWX() << "\t" << td.sumWX2() << "\t";
os << td.sumWY() << "\t" << td.sumWY2() << "\t";
os << td.sumWZ() << "\t" << td.sumWZ2() << "\t";
os << td.sumWXY() << "\t"; // << td.sumWXZ() << "\t" << td.sumWYZ() << "\t";
os << td.numEntries() << "\n";
// Outflows
/// @todo Disabled for now, reinstate with a *full* set of outflow info to allow marginalisation
os << "# 2D outflow persistency not currently supported until API is stable\n";
// for (int ix = -1; ix <= 1; ++ix) {
// for (int iy = -1; iy <= 1; ++iy) {
// if (ix == 0 && iy == 0) continue;
// os << "Outflow\t" << ix << ":" << iy << "\t";
// const Dbn3D& d = p.outflow(ix, iy);
// os << d.sumW() << "\t" << d.sumW2() << "\t";
// os << d.sumWX() << "\t" << d.sumWX2() << "\t";
// os << d.sumWY() << "\t" << d.sumWY2() << "\t";
// os << d.sumWZ() << "\t" << d.sumWZ2() << "\t";
// os << d.sumWXY() << "\t"; // << d.sumWXZ() << "\t" << d.sumWYZ() << "\t";
// os << d.numEntries() << "\n";
// }
// }
// Bins
os << "# xlow\t xhigh\t ylow\t yhigh\t sumw\t sumw2\t sumwx\t sumwx2\t sumwy\t sumwy2\t sumwz\t sumwz2\t sumwxy\t numEntries\n";
for (const ProfileBin2D& b : p.bins()) {
os << b.xMin() << "\t" << b.xMax() << "\t";
os << b.yMin() << "\t" << b.yMax() << "\t";
os << b.sumW() << "\t" << b.sumW2() << "\t";
os << b.sumWX() << "\t" << b.sumWX2() << "\t";
os << b.sumWY() << "\t" << b.sumWY2() << "\t";
os << b.sumWZ() << "\t" << b.sumWZ2() << "\t";
os << b.sumWXY() << "\t"; // << b.sumWXZ() << "\t" << b.sumWYZ() << "\t";
os << b.numEntries() << "\n";
}
os << "END " << _iotypestr("PROFILE2D") << "\n";
os.flags(oldflags);
}
void WriterYODA::writeScatter1D(std::ostream& os, const Scatter1D& s) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("SCATTER1D") << " " << s.path() << "\n";
+ //first write the Variations, a dummy annotation which
+ //contains the additional columns which will be written out
+ //for sytematic variations
+ YAML::Emitter out;
+ out << YAML::Flow ;
+ out << s.variations();
+ os << "Variations" << ": " << out.c_str() << "\n";
+ // then write the regular annotations
_writeAnnotations(os, s);
+
+ std::vector<std::string> variations= s.variations();
- std::vector<std::string> variations= s.variations();
+ //write headers
+ std::string headers="# xval\t ";
+ for (const auto &source : variations){
+ headers+=" xerr-"+source+"\t xerr-"+source+"\t";
+ }
+ os << headers << "\n";
+
+ //write points
for (const Point1D& pt : s.points()) {
// fill central value
os << pt.x();
// fill errors for variations. The first should always be "" which is nominal.
// Assumes here that all points in the Scatter have the same
// variations... if not a range error will get thrown from
// the point when the user tries to access a variation it
// doesn't have... @todo maybe better way to do this?
for (const auto &source : variations){
os << "\t" << pt.xErrMinus(source) << "\t" << pt.xErrPlus(source) ;
}
os << "\n";
}
os << "END " << _iotypestr("SCATTER1D") << "\n";
os << flush;
os.flags(oldflags);
}
void WriterYODA::writeScatter2D(std::ostream& os, const Scatter2D& s) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("SCATTER2D") << " " << s.path() << "\n";
+ //first write the Variations, a dummy annotation which
+ //contains the additional columns which will be written out
+ //for sytematic variations
+ YAML::Emitter out;
+ out << YAML::Flow ;
+ out << s.variations();
+ os << "Variations" << ": " << out.c_str() << "\n";
+ // then write the regular annotations
_writeAnnotations(os, s);
+
+ std::vector<std::string> variations= s.variations();
+ //write headers
/// @todo Change ordering to {vals} {errs} {errs} ...
- os << "# xval\t xerr-\t xerr+\t yval\t yerr-\t yerr+\n";
+ std::string headers="# xval\t xerr-\t xerr+\t yval\t";
+ for (const auto &source : variations){
+ headers+=" yerr-"+source+"\t yerr-"+source+"\t";
+ }
+ os << headers << "\n";
+
+ //write points
for (const Point2D& pt : s.points()) {
/// @todo Change ordering to {vals} {errs} {errs} ...
+ // fill central value
os << pt.x() << "\t" << pt.xErrMinus() << "\t" << pt.xErrPlus() << "\t";
- os << pt.y() << "\t" << pt.yErrMinus() << "\t" << pt.yErrPlus() << "\n";
+ os << pt.y();
+ // fill errors for variations. The first should always be "" which is nominal.
+ // Assumes here that all points in the Scatter have the same
+ // variations... if not a range error will get thrown from
+ // the point when the user tries to access a variation it
+ // doesn't have... @todo maybe better way to do this?
+ for (const auto &source : variations){
+ os << "\t" << pt.yErrMinus(source) << "\t" << pt.yErrPlus(source) ;
+ }
+ os << "\n";
}
os << "END " << _iotypestr("SCATTER2D") << "\n";
os << flush;
os.flags(oldflags);
}
void WriterYODA::writeScatter3D(std::ostream& os, const Scatter3D& s) {
ios_base::fmtflags oldflags = os.flags();
os << scientific << showpoint << setprecision(_precision);
os << "BEGIN " << _iotypestr("SCATTER3D") << " " << s.path() << "\n";
+ //first write the Variations, a dummy annotation which
+ //contains the additional columns which will be written out
+ //for sytematic variations
+ YAML::Emitter out;
+ out << YAML::Flow ;
+ out << s.variations();
+ os << "Variations" << ": " << out.c_str() << "\n";
+ // then write the regular annotations
_writeAnnotations(os, s);
+
+ std::vector<std::string> variations= s.variations();
+ //write headers
/// @todo Change ordering to {vals} {errs} {errs} ...
- os << "# xval\t xerr-\t xerr+\t yval\t yerr-\t yerr+\t zval\t zerr-\t zerr+\n";
+ std::string headers="# xval\t xerr-\t xerr+\t yval\t yerr-\t yerr+\t zval\t ";
+ for (const auto &source : variations){
+ headers+=" zerr-"+source+"\t zerr-"+source+"\t";
+ }
+ os << headers << "\n";
+
+ //write points
for (const Point3D& pt : s.points()) {
/// @todo Change ordering to {vals} {errs} {errs} ...
+ // fill central value
os << pt.x() << "\t" << pt.xErrMinus() << "\t" << pt.xErrPlus() << "\t";
os << pt.y() << "\t" << pt.yErrMinus() << "\t" << pt.yErrPlus() << "\t";
- os << pt.z() << "\t" << pt.zErrMinus() << "\t" << pt.zErrPlus() << "\n";
+ os << pt.z();
+ // fill errors for variations. The first should always be "" which is nominal.
+ // Assumes here that all points in the Scatter have the same
+ // variations... if not a range error will get thrown from
+ // the point when the user tries to access a variation it
+ // doesn't have... @todo maybe better way to do this?
+ for (const auto &source : variations){
+ os << "\t" << pt.zErrMinus(source) << "\t" << pt.zErrPlus(source) ;
+ }
+ os << "\n";
}
os << "END " << _iotypestr("SCATTER3D") << "\n";
os << flush;
os.flags(oldflags);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 4:26 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3802543
Default Alt Text
(288 KB)

Event Timeline