TPCCLIB
Loading...
Searching...
No Matches
img2dft.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <math.h>
15#include <string.h>
16#include <time.h>
17/*****************************************************************************/
18#include "libtpcmisc.h"
19#include "libtpccurveio.h"
20#include "libtpcimgio.h"
21#include "libtpcroi.h"
22#include "libtpcimgp.h"
23#include "libtpcmodel.h"
24#include "libtpcmodext.h"
25#include "libtpcidi.h"
26/*****************************************************************************/
27
28/*****************************************************************************/
29static char *info[] = {
30 "Calculating regional time-radioactivity concentration curves (TACs) from",
31 "a PET image in ECAT, Analyze 7.5, or NIfTI-1 format, when",
32 "regions-of-interests (ROIs) are given in ECAT 6.3 format ROI files,",
33 "as mask image, or as vrd file.",
34 "Regional TACs are written in output file in DFT format.",
35 "If file name for output file is not specified, it will be saved in the",
36 "default path replacing the extension of image file name with '.dft'.",
37 " ",
38 "Usage: @P [Options] image roifile(s) [tacfile]",
39 " ",
40 "Options:",
41 " -P[=<planes>]",
42 " Calculate all ROIs on all planes, or on specified plane;",
43 " by default, ROIs are calculated only on planes where they were drawn.",
44 " Effective only with ROI files, not with mask image.",
45 " -V=<sd|cv|var>",
46 " In addition to regional pixel value averages, either standard",
47 " deviation (sd), percentual coefficient of variation (cv), or",
48 " variance inside ROI(s) are calculated and saved in separate files",
49 " with extensions .sd, .cv, or .var, respectively.",
50 " Effective only with ROI files, not with mask file.",
51 " -tm Write time frame mid times instead of start and end times.",
52 " -median",
53 " Calculates ROI median instead of ROI average.",
54 " Effective only with ROI files, not with mask image.",
55 " -lms Calculates least median of squares estimate instead of ROI average.",
56 " Effective only with ROI files, not with mask image.",
57 " -lts Calculates least trimmed square estimate instead of ROI average.",
58 " Effective only with ROI files, not with mask image.",
59 " -stdoptions", // List standard options like --help, -v, etc
60 " ",
61 "Options -median, -lms and -lts can only be used for parametric or",
62 "static images.",
63 " ",
64 "Example 1:",
65 " @P a1204dy1.img a1204*.roi a1204dy1.dft",
66 "Example 2:",
67 " @P -P=4,6,8,10 us4321dy1.img us4321*.roi",
68 "Example 3:",
69 " @P -V=sd uo286suv.v uo286*.roi ",
70 "Example 4:",
71 " @P uo286suv.v uo286mask.v",
72 " ",
73 "See also: roilist, lmlist, eroi2img, roipxl, imgthrs, pxl2tac, tacformat",
74 " ",
75 "Keywords: image, ROI, mask, ECAT, TAC, analysis, modelling",
76 0};
77/*****************************************************************************/
78
79/*****************************************************************************/
80/* Turn on the globbing of the command line, since it is disabled by default in
81 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
82 In Unix&Linux wildcard command line processing is enabled by default. */
83/*
84#undef _CRT_glob
85#define _CRT_glob -1
86*/
87int _dowildcard = -1;
88/*****************************************************************************/
89
90/*****************************************************************************/
94/*****************************************************************************/
95int main(int argc, char **argv)
96{
97 int ai, help=0, version=0, verbose=1;
98 int ret, pxlNr, voi=0;
99 int allplanes=0;
100 int isRoi=0;
101 int variance=0;
102 int roifileNr=0;
103 int timetype=DFT_TIME_STARTEND;
104 int median=0, lms=0, lts=0;
105 ROI_list rlist;
106 RoiList *rptr;
107 INT_list ilist;
108 char *cptr, type[12], maskfile[FILENAME_MAX];
109 char imgfile[FILENAME_MAX], roifile[FILENAME_MAX],
110 dftfile[FILENAME_MAX], varfile[FILENAME_MAX];
111 IMG img, mimg;
112 DFT dft;
113 INTEGER_LIST mlist;
114 Matval matval;
115
116
117 /* Initiate data structures */
118 roi_init(&rlist);
119 imgInit(&img); imgInit(&mimg);
120 integerListInit(&mlist); intInit(&ilist);
121 dftInit(&dft);
122
123 /*
124 * Get arguments
125 */
126 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
127 imgfile[0]=roifile[0]=dftfile[0]=varfile[0]=maskfile[0]=(char)0;
128 /* Options */
129 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
130 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
131 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
132 if(strcasecmp(cptr, "TM")==0) {
133 timetype=DFT_TIME_MIDDLE; continue;
134 } else if(strncasecmp(cptr, "MEDIAN", 1)==0) {
135 median=1; continue;
136 } else if(strcasecmp(cptr, "LMS")==0) {
137 lms=1; continue;
138 } else if(strcasecmp(cptr, "LTS")==0) {
139 lts=1; continue;
140 } else if(strcasecmp(cptr, "P")==0 || strcasecmp(cptr, "PLANES")==0) {
141 allplanes=1; continue;
142 } else if(strncasecmp(cptr, "P=", 2)==0) {
143 cptr+=2; if(strlen(cptr)>0) {if(intExpand(cptr, &ilist)==0) continue;}
144 } else if(strncasecmp(cptr, "V=", 2)==0) {
145 cptr+=2;
146 if(strncasecmp(cptr, "VAR", 1)==0) {variance=1; continue;}
147 if(strncasecmp(cptr, "SD", 1)==0) {variance=2; continue;}
148 if(strncasecmp(cptr, "CV", 1)==0) {variance=3; continue;}
149 if(strlen(cptr)<1) {variance=1; continue;}
150 else if(*cptr=='s' || *cptr=='S') {variance=2; continue;}
151 else if(*cptr=='c' || *cptr=='C') {variance=3; continue;}
152 }
153 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
154 return(1);
155 } else break;
156
157 /* Print help or version? */
158 if(help==2) {tpcHtmlUsage(argv[0], info, ""); intEmpty(&ilist); return(0);}
159 if(help) {tpcPrintUsage(argv[0], info, stdout); intEmpty(&ilist); return(0);}
160 if(version) {tpcPrintBuild(argv[0], stdout); intEmpty(&ilist); return(0);}
161
162 /* Next is image file */
163 if(ai<argc) {
164 strlcpy(imgfile, argv[ai], FILENAME_MAX); ai++;
165 /* Do not check that file exists because Analyze file names can be funny */
166 }
167
168 /* Process other arguments */
169 for(; ai<argc; ai++) {
170 /* Get filename extension */
171 cptr=strrchr(argv[ai], '.');
172 /* Is this ROI file? */
173 if(cptr!=NULL && strcasecmp(cptr, ".roi")==0) {
174 strlcpy(roifile, argv[ai], FILENAME_MAX);
175 if(verbose>1) printf("roifile[%d] := %s\n", roifileNr+1, roifile);
176 ret=roi_read(roifile, &rlist);
177 if(ret) {
178 fprintf(stderr, "Error in reading '%s': %s\n", roifile, roierrmsg);
179 roi_empty(&rlist); intEmpty(&ilist);
180 return(2);
181 }
182 roifileNr++; continue;
183 } else if(!maskfile[0] && roifileNr==0) {
184 strlcpy(maskfile, argv[ai], FILENAME_MAX);
185 /* Do not check that file exists because Analyze file names can be funny*/
186 continue;
187 } else if(!dftfile[0]) {
188 strlcpy(dftfile, argv[ai], FILENAME_MAX); continue;
189 }
190 /* we should never get this far */
191 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
192 roi_empty(&rlist); intEmpty(&ilist);
193 return(1);
194 }
195
196 /* Is something missing? */
197 if(!imgfile[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
198 if((!roifile[0] || rlist.nr<=0) && !maskfile[0]) {
199 fprintf(stderr, "Error: no ROI or mask file found.\n");
200 roi_empty(&rlist); intEmpty(&ilist);
201 return(1);
202 }
203 /* Check for invalid option combinations */
204 if((variance>0 || median || lms || lts) && maskfile[0]) {
205 fprintf(stderr, "Error: mask file cannot be used with given options.\n");
206 roi_empty(&rlist); intEmpty(&ilist);
207 return(1);
208 }
209 if(variance>0 && (median || lms || lts)) {
210 fprintf(stderr, "Error: invalid combination of options.\n");
211 roi_empty(&rlist); intEmpty(&ilist);
212 return(1);
213 }
214
215 /* Set output filenames, if necessary */
216 if(!dftfile[0]) {
217 strlcpy(dftfile, imgfile, FILENAME_MAX);
218 cptr=strrchr(dftfile, '.'); if(cptr!=NULL) *cptr=(char)0;
219 strcat(dftfile, ".dft");
220 }
221 if(variance>0) {
222 strlcpy(varfile, dftfile, FILENAME_MAX);
223 cptr=strrchr(varfile, '.'); if(cptr!=NULL) *cptr=(char)0;
224 if(variance==1) strcat(varfile, ".var");
225 else if(variance==2) strcat(varfile, ".sd");
226 else strcat(varfile, ".cv");
227 }
228
229
230 /* In verbose mode print arguments and options */
231 if(verbose>1) {
232 for(ai=0; ai<argc; ai++)
233 printf("%s ", argv[ai]);
234 printf("\n");
235 printf("imgfile := %s\n", imgfile);
236 printf("dftfile := %s\n", dftfile);
237 printf("varfile := %s\n", varfile);
238 printf("roifileNr := %d\n", roifileNr);
239 if(allplanes) printf("ROIs are calculated on all image planes.\n");
240 if(ilist.nr>0) {
241 printf("ROIs are calculated on %d image planes:\n %d",
242 ilist.nr, ilist.i[0]);
243 for(int i=1; i<ilist.nr; i++) printf(", %d", ilist.i[i]);
244 printf("\n");
245 }
246 printf("maskfile := %s\n", maskfile);
247 printf("timetype := %d\n", timetype);
248 printf("median := %d\n", median);
249 printf("lms := %d\n", lms);
250 printf("lts := %d\n", lts);
251 printf("variance := %d\n", variance);
252 }
253 if(verbose>2 && rlist.nr>0) {
254 /* List ROIs */
255 printf("ROI# Name Plane Type Zoom RZoom Image\n");
256 rptr=rlist.rois;
257 while(rptr) {
258 if(rptr->roi->type==ROI_RECTANGULAR) strcpy(type, "rectangular");
259 else if(rptr->roi->type==ROI_CIRCULAR) strcpy(type, "circular");
260 else if(rptr->roi->type==ROI_ELLIPSE) strcpy(type, "ellipse");
261 else if(rptr->roi->type==ROI_TRACE) strcpy(type, "trace");
262 else strcpy(type, "???");
263 mat_numdoc(rptr->roi->matnum, &matval);
264 printf("%4d %-8.8s %3d %-5.5s %4.0f %5.0f %s\n",
265 rptr->roi->roi, rptr->roi->roiname, matval.plane, type,
266 rptr->roi->zoom, rptr->roi->recon_zoom, rptr->roi->imgfile);
267 rptr=rptr->next;
268 }
269 }
270
271
272 /*
273 * Read image
274 */
275 if(verbose>0) fprintf(stdout, "reading %s\n", imgfile);
276 ret=imgRead(imgfile, &img);
277 if(ret) {
278 fprintf(stderr, "Error in reading image: %s\n", img.statmsg);
279 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img);
280 return(3);
281 }
282 if(verbose>1) {
283 printf("dimt := %d\n", img.dimt);
284 printf("dimx := %d\n", img.dimx);
285 printf("dimy := %d\n", img.dimy);
286 printf("dimz := %d\n", img.dimz);
287 printf("unit := %s\n", imgUnit(img.unit));
288 }
289 if((median || lms || lts) && img.dimt!=1){
290 fprintf(stderr, "Error: do not use robust estimation for dynamic image.\n");
291 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img);
292 return(1);
293 }
294 if(verbose>50) imgInfo(&img);
295 /* check the file type */
296 if(img.type!=IMG_TYPE_IMAGE) {
297 fprintf(stderr, "Warning: file is not an image.\n");
298 }
299
300 /* If we have ROIs: */
301 /* Make sure that reconstruction zoom is the same in ROIs and in image */
302 if(rlist.nr>0) {
303 ret=0;
304 rptr=rlist.rois;
305 while(rptr) {
306 if(rptr->roi->recon_zoom!=img.zoom) {
307 /* If difference is not insignificant, then print (later) a warning */
308 if(fabs(rptr->roi->recon_zoom-img.zoom)>0.002) ret++;
309 /* In any case, change zooms to match */
310 if(img.zoom<1E-5) img.zoom=rptr->roi->recon_zoom;
311 else if(rptr->roi->recon_zoom<1E-5) rptr->roi->recon_zoom=img.zoom;
312 else img.zoom=rptr->roi->recon_zoom;
313 }
314 rptr=rptr->next;
315 }
316 if(ret>0) fprintf(stderr,
317 "Warning: ROI(s) may have been drawn to image with different reconstruction zoom.\n");
318 }
319
320
321 /*
322 * If ROI mask image was given, then read it and verify that it can be used
323 */
324 if(maskfile[0]) {
325 if(verbose>0) {fprintf(stdout, "reading %s\n", maskfile); fflush(stdout);}
326 /* Try to read as a mask image or vrd file */
327 ret=imgRead(maskfile, &mimg);
328 if(ret==0) {
329 if(verbose>50) imgInfo(&mimg);
330 /* Check the file type */
331 if(mimg.type!=IMG_TYPE_IMAGE) {
332 fprintf(stderr, "Warning: mask file is not an image.\n");
333 }
334 if(mimg.dimt!=1){
335 fprintf(stderr, "Error: ROI mask image contains more than one frame.\n");
336 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
337 return(3);
338 }
339 /* Check that image dimensions are the same */
340 if(mimg.dimx!=img.dimx || mimg.dimy!=img.dimy || mimg.dimz!=img.dimz) {
341 fprintf(stderr, "Error: invalid image dimensions in ROI mask image.\n");
342 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
343 return(3);
344 }
345 if(verbose>1) printf("mask image was read.\n");
346 } else {
347 if(verbose>1) printf("trying to read VRD file\n");
348 VOL_RANGE vr; VOL vol; volInit(&vol);
349 ret=vrdRead(maskfile, &vr, NULL);
350 if(ret==0) ret=volAllocate(&vol, img.dimz, img.dimy, img.dimx);
351 if(ret==0) ret=vrd2vol(&vr, &vol, 1.0, 0.0, NULL);
352 if(ret==0) ret=imgAllocate(&mimg, img.dimz, img.dimy, img.dimx, 1);
353 if(ret==0) {mimg.type=IMG_TYPE_IMAGE; ret=vol2img(&vol, &mimg, 1);}
354 volEmpty(&vol);
355 if(ret==0 && verbose>1) printf("vrd file was read.\n");
356 }
357 if(ret) {
358 fprintf(stderr, "Error: cannot read mask or volume range definition file\n");
359 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
360 return(3);
361 }
362
363 /* Get the nr of ROIs in the mask image */
364 ret=imgMaskRoiNr(&mimg, &mlist);
365 if(ret!=0 || mlist.nr==0) {
366 fprintf(stderr, "Error: invalid ROI mask image.\n");
367 if(verbose>1) printf("ret := %d\n", ret);
368 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
369 integerListEmpty(&mlist); return(3);
370 }
371 if(verbose>1) printf("ROI nr in mask image := %d\n", mlist.nr);
372 }
373
374
375 /*
376 * Allocate memory for regional TACs
377 */
378 if(verbose>1) {fprintf(stdout, "allocating memory for regional TACs\n"); fflush(stdout);}
379 /* Allocate memory for DFT */
380 if(rlist.nr>0) ret=dftAllocateWithIMG(&dft, rlist.nr, &img);
381 else ret=dftAllocateWithIMG(&dft, mlist.nr, &img);
382 if(ret) {
383 fprintf(stderr, "Error: cannot allocate memory.\n");
384 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
385 integerListEmpty(&mlist); dftEmpty(&dft);
386 return(4);
387 }
388 /* Set DFT information */
389 if(verbose>2) fprintf(stdout, "preparing DFT\n");
390 dft._type=DFT_FORMAT_STANDARD; /* File type */
391 {
392 char *cptr=strrchr(dftfile, '.');
393 if(cptr!=NULL && strcasecmp(cptr, ".TAC")==0)
394 dft._type=DFT_FORMAT_PMOD; /* File type */
395 }
396 dft.frameNr=img.dimt; /* Set frameNr */
397 dft.voiNr=0; /* needed! */
398 /* set study number */
399 if(strlen(dft.studynr)<1) studynr_from_fname(imgfile, dft.studynr);
400 /* TAC frame times are now in seconds, change to minutes if necessary */
401 if(img.isotopeHalflife>300 || (img.isotopeHalflife<=0.0 && dft.x2[img.dimt-1]>1200)) {
402 for(int fi=0; fi<img.dimt; fi++) {dft.x1[fi]/=60.0; dft.x2[fi]/=60.0; dft.x[fi]/=60.0;}
403 dft.timeunit=TUNIT_MIN;
404 }
405 dft.timetype=timetype;
406
407
408
409 /*
410 * If ROI mask image was given, then calculate TACs based on it, and quit
411 */
412 if(maskfile[0]) {
413 if(verbose>0) {fprintf(stdout, "calculating mask VOIs\n"); fflush(stdout);}
414
415 for(voi=0; voi<mlist.nr; voi++) {
416 pxlNr=imgVoiMaskTAC(&img, &mimg, mlist.list[voi], dft.voi[voi].y, verbose-2);
417 if(pxlNr<0) {
418 fprintf(stderr, "Error: cannot use ROI mask (%d).\n", -pxlNr);
419 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
420 integerListEmpty(&mlist); dftEmpty(&dft);
421 return(6);
422 }
423
424 /* Set TAC name */
425 strcpy(dft.voi[voi].voiname, "Mask");
426 sprintf(dft.voi[voi].hemisphere, "%d", mlist.list[voi]);
427 strcpy(dft.voi[voi].place, "");
428 sprintf(dft.voi[voi].name, "%s %s", dft.voi[voi].voiname, dft.voi[voi].hemisphere);
429 /* Set VOI volume */
430 dft.voi[voi].size=(double)pxlNr*img.sizex*img.sizey*img.sizez;
431 } // next mask
432 dft.voiNr=voi;
433 imgEmpty(&img); imgEmpty(&mimg); integerListEmpty(&mlist);
434 roi_empty(&rlist); intEmpty(&ilist);
435
436 /*
437 * Save the DFT file
438 */
439 if(verbose>1) fprintf(stdout, "saving the TACs\n");
440 ret=dftWrite(&dft, dftfile);
441 if(ret) {
442 fprintf(stderr, "Error in writing '%s': %s\n", dftfile, dfterrmsg);
443 dftEmpty(&dft); return(11);
444 }
445 if(verbose>0) fprintf(stdout, "%d regional TACs written in %s\n", dft.voiNr, dftfile);
446
447 /* Quit */
448 dftEmpty(&dft);
449 return(0);
450 }
451
452
453 /*
454 * Calculate ROIs
455 */
456 if(verbose>0) {fprintf(stdout, "processing ROIs\n"); fflush(stdout);}
457 int fi, ri, xi, yi, plane=0;
458 char **onoff=NULL;
459 double v, mean, var, *helpv;
460 float ***scaled_img;
461
462 /* Find largest image zoom that was used when ROIs were drawn */
463 rptr=rlist.rois;
464 int max_roi_zoom=0.0;
465 while(rptr) {
466 if((int)roundf(rptr->roi->zoom) > max_roi_zoom) max_roi_zoom=(int)roundf(rptr->roi->zoom);
467 rptr=rptr->next;
468 }
469 if(verbose>2) printf("max_roi_zoom := %d\n", max_roi_zoom);
470
471 /* Allocate memory for help vector, on-off matrix and scaled 2D image plane;
472 all of the max size of (possibly 2-, 3- or 4-times magnified) image on which the ROIs were drawn.
473 Note that some ROIs may have been drawn with smaller or no magnification. */
474 int roidimx=max_roi_zoom*img.dimx;
475 int roidimy=max_roi_zoom*img.dimy;
476
477 helpv=malloc(roidimy*roidimx*sizeof(double));
478 onoff=malloc(roidimx*sizeof(char*));
479 if(helpv==NULL || onoff==NULL) {
480 fprintf(stderr, "Error: out of memory.\n");
481 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
482 integerListEmpty(&mlist); dftEmpty(&dft);
483 return(5);
484 }
485 for(xi=0; xi<roidimx; xi++) {
486 onoff[xi]=malloc(roidimy*sizeof(char));
487 if(onoff[xi]==NULL) {
488 fprintf(stderr, "Error: out of memory.\n");
489 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
490 integerListEmpty(&mlist); dftEmpty(&dft);
491 free(helpv); return(5);
492 }
493 }
494 scaled_img=malloc(img.dimt*sizeof(float**));
495 if(scaled_img==NULL) {
496 fprintf(stderr, "Error: out of memory.\n");
497 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
498 integerListEmpty(&mlist); dftEmpty(&dft);
499 for(xi=0; xi<roidimx; xi++) free(onoff[xi]);
500 free(onoff);
501 free(helpv); return(5);
502 }
503 for(fi=0; fi<img.dimt; fi++){
504 scaled_img[fi]=malloc(roidimy*sizeof(float*));
505 if(scaled_img[fi]==NULL) {
506 fprintf(stderr, "Error: out of memory.\n");
507 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
508 integerListEmpty(&mlist); dftEmpty(&dft);
509 for(xi=0; xi<roidimx; xi++) free(onoff[xi]);
510 free(onoff);
511 free(helpv); return(5);
512 }
513 for(yi=0; yi<roidimy; yi++) {
514 scaled_img[fi][yi]=malloc(roidimx*sizeof(float));
515 if(scaled_img[fi][yi]==NULL) {
516 fprintf(stderr, "Error: out of memory.\n");
517 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
518 integerListEmpty(&mlist); dftEmpty(&dft);
519 for(xi=0; xi<roidimx; xi++) free(onoff[xi]);
520 free(onoff);
521 free(helpv); return(5);
522 }
523 }
524 }
525
526
527 /* One ROI at a time */
528 rptr=rlist.rois;
529 while(rptr) {
530 if(verbose>3) {
531 fprintf(stdout, "-----------\n Processing ROI %d\n", rptr->roi->roi);
532 fprintf(stdout, " ROI was drawn with zoom %f\n", rptr->roi->zoom);
533 fflush(stdout);
534 }
535 /* On which plane was this ROI drawn? */
536 mat_numdoc(rptr->roi->matnum, &matval);
537 plane=matval.plane;
538 if(verbose>4) {fprintf(stdout, " ROI plane %d\n", plane); fflush(stdout);}
539 /*
540 * Create ON-OFF matrix (0=outside all ROIs, >0=inside)
541 * Note that onoff[0..dimx][0..dimy], whereas
542 * IMG m[0..dimz-1][0..dimy][0..dimx][0..dimt]
543 */
544 /*ret=roi_onoff(rptr->roi, img.dimx, img.dimy, img.zoom, onoff);*/
545#if(1)
546 ret=roi_onoff(rptr->roi, (rptr->roi->zoom)*img.dimx, (rptr->roi->zoom)*img.dimy, onoff);
547#else
548 ret=roiOnOff(rptr->roi, (rptr->roi->zoom)*img.dimx, (rptr->roi->zoom)*img.dimy, onoff);
549#endif
550 if(ret) {
551 fprintf(stderr, "Error(%d) in setting ROI: %s\n", ret, roierrmsg);
552 if(verbose>2) {
553 roi_print(rptr->roi);
554 printf("dim_x=%d dim_y=%d zoom=%g\n", img.dimx, img.dimy, img.zoom);
555 }
556 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
557 integerListEmpty(&mlist); dftEmpty(&dft);
558 for(xi=0; xi<roidimx; xi++) free(onoff[xi]);
559 free(onoff);
560 for(fi=0; fi<img.dimt; fi++) {
561 for(yi=0; yi<roidimy; yi++) free(scaled_img[fi][yi]);
562 free(scaled_img[fi]);
563 }
564 free(scaled_img);
565 free(helpv); return(6);
566 }
567 if(verbose>5) roiOnOffPrint((rptr->roi->zoom)*img.dimx, (rptr->roi->zoom)*img.dimy, onoff);
568
569 /* Go through all image planes */
570 for(int zi=0; zi<img.dimz; zi++) {
571 /* Are we supposed to do anything for this plane? */
572 isRoi=0;
573 if(allplanes) {
574 isRoi=1;
575 } else if(ilist.nr>0) {
576 for(int i=0; i<ilist.nr; i++) if(ilist.i[i]==img.planeNumber[zi]) {isRoi=1; break;}
577 } else {
578 if(plane==img.planeNumber[zi]) isRoi=1;
579 }
580 if(isRoi==0) continue; // no, go to next image plane
581 if(verbose>4) {fprintf(stdout, " image plane %d\n", img.planeNumber[zi]); fflush(stdout);}
582
583 /* Allocate more memory for TAC, if necessary */
584 if(dft.voiNr>=dft._voidataNr) {
585 ret=dftAddmem(&dft, 10);
586 if(ret) {
587 fprintf(stderr, "Error: cannot reallocate memory for TACs.\n");
588 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
589 integerListEmpty(&mlist); dftEmpty(&dft);
590 for(xi=0; xi<roidimx; xi++) free(onoff[xi]);
591 free(onoff);
592 for(fi=0; fi<img.dimt; fi++) {
593 for(yi=0; yi<roidimy; yi++) free(scaled_img[fi][yi]);
594 free(scaled_img[fi]);
595 }
596 free(scaled_img);
597 free(helpv); return(6);
598 }
599 }
600
601 /* Scale input image to ROI drawing zoom: */
602 for(fi=0; fi<img.dimt; fi++) {
603 integerScale(fi, img.m[zi], scaled_img[fi], img.dimx, img.dimy, rptr->roi->zoom);
604 }
605
606 /* Calculate average of pixel values and volume */
607 pxlNr=0; voi=dft.voiNr;
608 for(yi=0; yi<(rptr->roi->zoom)*img.dimy; yi++) {
609 for(xi=0; xi<(rptr->roi->zoom)*img.dimx; xi++) {
610 if(onoff[xi][yi]>0) {
611 for(fi=0; fi<img.dimt; fi++) {
612 if(!(median||lms||lts)){ /*regular mean */
613 if(verbose>100) printf(" %g\n", scaled_img[fi][yi][xi]);
614 dft.voi[voi].y[fi]+=(double)scaled_img[fi][yi][xi];
615 } else {
616 helpv[pxlNr]=(double)scaled_img[fi][yi][xi];
617 }
618 }
619 pxlNr++;
620 }
621 }
622 }
623 if(verbose>1) {
624 printf("\n ROI %d\n", voi);
625 if(verbose>2) printf(" number_of_pixels := %d\n", pxlNr);
626 if(verbose>2 && !(median||lms||lts)) printf(" sum_of_pixels := %g\n", dft.voi[voi].y[0]);
627 }
628 if(!(median||lms||lts)) {
629 if(pxlNr>0) for(fi=0; fi<img.dimt; fi++) dft.voi[voi].y[fi]/=(double)pxlNr;
630 } else if(median) { /*median instead of mean*/
631 dft.voi[voi].y[0]=dmedian(helpv, pxlNr);
632 } else if(lms){ /*least median of squares estimate instead of mean*/
633 dft.voi[voi].y[0]=least_median_of_squares(helpv, pxlNr);
634 } else if(lts){ /* least trimmed square estimate instead of mean*/
635 least_trimmed_square(helpv, pxlNr, &mean, &var);
636 dft.voi[voi].y[0]=mean;
637 }
638
639 /* Calculate ROI volume */
640 dft.voi[voi].size=(double)pxlNr*img.sizex*img.sizey*img.sizez;
641 dft.voi[voi].size/=(rptr->roi->zoom*rptr->roi->zoom); // correct for ROI zooming
642
643 /* Calculate variance */
644 if(variance>0) {
645 if(lts) {
646 dft.voi[voi].y2[0]=var;
647 } else {
648 for(yi=0; yi<(rptr->roi->zoom)*img.dimy; yi++)
649 for(xi=0; xi<(rptr->roi->zoom)*img.dimx; xi++) {
650 if(onoff[xi][yi]>0) {
651 for(fi=0; fi<img.dimt; fi++) {
652 v=scaled_img[fi][yi][xi]-dft.voi[voi].y[fi];
653 dft.voi[voi].y2[fi]+=v*v;
654 }
655 }
656 }
657 if(pxlNr>1) for(fi=0; fi<img.dimt; fi++) dft.voi[voi].y2[fi]/=(double)(pxlNr-1);
658 }
659 if(variance>1) for(fi=0; fi<img.dimt; fi++)
660 if(dft.voi[voi].y2[fi]>0.0)
661 dft.voi[voi].y2[fi]=sqrt(dft.voi[voi].y2[fi]);
662 if(variance==3) for(fi=0; fi<img.dimt; fi++)
663 if(fabs(dft.voi[voi].y[fi])>1.0e-12) {
664 dft.voi[voi].y2[fi]/=dft.voi[voi].y[fi];
665 dft.voi[voi].y2[fi]*=100.0;
666 }
667 }
668
669 /* Set TAC name */
670 sprintf(dft.voi[voi].place, "Pl%03d", img.planeNumber[zi]);
671 int n=strTokenNr(rptr->roi->roiname, " -_,;\t");
672 if(n==0) {
673 sprintf(dft.voi[voi].voiname, "ROI%03d", rptr->roi->roi);
674 strcpy(dft.voi[voi].hemisphere, ".");
675 sprintf(dft.voi[voi].name, "ROI%03d__Pl%03d", rptr->roi->roi, img.planeNumber[zi]);
676 } else if(n==1) {
677 strTokenNCpy(rptr->roi->roiname, " -_,;\t", 1, dft.voi[voi].voiname, MAX_REGIONSUBNAME_LEN+1);
678 strcpy(dft.voi[voi].hemisphere, ".");
679 //strncpy(dft.voi[voi].name, rptr->roi->roiname, MAX_REGIONNAME_LEN);
680 //dft.voi[voi].name[MAX_REGIONNAME_LEN]=(char)0;
681 strTokenNCpy(rptr->roi->roiname, " -_,;\t", 1, dft.voi[voi].name, MAX_REGIONNAME_LEN+1);
682 if((strlen(dft.voi[voi].name)+3+strlen(dft.voi[voi].place))<MAX_REGIONNAME_LEN) {
683 strcat(dft.voi[voi].name, "__");
684 strlcat(dft.voi[voi].name, dft.voi[voi].place, MAX_REGIONNAME_LEN);
685 }
686 } else {
687 char tmp[MAX_REGIONNAME_LEN+1];
688 strTokenNCpy(rptr->roi->roiname, " -_,;\t", 1, dft.voi[voi].voiname,
690 strTokenNCpy(rptr->roi->roiname, " -_,;\t", 2, dft.voi[voi].hemisphere,
692 strTokenNCpy(rptr->roi->roiname, " -_,;\t", 1, dft.voi[voi].name,
694 strTokenNCpy(rptr->roi->roiname, " -_,;\t", 2, tmp,
696 /* Replace hemisphere name 'd' with 'dx', and 's' or 'si' with sin */
697 if(strcasecmp(tmp, "D")==0) {
698 strcpy(tmp, "dx"); strcpy(dft.voi[voi].hemisphere, "dx");
699 } else if(strcasecmp(tmp, "S")==0 || strcasecmp(tmp, "SI")==0) {
700 strcpy(tmp, "sin"); strcpy(dft.voi[voi].hemisphere, "sin");
701 }
702 if((strlen(dft.voi[voi].name)+1+strlen(tmp))<MAX_REGIONNAME_LEN) {
703 strcat(dft.voi[voi].name, "_");
704 strcat(dft.voi[voi].name, tmp);
705 }
706 if((strlen(dft.voi[voi].name)+3+strlen(dft.voi[voi].place))<MAX_REGIONNAME_LEN) {
707 strcat(dft.voi[voi].name, "_");
708 strlcat(dft.voi[voi].name, dft.voi[voi].place, MAX_REGIONNAME_LEN);
709 }
710 }
711 /* Tell the user what we just did */
712 if(verbose>0) {fprintf(stdout, " calculated %s\n", dft.voi[voi].name); fflush(stdout);}
713 dft.voiNr++;
714 } /* next image plane */
715 rptr=rptr->next;
716 } /* next ROI */
717
718 /* Free up the memory for onoff matrices etc */
719 roi_empty(&rlist); intEmpty(&ilist); imgEmpty(&img); imgEmpty(&mimg);
720 integerListEmpty(&mlist);
721 for(xi=0; xi<roidimx; xi++) free(onoff[xi]);
722 free(onoff);
723 for(fi=0; fi<img.dimt; fi++) {
724 for(yi=0; yi<roidimy; yi++) free(scaled_img[fi][yi]);
725 free(scaled_img[fi]);
726 }
727 free(scaled_img);
728 free(helpv);
729
730
731 /*
732 * Save the DFT file
733 */
734 if(verbose>1) fprintf(stdout, "saving the TACs\n");
735 /* Extra comments if robust estimation is used instead of regular mean */
736 if(median) sprintf(dft.comments, "# Median values for ROIs.\n");
737 if(lms) sprintf(dft.comments, "# Least median of squares values for ROIs.\n");
738 if(lts) sprintf(dft.comments, "# Least trimmed square values for ROIs.\n");
739 if(verbose>50) dftPrint(&dft);
740 ret=dftWrite(&dft, dftfile);
741 if(ret) {
742 fprintf(stderr, "Error in writing '%s': %s\n", dftfile, dfterrmsg);
743 dftEmpty(&dft); return(11);
744 }
745 if(verbose>0) fprintf(stdout, "%d regional TACs written in %s\n", dft.voiNr, dftfile);
746
747
748 /*
749 * Save the variances in DFT file, if required
750 */
751 if(variance>0) {
752 if(verbose>0) fprintf(stdout, "saving the variance curves\n");
753 sprintf(dft.comments, "# variances\n");
754 if(variance==2) {/*strcpy(dft.unit, dft.unit);*/}
755 else if(variance==3) strcpy(dft.unit, "%");
756 for(ri=0; ri<dft.voiNr; ri++) for(fi=0; fi<dft.frameNr; fi++)
757 dft.voi[ri].y[fi]=dft.voi[ri].y2[fi];
758 if(verbose>50) dftPrint(&dft);
759 ret=dftWrite(&dft, varfile);
760 if(ret) {
761 fprintf(stderr, "Error in writing '%s': %s\n", varfile, dfterrmsg);
762 dftEmpty(&dft); return(13);
763 }
764 if(verbose>0)
765 fprintf(stdout, "%d regional variance curves written in %s\n", dft.voiNr, varfile);
766 }
767
768 if(verbose>=0) printf("\n");
769 dftEmpty(&dft);
770 return(0);
771}
772/*****************************************************************************/
773
774/*****************************************************************************/
void dftInit(DFT *data)
Definition dft.c:38
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
void dftPrint(DFT *data)
Definition dftio.c:538
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
void mat_numdoc(int matnum, Matval *matval)
Definition ecat63ml.c:254
void roi_empty(ROI_list *rl)
Definition ecat_roi.c:18
void roi_print(ROI *roi)
Definition ecat_roi.c:333
void roi_init(ROI_list *rl)
Definition ecat_roi.c:49
int roi_read(const char *fname, ROI_list *rl)
Definition ecat_roi.c:114
char roierrmsg[128]
Definition ecat_roi.c:11
int roi_onoff(ROI *roi, int dimx, int dimy, char **m)
Definition ecat_roi.c:451
void roiOnOffPrint(int dimx, int dimy, char **m)
int roiOnOff(ROI *roi, int dimx, int dimy, char **m)
void imgInfo(IMG *image)
Definition img.c:359
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgMaskRoiNr(IMG *img, INTEGER_LIST *list)
Definition imgeval.c:176
int imgVoiMaskTAC(IMG *img, IMG *mask, int mv, double *tac, int verbose)
Definition imgeval.c:214
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
void integerScale(int frame, float ***src, float **targ, int width, int height, int zoom)
char * imgUnit(int dunit)
Definition imgunits.c:315
int integerListEmpty(INTEGER_LIST *l)
Definition intex.c:175
int integerListInit(INTEGER_LIST *l)
Definition intex.c:161
int intExpand(char *text, INT_list *list)
Definition intex.c:43
void intInit(INT_list *l)
Definition intex.c:12
void intEmpty(INT_list *l)
Definition intex.c:23
Header file for libtpccurveio.
#define DFT_FORMAT_PMOD
#define DFT_TIME_MIDDLE
#define DFT_FORMAT_STANDARD
#define DFT_TIME_STARTEND
Header file for libtpcidi.
Header file for libtpcimgio.
void volInit(VOL *vol)
Definition vol.c:26
int volAllocate(VOL *vol, int planes, int rows, int columns)
Definition vol.c:139
void volEmpty(VOL *vol)
Definition vol.c:74
int vrd2vol(VOL_RANGE *r, VOL *vol, float in, float out, char *status)
Definition vol.c:681
int vrdRead(char *vdffile, VOL_RANGE *vol_range, char *status)
Definition vol.c:742
int vol2img(VOL *vol, IMG *img, int frame)
Definition vol.c:351
#define IMG_TYPE_IMAGE
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
#define MAX_REGIONNAME_LEN
Definition libtpcmisc.h:154
int strTokenNCpy(const char *str1, const char *str2, int i, char *str3, int count)
Definition strext.c:45
int strTokenNr(const char *str1, const char *str2)
Definition strext.c:17
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
int studynr_from_fname(char *fname, char *studynr)
Definition studynr.c:119
size_t strlcat(char *dst, const char *src, size_t dstsize)
Definition strext.c:206
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
Header file for libtpcmodel.
double least_median_of_squares(double *data, int n)
Fit a constant (horisontal straight line) to the data by minimising the median of squared residuals.
Definition lms.c:21
double dmedian(double *data, int n)
Definition median.c:48
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341
int least_trimmed_square(double data[], long int n, double *mean, double *variance)
Definition lts.c:27
Header file for libtpcmodext.
int dftAllocateWithIMG(DFT *dft, int tacNr, IMG *img)
Definition misc_model.c:296
Header file for libtpcroi.
#define ROI_CIRCULAR
Definition libtpcroi.h:36
#define ROI_ELLIPSE
Definition libtpcroi.h:38
#define ROI_TRACE
Definition libtpcroi.h:40
#define ROI_RECTANGULAR
Definition libtpcroi.h:34
int _type
int timetype
Voi * voi
int timeunit
char studynr[MAX_STUDYNR_LEN+1]
double * x1
char comments[_DFT_COMMENT_LEN+1]
int voiNr
double * x2
int frameNr
double * x
char unit[MAX_UNITS_LEN+1]
float sizex
unsigned short int dimx
char type
float **** m
char unit
unsigned short int dimt
int * planeNumber
float sizey
unsigned short int dimz
unsigned short int dimy
float zoom
const char * statmsg
float isotopeHalflife
float sizez
int * i
Definition libtpcmisc.h:322
int plane
RoiList * rois
Definition libtpcroi.h:96
float zoom
Definition libtpcroi.h:47
int type
Definition libtpcroi.h:53
char roiname[256]
Definition libtpcroi.h:69
int matnum
Definition libtpcroi.h:51
int roi
Definition libtpcroi.h:67
float recon_zoom
Definition libtpcroi.h:49
char imgfile[FILENAME_MAX]
Definition libtpcroi.h:45
ROI * roi
Definition libtpcroi.h:86
struct _RoiList * next
Definition libtpcroi.h:88
double size
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]