[9e8dc22] | 1 | import math |
---|
| 2 | import pylab, numpy |
---|
| 3 | |
---|
| 4 | class PrInverse: |
---|
| 5 | |
---|
| 6 | D = 70.0 |
---|
| 7 | #alpha = 0.0001 |
---|
| 8 | alpha = 0.0 |
---|
| 9 | |
---|
| 10 | data_x = [] |
---|
| 11 | data_y = [] |
---|
| 12 | data_err = [] |
---|
| 13 | |
---|
| 14 | r = [] |
---|
| 15 | pr = [] |
---|
| 16 | pr_err = [] |
---|
| 17 | |
---|
| 18 | xmult = [] |
---|
| 19 | |
---|
| 20 | c = None |
---|
| 21 | |
---|
| 22 | def __init__(self, D=60.0): |
---|
| 23 | ## Max distance |
---|
| 24 | self.D = D |
---|
| 25 | self.xmult = pylab.arange(0.001, self.D, self.D/21.0) |
---|
| 26 | |
---|
| 27 | def l_multiplier(self, c): |
---|
| 28 | return self.alpha * self._lmult2(c) |
---|
| 29 | |
---|
| 30 | def _lmult1(self, c): |
---|
| 31 | sum = 0 |
---|
| 32 | for i in range(len(c)-1): |
---|
| 33 | sum += (c[i+1]-c[i])**2 |
---|
| 34 | return sum |
---|
| 35 | |
---|
| 36 | def _lmult2(self, c): |
---|
| 37 | sum = 0 |
---|
| 38 | for i in range(len(self.xmult)): |
---|
| 39 | dp = 0 |
---|
| 40 | for j in range(len(c)): |
---|
| 41 | dp += c[j] * self._ortho_derived(j+1, self.xmult[i]) |
---|
| 42 | sum += (dp**2) |
---|
| 43 | return sum * self.D/len(self.xmult) |
---|
| 44 | |
---|
| 45 | def _ortho_transformed(self, n, q): |
---|
| 46 | """ |
---|
| 47 | Fourier transform of the nth orthogonal function |
---|
| 48 | """ |
---|
| 49 | return 8.0*math.pi**2/q * self.D * n * (-1)**(n+1) * \ |
---|
| 50 | math.sin(q*self.D) / ( (math.pi*n)**2 - (q*self.D)**2) |
---|
| 51 | |
---|
| 52 | def _ortho_derived(self, n, r): |
---|
| 53 | |
---|
| 54 | return 2.0*math.sin(math.pi*n*r/self.D) + 2.0*r*math.cos(math.pi*n*r/self.D) |
---|
| 55 | |
---|
| 56 | def iq(self, c, q): |
---|
| 57 | sum = 0.0 |
---|
| 58 | N = len(c) |
---|
| 59 | #str = '' |
---|
| 60 | for i in range(N): |
---|
| 61 | # n goes from 1 to N in the formulas |
---|
| 62 | sum += c[i] * self._ortho_transformed(i+1, q) |
---|
| 63 | #str += "c%i=%g " % (i, c[i]); |
---|
| 64 | #print str |
---|
| 65 | #import time |
---|
| 66 | #time.sleep(10) |
---|
| 67 | return sum |
---|
| 68 | |
---|
| 69 | def residuals(self, params): |
---|
| 70 | """ |
---|
| 71 | Calculates the vector of residuals for each point |
---|
| 72 | in y for a given set of input parameters. |
---|
| 73 | @param params: list of parameter values |
---|
| 74 | @return: vector of residuals |
---|
| 75 | """ |
---|
| 76 | residuals = [] |
---|
| 77 | M = len(self.data_x) |
---|
| 78 | #lmult = self.l_multiplier(params) |
---|
| 79 | lmult = 0 |
---|
| 80 | for j in range(M): |
---|
| 81 | if self.data_x[j]>0.0: |
---|
| 82 | #print j |
---|
| 83 | value = (self.data_y[j] - self.iq(params, self.data_x[j]))**2 / self.data_err[j]**2 |
---|
| 84 | #print self.data_x[j], value, lmult/float(M) |
---|
| 85 | value += lmult/float(M) |
---|
| 86 | residuals.append( value ) |
---|
| 87 | |
---|
| 88 | return residuals |
---|
| 89 | |
---|
| 90 | def convert_res(self, res): |
---|
| 91 | v = numpy.asarray(res) |
---|
| 92 | if not v.flags.contiguous: |
---|
| 93 | print "not contiguous" |
---|
| 94 | v = numpy.array(res) |
---|
| 95 | |
---|
| 96 | print v |
---|
| 97 | res = self.c.residuals(v) |
---|
| 98 | print res |
---|
| 99 | #return self.c.residuals(v) |
---|
| 100 | return res |
---|
| 101 | |
---|
| 102 | def new_fit(self): |
---|
| 103 | from sans.pr.invertor import Invertor |
---|
| 104 | from scipy import optimize |
---|
| 105 | |
---|
| 106 | c = Invertor() |
---|
| 107 | c.set_dmax(self.D) |
---|
| 108 | c.set_x(self.data_x) |
---|
| 109 | c.set_y(self.data_y) |
---|
| 110 | c.set_err(self.data_err) |
---|
| 111 | |
---|
| 112 | out, cov_x = c.invert() |
---|
| 113 | |
---|
| 114 | return out, cov_x |
---|
| 115 | |
---|
| 116 | def new_fit_0(self): |
---|
| 117 | from sans.pr.core.pr_inversion import Cinvertor |
---|
| 118 | from scipy import optimize |
---|
| 119 | |
---|
| 120 | self.c = Cinvertor() |
---|
| 121 | self.c.set_dmax(self.D) |
---|
| 122 | self.c.set_x(self.data_x) |
---|
| 123 | self.c.set_y(self.data_y) |
---|
| 124 | self.c.set_err(self.data_err) |
---|
| 125 | print "Valid", self.c.is_valid() |
---|
| 126 | M=10 |
---|
| 127 | p = numpy.ones(M) |
---|
| 128 | |
---|
| 129 | p[0] = 10.0 |
---|
| 130 | |
---|
| 131 | out, cov_x, info, mesg, success = optimize.leastsq(self.c.residuals, p, full_output=1, warning=True) |
---|
| 132 | #out, cov_x, info, mesg, success = optimize.leastsq(self.convert_res, p, full_output=1, warning=True) |
---|
| 133 | |
---|
| 134 | |
---|
| 135 | return out, cov_x |
---|
| 136 | |
---|
| 137 | def fit(self): |
---|
| 138 | return self.new_fit() |
---|
| 139 | |
---|
| 140 | import numpy |
---|
| 141 | from scipy import optimize |
---|
| 142 | |
---|
| 143 | |
---|
| 144 | M = len(self.data_x)-3 |
---|
| 145 | M=3 |
---|
| 146 | print "Number of functions: ", M |
---|
| 147 | p = numpy.zeros(M) |
---|
| 148 | p[0] = 1000.0 |
---|
| 149 | |
---|
| 150 | out, cov_x, info, mesg, success = optimize.leastsq(self.residuals, p, full_output=1, warning=True) |
---|
| 151 | |
---|
| 152 | |
---|
| 153 | return out, cov_x |
---|
| 154 | |
---|
| 155 | def pr_theory(self, r, R): |
---|
| 156 | """ |
---|
| 157 | |
---|
| 158 | """ |
---|
| 159 | if r<=2*R: |
---|
| 160 | return 12.0* ((0.5*r/R)**2) * ((1.0-0.5*r/R)**2) * ( 2.0 + 0.5*r/R ) |
---|
| 161 | else: |
---|
| 162 | return 0.0 |
---|
| 163 | |
---|
| 164 | |
---|
| 165 | def residuals_pr(self, params): |
---|
| 166 | import pylab |
---|
| 167 | |
---|
| 168 | residuals = [] |
---|
| 169 | M = len(self.r) |
---|
| 170 | |
---|
| 171 | |
---|
| 172 | for j in range(M): |
---|
| 173 | |
---|
| 174 | if self.r[j]>0: |
---|
| 175 | err2 = (self.pr_err[j])**2 |
---|
| 176 | if j>0: |
---|
| 177 | err2 += 0.25*(self.pr[j-1]-self.pr[j-1])**2 |
---|
| 178 | value = (self.pr[j]-self.pr_calc(params, self.r[j]))**2/err2 |
---|
| 179 | residuals.append( value ) |
---|
| 180 | |
---|
| 181 | return residuals |
---|
| 182 | |
---|
| 183 | def pr_calc(self, c, r): |
---|
| 184 | sum = 0 |
---|
| 185 | N = len(c) |
---|
| 186 | for i in range(N): |
---|
| 187 | sum += c[i]*2.0*r*math.sin(math.pi*(i+1)*r/self.D) |
---|
| 188 | |
---|
| 189 | return sum |
---|
| 190 | |
---|
| 191 | def fill_sphere(self, radius=60): |
---|
| 192 | import pylab |
---|
| 193 | import numpy |
---|
| 194 | self.r = pylab.arange(0.0, radius, radius/50.0) |
---|
| 195 | M = len(self.r) |
---|
| 196 | self.pr = numpy.zeros(M) |
---|
| 197 | self.pr_err = numpy.zeros(M) |
---|
| 198 | |
---|
| 199 | for j in range(M): |
---|
| 200 | self.pr[j] = self.pr_theory(self.r[j], radius) |
---|
| 201 | self.pr_err[j] = math.sqrt(self.pr[j]) |
---|
| 202 | |
---|
| 203 | |
---|
| 204 | def fit_pr(self): |
---|
| 205 | import numpy |
---|
| 206 | from scipy import optimize |
---|
| 207 | |
---|
| 208 | |
---|
| 209 | M = len(self.r)-3 |
---|
| 210 | M=2 |
---|
| 211 | print "Number of functions: ", M |
---|
| 212 | p = numpy.ones(M) |
---|
| 213 | #p = numpy.ones(15) |
---|
| 214 | |
---|
| 215 | out, cov_x, info, mesg, success = optimize.leastsq(self.residuals_pr, p, full_output=1, warning=True) |
---|
| 216 | |
---|
| 217 | return out, cov_x |
---|
| 218 | |
---|
| 219 | |
---|
| 220 | |
---|
| 221 | def load(self, path = "sphere_test_data.txt"): |
---|
| 222 | # Read the data from the data file |
---|
| 223 | self.data_x = numpy.zeros(0) |
---|
| 224 | self.data_y = numpy.zeros(0) |
---|
| 225 | self.data_err = numpy.zeros(0) |
---|
| 226 | if not path == None: |
---|
| 227 | input_f = open(path,'r') |
---|
| 228 | buff = input_f.read() |
---|
| 229 | lines = buff.split('\n') |
---|
| 230 | for line in lines: |
---|
| 231 | try: |
---|
| 232 | toks = line.split() |
---|
| 233 | x = float(toks[0]) |
---|
| 234 | y = float(toks[1]) |
---|
| 235 | self.data_x = numpy.append(self.data_x, x) |
---|
| 236 | self.data_y = numpy.append(self.data_y, y) |
---|
| 237 | self.data_err = numpy.append(self.data_err, math.sqrt(y)+1000.0) |
---|
| 238 | except: |
---|
| 239 | print "Error reading line: ", line |
---|
| 240 | |
---|
| 241 | print "Lines read:", len(self.data_x) |
---|
| 242 | |
---|
| 243 | |
---|
| 244 | if __name__ == "__main__": |
---|
| 245 | from sans.pr.core.pr_inversion import Cinvertor |
---|
| 246 | pr = PrInverse() |
---|
| 247 | pr.load("sphere_80.txt") |
---|
| 248 | out, cov = pr.fit() |
---|
| 249 | |
---|
| 250 | print "output:" |
---|
| 251 | print out |
---|
| 252 | |
---|