1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | #include "ten.h" |
25 | #include "privateTen.h" |
26 | |
27 | double |
28 | tenBVecNonLinearFit_error(double *bb, double *ss, double *ww, int len, |
29 | double amp, double dec) { |
30 | int ii; |
31 | double err, tmp; |
32 | |
33 | err = 0; |
34 | for (ii=0; ii<len; ii++) { |
35 | tmp = ww[ii]*(amp*exp(-dec*bb[ii]) - ss[ii]); |
36 | err += tmp*tmp; |
37 | } |
38 | return err; |
39 | } |
40 | |
41 | void |
42 | tenBVecNonLinearFit_linear(double *amp, double *dec, |
43 | double *bb, double *ss, double *ww, int len) { |
44 | double x, y, wi=0, xi=0, yi=0, xiyi=0, xisq=0, det; |
45 | int ii; |
46 | |
47 | for (ii=0; ii<len; ii++) { |
48 | x = bb[ii]; |
49 | y = log(AIR_MAX(ss[ii], 0.01)((ss[ii]) > (0.01) ? (ss[ii]) : (0.01))); |
50 | xi += ww[ii]*x; |
51 | yi += ww[ii]*y; |
52 | xiyi += ww[ii]*x*y; |
53 | xisq += ww[ii]*x*x; |
54 | wi += ww[ii]; |
55 | } |
56 | det = xisq*wi - xi*xi; |
57 | *dec = -(wi*xiyi - xi*yi)/det; |
58 | *amp = exp((-xi*xiyi + xisq*yi)/det); |
59 | return; |
60 | } |
61 | |
62 | void |
63 | tenBVecNonLinearFit_GNstep(double *d_amp, double *d_dec, |
64 | double *bb, double *ss, double *ww, int len, |
65 | double amp, double dec) { |
66 | double tmp, ff, dfdx1, dfdx2, AA=0, BB=0, CC=0, JTf[2], det; |
67 | int ii; |
68 | |
69 | JTf[0] = JTf[1] = 0; |
70 | for (ii=0; ii<len; ii++) { |
71 | tmp = exp(-dec*bb[ii]); |
72 | ff = ww[ii]*(amp*tmp - ss[ii]); |
73 | dfdx1 = ww[ii]*tmp; |
74 | dfdx2 = -ww[ii]*amp*bb[ii]*tmp; |
75 | AA += dfdx1*dfdx1; |
76 | BB += dfdx1*dfdx2; |
77 | CC += dfdx2*dfdx2; |
78 | JTf[0] += dfdx1*ff; |
79 | JTf[1] += dfdx2*ff; |
80 | } |
81 | det = AA*CC - BB*BB; |
82 | *d_amp = -(CC*JTf[0] - BB*JTf[1])/det; |
83 | *d_dec = -(-BB*JTf[0] + AA*JTf[1])/det; |
84 | return; |
85 | } |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | int |
103 | tenBVecNonLinearFit(Nrrd *nout, const Nrrd *nin, |
104 | double *bb, double *ww, int iterMax, double eps) { |
105 | static const char me[]="tenBVecNonLinearFit"; |
106 | int map[NRRD_DIM_MAX16], vecSize, iter; |
107 | size_t ii, size[NRRD_DIM_MAX16], vecI, vecNum; |
108 | char *vec; |
109 | double *out, ss[AIR_STRLEN_SMALL(128+1)], amp, dec, d_amp, d_dec, error, diff, |
110 | (*vecLup)(const void *v, size_t I); |
111 | |
112 | if (!( nout && nin && bb && ww )) { |
113 | biffAddf(TENtenBiffKey, "%s: got NULL pointer", me); |
114 | return 1; |
115 | } |
116 | |
117 | if (!( nin->dim >= 2 )) { |
118 | biffAddf(TENtenBiffKey, "%s: nin->dim (%d) not >= 2", me, nin->dim); |
119 | return 1; |
120 | } |
121 | if (!( nin->axis[0].size < AIR_STRLEN_SMALL(128+1) )) { |
122 | char stmp[AIR_STRLEN_SMALL(128+1)]; |
123 | biffAddf(TENtenBiffKey, "%s: sorry need nin->axis[0].size (%s) < %d", me, |
124 | airSprintSize_t(stmp, nin->axis[0].size), AIR_STRLEN_SMALL(128+1)); |
125 | return 1; |
126 | } |
127 | |
128 | |
129 | nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size); |
130 | size[0] = 3; |
131 | if (nrrdMaybeAlloc_nva(nout, nrrdTypeDouble, nin->dim, size)) { |
132 | biffMovef(TENtenBiffKey, NRRDnrrdBiffKey, "%s: couldn't allocate output", me); |
133 | return 1; |
134 | } |
135 | for (ii=1; ii<nin->dim; ii++) { |
136 | map[ii] = ii; |
137 | } |
138 | map[0] = -1; |
139 | if (nrrdAxisInfoCopy(nout, nin, map, NRRD_AXIS_INFO_NONE0)) { |
140 | biffMovef(TENtenBiffKey, NRRDnrrdBiffKey, "%s: couldn't copy axis info", me); |
141 | return 1; |
142 | } |
143 | |
144 | |
145 | vecSize = nin->axis[0].size*nrrdTypeSize[nin->type]; |
146 | vecNum = nrrdElementNumber(nin)/nin->axis[0].size; |
147 | vecLup = nrrdDLookup[nin->type]; |
148 | vec = (char*)nin->data; |
149 | out = (double*)nout->data; |
150 | for (vecI=0; vecI<vecNum; vecI++) { |
151 | |
152 | for (ii=0; ii<nin->axis[0].size; ii++) { |
153 | ss[ii] = vecLup(vec, ii); |
154 | } |
155 | |
156 | tenBVecNonLinearFit_linear(&, &dec, bb, ss, ww, nin->axis[0].size); |
157 | error = tenBVecNonLinearFit_error(bb, ss, ww, nin->axis[0].size, amp, dec); |
| Value stored to 'error' is never read |
158 | |
159 | if (iterMax > 0) { |
160 | iter = 0; |
161 | do { |
162 | iter++; |
163 | tenBVecNonLinearFit_GNstep(&d_amp, &d_dec, |
164 | bb, ss, ww, nin->axis[0].size, amp, dec); |
165 | amp += 0.3*d_amp; |
166 | dec += 0.3*d_dec; |
167 | diff = d_amp*d_amp + d_dec*d_dec; |
168 | } while (iter < iterMax && diff > eps); |
169 | } |
170 | error = tenBVecNonLinearFit_error(bb, ss, ww, nin->axis[0].size, amp, dec); |
171 | out[0] = amp; |
172 | out[1] = dec; |
173 | out[2] = error; |
174 | vec += vecSize; |
175 | out += 3; |
176 | } |
177 | |
178 | return 0; |
179 | } |
180 | |