TPyFitFunction.cxx

Go to the documentation of this file.
00001 // Author: Wim Lavrijsen   November 2010
00002 
00003 // Bindings
00004 #include "PyROOT.h"
00005 #include "TPyFitFunction.h"
00006 #include "ObjectProxy.h"
00007 #include "MethodProxy.h"
00008 #include "PyBufferFactory.h"
00009 
00010 // Standard
00011 #include <stdexcept>
00012 
00013 //______________________________________________________________________________
00014 //                       Python wrapper for Fit functions
00015 //                       ================================
00016 //
00017 
00018 
00019 //- data ---------------------------------------------------------------------
00020 ClassImp(TPyMultiGenFunction)
00021 ClassImp(TPyMultiGradFunction)
00022 
00023 
00024 //- helper functions ---------------------------------------------------------
00025 static PyObject* GetOverriddenPyMethod( PyObject* pyself, const char* method )
00026 {
00027 // Retrieve an overriden method on pyself
00028    PyObject* pymethod = 0;
00029 
00030    if ( pyself && pyself != Py_None ) {
00031       pymethod = PyObject_GetAttrString( (PyObject*)pyself, const_cast< char* >( method ) );
00032       if ( ! PyROOT::MethodProxy_CheckExact( pymethod ) )
00033          return pymethod;
00034 
00035       Py_XDECREF( pymethod );
00036       pymethod = 0;
00037    }
00038 
00039    return pymethod;
00040 }
00041 
00042 static PyObject* DispatchCall( PyObject* pyself, const char* method, PyObject* pymethod = NULL,
00043    PyObject* arg1 = NULL, PyObject* arg2 = NULL, PyObject* arg3 = NULL )
00044 {
00045 // Forward <method> to python (need to refactor this with TPySelector).
00046    PyObject* result = 0;
00047 
00048 // get the named method and check for python side overload by not accepting the
00049 // binding's methodproxy
00050    if ( ! pymethod )
00051        pymethod = GetOverriddenPyMethod( pyself, method );
00052 
00053    if ( pymethod ) {
00054       result = PyObject_CallFunctionObjArgs( pymethod, arg1, arg2, arg3, NULL );
00055    } else {
00056    // means the method has not been overridden ... simply accept its not there
00057       result = 0; 
00058       PyErr_Format( PyExc_AttributeError,
00059          "method %s needs implementing in derived class", const_cast< char* >( method ) );
00060    }
00061 
00062    Py_XDECREF( pymethod );
00063 
00064    return result;
00065 }
00066 
00067 
00068 //- constructors/destructor --------------------------------------------------
00069 TPyMultiGenFunction::TPyMultiGenFunction( PyObject* self ) : fPySelf( 0 )
00070 {
00071 // Construct a TPyMultiGenFunction derived with <self> as the underlying
00072    if ( self ) {
00073    // steal reference as this is us, as seen from python
00074       fPySelf = self;
00075    } else {
00076       Py_INCREF( Py_None );        // using None allows clearer diagnostics
00077       fPySelf = Py_None;
00078    }
00079 }
00080 
00081 //____________________________________________________________________________
00082 TPyMultiGenFunction::~TPyMultiGenFunction()
00083 {
00084 // Destructor. Only deref if still holding on to Py_None (circular otherwise).
00085    if ( fPySelf == Py_None ) {
00086       Py_DECREF( fPySelf );
00087    }
00088 }
00089 
00090 
00091 //- public functions ---------------------------------------------------------
00092 unsigned int TPyMultiGenFunction::NDim() const
00093 {
00094 // Simply forward the call to python self.
00095    PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
00096 
00097    if ( ! pyresult ) {
00098       PyErr_Print();
00099       throw std::runtime_error( "Failure in TPyMultiGenFunction::NDim" );
00100    }
00101 
00102    unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
00103    Py_XDECREF( pyresult );
00104 
00105    return cppresult;
00106 }
00107 
00108 //____________________________________________________________________________
00109 double TPyMultiGenFunction::DoEval( const double* x ) const
00110 {
00111 // Simply forward the call to python self.
00112    PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00113    PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
00114    Py_DECREF( xbuf );
00115 
00116    if ( ! pyresult ) {
00117       PyErr_Print();
00118       throw std::runtime_error( "Failure in TPyMultiGenFunction::DoEval" );
00119    }
00120 
00121    double cppresult = (double)PyFloat_AsDouble( pyresult );
00122    Py_XDECREF( pyresult );
00123 
00124    return cppresult;
00125 }
00126 
00127 
00128 
00129 //- constructors/destructor --------------------------------------------------
00130 TPyMultiGradFunction::TPyMultiGradFunction( PyObject* self )
00131 {
00132 // Construct a TPyMultiGradFunction derived with <self> as the underlying
00133    if ( self ) {
00134    // steal reference as this is us, as seen from python
00135       fPySelf = self;
00136    } else {
00137       Py_INCREF( Py_None );        // using None allows clearer diagnostics
00138       fPySelf = Py_None;
00139    }
00140 }
00141 
00142 //____________________________________________________________________________
00143 TPyMultiGradFunction::~TPyMultiGradFunction()
00144 {
00145 // Destructor. Only deref if still holding on to Py_None (circular otherwise).
00146    if ( fPySelf == Py_None ) {
00147       Py_DECREF( fPySelf );
00148    }
00149 }
00150 
00151 
00152 //- public functions ---------------------------------------------------------
00153 unsigned int TPyMultiGradFunction::NDim() const
00154 {
00155 // Simply forward the call to python self.
00156    PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
00157 
00158    if ( ! pyresult ) {
00159       PyErr_Print();
00160       throw std::runtime_error( "Failure in TPyMultiGradFunction::NDim" );
00161    }
00162 
00163    unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
00164    Py_XDECREF( pyresult );
00165 
00166    return cppresult;
00167 }
00168 
00169 //____________________________________________________________________________
00170 double TPyMultiGradFunction::DoEval( const double* x ) const
00171 {
00172 // Simply forward the call to python self.
00173    PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00174    PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
00175    Py_DECREF( xbuf );
00176 
00177    if ( ! pyresult ) {
00178       PyErr_Print();
00179       throw std::runtime_error( "Failure in TPyMultiGradFunction::DoEval" );
00180    }
00181 
00182    double cppresult = (double)PyFloat_AsDouble( pyresult );
00183    Py_XDECREF( pyresult );
00184 
00185    return cppresult;
00186 }
00187 
00188 //____________________________________________________________________________
00189 void TPyMultiGradFunction::Gradient( const double* x, double* grad ) const {
00190 // Simply forward the call to python self.
00191    PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "Gradient" );
00192 
00193    if ( pymethod ) {
00194       PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00195       PyObject* gbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)grad );
00196       PyObject* pyresult = DispatchCall( fPySelf, "Gradient", pymethod, xbuf, gbuf );
00197       Py_DECREF( gbuf );
00198       Py_DECREF( xbuf );
00199 
00200       if ( ! pyresult ) {
00201          PyErr_Print();
00202          throw std::runtime_error( "Failure in TPyMultiGradFunction::Gradient" );
00203       }
00204 
00205       Py_DECREF( pyresult );
00206 
00207    } else
00208       return ROOT::Math::IMultiGradFunction::Gradient( x, grad );
00209 }
00210 
00211 //____________________________________________________________________________
00212 void TPyMultiGradFunction::FdF( const double* x, double& f, double* df ) const
00213 {
00214 // Simply forward the call to python self.
00215    PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "FdF" );
00216 
00217    if ( pymethod ) {
00218       PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00219       PyObject* pyf = PyList_New( 1 );
00220       PyList_SetItem( pyf, 0, PyFloat_FromDouble( f ) );
00221       PyObject* dfbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)df );
00222 
00223       PyObject* pyresult = DispatchCall( fPySelf, "FdF", pymethod, xbuf, pyf, dfbuf );
00224       f = PyFloat_AsDouble( PyList_GetItem( pyf, 0 ) );
00225 
00226       Py_DECREF( dfbuf );
00227       Py_DECREF( pyf );
00228       Py_DECREF( xbuf );
00229 
00230       if ( ! pyresult ) {
00231          PyErr_Print();
00232          throw std::runtime_error( "Failure in TPyMultiGradFunction::FdF" );
00233       }
00234 
00235       Py_DECREF( pyresult );
00236 
00237    } else
00238       return ROOT::Math::IMultiGradFunction::FdF( x, f, df );
00239 }
00240 
00241 //____________________________________________________________________________
00242 double TPyMultiGradFunction::DoDerivative( const double * x, unsigned int icoord ) const
00243 {
00244 // Simply forward the call to python self.
00245    PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00246    PyObject* pycoord = PyLong_FromLong( icoord );
00247 
00248    PyObject* pyresult = DispatchCall( fPySelf, "DoDerivative", NULL, xbuf, pycoord );
00249    Py_DECREF( pycoord );
00250    Py_DECREF( xbuf );
00251 
00252    if ( ! pyresult ) {
00253       PyErr_Print();
00254       throw std::runtime_error( "Failure in TPyMultiGradFunction::DoDerivative" );
00255    }
00256 
00257    double cppresult = (double)PyFloat_AsDouble( pyresult );
00258    Py_XDECREF( pyresult );
00259 
00260    return cppresult;
00261 }
00262 

Generated on Tue Jul 5 14:10:16 2011 for ROOT_528-00b_version by  doxygen 1.5.1