TPCCLIB
Loading...
Searching...
No Matches
dftinput.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6
7/*****************************************************************************/
8#include "libtpcmodext.h"
9/*****************************************************************************/
10
11/*****************************************************************************/
12
13/*****************************************************************************/
27 DFT *input,
29 DFT *tissue,
31 char *filename,
34 int *filetype,
37 double *ti1,
40 double *ti2,
43 int verifypeak,
46 char *status,
48 int verbose
49) {
50 int ri, n, ret, ftype=0;
51 DFT temp;
52 FILE *fp;
53
54 if(verbose>0) printf("dftReadinput(inp, tis, %s, type, ti1, ti2, %d, status, %d)\n",
55 filename, verifypeak, verbose);
56 if(filetype!=NULL) *filetype=0;
57
58 /* Check that PET data is ok */
59 if(input==NULL || tissue==NULL || filename==NULL) {
60 if(status!=NULL) strcpy(status, "program error");
61 return 1;
62 }
63 if(tissue->frameNr<1 || tissue->voiNr<1) {
64 if(status!=NULL) strcpy(status, "no pet data");
65 return 2;
66 }
67
68 /* Delete any previous input data and initiate temp data */
69 dftEmpty(input); dftInit(&temp);
70
71 /* Try to figure out what is the 'filename' */
72 ftype=0;
73 /* Can we open it as a file? */
74 fp=fopen(filename, "r");
75 if(fp!=NULL) {
76 /* File can be opened for read; close it for now */
77 if(verbose>1) printf(" file can be opened for reading.\n");
78 if(filetype!=NULL) *filetype=1;
79 fclose(fp);
80
81 /* Try to identify the file format */
82 ftype=dftFormat(filename);
83 if(ftype==DFT_FORMAT_UNKNOWN) {
84 if(filetype!=NULL) *filetype=0;
85 if(status!=NULL) strcpy(status, "unknown file format");
86 return 3;
87 } else if(ftype==DFT_FORMAT_FIT) {
88 if(filetype!=NULL) *filetype=3;
89 if(status!=NULL) strcpy(status, "cannot read fit file");
90 return 3;
91 }
92 if(verbose>2) printf(" fileformat=%d\n", ftype);
93
94 /* Try to read it */
95 if((ret=dftRead(filename, &temp))!=0) {
96 if(filetype!=NULL) *filetype=0;
97 if(status!=NULL) sprintf(status, "cannot read file (%d)", ret);
98 return(2);
99 }
100 /* Convert input time units to the same as in tissue data */
101 (void)dftTimeunitConversion(&temp, tissue->timeunit);
102 /* Check the tissue and plasma TAC concentration units */
103 ret=dftUnitConversion(&temp, petCunitId(tissue->unit));
104 if(ret!=0) {sprintf(status, "check the units of input and tissue data");}
105 /* Tell user what was the original input time range */
106 if(temp.timetype==DFT_TIME_STARTEND) {
107 if(ti1!=NULL) *ti1=temp.x1[0];
108 if(ti2!=NULL) *ti2=temp.x2[temp.frameNr-1];
109 } else {
110 if(ti1!=NULL) *ti1=temp.x[0];
111 if(ti2!=NULL) *ti2=temp.x[temp.frameNr-1];
112 }
113 /* Verify the peak if requested */
114 if(verifypeak!=0) {
115 ret=dftVerifyPeak(&temp, 0, verbose-2, status);
116 //if(ret!=0) sprintf(status, "input TAC should start at time zero");
117 if(ret>0) {dftEmpty(&temp); return 101;}
118 }
119 /* Interpolate and integrate data to pet times */
120 ret=dftInterpolate(&temp, tissue, input, status, verbose);
121 dftEmpty(&temp);
122 if(ret!=0) return 4;
123
124 } else {
125
126 /* it's not a file, at least an accessible file, but is it a region name? */
127 if(filetype!=NULL) *filetype=5;
128 /* Select ROIs that match the specified input name */
129 n=dftSelectRegions(tissue, filename, 1);
130 if(n<=0) {
131 if(status!=NULL) sprintf(status, "cannot find region");
132 return 7;
133 }
134 if(n==tissue->voiNr) {
135 if(status!=NULL) sprintf(status, "all regions do match");
136 return 8;
137 }
138 /* one or more regions was found ; move them to input data */
139 ret=dftdup(tissue, input); if(ret==0) {
140 ri=0; ret=0; while(ri<input->voiNr && ret==0) {
141 if(input->voi[ri].sw==0) ret=dftDelete(input, ri); else ri++;
142 }
143 if(ret==0) {
144 ri=0; ret=0; while(ri<tissue->voiNr && ret==0) {
145 if(tissue->voi[ri].sw!=0) ret=dftDelete(tissue, ri); else ri++;
146 }
147 }
148 }
149 if(ret!=0) {
150 if(status!=NULL) sprintf(status, "cannot separate input regions");
151 dftEmpty(input); return 9;
152 }
153 /* Try to select the best reference ROI */
154 ri=dftSelectBestReference(input); if(ri<0) {
155 if(status!=NULL) sprintf(status, "cannot separate input regions");
156 dftEmpty(input); return 10;
157 }
158 /* And move it to the first place */
159 if(ri>0) {dftMovevoi(input, ri, 0); ri=0;}
160 if(verbose>1) printf("selected ref region := %s\n", input->voi[0].name);
161 /* Verify the peak if requested */
162 if(verifypeak!=0) {
163 ret=dftVerifyPeak(input, 0, verbose-2, status);
164 //if(ret!=0) sprintf(status, "input TAC should start at time zero");
165 if(ret>0) {dftEmpty(input); return 101;}
166 }
167
168 /* Calculate integrals */
169 for(ri=0; ri<input->voiNr; ri++) {
170 if(input->timetype==DFT_TIME_STARTEND) {
171 ret=petintegral(input->x1, input->x2, input->voi[ri].y, input->frameNr,
172 input->voi[ri].y2, input->voi[ri].y3);
173 if(ti1!=NULL) *ti1=input->x1[0];
174 if(ti2!=NULL) *ti2=input->x2[input->frameNr-1];
175 } else {
176 ret=interpolate(input->x, input->voi[ri].y, input->frameNr,
177 input->x, NULL, input->voi[ri].y2, input->voi[ri].y3, input->frameNr);
178 if(ti1!=NULL) *ti1=input->x[0];
179 if(ti2!=NULL) *ti2=input->x[input->frameNr-1];
180 }
181 if(ret) {
182 if(status!=NULL) sprintf(status, "cannot integrate input");
183 dftEmpty(input); return(11);
184 }
185 }
186 }
187
188 return(0);
189}
190/*****************************************************************************/
191
192/*****************************************************************************/
206 DFT *tissue,
208 char *filename,
211 int *filetype,
213 int *ref_index,
216 char *status,
218 int verbose
219) {
220 int ri, n, ret;
221 DFT temp;
222 FILE *fp;
223 int ftype=0;
224
225 if(verbose>0) printf("dftReadReference(tis, %s, type, i, status, %d)\n", filename, verbose);
226
227 /* Check that input is ok */
228 if(tissue==NULL || filename==NULL || strlen(filename)<1) {
229 if(status!=NULL) strcpy(status, "program error");
230 return -1;
231 }
232 if(tissue->frameNr<1 || tissue->voiNr<1) {
233 if(status!=NULL) strcpy(status, "no pet data");
234 return -2;
235 }
236
237 /* Check if we can identify the reference as an unsupported file */
238 ret=dftFormat(filename);
239 if(ret==DFT_FORMAT_FIT) {
240 if(filetype!=NULL) *filetype=3;
241 if(status!=NULL) strcpy(status, "cannot read fit file");
242 return -3;
243 }
244
245
246 /* Can we open it as a file? */
247 fp=fopen(filename, "r");
248 if(fp!=NULL) {
249 fclose(fp);
250 /* Try to read the reference as a TAC file */
251 dftInit(&temp);
252 if((ret=dftRead(filename, &temp))!=0) {
253 if(status!=NULL) sprintf(status, "cannot read file (%d)", ret);
254 return -4;
255 }
256 if(filetype!=NULL) *filetype=1;
257
258 /* Convert ref time units to the same as in tissue data */
259 (void)dftTimeunitConversion(&temp, tissue->timeunit);
260 /* Check the tissue and ref TAC concentration units */
261 if((ret=dftUnitConversion(&temp, petCunitId(tissue->unit)))!=0) {
262 sprintf(status, "check the units of reference and tissue data");
263 }
264 /* Interpolate and integrate data to pet times */
265 /* this also verifies that ref data does not need extensive extrapolation */
266 ret=dftInterpolateInto(&temp, tissue, status, verbose);
267 if(ret!=0) {dftEmpty(&temp); return -5;}
268 /* Set switches to define which are reference regions and which are not */
269 for(ri=0; ri<tissue->voiNr-temp.voiNr; ri++) tissue->voi[ri].sw=0;
270 for(; ri<tissue->voiNr; ri++) tissue->voi[ri].sw=1;
271 /* Find the best reference region */
272 n=temp.voiNr; dftEmpty(&temp);
273 if(n==1) {
274 ri=tissue->voiNr-n;
275 } else {
276 if((ri=dftSelectBestReference(tissue))<0) {
277 sprintf(status, "cannot select the best reference region");
278 dftEmpty(&temp); return -6;
279 }
280 }
281 tissue->voi[ri].sw=2; if(ref_index!=NULL) *ref_index=ri;
282 if(verbose>1) printf("selected ref region := %s\n", tissue->voi[ri].name);
283 if(status!=NULL) sprintf(status, "%d reference curve(s) read", n);
284
285 return n;
286
287 } // reference file was read and processed
288
289
290 /* So it's not a file, at least an accessible file, but is it region name? */
291 ftype=5; if(filetype!=NULL) *filetype=ftype;
292 /* Select ROIs that match the specified input name */
293 n=dftSelectRegions(tissue, filename, 1);
294 if(verbose>1) printf("nr of ref regions := %d/%d\n", n, tissue->voiNr);
295 if(n<=0) {
296 if(status!=NULL) sprintf(status, "cannot find region");
297 return -7;
298 }
299 if(n==tissue->voiNr && tissue->voiNr>1) {
300 if(status!=NULL) sprintf(status, "all regions do match");
301 return -8;
302 }
303
304 /* Try to select the best reference ROI */
305 ri=dftSelectBestReference(tissue); if(ri<0) {
306 if(status!=NULL) sprintf(status, "cannot select the best reference region");
307 return -9;
308 }
309 tissue->voi[ri].sw=2; if(ref_index!=NULL) *ref_index=ri;
310 if(verbose>1) printf("selected ref region := %s\n", tissue->voi[ri].name);
311
312 /* Calculate integrals */
313 for(ri=0; ri<tissue->voiNr; ri++) if(tissue->voi[ri].sw>0) {
314 if(tissue->timetype==DFT_TIME_STARTEND) {
315 ret=petintegrate(tissue->x1, tissue->x2, tissue->voi[ri].y,
316 tissue->frameNr, tissue->voi[ri].y2, NULL);
317 } else {
318 ret=integrate(tissue->x, tissue->voi[ri].y, tissue->frameNr, tissue->voi[ri].y2);
319 }
320 if(ret) {
321 if(status!=NULL) sprintf(status, "cannot integrate input");
322 return(-11);
323 }
324 }
325
326 if(status!=NULL) sprintf(status, "%d reference curve(s) read", n);
327 return(n);
328}
329/*****************************************************************************/
330
331/*****************************************************************************/
344 char *tissuefile,
346 char *inputfile1,
348 char *inputfile2,
350 char *inputfile3,
352 double *fitdur,
354 int *fitframeNr,
356 DFT *tis,
358 DFT *inp,
361 FILE *loginfo,
363 int verbose,
366 char *status
367) {
368 int ret, fi, n, first, last, ii, input_nr=0;
369 DFT tmpdft;
370 double f, starttime, endtime;
371 FILE *wfp;
372 char *fname;
373
374
375 if(loginfo!=NULL && verbose>0) {
376 fprintf(loginfo, "dftReadModelingData(\n");
377 fprintf(loginfo, " %s,\n", tissuefile);
378 fprintf(loginfo, " %s,\n", inputfile1);
379 fprintf(loginfo, " %s,\n", inputfile2);
380 fprintf(loginfo, " %s,\n", inputfile3);
381 fprintf(loginfo, " %g,\n", *fitdur);
382 fprintf(loginfo, " *fitframeNr, *tis, *inp, *loginfo, %d, *status\n", verbose);
383 fprintf(loginfo, ")\n");
384 }
385 /* Check the input */
386 if(status!=NULL) sprintf(status, "program error");
387 if(tis==NULL || inp==NULL) return -1;
388 if(tissuefile==NULL || strlen(tissuefile)<1) return -2;
389 ret=0;
390 if(inputfile1==NULL || strlen(inputfile1)<1) return -3; else input_nr++;
391 if(inputfile2!=NULL && strlen(inputfile2)>0) input_nr++;
392 if(inputfile3!=NULL && strlen(inputfile3)>0) {
393 if(input_nr<2) return -4;
394 input_nr++;
395 }
396 if(status!=NULL) sprintf(status, "arguments validated");
397 /* Warnings will be printed into stderr */
398 wfp=stderr;
399
400 /* Delete any previous data and initiate temp data */
401 dftEmpty(inp); dftEmpty(tis); dftInit(&tmpdft);
402
403 /*
404 * Read tissue data
405 */
406 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading tissue data in %s\n", tissuefile);
407 if(dftRead(tissuefile, tis)) {
408 if(status!=NULL) sprintf(status, "cannot read '%s': %s", tissuefile, dfterrmsg);
409 return(2);
410 }
411 /* Check for NaN's */
412 ret=dft_nr_of_NA(tis); if(ret>0) {
413 if(status!=NULL) sprintf(status, "missing sample(s) in %s", tissuefile);
414 dftEmpty(tis); return(2);
415 }
416 /* Sort the data by increasing sample times */
417 dftSortByFrame(tis);
418 /* Do not check frame number; static scan is fine here */
419 /* Make sure that there is no overlap in frame times */
420 if(tis->timetype==DFT_TIME_STARTEND) {
421 if(loginfo!=NULL && verbose>0)
422 fprintf(loginfo, "checking frame overlap in %s\n", tissuefile);
423 ret=dftDeleteFrameOverlap(tis);
424 if(ret) {
425 if(status!=NULL) sprintf(status, "%s has overlapping frame times", tissuefile);
426 dftEmpty(tis); return(2);
427 }
428 }
429 if(tis->timeunit==TUNIT_UNKNOWN) {
430 fprintf(wfp, "Warning: tissue sample time units not known.\n");
431 }
432
433 /*
434 * Read first input data
435 */
436 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", inputfile1);
437 if(dftRead(inputfile1, inp)) {
438 if(status!=NULL) sprintf(status, "cannot read '%s': %s", inputfile1, dfterrmsg);
439 dftEmpty(tis); return(3);
440 }
441 /* Check and correct the sample time unit */
442 if(tis->timeunit==TUNIT_UNKNOWN) tis->timeunit=inp->timeunit;
443 else if(inp->timeunit==TUNIT_UNKNOWN) inp->timeunit=tis->timeunit;
444 if(inp->timeunit==TUNIT_UNKNOWN) {
445 fprintf(wfp, "Warning: input sample time units not known.\n");
446 }
447 if(tis->timeunit!=inp->timeunit &&
448 dftTimeunitConversion(inp, tis->timeunit)!=0) {
449 if(status!=NULL) sprintf(status, "tissue and plasma do have different time units");
450 dftEmpty(tis); dftEmpty(inp);
451 return(3);
452 }
453 if(inp->voiNr>1) {
454 fprintf(wfp, "Warning: using only first TAC in %s\n", inputfile1);
455 inp->voiNr=1;
456 }
457 if(inp->frameNr<4) {
458 if(status!=NULL) sprintf(status, "%s contains too few samples", inputfile1);
459 dftEmpty(tis); dftEmpty(inp); return(3);
460 }
461 /* Sort the data by increasing sample times */
462 dftSortByFrame(inp);
463
464 /*
465 * Read following input files, if required
466 */
467 for(ii=2; ii<=input_nr; ii++) {
468 if(ii==2) fname=inputfile2;
469 else fname=inputfile3;
470
471 /* Make room for one more curve in input data */
472 ret=dftAddmem(inp, 1);
473 if(ret) {
474 if(status!=NULL) sprintf(status, "cannot allocate more memory");
475 dftEmpty(tis); dftEmpty(inp); return(4);
476 }
477
478 /* Read blood data */
479 dftInit(&tmpdft);
480 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", fname);
481 if(dftRead(fname, &tmpdft)) {
482 if(status!=NULL) sprintf(status, "cannot read '%s': %s", fname, dfterrmsg);
483 dftEmpty(tis); dftEmpty(inp); return(4);
484 }
485 if(tmpdft.frameNr<4) {
486 if(status!=NULL) sprintf(status, "%s contains too few samples", fname);
487 dftEmpty(tis); dftEmpty(inp); dftEmpty(&tmpdft); return(4);
488 }
489
490 /* Check and correct the sample time unit */
491 if(tis->timeunit==TUNIT_UNKNOWN) tis->timeunit=tmpdft.timeunit;
492 else if(tmpdft.timeunit==TUNIT_UNKNOWN) tmpdft.timeunit=tis->timeunit;
493 if(tmpdft.timeunit==TUNIT_UNKNOWN) {
494 fprintf(wfp, "Warning: blood sample time units not known.\n");
495 }
496 if(inp->timeunit!=tmpdft.timeunit &&
497 dftTimeunitConversion(&tmpdft, inp->timeunit)!=0) {
498 if(status!=NULL) sprintf(status, "two input data are in different time units");
499 dftEmpty(tis); dftEmpty(inp); dftEmpty(&tmpdft);
500 return(4);
501 }
502 /* Sort the data by increasing sample times */
503 dftSortByFrame(&tmpdft);
504
505 /* Copy to input data */
506 if(tmpdft.voiNr>1) {
507 fprintf(wfp, "Warning: using only first TAC in %s\n", fname);
508 tmpdft.voiNr=1;
509 }
510 if(loginfo!=NULL && verbose>1)
511 fprintf(loginfo, "interpolating %d samples into %d samples.\n",
512 tmpdft.frameNr, inp->frameNr);
513 ret=dftInterpolateInto(&tmpdft, inp, status, verbose);
514 if(ret) {
515 if(loginfo!=NULL && verbose>0)
516 fprintf(loginfo, "dftInterpolateInto() := %d\n", ret);
517 dftEmpty(tis); dftEmpty(inp); dftEmpty(&tmpdft); return(4);
518 }
519 /* Remove the originally read blood data */
520 dftEmpty(&tmpdft);
521
522 } // next input file
523
524 /* Set time unit to min */
525 if(loginfo!=NULL && verbose>1)fprintf(loginfo, "setting time units to min.\n");
526 ret=dftTimeunitConversion(tis, TUNIT_MIN); if(ret)
527 fprintf(wfp, "Warning: check that regional data times are in minutes.\n");
528 ret=dftTimeunitConversion(inp, TUNIT_MIN); if(ret)
529 fprintf(wfp, "Warning: check that input data times are in minutes.\n");
530
531 /*
532 * Check the input data
533 */
534 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "checking input data\n");
535 if(inp->frameNr<4) {
536 if(status!=NULL) sprintf(status, "%s contains too few samples", inputfile1);
537 dftEmpty(tis); dftEmpty(inp); return(4);
538 }
539 /* Check for NaN's */
540 ret=dft_nr_of_NA(inp); if(ret>0) {
541 if(status!=NULL) sprintf(status, "missing sample(s) in data");
542 dftEmpty(tis); dftEmpty(inp); return(4);
543 }
544 /* Check that input and tissue time ranges are about the same */
545 if(tis->x[tis->frameNr-1]>10.0*inp->x[inp->frameNr-1] ||
546 tis->x[tis->frameNr-1]<0.10*inp->x[inp->frameNr-1]) {
547 fprintf(wfp, "Warning: you might need to check the sample time units.\n");
548 }
549 /* Check and give a warning, if the first value is the highest */
550 for(fi=1, n=0, f=inp->voi[0].y[0]; fi<inp->frameNr; fi++)
551 if(inp->voi[0].y[fi]>=f) {f=inp->voi[0].y[fi]; n=fi;}
552 if(n<2) fprintf(wfp, "Warning: check the first input sample values.\n");
553
554 /* Check the tissue and blood TAC concentration units */
555 ret=dftUnitConversion(inp, petCunitId(tis->unit));
556 if(ret!=0) {fprintf(wfp, "Note: check the units of input and tissue data.\n");}
557
558 /*
559 * Check and set fit time length
560 */
561 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "checking and setting fit time length\n");
562 /* Set fit duration */
563 starttime=0; endtime=*fitdur;
564 *fitframeNr=fittime_from_dft(tis, &starttime, &endtime, &first, &last, verbose);
565 if(loginfo!=NULL && verbose>1) {
566 fprintf(loginfo, "tis.frameNr := %d\n", tis->frameNr);
567 fprintf(loginfo, "starttime := %g\n", starttime);
568 fprintf(loginfo, "endtime := %g\n", endtime);
569 fprintf(loginfo, "first := %d\n", first);
570 fprintf(loginfo, "last := %d\n", last);
571 fprintf(loginfo, "fitframeNr := %d\n", *fitframeNr);
572 }
573 *fitdur=endtime;
574 /* Check that input data does not end much_before fitdur */
575 if(inp->timetype==DFT_TIME_STARTEND) f=inp->x2[inp->frameNr-1];
576 else f=inp->x[inp->frameNr-1];
577 if(*fitdur>1.2*f) {
578 if(status!=NULL) sprintf(status, "input TAC is too short");
579 dftEmpty(inp); dftEmpty(tis); return(5);
580 }
581 /* Cut off too many input samples to make calculation faster */
582 f=*fitdur+1.0; // One minute extra to allow time delay correction
583 if(loginfo!=NULL && verbose>0) printf("Input TAC cutoff at %g min\n", f);
584 for(fi=0; fi<inp->frameNr; fi++) if(inp->x[fi]>f) break;
585 if(fi<inp->frameNr) fi++;
586 inp->frameNr=fi;
587 if(inp->frameNr<4) {
588 if(status!=NULL) sprintf(status, "too few samples in specified fit duration.\n");
589 dftEmpty(inp); dftEmpty(tis); return(5);
590 }
591 if(loginfo!=NULL && verbose>1) {
592 fprintf(loginfo, "dft.frameNr := %d\ninp.frameNr := %d\nfitdur := %g\n",
593 tis->frameNr, inp->frameNr, *fitdur);
594 fprintf(loginfo, "fitframeNr := %d\n", *fitframeNr);
595 }
596
597 if(status!=NULL) sprintf(status, "ok");
598 return 0;
599}
600/*****************************************************************************/
601
602/*****************************************************************************/
610 DFT *dft,
612 int tacindex,
614 double *minx,
616 double *maxx,
618 double *miny,
620 double *maxy,
622 int *mini,
624 int *maxi,
626 int *mins,
628 int *maxs,
630 int verbose
631) {
632 int ri, fi, i1, i2, s1, s2;
633 double x, x1, x2, y1, y2;
634 int n, runnh, maxrunnh, runns, maxrunns;
635 double ym;
636 int run1h, run2h, maxrun1h, maxrun2h, run1s, run2s, maxrun1s, maxrun2s;
637
638 if(verbose>0)
639 printf("dftRobustMinMaxTAC(dft, %d, minx, maxx, miny, maxy, mini, maxi, mins, maxs, %d)\n",
640 tacindex, verbose);
641
642 if(dft==NULL) return(1);
643 if(tacindex>=dft->voiNr) return(2);
644 if(dft->voiNr<1 || dft->frameNr<1) return(3);
645
646 /* One TAC at a time */
647 double list[dft->frameNr];
648 x1=x2=y1=y2=nan(""); i1=i2=s1=s2=0;
649 for(ri=0; ri<dft->voiNr; ri++) {
650 if(tacindex>=0 && ri!=tacindex) continue;
651 //fprintf(stderr, "Region: %s\n", dft->voi[ri].name);
652 /* Calculate median of y values */
653 for(fi=n=0; fi<dft->frameNr; fi++) {
654 if(isnan(dft->voi[ri].y[fi])) continue;
655 if(dft->timetype==DFT_TIME_STARTEND) {
656 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;}
657 else {if(isnan(dft->x[fi])) continue;}
658 list[n++]=dft->voi[ri].y[fi];
659 }
660 if(n<10) {
661 maxrunnh=maxrunns=dft->frameNr;
662 maxrun1h=maxrun1s=0;
663 maxrun2h=maxrun2s=dft->frameNr-1;
664 } else {
665 ym=dmedian(list, n);
666 //fprintf(stderr, "median := %g\n", ym);
667 /* Search the longest run of values which are larger/smaller than the median */
668 runnh=maxrunnh=run1h=run2h=maxrun1h=maxrun2h=0;
669 runns=maxrunns=run1s=run2s=maxrun1s=maxrun2s=0;
670 for(fi=0; fi<dft->frameNr; fi++) {
671 if(isnan(dft->voi[ri].y[fi])) continue;
672 if(dft->timetype==DFT_TIME_STARTEND) {
673 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;}
674 else {if(isnan(dft->x[fi])) continue;}
675 /* max */
676 if(dft->voi[ri].y[fi]>ym) {
677 runnh++; if(runnh==1) {run1h=run2h=fi;} else {run2h=fi;}
678 } else {
679 if(runnh>maxrunnh) {maxrunnh=runnh; maxrun1h=run1h; maxrun2h=run2h;}
680 runnh=0;
681 }
682 /* min */
683 if(dft->voi[ri].y[fi]<ym) {
684 runns++; if(runns==1) {run1s=run2s=fi;} else {run2s=fi;}
685 } else {
686 if(runns>maxrunns) {maxrunns=runns; maxrun1s=run1s; maxrun2s=run2s;}
687 runns=0;
688 }
689 }
690 /* Get range also from the end part */
691 if(runnh>maxrunnh) {maxrunnh=runnh; maxrun1h=run1h; maxrun2h=run2h;}
692 if(runns>maxrunns) {maxrunns=runns; maxrun1s=run1s; maxrun2s=run2s;}
693 /* If longest range includes just one sample, then take the whole range */
694 if(maxrunnh<2) {maxrunnh=dft->frameNr; maxrun1h=0; maxrun2h=dft->frameNr-1;}
695 if(maxrunns<2) {maxrunns=dft->frameNr; maxrun1s=0; maxrun2s=dft->frameNr-1;}
696 }
697 if(verbose>12) {
698 fprintf(stderr, "longest run for max: %g - %g\n", dft->x[maxrun1h], dft->x[maxrun2h]);
699 fprintf(stderr, "longest run for min: %g - %g\n", dft->x[maxrun1s], dft->x[maxrun2s]);
700 }
701 /* Inside the range, search for max */
702 for(fi=maxrun1h; fi<=maxrun2h; fi++) {
703 if(isnan(dft->voi[ri].y[fi])) continue;
704 if(dft->timetype==DFT_TIME_STARTEND) {
705 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;
706 x=0.5*(dft->x1[fi]+dft->x2[fi]);
707 } else {
708 if(isnan(dft->x[fi])) continue;
709 x=dft->x[fi];
710 }
711 if(isnan(y2) || y2<dft->voi[ri].y[fi]) {y2=dft->voi[ri].y[fi]; i2=ri; x2=x; s2=fi;}
712 }
713 /* Inside the range, search for min */
714 for(fi=maxrun1s; fi<=maxrun2s; fi++) {
715 if(isnan(dft->voi[ri].y[fi])) continue;
716 if(dft->timetype==DFT_TIME_STARTEND) {
717 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;
718 x=0.5*(dft->x1[fi]+dft->x2[fi]);
719 } else {
720 if(isnan(dft->x[fi])) continue;
721 x=dft->x[fi];
722 }
723 if(isnan(y1) || y1>dft->voi[ri].y[fi]) {y1=dft->voi[ri].y[fi]; i1=ri; x1=x; s1=fi;}
724 }
725
726 } /* next TAC */
727
728 if(minx!=NULL) {if(isnan(x1)) return(11); else *minx=x1;}
729 if(maxx!=NULL) {if(isnan(x2)) return(12); else *maxx=x2;}
730 if(miny!=NULL) {if(isnan(y1)) return(13); else *miny=y1;}
731 if(maxy!=NULL) {if(isnan(y2)) return(14); else *maxy=y2;}
732 if(mini!=NULL) {if(isnan(y1)) return(13); else *mini=i1;}
733 if(maxi!=NULL) {if(isnan(y2)) return(14); else *maxi=i2;}
734 if(mins!=NULL) {if(isnan(y1)) return(13); else *mins=s1;}
735 if(maxs!=NULL) {if(isnan(y2)) return(14); else *maxs=s2;}
736 return(0);
737}
738/*****************************************************************************/
739
740/*****************************************************************************/
749 DFT *dft,
751 int index,
753 int verbose,
756 char *status
757) {
758 int ri, fi, ret, mini, maxi, starti, warn=0;
759 double minx, maxx, miny, maxy, startx, dif, lowesty;
760
761 if(verbose>0) printf("dftVerifyPeak(dft, %d, %d)\n", index, verbose);
762 /* Check the arguments */
763 if(status!=NULL) strcpy(status, "program error");
764 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return 1;
765 if(index>=dft->voiNr) return 1;
766
767 /* If less than 3 samples, then this can not be suitable as input TAC */
768 if(dft->frameNr<3) {
769 if(status!=NULL) strcpy(status, "too few samples");
770 return 2;
771 }
772
773 /* Make sure data is sorted by increasing sample time */
774 dftSortByFrame(dft);
775
776 /* Go through all TACs that are requested */
777 for(ri=0; ri<dft->voiNr; ri++) {
778 if(index>=0 && index!=ri) continue;
779 if(verbose>1) printf("checking region %d: %s\n", 1+ri, dft->voi[ri].name);
780
781 /* Get the TAC min and max */
782 ret=dftMinMaxTAC(dft, ri, &minx, &maxx, &miny, &maxy, NULL, NULL, &mini, &maxi);
783 if(ret!=0) {
784 if(verbose>0) printf("Error %d in dftMinMaxTAC()\n", ret);
785 if(status!=NULL) strcpy(status, "invalid TAC");
786 return 1;
787 }
788
789 /* Check that there are no big negative values */
790 if(maxy<=0.0) {
791 if(verbose>0) printf("TAC has no positive values.\n");
792 if(status!=NULL) strcpy(status, "no positive TAC values");
793 return 2;
794 }
795 if(miny<0.0) {
796 if((-miny)>0.40*maxy) {
797 if(verbose>0) printf("TAC has high negative value(s).\n");
798 if(status!=NULL) strcpy(status, "too high negative TAC values");
799 return 2;
800 }
801 if((-miny)>0.02*maxy) {
802 if(verbose>1) printf("TAC has negative value(s).\n");
803 warn++;
804 }
805 }
806
807 /* Get the first sample time, considering missing values */
808 startx=1.0E+10; starti=dft->frameNr-1;
809 for(fi=0; fi<dft->frameNr; fi++) {
810 if(isnan(dft->voi[ri].y[fi])) continue;
811 if(dft->timetype==DFT_TIME_STARTEND) {
812 if(isnan(dft->x1[fi])) continue;
813 if(isnan(dft->x2[fi])) continue;
814 startx=dft->x1[fi]; starti=fi; break;
815 } else {
816 if(isnan(dft->x[fi])) continue;
817 startx=dft->x[fi]; starti=fi; break;
818 }
819 }
820 if(verbose>2) printf("first time sample at %g\n", startx);
821
822 /* If the first sample is the peak, then check that sample time is not too late */
823 if(maxi==starti) {
824 if(verbose>2) printf("Peak at the first sample.\n");
825 if(status!=NULL) strcpy(status, "input TAC should start at time zero");
826 /* Calculate peak time to initial sample frequency ratio */
827 if(dft->timetype==DFT_TIME_STARTEND) {
828 dif=dft->x1[maxi]/(dft->x2[maxi]-dft->x1[maxi]);
829 } else {
830 //dif=dft->x[maxi]/(dft->x[maxi+1]-dft->x[maxi]);
831 for(fi=maxi+1; fi<dft->frameNr; fi++)
832 if(!isnan(dft->x[fi]) && dft->x[fi]>dft->x[maxi]) break;
833 if(fi==dft->frameNr) dif=1.0E+10;
834 else dif=dft->x[maxi]/(dft->x[fi]-dft->x[maxi]);
835 }
836 if(dif>0.3) {
837 if(verbose>0) printf("Peak at the first sample which is not at zero.\n");
838 if(verbose>1) printf("dif := %g\n", dif);
839 }
840 if(dif>5.0) {
841 return 2;
842 } else if(dif>1.0) {
843 /* Not bad, if peak is still much higher than tale */
844 if(maxy>20.*miny) warn++; else return 2;
845 if(verbose>1) printf("good peak/tail -ratio\n");
846 } else if(dif>0.3) warn++;
847 }
848
849 /* Search the lowest value before the peak */
850 lowesty=dft->voi[ri].y[starti];
851 for(fi=starti+1; fi<maxi; fi++)
852 if(dft->voi[ri].y[fi]<lowesty) lowesty=dft->voi[ri].y[fi];
853 if(verbose>2) printf("lowest value before peak: %g\n", lowesty);
854
855 /* If first sample is closer to peak and relatively high, then that is or may be a problem */
856 if(maxi>starti && startx>0.001 && startx>0.75*maxx) {
857 if(dft->voi[ri].y[starti]>0.66*maxy && lowesty>0.05*maxy && mini>maxi) {
858 if(verbose>0) printf("The first sample is relatively late and high.\n");
859 if(status!=NULL) strcpy(status, "input TAC should start at time zero");
860 if(verbose>2) {
861 printf("startx=%g\n", startx);
862 printf("starty=%g\n", dft->voi[ri].y[starti]);
863 printf("maxx=%g\n", maxx);
864 printf("maxy=%g\n", maxy);
865 }
866 return 2;
867 }
868 }
869 if(maxi>starti && startx>0.001 && startx>0.5*maxx) {
870 if(dft->voi[ri].y[starti]>0.5*maxy && lowesty>0.05*maxy && mini>maxi) {
871 if(verbose>1) printf("The first sample is relatively late and high.\n");
872 warn++;
873 }
874 }
875 if(verbose>5) {
876 printf("startx=%g\n", startx);
877 printf("starty=%g\n", dft->voi[ri].y[starti]);
878 printf("maxx=%g\n", maxx);
879 printf("maxy=%g\n", maxy);
880 }
881
882 /* If peak is not much higher than lowest value, that may indicate
883 a problem */
884 if(maxy<1.5*miny) {
885 if(verbose>0) printf("TAC does not have a clear peak.\n");
886 if(status!=NULL) strcpy(status, "input TAC peak missing");
887 return 2;
888 }
889 if(maxy<5.0*miny) {
890 if(verbose>1) printf("TAC does not have a clear peak.\n");
891 warn++;
892 }
893
894 } // next TAC
895
896 if(verbose>0 && warn>0) printf("%d warning(s)\n", warn);
897 if(warn>0) {
898 if(status!=NULL) strcpy(status, "input TAC is not optimal");
899 return -1;
900 }
901 if(status!=NULL) strcpy(status, "input TAC ok");
902 return 0;
903}
904/*****************************************************************************/
905
906/*****************************************************************************/
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 dftSortByFrame(DFT *dft)
Definition dft.c:1169
int dftSelectBestReference(DFT *dft)
Definition dft.c:314
int dftDelete(DFT *dft, int voi)
Definition dft.c:538
void dftEmpty(DFT *data)
Definition dft.c:20
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftSelectRegions(DFT *dft, char *region_name, int reset)
Definition dft.c:285
int dftReadinput(DFT *input, DFT *tissue, char *filename, int *filetype, double *ti1, double *ti2, int verifypeak, char *status, int verbose)
Definition dftinput.c:25
int dftVerifyPeak(DFT *dft, int index, int verbose, char *status)
Definition dftinput.c:747
int dftRobustMinMaxTAC(DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs, int verbose)
Definition dftinput.c:608
int dftReadReference(DFT *tissue, char *filename, int *filetype, int *ref_index, char *status, int verbose)
Definition dftinput.c:204
int dftReadModelingData(char *tissuefile, char *inputfile1, char *inputfile2, char *inputfile3, double *fitdur, int *fitframeNr, DFT *tis, DFT *inp, FILE *loginfo, int verbose, char *status)
Definition dftinput.c:342
int dftInterpolate(DFT *input, DFT *tissue, DFT *output, char *status, int verbose)
Definition dftint.c:162
int dftInterpolateInto(DFT *inp, DFT *tis, char *status, int verbose)
Definition dftint.c:281
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int dftFormat(char *fname)
Definition dftio.c:422
int dftUnitConversion(DFT *dft, int dunit)
Definition dftunit.c:25
int dftTimeunitConversion(DFT *dft, int tunit)
Definition dftunit.c:119
int fittime_from_dft(DFT *dft, double *startTime, double *endTime, int *first, int *last, int verbose)
Definition fittime.c:16
int petintegral(double *x1, double *x2, double *y, int nr, double *ie, double *iie)
Integrate PET TAC data to frame mid times.
Definition integr.c:771
int petintegrate(double *x1, double *x2, double *y, int nr, double *newyi, double *newyii)
Definition integr.c:334
int integrate(double *x, double *y, int nr, double *yi)
Definition integr.c:271
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
Definition integr.c:28
#define DFT_FORMAT_FIT
#define DFT_TIME_STARTEND
#define DFT_FORMAT_UNKNOWN
int petCunitId(const char *unit)
Definition petunits.c:74
double dmedian(double *data, int n)
Definition median.c:48
Header file for libtpcmodext.
int timetype
Voi * voi
int timeunit
double * x1
int voiNr
double * x2
int frameNr
double * x
char unit[MAX_UNITS_LEN+1]
double * y2
char sw
double * y
char name[MAX_REGIONNAME_LEN+1]
double * y3