Changeset 2d06beb in sasview for pr_inversion
- Timestamp:
- May 5, 2008 2:03:39 PM (17 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:
- b43a009
- Parents:
- 150c04a
- Location:
- pr_inversion
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
pr_inversion/c_extensions/Cinvertor.c
reca05c8 r2d06beb 80 80 Py_ssize_t ndata; 81 81 double *data; 82 int i; 82 83 83 84 if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL; 84 85 OUTVECTOR(data_obj,data,ndata); 85 self->params.x = data; 86 87 free(self->params.x); 88 self->params.x = (double*) malloc(ndata*sizeof(double)); 89 90 if(self->params.x==NULL) { 91 PyErr_SetString(CinvertorError, 92 "Cinvertor.set_x: problem allocating memory."); 93 return NULL; 94 } 95 96 for (i=0; i<ndata; i++) { 97 self->params.x[i] = data[i]; 98 } 99 100 //self->params.x = data; 86 101 self->params.npoints = ndata; 87 102 return Py_BuildValue("i", self->params.npoints); … … 95 110 96 111 if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL; 97 INVECTOR(data_obj, data, ndata);112 OUTVECTOR(data_obj, data, ndata); 98 113 99 114 // Check that the input array is large enough … … 120 135 Py_ssize_t ndata; 121 136 double *data; 137 int i; 122 138 123 139 if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL; 124 140 OUTVECTOR(data_obj,data,ndata); 125 self->params.y = data; 141 142 free(self->params.y); 143 self->params.y = (double*) malloc(ndata*sizeof(double)); 144 145 if(self->params.y==NULL) { 146 PyErr_SetString(CinvertorError, 147 "Cinvertor.set_y: problem allocating memory."); 148 return NULL; 149 } 150 151 for (i=0; i<ndata; i++) { 152 self->params.y[i] = data[i]; 153 } 154 155 //self->params.y = data; 126 156 self->params.ny = ndata; 127 157 return Py_BuildValue("i", self->params.ny); … … 135 165 136 166 if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL; 137 INVECTOR(data_obj, data, ndata);167 OUTVECTOR(data_obj, data, ndata); 138 168 139 169 // Check that the input array is large enough … … 160 190 Py_ssize_t ndata; 161 191 double *data; 192 int i; 162 193 163 194 if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL; 164 195 OUTVECTOR(data_obj,data,ndata); 165 self->params.err = data; 196 197 free(self->params.err); 198 self->params.err = (double*) malloc(ndata*sizeof(double)); 199 200 if(self->params.err==NULL) { 201 PyErr_SetString(CinvertorError, 202 "Cinvertor.set_err: problem allocating memory."); 203 return NULL; 204 } 205 206 for (i=0; i<ndata; i++) { 207 self->params.err[i] = data[i]; 208 } 209 210 //self->params.err = data; 166 211 self->params.nerr = ndata; 167 212 return Py_BuildValue("i", self->params.nerr); … … 175 220 176 221 if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL; 177 INVECTOR(data_obj, data, ndata);222 OUTVECTOR(data_obj, data, ndata); 178 223 179 224 // Check that the input array is large enough … … 414 459 } 415 460 461 static PyObject * basefunc_ft(Cinvertor *self, PyObject *args) { 462 double d_max, q; 463 int n; 464 465 if (!PyArg_ParseTuple(args, "did", &d_max, &n, &q)) return NULL; 466 return Py_BuildValue("f", ortho_transformed(d_max, n, q)); 467 468 } 416 469 417 470 static PyMethodDef Cinvertor_methods[] = { … … 435 488 {"get_pr_err", (PyCFunction)get_pr_err, METH_VARARGS, ""}, 436 489 {"is_valid", (PyCFunction)is_valid, METH_VARARGS, ""}, 490 {"basefunc_ft", (PyCFunction)basefunc_ft, METH_VARARGS, ""}, 437 491 438 492 {NULL} -
pr_inversion/c_extensions/invertor.c
reca05c8 r2d06beb 8 8 */ 9 9 void invertor_dealloc(Invertor_params *pars) { 10 //free(pars->x);11 //free(pars->y);12 //free(pars->err);10 free(pars->x); 11 free(pars->y); 12 free(pars->err); 13 13 } 14 14 … … 133 133 } 134 134 135 -
pr_inversion/c_extensions/invertor.h
reca05c8 r2d06beb 29 29 void pr_err(double *pars, double *err, double d_max, int n_c, 30 30 double r, double *pr_value, double *pr_value_err); 31 32 31 #endif -
pr_inversion/invertor.py
reca05c8 r2d06beb 5 5 6 6 ## Chisqr of the last computation 7 chisqr = 0 7 chi2 = 0 8 ## Time elapsed for last computation 9 elapsed = 0 8 10 9 11 def __init__(self): … … 58 60 return None 59 61 62 def clone(self): 63 """ 64 Return a clone of this instance 65 """ 66 invertor = Invertor() 67 invertor.chi2 = self.chi2 68 invertor.elapsed = self.elapsed 69 invertor.alpha = self.alpha 70 invertor.d_max = self.d_max 71 72 invertor.x = self.x 73 invertor.y = self.y 74 invertor.err = self.err 75 76 return invertor 77 60 78 def invert(self, nfunc=5): 61 79 """ … … 63 81 """ 64 82 from scipy import optimize 83 import time 65 84 66 85 # First, check that the current data is valid … … 69 88 70 89 p = numpy.ones(nfunc) 90 t_0 = time.time() 71 91 out, cov_x, info, mesg, success = optimize.leastsq(self.residuals, p, full_output=1, warning=True) 72 92 … … 78 98 79 99 self.chi2 = chisqr 100 101 # Store computation time 102 self.elapsed = time.time() - t_0 80 103 81 104 return out, cov_x … … 92 115 93 116 p = numpy.ones(nfunc) 117 t_0 = time.time() 94 118 out, cov_x, info, mesg, success = optimize.leastsq(self.pr_residuals, p, full_output=1, warning=True) 95 119 … … 102 126 self.chisqr = chisqr 103 127 128 # Store computation time 129 self.elapsed = time.time() - t_0 130 104 131 return out, cov_x 105 132 … … 117 144 118 145 return self.get_pr_err(c, c_err, r) 146 147 def lstsq(self, nfunc=5): 148 import math 149 from scipy.linalg.basic import lstsq 150 151 # a -- An M x N matrix. 152 # b -- An M x nrhs matrix or M vector. 153 npts = len(self.x) 154 nq = 20 155 sqrt_alpha = math.sqrt(self.alpha) 156 157 a = numpy.zeros([npts+nq, nfunc]) 158 b = numpy.zeros(npts+nq) 159 err = numpy.zeros(nfunc) 160 161 for j in range(nfunc): 162 for i in range(npts): 163 a[i][j] = self.basefunc_ft(self.d_max, j+1, self.x[i])/self.err[i] 164 for i_q in range(nq): 165 r = self.d_max/nq*i_q 166 #a[i_q+npts][j] = sqrt_alpha * 1.0/nq*self.d_max*2.0*math.fabs(math.sin(math.pi*(j+1)*r/self.d_max) + math.pi*(j+1)*r/self.d_max * math.cos(math.pi*(j+1)*r/self.d_max)) 167 a[i_q+npts][j] = sqrt_alpha * 1.0/nq*self.d_max*2.0*(2.0*math.pi*(j+1)/self.d_max*math.cos(math.pi*(j+1)*r/self.d_max) + math.pi**2*(j+1)**2*r/self.d_max**2 * math.sin(math.pi*(j+1)*r/self.d_max)) 168 169 for i in range(npts): 170 b[i] = self.y[i]/self.err[i] 171 172 c, chi2, rank, n = lstsq(a, b) 173 self.chi2 = chi2 174 175 at = numpy.transpose(a) 176 inv_cov = numpy.zeros([nfunc,nfunc]) 177 for i in range(nfunc): 178 for j in range(nfunc): 179 inv_cov[i][j] = 0.0 180 for k in range(npts): 181 inv_cov[i][j] = at[i][k]*a[k][j] 182 183 # Compute the reg term size for the output 184 sum_sig = 0.0 185 sum_reg = 0.0 186 for j in range(nfunc): 187 for i in range(npts): 188 sum_sig += (a[i][j])**2 189 for i in range(nq): 190 sum_reg += (a[i_q+npts][j])**2 191 192 new_alpha = sum_sig/(sum_reg/self.alpha) 193 print "Suggested alpha =", 0.1*new_alpha 194 195 try: 196 err = math.fabs(chi2/(npts-nfunc))* inv_cov 197 except: 198 print "Error estimating uncertainties" 199 200 201 return c, err 202 203 def svd(self, nfunc=5): 204 import math, time 205 # Ac - b = 0 206 207 A = numpy.zeros([nfunc, nfunc]) 208 y = numpy.zeros(nfunc) 209 210 t_0 = time.time() 211 for i in range(nfunc): 212 # A 213 for j in range(nfunc): 214 A[i][j] = 0.0 215 for k in range(len(self.x)): 216 err = self.err[k] 217 A[i][j] += 1.0/err/err*self.basefunc_ft(self.d_max, j+1, self.x[k]) \ 218 *self.basefunc_ft(self.d_max, i+1, self.x[k]); 219 #print A[i][j] 220 #A[i][j] -= self.alpha*(math.cos(math.pi*(i+j)) - math.cos(math.pi*(i-j))); 221 if i==j: 222 A[i][j] += -1.0*self.alpha 223 elif i-j==1 or i-j==-1: 224 A[i][j] += 1.0*self.alpha 225 #print " ",A[i][j] 226 # y 227 y[i] = 0.0 228 for k in range(len(self.x)): 229 y[i] = self.y[k]/self.err[k]/self.err[k]*self.basefunc_ft(self.d_max, i+1, self.x[k]) 230 231 print time.time()-t_0, 'secs' 232 233 # use numpy.pinv(A) 234 #inv_A = numpy.linalg.inv(A) 235 #c = y*inv_A 236 print y 237 c = numpy.linalg.solve(A, y) 238 239 240 print c 241 242 err = numpy.zeros(len(c)) 243 return c, err 244 245 246 119 247 120 248 -
pr_inversion/test/utest_invertor.py
reca05c8 r2d06beb 174 174 print "chi2 =", chi2/51.0 175 175 raise 176 177 def test_lstsq(self): 178 """ 179 Test an inversion for which we know the answer 180 """ 181 x, y, err = load("sphere_80.txt") 182 183 # Choose the right d_max... 184 self.invertor.d_max = 160.0 185 # Set a small alpha 186 self.invertor.alpha = .0007 187 # Set data 188 self.invertor.x = x 189 self.invertor.y = y 190 self.invertor.err = err 191 # Perform inversion 192 #out, cov = self.invertor.invert(10) 193 194 out, cov = self.invertor.lstsq(10) 195 196 197 # This is a very specific case 198 # We should make sure it always passes 199 try: 200 self.assertTrue(self.invertor.chi2/len(x)<200.00) 201 except: 202 print "Chi2(I(q)) =", self.invertor.chi2/len(x) 203 raise 204 205 # Check the computed P(r) with the theory 206 # for shpere of radius 80 207 x = pylab.arange(0.01, self.invertor.d_max, self.invertor.d_max/51.0) 208 y = numpy.zeros(len(x)) 209 dy = numpy.zeros(len(x)) 210 y_true = numpy.zeros(len(x)) 211 212 sum = 0.0 213 sum_true = 0.0 214 for i in range(len(x)): 215 #y[i] = self.invertor.pr(out, x[i]) 216 (y[i], dy[i]) = self.invertor.pr_err(out, cov, x[i]) 217 sum += y[i] 218 if x[i]<80.0: 219 y_true[i] = pr_theory(x[i], 80.0) 220 else: 221 y_true[i] = 0 222 sum_true += y_true[i] 223 224 y = y/sum*self.invertor.d_max/len(x) 225 dy = dy/sum*self.invertor.d_max/len(x) 226 y_true = y_true/sum_true*self.invertor.d_max/len(x) 227 228 chi2 = 0.0 229 for i in range(len(x)): 230 res = (y[i]-y_true[i])/dy[i] 231 chi2 += res*res 232 233 try: 234 self.assertTrue(chi2/51.0<50.0) 235 except: 236 print "chi2(P(r)) =", chi2/51.0 237 raise 176 238 177 239 def test_q_zero(self): … … 239 301 print "Chi2 =", self.invertor.chi2 240 302 raise 303 304 def no_test_time(self): 305 x, y, err = load("sphere_80.txt") 306 307 # Choose the right d_max... 308 self.invertor.d_max = 160.0 309 # Set a small alpha 310 self.invertor.alpha = 1e-7 311 # Set data 312 self.invertor.x = x 313 self.invertor.y = y 314 self.invertor.err = err 315 316 # time scales like nfunc**2 317 # on a Lenovo Intel Core 2 CPU T7400 @ 2.16GHz, 318 # I get time/(nfunc)**2 = 0.022 sec 241 319 242 243 320 out, cov = self.invertor.invert(15) 321 t16 = self.invertor.elapsed 322 323 out, cov = self.invertor.invert(30) 324 t30 = self.invertor.elapsed 325 326 t30s = t30/30.0**2 327 self.assertTrue( (t30s-t16/16.0**2)/t30s <1.2 ) 328 329 def test_clone(self): 330 self.invertor.x = self.x_in 331 clone = self.invertor.clone() 332 333 for i in range(len(self.x_in)): 334 self.assertEqual(self.x_in[i], clone.x[i]) 335 244 336 def pr_theory(r, R): 245 337 """
Note: See TracChangeset
for help on using the changeset viewer.