|
[yoda-svn] r492 - in trunk: . include/YODA srcblackhole at projects.hepforge.org blackhole at projects.hepforge.orgThu Jul 5 02:10:42 BST 2012
Author: buckley Date: Thu Jul 5 02:10:42 2012 New Revision: 492 Log: Adding outflows to Axis2D and derived histo/profile classes Modified: trunk/TODO trunk/include/YODA/Axis2D.h trunk/include/YODA/Histo2D.h trunk/src/Histo1D.cc trunk/src/Histo2D.cc trunk/src/Profile1D.cc trunk/src/Profile2D.cc Modified: trunk/TODO ============================================================================== --- trunk/TODO Thu Jul 5 00:55:29 2012 (r491) +++ trunk/TODO Thu Jul 5 02:10:42 2012 (r492) @@ -4,26 +4,18 @@ NOW * Add Axis1D/2D _locked member -> true on first fill. (AB) + Done for Axis1D: is it a good idea? * Add nice constructor behaviour and docstrings to the Scatter2D Python interface. (AB) -* Add Axis2D block outflows and outflow(ix, iy) with ix, oy in [-1, 0, 1]. (AB) - - * Remove nasty Cython shims (DM) +* Complete basic Histo2D and Profile2D functionality. (AB) -* Complete basid Histo2D and Profile2D functionality. (AB) - -* Add a merge() method in Bin2D. Add a constructor that takes Dbns. - -* Make Python interface test scripts (AB) +* Make Python interface test scripts (DM) * Add copy assignment to Point/Scatter3D and Dbn1D/2D. (AB) -* Rebinning: global rebinning of Axis2D -> Histo2D by integer factor(s) -- - different factors in x and y directions. - * Improve tests Makefile setup to work out the path to the Python build dir. (AB) @@ -31,6 +23,11 @@ NEXT +* Add a merge() method in Bin2D. Add a constructor that takes Dbns. + +* Rebinning: global rebinning of Axis2D -> Histo2D by integer factor(s) -- + different factors in x and y directions. + * Automatically determine input and output formats (= readers/writers) from file extn. * Test that a y-binned Histo2D has the same per-y-column stats as an Modified: trunk/include/YODA/Axis2D.h ============================================================================== --- trunk/include/YODA/Axis2D.h Thu Jul 5 00:55:29 2012 (r491) +++ trunk/include/YODA/Axis2D.h Thu Jul 5 02:10:42 2012 (r492) @@ -38,6 +38,9 @@ /// The internal bin container type. Not used for searching. typedef typename std::vector<Bin> Bins; + /// The internal container type for outflow distributions. + typedef std::map<size_t, DBN> Outflows; + /// @brief Type used to implement a search table of low bin edges (in 2D) mapped to bin indices. /// An index of -1 indicates a gap interval, without a corresponding bin. typedef std::map<double, long int> SubBinHash; @@ -75,22 +78,18 @@ } - /// @todo TODO - // /// State-setting constructor for persistency - // Axis2D(const Bins& bins, - // const std::vector<std::vector<DBN> >& outflows, - // const DBN& totalDbn) - // { - // } - + /// State-setting constructor for persistency + Axis2D(const Bins& bins, + const DBN& totalDbn, + const Outflows& outflows) + : _bins(bins), _dbn(totalDbn), _outflows(outflows) + { + if (_outflows.size() != 8) { + throw Exception("Axis2D outflow containers must have exactly 8 elements"); + } + _updateAxis(); + } - // /// Copy constructor - // /// @todo Needed? - // Axis2D(const Axis2D& a) { - // _bins = a._bins; - // _dbn = a._dbn; - // _outflows = a._outflows; - // } //@} @@ -104,10 +103,8 @@ /// bin, which is then constructed and added as usual. void addBin(double lowX, double lowY, double highX, double highY) { /// @todo TODO - // std::vector<Segment> coords; - // coords.push_back(std::make_pair(std::make_pair(lowX, lowY), - // std::make_pair(highX, highY))); - // addBin(coords); + + /// @todo Check for overlaps } //@} @@ -262,24 +259,32 @@ if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range"); return _binhash.begin()->first; } + /// A alias for lowEdgeX() + double xMin() const { return lowEdgeX();} /// Get the value of the highest x-edge on the axis const double highEdgeX() const { if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range"); return (--_binhash.end())->first; } + /// Alias for highEdgeX() + double xMax() const { return highEdgeX();} /// Get the value of the lowest y-edge on the axis const double lowEdgeY() const { if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range"); return _binhash.begin()->second.begin()->first; } + /// A alias for lowEdgeY() + double yMin() const { return lowEdgeY();} /// Get the value of the highest y-edge on the axis const double highEdgeY() const { if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range"); return (--_binhash.begin()->second.end())->first; } + /// Alias for highEdgeY() + double yMax() const { return highEdgeY();} /// Get the bins (non-const version) @@ -293,16 +298,26 @@ } - /// Get the outflows (non-const version) - /// @todo Explain the index structure - std::vector<std::vector<DBN> >& outflows() { - return _outflows; + /// @brief Get an outflow (non-const version) + /// + /// Two indices are used, for x and y: -1 = underflow, 0 = in-range, and +1 = overflow. + /// (0,0) is not a valid overflow index pair, since it is in range for both x and y. + DBN& outflow(size_t ix, size_t iy) { + if (ix == 0 && iy == 0) throw UserError("(0,0) is not a valid Axis2D overflow index"); + if (abs(ix) > 1 || abs(iy) > 1) throw UserError("Axis2D overflow indices are -1, 0, 1"); + size_t realindex = 3*(ix+1) + (iy+1); + return _outflows[realindex]; } - /// Get the outflows (const version) - /// @todo Explain the index structure - const std::vector<std::vector<DBN> >& outflows() const { - return _outflows; + /// @brief Get an outflow (const version) + /// + /// Two indices are used, for x and y: -1 = underflow, 0 = in-range, and +1 = overflow. + /// (0,0) is not a valid overflow index pair, since it is in range for both x and y. + const DBN& outflow(size_t ix, size_t iy) const { + if (ix == 0 && iy == 0) throw UserError("(0,0) is not a valid Axis2D overflow index"); + if (abs(ix) > 1 || abs(iy) > 1) throw UserError("Axis2D overflow indices are -1, 0, 1"); + size_t realindex = 3*(ix+1) + (iy+1); + return _outflows.find(realindex)->second; } @@ -424,15 +439,14 @@ bin.scaleXY(scaleX, scaleY); } _dbn.scaleXY(scaleX, scaleY); - - /// @todo Outflows - // for (size_t i = 0; i < _outflows.size(); ++i) { - // for (size_t j =0; j < _outflows[i].size(); ++j) { - // _outflows[i][j].scaleXY(scaleX, scaleY); - // } - // } - - /// @todo Rehash + // Outflows + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + _outflows[3*i+j].scaleXY(scaleX, scaleY);; + } + } + // Rehash + _updateAxis(); } @@ -442,13 +456,12 @@ bin.scaleW(scalefactor); } _dbn.scaleW(scalefactor); - - /// @todo Outflows - // for (size_t i = 0; i < _outflows.size(); ++i) { - // for (size_t j = 0; j < _outflows[i].size(); ++j) { - // _outflows[i][j].scaleW(scalefactor); - // } - // } + // Outflows + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + _outflows[3*i+j].scaleW(scalefactor); + } + } } //@} @@ -624,14 +637,6 @@ // } - /// 2D outflow filler - /// The function checks which outflow the coordinates are in - /// and fills the right one. - void _fillOutflows(double x, double y, double weight) { - /// @todo TODO - } - - private: /// @name Data structures @@ -643,15 +648,8 @@ /// Total distribution DBN _dbn; - /// Outflow distributions - /// - /// This contains eight subvectors, each being 1/8 of an outflow - /// and numbered clockwise from top left corner. The 'corner' outflows - /// contain just one DBN each. The ones between them contain as many DBNs - /// as the number of columns/rows in the respective part of the grid. - /// - /// @todo Replace with a more specialised class or a fixed array? - std::vector<std::vector<DBN> > _outflows; + /// Outflow distributions, indexed clockwise from top + Outflows _outflows; /// Cached bin edges for searching BinHash _binhash; Modified: trunk/include/YODA/Histo2D.h ============================================================================== --- trunk/include/YODA/Histo2D.h Thu Jul 5 00:55:29 2012 (r491) +++ trunk/include/YODA/Histo2D.h Thu Jul 5 02:10:42 2012 (r492) @@ -267,14 +267,20 @@ } - /// Access outflows (non-const) - std::vector<std::vector<Dbn2D> >& outflows() { - return _axis.outflows(); + /// @brief Access an outflow (non-const) + /// + /// Two indices are used, for x and y: -1 = underflow, 0 = in-range, and +1 = overflow. + /// (0,0) is not a valid overflow index pair, since it is in range for both x and y. + Dbn2D& outflow(size_t ix, size_t iy) { + return _axis.outflow(ix, iy); } - /// Access outflows (const) - const std::vector<std::vector<Dbn2D> >& outflows() const { - return _axis.outflows(); + /// @brief Access an outflow (const) + /// + /// Two indices are used, for x and y: -1 = underflow, 0 = in-range, and +1 = overflow. + /// (0,0) is not a valid overflow index pair, since it is in range for both x and y. + const Dbn2D& outflow(size_t ix, size_t iy) const { + return _axis.outflow(ix, iy); } //@} Modified: trunk/src/Histo1D.cc ============================================================================== --- trunk/src/Histo1D.cc Thu Jul 5 00:55:29 2012 (r491) +++ trunk/src/Histo1D.cc Thu Jul 5 02:10:42 2012 (r492) @@ -13,18 +13,19 @@ namespace YODA { - // typedef vector<HistoBin1D> Bins; void Histo1D::fill(double x, double weight) { - // Fill the underflow and overflow nicely + // Fill the overall distribution _axis.totalDbn().fill(x, weight); - if (x < _axis.xMin()) { _axis.underflow().fill(x, weight); return; } - if (x >= _axis.xMax()) { _axis.overflow().fill(x, weight); return; } - // Fill the normal bins + // Fill the bins and overflows try { HistoBin1D& b = binByCoord(x); b.fill(x, weight); - } catch (const RangeError& re) {} + } catch (const RangeError& re) { + if (x < _axis.xMin()) _axis.underflow().fill(x, weight); + else if (x >= _axis.xMax()) _axis.overflow().fill(x, weight); + } + // Lock the axis now that a fill has happened _axis._setLock(true); } Modified: trunk/src/Histo2D.cc ============================================================================== --- trunk/src/Histo2D.cc Thu Jul 5 00:55:29 2012 (r491) +++ trunk/src/Histo2D.cc Thu Jul 5 02:10:42 2012 (r492) @@ -11,6 +11,7 @@ namespace YODA { + /// @todo Move to header? Histo2D::Histo2D(const Histo2D& h, const std::string& path) : AnalysisObject("Histo2D", (path.size() == 0) ? h.path() : path, h, h.title()), _axis(h._axis) @@ -18,8 +19,20 @@ void Histo2D::fill(double x, double y, double weight) { - /// @todo TODO, incl. overflows - // return _axis.fill(x, y, weight); + // Fill the overall distribution + _axis.totalDbn().fill(x, y, weight); + // Fill the bins and overflows + try { + HistoBin2D& b = binByCoord(x, y); + b.fill(x, y, weight); + } catch (const RangeError& re) { + size_t ix(0), iy(0); + if (x < _axis.xMin()) ix = -1; else if (x >= _axis.xMax()) ix = 1; + if (y < _axis.yMin()) iy = -1; else if (y >= _axis.yMax()) iy = 1; + _axis.outflow(ix, iy).fill(x, y, weight); + } + // // Lock the axis now that a fill has happened + // _axis._setLock(true); } Modified: trunk/src/Profile1D.cc ============================================================================== --- trunk/src/Profile1D.cc Thu Jul 5 00:55:29 2012 (r491) +++ trunk/src/Profile1D.cc Thu Jul 5 02:10:42 2012 (r492) @@ -8,20 +8,23 @@ #include "YODA/Scatter2D.h" #include <cmath> +using namespace std; namespace YODA { void Profile1D::fill(double x, double y, double weight) { - // Fill the underflow and overflow nicely + // Fill the overall distribution _axis.totalDbn().fill(x, y, weight); - if (x < _axis.xMin()) { _axis.underflow().fill(x, y, weight); return; } - if (x >= _axis.xMax()) { _axis.overflow().fill(x, y, weight); return; } - // Fill the normal bins + // Fill the bins and overflows try { ProfileBin1D& b = binByCoord(x); b.fill(x, y, weight); - } catch (const RangeError& re) {} + } catch (const RangeError& re) { + if (x < _axis.xMin()) _axis.underflow().fill(x, y, weight); + else if (x >= _axis.xMax()) _axis.overflow().fill(x, y, weight); + } + // Lock the axis now that a fill has happened _axis._setLock(true); } Modified: trunk/src/Profile2D.cc ============================================================================== --- trunk/src/Profile2D.cc Thu Jul 5 00:55:29 2012 (r491) +++ trunk/src/Profile2D.cc Thu Jul 5 02:10:42 2012 (r492) @@ -2,12 +2,29 @@ #include "YODA/Scatter3D.h" #include "YODA/Histo2D.h" -namespace YODA { - +using namespace std; + +namespace YODA { + + void Profile2D::fill(double x, double y, double z, double weight) { - _axis.fill(x, y, z, weight); + // Fill the overall distribution + _axis.totalDbn().fill(x, y, z, weight); + // Fill the bins and overflows + try { + HistoBin2D& b = binByCoord(x); + b.fill(x, y, z, weight); + } catch (const RangeError& re) { + size_t ix(0), iy(0); + if (x < _axis.xMin()) ix = -1 else if (x >= _axis.xMax()) ix = 1; + if (y < _axis.yMin()) iy = -1 else if (y >= _axis.yMax()) iy = 1; + _axis.outflow(ix, iy).fill(x, y, z, weight); + } + // // Lock the axis now that a fill has happened + // _axis._setLock(true); } + double Profile2D::sumW(bool includeoverflows) const { if (includeoverflows) return _axis.totalDbn().sumW2(); double sumw = 0; @@ -17,6 +34,7 @@ return sumw; } + double Profile2D::sumW2(bool includeoverflows) const { if (includeoverflows) return _axis.totalDbn().sumW2(); double sumw = 0; @@ -26,6 +44,7 @@ return sumw; } + /// A copy constructor with optional new path Profile2D::Profile2D(const Profile2D& p, const std::string& path) : AnalysisObject("Profile2D", p.path(), p, p.title()) @@ -33,6 +52,7 @@ _axis = p._axis; } + /// Constructor from a Scatter3D's binning, with optional new path Profile2D::Profile2D(const Scatter3D& s, const std::string& path) : AnalysisObject("Profile2D", (path.size() == 0) ? s.path() : path, s, s.title()) @@ -44,6 +64,7 @@ _axis = Profile2DAxis(bins); } + /// Constructor from a Histo2D's binning, with optional new path Profile2D::Profile2D(const Histo2D& h, const std::string& path) : AnalysisObject("Profile2D", (path.size() == 0) ? h.path() : path, h, h.title()) @@ -55,12 +76,13 @@ _axis = Profile2DAxis(bins); } + /// Divide two profile histograms /// Note: I have remove the const requirement as it makes the program compile, /// was it right to do? Scatter3D divide(Profile2D& numer, Profile2D& denom) { /// @todo Make this check work - if(numer != denom) throw "It is impossible to add two incompatibly binned profile histograms!"; + if (numer != denom) throw "It is impossible to add two incompatibly binned profile histograms!"; Scatter3D tmp; for (size_t i = 0; i < numer.numBins(); ++i) { const ProfileBin2D& b1 = numer.bin(i); @@ -87,5 +109,5 @@ assert(tmp.numPoints() == numer.numBins()); return tmp; } - + }
More information about the yoda-svn mailing list |