TPCCLIB
Loading...
Searching...
No Matches
bf_dms.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#include "tpcfunc.h"
16#include "tpcbfm.h"
17/*****************************************************************************/
18
19/*****************************************************************************/
31 const double *x,
34 const double *x2,
37 const double *y,
39 double *w,
41 const int sNr,
43 const double kMin,
45 const double kMax,
47 const int fNr,
49 const double dtMin,
51 const double dtMax,
53 const double dtStep,
56 double *k,
59 double *a,
61 double *dtEst,
63 double *yfit,
65 TPCSTATUS *status
66) {
67 int verbose=0; if(status!=NULL) verbose=status->verbose;
68 if(verbose>0) printf("%s()\n", __func__);
69 else if(verbose>1) {
70 printf("%s(x, ", __func__);
71 if(x2==NULL) printf("null, y, "); else printf("x2, y, ");
72 if(w==NULL) printf("null"); else printf("w");
73 printf(" , %d, %.1e, %.1e, %d, %g, %g, %g, *k, *a, *dtEst, *yfit\n",
74 sNr, kMin, kMax, fNr, dtMin, dtMax, dtStep);
75 }
76 if(x==NULL || y==NULL) {
77 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
78 return(TPCERROR_NO_DATA);
79 }
80 if(sNr<4) {
81 if(verbose>1) fprintf(stderr, "invalid number of samples\n");
82 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
83 return(TPCERROR_TOO_FEW);
84 }
85 if(fNr<4) {
86 if(verbose>1) fprintf(stderr, "invalid number of functions\n");
87 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
88 return(TPCERROR_TOO_FEW);
89 }
90 if(!(kMin>0.0) || !(kMax>kMin)) {
91 if(verbose>1) fprintf(stderr, "invalid k range\n");
92 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
94 }
95 double dtRange=dtMax-dtMin;
96 if(!(dtRange>=0.0) || (dtRange>0.0 && !(dtStep<0.2*dtRange))) {
97 if(verbose>1) fprintf(stderr, "invalid delay time settings\n");
98 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
100 }
101
102 /* Allocate memory or set pointers for local a[] and k[] */
103 double *lk, *la, *localp;
104 localp=(double*)malloc(sizeof(double)*fNr*2);
105 if(localp==NULL) {
106 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
108 }
109 lk=localp; la=localp+fNr;
110
111 if(verbose>2) printf("computing k values\n");
112#if(1)
113 {
114 double r1, r2, s;
115 r1=log(kMin); r2=log(kMax); s=(r2-r1)/(double)(fNr-1);
116 if(verbose>3) printf(" r1 := %g\n r2 := %g\n s := %g\n", r1, r2, s);
117 for(int bi=0; bi<fNr; bi++) lk[bi]=exp((double)bi*s+r1);
118 }
119#else
120 {
121 double r1, r2, s;
122 r1=log10(kMin); r2=log10(kMax); s=(r2-r1)/(double)(fNr-1);
123 if(verbose>3) printf(" r1 := %g\n r2 := %g\n s := %g\n", r1, r2, s);
124 for(int bi=0; bi<fNr; bi++) lk[bi]=pow(10.0, (double)bi*s+r1);
125 }
126#endif
127
128 if(verbose>2) printf("computing the range of delay times to test\n");
129
130
131 /* Allocate memory required by NNLS */
132 if(verbose>2) printf("allocating memory for LLSQ\n");
133 NNLSQDATA lsq;
134 nnlsqDataInit(&lsq);
135 int ret=0;
136 if((ret=nnlsqDataAllocate(&lsq, fNr, sNr))!=TPCERROR_OK) {
137 free(localp);
138 statusSet(status, __func__, __FILE__, __LINE__, ret);
139 return(ret);
140 }
141
142 /* Set initial delay time to the middle of the given range */
143 double initDeltaT=dtMin;
144 if(dtMax>dtMin) initDeltaT=0.5*(dtMin+dtMax);
145 if(verbose>3) printf("initDeltaT := %g\n", initDeltaT);
146
147 /* LLSQ fit with initial delay time */
148 if(verbose>2) printf("LLSQ fitting\n");
149 double bestDeltaT=initDeltaT;
150 double bestR2=nan("");
151 double deltaT=initDeltaT;
152 if(verbose>2) printf(" deltaT=%g\n", deltaT);
153 if(verbose>6) printf("filling data matrix\n");
154 /* Fill NNLS B array with measured y values */
155 for(int m=0; m<lsq.m; m++) lsq.b[m]=y[m];
156 /* Fill NNLS A matrix with basis functions, calculated in place */
157 double p[3]={deltaT, 1.0, 0.0};
158 for(int n=0, ret=0; n<lsq.n && !ret; n++) {
159 p[2]=lk[n];
160 if(x2!=NULL) // frame start and end times available
161 ret=mfEvalFrameY("dmsurge", 3, p, lsq.m, x, x2, lsq.a[n], 0);
162 else
163 ret=mfEvalY("dmsurge", 3, p, lsq.m, x, lsq.a[n], 0);
164 }
165 if(ret) {
166 nnlsqDataFree(&lsq); free(localp);
167 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
169 }
170 /* Apply weights, if given */
171 if(w!=NULL) nnlsqDataWght(&lsq, w);
172 /* NNLS */
173 if(verbose>6) printf("applying NNLS\n");
174 lsq.iternr=3*lsq.n;
175 ret=nnlsq(&lsq, verbose-1);
176 if(ret>1) {
177 nnlsqDataFree(&lsq); free(localp);
178 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_SOLUTION);
179 return(TPCERROR_NO_SOLUTION);
180 }
181 if(verbose>2) printf(" -> r2=%g iterNr=%d\n", lsq.rnorm, lsq.iternr);
182 bestR2=lsq.rnorm;
183 /* Copy a[] values */
184 for(int n=0; n<lsq.n; n++) la[n]=lsq.x[n];
185
186 /* Try moving function to the left with delay steps */
187 deltaT=initDeltaT-dtStep;
188 while(dtStep>0.0 && deltaT>=dtMin) {
189 if(verbose>2) printf(" deltaT=%g\n", deltaT);
190 for(int m=0; m<lsq.m; m++) lsq.b[m]=y[m];
191 p[0]=deltaT;
192 for(int n=0, ret=0; n<lsq.n && !ret; n++) {
193 p[2]=lk[n];
194 if(x2!=NULL) // frame start and end times available
195 ret=mfEvalFrameY("dmsurge", 3, p, lsq.m, x, x2, lsq.a[n], 0);
196 else
197 ret=mfEvalY("dmsurge", 3, p, lsq.m, x, lsq.a[n], 0);
198 }
199 if(ret) {
200 nnlsqDataFree(&lsq); free(localp);
201 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
203 }
204 if(w!=NULL) nnlsqDataWght(&lsq, w);
205 lsq.iternr=3*lsq.n;
206 int ret=nnlsq(&lsq, verbose-1);
207 if(ret>1) break;
208 if(verbose>2) printf(" -> r2=%g iterNr=%d\n", lsq.rnorm, lsq.iternr);
209 if(lsq.rnorm<bestR2) {
210 bestR2=lsq.rnorm;
211 bestDeltaT=deltaT;
212 for(int n=0; n<lsq.n; n++) la[n]=lsq.x[n];
213 } //else if(nnls_r2>bestR2) break;
214 deltaT-=dtStep;
215 }
216 /* Try moving function to the right with delay steps */
217 deltaT=initDeltaT+dtStep;
218 while(dtStep>0.0 && deltaT<=dtMax) {
219 if(verbose>2) printf(" deltaT=%g\n", deltaT);
220 for(int m=0; m<lsq.m; m++) lsq.b[m]=y[m];
221 p[0]=deltaT;
222 //struct timespec ts[3];
223 //timespec_get(&ts[0], TIME_UTC);
224 for(int n=0, ret=0; n<lsq.n && !ret; n++) {
225 p[2]=lk[n];
226 if(x2!=NULL) // frame start and end times available
227 ret=mfEvalFrameY("dmsurge", 3, p, lsq.m, x, x2, lsq.a[n], 0);
228 else
229 ret=mfEvalY("dmsurge", 3, p, lsq.m, x, lsq.a[n], 0);
230 }
231 if(ret) {
232 nnlsqDataFree(&lsq); free(localp);
233 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
235 }
236 //timespec_get(&ts[1], TIME_UTC);
237 if(w!=NULL) nnlsqDataWght(&lsq, w);
238 lsq.iternr=3*lsq.n;
239 int ret=nnlsq(&lsq, verbose-1);
240 //timespec_get(&ts[2], TIME_UTC);
241 if(ret>1) break;
242 if(verbose>2) printf(" -> r2=%g iterNr=%d\n", lsq.rnorm, lsq.iternr);
243 if(lsq.rnorm<bestR2) {
244 bestR2=lsq.rnorm;
245 bestDeltaT=deltaT;
246 for(int n=0; n<lsq.n; n++) la[n]=lsq.x[n];
247 } //else if(nnls_r2>bestR2) break;
248 //printf(" time_to-fill=%g time_to_nnls=%g\n", timespecDifference(&ts[1], &ts[0]), timespecDifference(&ts[2], &ts[1]));
249 deltaT+=dtStep;
250 }
251
252 /* Compute fitted y[] */
253 if(yfit!=NULL) {
254 if(verbose>1) printf("computing yfit[]\n");
255 for(int m=0; m<lsq.m; m++) {
256 yfit[m]=0.0;
257 for(int n=0; n<lsq.n; n++)
258 if(la[n]>0.0)
259 yfit[m]+=la[n]*(x[m]+bestDeltaT)*exp(-lk[n]*(x[m]+bestDeltaT));
260 }
261 }
262
263 nnlsqDataFree(&lsq);
264
265 /* Copy a[] and b[] if requested */
266 if(a!=NULL) for(int bi=0; bi<fNr; bi++) a[bi]=la[bi];
267 if(k!=NULL) for(int bi=0; bi<fNr; bi++) k[bi]=lk[bi];
268 free(localp);
269
270 if(dtEst!=NULL) *dtEst=bestDeltaT;
271
272 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
273 return TPCERROR_OK;
274}
275/*****************************************************************************/
276
277/*****************************************************************************/
int spectralDMSurge(const double *x, const double *x2, const double *y, double *w, const int sNr, const double kMin, const double kMax, const int fNr, const double dtMin, const double dtMax, const double dtStep, double *k, double *a, double *dtEst, double *yfit, TPCSTATUS *status)
Definition bf_dms.c:27
int mfEvalY(const char *fid, const int parNr, const double *p, const int sampleNr, const double *x, double *y, const int verbose)
Definition func.c:26
int mfEvalFrameY(const char *fid, const int parNr, const double *p, const int sampleNr, const double *x1, const double *x2, double *y, const int verbose)
Definition func.c:790
int nnlsqDataWght(NNLSQDATA *d, double *weight)
Definition nnlsq.c:513
void nnlsqDataFree(NNLSQDATA *d)
Definition nnlsq.c:379
int nnlsqDataAllocate(NNLSQDATA *d, const int n, const int m)
Definition nnlsq.c:412
void nnlsqDataInit(NNLSQDATA *d)
Definition nnlsq.c:358
int nnlsq(NNLSQDATA *d, int verbose)
Definition nnlsq.c:55
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
double rnorm
Definition tpclinopt.h:136
double * x
Definition tpclinopt.h:123
double * b
Definition tpclinopt.h:121
double ** a
Definition tpclinopt.h:118
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_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 libtpcfunc.
Header file for libtpclinopt.