[yoda-svn] r390 - in trunk: pyext src

blackhole at projects.hepforge.org blackhole at projects.hepforge.org
Sat Sep 3 15:07:14 BST 2011


Author: davemallows
Date: Sat Sep  3 15:07:14 2011
New Revision: 390

Log:
More work on python bindings: mapped Histo1D ~pythonically.

Modified:
   trunk/pyext/cyoda.pxd
   trunk/pyext/yoda.pyx
   trunk/src/Histo1D.cc

Modified: trunk/pyext/cyoda.pxd
==============================================================================
--- trunk/pyext/cyoda.pxd	Sat Sep  3 01:22:57 2011	(r389)
+++ trunk/pyext/cyoda.pxd	Sat Sep  3 15:07:14 2011	(r390)
@@ -1,6 +1,7 @@
 from libcpp.vector cimport vector
 from libcpp.string cimport string
 from libcpp.pair cimport pair
+from libcpp cimport bool
 
 cdef extern from "YODA/AnalysisObject.h" namespace "YODA":
     cdef cppclass AnalysisObject:
@@ -11,9 +12,10 @@
         vector[AnalysisObject *] read(string filename)
 
 cdef extern from "YODA/Scatter2D.h" namespace "YODA":
-    cdef cppclass Scatter2D:
+    cdef cppclass Scatter2D(AnalysisObject):
         size_t numPoints()
         vector[Point2D] points()
+        Scatter2D (Scatter2D &s)
 
 cdef extern from "YODA/Point2D.h" namespace "YODA":
     cdef cppclass Point2D:
@@ -27,3 +29,51 @@
 
 cdef extern from "YODA/ReaderAIDA.h" namespace "YODA::ReaderAIDA":
     Reader& create()
+
+cdef extern from "YODA/Dbn1D.h" namespace "YODA":
+    cdef cppclass Dbn1D:
+        pass
+
+cdef extern from "YODA/HistoBin1D.h" namespace "YODA":
+    cdef cppclass HistoBin1D:
+        HistoBin1D (HistoBin1D &h)
+        double area()
+        double height()
+        double areaErr()
+        double heightErr()
+        HistoBin1D operator + (HistoBin1D &, HistoBin1D &)
+        HistoBin1D operator - (HistoBin1D &, HistoBin1D&)
+        pass
+
+cdef extern from "YODA/Histo1D.h" namespace "YODA":
+    Histo1D add(Histo1D &, Histo1D &)
+    Histo1D subtract(Histo1D &, Histo1D &)
+    Scatter2D divide(Histo1D &, Histo1D &)
+
+    cdef cppclass Histo1D(AnalysisObject):
+        Histo1D(size_t nbins, double lower, double upper, string &path,
+                string &title)
+        Histo1D(vector[double] &binedges, string &path, string &title)
+        Histo1D(vector[double] &binedges)
+        Histo1D(Histo1D &h, string &path)
+        Histo1D(Histo1D &h)
+        void fill(double x, 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[HistoBin1D] &bins()
+        Dbn1D &underflow()
+        Dbn1D &overflow()
+        void eraseBin(size_t index)
+        # Statistical functions
+        double integral(bool includeoverflows)
+        double integral(size_t a, size_t b)
+        double sumW(bool includeoverflows)
+        double sumW2(bool includeoverflows)
+        double variance(bool includeoverflows)
+        double stdDev(bool includeoverflows)

Modified: trunk/pyext/yoda.pyx
==============================================================================
--- trunk/pyext/yoda.pyx	Sat Sep  3 01:22:57 2011	(r389)
+++ trunk/pyext/yoda.pyx	Sat Sep  3 15:07:14 2011	(r390)
@@ -2,12 +2,17 @@
 from libcpp.vector cimport vector
 from libcpp.string cimport string
 from libcpp.pair cimport pair
+from libcpp cimport bool
 
 cdef class AnalysisObject:
     """Base object class"""
     cdef cyoda.AnalysisObject *thisptr
 
+    @property
     def type(self):
+        return self.type_()
+
+    cdef str type_(self):
         return self.thisptr.type().c_str()
 
 cdef class Point2D:
@@ -44,6 +49,10 @@
     cdef cyoda.Scatter2D * ptr(self):
         return <cyoda.Scatter2D *> self.thisptr
 
+    cdef setptr(self, cyoda.Scatter2D *ptr):
+        self.thisptr = <cyoda.AnalysisObject *> ptr
+        return self
+
     @property
     def points(self):
         cdef vector[cyoda.Point2D] vec
@@ -59,6 +68,9 @@
 
         return out
 
+    def __repr__(self):
+        return 'Scatter2D%r' % self.points
+
 cdef class ReaderAIDA:
     def read(self, char *filename):
         cdef vector[cyoda.AnalysisObject *] vec
@@ -67,8 +79,6 @@
         out = []
         for i in range(vec.size()):
             if str(vec[i].type().c_str()) == 'Scatter2D':
-                print (<cyoda.Scatter2D *> vec[i]).points().at(0).x(),\
-                      (<cyoda.Scatter2D *> vec[i]).points().at(0).y()
                 ana = Scatter2D()
             else:
                 ana = AnalysisObject()
@@ -78,3 +88,182 @@
             out.append(ana)
 
         return out
+
+
+cdef class Histo1D(AnalysisObject):
+    def __cinit__(self, *args, **kwargs):
+        cdef:
+            size_t nbins
+            double lower
+            double upper
+            char* path = '/'
+            char* title = ''
+
+        if len(args) == 3:
+            nbins, lower, upper = args[0], args[1], args[2]
+
+            self.setptr(
+                new cyoda.Histo1D(nbins, lower, upper, string(path), string(title))
+            )
+
+    cdef cyoda.Histo1D* ptr(self):
+        return <cyoda.Histo1D *> self.thisptr
+
+    cdef setptr(self, cyoda.Histo1D *ptr):
+        self.thisptr = ptr
+        return self
+    
+    def fill(self, double x, double weight=1.0):
+        self.ptr().fill(x, weight)
+
+    def reset(self):
+        """Reset the histogram but leave the bin structure"""
+        self.ptr().reset()
+
+    def scaleW(self, double factor):
+        """Scale the histogram and its statistics by given factor"""
+        self.ptr().scaleW(factor)
+
+    def mergeBins(self, size_t a, size_t b):
+        self.ptr().mergeBins(a, b)
+
+    def rebin(self, int n):
+        self.ptr().rebin(n)
+
+    @property
+    def bins(self):
+        cdef size_t numbins = self.ptr().numBins()
+        cdef size_t i
+        
+        cdef vector[cyoda.HistoBin1D] bins = self.ptr().bins()
+
+        cdef cyoda.HistoBin1D *b
+
+        out = []
+
+        for i in range(numbins):
+            out.append(HistoBin1D().set(bins[i]))
+
+        return out
+    
+    @property
+    def lowEdge(self):
+        return self.ptr().lowEdge()
+
+    @property
+    def highEdge(self):
+        return self.ptr().highEdge()
+
+    def underflow(self):
+        pass
+
+    def __delitem__(self, size_t ix):
+        self.ptr().eraseBin(ix)
+
+    def __getitem__(self, size_t ix):
+        return HistoBin1D().set(self.ptr().bins()[ix])
+
+    def integral(self, bool overflows=True):
+        return self.ptr().integral(overflows)
+
+    def sumW(self, bool overflows=True):
+        return self.ptr().sumW(overflows)
+
+    def sumW2(self, bool overflows=True):
+        return self.ptr().sumW2(overflows)
+
+    def variance(self, bool overflows=True):
+        return self.ptr().variance(overflows)
+
+    def stdDev(self, bool overflows=True):
+        return self.ptr().stdDev(overflows)
+
+    def __add__(Histo1D a, Histo1D b):
+        cdef cyoda.Histo1D *res
+        res = new cyoda.Histo1D(cyoda.add(a.ptr()[0], b.ptr()[0]))
+        return Histo1D().setptr(res)
+
+    def __sub__(Histo1D a, Histo1D b):
+        cdef cyoda.Histo1D *res
+        res = new cyoda.Histo1D(cyoda.subtract(a.ptr()[0], b.ptr()[0]))
+        return Histo1D().setptr(res)
+
+    def __mul__(x, y):
+        cdef cyoda.Histo1D *res
+        tx, ty = type(x), type(y)
+        if (tx is int or tx is float) and ty is Histo1D:
+            histo = <Histo1D> y; factor = <Histo1D> x
+        elif tx is Histo1D and (ty is int or ty is float):
+            histo = <Histo1D> x; factor = <Histo1D> y
+        else:
+            raise RuntimeError('Cannot multiply %r by %r' % (tx, ty))
+
+        print histo, factor
+        res = new cyoda.Histo1D(histo.ptr()[0])
+        res.scaleW(factor)
+        return Histo1D().setptr(res)
+
+    def _div_scalar(Histo1D x, double y):
+        cdef cyoda.Histo1D *res = new cyoda.Histo1D(x.ptr()[0])
+        if y == 0:
+            raise ArithmeticError('Histo1D: Divide by zero scalar')
+        res.scaleW(1.0 / y)
+        return Histo1D().setptr(res)
+
+    def _div_histo(Histo1D x, Histo1D y):
+        cdef cyoda.Scatter2D *res
+
+        res = new cyoda.Scatter2D(cyoda.divide(x.ptr()[0], y.ptr()[0]))
+        return Scatter2D().setptr(res)
+
+    def __div__(x, y):
+        tx = type(x); ty = type(y)
+        if tx is Histo1D:
+            if ty is int or ty is float:
+                return x._div_scalar(y)
+            elif ty is Histo1D:
+                return x._div_histo(y)
+        
+        raise RuntimeError('Cannot multiply %r by %r' % (tx, ty))
+    
+    def __repr__(self):
+        return 'Histo1D%r' % self.bins
+
+
+cdef class Dbn1D:
+    pass
+
+cdef class Bin1D:
+    pass
+         
+cdef class HistoBin1D(Bin1D):
+    cdef cyoda.HistoBin1D *thisptr
+
+    cdef setptr(self, cyoda.HistoBin1D *ptr):
+        return self
+
+    cdef set(self, cyoda.HistoBin1D ptr):
+        self.thisptr = new cyoda.HistoBin1D(ptr)
+        return self
+
+    cdef cyoda.HistoBin1D* ptr(self):
+        return self.thisptr
+
+    @property
+    def area(self):
+        return self.ptr().area()
+
+    @property
+    def height(self):
+        return self.ptr().height()
+
+    @property
+    def heightErr(self):
+        return self.ptr().heightErr()
+
+    @property
+    def areaErr(self):
+        return self.ptr().areaErr()
+
+    def __repr__(self):
+        return 'HistoBin1D(%r)' % self.area

Modified: trunk/src/Histo1D.cc
==============================================================================
--- trunk/src/Histo1D.cc	Sat Sep  3 01:22:57 2011	(r389)
+++ trunk/src/Histo1D.cc	Sat Sep  3 15:07:14 2011	(r390)
@@ -13,10 +13,8 @@
 
 namespace YODA {
 
-
   // typedef vector<HistoBin1D> Bins;
 
-
   void Histo1D::fill(double x, double weight) {
     // Fill the underflow and overflow nicely
     _axis.totalDbn().fill(x, weight);
@@ -152,7 +150,7 @@
         break;
       }
 
-      tmp.addPoint(x, exminus, explus, y, ey, ey);
+      tmp.addPoint(x, y, exminus, explus, ey, ey);
 
     }
     assert(tmp.numPoints() == numer.numBins());


More information about the yoda-svn mailing list