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

blackhole at projects.hepforge.org blackhole at projects.hepforge.org
Mon Jul 23 14:41:42 BST 2012


Author: buckley
Date: Mon Jul 23 14:41:42 2012
New Revision: 511

Log:
Adding Cython mappings for Dbn3D and Profile2D, and other fixes/improvements.

Added:
   trunk/pyext/yoda/include/20-Dbn3D.pyx
Modified:
   trunk/ChangeLog
   trunk/include/YODA/Histo2D.h
   trunk/include/YODA/Makefile.am
   trunk/include/YODA/Profile2D.h
   trunk/include/YODA/ProfileBin2D.h
   trunk/pyext/yoda/Makefile.am
   trunk/pyext/yoda/include/20-Dbn2D.pyx
   trunk/pyext/yoda/include/30-ProfileBin2D.pyx
   trunk/pyext/yoda/include/40-Histo1D.pyx
   trunk/pyext/yoda/include/40-Histo2D.pyx
   trunk/pyext/yoda/include/40-Profile1D.pyx
   trunk/pyext/yoda/include/40-Profile2D.pyx
   trunk/pyext/yoda/shims.h
   trunk/src/Histo2D.cc
   trunk/src/Profile2D.cc

Modified: trunk/ChangeLog
==============================================================================
--- trunk/ChangeLog	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/ChangeLog	Mon Jul 23 14:41:42 2012	(r511)
@@ -1,3 +1,7 @@
+2012-07-23  Andy Buckley  <andy.buckley at cern.ch>
+
+	* Adding Cython mappings for Dbn3D and Profile2D, and other fixes/improvements.
+
 2012-07-22  Andy Buckley  <andy.buckley at cern.ch>
 
 	* Adding Cython mappings for Scatter3D and ProfileBin2D.

Modified: trunk/include/YODA/Histo2D.h
==============================================================================
--- trunk/include/YODA/Histo2D.h	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/include/YODA/Histo2D.h	Mon Jul 23 14:41:42 2012	(r511)
@@ -7,13 +7,10 @@
 #define YODA_Histo2D_h
 
 #include "YODA/AnalysisObject.h"
-#include "YODA/Profile1D.h"
-#include "YODA/Histo1D.h"
-#include "YODA/Scatter3D.h"
 #include "YODA/HistoBin2D.h"
-#include "YODA/HistoBin1D.h"
 #include "YODA/Dbn2D.h"
 #include "YODA/Axis2D.h"
+#include "YODA/Scatter3D.h"
 #include "YODA/Exceptions.h"
 
 #include <vector>
@@ -22,15 +19,14 @@
 
 
   // Forward declaration
-  class Scatter3D;
+  class Profile2D;
 
   /// Convenience typedef
   typedef Axis2D<HistoBin2D, Dbn2D> Histo2DAxis;
 
 
-  /// A  one-dimensional histogram.
+  /// A two-dimensional histogram.
   class Histo2D : public AnalysisObject {
-
   public:
 
     /// Convenience typedefs
@@ -78,7 +74,13 @@
     Histo2D(const Histo2D& h, const std::string& path="");
 
 
-    /// @todo Add binning constructors from Scatter3D (and Profile2D?)
+    /// @todo Add binning constructors from Scatter3D and Profile2D?
+
+    // /// A constructor from a Scatter3D's binning, with optional new path
+    // Histo2D(const Scatter3D& s, const std::string& path="");
+
+    // /// Constructor from a Profile2D's binning, with optional new path
+    // Histo2D(const Profile2D& h, const std::string& path="");
 
 
     /// @brief State-setting constructor
@@ -153,10 +155,6 @@
     //   _axis.mergeBins(from, to);
     // }
 
-    void eraseBin(size_t index) {
-      _axis.eraseBin(index);
-    }
-
     /// Rebin the whole histo by a @a factorX in the X direction and
     /// @a factorY in the Y direction
     /// @todo TODO
@@ -164,6 +162,10 @@
     //   _axis.rebin(factorX, factorY);
     // }
 
+    void eraseBin(size_t index) {
+      _axis.eraseBin(index);
+    }
+
     //@}
 
 
@@ -346,6 +348,12 @@
     /// Get the standard error in y
     double yStdErr(bool includeoverflows=true) const;
 
+    /// Get the RMS in x
+    double xRMS(bool includeoverflows=true) const;
+
+    /// Get the RMS in y
+    double yRMS(bool includeoverflows=true) const;
+
     //@}
 
 

Modified: trunk/include/YODA/Makefile.am
==============================================================================
--- trunk/include/YODA/Makefile.am	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/include/YODA/Makefile.am	Mon Jul 23 14:41:42 2012	(r511)
@@ -2,13 +2,14 @@
     Exceptions.h  \
     AnalysisObject.h \
 	Weights.h Bin.h \
-	Dbn1D.h Dbn2D.h \
+	Dbn1D.h Dbn2D.h Dbn3D.h \
 	Axis1D.h Bin1D.h \
     Axis2D.h Bin2D.h \
     Plot.h \
     Histo1D.h HistoBin1D.h  \
     Histo2D.h HistoBin2D.h  \
     Profile1D.h ProfileBin1D.h \
+    Profile2D.h ProfileBin2D.h \
     Scatter2D.h Point2D.h \
     Scatter3D.h Point3D.h \
     Writer.h WriterAIDA.h WriterYODA.h \

Modified: trunk/include/YODA/Profile2D.h
==============================================================================
--- trunk/include/YODA/Profile2D.h	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/include/YODA/Profile2D.h	Mon Jul 23 14:41:42 2012	(r511)
@@ -1,19 +1,23 @@
-#ifndef YODA_Profile1D_h
-#define YODA_Profile1D_h
+// -*- C++ -*-
+//
+// This file is part of YODA -- Yet more Objects for Data Analysis
+// Copyright (C) 2008-2012 The YODA collaboration (see AUTHORS for details)
+//
+#ifndef YODA_Profile2D_h
+#define YODA_Profile2D_h
 
 #include "YODA/AnalysisObject.h"
 #include "YODA/ProfileBin2D.h"
-#include "YODA/Scatter3D.h"
 #include "YODA/Dbn3D.h"
 #include "YODA/Axis2D.h"
+#include "YODA/Scatter3D.h"
 #include "YODA/Exceptions.h"
 
 #include <vector>
-#include <string>
-#include <map>
 
 namespace YODA {
 
+
   // Forward declarations
   class Histo2D;
   class Scatter3D;
@@ -21,7 +25,8 @@
   /// Convenience typedef
   typedef Axis2D<ProfileBin2D, Dbn3D> Profile2DAxis;
 
-  /// A one-dimensional profile histogram.
+
+  /// A two-dimensional profile histogram.
   class Profile2D : public AnalysisObject {
   public:
 
@@ -29,8 +34,7 @@
     typedef Profile2DAxis Axis;
     typedef Axis::Bins Bins;
     typedef ProfileBin2D Bin;
-    typedef std::pair<double, double> Point;
-    typedef std::pair<Point, Point> Segment;
+    typedef Axis::Outflows Outflows;
 
 
     /// @name Constructors
@@ -60,6 +64,14 @@
     { }
 
 
+    /// Constructor accepting an explicit collection of bins.
+    Profile2D(const std::vector<Bin>& bins,
+              const std::string& path="", const std::string& title="")
+      : AnalysisObject("Profile2D", path, title),
+        _axis(bins)
+    { }
+
+
     /// A copy constructor with optional new path
     Profile2D(const Profile2D& p, const std::string& path="");
 
@@ -70,7 +82,14 @@
     Profile2D(const Histo2D& h, const std::string& path="");
 
     /// A state setting constructor
-    Profile2D();
+    Profile2D(const std::vector<ProfileBin2D>& bins,
+              const Dbn3D& totalDbn,
+              const Outflows& outflows,
+              const std::string& path="", const std::string& title="")
+      : AnalysisObject("Profile2D", path, title),
+        _axis(bins, totalDbn, outflows)
+    { }
+
 
     /// Assignment operator
     Profile2D& operator = (const Profile2D& p1) {
@@ -141,15 +160,53 @@
     //   _axis.addBin(binLimits);
     // }
 
+    void eraseBin(size_t index) {
+      _axis.eraseBin(index);
+    }
+
     //@}
 
 
     /// @name Bin accessors
     //@{
 
-    /// Number of bins of this axis (not counting under/over flow)
-    size_t numBins() const {
-      return _axis.bins().size();
+    /// Low x edge of this histo's axis
+    double lowEdgeX() const {
+      return _axis.lowEdgeX();
+    }
+    /// Alias for lowEdgeX()
+    double xMin() const {
+      return lowEdgeX();
+    }
+
+
+    /// Low y edge of this histo's axis
+    double lowEdgeY() const {
+        return _axis.lowEdgeY();
+    }
+    /// Alias for lowEdgeY()
+    double yMin() const {
+      return lowEdgeY();
+    }
+
+
+    /// High x edge of this histo's axis
+    double highEdgeX() const {
+      return _axis.highEdgeX();
+    }
+    /// Alias for highEdgeX()
+    double xMax() const {
+      return highEdgeX();
+    }
+
+
+    /// High y edge of this histo's axis
+    double highEdgeY() const {
+        return _axis.highEdgeY();
+    }
+    /// Alias for highEdgeY()
+    double yMax() const {
+      return highEdgeY();
     }
 
 
@@ -165,22 +222,54 @@
 
 
     /// Access a bin by index (non-const)
+    ProfileBin2D& bin(size_t index) {
+      return _axis.bins()[index];
+    }
+
+    /// Access a bin by index (const)
     const ProfileBin2D& bin(size_t index) const {
       return _axis.bins()[index];
     }
 
 
-    /// Access a bin by x-coordinate (non-const)
+    /// Access a bin by coordinate (non-const)
     ProfileBin2D& binByCoord(double x, double y) {
       return _axis.binByCoord(x, y);
     }
 
-    /// Access a bin by x-coordinate (const)
+    /// Access a bin by coordinate (const)
     const ProfileBin2D& binByCoord(double x, double y) const {
       return _axis.binByCoord(x, y);
     }
 
 
+    /// Return bin index (non-const version)
+    int findBinIndex(double coordX, double coordY) {
+      return _axis.getBinIndex(coordX, coordY);
+    }
+
+    /// Return bin index (const version)
+    const int findBinIndex(double coordX, double coordY) const {
+      return _axis.getBinIndex(coordX, coordY);
+    }
+
+
+    /// Number of bins of this axis (not counting under/over flow)
+    size_t numBins() const {
+      return _axis.bins().size();
+    }
+
+    /// Number of bins along the x axis
+    const size_t numBinsX() const {
+      return _axis.numBinsX();
+    }
+
+    /// Number of bins along the y axis
+    const size_t numBinsY() const{
+      return _axis.numBinsY();
+    }
+
+
     /// Access summary distribution, including gaps and overflows (non-const version)
     Dbn3D& totalDbn() {
       return _axis.totalDbn();
@@ -222,33 +311,41 @@
     /// Get the sum of squared weights in histo
     double sumW2(bool includeoverflows=true) const;
 
-    /// @todo TODO
-    // /// Get the mean x
-    // double xMean(bool includeoverflows=true) const;
+    /// Get the mean x
+    double xMean(bool includeoverflows=true) const;
 
-    /// @todo TODO
-    // /// Get the mean y
-    // double yMean(bool includeoverflows=true) const;
+    /// Get the mean y
+    double yMean(bool includeoverflows=true) const;
 
-    /// @todo TODO
-    // /// Get the variance in x
-    // double xVariance(bool includeoverflows=true) const;
+    /// Get the variance in x
+    double xVariance(bool includeoverflows=true) const;
 
-    /// @todo TODO
-    // /// Get the variance in y
-    // double yVariance(bool includeoverflows=true) const;
+    /// Get the variance in y
+    double yVariance(bool includeoverflows=true) const;
+
+    /// Get the standard deviation in x
+    double xStdDev(bool includeoverflows=true) const {
+      return std::sqrt(xVariance(includeoverflows));
+    }
+
+    /// Get the standard deviation in y
+    double yStdDev(bool includeoverflows=true) const {
+      return std::sqrt(yVariance(includeoverflows));
+    }
+
+    /// Get the standard error on <x>
+    double xStdErr(bool includeoverflows=true) const;
+
+    /// Get the standard error on <y>
+    double yStdErr(bool includeoverflows=true) const;
 
     /// @todo TODO
-    // /// Get the standard deviation in x
-    // double xStdDev(bool includeoverflows=true) const {
-    //   return std::sqrt(xVariance(includeoverflows));
-    // }
+    // /// Get the RMS in x
+    // double xRMS(bool includeoverflows=true) const;
 
     /// @todo TODO
-    // /// Get the standard deviation in y
-    // double yStdDev(bool includeoverflows=true) const {
-    //   return std::sqrt(yVariance(includeoverflows));
-    // }
+    // /// Get the RMS in y
+    // double yRMS(bool includeoverflows=true) const;
 
     //@}
 
@@ -289,6 +386,7 @@
     //@}
   };
 
+
   /// @name Combining profile histos: global operators
   //@{
 

Modified: trunk/include/YODA/ProfileBin2D.h
==============================================================================
--- trunk/include/YODA/ProfileBin2D.h	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/include/YODA/ProfileBin2D.h	Mon Jul 23 14:41:42 2012	(r511)
@@ -1,3 +1,8 @@
+// -*- C++ -*-
+//
+// This file is part of YODA -- Yet more Objects for Data Analysis
+// Copyright (C) 2008-2012 The YODA collaboration (see AUTHORS for details)
+//
 #ifndef YODA_ProfileBin2D_h
 #define YODA_ProfileBin2D_h
 

Modified: trunk/pyext/yoda/Makefile.am
==============================================================================
--- trunk/pyext/yoda/Makefile.am	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/Makefile.am	Mon Jul 23 14:41:42 2012	(r511)
@@ -5,7 +5,7 @@
 	$(PYTHON) -m cython --cplus yoda.pyx
 
 yoda.pyx: include/00-imports.pyx include/10-AnalysisObject.pyx \
-	include/20-Dbn1D.pyx include/20-Dbn2D.pyx \
+	include/20-Dbn1D.pyx include/20-Dbn2D.pyx include/20-Dbn3D.pyx \
 	include/20-Point2D.pyx include/20-Point3D.pyx \
 	include/30-HistoBin1D.pyx include/30-ProfileBin1D.pyx \
 	include/30-HistoBin2D.pyx include/30-ProfileBin2D.pyx \

Modified: trunk/pyext/yoda/include/20-Dbn2D.pyx
==============================================================================
--- trunk/pyext/yoda/include/20-Dbn2D.pyx	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/include/20-Dbn2D.pyx	Mon Jul 23 14:41:42 2012	(r511)
@@ -1,13 +1,14 @@
 cdef extern from "YODA/Dbn2D.h" namespace "YODA":
     cdef cppclass cDbn2D "Dbn2D":
         cDbn2D()
-        cDbn2D(unsigned int numEntries, double sumW, double sumW2, double sumWX, double sumWX2, double sumWY, double sumWY2, double sumWXY)
+        cDbn2D(unsigned long numEntries, double sumW, double sumW2,
+               double sumWX, double sumWX2, double sumWY, double sumWY2, double sumWXY)
         void fill(double valX, double valY, double weight)
         void reset()
         void scaleW(double scalefactor)
         void scaleX(double factor)
         void scaleY(double factor)
-        void scaleXY(double factor)
+        void scaleXY(double xfactor, double yfactor)
         double xMean()
         double yMean()
         double xVariance()
@@ -90,6 +91,8 @@
         "Scale the y variable by the given factor"
         self.ptr().scaleY(factor)
 
+    # TODO: map scaleXY Pythonically, with list/tuple args?
+
     @property
     def xMean(self):
         "Get the weighted mean x"

Added: trunk/pyext/yoda/include/20-Dbn3D.pyx
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/pyext/yoda/include/20-Dbn3D.pyx	Mon Jul 23 14:41:42 2012	(r511)
@@ -0,0 +1,265 @@
+cdef extern from "YODA/Dbn3D.h" namespace "YODA":
+    cdef cppclass cDbn3D "Dbn3D":
+        cDbn3D()
+        cDbn3D(unsigned long numEntries, double sumW, double sumW2,
+               double sumWX, double sumWX2, double sumWY, double sumWY2, double sumWZ, double sumWZ2,
+               double sumWXY, double sumWXZ, double sumWYZ, double sumWXYZ)
+        void fill(double valX, double valY, double valZ, double weight)
+        void reset()
+        void scaleW(double scalefactor)
+        void scaleX(double factor)
+        void scaleY(double factor)
+        void scaleZ(double factor)
+        void scaleXY(double xfactor, double yfactor)
+        void scaleXZ(double xfactor, double zfactor)
+        void scaleYZ(double yfactor, double zfactor)
+        void scaleXYZ(double xfactor, double yfactor, double zfactor)
+        double xMean()
+        double yMean()
+        double zMean()
+        double xVariance()
+        double yVariance()
+        double zVariance()
+        double xStdDev()
+        double yStdDev()
+        double zStdDev()
+        double xStdErr()
+        double yStdErr()
+        double zStdErr()
+        double xRMS()
+        double yRMS()
+        double zRMS()
+        unsigned long numEntries()
+        double effNumEntries()
+        double sumW()
+        double sumW2()
+        double sumWX()
+        double sumWX2()
+        double sumWY()
+        double sumWY2()
+        double sumWZ()
+        double sumWZ2()
+        double sumWXY()
+        double sumWXZ()
+        double sumWYZ()
+        double sumWXYZ()
+        # TODO: map operator+ and operator-, both internal and external
+
+
+cdef class Dbn3D:
+    """
+    A 2D distribution 'counter', used and exposed by 1D histograms and their bins.
+
+    TODO: Allow no-arg construction?
+    TODO: map operator+ and operator-, both internal and external
+    """
+
+    cdef cDbn3D* thisptr
+    cdef bool _dealloc
+
+    def __cinit__(self):
+        self._dealloc = False
+
+    def __dealloc__(self):
+        if self._dealloc:
+            del self.thisptr
+
+
+    def __init__(self, *args, **kwargs):
+        cdef:
+            unsigned int numEntries
+            double sumW, sumW2, sumWX, sumWX2, sumWY, sumWY2, sumWZ, sumWZ2, sumWXY, sumWXZ, sumWYZ, sumWXYZ
+        assert len(args) == 13
+        numEntries, sumW, sumW2, sumWX, sumWX2, sumWY, sumWY2, sumWZ, sumWZ2, sumWXY, sumWXZ, sumWYZ, sumWXYZ = args
+        self.setptr(new cDbn3D(numEntries, sumW, sumW2, sumWX, sumWX2, sumWY, sumWY2, sumWZ, sumWZ2, sumWXY, sumWXZ, sumWYZ, sumWXYZ), True)
+
+
+    cdef Dbn3D setptr(self, cDbn3D *ptr, bool dealloc):
+        if self._dealloc:
+            del self.thisptr
+
+        self.thisptr = ptr
+        self._dealloc = dealloc
+        return self
+
+    cdef cDbn3D* ptr(self):
+        return self.thisptr
+
+
+    def fill(self, double x, double y, double z, double weight=1.0):
+        "Fill the distribution with the given z and weight at given x and y."
+        self.ptr().fill(x, y, z, weight)
+
+    def reset(self):
+        "Reset the distribution counters to the unfilled state."
+        self.ptr().reset()
+
+    def scaleW(self, scalefactor):
+        "Scale the fill weights by the given factor"
+        self.ptr().scaleW(scalefactor)
+
+    def scaleX(self, factor):
+        "Scale the x variable by the given factor"
+        self.ptr().scaleX(factor)
+
+    def scaleY(self, factor):
+        "Scale the y variable by the given factor"
+        self.ptr().scaleY(factor)
+
+    def scaleZ(self, factor):
+        "Scale the z variable by the given factor"
+        self.ptr().scaleZ(factor)
+
+    # TODO: map scaleXY etc. -- Pythonically, with list/tuple args?
+
+    @property
+    def xMean(self):
+        "Get the weighted mean x"
+        return self.ptr().xMean()
+
+    @property
+    def yMean(self):
+        "Get the weighted mean y"
+        return self.ptr().yMean()
+
+    @property
+    def zMean(self):
+        "Get the weighted mean z"
+        return self.ptr().zMean()
+
+    @property
+    def xVariance(self):
+        "Get the weighted variance of x"
+        return self.ptr().xVariance()
+
+    @property
+    def yVariance(self):
+        "Get the weighted variance of y"
+        return self.ptr().yVariance()
+
+    @property
+    def zVariance(self):
+        "Get the weighted variance of z"
+        return self.ptr().zVariance()
+
+    @property
+    def xStdDev(self):
+        "Get the weighted standard deviation of x"
+        return self.ptr().xStdDev()
+
+    @property
+    def yStdDev(self):
+        "Get the weighted standard deviation of y"
+        return self.ptr().yStdDev()
+
+    @property
+    def zStdDev(self):
+        "Get the weighted standard deviation of z"
+        return self.ptr().zStdDev()
+
+    @property
+    def xStdErr(self):
+        "Get the weighted standard error on <x>"
+        return self.ptr().xStdDev()
+
+    @property
+    def yStdErr(self):
+        "Get the weighted standard error on <y>"
+        return self.ptr().yStdDev()
+
+    @property
+    def zStdErr(self):
+        "Get the weighted standard error on <z>"
+        return self.ptr().zStdDev()
+
+    @property
+    def xRMS(self):
+        "Get the weighted RMS of x"
+        return self.ptr().xRMS()
+
+    @property
+    def yRMS(self):
+        "Get the weighted RMS of y"
+        return self.ptr().yRMS()
+
+    @property
+    def zRMS(self):
+        "Get the weighted RMS of z"
+        return self.ptr().zRMS()
+
+    @property
+    def numEntries(self):
+        "Get the number of entries"
+        return self.ptr().numEntries()
+
+    @property
+    def effNumEntries(self):
+        "Get the effective number of entries (for weighted events)"
+        return self.ptr().effNumEntries()
+
+    @property
+    def sumW(self):
+        "Get the sum of weights"
+        return self.ptr().sumW()
+
+    @property
+    def sumW2(self):
+        "Get the sum of squared-weights"
+        return self.ptr().sumW2()
+
+    @property
+    def sumWX(self):
+        "Get the sum of weighted xs"
+        return self.ptr().sumWX()
+
+    @property
+    def sumWX2(self):
+        "Get the sum of weighted squared-xs"
+        return self.ptr().sumWX2()
+
+    @property
+    def sumWY(self):
+        "Get the sum of weighted ys"
+        return self.ptr().sumWY()
+
+    @property
+    def sumWY2(self):
+        "Get the sum of weighted squared-ys"
+        return self.ptr().sumWY2()
+
+    @property
+    def sumWZ(self):
+        "Get the sum of weighted zs"
+        return self.ptr().sumWZ()
+
+    @property
+    def sumWZ2(self):
+        "Get the sum of weighted squared-zs"
+        return self.ptr().sumWZ2()
+
+    @property
+    def sumWXY(self):
+        "Get the sum of weighted (x*y)s"
+        return self.ptr().sumWXY()
+
+    @property
+    def sumWXZ(self):
+        "Get the sum of weighted (x*z)s"
+        return self.ptr().sumWXZ()
+
+    @property
+    def sumWYZ(self):
+        "Get the sum of weighted (y*z)s"
+        return self.ptr().sumWYZ()
+
+    @property
+    def sumWXYZ(self):
+        "Get the sum of weighted (x*y*z)s"
+        return self.ptr().sumWXYZ()
+
+
+cdef Dbn3D Dbn3D_fromptr(cDbn3D *ptr, dealloc=False):
+    # Construct a Python Dbn3D from a pointer to a cDbn3D,
+    # without calling __init__ and excessive memory allocation
+    cdef Dbn3D dbn = Dbn3D.__new__(Dbn3D)
+    return dbn.setptr(ptr, dealloc)

Modified: trunk/pyext/yoda/include/30-ProfileBin2D.pyx
==============================================================================
--- trunk/pyext/yoda/include/30-ProfileBin2D.pyx	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/include/30-ProfileBin2D.pyx	Mon Jul 23 14:41:42 2012	(r511)
@@ -224,3 +224,9 @@
 
     def __repr__(self):
         return 'ProfileBin2D(%r)' % self.volume
+
+cdef ProfileBin2D ProfileBin2D_fromptr(cProfileBin2D *ptr, dealloc=False):
+    # Construct a Python ProfileBin2D from a pointer to a cProfileBin2D,
+    # without calling __init__ and excessive memory allocation
+    cdef ProfileBin2D bin = ProfileBin2D.__new__(ProfileBin2D)
+    return bin.setptr(ptr, dealloc)

Modified: trunk/pyext/yoda/include/40-Histo1D.pyx
==============================================================================
--- trunk/pyext/yoda/include/40-Histo1D.pyx	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/include/40-Histo1D.pyx	Mon Jul 23 14:41:42 2012	(r511)
@@ -241,9 +241,9 @@
     @property
     def totalDbn(self):
         """
-        h.totalDbn -> Distribution1D
+        h.totalDbn -> Dbn1D
 
-        Return the Distribution1D object representing the total distribution.
+        Return the Dbn1D object representing the total distribution.
 
         """
         return Dbn1D_fromptr(&self.ptr().totalDbn())
@@ -252,9 +252,9 @@
     @property
     def underflow(self):
         """
-        h.underflow -> Distribution1D
+        h.underflow -> Dbn1D
 
-        Return the Distribution1D object representing the underflow.
+        Return the Dbn1D object representing the underflow.
 
         """
         return Dbn1D_fromptr(&self.ptr().underflow())
@@ -263,9 +263,9 @@
     @property
     def overflow(self):
         """
-        h.overflow -> Distribution1D
+        h.overflow -> Dbn1D
 
-        Return the Distribution1D object representing the overflow.
+        Return the Dbn1D object representing the overflow.
 
         """
         return Dbn1D_fromptr(&self.ptr().overflow())

Modified: trunk/pyext/yoda/include/40-Histo2D.pyx
==============================================================================
--- trunk/pyext/yoda/include/40-Histo2D.pyx	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/include/40-Histo2D.pyx	Mon Jul 23 14:41:42 2012	(r511)
@@ -32,11 +32,12 @@
         cDbn2D& totalDbn()
 
         vector[cHistoBin2D]& bins()
+        int findBinIndex(double coordX, double coordY)
         cHistoBin2D& binByCoord(double x, double y)
-
         cHistoBin2D& bin(size_t i)
         void eraseBin(size_t i)
 
+
         # Statistical functions
         double integral(bool includeoverflows)
         double sumW(bool includeoverflows)

Modified: trunk/pyext/yoda/include/40-Profile1D.pyx
==============================================================================
--- trunk/pyext/yoda/include/40-Profile1D.pyx	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/include/40-Profile1D.pyx	Mon Jul 23 14:41:42 2012	(r511)
@@ -229,9 +229,9 @@
     @property
     def totalDbn(self):
         """
-        h.totalDbn -> Distribution1D
+        h.totalDbn -> Dbn2D
 
-        Return the Distribution1D object representing the total distribution.
+        Return the Dbn2D object representing the total distribution.
 
         """
         return Dbn2D_fromptr(&self.ptr().totalDbn())
@@ -240,9 +240,9 @@
     @property
     def underflow(self):
         """
-        h.underflow -> Distribution1D
+        h.underflow -> Dbn2D
 
-        Return the Distribution1D object representing the underflow.
+        Return the Dbn2D object representing the underflow.
 
         """
         return Dbn2D_fromptr(&self.ptr().underflow())
@@ -251,9 +251,9 @@
     @property
     def overflow(self):
         """
-        h.overflow -> Distribution1D
+        h.overflow -> Dbn2D
 
-        Return the Distribution1D object representing the overflow.
+        Return the Dbn2D object representing the overflow.
 
         """
         return Dbn2D_fromptr(&self.ptr().overflow())

Modified: trunk/pyext/yoda/include/40-Profile2D.pyx
==============================================================================
--- trunk/pyext/yoda/include/40-Profile2D.pyx	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/include/40-Profile2D.pyx	Mon Jul 23 14:41:42 2012	(r511)
@@ -1,691 +1,321 @@
-# cdef extern from "YODA/Histo2D.h" namespace "YODA":
-#     #cHisto2D operator + (cHisto2D &, cHisto2D &)
-#     #cHisto2D operator - (cHisto2D &, cHisto2D &)
+cdef extern from "YODA/Profile2D.h" namespace "YODA":
+    #cProfile2D operator + (cProfile2D &, cProfile2D &)
+    #cProfile2D operator - (cProfile2D &, cProfile2D &)
 
-#     cdef cppclass cHisto2D "YODA::Histo2D"(cAnalysisObject):
-#         cHisto2D()
-#         cHisto2D(string& path, string& title)
-#         cHisto2D(size_t nbinsX, double lowerX, double upperX,
-#                  size_t nbinsY, double lowerY, double upperY,
-#                  string& path, string& title)
-#         cHisto2D(vector[cHistoBin2D]&, string& path, string& title)
-#         cHisto2D(vector[double]& xedges, vector[double]& yedges, string& path, string& title)
-#         cHisto2D(cHisto2D& h)
+    cdef cppclass cProfile2D "YODA::Profile2D"(cAnalysisObject):
+        cProfile2D()
+        cProfile2D(string& path, string& title)
+        cProfile2D(size_t nbinsX, double lowerX, double upperX,
+                   size_t nbinsY, double lowerY, double upperY,
+                   string& path, string& title)
+        cProfile2D(vector[cProfileBin2D]&, string& path, string& title)
+        cProfile2D(vector[double]& xedges, vector[double]& yedges, string& path, string& title)
+        cProfile2D(cProfile2D& h)
 
-#         void fill(double x, double y, double weight)
-#         void reset()
-#         void scaleW(double scalefactor)
-#         void scaleXY(double scaleX, double scaleY)
-#         # void mergeBins(size_t a, size_t b)
-#         # void rebin(int a, int b)
+        void fill(double x, double y, double z, double weight)
+        void reset()
+        void scaleW(double scalefactor)
+        void scaleXY(double scaleX, double scaleY)
+        # void mergeBins(size_t a, size_t b)
+        # void rebin(int a, int b)
 
-#         # Bin Accessors
-#         size_t numBins()
-#         size_t numBinsX()
-#         size_t numBinsY()
+        # Bin Accessors
+        size_t numBins()
+        size_t numBinsX()
+        size_t numBinsY()
 
-#         double lowEdgeX()
-#         double lowEdgeY()
-#         double highEdgeX()
-#         double highEdgeY()
-#         cDbn2D& outflow(int ix, int iy)
-#         cDbn2D& totalDbn()
+        double lowEdgeX()
+        double lowEdgeY()
+        double highEdgeX()
+        double highEdgeY()
+        cDbn3D& outflow(int ix, int iy)
+        cDbn3D& totalDbn()
 
-#         vector[cHistoBin2D]& bins()
-#         cHistoBin2D& binByCoord(double x, double y)
+        vector[cProfileBin2D]& bins()
+        int findBinIndex(double coordX, double coordY)
+        cProfileBin2D& binByCoord(double x, double y)
+        cProfileBin2D& bin(size_t i)
+        void eraseBin(size_t i)
 
-#         cHistoBin2D& bin(size_t i)
-#         void eraseBin(size_t i)
+        # Statistical functions
+        double sumW(bool includeoverflows)
+        double sumW2(bool includeoverflows)
 
-#         # Statistical functions
-#         double integral(bool includeoverflows)
-#         double sumW(bool includeoverflows)
-#         double sumW2(bool includeoverflows)
+        double xMean(bool includeoverflows)
+        double yMean(bool includeoverflows)
 
-#         double xMean(bool includeoverflows)
-#         double yMean(bool includeoverflows)
+        double xVariance(bool includeoverflows)
+        double yVariance(bool includeoverflows)
 
-#         double xVariance(bool includeoverflows)
-#         double yVariance(bool includeoverflows)
+        double xStdDev(bool includeoverflows)
+        double yStdDev(bool includeoverflows)
 
-#         double xStdDev(bool includeoverflows)
-#         double yStdDev(bool includeoverflows)
+        double xStdErr(bool includeoverflows)
+        double yStdErr(bool includeoverflows)
 
-#         double xStdErr(bool includeoverflows)
-#         double yStdErr(bool includeoverflows)
 
+cdef class Profile2D(AnalysisObject):
+    """
+    2D profile histogram. Basic histogramming is currently supported, i.e. a
+    two-dimensional bin layout may be specified, filled, and queried. Outflow
+    distributions around the 8 sides and corners of the grid are supported, and
+    the bins need not be regularly sized or contiguous: bins which span rows
+    and/or columns, and gaps between bins are permitted.
 
-# cdef class Histo2D(AnalysisObject):
-#     """
-#     2D histogram. Basic histogramming is currently supported, i.e. a two-dimensional bin layout
-#     may be specified, filled, and queried. Outflow distributions around the 8 sides and
-#     corners of the grid are supported, and the bins need not be regularly sized or contiguous:
-#     bins which span rows and/or columns, and gaps between bins are permitted.
+    TODO: Bin merging/rebinning is not currently supported (the algorithm has to
+    be a bit more complex than usual due to the increased number of ways for it
+    to not work if the bin shapes are irregular.)
 
-#     TODO: Bin merging/rebinning is not currently supported (the algorithm has to
-#     be a bit more complex than usual due to the increased number of ways for it
-#     to not work if the bin shapes are irregular.)
+    Rescaling of weights and/or the x and y axes is permitted in-place: the result
+    is a still-valid Profile2D. Binning-compatible 2D histograms may be
+    divided, resulting in a Scatter3D rather than a Profile2D, since further
+    fills would not be meaningful.
 
-#     Rescaling of weights and/or the x and y axes is permitted in-place: the result
-#     is a still-valid Histo2D. Binning-compatible 2D histograms may be
-#     divided, resulting in a Scatter3D rather than a Histo2D, since further
-#     fills would not be meaningful.
+    Several sets of arguments are permitted to the constructor:
 
-#     Several sets of arguments are permitted to the constructor:
+    * Profile2D() -- default constructor. Not usually useful in Python, due to availability of None.
+    * Profile2D(bins[, path, title]) -- constructor from a list of bins.
+    * Profile2D(nx, xlow, xhigh, ny, ylow, yhigh[, path, title]) -- construct a uniform bin grid in both x and y directions.
+    * Profile2D(xedges, yedges[, path, title]) -- make a regular bin grid with given bin edges in x and y.
 
-#     * Histo2D() -- default constructor. Not usually useful in Python, due to availability of None.
-#     * Histo2D(bins[, path, title]) -- constructor from a list of bins.
-#     * Histo2D(nx, xlow, xhigh, ny, ylow, yhigh[, path, title]) -- construct a uniform bin grid in both x and y directions.
-#     * Histo2D(xedges, yedges[, path, title]) -- make a regular bin grid with given bin edges in x and y.
+    The path and title arguments are optional, and may either be specified via the
+    positional parameters or via explicit keyword arguments, e.g. path='/foo/bar'.
 
-#     The path and title arguments are optional, and may either be specified via the
-#     positional parameters or via explicit keyword arguments, e.g. path='/foo/bar'.
+    TODO: Add constructors from Scatter and Histo2D
+    TODO: Support adding and erasing bins
+    TODO: Support add, mul, div operators
+    """
 
-#     TODO: Add constructors from Scatter and Profile
-#     TODO: Support adding and erasing bins
-#     TODO: Support add, mul, div operators
-#     """
+    def __cinit__(self):
+        self._dealloc = False
 
-#     def __cinit__(self):
-#         self._dealloc = False
 
+    def __init__(self, *args, **kwargs):
+        cdef:
+            size_t nbinsX, nbinsY
+            double lowX, highX, lowY, highY
+            ProfileBin2D item
+            vector[cProfileBin2D] bin_vector
+            vector[double] xedges
+            vector[double] yedges
+            char* path = '/'
+            char* title = ''
 
-#     def __init__(self, *args, **kwargs):
-#         cdef:
-#             size_t nbinsX, nbinsY
-#             double lowX, highX, lowY, highY
-#             HistoBin2D item
-#             vector[cHistoBin2D] bin_vector
-#             vector[double] xedges
-#             vector[double] yedges
-#             char* path = '/'
-#             char* title = ''
+        ## Permit path and title specification via kwargs
+        if "path" in kwargs:
+            path = kwargs["path"]
+        if "title" in kwargs:
+            title = kwargs["title"]
 
-#         ## Permit path and title specification via kwargs
-#         if "path" in kwargs:
-#             path = kwargs["path"]
-#         if "title" in kwargs:
-#             title = kwargs["title"]
+        # TODO: Map copy constructor
 
-#         # TODO: Map copy constructor
+        if len(args) == 0:
+            self.setptr(new cProfile2D(string(path), string(title)), True)
+        elif len(args) == 1:
+            # Profile2D(bins[, path, title])
+            for b in args[0]:
+                item = b
+                bin_vector.push_back( item.ptr()[0] )
+            self.setptr(new cProfile2D(bin_vector, string(path), string(title)))
+        elif len(args) == 2:
+            # Profile2D(xedges, yedges[, path, title])
+            for x in args[0]:
+                xedges.push_back(x)
+            for y in args[1]:
+                yedges.push_back(y)
+            self.setptr(new cProfile2D(xedges, yedges, string(path), string(title)))
+        elif len(args) == 6:
+            # Profile2D(nx, xlow, xhigh, ny, ylow, yhigh[, path, title]) -- construct a uniform bin grid in both x and y directions.
+            nbinsX, lowX, highX, nbinsY, lowY, highY = args
+            self.setptr(new cProfile2D(nbinsX, lowX, highX, nbinsY, lowY, highY,
+                                       string(path), string(title)), True)
 
-#         if len(args) == 0:
-#             self.setptr(new cHisto2D(string(path), string(title)), True)
-#         elif len(args) == 1:
-#             # Histo2D(bins[, path, title])
-#             for b in args[0]:
-#                 item = b
-#                 bin_vector.push_back( item.ptr()[0] )
-#             self.setptr(new cHisto2D(bin_vector, string(path), string(title)))
-#         elif len(args) == 2:
-#             # Histo2D(xedges, yedges[, path, title])
-#             for x in args[0]:
-#                 xedges.push_back(x)
-#             for y in args[1]:
-#                 yedges.push_back(y)
-#             self.setptr(new cHisto2D(xedges, yedges, string(path), string(title)))
-#         elif len(args) == 6:
-#             # Histo2D(nx, xlow, xhigh, ny, ylow, yhigh[, path, title]) -- construct a uniform bin grid in both x and y directions.
-#             nbinsX, lowX, highX, nbinsY, lowY, highY = args
-#             self.setptr(new cHisto2D(nbinsX, lowX, highX, nbinsY, lowY, highY,
-#                                      string(path), string(title)), True)
 
+    cdef cProfile2D* ptr(self):
+        return <cProfile2D *> self.thisptr
 
-#     cdef cHisto2D* ptr(self):
-#         return <cHisto2D *> self.thisptr
 
+    def fill(self, double x, double y, double z, double weight=1.0):
+        "Fill the bin at (x, y) with the given z value and weight"
+        self.ptr().fill(x, y, z, weight)
 
-#     def fill(self, double x, double y, double weight=1.0):
-#         "Fill the bin at (x, y) with the given weight"
-#         self.ptr().fill(x, y, weight)
 
+    def reset(self):
+        """Reset the histogram counters but leave the bin structure"""
+        self.ptr().reset()
 
-#     def reset(self):
-#         """Reset the histogram counters but leave the bin structure"""
-#         self.ptr().reset()
 
+    def scaleW(self, double factor):
+        """Scale the histogram and its statistics by the given factor"""
+        self.ptr().scaleW(factor)
 
-#     def scaleW(self, double factor):
-#         """Scale the histogram and its statistics by the given factor"""
-#         self.ptr().scaleW(factor)
 
+    # def mergeBins(self, size_t a, size_t b):
+    #     self.ptr().mergeBins(a, b)
 
-#     # def mergeBins(self, size_t a, size_t b):
-#     #     self.ptr().mergeBins(a, b)
 
+    # def rebin(self, int a, int b):
+    #     self.ptr().rebin(a, b)
 
-#     # def rebin(self, int a, int b):
-#     #     self.ptr().rebin(a, b)
 
+    @property
+    def bins(self):
+        "Access the bins"
+        cdef size_t i
+        return tuple(ProfileBin2D_fromptr(&self.ptr().bin(i)) for i in xrange(self.ptr().numBins()))
 
-#     @property
-#     def bins(self):
-#         "Access the bins"
-#         cdef size_t i
-#         return tuple(HistoBin2D_fromptr(&self.ptr().bin(i)) for i in xrange(self.ptr().numBins()))
+    @property
+    def lowEdgeX(self):
+        "The lower bound of the histogram bin range in x"
+        return self.ptr().lowEdgeX()
 
-#     @property
-#     def lowEdgeX(self):
-#         "The lower bound of the histogram bin range in x"
-#         return self.ptr().lowEdgeX()
 
+    @property
+    def lowEdgeY(self):
+        "The lower bound of the histogram bin range in y"
+        return self.ptr().lowEdgeY()
 
-#     @property
-#     def lowEdgeY(self):
-#         "The lower bound of the histogram bin range in y"
-#         return self.ptr().lowEdgeY()
 
+    @property
+    def highEdgeX(self):
+        "The upper bound of the histogram bin range in x"
+        return self.ptr().highEdgeX()
 
-#     @property
-#     def highEdgeX(self):
-#         "The upper bound of the histogram bin range in x"
-#         return self.ptr().highEdgeX()
 
+    @property
+    def highEdgeY(self):
+        "The upper bound of the histogram bin range in y"
+        return self.ptr().highEdgeY()
 
-#     @property
-#     def highEdgeY(self):
-#         "The upper bound of the histogram bin range in y"
-#         return self.ptr().highEdgeY()
 
+    @property
+    def totalDbn(self):
+        """
+        h.totalDbn -> Dbn3D
 
-#     @property
-#     def totalDbn(self):
-#         """
-#         h.totalDbn -> Dbn2D
+        Return the Dbn3D object representing the total distribution.
 
-#         Return the Dbn2D object representing the total distribution.
+        """
+        return Dbn3D_fromptr(&self.ptr().totalDbn())
 
-#         """
-#         return Dbn2D_fromptr(&self.ptr().totalDbn())
 
+    def outflow(self, ix, iy):
+        """
+        h.outflow(ix, iy) -> Dbn3D
 
-#     def outflow(self, ix, iy):
-#         """
-#         h.outflow(ix, iy) -> Dbn2D
+        Return the Dbn3D object representing the outflow in the (ix,iy)
+        direction, where ix, iy = {-1, 0, 1}.
+        """
+        return Dbn3D_fromptr(&self.ptr().outflow(ix, iy))
 
-#         Return the Dbn2D object representing the outflow in the (ix,iy)
-#         direction, where ix, iy = {-1, 0, 1}.
-#         """
 
-#         return Dbn2D_fromptr(&self.ptr().outflow(ix, iy))
+    def __delitem__(self, size_t ix):
+        self.ptr().eraseBin(ix)
 
 
-#     def __delitem__(self, size_t ix):
-#         self.ptr().eraseBin(ix)
+    def __getitem__(self, size_t ix):
+        return ProfileBin2D().set(self.ptr().bins()[ix])
 
 
-#     def __getitem__(self, size_t ix):
-#         return HistoBin2D().set(self.ptr().bins()[ix])
+    def sumW(self, bool overflows=True):
+        """
+        h.sumW([bool overflows=True] -> float
 
+        Get the weight integral of the histo, with an optional bool argument to
+        decide whether the bin-range overflows are to be included.
+        """
+        return self.ptr().sumW(overflows)
 
-#     def integral(self, bool overflows=True):
-#         """
-#         h.integral([bool overflows=True] -> float
 
-#         Get the integral of the histo, with an optional bool argument to decide
-#         whether the bin-range overflows are to be included. Effectively a
-#         synonym for sumW.
-#         """
-#         return self.ptr().integral(overflows)
+    def sumW2(self, bool overflows=True):
+        """
+        h.sumW2([bool overflows=True] -> float
 
+        Get the weight**2 integral of the histo, with an optional bool argument
+        to decide whether the bin-range overflows are to be included.
+        """
+        return self.ptr().sumW2(overflows)
 
-#     def sumW(self, bool overflows=True):
-#         """
-#         h.sumW([bool overflows=True] -> float
 
-#         Get the weight integral of the histo, with an optional bool argument to
-#         decide whether the bin-range overflows are to be included.
-#         """
-#         return self.ptr().sumW(overflows)
+    def mean(self, bool overflows=True):
+        """
+        h.mean([bool overflows=True] -> (float, float)
 
+        Get the mean (x,y) point for this histo, with an optional bool argument
+        to decide whether the bin-range overflows are to be included.
+        """
+        cdef cProfile2D *s = self.ptr()
+        return (s.xMean(overflows), s.yMean(overflows))
 
-#     def sumW2(self, bool overflows=True):
-#         """
-#         h.sumW2([bool overflows=True] -> float
 
-#         Get the weight**2 integral of the histo, with an optional bool argument
-#         to decide whether the bin-range overflows are to be included.
-#         """
-#         return self.ptr().sumW2(overflows)
+    def variance(self, bool overflows=True):
+        """
+        h.variance([bool overflows=True] -> (float, float)
 
+        Get the (x,y) variances for this histo, with an optional bool argument
+        to decide whether the bin-range overflows are to be included.
+        """
+        cdef cProfile2D *s = self.ptr()
+        return (s.xVariance(overflows), s.yVariance(overflows))
 
-#     def mean(self, bool overflows=True):
-#         """
-#         h.mean([bool overflows=True] -> (float, float)
 
-#         Get the mean (x,y) point for this histo, with an optional bool argument
-#         to decide whether the bin-range overflows are to be included.
-#         """
-#         cdef cHisto2D *s = self.ptr()
-#         return (s.xMean(overflows), s.yMean(overflows))
+    def stdDev(self, bool overflows=True):
+        """
+        h.stdDev([bool overflows=True] -> (float, float)
 
+        Get the (x,y) standard deviations for this histo, with an optional bool
+        argument to decide whether the bin-range overflows are to be included.
+        """
+        cdef cProfile2D *s = self.ptr()
+        return (s.xStdDev(overflows), s.yStdDev(overflows))
 
-#     def variance(self, bool overflows=True):
-#         """
-#         h.variance([bool overflows=True] -> (float, float)
 
-#         Get the (x,y) variances for this histo, with an optional bool argument
-#         to decide whether the bin-range overflows are to be included.
-#         """
-#         cdef cHisto2D *s = self.ptr()
-#         return (s.xVariance(overflows), s.yVariance(overflows))
+    def stdErr(self, bool overflows=True):
+        """
+        h.stdErr([bool overflows=True] -> (float, float)
 
+        Get the (x,y) standard errors on the mean for this histo, with an
+        optional bool argument to decide whether the bin-range overflows are to
+        be included.
+        """
+        cdef cProfile2D *s = self.ptr()
+        return (s.xStdErr(overflows), s.yStdErr(overflows))
 
-#     def stdDev(self, bool overflows=True):
-#         """
-#         h.stdDev([bool overflows=True] -> (float, float)
 
-#         Get the (x,y) standard deviations for this histo, with an optional bool
-#         argument to decide whether the bin-range overflows are to be included.
-#         """
-#         cdef cHisto2D *s = self.ptr()
-#         return (s.xStdDev(overflows), s.yStdDev(overflows))
 
+    # def __add__(Profile2D a, Profile2D b):
+    #     cdef cProfile2D *res
+    #     res = new cProfile2D(a.ptr()[0] + b.ptr()[0])
+    #     return Profile2D().setptr(res)
 
-#     def stdErr(self, bool overflows=True):
-#         """
-#         h.stdErr([bool overflows=True] -> (float, float)
 
-#         Get the (x,y) standard errors on the mean for this histo, with an
-#         optional bool argument to decide whether the bin-range overflows are to
-#         be included.
-#         """
-#         cdef cHisto2D *s = self.ptr()
-#         return (s.xStdErr(overflows), s.yStdErr(overflows))
+    # def __sub__(Profile2D a, Profile2D b):
+    #     cdef cProfile2D *res
+    #     res = new cProfile2D(a.ptr()[0] - b.ptr()[0])
+    #     return Profile2D().setptr(res)
 
 
+    # def __mul__(x, y):
+    #     cdef cProfile2D *res
+    #     tx, ty = type(x), type(y)
+    #     if (tx is int or tx is float) and ty is Profile2D:
+    #         histo = <Profile2D> y; factor = <Profile2D> x
+    #     elif tx is Profile2D and (ty is int or ty is float):
+    #         histo = <Profile2D> x; factor = <Profile2D> y
+    #     else:
+    #         raise RuntimeError('Cannot multiply %r by %r' % (tx, ty))
 
-#     # def __add__(Histo2D a, Histo2D b):
-#     #     cdef cHisto2D *res
-#     #     res = new cHisto2D(a.ptr()[0] + b.ptr()[0])
-#     #     return Histo2D().setptr(res)
+    #     res = new cProfile2D(histo.ptr()[0])
+    #     res.scaleW(factor)
+    #     return Profile2D().setptr(res)
 
 
-#     # def __sub__(Histo2D a, Histo2D b):
-#     #     cdef cHisto2D *res
-#     #     res = new cHisto2D(a.ptr()[0] - b.ptr()[0])
-#     #     return Histo2D().setptr(res)
+    def __repr__(self):
+        return 'Profile2D%r' % self.bins
 
 
-#     # def __mul__(x, y):
-#     #     cdef cHisto2D *res
-#     #     tx, ty = type(x), type(y)
-#     #     if (tx is int or tx is float) and ty is Histo2D:
-#     #         histo = <Histo2D> y; factor = <Histo2D> x
-#     #     elif tx is Histo2D and (ty is int or ty is float):
-#     #         histo = <Histo2D> x; factor = <Histo2D> y
-#     #     else:
-#     #         raise RuntimeError('Cannot multiply %r by %r' % (tx, ty))
-
-#     #     res = new cHisto2D(histo.ptr()[0])
-#     #     res.scaleW(factor)
-#     #     return Histo2D().setptr(res)
-
-
-#     def __repr__(self):
-#         return 'Histo2D%r' % self.bins
-
-
-# cdef Histo2D Histo2D_fromptr(cHisto2D *ptr, dealloc=False):
-#     # Construct a Python Histo2D from a pointer to a cHisto2D,
-#     # without calling __init__ and excessive memory allocation
-#     cdef Histo2D bin = Histo2D.__new__(Histo2D)
-#     return bin.setptr(ptr, dealloc)
-# cdef extern from "YODA/Profile1D.h" namespace "YODA":
-
-#     cdef cppclass cProfile1D "YODA::Profile1D"(cAnalysisObject):
-#         cProfile1D()
-#         cProfile1D(size_t nbins, double lower, double upper, string& path, string& title)
-#         cProfile1D(vector[double]& binedges, string& path, string& title)
-#         cProfile1D(cProfile1D& h, string& path)
-#         cProfile1D(cProfile1D& h)
-
-#         void fill(double x, double y, double weight)
-#         void reset()
-#         void scaleW(double scalefactor)
-#         void mergeBins(size_t a, size_t b)
-#         void rebin(int n)
-
-#         # Bin Accessors
-#         size_t numBins()
-#         double lowEdge()
-#         double highEdge()
-
-#         vector[cProfileBin1D]& bins()
-#         cProfileBin1D& bin(size_t i)
-#         void eraseBin(size_t i)
-
-#         cDbn2D& totalDbn()
-#         cDbn2D& underflow()
-#         cDbn2D& overflow()
-#         void addBin(double low, double high)
-#         void addBins(vector[double]& binedges)
-
-#         # Statistical functions
-#         #double integral(bool includeoverflows)
-#         #double integral(size_t a, size_t b)
-#         double sumW(bool includeoverflows)
-#         double sumW2(bool includeoverflows)
-
-#     cProfile1D add(cProfile1D &, cProfile1D &)
-#     cProfile1D subtract(cProfile1D &, cProfile1D &)
-#     cScatter2D divide(cProfile1D &, cProfile1D &)
-#     #cScatter2D mkScatter(cProfile1D &)
-
-# cdef extern from "YODA/Scatter2D.h" namespace "YODA":
-#     cScatter2D mkScatter(cProfile1D &)
-
-
-
-# cdef class Profile1D(AnalysisObject):
-#     """
-#     1D profile histogram. Complete histogramming is supported, including
-#     uniform/regular binning, variable width binning, unbinned gaps in the
-#     covered range, and under/overflows (including the gaps). Rebinning by
-#     integer factors, or by explicit merging of contiguous bins is also
-#     supported.
-
-#     Rescaling of weights and/or the x axis is permitted in-place: the result
-#     is a still-valid Profile1D. Binning-compatible 2D profiles may be
-#     divided, resulting in a Scatter2D rather than a Profile1D, since further
-#     fills would not be meaningful.
-
-#     Several sets of arguments are permitted to the constructor:
-
-#     * Profile1D() -- default constructor. Not usually useful in Python, due to availability of None.
-#     * Profile1D(nbins, low, high[, path, title]) -- linear binning with n bins between low-high.
-#     * Profile1D(binedges[, path, title]) -- explicit bin edges (no bin gaps)
-
-#     The path and title arguments are optional, and may either be specified via the
-#     positional parameters or via explicit keyword arguments, e.g. path='/foo/bar'.
-
-#     TODO: Add constructors from Scatter and Histo
-#     TODO: Support addBin, addBins, eraseBin
-#     """
-
-#     def __init__(self, *args, **kwargs):
-#         self._dealloc = True
-#         cdef:
-#             size_t nbins
-#             double lower
-#             double upper
-#             vector[double] binedges
-#             char* path = '/'
-#             char* title = ''
-
-#         ## Permit path and title specification via kwargs
-#         if "path" in kwargs:
-#             path = kwargs["path"]
-#         if "title" in kwargs:
-#             path = kwargs["title"]
-
-#         ## Trigger different C++ constructors depending on Python args
-#         # TODO: Map copy constructors, esp. the path-resetting one
-#         if len(args) == 0:
-#             self.setptr(new cProfile1D())
-#         else:
-#             if type(args[0]) is list:
-#                 try:
-#                     for i in args[0]:
-#                         binedges.push_back(float(i))
-#                 except:
-#                     raise Exception("Invalid binedges container supplied to Profile1D constructor")
-#                 if len(args) >= 2:
-#                     assert "path" not in kwargs
-#                     path = args[1]
-#                 if len(args) == 3:
-#                     assert "title" not in kwargs
-#                     path = args[2]
-#                 if len(args) > 3:
-#                     raise ValueError("Too many arguments supplied to Profile1D constructor with a binedge list first arg")
-#                 self.setptr(new cProfile1D(binedges, string(path), string(title)))
-#             else:
-#                 assert len(args) >= 3
-#                 nbins, lower, upper = args[0:3]
-#                 if len(args) >= 4:
-#                     assert "path" not in kwargs
-#                     path = args[3]
-#                 if len(args) == 5:
-#                     assert "title" not in kwargs
-#                     path = args[4]
-#                 if len(args) > 5:
-#                     raise ValueError("Too many arguments supplied to Profile1D constructor")
-#                 self.setptr(new cProfile1D(nbins, lower, upper, string(path), string(title)))
-
-
-#     cdef cProfile1D* ptr(self):
-#         return <cProfile1D *> self.thisptr
-
-
-#     def asScatter(self):
-#         """
-#         h.asScatter() -> Scatter2D
-
-#         Return a 2D scatter data object from the profile's bins and heights.
-
-#         """
-#         cdef cScatter2D *s = new cScatter2D()
-#         s[0] = mkScatter(self.ptr()[0])
-#         return Scatter2D_fromptr(s, True)
-
-
-#     def fill(self, double x, double y, double weight=1.0):
-#         """
-#         h.fill(x, y[, weight=1.0]) -> self
-
-#         Fill the given profile with value y at position x, and optional weighting.
-
-#         """
-#         self.ptr().fill(x, y, weight)
-#         return self
-
-
-#     def reset(self):
-#         """
-#         h.reset() -> self
-
-#         Reset the histogram but leave the bin structure
-
-#         """
-#         self.ptr().reset()
-#         return self
-
-
-#     def scaleW(self, double factor):
-#         """
-#         s.scaleW(factor) -> self
-
-#         Scale the histogram and its statistics by given factor
-
-#         """
-#         self.ptr().scaleW(factor)
-#         return self
-
-
-#     def mergeBins(self, size_t a, size_t b):
-#         """
-#         s.mergeBins(from, to) -> self
-
-#         Merge bins between indexes from `from` to `to`
-
-#         """
-#         self.ptr().mergeBins(a, b)
-
-
-#     def rebin(self, int n):
-#         """
-#         s.rebin(n) -> self
-
-#         Merge every nth bin in the current histogram.
-
-#         """
-#         self.ptr().rebin(n)
-
-
-#     @property
-#     def bins(self):
-#         """
-#         h.bins -> tuple(ProfileBin1D)
-
-#         Access the bin objects of this histogram. Bin objects are mutable and
-#         changes to the bin objects will be propagated back to the histogram
-#         unless the copy() method is called on a bin.
-
-#         """
-#         cdef size_t i
-#         # cdef ProfileBin1D bin
-#         return tuple(ProfileBin1D_fromptr(& self.ptr().bin(i)) for i in xrange(self.ptr().numBins()))
-
-
-#     @property
-#     def lowEdge(self):
-#         """
-#         h.lowEdge -> float
-
-#         The x-value of the lowest edge of the lowest bin of the histogram.
-
-#         """
-#         return self.ptr().lowEdge()
-
-
-#     @property
-#     def highEdge(self):
-#         """
-#         h.highEdge -> float
-
-#         The x-value of the highest edge of the highest bin of the histogram.
-
-#         """
-#         return self.ptr().highEdge()
-
-
-#     @property
-#     def totalDbn(self):
-#         """
-#         h.totalDbn -> Distribution1D
-
-#         Return the Distribution1D object representing the total distribution.
-
-#         """
-#         return Dbn2D_fromptr(&self.ptr().totalDbn())
-
-
-#     @property
-#     def underflow(self):
-#         """
-#         h.underflow -> Distribution1D
-
-#         Return the Distribution1D object representing the underflow.
-
-#         """
-#         return Dbn2D_fromptr(&self.ptr().underflow())
-
-
-#     @property
-#     def overflow(self):
-#         """
-#         h.overflow -> Distribution1D
-
-#         Return the Distribution1D object representing the overflow.
-
-#         """
-#         return Dbn2D_fromptr(&self.ptr().overflow())
-
-
-#     # def __delitem__(self, size_t ix):
-#     #     self.ptr().eraseBin(ix)
-
-
-#     def __getitem__(self, size_t ix):
-#         return ProfileBin1D_fromptr(& self.ptr().bin(ix))
-
-
-#     def sumW(self, bool overflows=True):
-#         """
-#         s.sumW([overflows]) -> float
-
-#         Return the sum of weights of the histogram. If overflows is False,
-#         ignore over-and underflow bins.
-
-#         """
-
-#         return self.ptr().sumW(overflows)
-
-
-#     def sumW2(self, bool overflows=True):
-#         """
-#         s.sumW2([overflows]) -> float
-
-#         Return the sum of weights squared. If overflows is False, ignore
-#         over-and underflow bins.
-
-#         """
-#         return self.ptr().sumW2(overflows)
-
-
-#     def __add__(Profile1D a, Profile1D b):
-#         cdef cProfile1D *res = new cProfile1D(add(a.ptr()[0], b.ptr()[0]))
-#         return Profile1D_fromptr(res, True)
-
-
-#     def __sub__(Profile1D a, Profile1D b):
-#         cdef cProfile1D *res = new cProfile1D(subtract(a.ptr()[0], b.ptr()[0]))
-#         return Profile1D_fromptr(res, True)
-
-
-#     def __mul__(x, y):
-#         """
-#         Scalar multiplication. Equivalent to scaleW acting on a copy.
-
-#         """
-#         cdef cProfile1D *res
-#         tx, ty = type(x), type(y)
-#         if (tx is int or tx is float) and ty is Profile1D:
-#             histo = <Profile1D> y; factor = <Profile1D> x
-#         elif tx is Profile1D and (ty is int or ty is float):
-#             histo = <Profile1D> x; factor = <Profile1D> y
-#         else:
-#             raise RuntimeError('Cannot multiply %r by %r' % (tx, ty))
-
-#         res = new cProfile1D(histo.ptr()[0])
-#         res.scaleW(factor)
-#         return Profile1D_fromptr(res, True)
-
-
-#     def _div_scalar(Profile1D x, double y):
-#         if y == 0:
-#             raise ArithmeticError('Profile1D: Divide by zero scalar')
-
-#         cdef cProfile1D *res = new cProfile1D(x.ptr()[0])
-
-#         res.scaleW(1.0 / y)
-#         return Profile1D_fromptr(res, True)
-
-
-#     def _div_profile(Profile1D x, Profile1D y):
-#         cdef cScatter2D s = divide(x.ptr()[0], y.ptr()[0])
-#         return Scatter2D_fromptr(&s)
-
-
-#     def __div__(x, y):
-#         """
-#         Division by scalar (i.e. multiplication by reciprocal) or another
-#         1D histogram.
-
-#         """
-#         tx = type(x); ty = type(y)
-#         if tx is Profile1D:
-#             if ty is int or ty is float:
-#                 return x._div_scalar(y)
-#             elif ty is Profile1D:
-#                 return x._div_profile(y)
-#         raise RuntimeError('Cannot multiply %r by %r' % (tx, ty))
-
-
-#     def __repr__(self):
-#         return 'Profile1D%r' % self.bins
-
-
-# cdef Profile1D Profile1D_fromptr(cProfile1D *ptr, bool dealloc=False):
-#     cdef Profile1D profile = Profile1D.__new__(Profile1D)
-#     return profile.setptr(ptr, dealloc)
+cdef Profile2D Profile2D_fromptr(cProfile2D *ptr, dealloc=False):
+    # Construct a Python Profile2D from a pointer to a cProfile2D,
+    # without calling __init__ and excessive memory allocation
+    cdef Profile2D bin = Profile2D.__new__(Profile2D)
+    return bin.setptr(ptr, dealloc)

Modified: trunk/pyext/yoda/shims.h
==============================================================================
--- trunk/pyext/yoda/shims.h	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/pyext/yoda/shims.h	Mon Jul 23 14:41:42 2012	(r511)
@@ -11,9 +11,9 @@
 #include "YODA/ProfileBin1D.h"
 
 // 2D
-// #include "YODA/Histo2D.h"
-// #include "YODA/Profile2D.h"
-// #include "YODA/Scatter3D.h"
+#include "YODA/Histo2D.h"
+#include "YODA/Profile2D.h"
+#include "YODA/Scatter3D.h"
 #include "YODA/HistoBin2D.h"
 #include "YODA/ProfileBin2D.h"
 
@@ -77,3 +77,15 @@
 Scatter2D Scatter2D_mkScatter(const Histo1D& h) {
   return YODA::mkScatter(h);
 }
+
+// Scatter2D Scatter2D_mkScatter(const Profile1D& p) {
+//   return YODA::mkScatter(p);
+// }
+
+// Scatter3D Scatter3D_mkScatter(const Histo2D& h) {
+//   return YODA::mkScatter(h);
+// }
+
+// Scatter3D Scatter3D_mkScatter(const Profile2D& p) {
+//   return YODA::mkScatter(p);
+// }

Modified: trunk/src/Histo2D.cc
==============================================================================
--- trunk/src/Histo2D.cc	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/src/Histo2D.cc	Mon Jul 23 14:41:42 2012	(r511)
@@ -6,6 +6,7 @@
 #include "YODA/Histo2D.h"
 #include "YODA/Scatter3D.h"
 #include <cmath>
+
 using namespace std;
 
 namespace YODA {
@@ -101,6 +102,18 @@
   }
 
 
+  // double Profile2D::xRMS(bool includeoverflows) const {
+  //   if (includeoverflows) return _axis.totalDbn().xRMS();
+  //   /// @todo Finish
+  // }
+
+
+  // double Profile2D::yRMS(bool includeoverflows) const {
+  //   if (includeoverflows) return _axis.totalDbn().yRMS();
+  //   /// @todo Finish
+  // }
+
+
   /////////////////////////////////////
 
 
@@ -266,6 +279,7 @@
 
 
   Scatter3D divide(const Histo2D& numer, const Histo2D& denom) {
+    /// @todo Don't abuse equality operator -- test *axis* compatibility
     if (numer != denom) throw GridError("The two histos are not equivalently binned!");
     Scatter3D tmp;
     for (size_t i = 0; i < numer.numBins(); ++i) {

Modified: trunk/src/Profile2D.cc
==============================================================================
--- trunk/src/Profile2D.cc	Mon Jul 23 10:50:37 2012	(r510)
+++ trunk/src/Profile2D.cc	Mon Jul 23 14:41:42 2012	(r511)
@@ -1,3 +1,8 @@
+// -*- C++ -*-
+//
+// This file is part of YODA -- Yet more Objects for Data Analysis
+// Copyright (C) 2008-2012 The YODA collaboration (see AUTHORS for details)
+//
 #include "YODA/Profile2D.h"
 #include "YODA/Scatter3D.h"
 #include "YODA/Histo2D.h"
@@ -28,9 +33,7 @@
   double Profile2D::sumW(bool includeoverflows) const {
     if (includeoverflows) return _axis.totalDbn().sumW2();
     double sumw = 0;
-    foreach (const ProfileBin2D& b, bins()) {
-      sumw += b.sumW();
-    }
+    foreach (const ProfileBin2D& b, bins()) sumw += b.sumW();
     return sumw;
   }
 
@@ -38,13 +41,83 @@
   double Profile2D::sumW2(bool includeoverflows) const {
     if (includeoverflows) return _axis.totalDbn().sumW2();
     double sumw = 0;
-    foreach (const ProfileBin2D& b, bins()) {
-      sumw += b.sumW();
-    }
+    foreach (const ProfileBin2D& b, bins()) sumw += b.sumW();
     return sumw;
   }
 
 
+  double Profile2D::xMean(bool includeoverflows) const {
+    if (includeoverflows) return _axis.totalDbn().xMean();
+    double sumwx = 0;
+    foreach (const ProfileBin2D& b, bins()) sumwx += b.sumWX();
+    return sumwx/sumW();
+  }
+
+
+  double Profile2D::yMean(bool includeoverflows) const {
+    if (includeoverflows) return _axis.totalDbn().yMean();
+    double sumwy = 0;
+    foreach (const ProfileBin2D& b, bins()) sumwy += b.sumWY();
+    return sumwy/sumW();
+  }
+
+
+  double Profile2D::xVariance(bool includeoverflows) const {
+    if (includeoverflows) return _axis.totalDbn().xVariance();
+    /// @todo Improve this, by adding the Dbn2Ds and returning the resulting xVariance
+    double sigma2 = 0;
+    const double xMean = this->xMean();
+    for (size_t i = 0; i < bins().size(); ++i) {
+      const double diff = bin(i).focus().first - xMean;
+      sigma2 += diff * diff * bin(i).sumW();
+    }
+    return sigma2/sumW();
+  }
+
+
+  double Profile2D::yVariance(bool includeoverflows) const {
+    if (includeoverflows) return _axis.totalDbn().yVariance();
+    /// @todo Improve this, by adding the Dbn2Ds and returning the resulting yVariance
+    double sigma2 = 0;
+    const double yMean = this->yMean();
+    for (size_t i = 0; i < bins().size(); ++i) {
+      const double diff = bin(i).focus().first - yMean;
+      sigma2 += diff * diff * bin(i).sumW();
+    }
+    return sigma2/sumW();
+  }
+
+
+  double Profile2D::xStdErr(bool includeoverflows) const {
+    if (includeoverflows) return _axis.totalDbn().xStdErr();
+    const double effNumEntries = sumW(false)*sumW(false)/sumW2(false);
+    return std::sqrt(xVariance(false) / effNumEntries);
+  }
+
+
+  double Profile2D::yStdErr(bool includeoverflows) const {
+    if (includeoverflows) return _axis.totalDbn().yStdErr();
+    const double effNumEntries = sumW(false)*sumW(false)/sumW2(false);
+    return std::sqrt(yVariance(false) / effNumEntries);
+  }
+
+
+  // double Profile2D::xRMS(bool includeoverflows) const {
+  //   if (includeoverflows) return _axis.totalDbn().xRMS();
+  //   /// @todo Finish
+  // }
+
+
+  // double Profile2D::yRMS(bool includeoverflows) const {
+  //   if (includeoverflows) return _axis.totalDbn().yRMS();
+  //   /// @todo Finish
+  // }
+
+
+
+  /////////////////////////////////////
+
+
   /// A copy constructor with optional new path
   Profile2D::Profile2D(const Profile2D& p, const std::string& path)
     : AnalysisObject("Profile2D", p.path(), p, p.title()), _axis(p._axis)
@@ -77,9 +150,10 @@
 
   /// Divide two profile histograms
   Scatter3D divide(const Profile2D& numer, const Profile2D& denom) {
-    /// @todo TODO
+    /// @todo TODO -- implement!
 
     /// @todo Check that bins match
+    /// @todo Don't abuse equality operator -- test *axis* compatibility
 
     Scatter3D tmp;
     // for (size_t i = 0; i < numer.numBins(); ++i) {


More information about the yoda-svn mailing list