Logo ROOT  
Reference Guide
TPyFitFunction.cxx
Go to the documentation of this file.
1// Author: Wim Lavrijsen November 2010
2
3// Bindings
4#include "PyROOT.h"
5#include "TPyFitFunction.h"
6#include "ObjectProxy.h"
7#include "MethodProxy.h"
8#include "TPyBufferFactory.h"
9
10// Standard
11#include <stdexcept>
12
13//______________________________________________________________________________
14// Python wrapper for Fit functions
15// ================================
16//
17
18
19//- data ---------------------------------------------------------------------
22
23
24//- helper functions ---------------------------------------------------------
25static PyObject* GetOverriddenPyMethod( PyObject* pyself, const char* method )
26{
27// Retrieve an overriden method on pyself
28 PyObject* pymethod = 0;
29
30 if ( pyself && pyself != Py_None ) {
31 pymethod = PyObject_GetAttrString( (PyObject*)pyself, const_cast< char* >( method ) );
32 if ( ! PyROOT::MethodProxy_CheckExact( pymethod ) )
33 return pymethod;
34
35 Py_XDECREF( pymethod );
36 pymethod = 0;
37 }
38
39 return pymethod;
40}
41
42static PyObject* DispatchCall( PyObject* pyself, const char* method, PyObject* pymethod = NULL,
43 PyObject* arg1 = NULL, PyObject* arg2 = NULL, PyObject* arg3 = NULL )
44{
45// Forward <method> to python (need to refactor this with TPySelector).
46 PyObject* result = 0;
47
48// get the named method and check for python side overload by not accepting the
49// binding's methodproxy
50 if ( ! pymethod )
51 pymethod = GetOverriddenPyMethod( pyself, method );
52
53 if ( pymethod ) {
54 result = PyObject_CallFunctionObjArgs( pymethod, arg1, arg2, arg3, NULL );
55 } else {
56 // means the method has not been overridden ... simply accept its not there
57 result = 0;
58 PyErr_Format( PyExc_AttributeError,
59 "method %s needs implementing in derived class", const_cast< char* >( method ) );
60 }
61
62 Py_XDECREF( pymethod );
63
64 return result;
65}
66
67
68//- constructors/destructor --------------------------------------------------
70{
71// Construct a TPyMultiGenFunction derived with <self> as the underlying
72 if ( self ) {
73 // steal reference as this is us, as seen from python
74 fPySelf = self;
75 } else {
76 Py_INCREF( Py_None ); // using None allows clearer diagnostics
77 fPySelf = Py_None;
78 }
79}
80
81////////////////////////////////////////////////////////////////////////////////
82/// Destructor. Only deref if still holding on to Py_None (circular otherwise).
83
85{
86 if ( fPySelf == Py_None ) {
87 Py_DECREF( fPySelf );
88 }
89}
90
91
92//- public functions ---------------------------------------------------------
93unsigned int TPyMultiGenFunction::NDim() const
94{
95// Simply forward the call to python self.
96 PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
97
98 if ( ! pyresult ) {
99 PyErr_Print();
100 throw std::runtime_error( "Failure in TPyMultiGenFunction::NDim" );
101 }
102
103 unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
104 Py_XDECREF( pyresult );
105
106 return cppresult;
107}
108
109////////////////////////////////////////////////////////////////////////////////
110/// Simply forward the call to python self.
111
112double TPyMultiGenFunction::DoEval( const double* x ) const
113{
115 PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
116 Py_DECREF( xbuf );
117
118 if ( ! pyresult ) {
119 PyErr_Print();
120 throw std::runtime_error( "Failure in TPyMultiGenFunction::DoEval" );
121 }
122
123 double cppresult = (double)PyFloat_AsDouble( pyresult );
124 Py_XDECREF( pyresult );
125
126 return cppresult;
127}
128
129
130
131//- constructors/destructor --------------------------------------------------
133{
134// Construct a TPyMultiGradFunction derived with <self> as the underlying
135 if ( self ) {
136 // steal reference as this is us, as seen from python
137 fPySelf = self;
138 } else {
139 Py_INCREF( Py_None ); // using None allows clearer diagnostics
140 fPySelf = Py_None;
141 }
142}
143
144////////////////////////////////////////////////////////////////////////////////
145/// Destructor. Only deref if still holding on to Py_None (circular otherwise).
146
148{
149 if ( fPySelf == Py_None ) {
150 Py_DECREF( fPySelf );
151 }
152}
153
154
155//- public functions ---------------------------------------------------------
156unsigned int TPyMultiGradFunction::NDim() const
157{
158// Simply forward the call to python self.
159 PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
160
161 if ( ! pyresult ) {
162 PyErr_Print();
163 throw std::runtime_error( "Failure in TPyMultiGradFunction::NDim" );
164 }
165
166 unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
167 Py_XDECREF( pyresult );
168
169 return cppresult;
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// Simply forward the call to python self.
174
175double TPyMultiGradFunction::DoEval( const double* x ) const
176{
178 PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
179 Py_DECREF( xbuf );
180
181 if ( ! pyresult ) {
182 PyErr_Print();
183 throw std::runtime_error( "Failure in TPyMultiGradFunction::DoEval" );
184 }
185
186 double cppresult = (double)PyFloat_AsDouble( pyresult );
187 Py_XDECREF( pyresult );
188
189 return cppresult;
190}
191
192////////////////////////////////////////////////////////////////////////////////
193/// Simply forward the call to python self.
194
195void TPyMultiGradFunction::Gradient( const double* x, double* grad ) const {
196 PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "Gradient" );
197
198 if ( pymethod ) {
201 PyObject* pyresult = DispatchCall( fPySelf, "Gradient", pymethod, xbuf, gbuf );
202 Py_DECREF( gbuf );
203 Py_DECREF( xbuf );
204
205 if ( ! pyresult ) {
206 PyErr_Print();
207 throw std::runtime_error( "Failure in TPyMultiGradFunction::Gradient" );
208 }
209
210 Py_DECREF( pyresult );
211
212 } else
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Simply forward the call to python self.
218
219void TPyMultiGradFunction::FdF( const double* x, double& f, double* df ) const
220{
221 PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "FdF" );
222
223 if ( pymethod ) {
225 PyObject* pyf = PyList_New( 1 );
226 PyList_SetItem( pyf, 0, PyFloat_FromDouble( f ) );
228
229 PyObject* pyresult = DispatchCall( fPySelf, "FdF", pymethod, xbuf, pyf, dfbuf );
230 f = PyFloat_AsDouble( PyList_GetItem( pyf, 0 ) );
231
232 Py_DECREF( dfbuf );
233 Py_DECREF( pyf );
234 Py_DECREF( xbuf );
235
236 if ( ! pyresult ) {
237 PyErr_Print();
238 throw std::runtime_error( "Failure in TPyMultiGradFunction::FdF" );
239 }
240
241 Py_DECREF( pyresult );
242
243 } else
245}
246
247////////////////////////////////////////////////////////////////////////////////
248/// Simply forward the call to python self.
249
250double TPyMultiGradFunction::DoDerivative( const double * x, unsigned int icoord ) const
251{
253 PyObject* pycoord = PyLong_FromLong( icoord );
254
255 PyObject* pyresult = DispatchCall( fPySelf, "DoDerivative", NULL, xbuf, pycoord );
256 Py_DECREF( pycoord );
257 Py_DECREF( xbuf );
258
259 if ( ! pyresult ) {
260 PyErr_Print();
261 throw std::runtime_error( "Failure in TPyMultiGradFunction::DoDerivative" );
262 }
263
264 double cppresult = (double)PyFloat_AsDouble( pyresult );
265 Py_XDECREF( pyresult );
266
267 return cppresult;
268}
269
#define f(i)
Definition: RSha256.hxx:104
double Double_t
Definition: RtypesCore.h:55
#define ClassImp(name)
Definition: Rtypes.h:365
_object PyObject
Definition: TPyArg.h:20
static PyObject * GetOverriddenPyMethod(PyObject *pyself, const char *method)
static PyObject * DispatchCall(PyObject *pyself, const char *method, PyObject *pymethod=NULL, PyObject *arg1=NULL, PyObject *arg2=NULL, PyObject *arg3=NULL)
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
static TPyBufferFactory * Instance()
virtual void Gradient(const T *x, T *grad) const
Evaluate all the vector of function derivatives (gradient) at a point x.
Definition: IFunction.h:342
virtual void FdF(const T *x, T &f, T *df) const
Optimized method to evaluate at the same time the function value and derivative at a point x.
Definition: IFunction.h:357
virtual unsigned int NDim() const
Retrieve the dimension of the function.
TPyMultiGenFunction(PyObject *self=0)
virtual double DoEval(const double *x) const
Simply forward the call to python self.
virtual ~TPyMultiGenFunction()
Destructor. Only deref if still holding on to Py_None (circular otherwise).
TPyMultiGradFunction(PyObject *self=0)
virtual unsigned int NDim() const
Retrieve the dimension of the function.
virtual void Gradient(const double *x, double *grad) const
Simply forward the call to python self.
virtual double DoDerivative(const double *x, unsigned int icoord) const
Simply forward the call to python self.
virtual ~TPyMultiGradFunction()
Destructor. Only deref if still holding on to Py_None (circular otherwise).
virtual double DoEval(const double *x) const
Simply forward the call to python self.
virtual void FdF(const double *x, double &f, double *df) const
Simply forward the call to python self.
Double_t x[n]
Definition: legend1.C:17
Bool_t MethodProxy_CheckExact(T *object)
Definition: MethodProxy.h:69