|
[yoda-svn] r405 - in trunk/pyext/yoda: . includeblackhole at projects.hepforge.org blackhole at projects.hepforge.orgTue Nov 8 02:29:59 GMT 2011
Author: davemallows Date: Tue Nov 8 02:29:58 2011 New Revision: 405 Log: Updated cython bindings Added: trunk/pyext/yoda/include/00-imports.pyx trunk/pyext/yoda/include/40-WriterAIDA.pyx trunk/pyext/yoda/include/99-ReaderAIDA.pyx trunk/pyext/yoda/shims.h Deleted: trunk/pyext/yoda/imports.pyx trunk/pyext/yoda/include/40-ReaderAIDA.pyx trunk/pyext/yoda/yoda.cpp trunk/pyext/yoda/yoda.pyx Modified: trunk/pyext/yoda/Makefile.am trunk/pyext/yoda/include/10-AnalysisObject.pyx trunk/pyext/yoda/include/20-Point2D.pyx trunk/pyext/yoda/include/30-HistoBin1D.pyx trunk/pyext/yoda/include/30-HistoBin2D.pyx trunk/pyext/yoda/include/30-Scatter2D.pyx trunk/pyext/yoda/include/40-Histo1D.pyx trunk/pyext/yoda/include/40-Histo2D.pyx Modified: trunk/pyext/yoda/Makefile.am ============================================================================== --- trunk/pyext/yoda/Makefile.am Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/Makefile.am Tue Nov 8 02:29:58 2011 (r405) @@ -4,8 +4,9 @@ yoda.cpp: yoda.pyx $(PYTHON) -m cython --cplus yoda.pyx -yoda.pyx: imports.pyx include/10-AnalysisObject.pyx include/20-Dbn1D.pyx include/20-Point2D.pyx include/30-HistoBin1D.pyx include/30-HistoBin2D.pyx include/30-Reader.pyx include/30-Scatter2D.pyx include/40-Histo1D.pyx include/40-Histo2D.pyx include/40-ReaderAIDA.pyx - cat imports.pyx include/*.pyx > yoda.pyx +yoda.pyx: include/00-imports.pyx include/10-AnalysisObject.pyx include/20-Dbn1D.pyx include/20-Point2D.pyx include/30-HistoBin1D.pyx include/30-HistoBin2D.pyx include/30-Reader.pyx include/30-Scatter2D.pyx include/40-Histo1D.pyx include/40-Histo2D.pyx include/40-WriterAIDA.pyx include/99-ReaderAIDA.pyx + cat include/*.pyx > yoda.pyx clean-local: rm yoda.cpp yoda.pyx + Added: trunk/pyext/yoda/include/00-imports.pyx ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/pyext/yoda/include/00-imports.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -0,0 +1,4 @@ +from libcpp.vector cimport vector +from string cimport string +from libcpp.pair cimport pair +from libcpp cimport bool Modified: trunk/pyext/yoda/include/10-AnalysisObject.pyx ============================================================================== --- trunk/pyext/yoda/include/10-AnalysisObject.pyx Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/include/10-AnalysisObject.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -2,15 +2,29 @@ cdef cppclass cAnalysisObject "YODA::AnalysisObject": string type() -ctypedef cAnalysisObject* AOptr +ctypedef cAnalysisObject* AOptr cdef class AnalysisObject: """Base object class""" cdef cAnalysisObject *thisptr + cdef bool _dealloc + + def __cinit__(self): + self._dealloc = False @property def type(self): """The type of this analysis object as a string""" return self.thisptr.type().c_str() - # TODO: Map annotations, etc. + def __dealloc__(self): + if self._dealloc: + del self.thisptr + + cdef AnalysisObject setptr(self, AOptr ptr, dealloc=False): + if self._dealloc: + del self.thisptr + + self.thisptr = ptr + self._dealloc = dealloc + return self Modified: trunk/pyext/yoda/include/20-Point2D.pyx ============================================================================== --- trunk/pyext/yoda/include/20-Point2D.pyx Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/include/20-Point2D.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -21,10 +21,26 @@ cdef class Point2D: cdef cPoint2D* thisptr + cdef bool _dealloc + + cdef cPoint2D* ptr(self): + return self.thisptr + + cdef Point2D setptr(self, cPoint2D* ptr, dealloc=False): + if self._dealloc: + del self.thisptr + + self.thisptr = ptr + self._dealloc = dealloc + return self + def __cinit__(self): - self.thisptr = new cPoint2D() + self._dealloc = False def __init__(self, *args): + self.setptr(new cPoint2D(), True) + self._dealloc = True + if len(args) == 0: self.pos = 0, 0 elif len(args) == 2 : @@ -39,18 +55,22 @@ else: raise ValueError( 'Wrong number of values: can take 2, 4, or 6 parameters') + + def __dealloc__(self): + if self._dealloc: + del self.thisptr def _x(self): - return self.thisptr.x() + return self.ptr().x() def _y(self): - return self.thisptr.y() + return self.ptr().y() def _setX(self, double x): - self.thisptr.setX(x) + self.ptr().setX(x) def _setY(self, double y): - self.thisptr.setY(y) + self.ptr().setY(y) x = property(_x, _setX) y = property(_y, _setY) @@ -62,14 +82,14 @@ def _setPos(self, pos): cdef double x, y x, y = pos - self.thisptr.setX(x) - self.thisptr.setY(y) + self.ptr().setX(x) + self.ptr().setY(y) pos = property(_pos, _setPos) def _xErrs(self): """The x-errors as a 2-tuple (low, high)""" - cdef pair[double, double] xErrs = self.thisptr.xErrs() + cdef pair[double, double] xErrs = self.ptr().xErrs() return (xErrs.first, xErrs.second) def _setxErrs(self, arg): @@ -79,13 +99,13 @@ low = arg high = arg - self.thisptr.setXErr(low, high) + self.ptr().setXErr(low, high) xErrs = property(_xErrs, _setxErrs) def _yErrs(self): """The y-errors as a 2-tuple (low, high)""" - cdef pair[double, double] yErrs = self.thisptr.yErrs() + cdef pair[double, double] yErrs = self.ptr().yErrs() return (yErrs.first, yErrs.second) def _setyErrs(self, arg): @@ -96,12 +116,13 @@ low = arg high = arg - self.thisptr.setYErr(low, high) + self.ptr().setYErr(low, high) yErrs = property(_yErrs, _setyErrs) def __repr__(self): return 'Point2D({0},{1})'.format(self.x, self.y) - def __dealloc__(self): - del self.thisptr +cdef Point2D Point2D_fromptr(cPoint2D *ptr, dealloc = False): + cdef Point2D p = Point2D.__new__(Point2D) + return p.setptr(ptr, dealloc) Modified: trunk/pyext/yoda/include/30-HistoBin1D.pyx ============================================================================== --- trunk/pyext/yoda/include/30-HistoBin1D.pyx Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/include/30-HistoBin1D.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -2,6 +2,7 @@ cdef cppclass cHistoBin1D "YODA::HistoBin1D": cHistoBin1D (cHistoBin1D &h) + cHistoBin1D (double, double) double area() double height() double areaErr() @@ -31,27 +32,28 @@ double sumWX() double sumWX2() -# Disabled to work with Cython 0.13 -#cdef extern from "YODA/HistoBin1D.h" namespace "YODA::HistoBin1D": -# cHistoBin1D operator + (cHistoBin1D &, cHistoBin1D &) -# cHistoBin1D operator - (cHistoBin1D &, cHistoBin1D &)""" - -# TODO: re-enable these operators using a c++ shim like -#using namespace YODA -#Histo1D add__Histo1D(Histo1D a, Histo1D b) -#{ -# return YODA::Histo1D::add(a, b); -#} - +#Ugly hack using shim header for Cython 0.13 +cdef extern from "shims.h": + cHistoBin1D add_HistoBin1D (cHistoBin1D &, cHistoBin1D &) + cHistoBin1D subtract_HistoBin1D (cHistoBin1D &, cHistoBin1D &) cdef class HistoBin1D: cdef cHistoBin1D *thisptr + cdef bool _dealloc - cdef setptr(self, cHistoBin1D *ptr): - return self + def __cinit__(self): + self._dealloc = False + + def __dealloc__(self): + if self._dealloc: + del self.thisptr - cdef set(self, cHistoBin1D ptr): - self.thisptr = new cHistoBin1D(ptr) + cdef HistoBin1D setptr(self, cHistoBin1D *ptr, bool dealloc): + if self._dealloc: + del self.thisptr + + self.thisptr = ptr + self._dealloc = dealloc return self cdef cHistoBin1D* ptr(self): @@ -59,82 +61,144 @@ @property def lowEdge(self): + """The lower of the two bin edges.""" return self.ptr().lowEdge() xMin = lowEdge @property def highEdge(self): + """The higher of the two bin edges.""" return self.ptr().highEdge() xMax = highEdge @property def width(self): + """The width of the bin.""" return self.ptr().width() @property def focus(self): + """The focus of the bin.""" return self.ptr().focus() @property def midpoint(self): + """The point half-way between the bin edges.""" return self.ptr().midpoint() @property def xMean(self): + """The mean of the x-values that have filled the bin.""" return self.ptr().xMean() @property def xVariance(self): + """The variance of the x-values that have filled the bin.""" return self.ptr().xVariance() @property def xStdDev(self): + """The standard deviation of the x-values that have filled the bin.""" return self.ptr().xStdDev() @property def numEntries(self): + """The number of entries in the bin.""" return self.ptr().numEntries() @property def effNumEntries(self): + """The effective number of entries in the bin. This is + (s.sumW)**2 / s.sumW2""" return self.ptr().effNumEntries() @property def sumW(self): + """Sum of weights.""" return self.ptr().sumW() @property def sumW2(self): + """Sum of weights squared.""" return self.ptr().sumW2() @property def sumWX(self): + """Sum of the products of x-values and their weights.""" return self.ptr().sumWX() @property def sumWX2(self): + """Sum of the products of x-values squared and their weights.""" return self.ptr().sumWX2() @property def area(self): + """ + b.area <==> b.sumW + + The area of the bin is the sum of weights of the bin; it is + independent of width. + + """ return self.ptr().area() @property def height(self): + """ + b.height <==> b.area / b.width + + The height of the bin is defined as the area divided by the + width. + + """ return self.ptr().height() @property + def areaErr(self): + """ + Error computed using binomial statistics on squared sum of bin weights, + i.e. s.areaErr = sqrt(s.sumW2) + + """ + return self.ptr().areaErr() + + @property def heightErr(self): + """ + Height error - scales the s.areaError by the reciprocal of the + bin width. + + """ return self.ptr().heightErr() - @property - def areaErr(self): - return self.ptr().areaErr() def scaleX(self, double factor): + """ + bin.scaleX(factor) -> bin + + Scale the x-axis of `bin` in-place by `factor`. + + """ + self.ptr().scaleX(factor) + + def scaleW(self, double factor): + """ + bin.scaleW(factor) -> bin + + Scale `bin` in-place as if all weights were scaled by given `factor` + + """ self.ptr().scaleX(factor) def __repr__(self): return 'HistoBin1D(%r)' % self.area + +cdef HistoBin1D HistoBin1D_fromptr(cHistoBin1D *ptr, dealloc=False): + # Construct a Python HistoBin1D from a pointer to a cHistoBin1D, + # without calling __init__ and excessive memory allocation + cdef HistoBin1D bin = HistoBin1D.__new__(HistoBin1D) + return bin.setptr(ptr, dealloc) + Modified: trunk/pyext/yoda/include/30-HistoBin2D.pyx ============================================================================== --- trunk/pyext/yoda/include/30-HistoBin2D.pyx Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/include/30-HistoBin2D.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -47,10 +47,23 @@ double sumWXY() double sumWX2() double sumWY2() + cdef class HistoBin2D: cdef cHistoBin2D *thisptr - cdef setptr(self, cHistoBin2D *ptr): + def __cinit__(self): + self._dealloc = False + + def __dealloc__(self): + if self._dealloc: + del self.thisptr + + cdef HistoBin2D setptr(self, cHistoBin2D *ptr, bool dealloc): + if self._dealloc: + del self.thisptr + + self.thisptr = ptr + self._dealloc = dealloc return self cdef set(self, cHistoBin2D ptr): @@ -79,7 +92,6 @@ def scaleW(self, double factor): self.ptr().scaleW(factor) - @property def lowEdgeX(self): return self.ptr().lowEdgeX() @@ -88,7 +100,6 @@ def highEdgeX(self): return self.ptr().highEdgeX() - @property def lowEdgeY(self): return self.ptr().lowEdgeY() @@ -192,3 +203,9 @@ def __repr__(self): return 'HistoBin2D(%r)' % self.volume + +cdef HistoBin2D HistoBin2D_fromptr(cHistoBin2D *ptr, dealloc=False): + # Construct a Python HistoBin2D from a pointer to a cHistoBin2D, + # without calling __init__ and excessive memory allocation + cdef HistoBin2D bin = HistoBin2D.__new__(HistoBin2D) + return bin.setptr(ptr, dealloc) Modified: trunk/pyext/yoda/include/30-Scatter2D.pyx ============================================================================== --- trunk/pyext/yoda/include/30-Scatter2D.pyx Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/include/30-Scatter2D.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -2,37 +2,72 @@ cdef cppclass cScatter2D "YODA::Scatter2D" (cAnalysisObject): size_t numPoints() vector[cPoint2D] points() + cPoint2D& point(size_t i) cScatter2D (cScatter2D &s) + cScatter2D (vector[cPoint2D]&, string, string) + cScatter2D () cdef class Scatter2D(AnalysisObject): + cdef tuple _points - cdef cScatter2D * ptr(self): - return <cScatter2D *> self.thisptr + def __init__(self, points, char *path="", char *title=""): + points = tuple(points) - cdef setptr(self, cScatter2D *ptr): - self.thisptr = ptr - return self + cdef size_t N = len(points) + cdef vector[cPoint2D] point_vector = vector[cPoint2D](N) + cdef Point2D item + cdef cScatter2D *scatter + cdef int i + for i in range(N): + item = points[i] + point_vector[i] = item.ptr()[0] + + scatter = new cScatter2D(point_vector, string(path), string(title)) + self.setptr(scatter, True) + + self._points = points @property def numPoints(self): return self.ptr().numPoints() + + cdef cScatter2D * ptr(self): + return <cScatter2D *> self.thisptr + + def __getitem__(self, args): + return self.points.__getitem__(args) + + def copy(self): + return Scatter2D_fromptr(new cScatter2D(self.ptr()[0]), True) @property def points(self): - cdef vector[cPoint2D] vec - cdef int i - cdef cPoint2D *p - vec = self.ptr().points() - out = [] - for i in range(vec.size()): - pt = Point2D() - pt.thisptr[0] = vec[i] - out.append(pt) - - return out + cdef size_t i + cdef Point2D pt + if self._points: + return self._points + else: + out = [] + + for i in range(self.ptr().numPoints()): + pt = Point2D_fromptr(& self.ptr().point(i)) + out.append(pt) + + out = tuple(out) + self._points = out + return out def __repr__(self): - return 'Scatter2D%r' % self.points + return '<Scatter2D>' - def __dealloc__(self): - del self.thisptr + +# dealloc decides whether or not the python object is responsible for freeing +# used memory. Most times, it's not - we're just wrapping a C++ instance. +# However, the same classes should be used for both wrapping and creating. + +# It is important that we do free allocated C++ memory, because otherwise we can +# quickly end up with memory leaks. + +cdef Scatter2D Scatter2D_fromptr(cScatter2D* ptr, dealloc = False): + cdef Scatter2D scatter = Scatter2D.__new__(Scatter2D) + return scatter.setptr(ptr, False) Modified: trunk/pyext/yoda/include/40-Histo1D.pyx ============================================================================== --- trunk/pyext/yoda/include/40-Histo1D.pyx Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/include/40-Histo1D.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -1,5 +1,4 @@ cdef extern from "YODA/Histo1D.h" namespace "YODA": - # TODO: We can use these in place of the workaround when Cython 0.15 is available #cHisto1D operator + (cHisto1D &, cHisto1D &) #cHisto1D operator - (cHisto1D &, cHisto1D &) #cScatter2D operator / (cHisto1D &, cHisto1D &)""" @@ -23,6 +22,7 @@ double lowEdge() double highEdge() vector[cHistoBin1D] &bins() + cHistoBin1D & bin "bin"(size_t i) cDbn1D &underflow() cDbn1D &overflow() void eraseBin(size_t index) @@ -35,8 +35,17 @@ double variance(bool includeoverflows) double stdDev(bool includeoverflows) +cdef extern from "shims.h": + cHisto1D add_Histo1D (cHisto1D &, cHisto1D &) + cHisto1D subtract_Histo1D (cHisto1D &, cHisto1D &) + cScatter2D divide_Histo1D (cHisto1D &, cHisto1D &) + cScatter2D Scatter2D_mkScatter(cHisto1D &) + +from cython.operator cimport dereference as deref + cdef class Histo1D(AnalysisObject): - def __cinit__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): + self._dealloc = True cdef: size_t nbins double lower @@ -55,89 +64,201 @@ cdef cHisto1D* ptr(self): return <cHisto1D *> self.thisptr - - cdef setptr(self, cHisto1D *ptr): - self.thisptr = ptr - return self + + def asScatter(self): + """ + h.asScatter() -> Scatter2D + + Return a 2D scatter data object from the histogram's bins and heights + + """ + cdef cScatter2D *s = new cScatter2D() + s[0] = Scatter2D_mkScatter(self.ptr()[0]) + return Scatter2D_fromptr(s, True) def fill(self, double x, double weight=1.0): + """ + h.fill(x[, weight=1.0]) -> self + + Fill the given histogram with value x and optional weighting + + """ self.ptr().fill(x, weight) + return self def reset(self): - """Reset the histogram but leave the bin structure""" + """ + h.reset() -> self + + Reset the histogram but leave the bin structure + + """ self.ptr().reset() + return self def scaleW(self, double factor): - """Scale the histogram and its statistics by given 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): - cdef size_t numbins = self.ptr().numBins() - cdef size_t i + """ + h.bins -> tuple(HistoBin1D) + + 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 vector[cHistoBin1D] bins = self.ptr().bins() + """ - cdef cHistoBin1D *b + + cdef size_t numbins = self.ptr().numBins() + cdef size_t i + cdef HistoBin1D bin out = [] for i in range(numbins): - out.append(HistoBin1D().set(bins[i])) + bin = HistoBin1D_fromptr(& self.ptr().bins()[i]) + out.append(bin) + self.ptr().bins() return out - + @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): - return self.ptr().highEdge() + """ + h.highEdge -> float + The x-value of the highest edge of the highest bin of the histogram. + + """ + return self.ptr().highEdge() + @property def underflow(self): + """ + h.underflow -> Distribution1D + + Return the Distribution1D object representing the underflow. + + """ pass def __delitem__(self, size_t ix): self.ptr().eraseBin(ix) def __getitem__(self, size_t ix): - return HistoBin1D().set(self.ptr().bins()[ix]) + return HistoBin1D_fromptr(& self.ptr().bin(ix)) def integral(self, bool overflows=True): + """ + s.integral([overflows]) -> float + + Return the total area of the histogram. If overflows is False, ignore + over-and underflow bins. + + """ return self.ptr().integral(overflows) 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 mean(self, bool overflows=True): + """ + s.mean([overflows]) -> float + + Return the mean. If overflows is False, ignore the over- and underflow + bins. + + """ + def variance(self, bool overflows=True): + """ + s.variance([overflows]) -> float + + Return the variance. If overflows is False, ignore the over- and + underflow bins. + + """ return self.ptr().variance(overflows) def stdDev(self, bool overflows=True): - return self.ptr().stdDev(overflows) + """ + s.stdDev([overflows]) -> float + Return the standard deviation. If overflows is False, ignore over-and + underflow bins. + + """ + return self.ptr().stdDev(overflows) - """def __add__(Histo1D a, Histo1D b): - cdef cHisto1D *res - res = new cHisto1D(a.ptr()[0] + b.ptr()[0]) - return Histo1D().setptr(res) + def __add__(Histo1D a, Histo1D b): + cdef cHisto1D *res = new cHisto1D(add_Histo1D(a.ptr()[0], b.ptr()[0])) + return Histo1D_fromptr(res, True) def __sub__(Histo1D a, Histo1D b): - cdef cHisto1D *res - res = new cHisto1D(a.ptr()[0] - b.ptr()[0]) - return Histo1D().setptr(res) + cdef cHisto1D *res = new cHisto1D(subtract_Histo1D(a.ptr()[0], b.ptr()[0])) + return Histo1D_fromptr(res, True) def __mul__(x, y): + """ + Scalar multiplication. Equivalent to scaleW acting on a copy. + + """ cdef cHisto1D *res tx, ty = type(x), type(y) if (tx is int or tx is float) and ty is Histo1D: @@ -149,31 +270,39 @@ res = new cHisto1D(histo.ptr()[0]) res.scaleW(factor) - return Histo1D().setptr(res) - + return Histo1D_fromptr(res, True) def _div_scalar(Histo1D x, double y): - cdef cHisto1D *res = new cHisto1D(x.ptr()[0]) if y == 0: raise ArithmeticError('Histo1D: Divide by zero scalar') + + cdef cHisto1D *res = new cHisto1D(x.ptr()[0]) + res.scaleW(1.0 / y) - return Histo1D().setptr(res) + return Histo1D_fromptr(res, True) def _div_histo(Histo1D x, Histo1D y): - cdef cScatter2D *res - - res = new cScatter2D(x.ptr()[0] / y.ptr()[0]) - return Scatter2D().setptr(res) + cdef cScatter2D s = divide_Histo1D(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 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))""" - + + raise RuntimeError('Cannot multiply %r by %r' % (tx, ty)) + def __repr__(self): return 'Histo1D%r' % self.bins + +cdef Histo1D Histo1D_fromptr(cHisto1D *ptr, bool dealloc=False): + cdef Histo1D histo = Histo1D.__new__(Histo1D) + return histo.setptr(ptr, dealloc) Modified: trunk/pyext/yoda/include/40-Histo2D.pyx ============================================================================== --- trunk/pyext/yoda/include/40-Histo2D.pyx Mon Nov 7 09:13:22 2011 (r404) +++ trunk/pyext/yoda/include/40-Histo2D.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -7,7 +7,6 @@ size_t nbinsY, double lowerY, double upperY, string &path, string &title) - cHisto1D(cHisto1D &h, string &path) cHisto2D(cHisto2D &h) void fill(double x, double y, double weight) @@ -43,7 +42,13 @@ double yStdDev(bool includeoverflows) cdef class Histo2D(AnalysisObject): - def __cinit__(self, *args, **kwargs): + cdef tuple _bins + + def __cinit__(self): + self._bins = None + self._dealloc = False + + def __init__(self, *args, **kwargs): cdef: size_t nbinsX, nbinsY double lowX, highX, lowY, highY @@ -55,16 +60,12 @@ self.setptr( new cHisto2D(nbinsX, lowX, highX, nbinsY, lowY, highY, - string(path), string(title)) + string(path), string(title)), True ) cdef cHisto2D* ptr(self): return <cHisto2D *> self.thisptr - cdef setptr(self, cHisto2D *ptr): - self.thisptr = ptr - return self - def fill(self, double x, double y, double weight=1.0): self.ptr().fill(x, y, weight) @@ -86,17 +87,12 @@ def bins(self): cdef size_t numbins = self.ptr().numBins() cdef size_t i - - cdef vector[cHistoBin2D] bins = self.ptr().bins() - cdef cHistoBin2D *b + if self._bins is None: + self._bins = tuple([HistoBin2D_fromptr(& self.ptr().bins().at(i)) + for i in xrange(numbins)]) - out = [] - - for i in range(numbins): - out.append(HistoBin2D().set(bins[i])) - - return out + return self._bins @property def lowEdgeX(self): @@ -164,7 +160,11 @@ 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) Added: trunk/pyext/yoda/include/40-WriterAIDA.pyx ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/pyext/yoda/include/40-WriterAIDA.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -0,0 +1,17 @@ +cdef extern from "shims.h": + void WriterAIDA_write (string&, vector[AOptr]&) except + + +def __write_AIDA(char* filename, aos): + """Takes a file, returns a list of AnalysisObjects""" + cdef vector[AOptr] vec = vector[AOptr]() + cdef AnalysisObject ana + + for ao in aos: + ana = <AnalysisObject> ao + vec.push_back(ana.thisptr) + + WriterAIDA_write(string(filename), vec) + +class WriterAIDA: + """Read AIDA files""" + write = staticmethod(__write_AIDA) Added: trunk/pyext/yoda/include/99-ReaderAIDA.pyx ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/pyext/yoda/include/99-ReaderAIDA.pyx Tue Nov 8 02:29:58 2011 (r405) @@ -0,0 +1,27 @@ +cdef extern from "YODA/ReaderAIDA.h" namespace "YODA::ReaderAIDA": + cReader createReaderAIDA "YODA::ReaderAIDA::create" () + +def __read_AIDA(char *filename): + """Takes a file, returns a list of AnalysisObjects""" + cdef vector[AOptr] vec = vector[AOptr]() + cdef size_t i + cdef AnalysisObject ana, ana_ + + createReaderAIDA().read(string(filename), vec) + out = [] + + ana_ = AnalysisObject() + + for i in range(vec.size()): + ana_.thisptr = vec[i] + + if ana_.type == 'Scatter2D': + out.append(Scatter2D_fromptr(<cScatter2D*>vec[i], True)) + elif ana_.type == 'Histo1D': + out.append(Scatter2D_fromptr(<cScatter2D*>vec[i], True)) + + return out + +cdef class ReaderAIDA: + """Read AIDA files""" + read = staticmethod(__read_AIDA) Added: trunk/pyext/yoda/shims.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/pyext/yoda/shims.h Tue Nov 8 02:29:58 2011 (r405) @@ -0,0 +1,60 @@ +/// This file is purely for backward compatibility with Cython 1.3 and 1.4. + +#include "YODA/AnalysisObject.h" +#include "YODA/Histo1D.h" +#include "YODA/Scatter2D.h" +#include "YODA/HistoBin1D.h" +#include "YODA/Histo2D.h" +#include "YODA/Scatter3D.h" +#include "YODA/WriterAIDA.h" +#include <string> +#include <vector> + +using namespace YODA; + +/// Histo1D operators + +inline Histo1D add_Histo1D(const Histo1D& a, const Histo1D& b) { + return a + b; +} + +inline Histo1D subtract_Histo1D(const Histo1D& a, const Histo1D& b) { + return a - b; +} + +inline Scatter2D divide_Histo1D(const Histo1D& a, const Histo1D& b) { + return a / b; +} + +/// HistoBin1D Operators +inline HistoBin1D add_HistoBin1D(const HistoBin1D& a, const HistoBin1D& b) { + return a + b; +} + +inline HistoBin1D subtract_HistoBin1D(const HistoBin1D& a, const HistoBin1D& b) { + return a - b; +} + +/// Histo2D operators + +inline Histo2D add_Histo2D(const Histo2D& a, const Histo2D& b) { + return a + b; +} + +inline Histo2D subtract_Histo2D(const Histo2D& a, const Histo2D& b) { + return a - b; +} + +inline Scatter3D divide_Histo2D(const Histo2D& a, const Histo2D& b) { + return a / b; +} + +void WriterAIDA_write (const std::string& filename, const std::vector<AnalysisObject*>& aos) +{ + return WriterAIDA::write(filename, aos); +} + +Scatter2D Scatter2D_mkScatter(const Histo1D& h) +{ + return YODA::mkScatter(h); +}
More information about the yoda-svn mailing list |