[yoda-svn] r492 - in trunk: . include/YODA src

blackhole at projects.hepforge.org blackhole at projects.hepforge.org
Thu 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