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/*****************************************************************************/
31 const double *x,
34 const double *y,
36 double *w,
38 const int snr,
40 const double kmin,
42 const double kmax,
45 const int bnr,
47 double *k,
50 double *a,
52 double *yfit,
54 TPCSTATUS *status
55) {
56 int verbose=0; if(status!=NULL) verbose=status->verbose;
57 if(verbose>0) printf("%s()\n", __func__);
58 if(x==NULL || y==NULL || k==NULL || a==NULL || snr<1 || bnr<1) {
59 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
60 return TPCERROR_NO_DATA;
61 }
62 if(snr<3 || bnr<4) {
63 if(verbose>1) fprintf(stderr, "invalid sample or BF number\n");
64 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
65 return TPCERROR_TOO_FEW;
66 }
67 if(!(kmin>0.0) || kmin>=kmax) { // range cannot be computed otherwise
68 if(verbose>1) fprintf(stderr, "invalid k range\n");
69 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
71 }
72 int ret;
73
74 if(verbose>1) printf("computing k values\n");
75 {
76 double a, b, c;
77 a=log10(kmin); b=log10(kmax); c=(b-a)/(double)(bnr-1);
78 if(verbose>3) printf(" a := %g\n b := %g\n c := %g\n", a, b, c);
79 for(int bi=0; bi<bnr; bi++) k[bi]=pow(10.0, (double)bi*c+a);
80 }
81
82 /* Allocate memory required by NNLS */
83 int nnls_n, nnls_m, n, m, nnls_index[bnr];
84 double *nnls_a[bnr], *nnls_b, *nnls_zz, nnls_x[bnr], *nnls_mat,
85 nnls_wp[bnr], *dptr, nnls_rnorm;
86 if(verbose>1) printf("allocating memory for NNLS\n");
87 nnls_n=bnr; nnls_m=snr;
88 nnls_mat=(double*)malloc(((nnls_n+2)*nnls_m)*sizeof(double));
89 if(nnls_mat==NULL) {
90 if(verbose>1) fprintf(stderr, "Error: cannot allocate memory for NNLS.\n");
91 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
93 }
94 for(n=0, dptr=nnls_mat; n<nnls_n; n++) {nnls_a[n]=dptr; dptr+=nnls_m;}
95 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
96
97 if(verbose>1) printf("filling NNLS data matrix\n");
98 /* Fill NNLS B array with measured y values */
99 for(m=0; m<nnls_m; m++) nnls_b[m]=y[m];
100
101 /* Fill NNLS A matrix with basis functions, calculated in place */
102 for(n=0; n<nnls_n; n++)
103 for(m=0; m<nnls_m; m++)
104 nnls_a[n][m]=exp(-k[n]*x[m]);
105
106 /* Apply weights, if given */
107 if(w!=NULL) nnlsWght(nnls_n, nnls_m, nnls_a, nnls_b, w);
108
109 /* NNLS */
110 if(verbose>1) printf("applying NNLS\n");
111 ret=nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm, nnls_wp, nnls_zz, nnls_index);
112 if(ret>1) {
113 if(verbose>1) fprintf(stderr, "NNLS solution not possible.\n");
114 free(nnls_mat);
115 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_SOLUTION);
117 }
118 /* Copy a[] values */
119 if(a!=NULL) for(n=0; n<nnls_n; n++) a[n]=nnls_x[n];
120
121 /* Compute fitted y[] */
122 if(yfit!=NULL) {
123 if(verbose>1) printf("computing yfit[]\n");
124 for(m=0; m<nnls_m; m++) {
125 yfit[m]=0.0;
126 for(n=0; n<nnls_n; n++)
127 if(nnls_x[n]>0.0)
128 yfit[m]+=nnls_x[n]*exp(-k[n]*x[m]);
129 }
130 }
131 free(nnls_mat);
132
133 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
134 return TPCERROR_OK;
135}
136/*****************************************************************************/
137
138/*****************************************************************************/
148 double *k,
150 double *a,
152 const int n,
154 double *kmin,
156 double *kmax,
158 TPCSTATUS *status
159) {
160 int verbose=0; if(status!=NULL) verbose=status->verbose;
161 if(verbose>0) printf("%s(k[], a[], %d, *kmin, *kmax)\n", __func__, n);
162 if(k==NULL || a==NULL || n<1) {
163 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
164 return TPCERROR_NO_DATA;
165 }
166 double max=nan(""), min=nan("");
167 for(int i=0; i<n; i++) if(a[i]>0.0 && isfinite(k[i])) {
168 if(isnan(max) || k[i]>max) max=k[i];
169 if(isnan(min) || k[i]<min) min=k[i];
170 }
171 if(verbose>2) {
172 printf(" kmin := %g\n", min);
173 printf(" kmax := %g\n", max);
174 }
175 if(kmin!=NULL) *kmin=min;
176 if(kmax!=NULL) *kmax=max;
177 if(isnan(min) || isnan(max)) {
178 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
179 return TPCERROR_NO_VALUE;
180 }
181 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
182 return TPCERROR_OK;
183}
184/*****************************************************************************/
185
186/*****************************************************************************/
196 double *k,
198 double *a,
200 const int n
201) {
202 if(k==NULL || a==NULL || n<1) return(0);
203 int bfn=0, i=0, ii=0;
204 do {
205 i=doubleCSpanPositives(a+ii, n-ii);
206 ii+=i; if(n-ii<1) break;
207 i=doubleSpanPositives(a+ii, n-ii);
208 ii+=i; if(i>0) bfn++;
209 } while(ii<n);
210 return(bfn);
211}
212/*****************************************************************************/
213
214/*****************************************************************************/
230 double *k,
232 double *a,
234 const int n,
236 double *ke,
238 double *ae,
240 const int ne
241) {
242 if(k==NULL || a==NULL || n<1 || ke==NULL || ae==NULL || ne<1) return(0);
243
244 /* First, extract all zero-separated basis function clusters */
245 double *buf=NULL, *ok, *oa;
246 int bfn=spectralBFNr(k, a, n); if(bfn==0) return(0);
247 if(bfn>ne) {
248 /* we need to allocate memory locally */
249 buf=(double*)malloc(2*bfn*sizeof(double)); if(buf==NULL) return(0);
250 ok=buf; oa=buf+bfn;
251 } else {
252 /* we just set pointers to user-provided arrays */
253 ok=ke; oa=ae;
254 }
255 {
256 int nn=0, i=0, ii=0;
257 do {
258 i=doubleCSpanPositives(a+ii, n-ii);
259 ii+=i; if(n-ii<1) break;
260 i=doubleSpanPositives(a+ii, n-ii);
261 if(i==1) { // cluster contains just one positive a
262 oa[nn]=a[ii]; ok[nn]=k[ii];
263 nn++;
264 } else if(i>1) { // cluster contains more than one positive a
265 /* get sum of a values in the cluster */
266 oa[nn]=doubleSum(a+ii, i);
267 /* get weighted mean of k values in the cluster */
268 ok[nn]=doubleWMean(k+ii, a+ii, i);
269 nn++;
270 }
271 ii+=i;
272 } while(ii<n && nn<bfn);
273 if(0) {
274 printf("\n\tCluster a and k values\n");
275 for(int i=0; i<bfn; i++) printf("\t%g\t%g\n", oa[i], ok[i]);
276 printf("\n"); fflush(stdout);
277 }
278 }
279 /* If the number needs not to be reduced, then we are ready */
280 if(ne>=bfn) {
281 for(int i=bfn; i<ne; i++) ke[i]=ae[i]=0.0;
282 if(buf!=NULL) free(buf);
283 return(bfn);
284 }
285
286 while(ne<bfn) {
287 /* Search the smallest a parameter */
288 int ami=doubleAbsMinIndex(oa, bfn);
289 if(0) printf("smallest |a[%d]|=%g\n", ami, oa[ami]);
290 /* Combine it with previous or next cluster? */
291 int ci;
292 if(ami==0) ci=1;
293 else if(ami==bfn-1) ci=bfn-2;
294 else {if(fabs(oa[ami-1])<fabs(oa[ami+1])) ci=ami-1; else ci=ami+1;}
295 if(0) printf("combining clusters %d and %d\n", 1+ami, 1+ci);
296 /* Replace the cluster with combination of two clusters */
297 ok[ci]=(oa[ami]*ok[ami]+oa[ci]*ok[ci])/(oa[ami]+oa[ci]);
298 oa[ci]+=oa[ami];
299 /* Delete the cluster */
300 for(int i=ami+1; i<bfn; i++) oa[i-1]=oa[i];
301 for(int i=ami+1; i<bfn; i++) ok[i-1]=ok[i];
302 bfn--;
303 if(0) {
304 printf("\n\tAfter reduction, cluster a and k values\n");
305 for(int i=0; i<bfn; i++) printf("\t%g\t%g\n", oa[i], ok[i]);
306 printf("\n"); fflush(stdout);
307 }
308 }
309 for(int i=0; i<ne; i++) ae[i]=oa[i];
310 for(int i=0; i<ne; i++) ke[i]=ok[i];
311 if(buf!=NULL) free(buf);
312
313 return(bfn);
314}
315/*****************************************************************************/
316
317/*****************************************************************************/
int spectralBFNr(double *k, double *a, const int n)
Definition bf_dexp.c:193
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:28
int spectralKRange(double *k, double *a, const int n, double *kmin, double *kmax, TPCSTATUS *status)
Definition bf_dexp.c:145
int spectralBFExtract(double *k, double *a, const int n, double *ke, double *ae, const int ne)
Definition bf_dexp.c:227
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:43
int nnlsWght(int N, int M, double **A, double *b, double *weight)
Definition nnls.c:259
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.