[yoda-svn] r250 - in trunk: include/YODA src tests

blackhole at projects.hepforge.org blackhole at projects.hepforge.org
Tue Aug 16 12:20:14 BST 2011


Author: mkawalec
Date: Tue Aug 16 12:20:14 2011
New Revision: 250

Log:
Refactored Bin2D to only hold a reasonable amount of points. Fixed bin merger algorithm. Fixed some minor bugs. Notice the 3-fold speed improvement resulting from smaller bins being moved around the memory.

Modified:
   trunk/include/YODA/Axis2D.h
   trunk/include/YODA/Bin2D.h
   trunk/include/YODA/Histo2D.h
   trunk/src/Bin2D.cc
   trunk/tests/TestHisto2D.cc

Modified: trunk/include/YODA/Axis2D.h
==============================================================================
--- trunk/include/YODA/Axis2D.h	Tue Aug 16 10:36:38 2011	(r249)
+++ trunk/include/YODA/Axis2D.h	Tue Aug 16 12:20:14 2011	(r250)
@@ -8,6 +8,7 @@
 #include "YODA/Utils/cachedvector.h"
 #include "YODA/Utils/MathUtils.h"
 #include "YODA/Dbn2D.h"
+
 #include <string>
 #include <cassert>
 #include <cmath>
@@ -143,8 +144,6 @@
               {
                 temp += bin(_binHashSparse.first[y].second[x].first);
                 bin(_binHashSparse.first[y].second[x].first).isReal = false;
-
-                /// @todo The bin that was just added must be changed to virtual!
               }
             }
           }
@@ -162,7 +161,7 @@
         /// inner subcaches and half of this amount in the outer (grid boundary)
         /// subcaches. This makes isGriddy() a very, very fast function.
         /// @todo Is the name appropriate?
-        int isGriddy() const
+        bool isGriddy() const
         {
 
             /// Check if the number of edges parallel to X axis
@@ -171,11 +170,11 @@
             for(unsigned int i=1; i < _binHashSparse.first.size(); i++) {
                 if(i == _binHashSparse.first.size() - 1) {
                     if(_binHashSparse.first[i].second.size() != sizeX) {
-                        return -1;
+                        return false;
                     }
                 }
                 else if(_binHashSparse.first[i].second.size() != 2*sizeX) {
-                    return -1;
+                    return false;
                 }
             }
 
@@ -184,14 +183,14 @@
             for(unsigned int i=1; i < _binHashSparse.second.size(); i++) {
                 if(i!= _binHashSparse.second.size() - 1) {
                     if(2*sizeY != _binHashSparse.second[i].second.size()) {
-                        return -1;
+                        return false;
                     }
                 }
                 else if(_binHashSparse.second[i].second.size() != sizeY) return -1;
             }
 
             /// If everything is proper, announce it.
-            return 0;
+            return true;
         }
 
         /// Return a total number of bins in a Histo
@@ -755,21 +754,22 @@
                 if(_bins[i].yMin() < lowEdgeY) lowEdgeY = _bins[i].yMin();
                 if(_bins[i].yMax() > highEdgeY) highEdgeY = _bins[i].yMax();
             }
-
+            
+            cout << "LowX: " << lowEdgeX << " LowY: " << lowEdgeY << " HighX: " << highEdgeX << " HighY: " << highEdgeY << endl;
             _lowEdgeX = lowEdgeX;
             _highEdgeX = highEdgeX;
             _lowEdgeY = lowEdgeY;
             _highEdgeY = highEdgeY;
         }
 
-        /// @brief BIn index finder
+        /// @brief Bin index finder
         /// Looks through all the bins to see which
         /// one contains the point of interest.
         int _findBinIndex(double coordX, double coordY) const 
         {
            for(size_t i=0; i < _bins.size(); i++) {
-               if(_bins[i].lowEdgeX() <= coordX && _bins[i].highEdgeX()  >= coordX && 
-               _bins[i].lowEdgeY() <= coordY && _bins[i].highEdgeY() >= coordY &&
+               if(_bins[i].xMin() <= coordX && _bins[i].xMax()  >= coordX && 
+               _bins[i].yMin() <= coordY && _bins[i].yMax() >= coordY &&
                _bins[i].isReal) return i;
            }
         return -1;

Modified: trunk/include/YODA/Bin2D.h
==============================================================================
--- trunk/include/YODA/Bin2D.h	Tue Aug 16 10:36:38 2011	(r249)
+++ trunk/include/YODA/Bin2D.h	Tue Aug 16 12:20:14 2011	(r250)
@@ -49,7 +49,15 @@
     /// @name Modifiers
     //@{
 
-    const vector<Segment> edges() const { return _edges;}
+    const vector<Segment> edges() const { 
+      vector<Segment> ret;
+      ret.push_back(make_pair(make_pair(xMin(), yMin()), make_pair(xMin(), yMax())));
+      ret.push_back(make_pair(make_pair(xMin(), yMax()), make_pair(xMax(), yMax())));
+      ret.push_back(make_pair(make_pair(xMax(), yMin()), make_pair(xMax(), yMax())));
+      ret.push_back(make_pair(make_pair(xMin(), yMin()), make_pair(xMax(), yMin())));
+
+      return ret;
+    }
 
     /// Reset all bin data
     virtual void reset() {
@@ -67,14 +75,14 @@
 
     /// Get the low x edge of the bin.
     double lowEdgeX() const {
-      return _edges[0].first.first;
+      return _edges.first.first;
     }
     /// Synonym for lowEdgeX()
     double xMin() const { return lowEdgeX(); }
 
     /// Get the low y edge of the bin.
     double lowEdgeY() const {
-      return _edges[0].first.second;
+      return _edges.first.second;
     }
 
     /// Synonym for lowEdgeY()
@@ -87,26 +95,26 @@
     //@{
     /// Get the high x edge of the bin.
     double highEdgeX() const {
-      return _edges[1].second.first;
+      return _edges.second.first;
     }
     /// Synonym for highEdgeX()
     double xMax() const { return highEdgeX(); }
 
     /// Get the high y edge of the bin.
     double highEdgeY() const {
-      return _edges[1].second.second;
+      return _edges.second.second;
     }
     /// Synonym for highEdgeY()
     double yMax() const { return highEdgeY(); }
 
     /// Width of the bin in y
     double widthY() const {
-      return _edges[0].second.second - _edges[0].first.second;
+      return yMax() - yMin();
     }
 
     /// Width of the bin in x
     double widthX() const {
-      return _edges[1].second.first - _edges[0].first.first;
+      return _edges.second.first - _edges.first.first;
     }
     //@}
 
@@ -219,15 +227,15 @@
 
     Bin2D& subtract(const Bin2D& b);
 
-    std::vector<Segment> _edges;
+    Segment _edges;
     Dbn2D _dbn;
         
     /// Boundaries setter
     void _setBounds(double xMin, double yMin, double xMax, double yMax) {
-      _edges[0] = make_pair(make_pair(xMin, yMin), make_pair(xMin, yMax));
-      _edges[1] = make_pair(make_pair(xMin, yMax), make_pair(xMax, yMax));
-      _edges[2] = make_pair(make_pair(xMax, yMin), make_pair(xMax, yMax));
-      _edges[3] = make_pair(make_pair(xMin, yMin), make_pair(xMax, yMin));
+      _edges.first.first = xMin;
+      _edges.first.second = yMin;
+      _edges.second.first = xMax;
+      _edges.second.second = yMax;
     }
 
   };

Modified: trunk/include/YODA/Histo2D.h
==============================================================================
--- trunk/include/YODA/Histo2D.h	Tue Aug 16 10:36:38 2011	(r249)
+++ trunk/include/YODA/Histo2D.h	Tue Aug 16 12:20:14 2011	(r250)
@@ -290,6 +290,8 @@
     /// @todo Need to check that there is a continuous row for this y
     /// @todo Change the name!
     Histo1D cutterX(double atY, const std::string& path="", const std::string& title="") {
+      if(!_axis.isGriddy()) throw GridError("I cannot cut a Histo2D that is not a grid!");
+
       if (atY < lowEdgeY() || atY > highEdgeY()) throw RangeError("Y is outside the grid");
       vector<HistoBin1D> tempBins;
       
@@ -298,12 +300,11 @@
       const Dbn1D dbn(first.numEntries(), first.sumW(), first.sumW2(), first.sumWX(), first.sumWX2());
       tempBins.push_back(HistoBin1D(first.lowEdgeX(), first.highEdgeX(), dbn));
 
-      for (double i = first.xMax() + first.widthX()/2; i < highEdgeX(); i += first.widthX()) {
+      for (double i = first.midpoint().first + first.widthX(); i < highEdgeX(); i += first.widthX()) {
         const HistoBin2D& b2 = binByCoord(i, atY);
         const Dbn1D dbn2(b2.numEntries(), b2.sumW(), b2.sumW2(), b2.sumWX(), b2.sumWX2());
         tempBins.push_back(HistoBin1D(b2.lowEdgeX(), b2.highEdgeX(), dbn2));
       }
-
       /// @todo Think about the total, underflow and overflow distributions
       /// @todo Create total dbn from input bins
       return Histo1D(tempBins, Dbn1D(), Dbn1D(), Dbn1D(), path, title);
@@ -317,6 +318,8 @@
     /// @todo Need to check that there is a continuous column for this x
     /// @todo Change the name!
     Histo1D cutterY(double atX, const std::string& path="", const std::string& title="") {
+      if(!_axis.isGriddy()) throw GridError("I cannot cut a Histo2D that is not a grid!");
+
       if (atX < lowEdgeX() || atX > highEdgeX()) throw RangeError("X is outside the grid");
       vector<HistoBin1D> tempBins;
       
@@ -325,7 +328,7 @@
       const Dbn1D dbn(first.numEntries(), first.sumW(), first.sumW2(), first.sumWX(), first.sumWX2());
       tempBins.push_back(HistoBin1D(first.lowEdgeY(), first.highEdgeY(), dbn));
 
-      for (double i = first.yMax() + first.widthY()/2; i < highEdgeY(); i += first.widthY()) {
+      for (double i = first.midpoint().second + first.widthY(); i < highEdgeY(); i += first.widthY()) {
         const HistoBin2D& b2 = binByCoord(atX, i);
         const Dbn1D dbn2(b2.numEntries(), b2.sumW(), b2.sumW2(), b2.sumWX(), b2.sumWX2());
         tempBins.push_back(HistoBin1D(b2.lowEdgeY(), b2.highEdgeY(), dbn2));

Modified: trunk/src/Bin2D.cc
==============================================================================
--- trunk/src/Bin2D.cc	Tue Aug 16 10:36:38 2011	(r249)
+++ trunk/src/Bin2D.cc	Tue Aug 16 12:20:14 2011	(r250)
@@ -1,5 +1,6 @@
 #include "YODA/Bin2D.h"
 #include "YODA/HistoBin1D.h"
+#include "YODA/Exceptions.h"
 
 #include <cassert>
 #include <cmath>
@@ -11,51 +12,41 @@
 namespace YODA {
 
   Bin2D::Bin2D(double lowedgeX, double lowedgeY, double highedgeX, double highedgeY) {
-    assert(lowedgeX <= highedgeX && lowedgeY <= highedgeY);
+    if(lowedgeX > highedgeX || lowedgeY > highedgeY) throw RangeError("The bins are wrongly defined!"); 
     
-    /// @todo Why store with so much redundancy?
-    pair<pair<double,double>, pair<double,double> > edge1 =
-      make_pair(make_pair(lowedgeX, lowedgeY), make_pair(lowedgeX, highedgeY));
-    pair<pair<double,double>, pair<double,double> > edge2 =
-      make_pair(make_pair(lowedgeX, highedgeY), make_pair(highedgeX, highedgeY));
-    pair<pair<double,double>, pair<double,double> > edge3 =
-      make_pair(make_pair(highedgeX, lowedgeY), make_pair(highedgeX, highedgeY));
-    pair<pair<double,double>, pair<double,double> > edge4 =
-      make_pair(make_pair(lowedgeX, lowedgeY), make_pair(highedgeX, lowedgeY));
-
-    _edges.push_back(edge1);
-    _edges.push_back(edge2);
-    _edges.push_back(edge3);
-    _edges.push_back(edge4);
+    _edges.first.first = lowedgeX;
+    _edges.first.second = lowedgeY;
+    _edges.second.first = highedgeX;
+    _edges.second.second = highedgeY;
 
     isReal = true;
   }
 
   Bin2D::Bin2D(std::vector<std::pair<std::pair<double,double>,
                std::pair<double,double> > > edges) {
-    assert(edges.size() == 4);
-    _edges.push_back(edges[0]);
-    _edges.push_back(edges[1]);
-    _edges.push_back(edges[2]);
-    _edges.push_back(edges[3]);
+    if(edges.size() != 4) throw RangeError("The edge vector does not define a full rectangle!");
+    
+    _edges.first.first = edges[0].first.first;
+    _edges.first.second = edges[0].first.second;
+    _edges.second.first = edges[1].second.first;
+    _edges.second.second = edges[1].second.second;
 
     isReal = true;
   }
 
-
   void Bin2D::scaleXY(double scaleX, double scaleY) {
-    for (size_t i = 0; i < _edges.size(); ++i) {
-      _edges[i].first.first *= scaleX;
-      _edges[i].second.first *= scaleX;
-      _edges[i].first.second *= scaleY;
-      _edges[i].second.second *= scaleY;
-    }
+    _edges.first.first *= scaleX;
+    _edges.second.first *= scaleX;
+
+    _edges.first.second *= scaleY;
+    _edges.second.second *= scaleY;
+
     _dbn.scaleXY(scaleX, scaleY);
   }
 
   std::pair<double,double> Bin2D::midpoint() const {
     return make_pair((double)(xMax() - xMin())/2 + xMin(), (double)(yMax() - yMin())/2 + yMin());
-    }
+  }
 
     Bin2D& Bin2D::subtract(const Bin2D& b) {
         /// Automatically resize if adding a bin that does not have the same location

Modified: trunk/tests/TestHisto2D.cc
==============================================================================
--- trunk/tests/TestHisto2D.cc	Tue Aug 16 10:36:38 2011	(r249)
+++ trunk/tests/TestHisto2D.cc	Tue Aug 16 12:20:14 2011	(r250)
@@ -46,7 +46,6 @@
     cout << "Time to create 40K bins: " << tE - tS << "s" << endl;
     printStats(h);
 
-    h.mergeBins(1, 100);
 
     cout << h.numBinsTotal() << endl;
     h.addBin(0.1, 0.1, 0.2, 0.2);
@@ -162,16 +161,20 @@
     }
 
     /// Addition/Subtraction:
-    Histo2D first(100, 0, 100, 100, 0, 100);
+    cout << "Creating histos to be added/substracted/divided:" << endl;
+
+    Histo2D first(10, 0, 100, 10, 0, 100);
     first.fill(1,1,1);
     first.fill(23,1,1);
-    Histo2D second(100, 0, 100, 100, 0, 100);
+    Histo2D second(10, 0, 100, 10, 0, 100);
     second.fill(1,1,1);
 
+    cout << "Adding/Substracting/Dividing" << endl;
     Histo2D added(first+second);
     Histo2D subtracted(first-second);
     Scatter3D divided(first/second);
 
+    cout << "Done!" << endl;
     printStats(added);
     printStats(subtracted);
 
@@ -188,12 +191,12 @@
         return -1;
     }
     if(!fuzzyEquals(sampleHisto.sumW2(false), 1.51588e+10)) {
-        cout << "Something is wrong with weight squared!" << endl;
+        cout << "Something is wrong with weight squared! It is: " << sampleHisto.sumW2(false)<< endl;
         return -1;
     }
 
     Histo1D atY(sampleHisto.cutterX(0));
-    cout << atY.sumW(false) << " " <<atY.numBins() << endl;
+    cout << atY.sumW(false) << " " <<sampleHisto.sumW(false) << endl;
     if(!fuzzyEquals(atY.sumW(false), sampleHisto.sumW(false))){
         cout << "Something is wrong with weights when cut parallell to X axis." << endl;
         return -1;
@@ -214,5 +217,14 @@
         return -1;
     }
 
+    cout << "Testing bin merger:" << endl;
+    gettimeofday(&startTime, NULL);
+    h.mergeBins(0, 20000);
+    gettimeofday(&endTime, NULL);
+    tS = (startTime.tv_sec*1000000 + startTime.tv_usec)/(double)1000000;
+    tE = (endTime.tv_sec*1000000 + endTime.tv_usec)/(double)1000000;
+    
+    cout << "Time to merge 20k bins: " << tE - tS << "s" << endl;
+
     return EXIT_SUCCESS;
 }


More information about the yoda-svn mailing list