TPCCLIB
Loading...
Searching...
No Matches
dft.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6char dfterrmsg[64];
7/*****************************************************************************/
8#include "libtpccurveio.h"
9#include <unistd.h>
10/*****************************************************************************/
11/* local function definitions */
13int dftQSortName(const void *voi1, const void *voi2);
14int dftQSortPlane(const void *voi1, const void *voi2);
16/*****************************************************************************/
17
18/*****************************************************************************/
22 DFT *data
23) {
24 if(data==NULL) return;
25 if(data->_voidataNr>0) free((char*)(data->voi));
26 if(data->_dataSize>0) free((char*)(data->_data));
27 data->_dataSize=data->_voidataNr=0;
28 data->frameNr=data->voiNr=0;
29 data->studynr[0]=data->comments[0]=data->unit[0]=(char)0;
30 data->radiopharmaceutical[0]=data->isotope[0]=data->decayCorrected=(char)0;
31 data->scanStartTime[0]=data->injectionTime[0]=(char)0;
32 data->timeunit=data->timetype=0;
33}
34/*****************************************************************************/
35
36/*****************************************************************************/
40 DFT *data
41) {
42 if(data==NULL) return;
43 memset(data, 0, sizeof(DFT));
44 data->_voidataNr=data->_dataSize=0;
45 data->frameNr=data->voiNr=0;
46 data->studynr[0]=data->comments[0]=data->unit[0]=(char)0;
47 data->radiopharmaceutical[0]=data->isotope[0]=data->decayCorrected=(char)0;
48 data->scanStartTime[0]=data->injectionTime[0]=(char)0;
49 data->timeunit=data->timetype=data->isweight=0;
50}
51/*****************************************************************************/
52
53/*****************************************************************************/
59 DFT *data,
61 int frameNr,
63 int voiNr
64) {
65 int i, n;
66 double *d;
67
68
69 if(data==NULL) return 1;
70 /* Clear previous data */
71 dftEmpty(data);
72
73 /* Allocate memory for curves */
74 data->voi=(Voi*)calloc(voiNr, sizeof(Voi));
75 if(data->voi==NULL) return 1;
76 data->_voidataNr=voiNr;
77
78 /* Allocate memory for frames */
79 /* For 3 axes, weights, and for curves (3 for each VOI) */
80 /* And one extra 'frame' for overflow testing */
81 n=(frameNr+1)*(3+1+3*voiNr);
82 data->_data=(double*)calloc(n, sizeof(double));
83 if(data->_data==NULL) return 1;
84 data->_dataSize=n;
85
86 /* Set pointers for curve data */
87 d=data->_data; data->x = d;
88 d += frameNr + 1; data->x1 = d;
89 d += frameNr + 1; data->x2 = d;
90 d += frameNr + 1; data->w = d;
91 for(i=0; i<voiNr; i++) {
92 d += frameNr + 1; data->voi[i].y = d;
93 d += frameNr + 1; data->voi[i].y2 = d;
94 d += frameNr + 1; data->voi[i].y3 = d;
95 }
96
97 return 0;
98}
99/*****************************************************************************/
100
101/*****************************************************************************/
109 DFT *dft,
111 int voiNr
112) {
113 Voi *voi2;
114 double *data2, *dptr, *newx, *newx1, *newx2, *neww;
115 int ri, fi, dataSize2, voidataNr2;
116
117 /* Check the input */
118 if(dft==NULL || dft->voi==NULL || dft->frameNr<1 || dft->voiNr<1) return 1;
119 if(voiNr<0) return 1; else if(voiNr==0) return 0;
120
121 /* Allocate memory for new set of curve data (plus additional 'frame') */
122 voidataNr2=voiNr+dft->_voidataNr;
123 voi2=(Voi*)calloc(voidataNr2, sizeof(Voi));
124 if(voi2==NULL) return 3;
125 dataSize2=(dft->frameNr+1)*(3*voidataNr2+4);
126 data2=(double*)calloc(dataSize2, sizeof(double)); if(data2==NULL) return 3;
127 /* Set pointers for new curve data */
128 dptr=data2; newx=dptr; newx[dft->frameNr]=0.0;
129 dptr+=dft->frameNr+1; newx1=dptr; newx1[dft->frameNr]=0.0;
130 dptr+=dft->frameNr+1; newx2=dptr; newx2[dft->frameNr]=0.0;
131 dptr+=dft->frameNr+1; neww=dptr; neww[dft->frameNr]=0.0;
132 for(ri=0; ri<voidataNr2; ri++) {
133 dptr+=dft->frameNr+1; voi2[ri].y = dptr;
134 dptr+=dft->frameNr+1; voi2[ri].y2 = dptr;
135 dptr+=dft->frameNr+1; voi2[ri].y3 = dptr;
136 }
137
138 /* Copy the original contents */
139 for(ri=0; ri<dft->voiNr; ri++) {
140 /* Copy Voi header */
141 strcpy(voi2[ri].name, dft->voi[ri].name);
142 strcpy(voi2[ri].voiname, dft->voi[ri].voiname);
143 strcpy(voi2[ri].hemisphere, dft->voi[ri].hemisphere);
144 strcpy(voi2[ri].place, dft->voi[ri].place);
145 voi2[ri].size=dft->voi[ri].size;
146 voi2[ri].sw=dft->voi[ri].sw;
147 voi2[ri].sw2=dft->voi[ri].sw2;
148 voi2[ri].sw3=dft->voi[ri].sw3;
149 /* Copy Voi data */
150 for(fi=0; fi<dft->frameNr; fi++) {
151 voi2[ri].y[fi]=dft->voi[ri].y[fi];
152 voi2[ri].y2[fi]=dft->voi[ri].y2[fi];
153 voi2[ri].y3[fi]=dft->voi[ri].y3[fi];
154 }
155 }
156 for(fi=0; fi<dft->frameNr; fi++) {
157 newx[fi]=dft->x[fi]; newx1[fi]=dft->x1[fi]; newx2[fi]=dft->x2[fi];
158 neww[fi]=dft->w[fi];
159 }
160
161 /* Replace original pointers */
162 free(dft->_data); dft->_data=data2;
163 free(dft->voi); dft->voi=voi2;
164 dft->x=newx; dft->x1=newx1; dft->x2=newx2; dft->w=neww;
165 dft->_voidataNr=voidataNr2; dft->_dataSize=dataSize2;
166
167 /* Initiate values */
168 for(ri=dft->voiNr; ri<dft->_voidataNr; ri++) {
169 strcpy(dft->voi[ri].name, "");
170 strcpy(dft->voi[ri].voiname, "");
171 strcpy(dft->voi[ri].hemisphere, "");
172 strcpy(dft->voi[ri].place, "");
173 dft->voi[ri].size=1.0;
174 dft->voi[ri].sw=dft->voi[ri].sw2=dft->voi[ri].sw3=0;
175 for(fi=0; fi<dft->frameNr+1; fi++)
176 dft->voi[ri].y[fi]=dft->voi[ri].y2[fi]=dft->voi[ri].y3[fi]=0.0;
177 }
178
179 return 0;
180}
181/*****************************************************************************/
182
183/*****************************************************************************/
190 DFT *data1,
192 DFT *data2,
194 int voi
195) {
196 int i, n;
197
198 if(data1==NULL || data2==NULL) return 1;
199 /* Check that voi exists */
200 if(data2->voiNr<=voi || voi<0) {
201 strcpy(dfterrmsg, "there is no region to combine"); return 8;}
202
203 /* Check that frame number etc is the same */
204 if(data1->frameNr!=data2->frameNr ||
205 (data1->_type!=DFT_FORMAT_PLAIN && data2->_type!=DFT_FORMAT_PLAIN &&
206 (data1->timeunit!=data2->timeunit || strcasecmp(data1->unit, data2->unit))
207 )) {
208 strcpy(dfterrmsg, "data does not match"); return 8;}
209
210 /* Allocate more memory if necessary */
211 if(data1->_voidataNr==data1->voiNr)
212 if(dftAddmem(data1, 1)) {
213 strcpy(dfterrmsg, "cannot allocate memory"); return 8;}
214
215 /* Copy data */
216 n=data1->voiNr;
217 (void)dftCopyvoihdr(data2, voi, data1, n);
218 for(i=0; i<data1->frameNr; i++) {
219 data1->voi[n].y[i]=data2->voi[voi].y[i];
220 data1->voi[n].y2[i]=data2->voi[voi].y2[i];
221 data1->voi[n].y3[i]=data2->voi[voi].y3[i];
222 }
223 data1->voiNr+=1;
224
225 /* If data2 contains weights and data1 does not, then copy those */
226 if(data2->isweight && !data1->isweight)
227 for(i=0; i<data1->frameNr; i++) data1->w[i]=data2->w[i];
228
229 return 0;
230}
231/*****************************************************************************/
232
233/*****************************************************************************/
241 DFT *data,
243 char *name
244) {
245 unsigned int i, j, n;
246 char *p, n1[128], n2[128], n3[128], tmp[128], sname[1024];
247
248 if(data==NULL) return -1;
249 /* Select all, if no string was specified */
250 if(name==NULL || strlen(name)==0) {
251 for(i=0; i<(unsigned int)data->voiNr; i++) data->voi[i].sw=1;
252 return data->voiNr;
253 }
254 /* Make a copy of 'name' and use it */
255 strcpy(sname, name);
256 /* Check if string contains several substrings (hemisphere and place) */
257 n1[0]=n2[0]=n3[0]=(char)0;
258 p=strtok(sname, " ,;\n\t|"); if(p!=NULL) strcpy(n1, p); else return -1;
259 p=strtok(NULL, " ,;\n\t|"); if(p!=NULL) {
260 strcpy(n2, p); p=strtok(NULL, " ,;\n\t|"); if(p!=NULL) strcpy(n3, p);}
261 /* Convert strings to lowercase */
262 for(i=0; i<strlen(n1); i++) n1[i]=tolower(n1[i]);
263 for(i=0; i<strlen(n2); i++) n2[i]=tolower(n2[i]);
264 for(i=0; i<strlen(n3); i++) n3[i]=tolower(n3[i]);
265 /* Search through the data */
266 for(i=0, n=0; i<(unsigned int)data->voiNr; i++) {
267 data->voi[i].sw=0;
268 snprintf(tmp, 128, "%s%s%s", data->voi[i].voiname, data->voi[i].hemisphere,
269 data->voi[i].place);
270 for(j=0; j<strlen(tmp); j++) tmp[j]=tolower(tmp[j]);
271 if(strstr(tmp, n1)==NULL) continue;
272 if(n2[0] && strstr(tmp, n2)==NULL) continue;
273 if(n3[0] && strstr(tmp, n3)==NULL) continue;
274 data->voi[i].sw=1; n++;
275 }
276 return n;
277}
278/*****************************************************************************/
279
280/*****************************************************************************/
287 DFT *dft,
289 char *region_name,
291 int reset
292) {
293 int ri, match_nr=0;
294
295 /* Check the input */
296 if(dft==NULL || dft->voiNr<1 || strlen(region_name)<1) return(-1);
297 /* Reset all selections if required */
298 if(reset!=0) for(ri=0; ri<dft->voiNr; ri++) dft->voi[ri].sw=0;
299 /* Check each VOI */
300 for(ri=0; ri<dft->voiNr; ri++) {
301 if(rnameMatch(dft->voi[ri].name, ri+1, region_name)!=0) {
302 dft->voi[ri].sw=1; match_nr++;
303 }
304 }
305 return(match_nr);
306}
307/*****************************************************************************/
308
309/*****************************************************************************/
316 DFT *dft
317) {
318 int ri, len, min_len, i;
319
320 if(dft==NULL || dft->voiNr<1) return -1;
321 for(ri=0, i=-1, min_len=9999; ri<dft->voiNr; ri++) if(dft->voi[ri].sw) {
322 len=strlen(dft->voi[ri].voiname);
323 if(strcmp(dft->voi[ri].hemisphere, ".")!=0 &&
324 strcasecmp(dft->voi[ri].hemisphere, "AVG")!=0 &&
325 strcasecmp(dft->voi[ri].hemisphere, "MEAN")!=0)
326 len+=1+strlen(dft->voi[ri].hemisphere);
327 if(strcmp(dft->voi[ri].place, ".")!=0 &&
328 strcasecmp(dft->voi[ri].place, "ALL")!=0 &&
329 strcasecmp(dft->voi[ri].place, "AVG")!=0 &&
330 strcasecmp(dft->voi[ri].place, "MEAN")!=0)
331 len+=1+strlen(dft->voi[ri].place);
332 if(len<min_len) {min_len=len; i=ri;}
333 }
334 if(i<0) return -2; else return i;
335}
336/*****************************************************************************/
337
338/*****************************************************************************/
342 DFT *data
343) {
344 int i, j;
345 double f, fs;
346
347 if(data==NULL) return;
348 /* If data is told to contain frame start and end times, then check
349 that those really are there, or set to middle times, if necessary */
350 if(data->timetype==DFT_TIME_STARTEND) {
351 for(i=j=0; i<data->frameNr; i++) {
352 fs=data->x2[i]-data->x1[i]; if(fs>1.0E-10) {j=1; break;}
353 }
354 if(j==0) {
355 for(i=0; i<data->frameNr; i++) data->x[i]=0.5*(data->x1[i]+data->x2[i]);
357 }
358 }
359
360 /* Decide what to do, and get it done */
361 if(data->timetype==DFT_TIME_MIDDLE) {
362 /* frame start and end times from mid times */
363 /* Easy, if only one frame */
364 if(data->frameNr==1) {
365 if(data->x[0]<=0.0) {data->x1[0]=data->x[0]; data->x2[0]=0.0;}
366 else {data->x1[0]=0.0; data->x2[0]=2.0*data->x[0];}
367 return;
368 }
369 /* Fill start and end times with -999 */
370 for(i=0; i<data->frameNr; i++) data->x1[i]=data->x2[i]=-999.;
371 /* Search for sequences of nearly same frame lengths */
372 for(i=1; i<data->frameNr-1; i++) {
373 f=data->x[i]-data->x[i-1]; fs=data->x[i+1]-data->x[i];
374 if((f+fs)<=0.0 && fabs(fs-f)>=2.0) continue;
375 if((f+fs)>0.0 && (2.0*fabs(fs-f)/(f+fs))>0.1) continue;
376 //if(fabs(f-fs)>=2.0) continue;
377 f=(f+fs)/2.0;
378 data->x1[i-1]=data->x[i-1]-f/2.0; data->x2[i-1]=data->x[i-1]+f/2.0;
379 data->x1[i]=data->x[i]-f/2.0; data->x2[i]=data->x[i]+f/2.0;
380 data->x1[i+1]=data->x[i+1]-f/2.0; data->x2[i+1]=data->x[i+1]+f/2.0;
381 /* Check for negatives */
382 for(j=i-1; j<i+2; j++) {
383 if(data->x1[j]<0.0) data->x1[j]=0.0;
384 if(data->x2[j]<0.0) data->x2[j]=0.0;
385 }
386 }
387 /* If out-of-sequence frames were left out, fill those to the nearest one */
388 i=0; /* first frame */
389 if(data->x1[i]<0) {
390 if(data->x1[i+1]>0) data->x2[i]=data->x1[i+1];
391 else data->x2[i]=(data->x[i+1]+data->x[i])/2.0;
392 data->x1[i]=2.0*data->x[i]-data->x2[i];
393 }
394 i=data->frameNr-1; /* last frame */
395 if(data->x1[i]<0) {
396 if(data->x2[i-1]>0) data->x1[i]=data->x2[i-1];
397 else data->x1[i]=(data->x[i-1]+data->x[i])/2.0;
398 data->x2[i]=2.0*data->x[i]-data->x1[i];
399 }
400 /* other frames */
401 for(i=1; i<data->frameNr-1; i++) if(data->x1[i]<0.0) {
402 /* which frame is nearest? */
403 if(data->x[i]-data->x[i-1] <= data->x[i+1]-data->x[i]) { /* last one */
404 if(data->x2[i-1]>0) data->x1[i]=data->x2[i-1];
405 else data->x1[i]=(data->x[i-1]+data->x[i])/2.0;
406 data->x2[i]=2.*data->x[i]-data->x1[i];
407 } else { /* next one */
408 if(data->x1[i+1]>0) data->x2[i]=data->x1[i+1];
409 else data->x2[i]=(data->x[i+1]+data->x[i])/2.0;
410 data->x1[i]=2.0*data->x[i]-data->x2[i];
411 }
412 }
413 /* Check for negatives */
414 for(i=0; i<data->frameNr; i++) {
415 if(data->x1[i]<0.0) data->x1[i]=0.0;
416 if(data->x2[i]<0.0) data->x2[i]=data->x1[i];
417 }
418 /* Check for overlapping and very small gaps */
419 for(i=1; i<data->frameNr; i++) {
420 f=data->x1[i]-data->x2[i-1];
421 if(f<0.0) {
422 if(data->x[i]>data->x2[i-1]) data->x1[i]=data->x2[i-1];
423 else if(data->x[i-1]<data->x1[i]) data->x2[i-1]=data->x1[i];
424 else data->x1[i]=data->x2[i-1]=(data->x[i]+data->x[i-1])/2.0;
425 } else if(f>0.0 && f<1.0) {
426 data->x1[i]=data->x2[i-1]=(data->x1[i]+data->x2[i-1])/2.0;
427 }
428 }
429 } else if(data->timetype==DFT_TIME_STARTEND) {
430 /* mid times from frame start and end times */
431 for(i=0; i<data->frameNr; i++) data->x[i]=0.5*(data->x1[i]+data->x2[i]);
432 } else if(data->timetype==DFT_TIME_START) {
433 /* frame start times -> end and mid times */
434 for(i=0; i<data->frameNr-1; i++) data->x2[i]=data->x1[i+1];
435 data->x2[data->frameNr-1]=data->x1[data->frameNr-1]+
436 (data->x2[data->frameNr-2]-data->x1[data->frameNr-2]);
437 for(i=0; i<data->frameNr; i++) data->x[i]=0.5*(data->x1[i]+data->x2[i]);
438 } else if(data->timetype==DFT_TIME_END) {
439 /* frame end times -> start and mid times */
440 data->x1[0]=0.0;
441 for(i=1; i<data->frameNr; i++) data->x1[i]=data->x2[i-1];
442 for(i=0; i<data->frameNr; i++) data->x[i]=0.5*(data->x1[i]+data->x2[i]);
443 }
444
445 return;
446}
447/*****************************************************************************/
448
449/*****************************************************************************/
453 DFT *data
454) {
455 int i;
456
457 if(data==NULL || data->frameNr<1 || data->voiNr<1) return 0;
458 if(data->x[data->frameNr]!=0.0) return 1;
459 if(data->x1[data->frameNr]!=0.0) return 2;
460 if(data->x2[data->frameNr]!=0.0) return 3;
461 for(i=0; i<data->voiNr; i++) {
462 if(data->voi[i].y[data->frameNr]!=0.0) return 4;
463 if(data->voi[i].y2[data->frameNr]!=0.0) return 5;
464 if(data->voi[i].y3[data->frameNr]!=0.0) return 6;
465 }
466 return 0;
467}
468/*****************************************************************************/
469
470/*****************************************************************************/
474 DFT *data,
476 int from,
478 int to
479) {
480 int i;
481
482 /* Check that required data exists */
483 if(data==NULL || to>=data->_voidataNr || from>=data->_voidataNr) return 1;
484 if(from==to) return 0;
485
486 /* Copy VOI info */
487 strcpy(data->voi[to].name, data->voi[from].name);
488 strcpy(data->voi[to].voiname, data->voi[from].voiname);
489 strcpy(data->voi[to].hemisphere, data->voi[from].hemisphere);
490 strcpy(data->voi[to].place, data->voi[from].place);
491 data->voi[to].size=data->voi[from].size;
492 data->voi[to].sw=data->voi[from].sw;
493 data->voi[to].sw2=data->voi[from].sw2;
494 data->voi[to].sw3=data->voi[from].sw3;
495 /* Copy VOI curves */
496 for(i=0; i<data->frameNr; i++) {
497 data->voi[to].y[i]=data->voi[from].y[i];
498 data->voi[to].y2[i]=data->voi[from].y2[i];
499 data->voi[to].y3[i]=data->voi[from].y3[i];
500 }
501
502 return 0;
503}
504/*****************************************************************************/
505
506/*****************************************************************************/
510 DFT *dft,
512 int from,
514 int to
515) {
516 int ri;
517 size_t voisize;
518 Voi voi;
519
520 if(dft==NULL || from<0 || to<0) return(1);
521 if(from+1>dft->_voidataNr || to+1>dft->_voidataNr) return(2);
522 if(from==to) return(0);
523 voisize=sizeof(Voi);
524 memcpy(&voi, dft->voi+from, voisize);
525 if(from>to) for(ri=from; ri>to; ri--)
526 memcpy(dft->voi+ri, dft->voi+(ri-1), voisize);
527 else for(ri=from; ri<to; ri++)
528 memcpy(dft->voi+ri, dft->voi+(ri+1), voisize);
529 memcpy(dft->voi+ri, &voi, voisize);
530 return(0);
531}
532/*****************************************************************************/
533
534/*****************************************************************************/
540 DFT *dft,
542 int voi
543) {
544 int ret;
545
546 /* Check that region exists */
547 if(dft==NULL || voi>dft->voiNr-1 || voi<0) return(1);
548 /* If it is the last one, then just decrease the voiNr */
549 if(voi==dft->voiNr-1) {dft->voiNr--; return(0);}
550 /* Otherwise move it to the last position, and then decrease voiNr */
551 ret=dftMovevoi(dft, voi, dft->voiNr-1); if(ret) return(10+ret);
552 dft->voiNr--;
553 return(0);
554}
555/*****************************************************************************/
556
557/*****************************************************************************/
563 DFT *dft1,
565 DFT *dft2
566) {
567 if(dft1==NULL || dft2==NULL) return 1;
568 strcpy(dft2->studynr, dft1->studynr);
569 strcpy(dft2->unit, dft1->unit);
570 dft2->timeunit=dft1->timeunit; dft2->timetype=dft1->timetype;
571 strcpy(dft2->comments, dft1->comments);
572 strcpy(dft2->radiopharmaceutical, dft1->radiopharmaceutical);
573 strcpy(dft2->isotope, dft1->isotope);
574 strcpy(dft2->scanStartTime, dft1->scanStartTime);
575 strcpy(dft2->injectionTime, dft1->injectionTime);
576 dft2->decayCorrected=dft1->decayCorrected;
577 dft2->_type=dft1->_type;
578 return 0;
579}
580/*****************************************************************************/
581
582/*****************************************************************************/
589 DFT *dft1,
591 DFT *dft2,
593 int ow
594) {
595 if(dft1==NULL || dft2==NULL) return 1;
596 if(ow || (strlen(dft2->studynr)<1 && strcmp(dft2->studynr, ".")==0))
597 strcpy(dft2->studynr, dft1->studynr);
598 if(ow || dftUnitId(dft2->unit)==CUNIT_UNKNOWN)
599 strcpy(dft2->unit, dft1->unit);
600 if(ow || dft2->timeunit==TUNIT_UNKNOWN)
601 dft2->timeunit=dft1->timeunit;
602 dft2->timetype=dft1->timetype;
603 if(ow || strlen(dft2->radiopharmaceutical)<1)
604 strcpy(dft2->radiopharmaceutical, dft1->radiopharmaceutical);
605 if(ow || strlen(dft2->isotope)<1)
606 strcpy(dft2->isotope, dft1->isotope);
607 if(ow || strlen(dft2->scanStartTime)<1)
608 strcpy(dft2->scanStartTime, dft1->scanStartTime);
609 if(ow || strlen(dft2->injectionTime)<1)
610 strcpy(dft2->injectionTime, dft1->injectionTime);
611 if(ow || dft2->decayCorrected==DFT_DECAY_UNKNOWN)
612 dft2->decayCorrected=dft1->decayCorrected;
613 if(ow)
614 dft2->_type=dft1->_type;
615 return 0;
616}
617/*****************************************************************************/
618
619/*****************************************************************************/
625 DFT *dft1,
627 int from,
629 DFT *dft2,
631 int to
632) {
633 /* Check that required data exists */
634 if(dft1==NULL || dft2==NULL) return 1;
635 if(to>=dft2->_voidataNr || from>=dft1->_voidataNr) return 1;
636
637 /* Copy VOI info */
638 strcpy(dft2->voi[to].name, dft1->voi[from].name);
639 strcpy(dft2->voi[to].voiname, dft1->voi[from].voiname);
640 strcpy(dft2->voi[to].hemisphere, dft1->voi[from].hemisphere);
641 strcpy(dft2->voi[to].place, dft1->voi[from].place);
642 dft2->voi[to].size=dft1->voi[from].size;
643 dft2->voi[to].sw=dft1->voi[from].sw;
644 dft2->voi[to].sw2=dft1->voi[from].sw2;
645 dft2->voi[to].sw3=dft1->voi[from].sw3;
646
647 return 0;
648}
649/*****************************************************************************/
650
651/*****************************************************************************/
657 DFT *dft1,
660 DFT *dft2
661) {
662 int ri, fi, ret;
663
664 if(dft1==NULL || dft2==NULL) return 1;
665 /* Empty the new data */
666 dftEmpty(dft2);
667 /* Is that it? Is there any contents in dft1? */
668 if(dft1->voiNr==0 && dft1->frameNr==0) {
669 ret=dftCopymainhdr(dft1, dft2); return(ret);
670 }
671 /* Allocate memory for dft2 */
672 ret=dftSetmem(dft2, dft1->frameNr, dft1->voiNr); if(ret) return(ret);
673 dft2->voiNr=dft1->voiNr; dft2->frameNr=dft1->frameNr;
674 /* Copy the contents */
675 ret=dftCopymainhdr(dft1, dft2); if(ret) return(ret);
676 for(ri=0; ri<dft1->voiNr; ri++) {
677 ret=dftCopyvoihdr(dft1, ri, dft2, ri); if(ret) return(ret);
678 for(fi=0; fi<dft1->frameNr; fi++) {
679 dft2->voi[ri].y[fi]=dft1->voi[ri].y[fi];
680 dft2->voi[ri].y2[fi]=dft1->voi[ri].y2[fi];
681 dft2->voi[ri].y3[fi]=dft1->voi[ri].y3[fi];
682 }
683 }
684 for(fi=0; fi<dft1->frameNr; fi++) {
685 dft2->x[fi]=dft1->x[fi];
686 dft2->x1[fi]=dft1->x1[fi]; dft2->x2[fi]=dft1->x2[fi];
687 dft2->w[fi]=dft1->w[fi];
688 }
689 dft2->isweight=dft1->isweight;
690 return(0);
691}
692/*****************************************************************************/
693
694/*****************************************************************************/
705 DFT *dft,
707 int frameNr,
709 int voiNr,
711 DFT *dft_from
712) {
713 int ri, fi, ret;
714
715 /* Check the input */
716 if(dft==NULL || dft_from==NULL || frameNr<1 || voiNr<0) return 1;
717 /* Empty the new data */
718 dftEmpty(dft);
719 /* Allocate memory for dft */
720 ret=dftSetmem(dft, frameNr, voiNr); if(ret) return(ret);
721 dft->voiNr=voiNr; dft->frameNr=frameNr;
722 /* Copy the contents */
723 ret=dftCopymainhdr(dft_from, dft); if(ret) return(ret);
724 if(dft->voiNr==dft_from->voiNr) {
725 for(ri=0; ri<dft->voiNr; ri++) {
726 ret=dftCopyvoihdr(dft_from, ri, dft, ri); if(ret) return(ret);
727 if(dft->frameNr==dft_from->frameNr) {
728 for(fi=0; fi<dft->frameNr; fi++) {
729 dft->voi[ri].y[fi]=dft_from->voi[ri].y[fi];
730 dft->voi[ri].y2[fi]=dft_from->voi[ri].y2[fi];
731 dft->voi[ri].y3[fi]=dft_from->voi[ri].y3[fi];
732 }
733 }
734 }
735 }
736 if(dft->frameNr==dft_from->frameNr) {
737 for(fi=0; fi<dft->frameNr; fi++) {
738 dft->x[fi]=dft_from->x[fi];
739 dft->x1[fi]=dft_from->x1[fi]; dft->x2[fi]=dft_from->x2[fi];
740 dft->w[fi]=dft_from->w[fi];
741 }
742 dft->isweight=dft_from->isweight;
743 }
744 return(0);
745}
746/*****************************************************************************/
747
748/*****************************************************************************/
754 DFT *data
755) {
756 int i, j, n;
757 DFT temp;
758
759
760 /* Check whether nullframe exists */
761 if(data==NULL) return 1;
762 if(data->frameNr<1 || data->x[0]==0.0) return 0;
763
764 /* Allocate memory for temp data */
765 dftInit(&temp);
766 if(dftSetmem(&temp, data->frameNr, data->voiNr)) return 1;
767 temp.frameNr=data->frameNr; temp.voiNr=data->voiNr;
768
769 /* Copy data to temp */
770 strcpy(temp.studynr, data->studynr);
771 strcpy(temp.unit, data->unit);
772 temp.timeunit=data->timeunit; temp.timetype=data->timetype;
773 temp.isweight=data->isweight; temp._type=data->_type;
774 strcpy(temp.comments, data->comments);
775 for(j=0; j<data->frameNr; j++) {
776 temp.x[j]=data->x[j]; temp.x1[j]=data->x1[j]; temp.x2[j]=data->x2[j];
777 temp.w[j]=data->w[j];
778 for(i=0; i<data->voiNr; i++) {
779 temp.voi[i].y[j]=data->voi[i].y[j];
780 temp.voi[i].y2[j]=data->voi[i].y2[j];
781 temp.voi[i].y3[j]=data->voi[i].y3[j];
782 }
783 }
784 for(i=0; i<data->voiNr; i++) {
785 strcpy(temp.voi[i].name, data->voi[i].name);
786 strcpy(temp.voi[i].voiname, data->voi[i].voiname);
787 strcpy(temp.voi[i].hemisphere, data->voi[i].hemisphere);
788 strcpy(temp.voi[i].place, data->voi[i].place);
789 temp.voi[i].size=data->voi[i].size;
790 temp.voi[i].sw=data->voi[i].sw;
791 temp.voi[i].sw2=data->voi[i].sw2;
792 temp.voi[i].sw3=data->voi[i].sw3;
793 }
794
795 /* Reallocate memory for data */
796 dftEmpty(data);
797 if(dftSetmem(data, temp.frameNr+1, temp.voiNr)) {dftEmpty(&temp); return 2;}
798
799 /* Set nullframe */
800 data->x[0]=data->x1[0]=data->x2[0]=0.0; data->w[0]=0.0;
801 for(i=0; i<temp.voiNr; i++)
802 data->voi[i].y[0]=data->voi[i].y2[0]=data->voi[i].y3[0]=0.0;
803
804 /* Copy data back from temp */
805 strcpy(data->studynr, temp.studynr);
806 data->voiNr=temp.voiNr;
807 strcpy(data->unit, temp.unit);
808 data->timeunit=temp.timeunit; data->timetype=temp.timetype;
809 data->isweight=temp.isweight; data->_type=temp._type;
810 strcpy(data->comments, temp.comments);
811 for(j=0, n=1; j<temp.frameNr; j++) {
812 if(temp.x[j]<0.0) continue;
813 if(n==1) data->x2[0]=temp.x1[j];
814 data->x[n]=temp.x[j]; data->x1[n]=temp.x1[j]; data->x2[n]=temp.x2[j];
815 data->w[n]=temp.w[j];
816 for(i=0; i<temp.voiNr; i++) {
817 data->voi[i].y[n]=temp.voi[i].y[j];
818 data->voi[i].y2[n]=temp.voi[i].y2[j];
819 data->voi[i].y3[n]=temp.voi[i].y3[j];
820 }
821 n++;
822 }
823 data->frameNr=n;
824 for(i=0; i<temp.voiNr; i++) {
825 strcpy(data->voi[i].name, temp.voi[i].name);
826 strcpy(data->voi[i].voiname, temp.voi[i].voiname);
827 strcpy(data->voi[i].hemisphere, temp.voi[i].hemisphere);
828 strcpy(data->voi[i].place, temp.voi[i].place);
829 data->voi[i].size=temp.voi[i].size;
830 data->voi[i].sw=temp.voi[i].sw;
831 data->voi[i].sw2=temp.voi[i].sw2;
832 data->voi[i].sw3=temp.voi[i].sw3;
833 }
834
835 dftEmpty(&temp);
836
837 return 0;
838}
839/*****************************************************************************/
840
841/*****************************************************************************/
847 DFT *data
848) {
849 if(data==NULL) return(1);
850 if(data->voiNr<=1) return(0);
851 qsort(data->voi, data->voiNr, sizeof(Voi), dftQSortName);
852 return(0);
853}
855int dftQSortName(const void *voi1, const void *voi2)
856{
857 int res;
858
859 res=strcasecmp( ((Voi*)voi1)->name, ((Voi*)voi2)->name );
860 if(res!=0) return(res);
861 res=strcasecmp( ((Voi*)voi1)->voiname, ((Voi*)voi2)->voiname );
862 if(res!=0) return(res);
863 res=strcasecmp( ((Voi*)voi1)->hemisphere, ((Voi*)voi2)->hemisphere );
864 if(res!=0) return(res);
865 res=strcasecmp( ((Voi*)voi1)->place, ((Voi*)voi2)->place );
866 return(res);
867}
869/*****************************************************************************/
870
871/*****************************************************************************/
877 DFT *data
878) {
879 if(data==NULL) return(1);
880 if(data->voiNr<=1) return(0);
881 qsort(data->voi, data->voiNr, sizeof(Voi), dftQSortPlane);
882 return(0);
883}
885int dftQSortPlane(const void *voi1, const void *voi2)
886{
887 int res;
888
889 res=strcasecmp( ((Voi*)voi1)->place, ((Voi*)voi2)->place );
890 if(res!=0) return(res);
891 res=strcasecmp( ((Voi*)voi1)->name, ((Voi*)voi2)->name );
892 if(res!=0) return(res);
893 res=strcasecmp( ((Voi*)voi1)->voiname, ((Voi*)voi2)->voiname );
894 if(res!=0) return(res);
895 res=strcasecmp( ((Voi*)voi1)->hemisphere, ((Voi*)voi2)->hemisphere );
896 return(res);
897}
899/*****************************************************************************/
900
901/*****************************************************************************/
907 DFT *dft
908) {
909 int ri, fi, na_nr=0;
910 if(dft==NULL) return 0;
911 for(fi=0; fi<dft->frameNr; fi++) {
912 if(dft->timetype==DFT_TIME_STARTEND) {
913 if(isnan(dft->x1[fi])) na_nr++;
914 if(isnan(dft->x2[fi])) na_nr++;
915 } else {
916 if(isnan(dft->x[fi])) na_nr++;
917 }
918 for(ri=0; ri<dft->voiNr; ri++) if(isnan(dft->voi[ri].y[fi])) na_nr++;
919 }
920 return(na_nr);
921}
922/*****************************************************************************/
923
924/*****************************************************************************/
932 DFT *dft
933) {
934 int ri, fi, fj;
935 double x1, x2, y1, y2, x, y;
936
937 if(dft==NULL || dft->voiNr<1 || dft->frameNr<1) return(1);
938 for(ri=0; ri<dft->voiNr; ri++) for(fi=0; fi<dft->frameNr; fi++) {
939 if(isnan(dft->x[fi])) return(2);
940 if(isnan(dft->voi[ri].y[fi])) {
941 /* NA's before zero time are always replaced with 0 */
942 if(dft->x[fi]<0.0) {dft->voi[ri].y[fi]=0.0; continue;}
943 x=dft->x[fi];
944 /* Get the previous data that is not NA */
945 for(x1=y1=nan(""), fj=fi-1; fj>=0; fj--) if(!isnan(dft->voi[ri].y[fj])) {
946 x1=dft->x[fj]; y1=dft->voi[ri].y[fj]; break;
947 }
948 if(isnan(x1) || isnan(y1)) x1=y1=0.0;
949 /* Get the following data that is not NA */
950 for(x2=y2=nan(""), fj=fi+1; fj<dft->frameNr; fj++) if(!isnan(dft->voi[ri].y[fj])) {
951 x2=dft->x[fj]; y2=dft->voi[ri].y[fj]; break;
952 }
953 if(isnan(x2) || isnan(y2)) for(fj=fi-1; fj>=0; fj--) if(!isnan(dft->voi[ri].y[fj])) {
954 x2=dft->x[fj]; y2=dft->voi[ri].y[fj]; break;
955 }
956 if(isnan(x2) || isnan(y2)) return(2);
957 /* Calculate new value */
958 if(x2==x1) y=0.5*(y1+y2); else y=y2-(x2-x)*(y2-y1)/(x2-x1);
959 dft->voi[ri].y[fi]=y;
960 }
961 }
962 return(0);
963}
964/*****************************************************************************/
965
966/*****************************************************************************/
976 DFT *dft,
978 double *minx,
980 double *maxx,
982 double *miny,
984 double *maxy
985) {
986 int ri, fi, n;
987 double x1, x2, y1, y2;
988
989 if(dft==NULL) return(1);
990 x1=x2=y1=y2=nan("");
991 for(fi=0; fi<dft->frameNr; fi++) {
992 for(ri=0, n=0; ri<dft->voiNr; ri++) if(!isnan(dft->voi[ri].y[fi])) {
993 if(isnan(y1) || y1>dft->voi[ri].y[fi]) y1=dft->voi[ri].y[fi];
994 if(isnan(y2) || y2<dft->voi[ri].y[fi]) y2=dft->voi[ri].y[fi];
995 n++;
996 }
997 if(n==0) continue; // no true y values, thus do not use x either
998 if(dft->timetype==DFT_TIME_STARTEND) {
999 if(!isnan(dft->x1[fi])) {
1000 if(isnan(x1) || x1>dft->x1[fi]) x1=dft->x1[fi];
1001 }
1002 if(!isnan(dft->x2[fi])) {
1003 if(isnan(x2) || x2<dft->x2[fi]) x2=dft->x2[fi];
1004 }
1005 } else if(!isnan(dft->x[fi])) {
1006 if(isnan(x1) || x1>dft->x[fi]) x1=dft->x[fi];
1007 if(isnan(x2) || x2<dft->x[fi]) x2=dft->x[fi];
1008 }
1009 }
1010 if(minx!=NULL) {if(isnan(x1)) return(3); else *minx=x1;}
1011 if(maxx!=NULL) {if(isnan(x2)) return(4); else *maxx=x2;}
1012 if(miny!=NULL) {if(isnan(y1)) return(5); else *miny=y1;}
1013 if(maxy!=NULL) {if(isnan(y2)) return(6); else *maxy=y2;}
1014 return(0);
1015}
1016/*****************************************************************************/
1017
1018/*****************************************************************************/
1026 DFT *dft,
1028 int tacindex,
1030 double *minx,
1032 double *maxx,
1034 double *miny,
1036 double *maxy,
1038 int *mini,
1040 int *maxi,
1042 int *mins,
1044 int *maxs
1045) {
1046 int ri, fi, i1, i2, s1, s2;
1047 double x, x1, x2, y1, y2;
1048
1049 if(dft==NULL) return(1);
1050 if(tacindex>=dft->voiNr) return(2);
1051 if(dft->voiNr<1 || dft->frameNr<1) return(3);
1052
1053 x1=x2=y1=y2=nan(""); i1=i2=s1=s2=0;
1054 for(fi=0; fi<dft->frameNr; fi++) {
1055 if(dft->timetype==DFT_TIME_STARTEND) {
1056 if(isnan(dft->x1[fi])) continue;
1057 if(isnan(dft->x2[fi])) continue;
1058 x=0.5*(dft->x1[fi]+dft->x2[fi]);
1059 } else {
1060 if(isnan(dft->x[fi])) continue;
1061 x=dft->x[fi];
1062 }
1063 for(ri=0; ri<dft->voiNr; ri++) if(!isnan(dft->voi[ri].y[fi])) {
1064 if(tacindex>=0 && ri!=tacindex) continue;
1065 if(isnan(y1) || y1>dft->voi[ri].y[fi]) {
1066 y1=dft->voi[ri].y[fi]; i1=ri; x1=x; s1=fi;}
1067 if(isnan(y2) || y2<dft->voi[ri].y[fi]) {
1068 y2=dft->voi[ri].y[fi]; i2=ri; x2=x; s2=fi;}
1069 }
1070 }
1071 if(minx!=NULL) {if(isnan(x1)) return(11); else *minx=x1;}
1072 if(maxx!=NULL) {if(isnan(x2)) return(12); else *maxx=x2;}
1073 if(miny!=NULL) {if(isnan(y1)) return(13); else *miny=y1;}
1074 if(maxy!=NULL) {if(isnan(y2)) return(14); else *maxy=y2;}
1075 if(mini!=NULL) {if(isnan(y1)) return(13); else *mini=i1;}
1076 if(maxi!=NULL) {if(isnan(y2)) return(14); else *maxi=i2;}
1077 if(mins!=NULL) {if(isnan(y1)) return(13); else *mins=s1;}
1078 if(maxs!=NULL) {if(isnan(y2)) return(14); else *maxs=s2;}
1079 return(0);
1080}
1081/*****************************************************************************/
1082
1083/*****************************************************************************/
1092 DFT *dft,
1094 double t1,
1096 double t2,
1098 double *miny,
1100 double *maxy
1101) {
1102 int ri, fi;
1103 double x1, x2, y1, y2;
1104
1105 if(dft==NULL) return(1);
1106 y1=y2=nan("");
1107 for(fi=0; fi<dft->frameNr; fi++) {
1108 if(dft->timetype==DFT_TIME_STARTEND) {
1109 if(!isfinite(dft->x1[fi]) || !isfinite(dft->x2[fi])) continue;
1110 x1=dft->x1[fi]; x2=dft->x2[fi];
1111 } else {
1112 if(!isfinite(dft->x[fi])) continue;
1113 x1=x2=dft->x[fi];
1114 }
1115 if(x2<t1 || x1>t2) continue; // outside time range
1116 for(ri=0; ri<dft->voiNr; ri++) if(!isnan(dft->voi[ri].y[fi])) {
1117 if(isnan(y1) || y1>dft->voi[ri].y[fi]) y1=dft->voi[ri].y[fi];
1118 if(isnan(y2) || y2<dft->voi[ri].y[fi]) y2=dft->voi[ri].y[fi];
1119 }
1120 }
1121 if(miny!=NULL) {if(isnan(y1)) return(5); else *miny=y1;}
1122 if(maxy!=NULL) {if(isnan(y2)) return(6); else *maxy=y2;}
1123 return(0);
1124}
1125/*****************************************************************************/
1126
1127/*****************************************************************************/
1131 DFT *data
1132) {
1133 int i, j;
1134 double min=1e+99;
1135
1136 if(data==NULL) return(nan(""));
1137 for(i=0; i<data->voiNr ;i++) {
1138 for(j=0; j<data->frameNr; j++) {
1139 if(!isnan(data->voi[i].y[j]) && data->voi[i].y[j]<min) min=data->voi[i].y[j];
1140 }
1141 }
1142 return(min);
1143}
1144/*****************************************************************************/
1145
1146/*****************************************************************************/
1150 DFT *data
1151) {
1152 int i, j;
1153 double max=-1e+99;
1154
1155 if(data==NULL) return(nan(""));
1156 for(i=0; i<data->voiNr ;i++){
1157 for(j=0; j<data->frameNr; j++){
1158 if(!isnan(data->voi[i].y[j]) && data->voi[i].y[j]>max) max=data->voi[i].y[j];
1159 }
1160 }
1161 return(max);
1162}
1163/*****************************************************************************/
1164
1165/*****************************************************************************/
1171 DFT *dft
1172) {
1173 int ri, fi, fj;
1174 double d;
1175
1176 if(dft==NULL || dft->voiNr<1 || dft->frameNr<1) return(1);
1177 for(fi=0; fi<dft->frameNr-1; fi++) for(fj=fi+1; fj<dft->frameNr; fj++) {
1178 if(dft->x[fj]>=dft->x[fi]) continue;
1179 d=dft->x[fi]; dft->x[fi]=dft->x[fj]; dft->x[fj]=d;
1180 d=dft->x1[fi]; dft->x1[fi]=dft->x1[fj]; dft->x1[fj]=d;
1181 d=dft->x2[fi]; dft->x2[fi]=dft->x2[fj]; dft->x2[fj]=d;
1182 d=dft->w[fi]; dft->w[fi]=dft->w[fj]; dft->w[fj]=d;
1183 for(ri=0; ri<dft->voiNr; ri++) {
1184 d=dft->voi[ri].y[fi]; dft->voi[ri].y[fi]=dft->voi[ri].y[fj]; dft->voi[ri].y[fj]=d;
1185 d=dft->voi[ri].y2[fi]; dft->voi[ri].y2[fi]=dft->voi[ri].y2[fj]; dft->voi[ri].y2[fj]=d;
1186 d=dft->voi[ri].y3[fi]; dft->voi[ri].y3[fi]=dft->voi[ri].y3[fj]; dft->voi[ri].y3[fj]=d;
1187 }
1188 }
1189 return(0);
1190}
1191/*****************************************************************************/
1192
1193/*****************************************************************************/
1203 DFT *dft
1204) {
1205 int fi;
1206 double overlap, overlap_limit=1.8, flen1, flen2;
1207
1208 if(dft==NULL) return(1);
1209 if(dft->timetype!=DFT_TIME_STARTEND) return(0);
1210 if(dft->timeunit!=TUNIT_MIN && dft->timeunit!=TUNIT_SEC) return(0);
1211 if(dft->timeunit==TUNIT_MIN) overlap_limit/=60.0;
1212 for(fi=0; fi<dft->frameNr-1; fi++) {
1213 overlap=dft->x2[fi] - dft->x1[fi+1];
1214 if(overlap==0.0) continue; // no gap or overlap
1215 else if(overlap<-overlap_limit) continue; // gap is large, then do nothing
1216 else if(overlap>overlap_limit) return(2); // overlap is large: error
1217 /* Correct the small gap/overlap by making frame durations more similar */
1218 flen1=dft->x2[fi]-dft->x1[fi]; flen2=dft->x2[fi+1]-dft->x1[fi+1];
1219 if(overlap>0.0) { // overlap
1220 if(flen1>flen2) dft->x2[fi]=dft->x1[fi+1]; else dft->x1[fi+1]=dft->x2[fi];
1221 } else { // gap
1222 if(flen1>flen2) dft->x1[fi+1]=dft->x2[fi]; else dft->x2[fi]=dft->x1[fi+1];
1223 }
1224 }
1225 return(0);
1226}
1227/*****************************************************************************/
1228
1229/******************************************************************************/
1242 DFT *dft
1243) {
1244 int fi;
1245 double overlap, overlap_limit=0.0, flen1, flen2;
1246
1247 if(dft==NULL) return(1);
1248 if(dft->timetype!=DFT_TIME_STARTEND) return(0);
1249 for(fi=0; fi<dft->frameNr-1; fi++) {
1250 overlap=dft->x2[fi] - dft->x1[fi+1];
1251 if(overlap==0.0) continue; // no gap or overlap
1252 /* Calculate the frame length of current frame and the next frame */
1253 flen1=dft->x2[fi]-dft->x1[fi]; flen2=dft->x2[fi+1]-dft->x1[fi+1];
1254 if(flen1<0.0 || flen2<0.0) return(1);
1255 /* Set the limit */
1256 if(flen1<flen2) overlap_limit=0.2*flen1; else overlap_limit=0.2*flen2;
1257 /* Check if gap or overlap is too large to be fixed automatically */
1258 if(overlap<-overlap_limit) continue; // gap is too large, then do nothing
1259 if(overlap>overlap_limit) return(2); // overlap is too large: error
1260 /* Correct the small gap/overlap by making frame durations more similar */
1261 if(overlap>0.0) { // overlap
1262 if(flen1>flen2) dft->x2[fi]=dft->x1[fi+1]; else dft->x1[fi+1]=dft->x2[fi];
1263 } else { // gap
1264 if(flen1>flen2) dft->x1[fi+1]=dft->x2[fi]; else dft->x2[fi]=dft->x1[fi+1];
1265 }
1266 }
1267 return(0);
1268}
1269/******************************************************************************/
1270
1271/******************************************************************************/
1279 DFT *dft,
1281 double startT,
1283 double endT
1284) {
1285 int i, j, voi, first, origNr;
1286
1287 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return(1);
1288 if(endT<startT) return(2);
1289 if(startT<=dft->x[0] && endT>=dft->x[dft->frameNr-1]) return(0);
1290 origNr=dft->frameNr;
1291
1292 /* Delete end frames which are collected later than the end time */
1293 for(j=dft->frameNr-1; j>=0; j--) if(dft->x[j]<=endT) break;
1294 dft->frameNr=j+1;
1295
1296 /* Find the first frame that has been collected later than start time */
1297 for(j=0, first=-1; j<dft->frameNr; j++)
1298 if(dft->x[j]>=startT) {first=j; break;}
1299 if(first<0) {
1300 dft->frameNr=origNr; // undelete the end data
1301 return(3);
1302 }
1303
1304 /* Delete first frames */
1305 if(first>0) for(j=first, i=0; j<dft->frameNr; j++, i++) {
1306 dft->x[i]=dft->x[j]; dft->x1[i]=dft->x1[j]; dft->x2[i]=dft->x2[j];
1307 dft->w[i]=dft->w[j];
1308 for(voi=0; voi<dft->voiNr; voi++) {
1309 dft->voi[voi].y[i]=dft->voi[voi].y[j];
1310 dft->voi[voi].y2[i]=dft->voi[voi].y2[j];
1311 dft->voi[voi].y3[i]=dft->voi[voi].y3[j];
1312 }
1313 }
1314 dft->frameNr-=first;
1315
1316 return(0);
1317}
1318/******************************************************************************/
1319
1320/******************************************************************************/
1328 DFT *dft
1329) {
1330 char tmp[512];
1331
1332 if(dft==NULL) return;
1333 strcpy(dft->comments, "");
1334 /* Write in comments the information that will not be included in titles */
1335 if(dft->scanStartTime[0]) {
1336 sprintf(tmp, "# scan_start_time := %s\n", dft->scanStartTime);
1337 strcat(dft->comments, tmp);
1338 }
1339 if(dft->injectionTime[0]) {
1340 sprintf(tmp, "# injection_time := %s\n", dft->injectionTime);
1341 strcat(dft->comments, tmp);
1342 }
1343 strcpy(tmp, "# decay_correction := ");
1344 if(dft->decayCorrected==DFT_DECAY_CORRECTED) strcat(tmp, "Yes\n");
1345 else if(dft->decayCorrected==DFT_DECAY_NOTCORRECTED) strcat(tmp, "No\n");
1346 else strcat(tmp, "Unknown\n");
1347 if(dft->decayCorrected!=DFT_DECAY_UNKNOWN) strcat(dft->comments, tmp);
1348 if(dft->isotope[0]) {
1349 sprintf(tmp, "# isotope := %s\n", dft->isotope);
1350 strcat(dft->comments, tmp);
1351 }
1352 if(dft->radiopharmaceutical[0]) {
1353 sprintf(tmp, "# radiopharmaceutical := %s\n", dft->radiopharmaceutical);
1354 strcat(dft->comments, tmp);
1355 }
1356 /* If titles are set to be saved, then there's no need to put more in comments */
1357 if(dft->_type==DFT_FORMAT_STANDARD || dft->_type==DFT_FORMAT_PMOD) return;
1358
1359 /* Ok then, lets write even title information in comments */
1360 if(dft->studynr[0]) {
1361 sprintf(tmp, "# study_number := %s\n", dft->studynr);
1362 strcat(dft->comments, tmp);
1363 }
1364 if(dft->timeunit!=TUNIT_UNKNOWN) {
1365 sprintf(tmp, "# timeunit := %s\n", petTunit(dft->timeunit) );
1366 strcat(dft->comments, tmp);
1367 }
1368 if(petCunitId(dft->unit)!=CUNIT_UNKNOWN) {
1369 sprintf(tmp, "# unit := %s\n", dft->unit );
1370 strcat(dft->comments, tmp);
1371 }
1372 // Region names and volumes are not saved in comments because of space limit
1373
1374 return;
1375}
1376/*****************************************************************************/
1377
1378/*****************************************************************************/
1387 DFT *dft
1388) {
1389 DFT temp;
1390 int ret, ri, fi;
1391
1392 /* Check input */
1393 if(dft==NULL) return 1;
1394 if(dft->frameNr<1 || dft->voiNr<1) return 0;
1395
1396 /* Is there an initial gap? If not then we can finish here */
1397 if(dft->timetype==DFT_TIME_STARTEND) {
1398 if(dft->x1[0]<=0.0) return 0;
1399 } else {
1400 if(dft->x[0]<=0.0) return 0;
1401 }
1402
1403 /* Make a temporary storage of the data */
1404 dftInit(&temp); ret=dftdup(dft, &temp); if(ret!=0) return 10+ret;
1405 /* Delete and reallocate the original data pointer */
1406 dftEmpty(dft); ret=dftSetmem(dft, temp.frameNr+1, temp.voiNr);
1407 if(ret!=0) {
1408 dftdup(&temp, dft); dftEmpty(&temp);
1409 return 20+ret;
1410 }
1411 /* Copy data back, leaving first frame empty */
1412 ret=dftCopymainhdr(&temp, dft);
1413 if(ret!=0) {
1414 dftdup(&temp, dft); dftEmpty(&temp);
1415 return 30+ret;
1416 }
1417 dft->voiNr=temp.voiNr; dft->frameNr=1+temp.frameNr;
1418 dft->isweight=temp.isweight;
1419 strcpy(dft->comments, temp.comments);
1420 for(ri=0; ri<temp.voiNr; ri++) {
1421 ret=dftCopyvoihdr(&temp, ri, dft, ri);
1422 if(ret!=0) {
1423 dftdup(&temp, dft); dftEmpty(&temp);
1424 return 40+ret;
1425 }
1426 for(fi=0; fi<temp.frameNr; fi++) {
1427 dft->voi[ri].y[fi+1]=temp.voi[ri].y[fi];
1428 dft->voi[ri].y2[fi+1]=temp.voi[ri].y2[fi];
1429 dft->voi[ri].y3[fi+1]=temp.voi[ri].y3[fi];
1430 }
1431 /* Fill in the first frame */
1432 dft->voi[ri].y[0]=0.0;
1433 dft->voi[ri].y2[0]=0.0;
1434 dft->voi[ri].y3[0]=0.0;
1435 }
1436 for(fi=0; fi<temp.frameNr; fi++) {
1437 dft->x1[fi+1]=temp.x1[fi];
1438 dft->x2[fi+1]=temp.x2[fi];
1439 dft->x[fi+1]=temp.x[fi];
1440 dft->w[fi+1]=temp.w[fi];
1441 }
1442 dftEmpty(&temp);
1443
1444 /* Fill the first frame */
1445 dft->w[0]=1.0;
1446 if(dft->timetype==DFT_TIME_STARTEND) {
1447 dft->x1[0]=0.0;
1448 dft->x2[0]=dft->x1[1];
1449 dft->x[0]=0.5*(dft->x1[0]+dft->x2[0]);
1450 } else {
1451 dft->x1[0]=0.0;
1452 dft->x2[0]=dft->x1[1];
1453 dft->x[0]=0.0;
1454 }
1455
1456 return 0;
1457}
1458/*****************************************************************************/
1459
1460/*****************************************************************************/
1467 DFT *dft,
1469 int nr_to_add
1470) {
1471 DFT temp;
1472 int ret, ri, fi;
1473
1474 /* Check input */
1475 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return 1;
1476 if(nr_to_add<1) return 0;
1477
1478 /* Make a temporary storage of the data */
1479 dftInit(&temp); ret=dftdup(dft, &temp); if(ret!=0) return 10+ret;
1480 /* Delete and reallocate the original data pointer */
1481 dftEmpty(dft); ret=dftSetmem(dft, temp.frameNr+nr_to_add, temp.voiNr);
1482 if(ret!=0) {
1483 dftdup(&temp, dft); dftEmpty(&temp);
1484 return 20+ret;
1485 }
1486 /* Copy data back, leaving last frame(s) empty */
1487 ret=dftCopymainhdr(&temp, dft);
1488 if(ret!=0) {
1489 dftdup(&temp, dft); dftEmpty(&temp);
1490 return 30+ret;
1491 }
1492 dft->voiNr=temp.voiNr; dft->frameNr=nr_to_add+temp.frameNr;
1493 dft->isweight=temp.isweight;
1494 strcpy(dft->comments, temp.comments);
1495 for(ri=0; ri<temp.voiNr; ri++) {
1496 ret=dftCopyvoihdr(&temp, ri, dft, ri);
1497 if(ret!=0) {
1498 dftdup(&temp, dft); dftEmpty(&temp);
1499 return 40+ret;
1500 }
1501 for(fi=0; fi<temp.frameNr; fi++) {
1502 dft->voi[ri].y[fi]=temp.voi[ri].y[fi];
1503 dft->voi[ri].y2[fi]=temp.voi[ri].y2[fi];
1504 dft->voi[ri].y3[fi]=temp.voi[ri].y3[fi];
1505 }
1506 /* Fill in the first frame */
1507 dft->voi[ri].y[0]=0.0;
1508 dft->voi[ri].y2[0]=0.0;
1509 dft->voi[ri].y3[0]=0.0;
1510 }
1511 for(fi=0; fi<temp.frameNr; fi++) {
1512 dft->x1[fi]=temp.x1[fi];
1513 dft->x2[fi]=temp.x2[fi];
1514 dft->x[fi]=temp.x[fi];
1515 dft->w[fi]=temp.w[fi];
1516 }
1517
1518 /* Fill the last frames with NAs */
1519 for(fi=temp.frameNr; fi<dft->frameNr; fi++) {
1520 dft->w[fi]=1.0;
1521 dft->x1[fi]=dft->x2[fi]=dft->x[0]=0.0;
1522 for(ri=0; ri<dft->voiNr; ri++) dft->voi[ri].y[fi]=nan("");
1523 }
1524 dftEmpty(&temp);
1525
1526 return 0;
1527}
1528/*****************************************************************************/
1529
1530/*****************************************************************************/
1536 DFT *dft,
1538 int hemisphere,
1540 int place
1541) {
1542 int ri, n;
1543
1544 if(dft==NULL || dft->voiNr<1) return;
1545 if(hemisphere==0 && place==0) return;
1546
1547 /* Check if all TACs have the same field content: if yes, then
1548 delete the field content */
1549 if(hemisphere!=0) {
1550 for(ri=n=1; ri<dft->voiNr; ri++)
1551 if(strcasecmp(dft->voi[0].hemisphere, dft->voi[ri].hemisphere)==0) n++;
1552 if(n==dft->voiNr)
1553 for(ri=0; ri<dft->voiNr; ri++)
1554 strcpy(dft->voi[ri].hemisphere, "");
1555 }
1556 if(place!=0) {
1557 for(ri=n=1; ri<dft->voiNr; ri++)
1558 if(strcasecmp(dft->voi[0].place, dft->voi[ri].place)==0) n++;
1559 if(n==dft->voiNr)
1560 for(ri=0; ri<dft->voiNr; ri++)
1561 strcpy(dft->voi[ri].place, "");
1562 }
1563
1564 /* Construct combined TAC names */
1565 for(ri=0; ri<dft->voiNr; ri++)
1567 dft->voi[ri].voiname, dft->voi[ri].hemisphere,
1568 dft->voi[ri].place, '_');
1569 /* Ready */
1570 return;
1571}
1572/*****************************************************************************/
1573
1574/*****************************************************************************/
1583 DFT *dft,
1586 DFT *mean
1587) {
1588 int ret, fi, ri, n;
1589 double sum, ssum;
1590
1591 if(dft==NULL || mean==NULL) return(1);
1592 if(dft->voiNr<1 || dft->frameNr<1) return(2);
1593
1594 /* Allocate memory for mean data, if necessary */
1595 if(mean->voiNr<1 || mean->frameNr!=dft->frameNr) {
1596 dftEmpty(mean); ret=dftAllocateWithHeader(mean, dft->frameNr, 1, dft);
1597 if(ret!=0) return(100+ret);
1598 }
1599 strcpy(mean->voi[0].name, "Mean");
1600 strcpy(mean->voi[0].voiname, mean->voi[0].name);
1601
1602 /* Calculate the mean TAC */
1603 ret=0;
1604 for(fi=0; fi<dft->frameNr; fi++) {
1605 sum=ssum=0.0; n=0;
1606 for(ri=0; ri<dft->voiNr; ri++) if(!isnan(dft->voi[ri].y[fi])) {
1607 sum+=dft->voi[ri].y[fi];
1608 ssum+=dft->voi[ri].y[fi]*dft->voi[ri].y[fi];
1609 n++;
1610 }
1611 if(n==0) {
1612 mean->voi[0].y[fi]=mean->voi[0].y2[fi]=mean->voi[0].y3[fi]=nan("");
1613 } else {
1614 mean->voi[0].y[fi]=sum/(double)n;
1615 if(n==1) {
1616 mean->voi[0].y2[fi]=mean->voi[0].y3[fi]=0.0;
1617 } else {
1618 mean->voi[0].y2[fi]=sqrt((ssum-sum*sum/(double)n)/(double)(n-1));
1619 if(fabs(mean->voi[0].y[fi])>1.0E-25)
1620 mean->voi[0].y3[fi]=fabs(mean->voi[0].y2[fi]/mean->voi[0].y[fi]);
1621 else
1622 mean->voi[0].y3[fi]=0.0;
1623 }
1624 }
1625 if(n>0) ret++;
1626 }
1627 /* Check that at least half of frames contained acceptable data */
1628 if(2*ret<dft->frameNr) {dftEmpty(mean); return(10);}
1629
1630 return(0);
1631}
1632/*****************************************************************************/
1633
1634/*****************************************************************************/
1640 DFT *dft,
1642 double tstart,
1644 double tstop,
1647 int index
1648) {
1649 if(dft==NULL || dft->voiNr<0 || dft->frameNr<0) return(0);
1650 if(index>dft->voiNr-1) return(0);
1651 if(index>=0) { // TAC index given
1652 int n=0;
1653 double x;
1654 for(int i=0; i<dft->frameNr; i++) {
1655 if(dft->timetype!=DFT_TIME_STARTEND) x=dft->x[i];
1656 else x=0.5*(dft->x1[i]+dft->x2[i]);
1657 if(isnan(x) || !isfinite(x)) continue;
1658 if(x<tstart || x>tstop) continue;
1659 if(isnan(dft->voi[index].y[i]) || !isfinite(dft->voi[index].y[i]))
1660 continue;
1661 n++;
1662 }
1663 return(n);
1664 }
1665 /* Get min nr of all TACs */
1666 int n=0, minn=0;
1667 minn=dftValidNr(dft, tstart, tstop, 0);
1668 for(int j=1; j<dft->voiNr; j++) {
1669 n=dftValidNr(dft, tstart, tstop, j);
1670 if(n<minn) minn=n;
1671 }
1672 return(minn);
1673}
1674/*****************************************************************************/
1675
1676/*****************************************************************************/
int dftAddnullframe(DFT *data)
Definition dft.c:752
int dftCopyvoihdr(DFT *dft1, int from, DFT *dft2, int to)
Definition dft.c:623
int dftRemoveTimeRange(DFT *dft, double startT, double endT)
Definition dft.c:1275
void dftInit(DFT *data)
Definition dft.c:38
int dftMinMaxTAC(DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs)
Definition dft.c:1024
int dftdup(DFT *dft1, DFT *dft2)
Definition dft.c:655
char dfterrmsg[64]
Definition dft.c:6
int dftDeleteFrameOverlap(DFT *dft)
Definition dft.c:1237
int dftAddmem(DFT *dft, int voiNr)
Definition dft.c:107
int dftMovevoi(DFT *dft, int from, int to)
Definition dft.c:508
int dftAddSpaceForFrames(DFT *dft, int nr_to_add)
Definition dft.c:1465
void dftSetComments(DFT *dft)
Definition dft.c:1326
int dftSortByFrame(DFT *dft)
Definition dft.c:1169
int dftSelectBestReference(DFT *dft)
Definition dft.c:314
int dftCopymainhdr2(DFT *dft1, DFT *dft2, int ow)
Definition dft.c:587
int dftMinMax(DFT *dft, double *minx, double *maxx, double *miny, double *maxy)
Definition dft.c:974
int dftCopyvoi(DFT *data, int from, int to)
Definition dft.c:472
int dftDelete(DFT *dft, int voi)
Definition dft.c:538
int dftSort(DFT *data)
Definition dft.c:845
int dftMaxY(DFT *dft, double t1, double t2, double *miny, double *maxy)
Definition dft.c:1090
int dftValidNr(DFT *dft, double tstart, double tstop, int index)
Definition dft.c:1638
int dftMeanTAC(DFT *dft, DFT *mean)
Definition dft.c:1580
int dftSetmem(DFT *data, int frameNr, int voiNr)
Definition dft.c:57
double dft_kBqMin(DFT *data)
Definition dft.c:1129
int dftAdd(DFT *data1, DFT *data2, int voi)
Definition dft.c:188
void dftEmpty(DFT *data)
Definition dft.c:20
int dftFillInitialGap(DFT *dft)
Definition dft.c:1385
double dft_kBqMax(DFT *data)
Definition dft.c:1148
void dftRNameSimplify(DFT *dft, int hemisphere, int place)
Definition dft.c:1534
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftSortPlane(DFT *data)
Definition dft.c:875
int dftSelectRegions(DFT *dft, char *region_name, int reset)
Definition dft.c:285
int dftAllocateWithHeader(DFT *dft, int frameNr, int voiNr, DFT *dft_from)
Definition dft.c:702
int dftDeleteFrameOverlap_old(DFT *dft)
Definition dft.c:1200
void dftFrametimes(DFT *data)
Definition dft.c:340
int dftSelect(DFT *data, char *name)
Definition dft.c:239
int dftNAfill(DFT *dft)
Definition dft.c:930
int dftCopymainhdr(DFT *dft1, DFT *dft2)
Definition dft.c:561
int dftOverflow(DFT *data)
Definition dft.c:451
Header file for libtpccurveio.
#define DFT_DECAY_UNKNOWN
#define DFT_DECAY_NOTCORRECTED
#define DFT_FORMAT_PMOD
#define DFT_TIME_MIDDLE
#define DFT_FORMAT_STANDARD
#define DFT_DECAY_CORRECTED
#define DFT_TIME_END
#define DFT_TIME_START
#define DFT_FORMAT_PLAIN
#define DFT_TIME_STARTEND
int rnameCatenate(char *rname, int max_rname_len, char *name1, char *name2, char *name3, char space)
Definition rname.c:189
int petCunitId(const char *unit)
Definition petunits.c:74
int rnameMatch(char *rname, int rnr, char *test_str)
Definition rname.c:144
#define MAX_REGIONNAME_LEN
Definition libtpcmisc.h:154
char * petTunit(int tunit)
Definition petunits.c:226
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341
char scanStartTime[20]
char decayCorrected
int _type
int timetype
Voi * voi
int timeunit
char studynr[MAX_STUDYNR_LEN+1]
double * w
double * x1
char comments[_DFT_COMMENT_LEN+1]
int voiNr
double * x2
char injectionTime[20]
int frameNr
int isweight
char isotope[8]
double * x
char unit[MAX_UNITS_LEN+1]
char radiopharmaceutical[32]
double size
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
char sw
double * y
char name[MAX_REGIONNAME_LEN+1]
double * y3
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char sw2
char sw3
char place[MAX_REGIONSUBNAME_LEN+1]