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

blackhole at projects.hepforge.org blackhole at projects.hepforge.org
Sat Aug 6 21:04:31 BST 2011


Author: mkawalec
Date: Sat Aug  6 13:04:59 2011
New Revision: 222

Log:
Added a lot of comments and fixed binary search.

Modified:
   trunk/include/YODA/Axis2D.h
   trunk/include/YODA/Bin1D.h
   trunk/include/YODA/Bin2D.h
   trunk/include/YODA/Dbn1D.h
   trunk/include/YODA/Dbn2D.h
   trunk/include/YODA/Exceptions.h
   trunk/include/YODA/Histo2D.h
   trunk/include/YODA/HistoBin1D.h
   trunk/src/Bin1D.cc
   trunk/src/Bin2D.cc
   trunk/src/Dbn1D.cc
   trunk/src/Histo2D.cc
   trunk/src/HistoBin1D.cc

Modified: trunk/include/YODA/Axis2D.h
==============================================================================
--- trunk/include/YODA/Axis2D.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/Axis2D.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -15,97 +15,140 @@
 
 using namespace std;
 
-// A big number for the low/high search:
+/// A big number for the low/high search:
 /// @todo This isn't good enough! Why would this be guaranteed to be
 /// larger than the axis scale? Use e.g. std::limits<double> and/or determine
 /// the true extent when booking.
 /// @todo Also, the code convention is that _foo is a private member variable/function:
 /// for constants use all-caps, e.g. LARGENUM.
-const double _largeNum = 10000000000000.0;
+const double _largeNum = 1000000000000000000000.0;
+
 
 namespace YODA {
     template <typename BIN>
     class Axis2D {
     public:
-
+        
+        /// A collection of helpful typedefs
         typedef BIN Bin;
         typedef typename std::vector<BIN> Bins;
+        typedef typename std::pair<size_t, std::pair<double,double> > Edge;
+        typedef typename std::pair<double, std::vector<Edge> > EdgeCollection;
+        typedef typename std::pair<double, double> Point;
+        typedef typename std::pair<Point, Point> Segment;
 
     private:
 
-        /// Edge validator
-        /** Checks if an edge is vertical or horisontal and launches
-          * an appropriate checking function
+        /// @brief Segment validator function
+        /** 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 paralellize the program, if required.
           */
-        bool _validateEdge(vector<pair<pair<double,double>, pair<double,double> > >& edges) {
+        bool _validateEdge(vector<Segment>& edges)         
+        {
+            /// Setting the return variable. True means that no cuts were detected.
             bool ret = true;
+
+            /// Looping over all the edges provided
             for(unsigned int i=0; i < edges.size(); i++) {
+                /** 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(edges[i].first.first, edges[i].second.first)) ret =  _findCutsY(edges[i]);
+                
+                /// Check if the segment is horizontal and is it cutting any bin that already exists
                 else if(fuzzyEquals(edges[i].first.second, edges[i].second.second)) ret =  _findCutsX(edges[i]);
+                
+                /** This is a check that discards the bin if it is not a rectangle
+                  * composed of vertical and horizontal segments. 
+                  */
                 else ret = false;
-
+                
+                /** If a cut was detected, say it. There is no point in checking other edges
+                  * in the set.
+                  */
                 if(!ret) return false;
             }
+            /// If no cuts were detected in any of the edges, tell the launching function about this
             return true;
         }
-
-        /// Inclusion validator
-        /** An uncompleted function that checks if there exist a group of bins
-          * included in each other. It will be invoked before adding two Axises2D
-          */
-        bool _validateInclusion(pair<Utils::cachedvector<pair<double,vector<pair<size_t, pair<double,double> > > > >, Utils::cachedvector<pair<double,std::vector<pair<size_t, pair<double,double> > > > > >& edges) {
-            /// Making sure that the cache we will be using soon is correct and actual:
-            edges.first.regenCache();
-            edges.second.regenCache();
-
-            /// Now, checking if any of the edges is cutting any other:
-            for(unsigned int i=0; i < edges.first.size(); i++) {
-                for(unsigned int j = 0; j < edges.first[i].second.size(); j++) {
-                    size_t startX = edges.second._cache.lower_bound(approx(edges.first[i].second[j].second.first));
-                    size_t endX = edges.second._cache.upper_bound(edges.first[i].second[j].second.second);
-                    for(int p = startX; p < endX; p++) {
-                        if(edges.first[i].first > edges.second[i].second[p].second.first &&
-                           edges.first[i].first < edges.second[i].second[p].second.second){
-                            return false;
-                        }
-                    }
-                }
-            }
-
-            //TODO: Check inclusion
-        }
-
-        /// @name Binary search functions
-        //@{
-        /** I am exploiting the fact that we are operating on
-          * a sorted vector all the time. Therefore employing
-          * binary search to find the lower bound seems to be
-          * a logical step.
+        
+        /// @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.
           */
-        size_t _binaryS(Utils::cachedvector<pair<double, vector<pair<size_t, pair<double,double> > > > >& toSearch, double value, size_t lower, size_t higher) {
+        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);
             }
-            if(where == 0) return where;
+
+            /** This is not a redundant check, because
+              * of the nature of int division.
+              */
+            if (where == 0) return where;
+
+            /** Check if the value is somewhere inbetween
+              * 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);
         }
-        //@}
-        /// Function checking the cuts of horizontal segments
-        /** It searches for edges such that they may cut the edge in question and
-          * then checks if a cut indeed occurs.
+        
+        /// @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.
           */
-        bool _findCutsX(pair<pair<double,double>, pair<double,double> >& edge) {
+        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++) {
 
+            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(unsigned int 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) &&
@@ -114,11 +157,15 @@
                         }
                     }
                 }
+            /// If none of the existing edges is cutting this edge, announce it
             return true;
         }
 
-        /// Checking the cuts of vertical segments
-        bool _findCutsY(pair<pair<double,double>, pair<double,double> >& edge) {
+        /// @brief Function that finds cuts of vertical edges
+        /** For a detailed descpription, please look into
+          * documentation for _findCutsX().
+          */
+        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++) {
@@ -135,35 +182,76 @@
             return true;
         }
 
-        /// What to execute when an edge is dropped.
-        void _dropEdge(vector<pair<pair<double,double>, pair<double,double> > >& edges) {
-            std::cerr << "A set of edges was dropped. No additional information is implemented yet, so none can be given. Have a good day." << endl;
+        /// @brief Function executed when a set of edges is dropped.
+        /** It does not have any information about which edge in the set
+          * had failed the check. If this is needed such additional information
+          * can be readily implemented.
+          */
+        void _dropEdge(vector<Segment>& edges) {
+            std::cerr << "A set of edges was dropped." << endl;
         }
 
-        /// Function that adds an edge after it was verified by _validateEdge()
-        void _addEdge(vector<pair<pair<double,double>, pair<double,double> > >& edges) {
+        /// @brief Bin adder.
+        /** It contains all the commands that need to executed
+          * to properly add a bin. Specifially edges are added to 
+          * the edge cache (_binHashSparse) and a bin is created from
+          * those edges.
+          */
+        void _addEdge(vector<Segment>& edges) {
+            /// Check if there was no mistake made when adding segments to a vector.
+            if(edges.size() != 4) throw Exception("The segments supplied don't describe a full bin!");
+
+            /** This is the part in charge of adding each of the segments
+              * to the edge cache. Segments are assumed to be validated 
+              * beforehand.
+              */
             for(unsigned int j=0; j < edges.size(); j++) {
-                pair<pair<double,double>, pair<double,double> > edge = edges[j];
+                /// Association made for convinience.
+                Segment edge = edges[j];
+
+                /** 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(_binHashSparse.second, edge.first.first, 0, _binHashSparse.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 sement.
+                      */
                     for(; i < _binHashSparse.second.size() && i < end ; i++) {
-                    if(fuzzyEquals(_binHashSparse.second[i].first, edge.first.first)) {
-                        _binHashSparse.second[i].second.push_back(
-                            make_pair(_bins.size(),make_pair(edge.first.second, edge.second.second)));
-                        found = true;
+                        /// If this is the case, do what is needed to be done.
+                        if(fuzzyEquals(_binHashSparse.second[i].first, edge.first.first)) {
+                            _binHashSparse.second[i].second.push_back(make_pair(_bins.size(),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) {
-                        vector<pair<size_t, pair<double,double> > > temp;
+                        vector<Edge> temp;
                         temp.push_back(make_pair(_bins.size(), make_pair(edge.first.second, edge.second.second)));
                         _binHashSparse.second.push_back(make_pair(edge.first.first,temp));
                         sort(_binHashSparse.second.begin(), _binHashSparse.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(_binHashSparse.first, edge.first.second, 0, _binHashSparse.first.size())-1;
@@ -171,26 +259,28 @@
                     size_t end = i+3;
                     for(; i < _binHashSparse.first.size() && i < end; i++) {
                         if(fuzzyEquals(_binHashSparse.first[i].first, edge.first.second)) {
-                            _binHashSparse.first[i].second.push_back(
-                                make_pair(_bins.size(),make_pair(edge.first.first, edge.second.first)));
+                            _binHashSparse.first[i].second.push_back(make_pair(_bins.size(),make_pair(edge.first.first, edge.second.first)));
                             found = true;
                         }
                     }
                     if(!found) {
-                        vector<pair<size_t, pair<double,double> > > temp;
+                        vector<Edge> temp;
                         temp.push_back(make_pair(_bins.size(), make_pair(edge.first.first, edge.second.first)));
                         _binHashSparse.first.push_back(make_pair(edge.second.second, temp));
                         sort(_binHashSparse.first.begin(), _binHashSparse.first.end());
                     }
                 }
             }
+            /// Now, create a bin with the edges provided
             _bins.push_back(BIN(edges));
         }
 
-        /** This funcion looks on the orientation of an edge and
-         * if it is incorrect, returns the correct orientation.
-         */
-        void _fixOrientation(pair<pair<double,double>, pair<double,double> >& edge) {
+        /// @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;
@@ -204,51 +294,69 @@
                 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 vector<Segment>& binLimits) {
+            
+            /// For each of the rectangles
+            for(unsigned int i=0; i < binLimits.size(); i++) {
+                /// Produce the segments that a rectangle is composed of
+                Segment edge1 =
+                    make_pair(binLimits[i].first,
+                              make_pair(binLimits[i].first.first, binLimits[i].second.second));
+                Segment edge2 =
+                    make_pair(make_pair(binLimits[i].first.first, binLimits[i].second.second),
+                              binLimits[i].second);
+                Segment edge3 =
+                    make_pair(make_pair(binLimits[i].second.first, binLimits[i].first.second),
+                              binLimits[i].second);
+                Segment edge4 =
+                    make_pair(binLimits[i].first,
+                              make_pair(binLimits[i].second.first, binLimits[i].first.second));
 
-        /// A function if charge of adding the edges.
-        void _mkAxis(const vector<pair<pair<double,double>,pair<double,double> > >& binedges) {
-            for(unsigned int i=0; i < binedges.size(); i++) {
-                pair<pair<double,double>, pair<double,double> > edge1 =
-                    make_pair(binedges[i].first,
-                              make_pair(binedges[i].first.first, binedges[i].second.second));
-                pair<pair<double,double>, pair<double,double> > edge2 =
-                    make_pair(make_pair(binedges[i].first.first, binedges[i].second.second),
-                              binedges[i].second);
-                pair<pair<double,double>, pair<double,double> > edge3 =
-                    make_pair(make_pair(binedges[i].second.first, binedges[i].first.second),
-                              binedges[i].second);
-                pair<pair<double,double>, pair<double,double> > edge4 =
-                    make_pair(binedges[i].first,
-                              make_pair(binedges[i].second.first, binedges[i].first.second));
-
+                /// Check if they are made properly
                 _fixOrientation(edge1); _fixOrientation(edge2);
                 _fixOrientation(edge3); _fixOrientation(edge4);
 
-                vector<pair<pair<double,double>, pair<double,double> > > edges;
+                /// Add all the segments to a vector
+                vector<Segment> edges;
                 edges.push_back(edge1); edges.push_back(edge2);
                 edges.push_back(edge3); edges.push_back(edge4);
 
-                //TODO: the _dropEdge() part should be moved into _addEdge() function and indicate which edge
-                //      is the conflicting one, not dropping the whole edgeset, as it is doing now. Same in addBins.
+                /// And check if a bin is a proper one, if it is, add it.
                 if(_validateEdge(edges))  _addEdge(edges);
                 else _dropEdge(edges);
 
             }
 
-
-            //Setting all the caches
+            /// Setting all the caches
             _binHashSparse.first.regenCache();
             _binHashSparse.second.regenCache();
             _regenDelimiters();
         }
 
-        /// Generating the extrema of the graph.
+        /// @brief Plot extrema (re)generator.
+        /** Since scrolling through every bin is an expensive 
+          * operation to do every time we need the limits of 
+          * the plot, there are caches set up. This function
+          * regenerates them. It should be run after any change is made 
+          * to bin layout.
+          */
         void _regenDelimiters() {
             double highEdgeX = -_largeNum;
             double highEdgeY = -_largeNum;
             double lowEdgeX = _largeNum;
             double lowEdgeY = _largeNum;
-
+            
+            /// Scroll through the bins and set the delimiters.
             for(unsigned int i=0; i < _bins.size(); i++) {
                 if(_bins[i].xMin() < lowEdgeX) lowEdgeX = _bins[i].xMin();
                 if(_bins[i].xMax() > highEdgeX) highEdgeX = _bins[i].xMax();
@@ -266,46 +374,58 @@
         /// @name Constructors:
         //@{
 
-        /// Empty constructor:
+        /// @brief Empty constructor
+        /** Only added because it is required by SWIG. 
+          * It doesn't make much sense to use it.
+          */
         Axis2D() {
-            vector<pair<pair<double,double>, pair<double,double> > > edges;
+            vector<Segment> edges;
             _mkAxis(edges);
         }
-
-        ///Default constructor
-        Axis2D(const vector<pair<pair<double,double>, pair<double,double> > >& binedges) {
-            _mkAxis(binedges);
+        
+        /// Constructor provided with a vector of bin delimiters
+        Axis2D(const vector<Segment>& binLimits) {
+            _mkAxis(binLimits);
         }
 
         ///Most standard constructor, should be self-explanatory
         Axis2D(size_t nbinsX, double lowerX, double upperX, size_t nbinsY, double lowerY, double upperY) {
-            vector<pair<pair<double,double>, pair<double,double> > > edges;
+            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) {
-                    edges.push_back(make_pair(make_pair(i, j),
+                    binLimits.push_back(make_pair(make_pair(i, j),
                                               make_pair((double)(i+coeffX), (double)(j+coeffY))));
                 }
             }
-            _mkAxis(edges);
+            _mkAxis(binLimits);
         }
         //@}
 
         /// @name Addition operators:
         //@{
-        /** This is a bin addition operator. It is given a set of boindary points (bottom-left
-         * and top-right) that uniquely determine a bin and it adds a set of bins basing on that.
-         * Please, try to include as many bins as possible in one call, as regenCache() is too
-         * computationaly expensive to be called for each single bin in a series.
-         */
-        void addBin(const vector<pair<pair<double,double>, pair<double,double> > >& vertexCoords) {
-            _mkAxis(vertexCoords);
+        
+        /// @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. 
+          * No merging is supported, and I don't think it should before the support
+          * for merging for '+' operator (codewise it should be the same thing).
+          */
+        void addBin(const vector<Segment>& binLimits) {
+            _mkAxis(binLimits);
         }
-
+        
+        /// @brief Bin addition operator
+        /** This operator is supplied with whe extreamal coordinates of just
+          * one bin. It then launches the standard bin addition procedure.
+          */
         void addBin(double lowX, double lowY, double highX, double highY) {
-            vector<pair<pair<double,double>, pair<double,double> > > coords;
+            vector<Segment> coords;
             coords.push_back(make_pair(make_pair(lowX, lowY), make_pair(highX, highY)));
 
             addBin(coords);
@@ -315,13 +435,19 @@
         /// @name Some helper functions:
         //@{
 
-        /// Return a total number of bins in Histo
 
-        /// Checks if our bins form a grid.
-        /** Uses a very neat property of _binCacheSparse,
-          * namely that it will containg the same number of
-          * edges on inner sides and half the number on outer ones*/
+        /// @name 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 isGriddy() a very, very fast function.
+          */
         int isGriddy() {
+            
+            /** Check if the number of edges parallel to X axis
+              * is proper in every subcache.
+              */
             unsigned int sizeX = _binHashSparse.first[0].second.size();
             for(unsigned int i=1; i < _binHashSparse.first.size(); i++) {
                 if(i == _binHashSparse.first.size() - 1) {
@@ -333,6 +459,8 @@
                     return -1;
                 }
             }
+
+            /// Do the same for edges parallel to Y axis.
             unsigned int sizeY = _binHashSparse.second[0].second.size();
             for(unsigned int i=1; i < _binHashSparse.second.size(); i++) {
                 if(i!= _binHashSparse.second.size() - 1) {
@@ -342,10 +470,13 @@
                 }
                 else if(_binHashSparse.second[i].second.size() != sizeY) return -1;
             }
+
+            /// If everything is proper, announce it.
             return 0;
         }
 
 
+        /// Return a total number of bins in a Histo
         unsigned int numBinsTotal() const {
             return _bins.size();
         }
@@ -465,14 +596,14 @@
         }
 
         /// Get the binHash(non-const version)
-        std::pair<Utils::cachedvector<pair<double,std::vector<pair<size_t, pair<double,double> > > > >,
-                  Utils::cachedvector<pair<double,std::vector<pair<size_t, pair<double,double> > > > > > getHash() {
+        std::pair<Utils::cachedvector<EdgeCollection>, 
+                  Utils::cachedvector<EdgeCollection> > getHash() {
             return _binHashSparse;
         }
 
         /// Get the binHash(const version)
-        const std::pair<Utils::cachedvector<pair<double,std::vector<pair<size_t, pair<double,double> > > > >,
-                  Utils::cachedvector<pair<double,std::vector<pair<size_t, pair<double,double> > > > > > getHash() const {
+        const std::pair<Utils::cachedvector<EdgeCollection>,
+                  Utils::cachedvector<EdgeCollection > > getHash() const {
             return _binHashSparse;
         }
 
@@ -484,6 +615,10 @@
          *  found, ie. (coordX, coordY) is a point in empty space -1 is returned.
          */
         int findBinIndex(double coordX, double coordY) const {
+            /** It is need to apply this trick not to have a coordinate 
+              * pointing directly on the edge. Notice that this is lower that 
+              * fuzzyEquals() tolerance.
+              */
             coordX += 0.0000000001; coordY += 0.00000000001;
 
             size_t indexY = (*_binHashSparse.first._cache.lower_bound(approx(coordY))).second;
@@ -516,7 +651,12 @@
             for (size_t i=0; i<_bins.size(); i++) _bins[i].reset();
         }
 
-        /// Scales the axis in a given direction by a specified coefficient
+        /// @brief Axis scaler
+        /** Scales the axis with a given scale. If no scale is given, assumes 
+          * identity transform.
+          * 
+          * @todo Should a support for matrix transformations be added?
+          */
         void scale(double scaleX = 1.0, double scaleY = 1.0) {
             // Two loops are put on purpose, just to protect
             // against improper _binHashSparse
@@ -535,11 +675,11 @@
                 }
             }
 
+            /// Regenerate the bin edges cache.
             _binHashSparse.first.regenCache();
             _binHashSparse.second.regenCache();
 
-            // Now, as we have the map rescaled, we need to update the bins
-            // in their own structure in order to have high/low edges correct
+            /// Now, as we have the map rescaled, we need to update the bins
             for(unsigned int i=0; i < _bins.size(); i++) _bins[i].scale(scaleX, scaleY);
             _dbn.scale(scaleX, scaleY);
             _underflow.scale(scaleX, scaleY);
@@ -571,9 +711,9 @@
             return ! operator == (other);
         }
 
-        /// Addition operator
+        /// @brief Addition operator
         /** At this stage it is only possible to add two histograms with
-          * the same binnings. Compatible but not equal binning soon to come
+          * the same binnings. Compatible but not equal binning to come soon.
           */
         Axis2D<BIN>& operator += (const Axis2D<BIN>& toAdd) {
             if (*this != toAdd) {
@@ -615,14 +755,14 @@
         /// The total distribution
         Dbn2D _dbn;
 
-        /// Bin hash structure
+        /// @brief Bin hash structure
         /** 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.
           */
-        std::pair<Utils::cachedvector<pair<double,std::vector<pair<size_t, pair<double,double> > > > >,
-                  Utils::cachedvector<pair<double,std::vector<pair<size_t, pair<double,double> > > > > >
+        std::pair<Utils::cachedvector<EdgeCollection>,
+                  Utils::cachedvector<EdgeCollection> >
                   _binHashSparse;
 
         /// Low/High edges:
@@ -646,11 +786,6 @@
         return tmp;
     }
 
-    /// Less-than operator
-    inline bool operator < (const pair<vector<double>, vector<double> >& a, const pair<vector<double>, vector<double> >& b) {
-        if(a.first == b.first) return a.second < b.second;
-        return a.first < b.first;
-    }
 
 }
 

Modified: trunk/include/YODA/Bin1D.h
==============================================================================
--- trunk/include/YODA/Bin1D.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/Bin1D.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -26,6 +26,10 @@
 
     Bin1D(std::pair<double,double> edges);
 
+    /// A constructor for cutting along a given axis:
+    Bin1D(double lowedge, double highedge, unsigned long numFills, 
+          double sumW, double sumW2, double sumWX, double sumWX2);
+
     //@}
 
 
@@ -113,13 +117,6 @@
 
     //@}
 
-    /// Setters
-    void setW(double sumW);
-    void setW2(double sumW2);
-    void setWX(double sumWX);
-    void setWX2(double sumWX2);
-    void setNumFills(double numFills);
-
   public:
 
 

Modified: trunk/include/YODA/Bin2D.h
==============================================================================
--- trunk/include/YODA/Bin2D.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/Bin2D.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -3,7 +3,6 @@
 
 #include "YODA/Bin.h"
 #include "YODA/Dbn2D.h"
-#include "YODA/HistoBin1D.h"
 #include <string>
 #include <utility>
 #include <vector>
@@ -84,24 +83,9 @@
         double sumWX2() const;
         double sumWY2() const;
 
-        /// Setters
-        void setW(double sumW);
-        void setW2(double sumW2);
-        void setWX(double sumWX);
-        void setWY(double sumWY);
-        void setWX2(double sumWX2);
-        void setWY2(double sumWY2);
-        void setWXY(double sumWXY);
-
         ///@name Transformers
         //@{
 
-        /// Transform, taking X coordinates as a bin width
-        HistoBin1D transformX();
-
-        /// Transform, taking Y coordinates as bin width
-        HistoBin1D transformY();
-
         /// Addition operators:
         Bin2D& operator += (const Bin2D&);
         Bin2D& operator -= (const Bin2D&);

Modified: trunk/include/YODA/Dbn1D.h
==============================================================================
--- trunk/include/YODA/Dbn1D.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/Dbn1D.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -21,6 +21,7 @@
   /// sampled distribution. It is used to provide this information in bins
   /// and for the "hidden" \f$ y \f$ distribution in profile histogram bins.
   class Dbn1D {
+  friend class Bin1D;
   public:
 
     /// Constructor.
@@ -28,7 +29,6 @@
       reset();
     }
 
-
     /// @name Modifiers
     //@{
 
@@ -115,14 +115,6 @@
 
     //@}
 
-    /// Setters
-    void setW(double sumW);
-    void setW2(double sumW2);
-    void setWX(double sumWX);
-    void setWX2(double sumWX2);
-    void setNumFills(double numFills);
-
-
   public:
 
     /// Add two dbns

Modified: trunk/include/YODA/Dbn2D.h
==============================================================================
--- trunk/include/YODA/Dbn2D.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/Dbn2D.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -37,16 +37,6 @@
             _sumWXY *= scaleX*scaleY;
         }
         
-        /// Setters
-        void setW(double sumW)      { _sumW = sumW;}
-        void setW2(double sumW2)    { _sumW2 = sumW2;}
-        void setWX(double sumWX)    { _sumWX = sumWX;}
-        void setWY(double sumWY)    { _sumWY = sumWY;}
-        void setWX2(double sumWX2)  { _sumWX2 = sumWX2;}
-        void setWY2(double sumWY2)  { _sumWY2 = sumWY2;}
-        void setWXY(double sumWXY)  { _sumWXY = sumWXY;}
-        void setNumfills(unsigned long numFills) {_numFills = numFills;}
-
         /// Some in-distribution variables. Should be self-evident.
         double xMean() const;
         double yMean() const;

Modified: trunk/include/YODA/Exceptions.h
==============================================================================
--- trunk/include/YODA/Exceptions.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/Exceptions.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -28,7 +28,7 @@
     RangeError(const std::string& what) : Exception(what) {}
   };
 
-  /// Error to throw when a slicing is requested on a non-slicable state of an object:
+  /// Error to throw when a slicing is requested on a non-slicable state of an object.
   class GridError : public Exception {
   public:
     GridError(const std::string& what) : Exception(what) {}

Modified: trunk/include/YODA/Histo2D.h
==============================================================================
--- trunk/include/YODA/Histo2D.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/Histo2D.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -8,6 +8,7 @@
 
 #include "YODA/AnalysisObject.h"
 #include "YODA/HistoBin2D.h"
+#include "YODA/HistoBin1D.h"
 #include "YODA/Scatter3D.h"
 #include "YODA/Axis2D.h"
 #include "YODA/Exceptions.h"
@@ -288,10 +289,13 @@
         if(atY < lowEdgeY() || atY > highEdgeY()) throw RangeError("Y is outside the grid");
         HistoBin2D first = binByCoord(lowEdgeX(), atY);
         vector<HistoBin1D> temp;
-        temp.push_back(first.transformX());
+        temp.push_back(HistoBin1D(first.lowEdgeX(), first.highEdgeX(), first.numEntries(),
+                       first.sumW(), first.sumW2(), first.sumWX(), first.sumWX2()));
 
         for(double i = first.xMax() + first.widthX()/2; i < highEdgeX(); i+=first.widthX()){
-            temp.push_back(binByCoord(i,atY).transformX());
+            HistoBin2D tempBin = binByCoord(i, atY);
+            temp.push_back(HistoBin1D(tempBin.lowEdgeX(), tempBin.highEdgeX(), tempBin.numEntries(),
+                           tempBin.sumW(), tempBin.sumW2(), tempBin.sumWX(), tempBin.sumWX2()));
         }
 
         Histo1D ret(temp);
@@ -302,10 +306,13 @@
         if(atX < lowEdgeX() || atX > highEdgeX()) throw RangeError("X is outside the grid");
         HistoBin2D first = binByCoord(lowEdgeX(), atX);
         vector<HistoBin1D> temp;
-        temp.push_back(first.transformY());
+        temp.push_back(HistoBin1D(first.lowEdgeY(), first.highEdgeY(), first.numEntries(),
+                                  first.sumW(), first.sumW2(), first.sumWX(), first.sumWX2()));
 
         for(double i = first.yMax() + first.widthY()/2; i < highEdgeY(); i+=first.widthY()){
-            temp.push_back(binByCoord(atX,i).transformY());
+            HistoBin2D tempBin = binByCoord(atX, i);
+            temp.push_back(HistoBin1D(tempBin.lowEdgeY(), tempBin.highEdgeY(), tempBin.numEntries(),
+                           tempBin.sumW(), tempBin.sumW2(), tempBin.sumWX(), tempBin.sumWX2()));
         }
 
         Histo1D ret(temp);

Modified: trunk/include/YODA/HistoBin1D.h
==============================================================================
--- trunk/include/YODA/HistoBin1D.h	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/include/YODA/HistoBin1D.h	Sat Aug  6 13:04:59 2011	(r222)
@@ -22,6 +22,8 @@
     //@{
     HistoBin1D(double lowedge, double highedge);
     HistoBin1D(std::pair<double,double> edges);
+    HistoBin1D(double lowedge, double highedge, unsigned long numFills,
+               double sumW, double sumW2, double sumWX, double sumWX2);
     //@}
 
 

Modified: trunk/src/Bin1D.cc
==============================================================================
--- trunk/src/Bin1D.cc	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/src/Bin1D.cc	Sat Aug  6 13:04:59 2011	(r222)
@@ -25,6 +25,17 @@
     assert( _edges.second >= _edges.first );
   }
 
+  Bin1D::Bin1D(double lowedge, double highedge, unsigned long numFills,
+               double sumW, double sumW2, double sumWX, double sumWX2) 
+               :_edges( make_pair(lowedge, highedge) ) 
+  {
+    _xdbn._numFills =   numFills;
+    _xdbn._sumW =       sumW;
+    _xdbn._sumW2 =      sumW2;
+    _xdbn._sumWX =      sumWX;
+    _xdbn._sumWX2 =     sumWX2;
+  }
+
 
   void Bin1D::reset () {
     _xdbn.reset();
@@ -109,12 +120,6 @@
     return _xdbn.sumWX2();
   }
 
-  void Bin1D::setW(double sumW)             {_xdbn.setW(sumW);}
-  void Bin1D::setW2(double sumW2)           {_xdbn.setW2(sumW2);}
-  void Bin1D::setWX(double sumWX)           {_xdbn.setWX(sumWX);}
-  void Bin1D::setWX2(double sumWX2)         {_xdbn.setWX2(sumWX2);}
-  void Bin1D::setNumFills(double numFills)  {_xdbn.setNumFills(numFills);}
-
   Bin1D& Bin1D::add(const Bin1D& b) {
     assert(_edges == b._edges);
     _xdbn += b._xdbn;

Modified: trunk/src/Bin2D.cc
==============================================================================
--- trunk/src/Bin2D.cc	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/src/Bin2D.cc	Sat Aug  6 13:04:59 2011	(r222)
@@ -136,41 +136,6 @@
         return _dbn.sumWY2();
     }
 
-    /// Dbn setters:
-    void Bin2D::setW(double sumW)      {_dbn.setW(sumW);}
-    void Bin2D::setW2(double sumW2)    {_dbn.setW2(sumW2);}
-    void Bin2D::setWX(double sumWX)    {_dbn.setWX(sumWX);}
-    void Bin2D::setWY(double sumWY)    {_dbn.setWY(sumWY);}
-    void Bin2D::setWX2(double sumWX2)  {_dbn.setWX2(sumWX2);}
-    void Bin2D::setWY2(double sumWY2)  {_dbn.setWY2(sumWY2);}
-    void Bin2D::setWXY(double sumWXY)  {_dbn.setWY2(sumWXY);}
-
-    /// Transformer transforming taking X as width
-    HistoBin1D Bin2D::transformX() {
-        HistoBin1D temp(lowEdgeX(), highEdgeX());
-        
-        temp.setW(sumW());
-        temp.setW2(sumW2());
-        temp.setWX(sumWX());
-        temp.setWX2(sumWX2());
-        temp.setNumFills(numEntries());
-
-        return temp;
-    }
-    
-    /// Transformer transforming taking Y as width
-    HistoBin1D Bin2D::transformY() {
-        HistoBin1D temp(lowEdgeY(), highEdgeY());
-        
-        temp.setW(sumW());
-        temp.setW2(sumW2());
-        temp.setWX(sumWY());
-        temp.setWX2(sumWY2());
-        temp.setNumFills(numEntries());
-
-        return temp;
-    }
-
     Bin2D& Bin2D::add(const Bin2D& b) {
         assert(_edges == b._edges);
         _dbn += b._dbn;

Modified: trunk/src/Dbn1D.cc
==============================================================================
--- trunk/src/Dbn1D.cc	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/src/Dbn1D.cc	Sat Aug  6 13:04:59 2011	(r222)
@@ -103,13 +103,6 @@
     return std::sqrt(variance() / effNumEntries());
   }
 
-  /// Setters
-  void Dbn1D::setW(double sumW)             {_sumW = sumW;}
-  void Dbn1D::setW2(double sumW2)           {_sumW2 = sumW2;}
-  void Dbn1D::setWX(double sumWX)           {_sumWX = sumWX;}
-  void Dbn1D::setWX2(double sumWX2)         {_sumWX2 = sumWX2;}
-  void Dbn1D::setNumFills(double numFills)  {_numFills = numFills;}
-
 
   Dbn1D& Dbn1D::add(const Dbn1D& d) {
     _numFills += d._numFills;

Modified: trunk/src/Histo2D.cc
==============================================================================
--- trunk/src/Histo2D.cc	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/src/Histo2D.cc	Sat Aug  6 13:04:59 2011	(r222)
@@ -4,7 +4,7 @@
 // Copyright (C) 2008-2011 The YODA collaboration (see AUTHORS for details)
 //
 #include "YODA/Histo2D.h"
-#include "YODA/Scatter2D.h"
+#include "YODA/Scatter3D.h"
 
 #include <cmath>
 #include <iostream>
@@ -32,6 +32,7 @@
     }
     else if (x < _axis.lowEdgeX()) { _axis.underflow().fill(x, y, weight); }
     else if (x >= _axis.highEdgeX()) { _axis.overflow().fill(x, y, weight); }
+    else throw GridError("You are trying to fill an empty space on a grid!");
     return index;
   }
 

Modified: trunk/src/HistoBin1D.cc
==============================================================================
--- trunk/src/HistoBin1D.cc	Thu Aug  4 09:58:42 2011	(r221)
+++ trunk/src/HistoBin1D.cc	Sat Aug  6 13:04:59 2011	(r222)
@@ -20,6 +20,11 @@
     : Bin1D(edges)
   { }
 
+  HistoBin1D::HistoBin1D(double low, double high, unsigned long numFills, double sumW,
+                         double sumW2, double sumWX, double sumWX2)
+    : Bin1D(low, high, numFills, sumW, sumW2, sumWX, sumWX2)
+  { }
+
 
   void HistoBin1D::fill(double x, double w) {
     assert( _edges.first < _edges.second );


More information about the yoda-svn mailing list