|
[yoda-svn] r556 - in trunk: . include/YODA include/YODA/Utils pyext pyext/yoda pyext/yoda/includeblackhole at projects.hepforge.org blackhole at projects.hepforge.orgSat Feb 2 13:19:11 GMT 2013
Author: davemallows Date: Sat Feb 2 13:19:10 2013 New Revision: 556 Log: Adding support for Python >= 2.4 and fixing warnings present in GCC 4.1. Modified: trunk/ChangeLog trunk/configure.ac trunk/include/YODA/Bin2D.h trunk/include/YODA/Utils/BinSearcher.h trunk/pyext/template.py trunk/pyext/yoda/core.pyx trunk/pyext/yoda/declarations.pxd trunk/pyext/yoda/include/Dbn3D.pyx trunk/pyext/yoda/include/Histo2D.pyx trunk/pyext/yoda/include/Point2D.pyx trunk/pyext/yoda/include/Point3D.pyx trunk/pyext/yoda/include/Scatter2D.pyx trunk/pyext/yoda/util.pyx Modified: trunk/ChangeLog ============================================================================== --- trunk/ChangeLog Wed Jan 30 15:50:44 2013 (r555) +++ trunk/ChangeLog Sat Feb 2 13:19:10 2013 (r556) @@ -1,3 +1,9 @@ +2013-02-02 David Mallows <dave.mallows at gmail.com> + + * Adding support for Python >= 2.4 (was Python >= 2.6) + + * Fixing miscellaneous warnings on GCC 4.1 + 2013-01-30 Andy Buckley <andy.buckley at cern.ch> * Adding a points() method to the Python Scatter2D wrapper. Modified: trunk/configure.ac ============================================================================== --- trunk/configure.ac Wed Jan 30 15:50:44 2013 (r555) +++ trunk/configure.ac Sat Feb 2 13:19:10 2013 (r556) @@ -32,6 +32,7 @@ AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL + ## Work out library suffix for the build LIB_SUFFIX=\\\"$shrext_cmds\\\" AC_SUBST([LIB_SUFFIX]) @@ -48,7 +49,7 @@ ## Basic Python checks if test x$enable_pyext == xyes; then AZ_PYTHON_PATH - AZ_PYTHON_VERSION_ENSURE([2.6]) + AZ_PYTHON_VERSION_ENSURE([2.4]) PYTHON_VERSION=`$PYTHON -c "import sys; print '.'.join(map(str, sys.version_info@<:@:2@:>@));"` AC_SUBST(PYTHON_VERSION) RIVET_PYTHONPATH=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(prefix='$prefix', plat_specific=True);"` Modified: trunk/include/YODA/Bin2D.h ============================================================================== --- trunk/include/YODA/Bin2D.h Wed Jan 30 15:50:44 2013 (r555) +++ trunk/include/YODA/Bin2D.h Sat Feb 2 13:19:10 2013 (r556) @@ -268,7 +268,7 @@ } /// The effective number of entries - unsigned long effNumEntries() const { + double effNumEntries() const { return _dbn.effNumEntries(); } @@ -421,8 +421,8 @@ return yedges(); } - double _edge_perp(int i) const { - double output; + double _edge_perp(size_t i) const { + double output = 0.0; switch (i) { case 0: output = xMax(); break; Modified: trunk/include/YODA/Utils/BinSearcher.h ============================================================================== --- trunk/include/YODA/Utils/BinSearcher.h Wed Jan 30 15:50:44 2013 (r555) +++ trunk/include/YODA/Utils/BinSearcher.h Sat Feb 2 13:19:10 2013 (r556) @@ -174,7 +174,7 @@ } size_t estimate(const double x) const { - double y = (*_est)(x); + size_t y = (size_t)(*_est)(x); size_t yi = 0 ? (y < 0) : y; return (yi > _max) ? _max : yi; } Modified: trunk/pyext/template.py ============================================================================== --- trunk/pyext/template.py Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/template.py Sat Feb 2 13:19:10 2013 (r556) @@ -1,5 +1,15 @@ from string import Template -from itertools import product, izip +from itertools import izip + +def product(*args, **kwds): + # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy + # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 + pools = map(tuple, args) * kwds.get('repeat', 1) + result = [[]] + for pool in pools: + result = [x+[y] for x in result for y in pool] + for prod in result: + yield tuple(prod) # A total mess. Uses python's string.Template to substitute values in various # templated C++ wrappers, as Cython has no support for templates (and fused @@ -37,8 +47,9 @@ product(*kwargs.itervalues())] full_filename = os.path.join(INCLUDE_DIR, filename + '.pyx') - with open(path(full_filename)) as f: - template = Template(f.read()) + f = open(path(full_filename)) + template = Template(f.read()) + f.close() plain_name = filename for i in individuals[0]: @@ -54,14 +65,16 @@ newname = newname.replace(i, j) out_filename = os.path.join(GENERATED_DIR, newname + '.pyx') - with open(path(out_filename), 'w') as f: - f.write(GENERATED_HEADER.substitute(filename=filename)) - f.write(template.substitute(**a)) + f = open(path(out_filename), 'w') + f.write(GENERATED_HEADER.substitute(filename=filename)) + f.write(template.substitute(**a)) + f.close() includes.append(out_filename) inc_filename = os.path.join(INCLUDE_DIR, plain_name + '.pxi') - with open(path(inc_filename), 'w') as f: - f.write(GENERATED_HEADER.substitute(filename=filename)) - f.write("\n".join('include "%s"' % i for i in includes)) + f = open(path(inc_filename), 'w') + f.write(GENERATED_HEADER.substitute(filename=filename)) + f.write("\n".join('include "%s"' % i for i in includes)) + f.close() Modified: trunk/pyext/yoda/core.pyx ============================================================================== --- trunk/pyext/yoda/core.pyx Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/core.pyx Sat Feb 2 13:19:10 2013 (r556) @@ -6,7 +6,7 @@ from libcpp.vector cimport vector from libcpp.pair cimport pair from libcpp.map cimport map -import ctypes +#import ctypes # Not done here any more, instead done on transformX/Y. # Pure python imports from itertools import repeat, imap Modified: trunk/pyext/yoda/declarations.pxd ============================================================================== --- trunk/pyext/yoda/declarations.pxd Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/declarations.pxd Sat Feb 2 13:19:10 2013 (r556) @@ -35,7 +35,7 @@ # Raw distribution running sums unsigned long numEntries() except+ err - unsigned long effNumEntries() except+ err + double effNumEntries() except+ err double sumW() except+ err double sumW2() except+ err double sumWX() except+ err @@ -73,7 +73,7 @@ # Raw distribution running sums unsigned long numEntries() except+ err - unsigned long effNumEntries() except+ err + double effNumEntries() except+ err double sumW() except+ err double sumW2() except+ err double sumWX() except+ err @@ -129,7 +129,7 @@ # Raw distribution running sums unsigned long numEntries() - unsigned long effNumEntries() + double effNumEntries() double sumW() double sumW2() @@ -280,7 +280,7 @@ # raw statistics unsigned long numEntries() except+ err - unsigned long effNumEntries() except+ err + double effNumEntries() except+ err double sumW() except+ err double sumW2() except+ err double sumWX() except+ err @@ -335,7 +335,7 @@ # raw statistics unsigned long numEntries() except+ err - unsigned long effNumEntries() except+ err + double effNumEntries() except+ err double sumW() except+ err double sumW2() except+ err double sumWX() except+ err Modified: trunk/pyext/yoda/include/Dbn3D.pyx ============================================================================== --- trunk/pyext/yoda/include/Dbn3D.pyx Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/include/Dbn3D.pyx Sat Feb 2 13:19:10 2013 (r556) @@ -1,6 +1,3 @@ -from collections import namedtuple -from itertools import izip, repeat - cdef class Dbn3D(util.Base): """ A 2D distribution 'counter', used and exposed by 2D histograms and Modified: trunk/pyext/yoda/include/Histo2D.pyx ============================================================================== --- trunk/pyext/yoda/include/Histo2D.pyx Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/include/Histo2D.pyx Sat Feb 2 13:19:10 2013 (r556) @@ -38,9 +38,16 @@ def fill(self, double x, double y, weight=1.0): self._Histo2D().fill(x, y, weight) + # Todo: amalgomate this with fill to take arbitrary iterators? def fill_many(self, xs, ys, weight=1.0): - for x, y in izip(xs, ys): - self._Histo2D().fill(x, y, weight) + cdef double x, y + try: + while True: + x = next(xs) + y = next(ys) + self._Histo2D().fill(x, y, weight) + except StopIteration: + pass def copy(self, char *path=""): return util.new_owned_cls(Histo2D, Modified: trunk/pyext/yoda/include/Point2D.pyx ============================================================================== --- trunk/pyext/yoda/include/Point2D.pyx Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/include/Point2D.pyx Sat Feb 2 13:19:10 2013 (r556) @@ -1,6 +1,3 @@ -from collections import namedtuple -from libcpp cimport bool - cdef inline pair[double, double] read_symmetric(object val) except *: try: a, b = val Modified: trunk/pyext/yoda/include/Point3D.pyx ============================================================================== --- trunk/pyext/yoda/include/Point3D.pyx Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/include/Point3D.pyx Sat Feb 2 13:19:10 2013 (r556) @@ -1,6 +1,3 @@ -from collections import namedtuple -from libcpp cimport bool - # TODO: make more consistent with Point2D cdef class Point3D(util.Base): Modified: trunk/pyext/yoda/include/Scatter2D.pyx ============================================================================== --- trunk/pyext/yoda/include/Scatter2D.pyx Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/include/Scatter2D.pyx Sat Feb 2 13:19:10 2013 (r556) @@ -1,6 +1,5 @@ #TODO: Tidy up + docstrings etc. -cdef object transform_functor = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double) cdef class Scatter2D(AnalysisObject): """ @@ -11,11 +10,6 @@ cdef inline c.Scatter2D *_Scatter2D(self) except NULL: return <c.Scatter2D*> self.ptr() - # There is a pythonic constructor here, and it looks a little like... - # __init__(self, *args, **kwargs) - # ([edge], path="", title="") - # ([bins], **kwargs) - def __init__(self, *args, **kwargs): util.try_loop([self.__init_2, self.__init_3], *args, **kwargs) @@ -74,20 +68,30 @@ def transformX(self, f): + # Import ctypes here (rather than at module import) so that Python 2.4 + # users don't need ctypes to use the rest of the library. + import ctypes + try: - callback = transform_functor(f) + callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f) except: - raise RuntimeError("Callback be of type (double) -> double") + raise RuntimeError("Callback is not of type (double) -> double") + fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0] c.Scatter2D_transformX(deref(self._Scatter2D()), fptr) def transformY(self, f): + # Import ctypes here (rather than at module import) so that Python 2.4 + # users don't need ctypes to use the rest of the library. + import ctypes + try: - callback = transform_functor(f) + callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f) except: - raise RuntimeError("Callback be of type (double) -> double") + raise RuntimeError("Callback is not of type (double) -> double") + fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0] Modified: trunk/pyext/yoda/util.pyx ============================================================================== --- trunk/pyext/yoda/util.pyx Wed Jan 30 15:50:44 2013 (r555) +++ trunk/pyext/yoda/util.pyx Sat Feb 2 13:19:10 2013 (r556) @@ -1,4 +1,5 @@ -from collections import namedtuple +#from collections import namedtuple +from operator import itemgetter cdef class Base: pass @@ -13,7 +14,183 @@ raise TypeError(_msg) -Edges = namedtuple('Edges', ('low', 'high')) -Errors = namedtuple('Errors', ('minus', 'plus')) -XY = namedtuple('XY', ('x', 'y')) -XYZ = namedtuple('XYZ', ('x', 'y', 'z')) +class Edges(tuple): + 'Edges(low, high)' + + __slots__ = () + + _fields = ('low', 'high') + + def __new__(_cls, low, high): + 'Create new instance of Edges(low, high)' + return tuple.__new__(_cls, (low, high)) + + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + 'Make a new Edges object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != 2: + raise TypeError('Expected 2 arguments, got %d' % len(result)) + return result + + def __repr__(self): + 'Return a nicely formatted representation string' + return 'Edges(low=%r, high=%r)' % self + + def _asdict(self): + 'Return a new dict which maps field names to their values' + return dict(zip(self._fields, self)) + + __dict__ = property(_asdict) + + def _replace(_self, **kwds): + 'Return a new Edges object replacing specified fields with new values' + result = _self._make(map(kwds.pop, ('low', 'high'), _self)) + if kwds: + raise ValueError('Got unexpected field names: %r' % kwds.keys()) + return result + + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) + + low = property(itemgetter(0), doc='Alias for field number 0') + high = property(itemgetter(1), doc='Alias for field number 1') + + +class Errors(tuple): + 'Errors(minus, plus)' + + __slots__ = () + + _fields = ('minus', 'plus') + + def __new__(_cls, minus, plus): + 'Create new instance of Errors(minus, plus)' + return tuple.__new__(_cls, (minus, plus)) + + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + 'Make a new Errors object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != 2: + raise TypeError('Expected 2 arguments, got %d' % len(result)) + return result + + def __repr__(self): + 'Return a nicely formatted representation string' + return 'Errors(minus=%r, plus=%r)' % self + + def _asdict(self): + 'Return a new dict which maps field names to their values' + return dict(zip(self._fields, self)) + + __dict__ = property(_asdict) + + def _replace(_self, **kwds): + 'Return a new Errors object replacing specified fields with new values' + result = _self._make(map(kwds.pop, ('minus', 'plus'), _self)) + if kwds: + raise ValueError('Got unexpected field names: %r' % kwds.keys()) + return result + + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) + + minus = property(itemgetter(0), doc='Alias for field number 0') + plus = property(itemgetter(1), doc='Alias for field number 1') + + +#Edges = namedtuple('Edges', ('low', 'high')) +#Errors = namedtuple('Errors', ('minus', 'plus')) +#XY = namedtuple('XY', ('x', 'y')) +class XY(tuple): + 'XY(x, y)' + + __slots__ = () + + _fields = ('x', 'y') + + def __new__(_cls, x, y): + 'Create new instance of XY(x, y)' + return tuple.__new__(_cls, (x, y)) + + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + 'Make a new XY object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != 2: + raise TypeError('Expected 2 arguments, got %d' % len(result)) + return result + + def __repr__(self): + 'Return a nicely formatted representation string' + return 'XY(x=%r, y=%r)' % self + + def _asdict(self): + 'Return a new dict which maps field names to their values' + return dict(zip(self._fields, self)) + + __dict__ = property(_asdict) + + def _replace(_self, **kwds): + 'Return a new XY object replacing specified fields with new values' + result = _self._make(map(kwds.pop, ('x', 'y'), _self)) + if kwds: + raise ValueError('Got unexpected field names: %r' % kwds.keys()) + return result + + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) + + x = property(itemgetter(0), doc='Alias for field number 0') + y = property(itemgetter(1), doc='Alias for field number 1') + +#XYZ = namedtuple('XYZ', ('x', 'y', 'z')) + +class XYZ(tuple): + 'XYZ(x, y, z)' + + __slots__ = () + + _fields = ('x', 'y', 'z') + + def __new__(_cls, x, y, z): + 'Create new instance of XYZ(x, y, z)' + return tuple.__new__(_cls, (x, y, z)) + + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + 'Make a new XYZ object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != 3: + raise TypeError('Expected 3 arguments, got %d' % len(result)) + return result + + def __repr__(self): + 'Return a nicely formatted representation string' + return 'XYZ(x=%r, y=%r, z=%r)' % self + + def _asdict(self): + 'Return a new dict which maps field names to their values' + return dict(zip(self._fields, self)) + + __dict__ = property(_asdict) + + def _replace(_self, **kwds): + 'Return a new XYZ object replacing specified fields with new values' + result = _self._make(map(kwds.pop, ('x', 'y', 'z'), _self)) + if kwds: + raise ValueError('Got unexpected field names: %r' % kwds.keys()) + return result + + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) + + x = property(itemgetter(0), doc='Alias for field number 0') + y = property(itemgetter(1), doc='Alias for field number 1') + z = property(itemgetter(2), doc='Alias for field number 2') +
More information about the yoda-svn mailing list |