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

blackhole at projects.hepforge.org blackhole at projects.hepforge.org
Fri Jun 15 19:25:00 BST 2012


Author: buckley
Date: Fri Jun 15 19:25:00 2012
New Revision: 470

Log:
Histo2D reintroduced into compilation, and 2D classes cut down until compilation works (plus some consistency/minimalisation tidying). Work on implementing Axis2D etc. can now start in earnest.

Modified:
   trunk/TODO
   trunk/include/YODA/Axis1D.h
   trunk/include/YODA/Axis2D.h
   trunk/include/YODA/Bin1D.h
   trunk/include/YODA/Bin2D.h
   trunk/include/YODA/Histo2D.h
   trunk/include/YODA/HistoBin1D.h
   trunk/include/YODA/HistoBin2D.h
   trunk/include/YODA/ProfileBin1D.h
   trunk/include/YODA/ProfileBin2D.h
   trunk/include/YODA/ReaderYODA.h
   trunk/src/Histo2D.cc
   trunk/src/Makefile.am

Modified: trunk/TODO
==============================================================================
--- trunk/TODO	Fri May  4 11:03:33 2012	(r469)
+++ trunk/TODO	Fri Jun 15 19:25:00 2012	(r470)
@@ -21,6 +21,8 @@
 
 * Improve tests Makefile setup to work out the path to the Python build dir. (AB)
 
+* Remove nasty Cython shims (DM)
+
 
 
 NEXT

Modified: trunk/include/YODA/Axis1D.h
==============================================================================
--- trunk/include/YODA/Axis1D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/Axis1D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -19,21 +19,25 @@
   class Axis1D {
   public:
 
-    /// Convenience typedefs
+    /// Typedefs
+    //@{
+
+    /// Bin type
     typedef BIN1D Bin;
 
-    /// A vector containing 1D bins. It is not used for searching,
-    /// only for bins storage.
-    typedef typename std::vector<BIN1D> Bins;
+    /// A vector containing 1D bins. Not used for searching.
+    typedef typename std::vector<Bin> Bins;
 
-    /// Type used to implement a search table of low bin edges mapped to bin indices.
+    /// @brief Type used to implement a search table of low bin edges mapped to bin indices.
     /// An index of -1 indicates a gap interval, without a corresponding bin.
     typedef std::map<double, long int> BinHash;
 
+    //@}
+
+
     /// @name Constructors
     //@{
 
-
     /// Empty constructor
     Axis1D() { }
 
@@ -45,6 +49,7 @@
 
 
     /// Constructor with the number of bins and the axis limits
+    /// @todo Rewrite interface to use a pair for the low/high
     Axis1D(size_t nbins, double lower, double upper) {
       _addBins(linspace(lower, upper, nbins));
     }
@@ -170,7 +175,7 @@
     long int getBinIndex(double coord) const {
       // First check that we are within the axis bounds at all
       if (coord < lowEdge() || coord > highEdge()) return -1;
-      // Then return the lower-edge lookup from the hash map
+      // Then return the lower-edge lookup from the hash map.
       // NB. both upper_bound and lower_bound return values *greater* than (or equal) to coord,
       // so we have to step back one iteration to get to the lower-or-equal containing bin edge.
       BinHash::const_iterator itabove = _binhash.upper_bound(coord);
@@ -361,11 +366,13 @@
       }
     }
 
+
     /// Check if there are any bin edges between values @a from and @a to.
     bool _edgeInRange(double from, double to) const {
       return (--_binhash.upper_bound(from)) != (--_binhash.lower_bound(to));
     }
 
+
     /// Check if there are any gaps in the axis' binning between bin indices @a from and @a to, inclusive.
     bool _gapInRange(size_t ifrom, size_t ito) const {
       assert(ifrom < numBins() && ito < numBins() && ifrom <= ito);
@@ -390,7 +397,7 @@
     /// Total distribution
     DBN _dbn;
 
-    /// Under- and over- flows
+    /// Under- and overflows
     DBN _underflow;
     DBN _overflow;
 

Modified: trunk/include/YODA/Axis2D.h
==============================================================================
--- trunk/include/YODA/Axis2D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/Axis2D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -24,90 +24,66 @@
   /// workings.
   template <typename BIN2D, typename DBN>
   class Axis2D {
+  public:
 
-    /// @name Internal typedefs
+    /// @name Typedefs
     //@{
 
-    /// When an edge is added to the collection it must obey the following
-    /// format: the size_t specifies the bin this edge is a member of, and the
-    /// pair of doubles contains the beginning and end of the edge.
-    typedef typename std::pair<size_t, std::pair<double,double> > Edge;
-
-    /// A type being a basic substructure of _binHashSparse. It contains a indicator
-    /// specifying the major coordinate and a collection of edges sharing the same major
-    /// coordinate.
-    typedef typename std::pair<double, std::vector<Edge> > EdgeCollection;
-
-    /// A simple point in 2D
-    typedef typename std::pair<double, double> Point;
-
-    /// Segment, having a beginning and end.
-    typedef typename std::pair<Point, Point> Segment;
-
-    //@}
-
-
-  public:
-
-    // A few helpful typedefs
+    /// Bin type
     typedef BIN2D Bin;
 
-    /// @brief The internal bin container type
-    ///
-    /// The following vector holds in itself an information about a Bin and a
-    /// state in which it is. If the state is set to be false the bin will not
-    /// be displayed and in effect will be treated as non-existent. The most
-    /// common situation when such a functionality is needed is when merging a
-    /// bin. For detailed description about what happens in such case, please
-    /// refer to the mergeBins() function.
+    /// The internal bin container type. Not used for searching.
     typedef typename std::vector<Bin> Bins;
 
+    /// @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, int> SubBinHash;
+    typedef std::map<double, SubBinHash> BinHash;
+
+    //@}
 
-  public:
 
     /// @name Constructors:
     //@{
 
-    /// @brief Empty constructor
-    ///
-    /// Only added because it is required by SWIG.
-    /// It doesn't make much sense to use it.
-    /// @todo Really "required"? Eliminate the requirement in the SWIG mapping.
-    Axis2D() {
-      std::vector<Segment> edges;
-      _mkAxis(edges);
-    }
+    /// Empty constructor
+    Axis2D() {}
 
 
     /// Most standard constructor accepting X/Y ranges and number of bins
-    /// on each of the axis. Both Axis are divided linearly.
+    /// on each of the axis. Both axes are divided linearly.
+    /// @todo Rewrite interface to use pairs for the low/high
     Axis2D(size_t nbinsX, double lowerX, double upperX, size_t nbinsY, double lowerY, double upperY) {
-      std::vector<Segment> binLimits;
-      double coeffX = (upperX - lowerX)/(double)nbinsX;
-      double coeffY = (upperY - lowerX)/(double)nbinsY;
-      for (double i = lowerX; i < upperX; i += coeffX) {
-        for (double j = lowerY; j < upperY; j += coeffY) {
-          binLimits.push_back(std::make_pair(std::make_pair(i, j),
-                                             std::make_pair((double)(i+coeffX), (double)(j+coeffY))));
-        }
-      }
-      _mkAxis(binLimits);
-      _setOutflows();
+      /// @todo TODO
+
+      // std::vector<Segment> binLimits;
+      // double coeffX = (upperX - lowerX)/(double)nbinsX;
+      // double coeffY = (upperY - lowerX)/(double)nbinsY;
+      // for (double i = lowerX; i < upperX; i += coeffX) {
+      //   for (double j = lowerY; j < upperY; j += coeffY) {
+      //     binLimits.push_back(std::make_pair(std::make_pair(i, j),
+      //                                        std::make_pair((double)(i+coeffX), (double)(j+coeffY))));
+      //   }
+      // }
+      // _mkAxis(binLimits);
+      // _setOutflows();
     }
 
 
     /// A constructor with specified x and y axis bin limits.
     Axis2D(const std::vector<double>& xedges, const std::vector<double>& yedges) {
-      std::vector<Segment> binLimits;
-      /// Generate bin limits
-      for (size_t i = 0; i < yedges.size() - 1; ++i) {
-        for (size_t  j = 0; j < xedges.size() - 1; ++j) {
-          binLimits.push_back(std::make_pair(std::make_pair(xedges[j], yedges[i]),
-                                             std::make_pair(xedges[j+1], yedges[i+1])));
-        }
-      }
-      _mkAxis(binLimits);
-      _setOutflows();
+      /// @todo TODO
+
+      // std::vector<Segment> binLimits;
+      // /// Generate bin limits
+      // for (size_t i = 0; i < yedges.size() - 1; ++i) {
+      //   for (size_t  j = 0; j < xedges.size() - 1; ++j) {
+      //     binLimits.push_back(std::make_pair(std::make_pair(xedges[j], yedges[i]),
+      //                                        std::make_pair(xedges[j+1], yedges[i+1])));
+      //   }
+      // }
+      // _mkAxis(binLimits);
+      // _setOutflows();
     }
 
     /// @brief A constructor accepting a list of bins and all the outflows
@@ -117,53 +93,53 @@
            const std::vector<std::vector<DBN> >& outflows,
            const DBN& totalDbn)
     {
-      std::vector<Segment> binLimits;
-      foreach(Bin bin, bins) {
-        binLimits.push_back(std::make_pair(std::make_pair(bin.xMin(), bin.yMin()),
-                                           std::make_pair(bin.xMax(), bin.yMax())));
-      }
-      _mkAxis(binLimits);
-      for (size_t i = 0; i < _bins.size(); ++i) {
-        _bins[i] = bins[i];
-      }
-      if (isGrid()) _setOutflows();
-      _outflows = outflows;
+      /// @todo TODO
+
+      // std::vector<Segment> binLimits;
+      // foreach(Bin bin, bins) {
+      //   binLimits.push_back(std::make_pair(std::make_pair(bin.xMin(), bin.yMin()),
+      //                                      std::make_pair(bin.xMax(), bin.yMax())));
+      // }
+      // _mkAxis(binLimits);
+      // for (size_t i = 0; i < _bins.size(); ++i) {
+      //   _bins[i] = bins[i];
+      // }
+      // if (isGrid()) _setOutflows();
+      // _outflows = outflows;
 
-      _dbn = totalDbn;
+      // _dbn = totalDbn;
     }
 
-    /// A constructor accepting just a list of bins
-    Axis2D(const Bins& bins) 
+
+    /// Constructor accepting just a list of bins
+    Axis2D(const Bins& bins)
     {
-      std::vector<Segment> binLimits;
-      foreach(Bin bin, bins) {
-        binLimits.push_back(std::make_pair(std::make_pair(bin.xMin(), bin.yMin()),
-                                           std::make_pair(bin.xMax(), bin.yMax())));
-      }
-      _mkAxis(binLimits);
-      for (size_t i = 0; i < _bins.size(); ++i) {
-        _bins[i] = bins[i];
-      }
-      if (isGrid()) _setOutflows();
+      /// @todo TODO
+
+      // std::vector<Segment> binLimits;
+      // foreach(Bin bin, bins) {
+      //   binLimits.push_back(std::make_pair(std::make_pair(bin.xMin(), bin.yMin()),
+      //                                      std::make_pair(bin.xMax(), bin.yMax())));
+      // }
+      // _mkAxis(binLimits);
+      // for (size_t i = 0; i < _bins.size(); ++i) {
+      //   _bins[i] = bins[i];
+      // }
+      // if (isGrid()) _setOutflows();
     }
 
-    /// A copy constructor
+
+    /// Copy constructor
     Axis2D(const Axis2D& a) {
       _bins = a._bins;
       _dbn = a._dbn;
       _outflows = a._outflows;
 
-      _binHashSparse.first.regenCache();
-      _binHashSparse.second.regenCache();
-    }
-
-    /// Constructor provided with a vector of bin delimiters
-    Axis2D(const std::vector<Segment>& binLimits) {
-      _mkAxis(binLimits);
-      if (isGrid()) _setOutflows();
+      /// @todo TODO
+      // _binHashSparse.first.regenCache();
+      // _binHashSparse.second.regenCache();
     }
 
-
     //@}
 
 
@@ -172,28 +148,14 @@
 
     /// @brief Bin addition operator
     ///
-    /// This operator is provided a vector of limiting points in the format
-    /// required by _mkAxis().  It should be noted that there is nothing special
-    /// about the initiation stage of Axis2D, and the edges can be added online
-    /// if they meet all the requirements of non-degeneracy.
-    ///
-    /// Be aware that adding a Bin to an existing axis created by one of
-    /// constructors wipes out all the outflows since a concept of them is no
-    /// longer meaningful!
-    void addBin(const std::vector<Segment>& binLimits) {
-      _mkAxis(binLimits);
-      _outflows.resize(0);
-    }
-
-    /// @brief Bin addition operator
-    ///
     /// This operator is supplied with the extremal coordinates of just a new
     /// bin, which is then constructed and added as usual.
     void addBin(double lowX, double lowY, double highX, double highY) {
-      std::vector<Segment> coords;
-      coords.push_back(std::make_pair(std::make_pair(lowX, lowY),
-                                      std::make_pair(highX, highY)));
-      addBin(coords);
+      /// @todo TODO
+      // std::vector<Segment> coords;
+      // coords.push_back(std::make_pair(std::make_pair(lowX, lowY),
+      //                                 std::make_pair(highX, highY)));
+      // addBin(coords);
     }
 
     //@}
@@ -202,146 +164,115 @@
     /// @name Modifiers
     //@{
 
-    /// @brief Fill operator in 2D
-    ///
-    /// Called when it is wanted to fill a certain position on an Axis
-    int fill(double x, double y, double weight) {
-      // Filling the total distribution
-      _dbn.fill(x, y, weight);
-
-      // Filling a bin if the coordinates point to one.
-      int index = getBinIndex(x, y);
-      if (index != -1) _bins[index].fill(x, y, weight);
-
-      // If coordinates point outside any of the bins and and the outflows were
-      // properly set (i.e. we are dealing with a grid), fill a proper outflow.
-      else if (_outflows.size() == 8) _fillOutflows(x, y, weight);
-
-      // Return an information regarding what was filled.
-      return index;
-    }
-
-    /// @brief Fill operator for the 3D case
-    /// For a detailed description, please see the 2D one.
-    int fill(double x, double y, double z, double weight) {
-      _dbn.fill(x, y, z, weight);
-      
-      int index = getBinIndex(x,y);
-      if (index != -1) _bins[index].fill(x, y, z, weight);
-
-      else if (_outflows.size() == 8) _fillOutflows(x, y, z, weight);
-      return index;
-    }
-
-
-
-    /// Merge a range of bins, given the bin IDs of points at the lower-left and upper-right.
-    void mergeBins(size_t from, size_t to) {
-      /// Acquire the starting/ending bins
-      BIN2D& start = bin(from);
-      BIN2D& end = bin(to);
-
-      /// Set the bin to be added as a starting bin
-      /// and then remove the unneeded starting bin from
-      /// the list of bins.
-      BIN2D temp = start;
-      eraseBin(from);
-
-      // Sanity-check of input indices
-      if (start.midpoint().first > end.midpoint().first) {
-        throw RangeError("The start bin has a greater x value than the end bin.");
-      }
-      if (start.midpoint().second > end.midpoint().second) {
-        std::cout << "Start: " << start.midpoint().second;
-        std::cout << " end: " << end.midpoint().second << std::endl;
-        throw RangeError("The start bin has a greater y value than the end bin.");
-      }
-
-      /// Create a vector that will contain indexes of bins that
-      /// will be removed after merging them with our 'main' bin.
-      std::vector<size_t> toRemove;
-
-      /// Look for lower/upper limit of the merge function operation.
-      /// i.e.: search for index of lowEdgeY of starting bin in _binHashSparse
-      /// and lowEdgeY of ending bin. This way we don't have to scroll through all
-      /// the bins to check which ones we have to add.
-      for (size_t y = (*_binHashSparse.first._cache.lower_bound(start.yMin())).second;
-           y <= (*_binHashSparse.first._cache.lower_bound(end.yMin())).second; ++y) {
-        /// For all the bins that are in the bounds specified in previous for
-        for (size_t x = 0; x < _binHashSparse.first[y].second.size(); ++x) {
-          /// If the bin lies in a rectangle produced by starting and ending bins
-          /// (ie. the one spanned by lower-left point of starting bin and top-right
-          /// point of ending bin) and was not merged already:
-          if (((_binHashSparse.first[y].second[x].second.first > start.xMin() ||
-               fuzzyEquals(_binHashSparse.first[y].second[x].second.first, start.xMin())) &&
-              (_binHashSparse.first[y].second[x].second.second < end.xMax() ||
-               fuzzyEquals(_binHashSparse.first[y].second[x].second.second, end.xMax())))&&
-               !(std::find(toRemove.begin(), toRemove.end(), _binHashSparse.first[y].second[x].first) != toRemove.end()))
-            {
-              /// Merge it with the temp bin and mark it as ready for removal
-              temp += bin(_binHashSparse.first[y].second[x].first);
-              toRemove.push_back(_binHashSparse.first[y].second[x].first);
-            }
-        }
-      }
+    // /// Merge a range of bins, given the bin IDs of points at the lower-left and upper-right.
+    // /// @todo TODO
+    // void mergeBins(size_t from, size_t to) {
+    //   /// Acquire the starting/ending bins
+    //   BIN2D& start = bin(from);
+    //   BIN2D& end = bin(to);
+
+    //   /// Set the bin to be added as a starting bin
+    //   /// and then remove the unneeded starting bin from
+    //   /// the list of bins.
+    //   BIN2D temp = start;
+    //   eraseBin(from);
+
+    //   // Sanity-check of input indices
+    //   if (start.midpoint().first > end.midpoint().first) {
+    //     throw RangeError("The start bin has a greater x value than the end bin.");
+    //   }
+    //   if (start.midpoint().second > end.midpoint().second) {
+    //     std::cout << "Start: " << start.midpoint().second;
+    //     std::cout << " end: " << end.midpoint().second << std::endl;
+    //     throw RangeError("The start bin has a greater y value than the end bin.");
+    //   }
+
+    //   /// Create a vector that will contain indexes of bins that
+    //   /// will be removed after merging them with our 'main' bin.
+    //   std::vector<size_t> toRemove;
+
+    //   /// Look for lower/upper limit of the merge function operation.
+    //   /// i.e.: search for index of lowEdgeY of starting bin in _binHashSparse
+    //   /// and lowEdgeY of ending bin. This way we don't have to scroll through all
+    //   /// the bins to check which ones we have to add.
+    //   for (size_t y = (*_binHashSparse.first._cache.lower_bound(start.yMin())).second;
+    //        y <= (*_binHashSparse.first._cache.lower_bound(end.yMin())).second; ++y) {
+    //     /// For all the bins that are in the bounds specified in previous for
+    //     for (size_t x = 0; x < _binHashSparse.first[y].second.size(); ++x) {
+    //       /// If the bin lies in a rectangle produced by starting and ending bins
+    //       /// (ie. the one spanned by lower-left point of starting bin and top-right
+    //       /// point of ending bin) and was not merged already:
+    //       if (((_binHashSparse.first[y].second[x].second.first > start.xMin() ||
+    //            fuzzyEquals(_binHashSparse.first[y].second[x].second.first, start.xMin())) &&
+    //           (_binHashSparse.first[y].second[x].second.second < end.xMax() ||
+    //            fuzzyEquals(_binHashSparse.first[y].second[x].second.second, end.xMax())))&&
+    //            !(std::find(toRemove.begin(), toRemove.end(), _binHashSparse.first[y].second[x].first) != toRemove.end()))
+    //         {
+    //           /// Merge it with the temp bin and mark it as ready for removal
+    //           temp += bin(_binHashSparse.first[y].second[x].first);
+    //           toRemove.push_back(_binHashSparse.first[y].second[x].first);
+    //         }
+    //     }
+    //   }
+
+    //   /// Now, drop the bins to be dropped
+    //   /// Keeping in mind that the bins must be removed from the highest index
+    //   /// down, otherwise we will end up removing other bins that we intend to
+    //   std::sort(toRemove.begin(), toRemove.end());
+    //   std::reverse(toRemove.begin(), toRemove.end());
+    //   foreach(size_t remove, toRemove) eraseBin(remove);
+
+    //   /// Add edges of our merged bin to _binHashSparse and don't create a default
+    //   /// empty bin.
+    //   _addEdge(temp.edges(), _binHashSparse, false);
+
+    //   /// Add the actual merged bin to the Axis.
+    //   _bins.push_back(temp);
+
+
+
+    //   /// And regenerate the caches on _binHashSparse
+    //   _binHashSparse.first.regenCache();
+    //   _binHashSparse.second.regenCache();
+    // }
+
+    // /// Merge a range of bins giving start and end coordinates
+    // void mergeBins(double startX, double startY, double endX, double endY) {
+    //   mergeBins(binByCoord(startX, startY), binByCoord(endX, endY));
+    // }
+
+    // /// Rebin by an interger factor
+    // /// NOT YET WORKING!!11!!1111
+    // void rebin(size_t factorX, size_t factorY) {
+    //   if (!isGrid()) throw GridError("Rebinning by a factor can only act on full grids!");
+    //   if(factorX < 1 || factorY < 1) throw RangeError("Factors cannot be smaller than unity!");
+
+    //   size_t binsInColumn = _binHashSparse.first.size() - 1;
+
+    //   std::cout << std::endl << "Bins in column: " << binsInColumn << std::endl;
+    //   std::cout <<  "Number of bins: " << _bins.size() << std::endl;
+    //   size_t startIndex = 0;
+    //   while(true) {
+    //     size_t endIndex = startIndex;
+    //     for(size_t i = 1; i < factorY; ++i){
+    //       if(_hasAbove(endIndex) == 1) endIndex++;
+    //       else break;
+    //     }
+    //     binsInColumn -= endIndex - startIndex;
+    //     for(size_t i = 1; i < factorX; ++i){
+    //       if(endIndex + binsInColumn < _bins.size()) endIndex += binsInColumn;
+    //       else break;
+    //     }
+    //     if(endIndex + 1 >= _bins.size()) break;
+    //     mergeBins(startIndex, endIndex);
+    //     if(startIndex + 1 < _bins.size()) startIndex++;
+    //     else break;
 
-      /// Now, drop the bins to be dropped
-      /// Keeping in mind that the bins must be removed from the highest index
-      /// down, otherwise we will end up removing other bins that we intend to
-      std::sort(toRemove.begin(), toRemove.end());
-      std::reverse(toRemove.begin(), toRemove.end());
-      foreach(size_t remove, toRemove) eraseBin(remove);
-      
-      /// Add edges of our merged bin to _binHashSparse and don't create a default
-      /// empty bin.
-      _addEdge(temp.edges(), _binHashSparse, false);
-
-      /// Add the actual merged bin to the Axis.
-      _bins.push_back(temp);
-
-      
-
-      /// And regenerate the caches on _binHashSparse
-      _binHashSparse.first.regenCache();
-      _binHashSparse.second.regenCache();
-    }
-
-    /// Merge a range of bins giving start and end coordinates
-    void mergeBins(double startX, double startY, double endX, double endY) {
-      mergeBins(binByCoord(startX, startY), binByCoord(endX, endY));
-    }
-
-    /// Rebin by an interger factor
-    /// NOT YET WORKING!!11!!1111
-    void rebin(size_t factorX, size_t factorY) {
-      if (!isGrid()) throw GridError("Rebinning by a factor can only act on full grids!");
-      if(factorX < 1 || factorY < 1) throw RangeError("Factors cannot be smaller than unity!");
-      
-      size_t binsInColumn = _binHashSparse.first.size() - 1;
-
-      std::cout << std::endl << "Bins in column: " << binsInColumn << std::endl;
-      std::cout <<  "Number of bins: " << _bins.size() << std::endl;
-      size_t startIndex = 0;
-      while(true) {
-        size_t endIndex = startIndex;
-        for(size_t i = 1; i < factorY; ++i){ 
-          if(_hasAbove(endIndex) == 1) endIndex++;
-          else break;
-        }
-        binsInColumn -= endIndex - startIndex;
-        for(size_t i = 1; i < factorX; ++i){
-          if(endIndex + binsInColumn < _bins.size()) endIndex += binsInColumn;
-          else break;
-        }
-        if(endIndex + 1 >= _bins.size()) break;
-        mergeBins(startIndex, endIndex);
-        if(startIndex + 1 < _bins.size()) startIndex++;
-        else break;
+    //     if(_hasAbove(startIndex-1) == 0) binsInColumn = _binHashSparse.first.size() -1;
+    //   }
 
-        if(_hasAbove(startIndex-1) == 0) binsInColumn = _binHashSparse.first.size() -1;
-      }
+    // }
 
-    }
 
     /// Reset the axis statistics
     void reset() {
@@ -365,33 +296,37 @@
 
     /// Get the number of bins along X axis
     const size_t numBinsX() const {
-      return _binHashSparse.second.size()/2;
+      return (numBins() > 0) ? _binhash.size() : 0;
     }
 
     /// Get the number of bins along Y axis
     const size_t numBinsY() const {
-      return _binHashSparse.first.size()/2;
+      return (numBins() > 0) ? _binhash.begin()->second.size() : 0;
     }
 
 
     /// Get the value of the lowest x-edge on the axis
     const double lowEdgeX() const {
-      return _binHashSparse.second.front().first;
+      if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range");
+      return _binhash.begin()->first;
     }
 
     /// Get the value of the highest x-edge on the axis
     const double highEdgeX() const {
-      return _binHashSparse.second.back().first;
+      if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range");
+      return (--_binhash.end())->first;
     }
 
     /// Get the value of the lowest y-edge on the axis
     const double lowEdgeY() const {
-      return _binHashSparse.first.front().first;
+      if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range");
+      return _binhash.begin()->second.begin()->first;
     }
 
     /// Get the value of the highest y-edge on the axis
     const double highEdgeY() const {
-      return _binHashSparse.first.back().first;
+      if (numBins() == 0) throw RangeError("This axis contains no bins and so has no defined range");
+      return (--_binhash.begin()->second.end())->first;
     }
 
 
@@ -435,15 +370,15 @@
     /// Get a bin at given coordinates (non-const version)
     BIN2D& binByCoord(double x, double y) {
       const int ret = getBinIndex(x, y);
-      if (ret != -1) return bin(ret);
-      else throw RangeError("No bin found!!");
+      if (ret == -1) throw RangeError("No bin found!!");
+      return bin(ret);
     }
 
     /// Get a bin at given coordinates (const version)
     const BIN2D& binByCoord(double x, double y) const {
       const int ret = getBinIndex(x, y);
-      if (ret != -1) return bin(ret);
-      else throw RangeError("No bin found!!");
+      if (ret == -1) throw RangeError("No bin found!!");
+      return bin(ret);
     }
 
 
@@ -473,103 +408,54 @@
     ///
     /// Looks through all the bins to see which one contains the point of
     /// interest.
-    const int getBinIndex(double coordX, double coordY) const {
-      // In case we are just operating on a regular grid
-      if (isGrid()) {
-        coordX += coordX/2000000000;
-        coordY += coordY/2000000000;
-        size_t indexY = (*_binHashSparse.first._cache.lower_bound(approx(coordY))).second;
-
-        if (indexY < _binHashSparse.first.size()) {
-          foreach(Edge edgeY, _binHashSparse.first[indexY].second) {
-            if (edgeY.second.first < coordX && edgeY.second.second > coordX) {
-              size_t indexX = (*_binHashSparse.second._cache.lower_bound(approx(coordX))).second;
-              if (indexX < _binHashSparse.second.size()) {
-                foreach (Edge edgeX, _binHashSparse.second[indexX].second) {
-                  if (edgeX.second.first < coordY && edgeX.second.second > coordY &&
-                      (edgeX.first == edgeY.first))
-                    return edgeX.first;
-                }
-              }
-            }
-          }
-        }
-        return -1;
-      }
-
-      // In case we have something more complicated
-      for (size_t i = 0; i < _bins.size(); ++i) {
-        if (_bins[i].xMin() <= coordX && _bins[i].xMax() >= coordX &&
-            _bins[i].yMin() <= coordY && _bins[i].yMax() >= coordY)
-             return i;
-      }
-      return -1;
-    }
-
-
-    /// Fast column number searcher
-    const size_t getBinColumn(size_t index) const {
-      // Check if assumptions are reasonable
-      if (!_isGrid) throw GridError("This operation can only be performed when an array is a grid!");
-      if (index >= _bins.size()) throw RangeError("Index is bigger than the size of bins vector!");
-
-      // Find the column number
-      size_t ret  = (*_binHashSparse.first._cache.lower_bound(approx(bin(index).yMin()))).second;
-      return ret;
-    }
-
-
-    /// Fast row number searcher
-    const size_t getBinRow(size_t index) const {
-      // Check if assumptions are reasonable
-      if (!_isGrid) throw GridError("This operation can only be performed when an array is a grid!");
-      if (index >= _bins.size()) throw RangeError("Index is bigger than the size of bins vector!");
-
-      // Find the row number
-      size_t ret  = (*_binHashSparse.second._cache.lower_bound(approx(bin(index).xMin()))).second;
-      return ret;
+    const long getBinIndex(double coordX, double coordY) const {
+      // First check that we are within the axis bounds at all
+      if (coordX < lowEdgeX() || coordX > highEdgeX()) return -1;
+      if (coordY < lowEdgeY() || coordY > highEdgeY()) return -1;
+      // Then return the lower-edge lookup (in both directions) from the hash map.
+      // NB. both upper_bound and lower_bound return values *greater* than (or equal) to coord,
+      // so we have to step back one iteration to get to the lower-or-equal containing bin edge.
+      BinHash::const_iterator itaboveX = _binhash.upper_bound(coordX);
+      SubBinHash::const_iterator itaboveY = (--itaboveX)->second.upper_bound(coordY);
+      int index = (--itaboveY)->second;
+      return index;
     }
 
 
-    /// Check if the axis has a grid structure or not
-    bool isGrid() const {
-      return _isGrid;
-    }
+    // /// Fast column number searcher
+    // const size_t getBinColumn(size_t index) const {
+    //   // Check if assumptions are reasonable
+    //   if (!_isGrid) throw GridError("This operation can only be performed when an array is a grid!");
+    //   if (index >= _bins.size()) throw RangeError("Index is bigger than the size of bins vector!");
+
+    //   // Find the column number
+    //   size_t ret  = (*_binHashSparse.first._cache.lower_bound(approx(bin(index).yMin()))).second;
+    //   return ret;
+    // }
+
+
+    // /// Fast row number searcher
+    // const size_t getBinRow(size_t index) const {
+    //   // Check if assumptions are reasonable
+    //   if (!_isGrid) throw GridError("This operation can only be performed when an array is a grid!");
+    //   if (index >= _bins.size()) throw RangeError("Index is bigger than the size of bins vector!");
+
+    //   // Find the row number
+    //   size_t ret  = (*_binHashSparse.second._cache.lower_bound(approx(bin(index).xMin()))).second;
+    //   return ret;
+    // }
 
 
     /// @brief Bin eraser
     ///
-    /// Removes a bin at a position. Additionally, modifies bin cache to
-    /// make it represent the new bin set.
+    /// Removes a bin at a position.
     void eraseBin(size_t index) {
       // Check the correctness of assumptions
-      if (index >= _bins.size()) throw RangeError("Index is bigger than the size of bins vector!");
-
-      _bins.erase(_bins.begin() + index);
-      // Check if delimiter if recomputed after every for run.
-      for (size_t i = 0; i < _binHashSparse.first.size(); ++i) {
-        for (size_t j = 0; j < _binHashSparse.first[i].second.size(); ++j) {
-          if (_binHashSparse.first[i].second[j].first == index) {
-            _binHashSparse.first[i].second.erase(_binHashSparse.first[i].second.begin() + j);
-            j--;
-          }
-          else if (_binHashSparse.first[i].second[j].first > index) {
-            _binHashSparse.first[i].second[j].first--;
-          }
-        }
-      }
+      if (index >= numBins()) throw RangeError("Index is bigger than the size of bins vector!");
 
-      for (size_t i = 0; i < _binHashSparse.second.size(); ++i) {
-        for (size_t j = 0; j < _binHashSparse.second[i].second.size(); ++j) {
-          if (_binHashSparse.second[i].second[j].first == index) {
-            _binHashSparse.second[i].second.erase(_binHashSparse.second[i].second.begin() + j);
-            j--;
-          }
-          else if (_binHashSparse.second[i].second[j].first > index) {
-            _binHashSparse.second[i].second[j].first--;
-          }
-        }
-      }
+      /// @todo Check for overlaps
+      /// @todo If within the current bounds, create and rehash
+      /// @todo If outside the bounds, check for grid compatibility, create and rehash
     }
     //@}
 
@@ -582,52 +468,35 @@
     /// Scales the axis with a given scale.
     /// @todo Add a specific check for a scaling of 1.0, to avoid doing work when no scaling is wanted.
     void scaleXY(double scaleX, double scaleY) {
-      // Two loops are put on purpose, just to protect
-      // against improper _binHashSparse
-      for (size_t i = 0; i < _binHashSparse.first.size(); ++i) {
-        _binHashSparse.first[i].first *= scaleY;
-        for (size_t j = 0; j < _binHashSparse.first[i].second.size(); ++j) {
-          _binHashSparse.first[i].second[j].second.first  *= scaleX;
-          _binHashSparse.first[i].second[j].second.second *= scaleX;
-        }
-      }
-      for (size_t i = 0; i < _binHashSparse.second.size(); ++i) {
-        _binHashSparse.second[i].first *= scaleX;
-        for (size_t j = 0; j < _binHashSparse.second[i].second.size(); ++j) {
-          _binHashSparse.second[i].second[j].second.first  *= scaleY;
-          _binHashSparse.second[i].second[j].second.second *= scaleY;
-        }
-      }
-
-      /// Regenerate the bin edges cache.
-      _binHashSparse.first.regenCache();
-      _binHashSparse.second.regenCache();
-
-      /// Now, as we have the map rescaled, we need to update the bins
       foreach(Bin bin, _bins) {
         bin.scaleXY(scaleX, scaleY);
       }
-
       _dbn.scaleXY(scaleX, scaleY);
-      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 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
     }
 
 
     /// Scales the bin weights
     void scaleW(double scalefactor) {
-      _dbn.scaleW(scalefactor);
-      for (size_t i = 0; i < _outflows.size(); ++i) {
-        for (size_t j = 0; j < _outflows[i].size(); ++j) {
-          _outflows[i][j].scaleW(scalefactor);
-        }
-      }
       foreach(Bin bin, _bins) {
         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);
+      //   }
+      // }
     }
 
     //@}
@@ -636,19 +505,10 @@
     /// @name Operators
     //@{
 
-    /// Equality operator
+    /// Equality operator (on binning only)
     bool operator == (const Axis2D& other) const {
-      if (isGrid()) {
-        foreach(Bin bin, _bins) {
-          int index = other.getBinIndex(bin.midpoint().first, bin.midpoint().second);
-          if (index != -1) {
-            if (other.bin(index) != bin) return false;
-          }
-          else return false;
-        }
-        return true;
-      }
-      else return _binHashSparse == other._binHashSparse;
+      /// @todo TODO
+      return true;
     }
 
 
@@ -663,7 +523,7 @@
     /// @todo Compatible but not equal binning to come soon.
     Axis2D<BIN2D, DBN>& operator += (const Axis2D<BIN2D, DBN>& toAdd) {
       if (*this != toAdd) {
-        throw LogicError("YODA::Histo1D: Cannot add axes with different binnings.");
+        throw LogicError("YODA::Axis2D: Cannot add axes with different binnings.");
       }
       for (size_t i = 0; i < bins().size(); ++i) {
         bin(i) += toAdd.bin(i);
@@ -679,7 +539,7 @@
     /// @todo Compatible but not equal binning to come soon.
     Axis2D<BIN2D, DBN>& operator -= (const Axis2D<BIN2D, DBN>& toSubtract) {
       if (*this != toSubtract) {
-        throw LogicError("YODA::Histo1D: Cannot add axes with different binnings.");
+        throw LogicError("YODA::Axis2D: Cannot add axes with different binnings.");
       }
       for (size_t i = 0; i < bins().size(); ++i) {
         bin(i) -= toSubtract.bin(i);
@@ -693,456 +553,105 @@
 
   private:
 
-    int _hasAbove(size_t index){
-      if(index == _bins.size() - 1) return -1;
-      if(fuzzyEquals(_bins[index].yMax(), _bins[index+1].yMin()) &&
-         fuzzyEquals(_bins[index].xMin(), _bins[index+1].xMin()) &&
-         fuzzyEquals(_bins[index].xMax(), _bins[index+1].xMax())) return 1;
-      if(fuzzyEquals(_bins[index].xMax(), _bins[index+1].xMin())) return 0;
-      return 1500;
-    }
+    // /// Add new bins, constructed from two sorted vectors of edges, to the axis
+    // void _addBins(const std::vector<double>& xbinedges, const std::vector<double>& ybinedges) {
+    //   //std::sort(binedges.begin(), binedges.end());
+    //   if (_edgeInRange(binedges.front(), binedges.back())) {
+    //     throw RangeError("New bin range overlaps with existing bin edges");
+    //   }
+    //   for (size_t i = 0; i < binedges.size() - 1; ++i) {
+    //     _bins.push_back(BIN1D(binedges[i], binedges[i+1]));
+    //   }
+    //   _updateAxis();
+    // }
 
 
-    /// @brief Outflows pre-setter
-    /// Sets the correct number of bins in each of the outflows.
-    void _setOutflows() {
-      _outflows.resize(8);
+    /// Add new bins to the axis
+    void _addBins(const Bins& bins) {
+      for (size_t i = 0; i < bins.size(); ++i) {
 
-      _outflows[0].resize(1);
-      _outflows[1].resize(_binHashSparse.second.size());
-      _outflows[2].resize(1);
-      _outflows[3].resize(_binHashSparse.first.size());
-      _outflows[4].resize(1);
-      _outflows[5].resize(_binHashSparse.second.size());
-      _outflows[6].resize(1);
-      _outflows[7].resize(_binHashSparse.first.size());
+        /// @todo Check for 2D edge overlaps
 
-    }
-
-
-    /// 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) {
-      if (x < _lowEdgeX && y > _highEdgeY) _outflows[0][0].fill(x, y, weight);
-      else if (x > _lowEdgeX && x < _highEdgeX && y > _highEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.second, x, 0, _binHashSparse.second.size());
-        _outflows[1][element].fill(x, y, weight);
-      }
-      else if (x > _highEdgeX && y > _highEdgeY) _outflows[2][0].fill(x, y, weight);
-      else if (x > _highEdgeX && y > _lowEdgeY && y < _highEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.first, y, 0, _binHashSparse.first.size());
-        _outflows[3][element].fill(x, y, weight);
-      }
-      else if (x > _highEdgeX && y < _lowEdgeY) _outflows[4][0].fill(x, y, weight);
-      else if (x > _lowEdgeX && x < _highEdgeX && y < _lowEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.second, x, 0, _binHashSparse.second.size());
-        _outflows[5][element].fill(x, y, weight);
-      }
-      else if (x < _lowEdgeX && y < _lowEdgeY) _outflows[6][0].fill(x, y, weight);
-      else if (x < _lowEdgeX && y > _lowEdgeY && y < _highEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.first, y, 0, _binHashSparse.first.size());
-        _outflows[7][element].fill(x, y, weight);
-      }
-
-    }
-    
-    /// 3D outflow filler
-    void _fillOutflows(double x, double y, double z, double weight) {
-      if (x < _lowEdgeX && y > _highEdgeY) _outflows[0][0].fill(x, y, z, weight);
-      else if (x > _lowEdgeX && x < _highEdgeX && y > _highEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.second, x, 0, _binHashSparse.second.size());
-        _outflows[1][element].fill(x, y, z, weight);
-      }
-      else if (x > _highEdgeX && y > _highEdgeY) _outflows[2][0].fill(x, y, z, weight);
-      else if (x > _highEdgeX && y > _lowEdgeY && y < _highEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.first, y, 0, _binHashSparse.first.size());
-        _outflows[3][element].fill(x, y, z, weight);
-      }
-      else if (x > _highEdgeX && y < _lowEdgeY) _outflows[4][0].fill(x, y, z, weight);
-      else if (x > _lowEdgeX && x < _highEdgeX && y < _lowEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.second, x, 0, _binHashSparse.second.size());
-        _outflows[5][element].fill(x, y, z, weight);
-      }
-      else if (x < _lowEdgeX && y < _lowEdgeY) _outflows[6][0].fill(x, y, z, weight);
-      else if (x < _lowEdgeX && y > _lowEdgeY && y < _highEdgeY)
-      {
-        size_t element = _binaryS(_binHashSparse.first, y, 0, _binHashSparse.first.size());
-        _outflows[7][element].fill(x, y, z, weight);
-      }
-
-    }
-
-    /// @brief Checks if our bins form a grid.
-    ///
-    /// This function uses a neat property of _binHashSparse.  If it is
-    /// containing a set of edges forming a grid without gaps in the middle it
-    /// will have the same number of edges in the inner subcaches and half of
-    /// this amount in the outer (grid boundary) subcaches. This makes isGrid()
-    /// a very, very fast function.
-    void _genGridCache() {
-      // Check if the number of edges parallel to the x axis is proper in every
-      // subcache.
-      size_t sizeX = _binHashSparse.first[0].second.size();
-      for (size_t i = 1; i < _binHashSparse.first.size(); ++i) {
-        if (i == _binHashSparse.first.size() - 1) {
-          if (_binHashSparse.first[i].second.size() != sizeX) {
-            _isGrid = false;
-            return;
-          }
-        }
-        else if (_binHashSparse.first[i].second.size() != 2*sizeX) {
-          _isGrid = false;
-          return;
-        }
-      }
-
-      // Do the same for edges parallel to the y axis.
-      size_t sizeY = _binHashSparse.second[0].second.size();
-      for (size_t i = 1; i < _binHashSparse.second.size(); ++i) {
-        if (i != _binHashSparse.second.size() - 1) {
-          if (2*sizeY != _binHashSparse.second[i].second.size()) {
-            _isGrid = false;
-            return;
-          }
-        }
-        else if (_binHashSparse.second[i].second.size() != sizeY) {
-          _isGrid = false;
-          return;
-        }
+        // if (_edgeInRange(bins[i].xMin(), bins[i].xMax())) {
+        //   throw RangeError("New bin range overlaps with existing bin edges");
+        // }
+        _bins.push_back(bins[i]);
       }
-
-      // If everything is proper, announce it.
-      _isGrid = true;
+      _updateAxis();
     }
 
 
-    /// @brief Segment validator function
+    /// Sort the bins vector, and regenerate the bin hash
     ///
-    /// This a 'dispatcher' function. It checks if the segment in question
-    /// is vertical or horizontal and launches the appropriate function
-    /// searching for cuts in the prope direction. Since it operates on
-    /// a vector of segments it is prepared to act on arbitrarly large sets of edges,
-    /// in practice usually being four sides of a rectangular bin.
-    ///
-    /// Notice that it will never be checked, in the current state, if there is a cut
-    /// in edges in the edgeset. This imposes the requirement of provide the program
-    /// with non-degenerate bins, until checking in implemented. However, it doesn't seem
-    /// to be needed, as edges are not generated by a user.
-    ///
-    /// This is also a perfect place to parallelize, if required.
-    bool _validateEdge(std::vector<Segment>& edges) {
-      // Setting the return variable. True means that no cuts were detected.
-      bool ret = true;
-
-      // Looping over all the edges provided
-      foreach(Segment edge, edges) {
-        // If the X coordinate of the starting point is the same
-        // as X coordinate of the ending one, checks if there are cuts
-        // on this vertical segment.
-        if (fuzzyEquals(edge.first.first, edge.second.first)) {
-          ret = _findCutsY(edge);
-        }
-
-        /// Check if the segment is horizontal and is it cutting any bin that already exists
-        else if (fuzzyEquals(edge.first.second, edge.second.second)) {
-          ret =  _findCutsX(edge);
-        }
-
-        // This is a check that discards the bin if it is not a rectangle
-        // composed of vertical and horizontal segments.
-        else {
-          ret = false;
+    /// The bin hash is purely for searching, and is generated from the bins list only.
+    void _updateAxis() {
+      std::sort(_bins.begin(), _bins.end());
+      _binhash.clear();
+      for (size_t i = 0; i < numBins(); ++i) {
+        // Add low edge hash for each bin
+        _binhash[bin(i).xMin()] = i;
+        // If the next bin is not contiguous, add a gap index for the high edge of this bin
+        if (i+1 < numBins() && !fuzzyEquals(bin(i).xMax(), bin(i+1).xMin())) {
+          _binhash[bin(i).xMax()] = -1;
         }
-
-        // If a cut was detected, return false immediately.
-        if (!ret) return false;
       }
-      // If no cuts were detected in any of the edges, tell the launching function about this
-      return true;
     }
 
 
-    /// @brief A binary search function
-    ///
-    /// This is conceptually the same implementation as in STL
-    /// but because it returns the index of an element in a vector,
-    /// it is easier to use in our case than the STL implementation
-    /// that returns a pointer at the element.
-    ///
-    /// @todo This is far too big to be inline: move it to the bottom of this file, or perhaps to a .cc
-    /// @todo Does this actually have to be a member function? Isn't it just a function?
-    size_t _binaryS(Utils::cachedvector<EdgeCollection>& toSearch,
-                    double value, size_t lower, size_t higher) {
-      // Just a check if such degenerate situation happens
-      if (lower == higher) return lower;
-
-      // Choose a midpoint that will be our pivot
-      size_t where = (higher+lower)/2;
-
-      // Launch the same procedure on half of the range above the pivot
-      if (value >= toSearch[where].first) {
-        if (where == toSearch.size() - 1) return where;
-        if (value <= toSearch[where+1].first) return where;
-        return _binaryS(toSearch, value, where, higher);
-      }
-
-      // This is not a redundant check, because of the nature of int division.
-      if (where == 0) return where;
-
-      // Check if the value is somewhere in-between an element at the position
-      // in question and an element at a lower position. If so, return an index
-      // to the current positon.
-      if (value >= toSearch[where-1].first) return where;
-
-      // If none of the above occurs, the value must be smaller that the element
-      // at the current position. In such case, launch the search on half of the
-      // interval below the current position.
-      return _binaryS(toSearch, value, lower, where);
-    }
+    /// @todo Convert from 1D to 2D
+    // /// Check if there are any bin edges between values @a from and @a to.
+    // bool _edgeInRange(double from, double to) const {
+    //   return (--_binhash.upper_bound(from)) != (--_binhash.lower_bound(to));
+    // }
 
 
-    /// @brief Function that finds cuts of horizontal edges.
-    ///
-    /// A specialised function that tries to exploit the fact
-    /// that edges can cut one another only on right angles
-    /// to the highest extent. The inner workings are explained
-    /// in the comments placed in the function body.
-    ///
-    /// @todo Explain what "cuts" are -- this is not obvious
-    bool _findCutsX(Segment& edge) {
-      // Look up the limits of search in the _binHashSparse
-      // structure. We are not interested in the vertical edges
-      // that are before the beginning of our segment or after its end.
-      size_t i = _binaryS(_binHashSparse.second, edge.first.first, 0, _binHashSparse.second.size());
-      size_t end = _binaryS(_binHashSparse.second, edge.second.first, 0, _binHashSparse.second.size());
-
-      for (; i < end; ++i) {
-        // Scroll through all the vertical segments with a given X coordinate
-        // and see if any of those fulfills the cutting requirement. If it does,
-        // announce it.
-        for (size_t j = 0; j < _binHashSparse.second[i].second.size(); ++j) {
-          // Note that we are not taking into account the edges touching the
-          // segment in question. That's because sides of a bin touch
-          if (_binHashSparse.second[i].second[j].second.first < edge.first.second &&
-              _binHashSparse.second[i].second[j].second.second > edge.first.second &&
-              !fuzzyEquals(_binHashSparse.second[i].second[j].second.first, edge.first.second) &&
-              !fuzzyEquals(_binHashSparse.second[i].second[j].second.second, edge.first.second)) {
-            return false;
-          }
-        }
-      }
-      // If none of the existing edges is cutting this edge, announce it
-      return true;
-    }
+    /// @todo Convert from 1D to 2D
+    // /// Check if there are any gaps in the axis' binning between bin indices @a from and @a to, inclusive.
+    // bool _gapInRange(size_t ifrom, size_t ito) const {
+    //   assert(ifrom < numBins() && ito < numBins() && ifrom <= ito);
+    //   if (ifrom == ito) return false;
+    //   BinHash::const_iterator start = (--_binhash.upper_bound(bin(ifrom).midpoint()));
+    //   BinHash::const_iterator end = _binhash.upper_bound(bin(ifrom).midpoint());
+    //   for (BinHash::const_iterator it = start; it != end; ++it) {
+    //     if (it->second == -1) return true;
+    //   }
+    //   return false;
+    // }
 
 
-    /// @brief Function that finds cuts of vertical edges
-    ///
-    /// For a detailed description, see the documentation for _findCutsX().
-    ///
-    /// @todo Explain what "cuts" are -- this is not obvious
-    /// @todo Can the code for "cut" finding be abstracted to work in both
-    /// directions, to avoid writing (and maintaining) it twice?
-    bool _findCutsY(Segment& edge) {
-      size_t i = _binaryS(_binHashSparse.first, edge.first.second, 0, _binHashSparse.first.size());
-      size_t end = _binaryS(_binHashSparse.first, edge.second.second, 0, _binHashSparse.first.size());
-      for (; i < end; ++i) {
-        for (size_t j = 0; j < _binHashSparse.first[i].second.size(); ++j) {
-          if (_binHashSparse.first[i].second[j].second.first < edge.first.first &&
-              _binHashSparse.first[i].second[j].second.second > edge.first.first &&
-              !fuzzyEquals(_binHashSparse.first[i].second[j].second.first, edge.first.first) &&
-              !fuzzyEquals(_binHashSparse.first[i].second[j].second.second, edge.first.first)) {
-            return false;
-          }
-        }
-      }
-      return true;
-    }
-
-
-    /// @brief Bin inserter
-    ///
-    /// It contains all the commands that need to executed to properly add a
-    /// bin. Specifically edges are added to the edge cache (_binHashSparse) and
-    /// a bin is created from those edges.
-    void _addEdge(Segment edges, std::pair<Utils::cachedvector<EdgeCollection>,
-                  Utils::cachedvector<EdgeCollection> >& binHash, bool addBin = true) {
-
-      // This is the part in charge of adding each of the segments
-      // to the edge cache. Segments are assumed to be validated
-      // beforehand.
-      foreach(Segment edge, edges) {
-        // Do the following if the edge is vertical.
-        // Those two cases need to be distinguished
-        // because of the way in which edge cache is structured.
-        if (edge.first.first == edge.second.first) {
-          // See if our edge has the same X coordinate as any other
-          // edge that is currently in the cache.
-
-          // Keeps the status of the search
-          bool found = false;
-
-          // There is only a certain set of X coordinates that we need to sweep
-          // to check if our segment has the same X coordinate. Find them.
-          size_t i = _binaryS(binHash.second, edge.first.first, 0, binHash.second.size()) - 1;
-          if (i < 0) i = 0;
-          size_t end = i + 3;
-
-          // For the coordinates in range, check if one of them is an X
-          // coordinate of the segment.
-          for (; i < binHash.second.size() && i < end ; ++i) {
-            /// If this is the case, do what is needed to be done.
-            if (fuzzyEquals(binHash.second[i].first, edge.first.first)) {
-              binHash.second[i].second.push_back(std::make_pair(_bins.size(),
-                                                                std::make_pair(edge.first.second, edge.second.second)));
-              found = true;
-              break;
-            }
-          }
-
-          // If no edge with the same X coordinate exist, create
-          // a new subhash at the X coordinate of a segment.
-          if (!found) {
-            std::vector<Edge> temp;
-            temp.push_back(std::make_pair(_bins.size(), std::make_pair(edge.first.second, edge.second.second)));
-            binHash.second.push_back(std::make_pair(edge.first.first, temp));
-            sort(binHash.second.begin(), binHash.second.end());
-          }
-        }
-
-        // See the vertical case for description of a horizontal one
-        else if (edge.first.second == edge.second.second) {
-          bool found = false;
-          size_t i = _binaryS(binHash.first, edge.first.second, 0, binHash.first.size())-1;
-          if (i < 0) i = 0;
-          size_t end = i+3;
-          for (; i < binHash.first.size() && i < end; ++i) {
-            if (fuzzyEquals(binHash.first[i].first, edge.first.second)) {
-              binHash.first[i].second.push_back(std::make_pair(_bins.size(),
-                                                               std::make_pair(edge.first.first, edge.second.first)));
-              found = true;
-            }
-          }
-          if (!found) {
-            std::vector<Edge> temp;
-            temp.push_back(std::make_pair(_bins.size(), std::make_pair(edge.first.first, edge.second.first)));
-            binHash.first.push_back(std::make_pair(edge.second.second, temp));
-            sort(binHash.first.begin(), binHash.first.end());
-          }
-        }
-      }
-
-      // Now, create a bin with the edges provided
-      if (addBin) _bins.push_back(BIN2D(edges));
-    }
-
-
-    /// @brief Orientation fixer
-    ///
-    /// Check if the orientation of an edge is proper
-    /// for the rest of the algorithm to work on, and if it is not
-    /// fix it.
-    void _fixOrientation(Segment& edge) {
-      if (fuzzyEquals(edge.first.first, edge.second.first)) {
-        if (edge.first.second > edge.second.second) {
-          double temp = edge.second.second;
-          edge.second.second = edge.first.second;
-          edge.first.second = temp;
-        }
-      }
-      else if (edge.first.first > edge.second.first) {
-        double temp = edge.first.first;
-        edge.first.first = edge.second.first;
-        edge.second.first = temp;
-      }
-    }
-
-
-    /// @brief Axis creator
-    ///
-    /// The top-level function taking part in the process of adding
-    /// edges. Creating an axis is the same operation for it as adding new bins
-    /// so it can be as well used to add some custom bins.
-    ///
-    /// It accepts two extremal points of a rectangle (top-right and
-    /// bottom-left) as input.
-    void _mkAxis(const std::vector<Segment>& binLimits) {
-
-      // For each of the rectangles
-      foreach(Segment binLimit, binLimits) {
-        // Produce the segments that a rectangle is composed of
-        Segment edge1 =
-          std::make_pair(binLimit.first,
-                         std::make_pair(binLimit.first.first, binLimit.second.second));
-        Segment edge2 =
-          std::make_pair(std::make_pair(binLimit.first.first, binLimit.second.second),
-                         binLimit.second);
-        Segment edge3 =
-          std::make_pair(std::make_pair(binLimit.second.first, binLimit.first.second),
-                         binLimit.second);
-        Segment edge4 =
-          std::make_pair(binLimit.first,
-                         std::make_pair(binLimit.second.first, binLimit.first.second));
-
-        // Check if they are made properly
-        _fixOrientation(edge1); _fixOrientation(edge2);
-        _fixOrientation(edge3); _fixOrientation(edge4);
-
-        // Add all the segments to a vector
-        std::vector<Segment> edges;
-        edges.push_back(edge1); edges.push_back(edge2);
-        edges.push_back(edge3); edges.push_back(edge4);
-
-        // And check if a bin is a proper one, if it is, add it.
-        if (_validateEdge(edges))  _addEdge(edges, _binHashSparse);
-      }
-
-      // Setting all the caches
-      _binHashSparse.first.regenCache();
-      _binHashSparse.second.regenCache();
-      _genGridCache();
+    /// 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
+    //@{
+
     /// Bins contained in this histogram
     Bins _bins;
 
-    /// Outflow distributions
-    /// It 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.
-    std::vector<std::vector<DBN> > _outflows;
-
     /// Total distribution
     DBN _dbn;
 
-    /// @brief Bin hash structure
+    /// Outflow distributions
     ///
-    /// First in pair is holding the horizontal edges indexed by first.first
-    /// which is an y coordinate. The last pair specifies x coordinates (begin, end) of
-    /// the horizontal edge.
-    /// Analogous for the second member of the pair.
+    /// 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.
     ///
-    /// For the fullest description, see typedefs at the beginning
-    /// of this file.
-    std::pair<Utils::cachedvector<EdgeCollection>, Utils::cachedvector<EdgeCollection> > _binHashSparse;
+    /// @todo Replace with a more specialised class or a fixed array?
+    std::vector<std::vector<DBN> > _outflows;
 
-    /// Low/high edges
-    double _highEdgeX, _highEdgeY, _lowEdgeX, _lowEdgeY;
+    /// Cached bin edges for searching
+    BinHash _binhash;
 
-    /// Flag to mark if this histogram has a grid structure or not
-    bool _isGrid;
+    //@}
 
   };
 
@@ -1166,7 +675,7 @@
     tmp -= second;
     return tmp;
   }
-  
+
   //@}
 
 

Modified: trunk/include/YODA/Bin1D.h
==============================================================================
--- trunk/include/YODA/Bin1D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/Bin1D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -33,30 +33,35 @@
     /// @name Constructors
     //@{
 
-    /// Init a new, empty bin with a pair of edges.
-    Bin1D(double lowedge, double highedge)
-      : _edges( std::make_pair(lowedge, highedge) )
-    {
-      assert( _edges.second > _edges.first );
-    }
+    // /// Make a new, empty bin with a pair of edges.
+    // Bin1D(double lowedge, double highedge)
+    //   : _edges( std::make_pair(lowedge, highedge) )
+    // {
+    //   if (_edges.second < _edges.first) {
+    //     throw RangeError("The bin edges are wrongly defined!");
+    //   }
+    // }
 
 
-    /// Init a new, empty bin with a pair of edges.
+    /// Make a new, empty bin with a pair of edges.
     Bin1D(const std::pair<double,double>& edges)
-      : _edges( edges )
+      : _edges(edges)
     {
-      assert( _edges.second >= _edges.first );
+      if (_edges.second < _edges.first) {
+        throw RangeError("The bin edges are wrongly defined!");
+      }
     }
 
 
-    /// @brief Init a bin with all the components of a fill history.
+    /// @brief Make a bin with all the components of a fill history.
     ///
     /// Mainly intended for internal persistency use.
-    Bin1D(double lowedge, double highedge, const DBN& dbn)
-      : _edges( std::make_pair(lowedge, highedge) ),
-        _dbn(dbn)
+    Bin1D(const std::pair<double,double>& edges, const DBN& dbn)
+      : _edges(edges), _dbn(dbn)
     {
-      assert( _edges.second >= _edges.first );
+      if (_edges.second < _edges.first) {
+        throw RangeError("The bin edges are wrongly defined!");
+      }
     }
 
 

Modified: trunk/include/YODA/Bin2D.h
==============================================================================
--- trunk/include/YODA/Bin2D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/Bin2D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -27,40 +27,64 @@
   class Bin2D : public Bin {
   public:
 
-    /// Convenience typedefs
-    typedef typename std::pair<double, double> Point;
-    typedef typename std::pair<Point, Point> Segment;
-
     /// @name Constructors
     //@{
 
-    /// Init a new, empty bin with a pair of edges.
-    Bin2D(double xMin, double yMin, double xMax, double yMax) {
-      if (xMin > xMax || yMin > yMax) {
-        throw RangeError("The bins are wrongly defined!");
+    // /// Make a new, empty bin with two pairs of edges.
+    // Bin2D(double xmin, double ymin, double xmax, double ymax)
+    //   : _xedges( std::make_pair(xmin, xmax) ),
+    //     _yedges( std::make_pair(ymin, ymax) )
+    // {
+    //   if (_xedges.second < _xedges.first) {
+    //     throw RangeError("The bin x-edges are wrongly defined!");
+    //   }
+    //   if (_yedges.second < _yedges.first) {
+    //     throw RangeError("The bin y-edges are wrongly defined!");
+    //   }
+    // }
+
+
+   /// Make a new, empty bin with two pairs of edges.
+    Bin2D(const std::pair<double, double>& xedges, const std::pair<double, double>& yedges)
+      : _xedges( xedges ), _yedges( yedges )
+    {
+      if (_xedges.second < _xedges.first) {
+        throw RangeError("The bin x-edges are wrongly defined!");
+      }
+      if (_yedges.second < _yedges.first) {
+        throw RangeError("The bin y-edges are wrongly defined!");
       }
-      _edges.first.first = xMin;
-      _edges.first.second = yMin;
-      _edges.second.first = xMax;
-      _edges.second.second = yMax;
     }
 
 
-    /// Init a new, empty bin with a pair of edges.
-    Bin2D(const Segment& edges) {
-      _edges = edges;
+    /// @brief Make a bin with all the components of a fill history.
+    ///
+    /// Mainly intended for internal persistency use.
+    Bin2D(const std::pair<double, double>& xedges,
+          const std::pair<double, double>& yedges, const DBN& dbn)
+      : _xedges(xedges), _yedges(yedges), _dbn(dbn)
+    {
+      if (_xedges.second < _xedges.first) {
+        throw RangeError("The bin x-edges are wrongly defined!");
+      }
+      if (_yedges.second < _yedges.first) {
+        throw RangeError("The bin y-edges are wrongly defined!");
+      }
     }
 
+
     /// Copy constructor
     Bin2D(const Bin2D<DBN>& b)
-      : _edges(b._edges),
+      : _xedges(b._xedges),
+        _yedges(b._yedges),
         _dbn(b._dbn)
     { }
 
 
     /// Copy assignment
     Bin2D<DBN>& operator = (const Bin2D<DBN>& b) {
-      _edges = b._edges;
+      _xedges = b._xedges;
+      _yedges = b._yedges;
       _dbn = b._dbn;
       return *this;
     }
@@ -83,11 +107,11 @@
 
     /// Scale the x and y coordinates and distributions.
     void scaleXY(double scaleX, double scaleY) {
-      _edges.first.first *= scaleX;
-      _edges.second.first *= scaleX;
+      _xedges.first *= scaleX;
+      _xedges.second *= scaleX;
 
-      _edges.first.second *= scaleY;
-      _edges.second.second *= scaleY;
+      _yedges.first *= scaleY;
+      _yedges.second *= scaleY;
 
       _dbn.scaleXY(scaleX, scaleY);
     }
@@ -102,7 +126,7 @@
 
     /// Lower x limit of the bin (inclusive).
     double lowEdgeX() const {
-      return _edges.first.first;
+      return _xedges.first;
     }
     /// Synonym for lowEdgeX()
     double xMin() const {
@@ -111,7 +135,7 @@
 
     /// Lower y limit of the bin (inclusive).
     double lowEdgeY() const {
-      return _edges.first.second;
+      return _yedges.first;
     }
     /// Synonym for lowEdgeY()
     double yMin() const {
@@ -120,7 +144,7 @@
 
     /// Upper x limit of the bin (exclusive).
     double highEdgeX() const {
-      return _edges.second.first;
+      return _xedges.second;
     }
     /// Synonym for highEdgeX()
     double xMax() const {
@@ -129,18 +153,13 @@
 
     /// Upper y limit of the bin (exclusive).
     double highEdgeY() const {
-      return _edges.second.second;
+      return _yedges.second;
     }
     /// Synonym for highEdgeY()
     double yMax() const {
       return highEdgeY();
     }
 
-    /// Get the {low,high} edges as an STL @c pair.
-    const Segment edges() const {
-      return _edges;
-    }
-
     /// Width of the bin in x
     double widthX() const {
       return xMax() - xMin();
@@ -152,7 +171,7 @@
     }
 
     /// The mean position in the bin, or the midpoint if that is not available.
-    Point focus() const {
+    std::pair<double, double> focus() const {
       if (!isZero(sumW())) {
         return std::make_pair(xMean(), yMean());
       } else {
@@ -161,7 +180,7 @@
     }
 
     /// Geometric centre of the bin, i.e. high+low/2.0
-    Point midpoint() const {
+    std::pair<double, double> midpoint() const {
       return std::make_pair((xMax() + xMin())/2, (yMax() + yMin())/2);
     }
 
@@ -309,7 +328,7 @@
     /// This operator is defined for adding two bins with equivalent binning.
     /// It cannot be used to merge two bins into one larger bin.
     Bin2D<DBN>& add(const Bin2D<DBN>& b) {
-      if (_edges != b._edges) {
+      if (_xedges != b._xedges || _yedges != b._yedges) {
         throw LogicError("Attempted to add two bins with different edges");
       }
       _dbn += b._dbn;
@@ -322,7 +341,7 @@
     /// This operator is defined for subtracting two bins with equivalent binning.
     /// It cannot be used to merge two bins into one larger bin.
     Bin2D<DBN>& subtract(const Bin2D<DBN>& b) {
-      if (_edges != b._edges) {
+      if (_xedges != b._xedges || _yedges != b._yedges) {
         throw LogicError("Attempted to add two bins with different edges");
       }
       _dbn -= b._dbn;
@@ -335,7 +354,8 @@
   protected:
 
     /// The bin limits
-    Segment _edges;
+    std::pair<double,double> _xedges;
+    std::pair<double,double> _yedges;
 
     // Distribution of weighted x (and perhaps y) values
     DBN _dbn;

Modified: trunk/include/YODA/Histo2D.h
==============================================================================
--- trunk/include/YODA/Histo2D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/Histo2D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -50,16 +50,6 @@
         _axis(nbinsX, lowerX, upperX, nbinsY, lowerY, upperY)
     { }
 
-    /// A default constructor. One needs to provide two points
-    /// (top-right and bottom-left) for each rectangular bin that
-    /// is created. It is assumed that the binedges vector is nonempty (why btw?).
-    /// @todo Drop the pairings -- it is more natural, less contrived, and cleaner in code as xlow/high and ylow/high
-    Histo2D(const std::vector<std::pair<std::pair<double,double>, std::pair<double,double> > >& binedges,
-            const std::string& path="",
-            const std::string& title="")
-      : AnalysisObject("Histo2D", path, title),
-      _axis(binedges)
-    { }
 
     /// Constructor accepting the bin edges on X and Y axis.
     Histo2D(const std::vector<double>& xedges, const std::vector<double>& yedges,
@@ -68,6 +58,7 @@
             _axis(xedges, yedges)
     { }
 
+
     /// Copy constructor with optional new path
     Histo2D(const Histo2D& h, const std::string& path="");
 
@@ -92,13 +83,11 @@
     /// @name Modifiers
     //@{
 
-    /// @brief Fill histo by value and weight
-    ///
-    /// It relies on Axis2D for searching procedures and complains loudly if no
-    /// bin was found.
-    int fill(double x, double y, double weight=1.0);
+    /// @brief Fill histo with weight at (x,y)
+    void fill(double x, double y, double weight=1.0);
 
     /// @brief Reset the histogram.
+    ///
     /// Keep the binning but set all bin contents and related quantities to zero
     void reset() {
       _axis.reset();
@@ -128,20 +117,23 @@
       _axis.scaleXY(scaleX, scaleY);
     }
 
-    /// Adding bins
-    void addBin(const std::vector<std::pair<std::pair<double,double>, std::pair<double,double> > > coords) {
-        _axis.addBin(coords);
-    }
-
-    /// Adding bins which is not so eloquent
-    void addBin(double lowX, double lowY, double highX, double highY)   {
-        _axis.addBin(lowX, lowY, highX, highY);
-    }
-
-    /// Merge the bins
-    void mergeBins(size_t from, size_t to) {
-      _axis.mergeBins(from, to);
-    }
+    // /// Adding bins
+    /// @todo TODO
+    // void addBin(const std::vector<std::pair<std::pair<double,double>, std::pair<double,double> > > coords) {
+    //     _axis.addBin(coords);
+    // }
+
+    // /// Adding bins which is not so eloquent
+    /// @todo TODO
+    // void addBin(double lowX, double lowY, double highX, double highY)   {
+    //     _axis.addBin(lowX, lowY, highX, highY);
+    // }
+
+    // /// Merge the bins
+    /// @todo TODO
+    // void mergeBins(size_t from, size_t to) {
+    //   _axis.mergeBins(from, to);
+    // }
 
     void eraseBin(size_t index) {
       _axis.eraseBin(index);
@@ -149,9 +141,10 @@
 
     /// Rebin the whole histo by a @a factorX in the X direction and
     /// @a factorY in the Y direction
-    void rebin(size_t factorX, size_t factorY){
-      _axis.rebin(factorX, factorY);
-    }
+    /// @todo TODO
+    // void rebin(size_t factorX, size_t factorY){
+    //   _axis.rebin(factorX, factorY);
+    // }
 
     //@}
 
@@ -355,31 +348,31 @@
     //@}
 
 
-    /// @name Slicing operators
-    //@{
-
-    /// @brief Create a Histo1D for the bin slice parallel to the x axis at the specified y coordinate
-    ///
-    /// Note that the created histogram will not have correctly filled underflow and overflow bins.
-    /// @todo It's not really *at* the specified y coord: it's for the corresponding bin row.
-    /// @todo Change the name!
-    Histo1D cutterX(double atY, const std::string& path="", const std::string& title="");
+    // /// @name Slicing operators
+    // //@{
 
-
-    /// @brief Create a Histo1D for the bin slice parallel to the y axis at the specified x coordinate
-    ///
-    /// Note that the created histogram will not have correctly filled underflow and overflow bins.
-    /// @todo It's not really *at* the specified x coord: it's for the corresponding bin row.
-    /// @todo Change the name!
-    Histo1D cutterY(double atX, const std::string& path="", const std::string& title="");
-
-
-    /// @brief X-wise Profile1D creator from Histo2D
-    Profile1D mkProfileX();
-
-    /// @brief Y-wise Profile1D creator from Histo2D
-    Profile1D mkProfileY();
-    //@}
+    // /// @brief Create a Histo1D for the bin slice parallel to the x axis at the specified y coordinate
+    // ///
+    // /// Note that the created histogram will not have correctly filled underflow and overflow bins.
+    // /// @todo It's not really *at* the specified y coord: it's for the corresponding bin row.
+    // /// @todo Change the name!
+    // Histo1D cutterX(double atY, const std::string& path="", const std::string& title="");
+
+
+    // /// @brief Create a Histo1D for the bin slice parallel to the y axis at the specified x coordinate
+    // ///
+    // /// Note that the created histogram will not have correctly filled underflow and overflow bins.
+    // /// @todo It's not really *at* the specified x coord: it's for the corresponding bin row.
+    // /// @todo Change the name!
+    // Histo1D cutterY(double atX, const std::string& path="", const std::string& title="");
+
+
+    // /// @brief X-wise Profile1D creator from Histo2D
+    // Profile1D mkProfileX();
+
+    // /// @brief Y-wise Profile1D creator from Histo2D
+    // Profile1D mkProfileY();
+    // //@}
 
 
 

Modified: trunk/include/YODA/HistoBin1D.h
==============================================================================
--- trunk/include/YODA/HistoBin1D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/HistoBin1D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -26,23 +26,23 @@
     /// @name Constructor giving bin low and high edges.
     //@{
 
-    /// Init a new, empty bin with a pair of edges.
+    /// Make a new, empty bin with a pair of edges.
     HistoBin1D(double lowedge, double highedge)
-      : Bin1D<Dbn1D>(lowedge, highedge)
+      : Bin1D<Dbn1D>(std::make_pair(lowedge, highedge))
     { }
 
 
-    /// Init a new, empty bin with a pair of edges.
+    /// Make a new, empty bin with a pair of edges.
     HistoBin1D(const std::pair<double,double>& edges)
       : Bin1D<Dbn1D>(edges)
     { }
 
 
-    /// @brief Init a bin with all the components of a fill history.
+    /// @brief Make a bin with all the components of a fill history.
     ///
     /// Mainly intended for internal persistency use.
-    HistoBin1D(double lowedge, double highedge, const Dbn1D& dbnx)
-      : Bin1D<Dbn1D>(lowedge, highedge, dbnx)
+    HistoBin1D(std::pair<double, double> edges, const Dbn1D& dbnx)
+      : Bin1D<Dbn1D>(edges, dbnx)
     { }
 
 

Modified: trunk/include/YODA/HistoBin2D.h
==============================================================================
--- trunk/include/YODA/HistoBin2D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/HistoBin2D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -23,22 +23,28 @@
     /// @name Constructors
     //@{
 
-    /// Constructor accepting a set of extremal points of a bin
-    HistoBin2D(double xMin, double xMax,
-               double yMin, double yMax)
-      : Bin2D<Dbn2D>(xMin, yMin, xMax, yMax)
+    /// Make a new, empty bin with two pairs of edges.
+    HistoBin2D(double xmin, double ymin, double xmax, double ymax)
+      : Bin2D<Dbn2D>(std::make_pair(xmin, ymin), std::make_pair(xmax, ymax))
     { }
 
     /// Constructor accepting a set of all edges of a bin
-    HistoBin2D(std::pair<std::pair<double,double>, std::pair<double,double> >& edges)
-      : Bin2D<Dbn2D>(edges)
-    { }
-
-
-    /// @todo Add copy constructor
-
-    //@}
-
+    HistoBin2D(const std::pair<double,double>& xedges, std::pair<double,double>& yedges)
+      : Bin2D<Dbn2D>(xedges, yedges)
+      { }
+
+    /// @brief Make a bin with all the components of a fill history.
+    ///
+    /// Mainly intended for internal persistency use.
+    HistoBin2D(const std::pair<double, double>& xedges,
+               const std::pair<double, double>& yedges, const Dbn2D& dbn)
+      : Bin2D<Dbn2D>(xedges, yedges, dbn)
+      { }
+
+    /// Copy constructor
+    HistoBin2D(const HistoBin2D& pb)
+      : Bin2D<Dbn2D>(pb)
+      { }
 
     /// @name Modifiers
     //@{
@@ -95,20 +101,20 @@
     /// @name Transformers
     //@{
 
-    /// @brief Transformer taking x as the primary axis of ProfileBin1D
-    /// @todo Need to think about the name, and clarify what "primary axis" means
-    ProfileBin1D transformX() {
-      ProfileBin1D ret(xMin(), xMax(), Dbn2D(_dbn));
-      return ret;
-    }
-
-    /// @brief Transformer taking y as the primary axis of ProfileBin1D
-    /// @todo Need to think about the name, and clarify what "primary axis" means
-    ProfileBin1D transformY() {
-      Dbn2D dbn = _dbn; dbn.flipXY();
-      ProfileBin1D ret(yMin(), yMax(), Dbn2D(dbn));
-      return ret;
-    }
+    // /// @brief Transformer taking x as the primary axis of ProfileBin1D
+    // /// @todo Need to think about the name, and clarify what "primary axis" means
+    // ProfileBin1D transformX() {
+    //   ProfileBin1D ret(std::make_pair(xMin(), xMax()), Dbn2D(_dbn));
+    //   return ret;
+    // }
+
+    // /// @brief Transformer taking y as the primary axis of ProfileBin1D
+    // /// @todo Need to think about the name, and clarify what "primary axis" means
+    // ProfileBin1D transformY() {
+    //   Dbn2D dbn = _dbn; dbn.flipXY();
+    //   ProfileBin1D ret(std::make_pair(yMin(), yMax()), Dbn2D(dbn));
+    //   return ret;
+    // }
 
     //@}
   };

Modified: trunk/include/YODA/ProfileBin1D.h
==============================================================================
--- trunk/include/YODA/ProfileBin1D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/ProfileBin1D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -28,7 +28,7 @@
 
     /// Constructor giving bin low and high edges.
     ProfileBin1D(double lowedge, double highedge)
-      : Bin1D<Dbn2D>(lowedge, highedge)
+      : Bin1D<Dbn2D>(std::make_pair(lowedge, highedge))
     { }
 
 
@@ -38,11 +38,11 @@
     { }
 
 
-    /// @brief Init a profile bin with all the components of a fill history.
+    /// @brief Make a profile bin with all the components of a fill history.
     ///
     /// Mainly intended for internal persistency use.
-    ProfileBin1D(double lowedge, double highedge, const Dbn2D& dbnxy)
-      : Bin1D<Dbn2D>(lowedge, highedge, dbnxy)
+    ProfileBin1D(std::pair<double, double> edges, const Dbn2D& dbnxy)
+      : Bin1D<Dbn2D>(edges, dbnxy)
     {  }
 
 

Modified: trunk/include/YODA/ProfileBin2D.h
==============================================================================
--- trunk/include/YODA/ProfileBin2D.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/ProfileBin2D.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -21,19 +21,22 @@
     /// @name Constructors
     //@{
 
-    /// Constructor giving lowedgesX/Y
-    ProfileBin2D(double lowX, double lowY, double highX, double highY)
-      : Bin2D<Dbn3D>(lowX, lowY, highX, highY)
+    /// Make a new, empty bin with two pairs of edges.
+    ProfileBin2D(double xmin, double ymin, double xmax, double ymax) {
+      : Bin2D<Dbn3D>(std::make_pair(xmin, ymin), std::make_pair(xmax, ymax))
     { }
 
-    ProfileBin2D(const std::pair<std::pair<double,double>,std::pair<double,double> >& edges)
-      : Bin2D<Dbn3D>(edges)
+    /// Constructor accepting a set of all edges of a bin
+    ProfileBin2D(const std::pair<double,double> xedges, std::pair<double,double>& yedges)
+      : Bin2D<Dbn3D>(xedges, yedges)
     { }
 
-    /// Unpersisting constructor
-    ProfileBin2D(double lowX, double lowY, double highX, double highY,
-                 const Dbn3D& dbnxyz)
-      : Bin2D<Dbn3D>(lowX, lowY, highX, highY)
+    /// @brief Make a bin with all the components of a fill history.
+    ///
+    /// Mainly intended for internal persistency use.
+    ProfileBin2D(const std::pair<double, double>& xedges,
+                 const std::pair<double, double>& yedges, const Dbn3D& dbn)
+      : Bin2D<Dbn3D>(xedges, yedges, dbn)
     { }
 
     /// Copy constructor

Modified: trunk/include/YODA/ReaderYODA.h
==============================================================================
--- trunk/include/YODA/ReaderYODA.h	Fri May  4 11:03:33 2012	(r469)
+++ trunk/include/YODA/ReaderYODA.h	Fri Jun 15 19:25:00 2012	(r470)
@@ -188,11 +188,11 @@
     /// Filling a bin
     struct fillbin {
       void operator()(const histo1dbin b, qi::unused_type, qi::unused_type) const {
-        YODA::HistoBin1D bin(b.lowedge, b.highedge, YODA::Dbn1D(b.dbn.numFills, b.dbn.sumW, b.dbn.sumW2, b.dbn.sumWX, b.dbn.sumWX2));
+        YODA::HistoBin1D bin(std::make_pair(b.lowedge, b.highedge), YODA::Dbn1D(b.dbn.numFills, b.dbn.sumW, b.dbn.sumW2, b.dbn.sumWX, b.dbn.sumWX2));
         _histo1d.bins.push_back(bin);
       }
       void operator()(const profile1dbin b, qi::unused_type, qi::unused_type) const {
-        YODA::ProfileBin1D bin(b.lowedge, b.highedge, YODA::Dbn2D(b.dbn.numFills, b.dbn.sumW, b.dbn.sumW2, b.dbn.sumWX, b.dbn.sumWX2, b.dbn.sumWY, b.dbn.sumWY2, 0.0));
+        YODA::ProfileBin1D bin(std::make_pair(b.lowedge, b.highedge), YODA::Dbn2D(b.dbn.numFills, b.dbn.sumW, b.dbn.sumW2, b.dbn.sumWX, b.dbn.sumWX2, b.dbn.sumWY, b.dbn.sumWY2, 0.0));
         _profile1d.bins.push_back(bin);
       }
     };
@@ -211,7 +211,7 @@
     struct fillkeyval {
       void operator()(const keyval m, qi::unused_type, qi::unused_type) const {
         _annotations[m.key] = m.val;
-      } 
+      }
     };
 
 

Modified: trunk/src/Histo2D.cc
==============================================================================
--- trunk/src/Histo2D.cc	Fri May  4 11:03:33 2012	(r469)
+++ trunk/src/Histo2D.cc	Fri Jun 15 19:25:00 2012	(r470)
@@ -4,7 +4,6 @@
 // Copyright (C) 2008-2012 The YODA collaboration (see AUTHORS for details)
 //
 #include "YODA/Histo2D.h"
-#include "YODA/ProfileBin2D.h"
 #include "YODA/Scatter3D.h"
 #include <cmath>
 using namespace std;
@@ -18,8 +17,9 @@
   { }
 
 
-  int Histo2D::fill(double x, double y, double weight) {
-    return _axis.fill(x, y, weight);
+  void Histo2D::fill(double x, double y, double weight) {
+    /// @todo TODO, incl. overflows
+    // return _axis.fill(x, y, weight);
   }
 
 
@@ -87,135 +87,133 @@
   }
 
 
-    Histo1D Histo2D::cutterX(double atY, const std::string& path, const std::string& title) {
-      if (!_axis.isGrid()) throw GridError("Attempt to cut a Histo2D that is not a grid!");
+  // Histo1D Histo2D::cutterX(double atY, const std::string& path, const std::string& title) {
+  //   if (!_axis.isGrid()) throw GridError("Attempt to cut a Histo2D that is not a grid!");
 
-      if (atY < lowEdgeY() || atY > highEdgeY()) throw RangeError("Y is outside the grid");
-      vector<HistoBin1D> tempBins;
+  //   if (atY < lowEdgeY() || atY > highEdgeY()) throw RangeError("Y is outside the grid");
+  //   vector<HistoBin1D> tempBins;
 
-      for (double i = binByCoord(lowEdgeX(), atY).xMin(); i < highEdgeX(); i += binByCoord(i, atY).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));
-      }
-
-      /// Setting under/over flows
-      Dbn2D underflow;
-      underflow += _axis.outflows()[7][_axis.getBinRow(_axis.getBinIndex(lowEdgeX(), atY))];
+  //   for (double i = binByCoord(lowEdgeX(), atY).xMin(); i < highEdgeX(); i += binByCoord(i, atY).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));
+  //   }
+
+  //   /// Setting under/over flows
+  //   Dbn2D underflow;
+  //   underflow += _axis.outflows()[7][_axis.getBinRow(_axis.getBinIndex(lowEdgeX(), atY))];
+
+  //   Dbn2D overflow;
+  //   overflow += _axis.outflows()[3][_axis.getBinRow(_axis.getBinIndex(lowEdgeX(), atY))];
+
+  //   return Histo1D(tempBins, _axis.totalDbn().transformX(), underflow.transformX(), overflow.transformX(), path, title);
+
+  // }
+
+
+  // Histo1D Histo2D::cutterY(double atX, const std::string& path, const std::string& title) {
+  //   if (!_axis.isGrid()) throw GridError("Attempt to cut a Histo2D that is not a grid!");
+
+  //   if (atX < lowEdgeX() || atX > highEdgeX()) throw RangeError("X is outside the grid");
+  //   vector<HistoBin1D> tempBins;
+
+  //   for (double i = binByCoord(atX, lowEdgeY()).yMin(); i < highEdgeY(); i += binByCoord(atX, i).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));
+  //   }
+
+  //   // Setting under/over flows
+  //   Dbn2D underflow;
+  //   underflow += _axis.outflows()[1][_axis.getBinColumn(_axis.getBinIndex(atX, lowEdgeY()))];
+
+  //   Dbn2D overflow;
+  //   overflow += _axis.outflows()[5][_axis.getBinColumn(_axis.getBinIndex(atX, lowEdgeY()))];
+  //   Dbn2D total = _axis.totalDbn();
+
+  //   // Making sure that we rotate our distributions, as we are cutting parallel to Y axis now
+  //   total.flipXY();
+  //   underflow.flipXY();
+  //   overflow.flipXY();
+
+  //   return Histo1D(tempBins, total.transformX(), underflow.transformX(), overflow.transformX(), path, title);
+  // }
+
+
+  // Profile1D Histo2D::mkProfileX() {
+  //   if (!_axis.isGrid()) throw GridError("Profile1D cannot be made from a histogram that is not a grid!");
+
+  //   vector<ProfileBin1D> prof;
+  //   for(int i = lowEdgeX() + _axis.bin(0).midpoint().first; i < highEdgeX(); i+= _axis.bin(0).widthX()) {
+  //     HistoBin2D& bin(_axis.binByCoord(i, lowEdgeY()));
+  //     HistoBin2D composite(bin.xMin(), bin.xMax(), bin.yMin(), bin.yMax()) ;
+  //     for(int j = lowEdgeY() + _axis.bin(0).midpoint().second; j < highEdgeY(); j += _axis.bin(0).widthY()) {
+  //       composite += _axis.binByCoord(i, j);
+  //     }
+  //     prof.push_back(composite.transformX());
+  //   }
+
+  //   vector<vector<Dbn2D> >& outflows = _axis.outflows();
+
+  //   /// Properly setting an underflow
+  //   Dbn2D underflow;
+  //   underflow += outflows[0][0]; underflow += outflows[6][0];
+  //   for(size_t i = 0; i < outflows[7].size(); ++i) {
+  //     underflow += outflows[7][i];
+  //   }
+
+  //   /// Setting an overflow
+  //   Dbn2D overflow;
+  //   overflow += outflows[2][0]; overflow += outflows[4][0];
+  //   for(size_t i = 0; i < outflows[3].size(); ++i) {
+  //     overflow += outflows[3][i];
+  //   }
+
+  //   /// And constructing a profile 1D from all this data
+  //   Profile1D ret(prof, _axis.totalDbn(), underflow, overflow);
+  //   return ret;
+
+  // }
+
+  // Profile1D Histo2D::mkProfileY() {
+  //   if (!_axis.isGrid()) throw GridError("Profile1D cannot be made from a histogram that is not a grid!");
+
+  //   vector<ProfileBin1D> prof;
+  //   for(int i = lowEdgeY() + _axis.bin(0).midpoint().second; i < highEdgeY(); i+= _axis.bin(0).widthY()) {
+  //     HistoBin2D& bin(_axis.binByCoord(i, lowEdgeY()));
+  //     HistoBin2D composite(bin.xMin(), bin.xMax(), bin.yMin(), bin.yMax()) ;
+  //     for(int j = lowEdgeX() + _axis.bin(0).midpoint().first; j < highEdgeX(); j += _axis.bin(0).widthX()) {
+  //       composite += _axis.binByCoord(i, j);
+  //     }
+  //     prof.push_back(composite.transformY());
+  //   }
+
+  //   vector<vector<Dbn2D> >& outflows = _axis.outflows();
+
+  //   /// Properly setting an underflow
+  //   Dbn2D underflow;
+  //   underflow += outflows[0][0]; underflow += outflows[2][0];
+  //   for(size_t i = 0; i < outflows[1].size(); ++i) {
+  //     underflow += outflows[1][i];
+  //   }
+
+  //   /// Setting an overflow
+  //   Dbn2D overflow;
+  //   overflow += outflows[6][0]; overflow += outflows[4][0];
+  //   for(size_t i = 0; i < outflows[5].size(); ++i) {
+  //     overflow += outflows[5][i];
+  //   }
+
+  //   /// Setting a flipped total distribution
+  //   Dbn2D td = _axis.totalDbn();
+  //   td.flipXY();
+
+  //   /// And constructing a profile 1D from all this data
+  //   Profile1D ret(prof, td, underflow, overflow);
+  //   return ret;
+  // }
 
-      Dbn2D overflow;
-      overflow += _axis.outflows()[3][_axis.getBinRow(_axis.getBinIndex(lowEdgeX(), atY))];
 
-      return Histo1D(tempBins, _axis.totalDbn().transformX(), underflow.transformX(), overflow.transformX(), path, title);
-
-    }
-
-
-    Histo1D Histo2D::cutterY(double atX, const std::string& path, const std::string& title) {
-      if (!_axis.isGrid()) throw GridError("Attempt to cut a Histo2D that is not a grid!");
-
-      if (atX < lowEdgeX() || atX > highEdgeX()) throw RangeError("X is outside the grid");
-      vector<HistoBin1D> tempBins;
-
-      for (double i = binByCoord(atX, lowEdgeY()).yMin(); i < highEdgeY(); i += binByCoord(atX, i).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));
-      }
-
-      // Setting under/over flows
-      Dbn2D underflow;
-      underflow += _axis.outflows()[1][_axis.getBinColumn(_axis.getBinIndex(atX, lowEdgeY()))];
-
-      Dbn2D overflow;
-      overflow += _axis.outflows()[5][_axis.getBinColumn(_axis.getBinIndex(atX, lowEdgeY()))];
-      Dbn2D total = _axis.totalDbn();
-
-      // Making sure that we rotate our distributions, as we are cutting parallel to Y axis now
-      total.flipXY();
-      underflow.flipXY();
-      overflow.flipXY();
-
-      return Histo1D(tempBins, total.transformX(), underflow.transformX(), overflow.transformX(), path, title);
-    }
-
-
-    Profile1D Histo2D::mkProfileX() {
-      if (!_axis.isGrid()) throw GridError("Profile1D cannot be made from a histogram that is not a grid!");
-
-      vector<ProfileBin1D> prof;
-      for(int i = lowEdgeX() + _axis.bin(0).midpoint().first; i < highEdgeX(); i+= _axis.bin(0).widthX()) {
-        HistoBin2D& bin(_axis.binByCoord(i, lowEdgeY()));
-        HistoBin2D composite(bin.xMin(), bin.xMax(), bin.yMin(), bin.yMax()) ;
-        for(int j = lowEdgeY() + _axis.bin(0).midpoint().second; j < highEdgeY(); j += _axis.bin(0).widthY()) {
-          composite += _axis.binByCoord(i, j);
-        }
-      prof.push_back(composite.transformX());
-      }
-
-      vector<vector<Dbn2D> >& outflows = _axis.outflows();
-
-      /// Properly setting an underflow
-      Dbn2D underflow;
-      underflow += outflows[0][0]; underflow += outflows[6][0];
-      for(size_t i = 0; i < outflows[7].size(); ++i) {
-        underflow += outflows[7][i];
-      }
-
-      /// Setting an overflow
-      Dbn2D overflow;
-      overflow += outflows[2][0]; overflow += outflows[4][0];
-      for(size_t i = 0; i < outflows[3].size(); ++i) {
-        overflow += outflows[3][i];
-      }
-
-      /// And constructing a profile 1D from all this data
-      Profile1D ret(prof, _axis.totalDbn(), underflow, overflow);
-      return ret;
-
-    }
-
-    Profile1D Histo2D::mkProfileY() {
-      if (!_axis.isGrid()) throw GridError("Profile1D cannot be made from a histogram that is not a grid!");
-
-      vector<ProfileBin1D> prof;
-      for(int i = lowEdgeY() + _axis.bin(0).midpoint().second; i < highEdgeY(); i+= _axis.bin(0).widthY()) {
-        HistoBin2D& bin(_axis.binByCoord(i, lowEdgeY()));
-        HistoBin2D composite(bin.xMin(), bin.xMax(), bin.yMin(), bin.yMax()) ;
-        for(int j = lowEdgeX() + _axis.bin(0).midpoint().first; j < highEdgeX(); j += _axis.bin(0).widthX()) {
-          composite += _axis.binByCoord(i, j);
-        }
-      prof.push_back(composite.transformY());
-      }
-
-      vector<vector<Dbn2D> >& outflows = _axis.outflows();
-
-      /// Properly setting an underflow
-      Dbn2D underflow;
-      underflow += outflows[0][0]; underflow += outflows[2][0];
-      for(size_t i = 0; i < outflows[1].size(); ++i) {
-        underflow += outflows[1][i];
-      }
-
-      /// Setting an overflow
-      Dbn2D overflow;
-      overflow += outflows[6][0]; overflow += outflows[4][0];
-      for(size_t i = 0; i < outflows[5].size(); ++i) {
-        overflow += outflows[5][i];
-      }
-
-      /// Setting a flipped total distribution
-      Dbn2D td = _axis.totalDbn();
-      td.flipXY();
-
-      /// And constructing a profile 1D from all this data
-      Profile1D ret(prof, td, underflow, overflow);
-      return ret;
-    }
-
-
-  /// @todo Check how finding the correct bins works in the case of
-  /// a sparse representation, and if it is decent, code it in here.
   Scatter3D divide(const Histo2D& numer, const Histo2D& denom) {
     if (numer != denom) throw GridError("The two histos are not equivalently binned!");
     Scatter3D tmp;

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	Fri May  4 11:03:33 2012	(r469)
+++ trunk/src/Makefile.am	Fri Jun 15 19:25:00 2012	(r470)
@@ -13,9 +13,8 @@
     WriterYODA.cc \
     Reader.cc \
     ReaderAIDA.cc \
-    ReaderYODA.cc
-
-#    Histo2D.cc \
+    ReaderYODA.cc \
+    Histo2D.cc
 #    Profile2D.cc \
 #    Scatter3D.cc
 


More information about the yoda-svn mailing list