TPCCLIB
Loading...
Searching...
No Matches
dftinput.c File Reference

Procedures for handling model input data. More...

#include "libtpcmodext.h"

Go to the source code of this file.

Functions

int dftReadinput (DFT *input, DFT *tissue, char *filename, int *filetype, double *ti1, double *ti2, int verifypeak, char *status, int verbose)
 
int dftReadReference (DFT *tissue, char *filename, int *filetype, int *ref_index, char *status, int verbose)
 
int dftReadModelingData (char *tissuefile, char *inputfile1, char *inputfile2, char *inputfile3, double *fitdur, int *fitframeNr, DFT *tis, DFT *inp, FILE *loginfo, int verbose, char *status)
 
int dftRobustMinMaxTAC (DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs, int verbose)
 
int dftVerifyPeak (DFT *dft, int index, int verbose, char *status)
 

Detailed Description

Procedures for handling model input data.

Author
Vesa Oikonen

Definition in file dftinput.c.

Function Documentation

◆ dftReadinput()

int dftReadinput ( DFT * input,
DFT * tissue,
char * filename,
int * filetype,
double * ti1,
double * ti2,
int verifypeak,
char * status,
int verbose )

Read DFT format input TAC data to match the time frames in the specified tissue DFT file. Instead of input filename, a reference region name can be given: then all the matching tacs (based on roi names) are moved from the roi data to the input data, with the best match as first tac. Input data is interpolated (if necessary) and also integrated to y2[]. Input time and concentration units are tried to be converted to be the same as in tissue data.

Returns
Returns 0 if successful, and >0 in case of an error, and specifically 101 in case input TAC is not valid.
See also
dftReadReference, dftRead, dftReadModelingData, dftVerifyPeak, imgReadModelingData
Parameters
inputInput data, previous contents are cleared.
tissuePET data containing frames and possible input regions.
filenameInput data filename, or region name in PET data.
filetypeType of input, as found out here; 1 and 2 =tac, 3=fit, 5=region name; enter NULL, if not needed.
ti1First time of input data before interpolation (in tissue time units); use this to check that required time range was measured; NULL if not needed.
ti2Last time of input data before interpolation (in tissue time units); use this to check that required time range was measured; NULL if not needed.
verifypeakSet to <>0 to verify that input TAC does not start too late and has decent peak to provide reliable AUC0-T.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 25 of file dftinput.c.

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}
void dftInit(DFT *data)
Definition dft.c:38
int dftdup(DFT *dft1, DFT *dft2)
Definition dft.c:655
int dftMovevoi(DFT *dft, int from, int to)
Definition dft.c:508
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 dftSelectRegions(DFT *dft, char *region_name, int reset)
Definition dft.c:285
int dftVerifyPeak(DFT *dft, int index, int verbose, char *status)
Definition dftinput.c:747
int dftInterpolate(DFT *input, DFT *tissue, DFT *output, char *status, int verbose)
Definition dftint.c:162
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 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 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
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

◆ dftReadModelingData()

int dftReadModelingData ( char * tissuefile,
char * inputfile1,
char * inputfile2,
char * inputfile3,
double * fitdur,
int * fitframeNr,
DFT * tis,
DFT * inp,
FILE * loginfo,
int verbose,
char * status )

Read tissue and input data for modeling. Time units are converted to min and input calibration units to units of tissue data. Input data is NOT interpolated to tissue times. If input data extends much further than fit duration, the last part is removed to save computation time in simulations. Input data is verified not to end too early, and not to start too late.

Returns
Returns 0 when successful, otherwise a non-zero value.
See also
dftReadReference, dftRead, dftReadinput, imgReadModelingData
Parameters
tissuefileTissue data filename; one time sample is sufficient here.
inputfile11st input data filename.
inputfile22nd input data filename (or NULL if only not needed).
inputfile33rd input data filename (or NULL if only not needed).
fitdurFit duration (in minutes); shortened if longer than tissue data.
fitframeNrNr of time frames (samples) in tissue data that are inside fitdur will be written here.
tisPointer to initiated DFT into which tissue data will be written.
inpPointer to initiated DFT into which input data (plasma and/or blood) will be written.
loginfoGive file pointer (for example stdout) where log information is printed; NULL if not needed; warnings will be printed in stderr anyway.
verboseVerbose level; if zero, then only warnings are printed into stderr.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 342 of file dftinput.c.

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}
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 dftSortByFrame(DFT *dft)
Definition dft.c:1169
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftInterpolateInto(DFT *inp, DFT *tis, char *status, int verbose)
Definition dftint.c:281
int fittime_from_dft(DFT *dft, double *startTime, double *endTime, int *first, int *last, int verbose)
Definition fittime.c:16

◆ dftReadReference()

int dftReadReference ( DFT * tissue,
char * filename,
int * filetype,
int * ref_index,
char * status,
int verbose )

Read DFT format reference region TAC data and add it into DFT already containing other tissue TACs, if reference region TAC(s) are be given in a separate file. Alternatively the reference region name can be given, which will then be selected from existing tissue TACs. Reference TACs are marked in DFT with sw=2 (best name match) or sw=1; if reference region file contains several TACs then the one which contains name 'mean' or 'avg' or has shortest total name length is given value sw=2. When necessary, reference data is interpolated and units converted to match the existing tissue DFT. Reference TAC is also integrated into y2[].

Returns
Returns the number of reference TACs, and <=0 in case of an error.
See also
dftReadinput, dftRead, dftReadModelingData, imgReadModelingData
Parameters
tissuePET data containing existing tissue TACs, possibly also ref regions.
filenameReference TAC filename, or region name in previous data.
filetypeType of input, as found out here; 1 and 2 =tac, 3=fit, 5=region name; enter NULL, if not needed.
ref_indexIndex of the best reference region; enter NULL if not needed.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 204 of file dftinput.c.

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}
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

◆ dftRobustMinMaxTAC()

int dftRobustMinMaxTAC ( DFT * dft,
int tacindex,
double * minx,
double * maxx,
double * miny,
double * maxy,
int * mini,
int * maxi,
int * mins,
int * maxs,
int verbose )

Robust search of the min and max values of DFT TAC data. Data may contain NaN's, and individual outliers are not taken as min or max.

See also
dftMinMaxTAC, dftMinMax
Returns
Returns 0 if successful.
Parameters
dftPointer to the DFT TAC data to search.
tacindexIndex of the only TAC which is searched for min and max; <0 if all.
minxPointer to X at TAC min; set to NULL if not needed.
maxxPointer to X at TAC max; set to NULL if not needed.
minyPointer to min Y; set to NULL if not needed.
maxyPointer to max Y; set to NULL if not needed.
miniIndex of min TAC; set to NULL if not needed.
maxiIndex of max TAC; set to NULL if not needed.
minsIndex of min sample; set to NULL if not needed.
maxsIndex of max sample; set to NULL if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 608 of file dftinput.c.

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}
double dmedian(double *data, int n)
Definition median.c:48

◆ dftVerifyPeak()

int dftVerifyPeak ( DFT * dft,
int index,
int verbose,
char * status )

Verify that specified (input) TAC contains peak and that it does not start too late to get reliable estimate of AUC.

Returns
Returns 0 in case data is suitable, < 0 if there may be a problem, 1 in case of an error, and 2 if peak seems to be missed.
See also
dftReadModelingData, imgReadModelingData
Parameters
dftPointer to TAC data which is verified.
indexIndex of TAC to be verified; <0 in case all are (separately) verified.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 747 of file dftinput.c.

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}
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

Referenced by dftFixPeak(), dftReadinput(), and imgReadModelingData().