TPCCLIB
Loading...
Searching...
No Matches
bf_dexp.c
Go to the documentation of this file.
1
4/*****************************************************************************/
5#include "tpcclibConfig.h"
6/*****************************************************************************/
7#include <stdio.h>
8#include <stdlib.h>
9#include <math.h>
10#include <time.h>
11#include <string.h>
12/*****************************************************************************/
13#include "tpcextensions.h"
14#include "tpclinopt.h"
15/*****************************************************************************/
16#include "tpcbfm.h"
17/*****************************************************************************/
18
19/*****************************************************************************/
32 const double *x,
35 const double *y,
37 double *w,
39 const int snr,
41 const double kmin,
43 const double kmax,
46 const int bnr,
48 double *k,
51 double *a,
53 double *yfit,
55 TPCSTATUS *status
56) {
57 int verbose=0; if(status!=NULL) verbose=status->verbose;
58 if(verbose>0) printf("%s()\n", __func__);
59 if(x==NULL || y==NULL || k==NULL || a==NULL || snr<1 || bnr<1) {
60 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
61 return TPCERROR_NO_DATA;
62 }
63 if(snr<3 || bnr<4) {
64 if(verbose>1) fprintf(stderr, "invalid sample or BF number\n");
65 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
66 return TPCERROR_TOO_FEW;
67 }
68 if(!(kmin>0.0) || kmin>=kmax) { // range cannot be computed otherwise
69 if(verbose>1) fprintf(stderr, "invalid k range\n");
70 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
72 }
73 int ret;
74
75 if(verbose>1) printf("computing k values\n");
76 {
77 double a, b, c;
78 a=log10(kmin); b=log10(kmax); c=(b-a)/(double)(bnr-1);
79 if(verbose>3) printf(" a := %g\n b := %g\n c := %g\n", a, b, c);
80 for(int bi=0; bi<bnr; bi++) k[bi]=pow(10.0, (double)bi*c+a);
81 }
82
83 /* Allocate memory required by NNLS */
84 int nnls_n, nnls_m, n, m, nnls_index[bnr];
85 double *nnls_a[bnr], *nnls_b, *nnls_zz, nnls_x[bnr], *nnls_mat,
86 nnls_wp[bnr], *dptr, nnls_rnorm;
87 if(verbose>1) printf("allocating memory for NNLS\n");
88 nnls_n=bnr; nnls_m=snr;
89 nnls_mat=(double*)malloc(((nnls_n+2)*nnls_m)*sizeof(double));
90 if(nnls_mat==NULL) {
91 if(verbose>1) fprintf(stderr, "Error: cannot allocate memory for NNLS.\n");
92 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
94 }
95 for(n=0, dptr=nnls_mat; n<nnls_n; n++) {nnls_a[n]=dptr; dptr+=nnls_m;}
96 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
97
98 if(verbose>1) printf("filling NNLS data matrix\n");
99 /* Fill NNLS B array with measured y values */
100 for(m=0; m<nnls_m; m++) nnls_b[m]=y[m];
101
102 /* Fill NNLS A matrix with basis functions, calculated in place */
103 for(n=0; n<nnls_n; n++)
104 for(m=0; m<nnls_m; m++)
105 nnls_a[n][m]=exp(-k[n]*x[m]);
106
107 /* Apply weights, if given */
108 if(w!=NULL) nnlsWght(nnls_n, nnls_m, nnls_a, nnls_b, w);
109
110 /* NNLS */
111 if(verbose>1) printf("applying NNLS\n");
112 ret=nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm, nnls_wp, nnls_zz, nnls_index);
113 if(ret>1) {
114 if(verbose>1) fprintf(stderr, "NNLS solution not possible.\n");
115 free(nnls_mat);
116 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_SOLUTION);
118 }
119 /* Copy a[] values */
120 if(a!=NULL) for(n=0; n<nnls_n; n++) a[n]=nnls_x[n];
121
122 /* Compute fitted y[] */
123 if(yfit!=NULL) {
124 if(verbose>1) printf("computing yfit[]\n");
125 for(m=0; m<nnls_m; m++) {
126 yfit[m]=0.0;
127 for(n=0; n<nnls_n; n++)
128 if(nnls_x[n]>0.0)
129 yfit[m]+=nnls_x[n]*exp(-k[n]*x[m]);
130 }
131 }
132 free(nnls_mat);
133
134 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
135 return TPCERROR_OK;
136}
137/*****************************************************************************/
138
139/*****************************************************************************/
149 double *k,
151 double *a,
153 const int n,
155 double *kmin,
157 double *kmax,
159 TPCSTATUS *status
160) {
161 int verbose=0; if(status!=NULL) verbose=status->verbose;
162 if(verbose>0) printf("%s(k[], a[], %d, *kmin, *kmax)\n", __func__, n);
163 if(k==NULL || a==NULL || n<1) {
164 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
165 return TPCERROR_NO_DATA;
166 }
167 double max=nan(""), min=nan("");
168 for(int i=0; i<n; i++) if(a[i]>0.0 && isfinite(k[i])) {
169 if(isnan(max) || k[i]>max) max=k[i];
170 if(isnan(min) || k[i]<min) min=k[i];
171 }
172 if(verbose>2) {
173 printf(" kmin := %g\n", min);
174 printf(" kmax := %g\n", max);
175 }
176 if(kmin!=NULL) *kmin=min;
177 if(kmax!=NULL) *kmax=max;
178 if(isnan(min) || isnan(max)) {
179 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
180 return TPCERROR_NO_VALUE;
181 }
182 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
183 return TPCERROR_OK;
184}
185/*****************************************************************************/
186
187/*****************************************************************************/
197 double *k,
199 double *a,
201 const int n
202) {
203 if(k==NULL || a==NULL || n<1) return(0);
204 int bfn=0, i=0, ii=0;
205 do {
206 i=doubleCSpanPositives(a+ii, n-ii);
207 ii+=i; if(n-ii<1) break;
208 i=doubleSpanPositives(a+ii, n-ii);
209 ii+=i; if(i>0) bfn++;
210 } while(ii<n);
211 return(bfn);
212}
213/*****************************************************************************/
214
215/*****************************************************************************/
231 double *k,
233 double *a,
235 const int n,
237 double *ke,
239 double *ae,
241 const int ne
242) {
243 if(k==NULL || a==NULL || n<1 || ke==NULL || ae==NULL || ne<1) return(0);
244
245 /* First, extract all zero-separated basis function clusters */
246 double *buf=NULL, *ok, *oa;
247 int bfn=spectralBFNr(k, a, n); if(bfn==0) return(0);
248 if(bfn>ne) {
249 /* we need to allocate memory locally */
250 buf=(double*)malloc(2*bfn*sizeof(double)); if(buf==NULL) return(0);
251 ok=buf; oa=buf+bfn;
252 } else {
253 /* we just set pointers to user-provided arrays */
254 ok=ke; oa=ae;
255 }
256 {
257 int nn=0, i=0, ii=0;
258 do {
259 i=doubleCSpanPositives(a+ii, n-ii);
260 ii+=i; if(n-ii<1) break;
261 i=doubleSpanPositives(a+ii, n-ii);
262 if(i==1) { // cluster contains just one positive a
263 oa[nn]=a[ii]; ok[nn]=k[ii];
264 nn++;
265 } else if(i>1) { // cluster contains more than one positive a
266 /* get sum of a values in the cluster */
267 oa[nn]=doubleSum(a+ii, i);
268 /* get weighted mean of k values in the cluster */
269 ok[nn]=doubleWMean(k+ii, a+ii, i);
270 nn++;
271 }
272 ii+=i;
273 } while(ii<n && nn<bfn);
274 if(0) {
275 printf("\n\tCluster a and k values\n");
276 for(int i=0; i<bfn; i++) printf("\t%g\t%g\n", oa[i], ok[i]);
277 printf("\n"); fflush(stdout);
278 }
279 }
280 /* If the number needs not to be reduced, then we are ready */
281 if(ne>=bfn) {
282 for(int i=bfn; i<ne; i++) ke[i]=ae[i]=0.0;
283 if(buf!=NULL) free(buf);
284 return(bfn);
285 }
286
287 while(ne<bfn) {
288 /* Search the smallest a parameter */
289 int ami=doubleAbsMinIndex(oa, bfn);
290 if(0) printf("smallest |a[%d]|=%g\n", ami, oa[ami]);
291 /* Combine it with previous or next cluster? */
292 int ci;
293 if(ami==0) ci=1;
294 else if(ami==bfn-1) ci=bfn-2;
295 else {if(fabs(oa[ami-1])<fabs(oa[ami+1])) ci=ami-1; else ci=ami+1;}
296 if(0) printf("combining clusters %d and %d\n", 1+ami, 1+ci);
297 /* Replace the cluster with combination of two clusters */
298 ok[ci]=(oa[ami]*ok[ami]+oa[ci]*ok[ci])/(oa[ami]+oa[ci]);
299 oa[ci]+=oa[ami];
300 /* Delete the cluster */
301 for(int i=ami+1; i<bfn; i++) oa[i-1]=oa[i];
302 for(int i=ami+1; i<bfn; i++) ok[i-1]=ok[i];
303 bfn--;
304 if(0) {
305 printf("\n\tAfter reduction, cluster a and k values\n");
306 for(int i=0; i<bfn; i++) printf("\t%g\t%g\n", oa[i], ok[i]);
307 printf("\n"); fflush(stdout);
308 }
309 }
310 for(int i=0; i<ne; i++) ae[i]=oa[i];
311 for(int i=0; i<ne; i++) ke[i]=ok[i];
312 if(buf!=NULL) free(buf);
313
314 return(bfn);
315}
316/*****************************************************************************/
317
318/*****************************************************************************/
int spectralBFNr(double *k, double *a, const int n)
Definition bf_dexp.c:194
int spectralDExp(const double *x, const double *y, double *w, const int snr, const double kmin, const double kmax, const int bnr, double *k, double *a, double *yfit, TPCSTATUS *status)
Definition bf_dexp.c:29
int spectralKRange(double *k, double *a, const int n, double *kmin, double *kmax, TPCSTATUS *status)
Definition bf_dexp.c:146
int spectralBFExtract(double *k, double *a, const int n, double *ke, double *ae, const int ne)
Definition bf_dexp.c:228
int doubleSpanPositives(double *a, const int n)
Definition doubleutil.c:302
unsigned int doubleAbsMinIndex(double *a, const unsigned int n)
Definition doubleutil.c:416
int doubleCSpanPositives(double *a, const int n)
Definition doubleutil.c:320
double doubleWMean(double *a, double *w, const unsigned int n)
Definition doubleutil.c:244
double doubleSum(double *a, const unsigned int n)
Definition doubleutil.c:206
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *wp, double *zzp, int *indexp)
Definition nnls.c:48
int nnlsWght(int N, int M, double **A, double *b, double *weight)
Definition nnls.c:264
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
int verbose
Verbose level, used by statusPrint() etc.
Header file for libtpcbfm.
Header file for library libtpcextensions.
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_NO_SOLUTION
No solution.
@ TPCERROR_NO_VALUE
Value not found.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_TOO_FEW
File contains too few samples.
Header file for libtpclinopt.