TPCCLIB
Loading...
Searching...
No Matches
imginput.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6
7/*****************************************************************************/
8#include "libtpcmodext.h"
9/*****************************************************************************/
10
11/*****************************************************************************/
26 char *petfile,
33 char *siffile,
35 char *inputfile1,
37 char *inputfile2,
39 char *inputfile3,
42 double *fitdur,
45 int *fitframeNr,
47 IMG *img,
51 DFT *inp,
55 DFT *iinp,
58 int verifypeak,
61 FILE *loginfo,
63 int verbose,
66 char *status
67) {
68 int ret, fi, n, first, last, ii, input_nr=0;
69 DFT tmpdft, dft;
70 SIF sif;
71 double f, starttime, endtime;
72 FILE *wfp;
73 char *fname, tmp[512];
74
75
76 if(loginfo!=NULL && verbose>0) {
77 fprintf(loginfo, "imgReadModelingData(\n");
78 fprintf(loginfo, " %s,\n", petfile);
79 fprintf(loginfo, " %s,\n", inputfile1);
80 fprintf(loginfo, " %s,\n", inputfile2);
81 fprintf(loginfo, " %s,\n", inputfile3);
82 fprintf(loginfo, " %g,\n", *fitdur);
83 fprintf(loginfo, " *fitframeNr, *tis, *inp, *iinp *loginfo, %d, *status\n", verbose);
84 fprintf(loginfo, ")\n");
85 }
86 /* Check the function input */
87 if(status!=NULL) sprintf(status, "program error");
88 if(img==NULL || (inp==NULL && iinp==NULL)) return -1;
89 if(petfile==NULL || strlen(petfile)<1) return -2;
90 ret=0;
91 if(inputfile1==NULL || strlen(inputfile1)<1) return -3; else input_nr++;
92 if(inputfile2!=NULL && strlen(inputfile2)>0) input_nr++;
93 if(inputfile3!=NULL && strlen(inputfile3)>0) {
94 if(input_nr<2) return -4;
95 input_nr++;
96 }
97 if(fitframeNr==NULL || fitdur==NULL) return -5;
98 if(status!=NULL) sprintf(status, "arguments validated");
99 /* Warnings will be printed into stderr */
100 wfp=stderr;
101
102 /* Check that input file(s) exist, because image is read first, and it might take a while */
103 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "checking access to input files\n");
104 if(access(inputfile1, 0) == -1) {
105 sprintf(tmp, "cannot read '%s'", inputfile1);
106 if(status!=NULL) strcpy(status, tmp);
107 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
108 else fprintf(wfp, "Error: %s\n", tmp);
109 return(1);
110 }
111 for(ii=2; ii<=input_nr; ii++) {
112 if(ii==2) fname=inputfile2; else fname=inputfile3;
113 if(access(fname, 0) == -1) {
114 sprintf(tmp, "cannot read '%s'", fname);
115 if(status!=NULL) strcpy(status, tmp);
116 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
117 else fprintf(wfp, "Error: %s\n", tmp);
118 return(1);
119 }
120 }
121
122 /* Delete any previous data and initiate temp data */
123 dftEmpty(inp); dftEmpty(iinp); imgEmpty(img);
124
125
126 /*
127 * Read PET image
128 */
129 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading image %s\n", petfile);
130 imgInit(img);
131 ret=imgRead(petfile, img); fflush(stderr); fflush(stdout);
132 if(ret) {
133 sprintf(tmp, "cannot read '%s': %s", petfile, img->statmsg);
134 if(status!=NULL) strcpy(status, tmp);
135 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
136 else fprintf(wfp, "Error: %s\n", tmp);
137 if(loginfo!=NULL) fprintf(loginfo, "imgRead(%s, img) := %d\n", petfile, ret);
138 return(2);
139 }
140 /* Check if PET data is raw or image */
141 if(img->type!=IMG_TYPE_IMAGE) {
142 sprintf(tmp, "%s is not an image.\n", petfile);
143 if(status!=NULL) strcpy(status, tmp);
144 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
145 else fprintf(wfp, "Error: %s\n", tmp);
146 imgEmpty(img); return(3);
147 }
148 if(loginfo!=NULL && verbose>2)
149 fprintf(loginfo, "image contains %d frames and %d planes.\n", img->dimt, img->dimz);
150
151 /* Read SIF, if specified */
152 if(siffile!=NULL && siffile[0]) {
153 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading SIF %s\n", siffile);
154 sifInit(&sif);
155 ret=sifRead(siffile, &sif);
156 if(ret) {
157 sprintf(tmp, "cannot read '%s': %s", siffile, siferrmsg);
158 if(status!=NULL) strcpy(status, tmp);
159 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
160 else fprintf(wfp, "Error: %s\n", tmp);
161 imgEmpty(img); return(4);
162 }
163 /* Get isotope from SIF, if available */
164 {
165 double hl;
167 if(hl>0.0) {
168 img->isotopeHalflife=60.0*hl;
169 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "isotope code read from %s\n", siffile);
170 }
171 }
172 /* Get frame times from SIF if not available in image */
173 if(!imgExistentTimes(img) && img->dimt<=sif.frameNr) {
174 for(fi=0; fi<img->dimt; fi++) {
175 img->start[fi]=sif.x1[fi]; img->end[fi]=sif.x2[fi];
176 img->mid[fi]=0.5*(sif.x1[fi]+sif.x2[fi]);
177 }
178 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "image frame times read from %s\n", siffile);
179 }
180 sifEmpty(&sif);
181 }
182
183 /* Check that image frame times are available */
184 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "checking image contents\n");
185 if(!imgExistentTimes(img)) {
186 strcpy(tmp, "image frame times not available");
187 if(status!=NULL) strcpy(status, tmp);
188 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
189 else fprintf(wfp, "Error: %s\n", tmp);
190 imgEmpty(img); return(5);
191 }
192 /* Make sure that there is no overlap in image frames */
193 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "checking frame overlap in %s\n", petfile);
194 ret=imgDeleteFrameOverlap(img);
195 if(ret) {
196 strcpy(tmp, "image has overlapping frame times");
197 if(status!=NULL) strcpy(status, tmp);
198 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
199 else fprintf(wfp, "Error: %s\n", tmp);
200 imgEmpty(img); return(5);
201 }
202 /* Check fit end time with the PET image */
203 if(!(*fitdur>0.0)) *fitdur=1.0E+99;
204 else if(*fitdur<1.0E+10) *fitdur*=60.0; // fit time must be in sec
205 *fitframeNr=fittime_from_img(img, fitdur, verbose-2);
206 if(*fitframeNr<1 || *fitdur<=3.5) {
207 strcpy(tmp, "image has no data in fit time range");
208 if(status!=NULL) strcpy(status, tmp);
209 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
210 else fprintf(wfp, "Error: %s\n", tmp);
211 imgEmpty(img); return(5);
212 }
213 *fitdur/=60.0; // back to minutes
214 if(loginfo!=NULL && verbose>3) {
215 fprintf(loginfo, "fittimeFinal := %g min\n", *fitdur);
216 fprintf(loginfo, "fitframeNr := %d\n", *fitframeNr);
217 }
218
219
220 /*
221 * Read first input data
222 */
223 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", inputfile1);
224 dftInit(&dft);
225 if(dftRead(inputfile1, &dft)) {
226 sprintf(tmp, "cannot read '%s': %s", inputfile1, dfterrmsg);
227 if(status!=NULL) strcpy(status, tmp);
228 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
229 else fprintf(wfp, "Error: %s\n", tmp);
230 imgEmpty(img); return(11);
231 }
232 /* Check TAC nr */
233 if(dft.voiNr>1) {
234 if(verbose>0) {
235 strcpy(tmp, "only first TAC is used as input");
236 if(loginfo!=NULL) fprintf(loginfo, "Warning: %s.\n", tmp);
237 else fprintf(wfp, "Warning: %s.\n", tmp);
238 }
239 dft.voiNr=1;
240 }
241 /* check if file contains NAs (missing values) */
242 if(dft_nr_of_NA(&dft)>0) {
243 strcpy(tmp, "missing values in input file");
244 if(status!=NULL) strcpy(status, tmp);
245 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
246 else fprintf(wfp, "Error: %s.\n", tmp);
247 imgEmpty(img); dftEmpty(&dft); return(12);
248 }
249 /* Check the concentration units */
250 ret=cunit_check_dft_vs_img(&dft, img, tmp, verbose-2);
251 if(ret==0) {
252 if(loginfo!=NULL && verbose>3) fprintf(loginfo, "%s\n", tmp);
253 } else if(ret<0) {
254 fprintf(wfp, "Warning: %s\n", tmp);
255 } else {
256 if(status!=NULL) strcpy(status, tmp);
257 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
258 else fprintf(wfp, "Error: %s.\n", tmp);
259 imgEmpty(img); dftEmpty(&dft); return(13);
260 }
261 if(verbose>3)
262 printf("input time range := %g - %g %s\n",
263 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
264 /* Set time unit to sec like in IMG */
265 if(dft.timeunit==TUNIT_UNKNOWN) {
266 if(dftEndtime(&dft)<0.2*imgEndtime(img)) dft.timeunit=TUNIT_MIN;
267 else dft.timeunit=TUNIT_SEC;
268 fprintf(wfp, "Warning: assuming that times are in %s in %s\n",
269 petTunit(dft.timeunit), inputfile1);
270 }
271 /* Set time unit to sec like in IMG */
272 ret=dftTimeunitConversion(&dft, TUNIT_SEC);
273 if(verbose>1)
274 printf("input time range := %g - %g %s\n",
275 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
276
277 /* Verify the peak if requested; only for the first input TAC, because
278 for example metabolite TAC may not show bolus shape */
279 if(verifypeak!=0) {
280 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "verifying input peak\n");
281 ret=dftVerifyPeak(&dft, 0, verbose-5, tmp);
282 if(ret>0) {
283 if(status!=NULL) strcpy(status, tmp);
284 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
285 else fprintf(wfp, "Error: %s.\n", tmp);
286 imgEmpty(img); dftEmpty(&dft); return(14);
287 }
288 }
289 if(verbose>5)
290 printf("input time range := %g - %g %s\n",
291 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
292
293
294 /*
295 * Read following input files, if required
296 */
297 dftInit(&tmpdft);
298 for(ii=2; ii<=input_nr; ii++) {
299 if(ii==2) fname=inputfile2; else fname=inputfile3;
300
301 /* Make room for one more curve in input data */
302 ret=dftAddmem(&dft, 1);
303 if(ret) {
304 strcpy(tmp, "cannot allocate more memory");
305 if(status!=NULL) strcpy(status, tmp);
306 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
307 else fprintf(wfp, "Error: %s\n", tmp);
308 imgEmpty(img); dftEmpty(&dft); return(15);
309 }
310 /* Read input TAC */
311 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", fname);
312 if(dftRead(fname, &tmpdft)) {
313 sprintf(tmp, "cannot read '%s': %s", fname, dfterrmsg);
314 if(status!=NULL) strcpy(status, tmp);
315 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
316 else fprintf(wfp, "Error: %s\n", tmp);
317 imgEmpty(img); dftEmpty(&dft); return(16);
318 }
319 /* Check TAC nr */
320 if(tmpdft.voiNr>1) {
321 if(verbose>0) {
322 strcpy(tmp, "only first TAC is used as input");
323 if(loginfo!=NULL) fprintf(loginfo, "Warning: %s.\n", tmp);
324 else fprintf(wfp, "Warning: %s.\n", tmp);
325 }
326 dft.voiNr=1;
327 }
328 /* check if file contains NAs (missing values) */
329 if(dft_nr_of_NA(&tmpdft)>0) {
330 strcpy(tmp, "missing values in input file");
331 if(status!=NULL) strcpy(status, tmp);
332 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
333 else fprintf(wfp, "Error: %s\n", tmp);
334 imgEmpty(img); dftEmpty(&dft); dftEmpty(&tmpdft); return(17);
335 }
336 /* Check and correct the sample time unit */
337 if(tmpdft.timeunit==TUNIT_UNKNOWN) {
338 if(dftEndtime(&tmpdft)<0.2*imgEndtime(img)) tmpdft.timeunit=TUNIT_MIN;
339 else tmpdft.timeunit=TUNIT_SEC;
340 fprintf(wfp, "Warning: assuming that times are in %s in %s\n",
341 petTunit(tmpdft.timeunit), fname);
342 }
343 dftTimeunitConversion(&tmpdft, dft.timeunit);
344 /* Check the concentration units */
345 ret=cunit_check_dft_vs_img(&tmpdft, img, tmp, verbose-2);
346 if(ret==0) {
347 if(loginfo!=NULL && verbose>3) fprintf(loginfo, "%s\n", tmp);
348 } else if(ret<0) {
349 fprintf(wfp, "Warning: %s\n", tmp);
350 } else {
351 if(status!=NULL) strcpy(status, tmp);
352 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
353 else fprintf(wfp, "Error: %s\n", tmp);
354 imgEmpty(img); dftEmpty(&dft); dftEmpty(&tmpdft); return(18);
355 }
356 /* Copy to input data */
357 if(loginfo!=NULL && verbose>1)
358 fprintf(loginfo, "interpolating %d samples into %d samples.\n", tmpdft.frameNr, dft.frameNr);
359 ret=dftInterpolateInto(&tmpdft, &dft, tmp, verbose);
360 if(ret) {
361 if(loginfo!=NULL) fprintf(loginfo, "dftInterpolateInto() := %d\n", ret);
362 if(status!=NULL) strcpy(status, tmp);
363 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
364 else fprintf(wfp, "Error: %s\n", tmp);
365 imgEmpty(img); dftEmpty(&dft); dftEmpty(&tmpdft); return(19);
366 }
367 /* Remove the originally read input data */
368 dftEmpty(&tmpdft);
369
370 } // next input file
371 if(verbose>10)
372 printf("input time range := %g - %g %s\n",
373 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
374
375
376 /*
377 * Check and set input data range vs fit time length
378 */
379 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "checking and setting input sample time range\n");
380 /* Check that input data does not end _much_ before fitdur;
381 dftInterpolateForIMG() below tests this again. */
382 starttime=0; endtime=*fitdur; // start and end times always in min
383 n=fittime_from_dft(&dft, &starttime, &endtime, &first, &last, verbose-1);
384 if(loginfo!=NULL && verbose>2) {
385 fprintf(loginfo, "starttime := %g min\n", starttime);
386 fprintf(loginfo, "endtime := %g min\n", endtime);
387 fprintf(loginfo, "sample_nr := %d\n", n);
388 }
389 if(*fitdur>1.5*endtime && (*fitdur-endtime)>0.15) {
390 strcpy(tmp, "input TAC is too short");
391 if(status!=NULL) strcpy(status, tmp);
392 else if(verbose>0) fprintf(wfp, "Error: %s\n", tmp);
393 imgEmpty(img); dftEmpty(&dft); return(21);
394 }
395#if(0)
396 /* Do NOT test this here! It would prevent using this function in
397 reading steady-state studies etc */
398 if(n<4) {
399 strcpy(tmp, "too few input samples in specified fit duration");
400 if(status!=NULL) strcpy(status, tmp);
401 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
402 else fprintf(wfp, "Error: %s\n", tmp);
403 imgEmpty(img); dftEmpty(&dft); return(22);
404 }
405#endif
406 /* Cut off too many input samples to make calculation faster */
407 if(verbose>10) {
408 printf("input time range := %g - %g %s\n",
409 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
410 printf("fitdur := %g min\n", *fitdur);
411 }
412 f=*fitdur*60.0+60.0; // add 60 s to allow time delay correction
413 if(dftEndtime(&dft)>f) {
414 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "Input TAC cutoff at %g sec\n", f);
415 for(fi=0; fi<dft.frameNr; fi++) if(dft.x[fi]>f) break;
416 if(fi<dft.frameNr) fi++;
417 dft.frameNr=fi;
418 }
419 if(verbose>10) printf("input time range := %g - %g %s\n",
420 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
421
422 /* Copy input data to given pointer, if required */
423 if(inp!=NULL) {
424 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "copying input TAC\n");
425 ret=dftdup(&dft, inp);
426 if(ret!=0) {
427 strcpy(tmp, "cannot copy TAC contents");
428 if(status!=NULL) strcpy(status, tmp);
429 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
430 else fprintf(wfp, "Error: %s\n", tmp);
431 imgEmpty(img); dftEmpty(&dft); return(31);
432 }
433 }
434
435 /* Interpolate input data to given pointer, if required */
436 if(iinp!=NULL) {
437 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "interpolating input TAC\n");
438 ret=dftInterpolateForIMG(&dft, img, *fitframeNr, iinp, NULL, NULL, verbose, tmp);
439 if(ret!=0) {
440 if(status!=NULL) strcpy(status, tmp);
441 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
442 else fprintf(wfp, "Error: %s\n", tmp);
443 imgEmpty(img); dftEmpty(&dft); return(33);
444 }
445 }
446
447 dftEmpty(&dft);
448 if(status!=NULL) sprintf(status, "ok");
449 return(0);
450}
451/*****************************************************************************/
452
453/*****************************************************************************/
void dftInit(DFT *data)
Definition dft.c:38
int dftdup(DFT *dft1, DFT *dft2)
Definition dft.c:655
char dfterrmsg[64]
Definition dft.c:6
int dftAddmem(DFT *dft, int voiNr)
Definition dft.c:107
void dftEmpty(DFT *data)
Definition dft.c:20
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftVerifyPeak(DFT *dft, int index, int verbose, char *status)
Definition dftinput.c:747
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 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
double imgEndtime(IMG *img)
Definition fittime.c:339
int fittime_from_img(IMG *img, double *fittime, int verbose)
Definition fittime.c:74
double dftEndtime(DFT *dft)
Definition fittime.c:315
double hlFromIsotope(char *isocode)
Definition halflife.c:55
int imgExistentTimes(IMG *img)
Definition img.c:613
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgDeleteFrameOverlap(IMG *img)
Definition imgframe.c:77
int imgReadModelingData(char *petfile, char *siffile, char *inputfile1, char *inputfile2, char *inputfile3, double *fitdur, int *fitframeNr, IMG *img, DFT *inp, DFT *iinp, int verifypeak, FILE *loginfo, int verbose, char *status)
Definition imginput.c:24
void sifInit(SIF *data)
Definition sif.c:17
void sifEmpty(SIF *data)
Definition sif.c:33
int sifRead(char *filename, SIF *data)
Definition sifio.c:21
#define IMG_TYPE_IMAGE
char siferrmsg[128]
Definition sif.c:7
char * petTunit(int tunit)
Definition petunits.c:226
Header file for libtpcmodext.
int dftInterpolateForIMG(DFT *input, IMG *img, int frame_nr, DFT *output, double *ti1, double *ti2, int verbose, char *status)
Definition misc_model.c:17
int cunit_check_dft_vs_img(DFT *dft, IMG *img, char *errmsg, int verbose)
Definition units_check.c:18
int timeunit
int voiNr
int frameNr
double * x
char type
unsigned short int dimt
float * start
unsigned short int dimz
float * end
const char * statmsg
float isotopeHalflife
float * mid
double * x1
int frameNr
double * x2
char isotope_name[8]