Changeset 9bd69098 in sasview for sansmodels/src/sans/models/c_models/CCylinderModel.cpp
- Timestamp:
- Aug 7, 2009 9:10:34 AM (15 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 58c6ba6
- Parents:
- 83a25da
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sansmodels/src/sans/models/c_models/CCylinderModel.cpp
r4176435 r9bd69098 22 22 * 23 23 */ 24 #define NO_IMPORT_ARRAY 25 #define PY_ARRAY_UNIQUE_SYMBOL PyArray_API_sans 24 26 25 27 extern "C" { 26 28 #include <Python.h> 29 #include <arrayobject.h> 27 30 #include "structmember.h" 28 31 #include <stdio.h> … … 142 145 } 143 146 } 144 147 /** 148 * Function to call to evaluate model 149 * @param args: input numpy array q[] 150 * @return: numpy array object 151 */ 152 153 static PyObject *evaluateOneDim(CylinderModel* model, PyArrayObject *q){ 154 PyArrayObject *result; 155 156 // Check validity of array q , q must be of dimension 1, an array of double 157 if (q->nd != 1 || q->descr->type_num != PyArray_DOUBLE) 158 { 159 //const char * message= "Invalid array: q->nd=%d,type_num=%d\n",q->nd,q->descr->type_num; 160 //PyErr_SetString(PyExc_ValueError , message); 161 return NULL; 162 } 163 result = (PyArrayObject *)PyArray_FromDims(q->nd, (int *)(q->dimensions), 164 PyArray_DOUBLE); 165 if (result == NULL) { 166 const char * message= "Could not create result "; 167 PyErr_SetString(PyExc_RuntimeError , message); 168 return NULL; 169 } 170 for (int i = 0; i < q->dimensions[0]; i++){ 171 double q_value = *(double *)(q->data + i*q->strides[0]); 172 double *result_value = (double *)(result->data + i*result->strides[0]); 173 *result_value =(*model)(q_value); 174 } 175 return PyArray_Return(result); 176 } 177 /** 178 * Function to call to evaluate model 179 * @param args: input numpy array [q[],phi[]] 180 * @return: numpy array object 181 */ 182 static PyObject * evaluateTwoDim( CylinderModel* model, 183 PyArrayObject *q, PyArrayObject *phi) 184 { 185 PyArrayObject *result; 186 //check validity of input vectors 187 if (q->nd != 1 || q->descr->type_num != PyArray_DOUBLE 188 || phi->nd != 1 || phi->descr->type_num != PyArray_DOUBLE 189 || phi->dimensions[0] != q->dimensions[0]){ 190 191 //const char * message= "Invalid array: q->nd=%d,type_num=%d\n",q->nd,q->descr->type_num; 192 PyErr_SetString(PyExc_ValueError ,"wrong input"); 193 return NULL; 194 } 195 result= (PyArrayObject *)PyArray_FromDims(q->nd,(int*)(q->dimensions), PyArray_DOUBLE); 196 197 if (result == NULL){ 198 const char * message= "Could not create result "; 199 PyErr_SetString(PyExc_RuntimeError , message); 200 return NULL; 201 } 202 203 for (int i = 0; i < q->dimensions[0]; i++) { 204 double q_value = *(double *)(q->data + i*q->strides[0]); 205 double phi_value = *(double *)(phi->data + i*phi->strides[0]); 206 double *result_value = (double *)(result->data + i*result->strides[0]); 207 if (q_value == 0) 208 *result_value = 0.0; 209 else 210 *result_value = model->evaluate_rphi(q_value, phi_value); 211 } 212 return PyArray_Return(result); 213 } 214 /** 215 * Function to call to evaluate model 216 * @param args: input numpy array [x[],y[]] 217 * @return: numpy array object 218 */ 219 static PyObject * evaluateTwoDimXY( CylinderModel* model, 220 PyArrayObject *x, PyArrayObject *y) 221 { 222 PyArrayObject *result; 223 int i,j, x_len, y_len, dims[2]; 224 //check validity of input vectors 225 if (x->nd != 2 || x->descr->type_num != PyArray_DOUBLE 226 || y->nd != 2 || y->descr->type_num != PyArray_DOUBLE 227 || y->dimensions[1] != x->dimensions[0]){ 228 const char * message= "evaluateTwoDimXY expect 2 numpy arrays"; 229 PyErr_SetString(PyExc_ValueError , message); 230 return NULL; 231 } 232 233 if (PyArray_Check(x) && PyArray_Check(y)) { 234 x_len = dims[0]= x->dimensions[0]; 235 y_len = dims[1]= y->dimensions[1]; 236 237 // Make a new double matrix of same dims 238 result=(PyArrayObject *) PyArray_FromDims(2,dims,NPY_DOUBLE); 239 if (result == NULL){ 240 const char * message= "Could not create result "; 241 PyErr_SetString(PyExc_RuntimeError , message); 242 return NULL; 243 } 244 245 /* Do the calculation. */ 246 for ( i=0; i< x_len; i++) { 247 for ( j=0; j< y_len; j++) { 248 double x_value = *(double *)(x->data + i*x->strides[0]); 249 double y_value = *(double *)(y->data + j*y->strides[1]); 250 double *result_value = (double *)(result->data + 251 i*result->strides[0] + j*result->strides[1]); 252 *result_value = (*model)(x_value, y_value); 253 } 254 } 255 return PyArray_Return(result); 256 257 }else{ 258 PyErr_SetString(CCylinderModelError, 259 "CCylinderModel.evaluateTwoDimXY couldn't run."); 260 return NULL; 261 } 262 } 263 /** 264 * evalDistribution function evaluate a model function with input vector 265 * @param args: input q as vector or [qx, qy] where qx, qy are vectors 266 * 267 */ 268 static PyObject * evalDistribution(CCylinderModel *self, PyObject *args){ 269 PyObject *qx, *qy; 270 PyArrayObject * pars; 271 int npars ,mpars; 272 273 // Get parameters 274 275 // Reader parameter dictionary 276 self->model->scale = PyFloat_AsDouble( PyDict_GetItemString(self->params, "scale") ); 277 self->model->length = PyFloat_AsDouble( PyDict_GetItemString(self->params, "length") ); 278 self->model->cyl_theta = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_theta") ); 279 self->model->background = PyFloat_AsDouble( PyDict_GetItemString(self->params, "background") ); 280 self->model->radius = PyFloat_AsDouble( PyDict_GetItemString(self->params, "radius") ); 281 self->model->contrast = PyFloat_AsDouble( PyDict_GetItemString(self->params, "contrast") ); 282 self->model->cyl_phi = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_phi") ); 283 // Read in dispersion parameters 284 PyObject* disp_dict; 285 DispersionVisitor* visitor = new DispersionVisitor(); 286 disp_dict = PyDict_GetItemString(self->dispersion, "radius"); 287 self->model->radius.dispersion->accept_as_destination(visitor, self->model->radius.dispersion, disp_dict); 288 disp_dict = PyDict_GetItemString(self->dispersion, "length"); 289 self->model->length.dispersion->accept_as_destination(visitor, self->model->length.dispersion, disp_dict); 290 disp_dict = PyDict_GetItemString(self->dispersion, "cyl_theta"); 291 self->model->cyl_theta.dispersion->accept_as_destination(visitor, self->model->cyl_theta.dispersion, disp_dict); 292 disp_dict = PyDict_GetItemString(self->dispersion, "cyl_phi"); 293 self->model->cyl_phi.dispersion->accept_as_destination(visitor, self->model->cyl_phi.dispersion, disp_dict); 294 295 296 // Get input and determine whether we have to supply a 1D or 2D return value. 297 if ( !PyArg_ParseTuple(args,"O",&pars) ) { 298 PyErr_SetString(CCylinderModelError, 299 "CCylinderModel.evalDistribution expects a q value."); 300 return NULL; 301 } 302 // Check params 303 304 if(PyArray_Check(pars)==1) { 305 306 // Length of list should 1 or 2 307 npars = pars->nd; 308 if(npars==1) { 309 // input is a numpy array 310 if (PyArray_Check(pars)) { 311 return evaluateOneDim(self->model, (PyArrayObject*)pars); 312 } 313 }else{ 314 PyErr_SetString(CCylinderModelError, 315 "CCylinderModel.evalDistribution expect numpy array of one dimension."); 316 return NULL; 317 } 318 }else if( PyList_Check(pars)==1) { 319 // Length of list should be 2 for I(qx,qy) 320 mpars = PyList_GET_SIZE(pars); 321 if(mpars!=2) { 322 PyErr_SetString(CCylinderModelError, 323 "CCylinderModel.evalDistribution expects a list of dimension 2."); 324 return NULL; 325 } 326 qx = PyList_GET_ITEM(pars,0); 327 qy = PyList_GET_ITEM(pars,1); 328 if (PyArray_Check(qx) && PyArray_Check(qy)) { 329 return evaluateTwoDimXY(self->model, (PyArrayObject*)qx, 330 (PyArrayObject*)qy); 331 }else{ 332 PyErr_SetString(CCylinderModelError, 333 "CCylinderModel.evalDistribution expect 2 numpy arrays in list."); 334 return NULL; 335 } 336 }else{ 337 PyErr_SetString(CCylinderModelError, 338 "CCylinderModel.evalDistribution couln't be run."); 339 return NULL; 340 } 341 } 145 342 146 343 /** … … 326 523 {"runXY", (PyCFunction)runXY , METH_VARARGS, 327 524 "Evaluate the model at a given Q or Qx, Qy"}, 525 526 {"evalDistribution", (PyCFunction)evalDistribution , METH_VARARGS, 527 "Evaluate the model at a given Q or Qx, Qy vector "}, 328 528 {"reset", (PyCFunction)reset , METH_VARARGS, 329 529 "Reset pair correlation"}, … … 376 576 377 577 378 static PyMethodDef module_methods[] = {379 {NULL}380 };578 //static PyMethodDef module_methods[] = { 579 // {NULL} 580 //}; 381 581 382 582 /**
Note: See TracChangeset
for help on using the changeset viewer.