TPCCLIB
Loading...
Searching...
No Matches
eabaort.c
Go to the documentation of this file.
1
10/*****************************************************************************/
11#include "tpcclibConfig.h"
12/*****************************************************************************/
13#include <stdio.h>
14#include <stdlib.h>
15#include <math.h>
16#include <string.h>
17#include <unistd.h>
18#include <time.h>
19/*****************************************************************************/
20#include "libtpcmisc.h"
21#include "libtpccurveio.h"
22#include "libtpcimgio.h"
23#include "libtpcimgp.h"
24#include "libtpcmodel.h"
25#include "libtpcmodext.h"
26#include "libtpcidi.h"
27/*****************************************************************************/
28
29/*****************************************************************************/
30static char *info[] = {
31 "Extracts arterial input curve from human abdominal region of a dynamic",
32 "[O-15]H2O PET image by finding the aorta, and corrects it with",
33 "recovery coefficient based on method (1, 4).",
34 "The current method does also account for effect of background",
35 "radioactivity on recovery coefficient (3).",
36 " ",
37 "Supported file formats are ECAT 6.3, ECAT 7, NIfTI-1, and Analyze 7.5.",
38 "In case of NIfTI and Analyze image input, you may need to add the frame",
39 "information to the blood data afterwards.",
40 "NOTICE: all image planes should contain a clear view of the abdominal",
41 "aorta that has not yet split into two vessels, and no other high spots;",
42 "crop the image before using this program.",
43 "NOTICE: It is recommended that either the full width half maximum (FWHM)",
44 "value or individually measured aorta diameter is specified as command-line",
45 "option, because both cannot be reliably estimated from a noisy image.",
46 "NOTICE: It is also recommended that the full width half maximum (FWHM)",
47 "value is determined for each scanner and reconstruction method.",
48 " ",
49 "Usage: @P [Options] petimage bloodfile",
50 " ",
51 "Options:",
52 " -FWHM=<value|fit>",
53 " Enter a fixed value for FWHM (mm); fitted by default.",
54 " Results will not be reliable unless either FWHM or vessel diameter",
55 " is measured and fixed.",
56 " -diameter=<value>",
57 " Enter a fixed value for inner vessel diameter (mm); fitted by default.",
58 " Results will not be reliable unless either FWHM or vessel diameter",
59 " is measured and fixed.",
60 " -plane=<Mean|Median|Best>",
61 " Model is fitted separately to all image planes, and by default",
62 " the mean FWHM and vessel diameter are used to estimate an average",
63 " blood TAC using all image planes.",
64 " With this option the median can be used instead of the mean, or",
65 " blood TAC can be estimated only from the plane that provides",
66 " the highest fitted peak.",
67 " -model=<germano|gaussian>",
68 " Select the PVE simulation method; Gaussian smoothing by default.",
69 " -pixelsize=<value>",
70 " Set image pixel size (mm) in x,y dimensions. Necessary, if image header",
71 " does not have valid pixel size.",
72 " -fitsize=<value>",
73 " Length (mm) of the fit square side. By default, 30x30mm square",
74 " surrounding the peak pixel value is used in the fit.",
75 " -sum=<filename>",
76 " Save sum image sub-volume which is used to fit vessel position.",
77 " -sumfit=<filename>",
78 " Save fitted sum image sub-volume.",
79 " -bkg=<filename>",
80 " Model estimated background curve.",
81 " -peak=<filename>",
82 " Model estimated peak TAC (not corrected for recovery error).",
83 " -subvol=<filename>",
84 " Subrange of the original dynamic image used in fit; for testing.",
85 " -stdoptions", // List standard options like --help, -v, etc
86 " ",
87 "Example 1: FWHM is measured, vessel diameter is estimated from image:",
88 " eabaort -FWHM=6.3 -diameter=best s9876dy1.v s9876ab.dat ",
89 " ",
90 "Example 2: vessel diameter is measured, FWHM is estimated from image:",
91 " eabaort -FWHM=fit -diameter=19.2 s9876dy1.v s9876ab.dat ",
92 " ",
93 "References:",
94 "1. Germano G, Chen BC, Huang S-C, Gambhir SS, Hoffman EJ, Phelps ME.",
95 " Use of abdominal aorta for arterial input function determination",
96 " in hepatic and renal PET studies. J Nucl Med 1992;33:613-620.",
97 "2. Scremin OU, Cuevas-Trisan RL, Scremin E, Brown CV, Mandelkern MA.",
98 " Functional electrical stimulation effect on skeletal muscle blood",
99 " flow measured with H215O positron emission tomography. Arch Phys",
100 " Med Rehabil 1998;79:641-646.",
101 "3. Brix G, Belleman ME, Hauser H, Doll J. Recovery-koeffizienten zur",
102 " quantifierung der arteriellen inputfunktion aus dynamischen PET-",
103 " messungen: experimentelle und theoretische bestimmung. Nuklearmedizin",
104 " 2002;41:184-190.",
105 "4. Liukko KE, Oikonen VJ, Tolvanen TK, Virtanen KA, Viljanen AP, Sipilä HT,",
106 " Nuutila P, Iozzo P. Non-invasive estimation of subcutaneous and visceral",
107 " adipose tissue blood flow by using [15O]H2O PET with image derived input",
108 " functions. Open Med Imaging J. 2007; 1: 7-13.",
109 " ",
110 "See also: fit_h2o, imgflow, fitdelay, imgbox, simiart",
111 " ",
112 "Keywords: input, blood, image, aorta",
113 0};
114/*****************************************************************************/
115
116/*****************************************************************************/
117/* Turn on the globbing of the command line, since it is disabled by default in
118 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
119 In Unix&Linux wildcard command line processing is enabled by default. */
120/*
121#undef _CRT_glob
122#define _CRT_glob -1
123*/
124int _dowildcard = -1;
125/*****************************************************************************/
126
127/*****************************************************************************/
128/* Local functions */
129double func(int parNr, double *p, void*);
130/*****************************************************************************/
131
132/*****************************************************************************/
134enum estim_mode {P_FIXED, P_MEAN, P_MEDIAN, P_BEST};
136enum parameter {P_BKG, P_PEAK, P_POSX, P_POSY, P_RAD, P_FWHM};
138enum vm_type {VM_GERMANO, VM_GAUSSIAN};
139/*****************************************************************************/
140double pmin[MAX_PARAMETERS], pmax[MAX_PARAMETERS];
141int parNr=6, iterNr;
142/*****************************************************************************/
143IMG pmimg, psimg;
144int ppi=0;
145int vessel_model=VM_GAUSSIAN;
146/*****************************************************************************/
147
148/*****************************************************************************/
152int main(int argc, char *argv[])
153{
154 int ai, help=0, version=0, verbose=1;
155 int fi, ret, pi, yi, xi, i;
156 int side;
157 int mode_plane=P_MEAN;
158 int best_plane=-1;
159 char imgfile[FILENAME_MAX], tacfile[FILENAME_MAX],
160 regfile[FILENAME_MAX], maxfile[FILENAME_MAX], bkgfile[FILENAME_MAX],
161 sumfile[FILENAME_MAX], suffile[FILENAME_MAX];
162 char tmp[512], *cptr;
163 IMG img, rimg, fimg, simg;
164 float maxv, minv, avg, f;
165 double ss, *chainptr, *chain, **p, ***pf, pxlsize=-1.0;
166 double reccoef=0, rad=0;
167 DFT dft;
168 IMG_RANGE ir;
169 IMG_PIXEL imax, imin, ppos;
170 double xorig, yorig;
171 int planeNr=0, peakFrame;
172 double fitsize=40.0; // fit square side length (mm)
173 double diameter=-1.0, radius=6., FWHM=-1.0;
174
175
176
177 /*
178 * Get and check the program arguments
179 */
180 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
181 imgfile[0]=tacfile[0]=regfile[0]=maxfile[0]=bkgfile[0]=sumfile[0]=suffile[0]=(char)0;
182 /* Get options */
183 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
184 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
185 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
186 if(strncasecmp(cptr, "MODEL=", 6)==0) {
187 if(strncasecmp(cptr+6, "GERMANO", 3)==0) {
188 vessel_model=VM_GERMANO; continue;}
189 if(strncasecmp(cptr+6, "GAUSSIAN", 3)==0) {
190 vessel_model=VM_GAUSSIAN; continue;}
191 } else if(strncasecmp(cptr, "PIXELSIZE=", 10)==0) {
192 pxlsize=atof_dpi(cptr+10); if(pxlsize>0) continue;
193 } else if(strncasecmp(cptr, "SUBVOL=", 7)==0) {
194 strlcpy(regfile, cptr+7, FILENAME_MAX); if(strlen(regfile)>0) continue;
195 } else if(strncasecmp(cptr, "SUM=", 4)==0) {
196 strlcpy(sumfile, cptr+4, FILENAME_MAX); if(strlen(sumfile)>0) continue;
197 } else if(strncasecmp(cptr, "SUMFIT=", 7)==0) {
198 strlcpy(suffile, cptr+7, FILENAME_MAX); if(strlen(suffile)>0) continue;
199 } else if(strncasecmp(cptr, "BKG=", 4)==0) {
200 strlcpy(bkgfile, cptr+4, FILENAME_MAX); if(strlen(bkgfile)>0) continue;
201 } else if(strncasecmp(cptr, "PEAK=", 5)==0) {
202 strlcpy(maxfile, cptr+5, FILENAME_MAX); if(strlen(maxfile)>0) continue;
203 } else if(strncasecmp(cptr, "F=", 2)==0) {
204 FWHM=atof_dpi(cptr+2); if(FWHM>0.0) continue;
205 } else if(strncasecmp(cptr, "FWHM=", 5)==0) {
206 if(strcasecmp(cptr+5, "FIT")==0) continue;
207 FWHM=atof_dpi(cptr+5); if(FWHM>0.0) continue;
208 } else if(strncasecmp(cptr, "FITSIZE=", 8)==0) {
209 fitsize=atof_dpi(cptr+8); if(fitsize>0.0) continue;
210 } else if(strncasecmp(cptr, "DIAMETER=", 9)==0) {
211 ret=atof_with_check(cptr+9, &diameter);
212 if(ret==0 && diameter>0.0) continue;
213 } else if(strncasecmp(cptr, "PLANE=", 6)==0) {
214 if(strcasecmp(cptr+6, "MEAN")==0) {mode_plane=P_MEAN; continue;}
215 if(strcasecmp(cptr+6, "MEDIAN")==0) {mode_plane=P_MEDIAN; continue;}
216 if(strcasecmp(cptr+6, "BEST")==0) {mode_plane=P_BEST; continue;}
217 }
218 /* We should not be here */
219 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
220 return(1);
221 } else break;
222
223
224 /* Print help or version? */
225 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
226 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
227 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
228
229 /* Process other arguments, starting from the first non-option */
230 if(ai<argc) strlcpy(imgfile, argv[ai++], FILENAME_MAX);
231 if(ai<argc) strlcpy(tacfile, argv[ai++], FILENAME_MAX);
232 if(ai<argc) {
233 /* We should not be here */
234 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
235 return(1);
236 }
237 /* Did we get all the information that we need? */
238
239 /* Check what we got */
240 if(!tacfile[0]) {
241 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
242 return(1);
243 }
244
245 /* In verbose mode print arguments and options */
246 if(verbose>1) {
247 printf("imgfile := %s\n", imgfile);
248 printf("tacfile := %s\n", tacfile);
249 printf("sumfile := %s\n", sumfile);
250 printf("suffile := %s\n", suffile);
251 printf("regfile := %s\n", regfile);
252 printf("maxfile := %s\n", maxfile);
253 printf("bkgfile := %s\n", bkgfile);
254 printf("pxlsize := %g\n", pxlsize);
255 printf("fitsize := %g\n", fitsize);
256 printf("vessel_model := %d\n", vessel_model);
257 printf("mode_plane := %d\n", mode_plane);
258 printf("diameter := %g\n", diameter);
259 printf("FWHM := %g\n", FWHM);
260 fflush(stdout);
261 }
262 if(verbose>9) IMG_TEST=verbose-9; else IMG_TEST=0;
263 if(verbose>19) VOL_TEST=verbose-19; else VOL_TEST=0;
264
265 /* Initiate data structures */
266 imgInit(&img); imgInit(&rimg); imgInit(&simg); imgInit(&fimg);
267 dftInit(&dft);
268 imgInit(&pmimg); imgInit(&psimg);
269
270
271 /*
272 * Read the PET image
273 */
274 if(verbose>1) fprintf(stdout, "reading %s\n", imgfile);
275 ret=imgRead(imgfile, &img);
276 if(ret) {
277 fprintf(stderr, "Error in reading image: %s\n", img.statmsg);
278 imgEmpty(&img); return(3);
279 }
280 if(imgNaNs(&img, 1)>0)
281 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
282 /* Check if PET data is raw or image */
283 if(img.type!=IMG_TYPE_IMAGE) {
284 fprintf(stderr, "Error: %s is not an image.\n", imgfile);
285 imgEmpty(&img); return(3);
286 }
287 /* Check that this is dynamic image with at least 4 frames */
288 if(img.dimt<4) {
289 if(img.dimt<2)
290 strcpy(tmp, "static image can not be used to provide valid input");
291 else
292 strcpy(tmp, "image has too few time frames to provide valid input TAC");
293 fprintf(stderr, "Warning: %s.\n", tmp);
294 }
295 /* Check that isotope is O-15 */
296 if(strcasecmp(imgIsotope(&img), "O-15"))
297 fprintf(stderr, "\nWarning: method is only validated for [O-15]H2O!\n\n");
298 /* Check that image contains pixel sizes */
299 if(pxlsize>0) {
300 if(verbose>1) printf("original_image_pixel_size := %g\n", img.sizex);
301 img.sizex=img.sizey=pxlsize;
302 } else {
303 if(img.sizex<=0 || img.sizey<=0) {
304 fprintf(stderr, "Error: image does not contain pixel size.\n");
305 fprintf(stdout, "Note: set pixel size with option -pixelsize.\n");
306 imgEmpty(&img); return(3);
307 }
308 if(img.sizex!=img.sizey) {
309 fprintf(stderr, "Error: different x and y pixel size.\n");
310 imgEmpty(&img); return(3);
311 }
312 }
313 if(verbose>0) printf("image_pixel_size := %g\n", img.sizex);
314 /* Check that image contains frame times */
315 if(imgExistentTimes(&img)==0.0) {
316 fprintf(stderr, "\nWarning: image does not contain frame times.\n\n");
317 /* Set frame times to 0.5,1.5,2.5,... */
318 for(fi=0; fi<img.dimt; fi++) {
319 img.start[fi]=(float)fi; img.end[fi]=(float)(fi+1);
320 img.mid[fi]=0.5*(img.start[fi]+img.end[fi]);
321 }
322 }
323
324
325 /*
326 * Search the pixel with highest peak value,
327 * which occurs during the first half of the scan
328 */
329 if(verbose>1) printf("searching for peak pixel\n");
330 imax.z=imax.y=imax.x=imax.f=1;
331 ret=imgGetPeak(&img, img.end[img.dimt/2], &imax, 2);
332 if(ret!=0) {
333 fprintf(stderr, "Error: cannot find peak pixel in image (%d).\n", ret);
334 imgEmpty(&img);
335 return(4);
336 }
337 maxv=img.m[imax.z-1][imax.y-1][imax.x-1][imax.f-1];
338 peakFrame=imax.f;
339 if(verbose>0) {
340 printf("peak_value := %g\n", maxv);
341 printf("peak_pos(z,y,x,t) := [%d,%d,%d,%d]\n", imax.z, imax.y, imax.x, imax.f);
342 }
343
344 /* Calculate average over time frames from zero to peak time,
345 search peak again to define the image subvolume that is used from
346 now on.
347 Also use sum ....
348 ... to search diameter using that, because vessel visualization will
349 be better BEFORE the peak than at the peak.
350 */
351 if(verbose>1) printf("summing image frames 1-%d\n", imax.f);
352 ret=imgFrameIntegral(&img, 0, imax.f-1, &simg, verbose-3);
353 if(verbose>1 && ret!=0) printf("imgFrameIntegral() := %d\n", ret);
354 if(ret==0) {
355 ret=imgArithmConst(&simg, img.end[imax.f-1]-img.start[0], '/', -1., verbose-3);
356 if(verbose>1 && ret!=0) printf("imgArithmConst() := %d\n", ret);
357 }
358 if(ret!=0) {
359 fprintf(stderr, "Error: cannot calculate sum image.\n");
360 imgEmpty(&img);
361 return(5);
362 }
363 if(verbose>1) printf("searching for peak pixel in sum image\n");
364 imax.z=imax.y=imax.x=imax.f=1;
365 ret=imgGetPeak(&simg, simg.end[0], &imax, 2);
366 if(ret!=0) {
367 fprintf(stderr, "Error: cannot find peak pixel in sum image (%d).\n", ret);
368 imgEmpty(&img); imgEmpty(&simg);
369 return(5);
370 }
371 maxv=simg.m[imax.z-1][imax.y-1][imax.x-1][imax.f-1];
372 if(verbose>0) {
373 printf("sum_peak_value := %g\n", maxv);
374 printf("sum_peak_pos(z,y,x,t) := [%d,%d,%d,%d]\n",
375 imax.z, imax.y, imax.x, imax.f);
376 }
377 /* This sum image is not needed any more; another will be made later */
378 imgEmpty(&simg);
379
380
381 /*
382 * Define the image subvolume that is used in the fitting;
383 * it should contain the whole vessel and some surroundings
384 * for estimation of background
385 */
386 if(verbose>1) printf("extracting image subvolume for fitting\n");
387 side=(int)ceil(fitsize/img.sizex);
388 if(verbose>1) printf("side := %d\n", side);
389 if(side<3 || side>img.dimx) {
390 fprintf(stderr, "Error: invalid fit square area.\n");
391 imgEmpty(&img);
392 return(6);
393 }
394 ir.f1=1; ir.f2=img.dimt; // all frames are needed
395 ir.x1=imax.x-side/2; if(ir.x1<1) ir.x1=1;
396 ir.y1=imax.y-side/2; if(ir.y1<1) ir.y1=1;
397 ir.x2=imax.x+side/2; if(ir.x2>img.dimx) ir.x2=img.dimx;
398 ir.y2=imax.y+side/2; if(ir.y2>img.dimy) ir.y2=img.dimy;
399 ir.z1=1; ir.z2=img.dimz; // all planes are always used in the fitting
400 if(verbose>1) printf("image fit volume: z=[%d,%d] y=[%d,%d] x=[%d,%d] f=[%d,%d]\n",
401 ir.z1, ir.z2, ir.y1, ir.y2, ir.x1, ir.x2, ir.f1, ir.f2);
402 xorig=imax.x; yorig=imax.y;
403 /*
404 * Extract the fit image range
405 */
406 ret=imgExtractRange(&img, ir, &rimg);
407 if(ret) {
408 fprintf(stderr, "Error in extracting image fit range: %s\n", rimg.statmsg);
409 imgEmpty(&img); dftEmpty(&dft);
410 return(7);
411 }
412 //imgInfo(&rimg);
413 /* If requested, write the extracted image as it is now to regfile */
414 if(regfile[0]) {
415 if(verbose>0) fprintf(stdout, "writing %s\n", regfile);
416 ret=imgWrite(regfile, &rimg);
417 if(ret) {
418 fprintf(stderr, "Error in writing image: %s\n", rimg.statmsg);
419 imgEmpty(&img); imgEmpty(&rimg);
420 return(7);
421 }
422 }
423 /* Original dynamic image is not needed any more */
424 imgEmpty(&img);
425 /* Note that after extraction, the previous peak position is not valid */
426
427
428 /*
429 * Estimate the position (center) of vessel and, if required, also
430 * the diameter of vessel for each plane (that is left).
431 *
432 * Use sum image from zero time to peak time in this fitting,
433 * because vessel may not be identifiable at all in later frames.
434 *
435 * Diameter and position estimated here will be fixed when Background
436 * and peak values are later fitted for each image frame.
437 */
438 /* LATER: try to fit all planes at the same time with common parameters
439 for bkg and art and radius, and separately for each plane the
440 posx,posy of center of vessel (preferably delta for that to allow
441 better limits for it).
442 */
443
444 if(verbose>1) {
445 printf("estimating the position of vessel centre");
446 if(diameter<0.0) printf(" and diameter");
447 if(FWHM<0.0) printf(" and FWHM");
448 printf("\n");
449 }
450
451 /* Compute sum image */
452 f=rimg.end[peakFrame-1]-rimg.start[0];
453 if(verbose>2) printf("summing first %g sec\n", f);
454 ret=imgFrameIntegral(&rimg, 0, peakFrame-1, &simg, verbose-4);
455 if(ret==0) ret=imgArithmConst(&simg, f, '/', -1., verbose-5);
456 if(ret!=0) {
457 fprintf(stderr, "Error: cannot calculate sum image.\n");
458 imgEmpty(&rimg);
459 return(8);
460 }
461 /* If requested, write the sum image as it is now to sumfile */
462 if(sumfile[0]) {
463 if(verbose>0) fprintf(stdout, "writing %s\n", sumfile);
464 ret=imgWrite(sumfile, &simg);
465 if(ret) {
466 fprintf(stderr, "Error in writing image: %s\n", simg.statmsg);
467 imgEmpty(&rimg); imgEmpty(&simg);
468 return(8);
469 }
470 }
471
472 /* Allocate memory for parameter values (p for one frame and all planes,
473 and pf for all frames and all planes) */
474 /* Frames are not fitted in current version, but keep the code for now */
475 if(verbose>1) printf("allocating memory for parameters\n");
476 planeNr=rimg.dimz;
477 chain=(double*)malloc(parNr*rimg.dimz*(rimg.dimt+1)*sizeof(double));
478 p=(double**)malloc(rimg.dimz*(rimg.dimt+1)*sizeof(double*));
479 pf=(double***)malloc(rimg.dimt*sizeof(double**));
480 if(chain==NULL || p==NULL || pf==NULL) {
481 fprintf(stderr, "Error: out of memory.\n");
482 imgEmpty(&rimg); imgEmpty(&simg); return(1);
483 }
484 for(fi=0, chainptr=chain; fi<=rimg.dimt; fi++) {
485 for(i=0; i<rimg.dimz; i++) {
486 p[fi*rimg.dimz+i]=chainptr;
487 chainptr+=parNr;
488 }
489 if(fi==0) continue; // first set is for one-frame fits
490 pf[fi-1]=p+fi*rimg.dimz;
491 }
492
493 /* Determine volume max and mean value, to be used to set initial values
494 for fitting the vessel diameter and position.
495 */
496 if(verbose>1) printf("searching for maximum pixel\n");
497 ret=imgRangeMinMax(&simg, NULL, &imax, &maxv, &imin, &minv);
498 if(ret==0) ret=imgAvg(&simg, NULL, &avg); // remove later
499 if(ret!=0) {
500 fprintf(stderr, "Error: invalid volume contents.\n");
501 imgEmpty(&rimg); imgEmpty(&simg);
502 free(pf); free(p); free(chain); return(15);
503 }
504 if(verbose>1) {
505 fprintf(stdout, "fit volume maxv=%g at x,y,z=(%d,%d,%d)\n",
506 maxv, imax.x, imax.y, imax.z);
507 fprintf(stdout, "fit volume avg=%g\n", avg);
508 }
509 if(maxv<=0.0) {
510 fprintf(stderr, "Error: invalid volume voxel contents.\n");
511 imgEmpty(&rimg); imgEmpty(&simg);
512 free(pf); free(p); free(chain); return(15);
513 }
514
515
516 /* Estimate volume peak position, to be used to set initial values
517 for fitting the vessel diameter and position.
518 */
519 ret=imgGetConcWeightedPeakPos(&simg, 0.8, &ppos, verbose-3);
520 if(ret!=0) {
521 fprintf(stderr, "Error: cannot find peak in image subvolume.\n");
522 imgEmpty(&rimg); imgEmpty(&simg);
523 free(pf); free(p); free(chain); return(16);
524 }
525 xorig=ppos.x-1; yorig=ppos.y-1;
526 if(verbose>1) {
527 printf("xorig := %g\n", xorig);
528 printf("yorig := %g\n", yorig);
529 }
530
531
532 /* For fitting, allocate memory for one image plane for 1) measured image,
533 * and 2) simulated image
534 */
535 if(verbose>1) printf("allocating memory for image planes for fitting\n");
536 ret=imgAllocateWithHeader(&pmimg, 1, simg.dimy, simg.dimx, 1,&simg);
537 if(ret==0) ret=imgAllocateWithHeader(&psimg, 1, simg.dimy, simg.dimx,1,&simg);
538 if(ret) {
539 fprintf(stderr, "Error: cannot allocate memory for image planes.\n");
540 imgEmpty(&simg); imgEmpty(&rimg);
541 free(pf); free(p); free(chain); return(17);
542 }
543 /* If user wants to save the fitted image, then we need to allocate memory for that too */
544 if(suffile[0]) {
545 if(verbose>1) printf("allocating memory for fitted image\n");
546 ret=imgAllocateWithHeader(&fimg, simg.dimz, simg.dimy, simg.dimx, 1, &simg);
547 if(ret) {
548 fprintf(stderr, "Error: cannot allocate memory for fitted image.\n");
549 imgEmpty(&simg); imgEmpty(&rimg); imgEmpty(&pmimg); imgEmpty(&psimg);
550 free(pf); free(p); free(chain); return(18);
551 }
552 }
553
554 /*
555 * Fit the vessel image model
556 */
557
558 /* Set initial values */
559 for(ppi=0; ppi<planeNr; ppi++) {
560 /* Background activity, should be about the avg */
561 p[ppi][P_BKG]=avg; if(p[ppi][P_BKG]<0.0) p[ppi][P_BKG]=0.0;
562 /* True activity in vessel */
563 p[ppi][P_PEAK]=maxv;
564 /* Coordinates of artery (in millimeters from upper left image corner) */
565 p[ppi][P_POSX]=(0.5+xorig)*simg.sizex;
566 p[ppi][P_POSY]=(0.5+yorig)*simg.sizey;
567 /* radius of the vessel (in millimeters) */
568 if(diameter>0.0) radius=0.5*diameter; else radius=6.0;
569 p[ppi][P_RAD]=radius;
570 /* FWHM (in millimeters) */
571 if(FWHM>0.0) p[ppi][P_FWHM]=FWHM; else p[ppi][P_FWHM]=8.0;
572 }
573 /* Set limits */
574 /* Note that now we are fitting only peak frame, where arterial activity
575 must be higher than background, but in other frames arterial curve may
576 be lower than background */
577 /* True Background activity */
578 pmin[P_BKG]=minv; pmax[P_BKG]=avg;
579 /* True activity in vessel */
580 pmin[P_PEAK]=avg; if(pmin[P_PEAK]<0.0) pmin[P_PEAK]=0.0;
581 pmax[P_PEAK]=avg+3.0*(maxv-avg);
582 /* Coordinates of artery (in millimeters from upper left image corner) */
583 pmin[P_POSX]=(xorig-0.45*(double)simg.dimx)*simg.sizex;
584 pmax[P_POSX]=(xorig+0.45*(double)simg.dimx)*simg.sizex;
585 pmin[P_POSY]=(yorig-0.45*(double)simg.dimy)*simg.sizey;
586 pmax[P_POSY]=(yorig+0.45*(double)simg.dimy)*simg.sizey;
587 /* radius of the vessel (in millimeters) */
588 if(diameter>0.0) pmin[P_RAD]=pmax[P_RAD]=0.5*diameter;
589 else {
590 pmin[P_RAD]=1.5;
591 pmax[P_RAD]=14.0; //0.33*simg.sizex*(double)simg.dimx;
592 }
593 /* FWHM (in millimeters)*/
594 if(FWHM>0.0) pmin[P_FWHM]=pmax[P_FWHM]=FWHM;
595 else {pmin[P_FWHM]=0.1; pmax[P_FWHM]=20.0;}
596 if(verbose>2) {
597 fprintf(stdout, "Initial values and constraints:\n");
598 for(pi=0; pi<parNr; pi++)
599 fprintf(stdout, "p=%g [%g, %g]\n", p[0][pi], pmin[pi], pmax[pi]);
600 }
601
602 /* Set TGO options */
603 int tgoNr, neighNr;
605 TGO_LOCAL_OPT=1; // 0=Powell-Brent, 1=Bobyqa
606 TGO_SQUARED_TRANSF=0; // 0;
607
608 /* Fit plane-by-plane (ppi is global, and used in func() */
609 if(verbose>0) printf("fitting image planes...\n");
610 for(ppi=0; ppi<planeNr; ppi++) {
611
612 if(verbose>2 && simg.dimz>1) printf("plane %d\n", 1+ppi);
613 if(verbose>5) printf(" initial_SS := %g\n", func(parNr, p[ppi], NULL));
614
615 /* Copy measured data from this image plane for use in func */
616 for(yi=0; yi<simg.dimy; yi++) for(xi=0; xi<simg.dimx; xi++)
617 pmimg.m[0][yi][xi][0]=simg.m[ppi][yi][xi][0];
618
619 tgoNr=1000; // 600
620 neighNr=6; // 4
621 ret=tgo(pmin, pmax, func, NULL, parNr, neighNr, &ss, p[ppi], tgoNr, 1, verbose-18);
622 if(ret>0) {
623 fprintf(stderr, "Error in optimization (%d).\n", ret);
624 imgEmpty(&rimg); imgEmpty(&simg); imgEmpty(&pmimg); imgEmpty(&psimg);
625 imgEmpty(&fimg);
626 free(pf); free(p); free(chain); return(20);
627 }
628 if(verbose>5) {
629 float tiffm=-1.0;
630 char fname[256];
631 sprintf(fname, "imgsim%0d.tif", 1+ppi);
632 tiffWriteImg(&psimg, 0, 0, &tiffm, PET_GRAYSCALE, fname,
633 0, 0, 0, NULL);
634 }
635
636 if(ret==1 && verbose>1) printf("Max iteration nr was reached.\n");
637 if(verbose>4) {
638 printf("param estimates:");
639 for(pi=0; pi<parNr; pi++) printf(" %g", p[ppi][pi]);
640 printf(" SS=%g\n", ss);
641 }
642
643 /* Print parameters in suitable format for automated tests */
644 if(verbose>1) {
645 printf("fwhm[%d] := %g\n", 1+ppi, p[ppi][P_FWHM]);
646 printf("radius[%d] := %g\n", 1+ppi, p[ppi][P_RAD]);
647 printf("posx[%d] := %g\n", 1+ppi, p[ppi][P_POSX]);
648 printf("posy[%d] := %g\n", 1+ppi, p[ppi][P_POSY]);
649 printf("peak[%d] := %g\n", 1+ppi, p[ppi][P_PEAK]);
650 printf("bkg[%d] := %g\n", 1+ppi, p[ppi][P_BKG]);
651 }
652
653 /* Copy simulated image plane for saving later, if necessary */
654 if(suffile[0]) {
655 for(yi=0; yi<simg.dimy; yi++) for(xi=0; xi<simg.dimx; xi++)
656 fimg.m[ppi][yi][xi][0]=psimg.m[0][yi][xi][0];
657 }
658
659 } /* next image plane */
660 /* Sum image and image planes for fitting are not needed any more */
661 imgEmpty(&simg); imgEmpty(&pmimg); imgEmpty(&psimg);
662
663 /* If required, save fitted image in file */
664 if(suffile[0]) {
665 printf("Writing fitted image in %s\n", suffile);
666 ret=imgWrite(suffile, &fimg);
667 if(ret) fprintf(stderr, "Error in writing %s\n", suffile);
668 imgEmpty(&fimg); // not needed anymore
669 }
670
671 /*
672 * If required, find the image plane with the highest fitted peak,
673 * and get the FWHM and vessel radius from that.
674 * Note: the highest estimated blood concentration is not searched,
675 * but the highest estimated peak pixel value, ie, estimated blood x RC.
676 */
677 if(mode_plane==P_BEST) {
678 double f, a;
679 best_plane=ppi=0; a=p[ppi][P_PEAK];
680 a*=rcPeakPET(p[ppi][P_FWHM], p[ppi][P_RAD]); f=a;
681printf("plane %d a=%g\n", 1, a);
682 for(ppi=1; ppi<rimg.dimz; ppi++) {
683 a=p[ppi][P_PEAK];
684 a*=rcPeakPET(p[ppi][P_FWHM], p[ppi][P_RAD]);
685 if(a>f) {f=a; best_plane=ppi;}
686printf("plane %d a=%g\n", 1+ppi, a);
687 }
688 if(verbose>1 && rimg.dimz>1) printf("best_plane := %d\n", 1+best_plane);
689 rad=radius=p[best_plane][P_RAD];
690 FWHM=p[best_plane][P_FWHM];
691 }
692
693 /*
694 * Otherwise, calculate the mean or median of FWHM and vessel radius
695 */
696 if(mode_plane==P_MEAN || mode_plane==P_MEDIAN) {
697 double *a, sd, avg, med;
698 a=(double*)malloc(rimg.dimz*sizeof(double));
699 /* radius */
700 for(ppi=0; ppi<rimg.dimz; ppi++) a[ppi]=p[ppi][P_RAD];
701 med=dmedian(a, rimg.dimz);
702 avg=dmean(a, rimg.dimz, &sd);
703 if(verbose>1 && rimg.dimz>1) {
704 printf(" radius_mean := %g\n", avg);
705 printf(" radius_sd := %g\n", sd);
706 printf(" radius_median := %g\n", med);
707 }
708 if(mode_plane==P_MEDIAN) radius=med; else radius=avg;
709 rad=radius;
710 /* FWHM */
711 for(ppi=0; ppi<rimg.dimz; ppi++) a[ppi]=p[ppi][P_FWHM];
712 med=dmedian(a, rimg.dimz);
713 avg=dmean(a, rimg.dimz, &sd);
714 if(verbose>1 && rimg.dimz>1) {
715 printf(" FWHM_mean := %g\n", avg);
716 printf(" FWHM_sd := %g\n", sd);
717 printf(" FWHM_median := %g\n", med);
718 }
719 if(mode_plane==P_MEDIAN) FWHM=med; else FWHM=avg;
720 free(a);
721 }
722 if(verbose>0) printf("vessel_radius := %g\n", radius);
723 if(verbose>0) printf("FWHM := %g\n", FWHM);
724
725
726 /*
727 * Calculate the recovery coefficient for zero background
728 */
729 reccoef=rcPeakPET(FWHM, rad);
730 if(verbose>0) printf("RC := %g\n", reccoef);
731 if(verbose>0) printf("Correction factor (1/RC) := %.2f\n", 1.0/reccoef);
732
733
734 /*
735 * Make DFT for saving blood TACs
736 */
737 if(verbose>2) printf("allocating memory for blood TAC\n");
738 // ... and background and non-corrected peak TACs for testing
739 ret=dftAllocateWithIMG(&dft, 3, &rimg);
740 //if(ret==0) ret=dftAllocateWithIMG(&bdft, 1, &img);
741 if(ret!=0) {
742 fprintf(stderr, "Error: cannot allocate memory for blood TACs.\n");
743 imgEmpty(&rimg);
744 free(pf); free(p); free(chain); return(31);
745 }
746 sprintf(dft.voi[0].voiname, "Blood");
747 sprintf(dft.voi[1].voiname, "Backgr");
748 sprintf(dft.voi[2].voiname, "Peak");
749 for(i=0; i<3; i++) strcpy(dft.voi[i].name, dft.voi[i].voiname);
751
752
753 /*
754 * Calculate mean of pixel values representing the centre of vessel
755 * and background from each plane and frame.
756 * Max 1/5 of vessel diameter should be used (Germano et al.) so that
757 * the RC calculated at the centre would be valid.
758 * Difference between vessel and background will be RC corrected.
759 * Model parameter C must not be RC corrected, because it represents
760 * already the 'correct' blood value. Simulated peak pixel value
761 * could be used as blood value after RC correction, unless it is
762 * simulated with Germano model, which tends to overestimate it.
763 */
764 if(verbose>1) printf("estimating peak and background level\n");
765 /* Make a template image for the peak and background regions */
766 IMG mask;
767 imgInit(&mask);
768 ret=imgAllocateWithHeader(&mask, rimg.dimz, rimg.dimy, rimg.dimx, 1, &rimg);
769 if(ret) {
770 fprintf(stderr, "Error in allocating memory for mask image.\n");
771 imgEmpty(&rimg);
772 free(pf); free(p); free(chain); dftEmpty(&dft);
773 return(40);
774 }
775 /* Estimate the vessel region from every plane, or just the best plane */
776 double mv=0.0, r=0.0;
777 int pxlMinNr;
778 pxlMinNr=1; if(best_plane>=0) pxlMinNr+=2;
779 for(ppi=0; ppi<planeNr; ppi++) {
780 if(best_plane>=0 && best_plane!=ppi) continue;
781 if(verbose>1) printf("vessel plane := %d\n", 1+ppi);
782 r=rad/6.0; mv=0.0; ret=0;
783 while(mv<pxlMinNr && ret==0) {
784 if(verbose>2) printf("r := %g\n", r);
785 if(verbose>2) printf("mv := %g\n", mv);
786 ret=imgCircleMask(&mask, ppi, p[ppi][P_POSX], p[ppi][P_POSY], r, 1.0,
787 &mv, verbose-9);
788 if(mv<pxlMinNr) r+=0.35*rimg.sizex;
789 }
790 if(ret) {
791 fprintf(stderr, "Error: cannot create mask mask image.\n");
792 imgEmpty(&rimg); imgEmpty(&mask);
793 free(pf); free(p); free(chain); dftEmpty(&dft);
794 return(42);
795 }
796 }
797 if(verbose>0) printf("vessel ROI radius: %g\n", r);
798 if(verbose>2) {
799 float tiffm=1.0;
800 tiffWriteImg(&mask, -1, -1, &tiffm, PET_GRAYSCALE, "peakmask.tif", 0, 0, 0, NULL);
801 }
802 ret=imgMaskTAC(&rimg, &mask, dft.voi[2].y, verbose-7);
803 if(ret!=0) {
804 fprintf(stderr, "Error: cannot calculate vessel TAC.\n");
805 imgEmpty(&rimg); imgEmpty(&mask);
806 dftEmpty(&dft);
807 return(43);
808 }
809 if(verbose>4) {
810 /* For testing, save TACs of each pixel */
811 DFT pdft;
812 dftInit(&pdft);
813 ret=imgMaskPixelTACs(&rimg, &mask, 0.1, &pdft, verbose-10);
814 if(ret!=0) {
815 fprintf(stderr, "Error: cannot extract pixel TACs.\n");
816 } else {
817 ret=dftWrite(&pdft, "peakpixels.dft");
818 if(ret!=0) fprintf(stderr, "Error: cannot save pixel TACs.\n");
819 }
820 dftEmpty(&pdft);
821 }
822 /* Estimate the background region from every plane, or just the best plane */
823 double r1, r2;
824 pxlMinNr=2; if(best_plane>=0) pxlMinNr+=3;
825 for(i=0; i<mask.dimz*mask.dimy*mask.dimx; i++) mask.pixel[i]=0.0;
826 for(ppi=0; ppi<planeNr; ppi++) {
827 if(best_plane>=0 && best_plane!=ppi) continue;
828 if(verbose>2) printf("background plane := %d\n", 1+ppi);
829 r1=rad+2.4*FWHM; r2=rad+2.5*FWHM; mv=0.0; ret=0;
830 while(mv<pxlMinNr && ret==0 && r1>0.0) {
831 if(verbose>3) printf("r1 := %g\n", r1);
832 if(verbose>3) printf("r2 := %g\n", r2);
833 ret=imgRingMask(&mask, ppi, p[ppi][P_POSX], p[ppi][P_POSY], r1, r2, 1.0, &mv, verbose-10);
834 r1-=0.5*rimg.sizex;
835 }
836 if(ret) {
837 fprintf(stderr, "Error: cannot create mask mask image.\n");
838 imgEmpty(&rimg); imgEmpty(&mask);
839 free(pf); free(p); free(chain); dftEmpty(&dft);
840 return(44);
841 }
842 }
843 if(verbose>4) {
844 float tiffm=1.0;
845 tiffWriteImg(&mask, -1, -1, &tiffm, PET_GRAYSCALE, "bkgmask.tif", 0, 0, 0, NULL);
846 }
847 ret=imgMaskTAC(&rimg, &mask, dft.voi[1].y, verbose-7);
848 if(ret!=0) {
849 fprintf(stderr, "Error: cannot calculate background TAC.\n");
850 imgEmpty(&rimg); imgEmpty(&mask);
851 dftEmpty(&dft);
852 return(45);
853 }
854 if(verbose>6) {
855 /* For testing, save TACs of each pixel */
856 DFT pdft;
857 dftInit(&pdft);
858 ret=imgMaskPixelTACs(&rimg, &mask, 0.1, &pdft, verbose-10);
859 if(ret!=0) {
860 fprintf(stderr, "Error: cannot extract pixel TACs.\n");
861 } else {
862 ret=dftWrite(&pdft, "bkgpixels.dft");
863 if(ret!=0) fprintf(stderr, "Error: cannot save pixel TACs.\n");
864 }
865 dftEmpty(&pdft);
866 }
867 /* Mask image is no longer needed */
868 imgEmpty(&mask);
869
870 /* Model parameters are no longer needed */
871 free(pf); free(p); free(chain);
872
873
874 /*
875 * Calculate recovery corrected blood TAC
876 */
877 for(fi=0; fi<rimg.dimt; fi++) {
878 /* calculate the difference between vessel centre and background */
879 dft.voi[0].y[fi]=dft.voi[2].y[fi]-dft.voi[1].y[fi];
880 /* correct that for RC */
881 dft.voi[0].y[fi]*=(1.0/reccoef);
882 /* add background */
883 dft.voi[0].y[fi]+=dft.voi[1].y[fi];
884 }
885
886 /*
887 * Save the recovery corrected blood TAC
888 */
889 if(verbose>1) printf("saving recovery corrected blood TAC\n");
890 snprintf(tmp, 512, "# Image-derived input from %s\n", imgfile);
891 strcpy(dft.comments, tmp);
892 {
893 char prname[64];
894 tpcProgramName(argv[0], 0, 0, prname, 64);
895 snprintf(tmp, 512, "# Program: %s\n", prname);
896 strcat(dft.comments, tmp);
897 }
898 snprintf(tmp, 512, "# FWHM: %g mm\n", FWHM);
899 strcat(dft.comments, tmp);
900 snprintf(tmp, 512, "# vessel_diameter: %g mm\n", 2.0*rad);
901 strcat(dft.comments, tmp);
902 snprintf(tmp, 512, "# RC: %g\n", reccoef);
903 strcat(dft.comments, tmp);
904 dft.voiNr=1;
905 ret=dftWrite(&dft, tacfile);
906 if(ret) {
907 fprintf(stderr, "Error in writing %s: %s\n", tacfile, dfterrmsg);
908 imgEmpty(&rimg);
909 dftEmpty(&dft); return(61);
910 }
911 if(verbose>0) fprintf(stdout, "Corrected blood TAC written in %s\n", tacfile);
912
913
914 /*
915 * Save the background TAC, if required
916 */
917 if(bkgfile[0]) {
918 if(verbose>1) printf("saving background tac\n");
919 snprintf(tmp, 512, "# Image-derived input background from %s\n", imgfile);
920 strcpy(dft.comments, tmp);
921 {
922 char prname[64];
923 tpcProgramName(argv[0], 0, 0, prname, 64);
924 snprintf(tmp, 512, "# Program: %s\n", prname);
925 strcat(dft.comments, tmp);
926 }
927 snprintf(tmp, 512, "# FWHM: %g mm\n", FWHM);
928 strcat(dft.comments, tmp);
929 snprintf(tmp, 512, "# vessel_diameter: %g mm\n", 2.0*rad);
930 strcat(dft.comments, tmp);
931 snprintf(tmp, 512, "# RC: %g\n", reccoef);
932 strcat(dft.comments, tmp);
933 for(fi=0; fi<dft.frameNr; fi++) dft.voi[0].y[fi]=dft.voi[1].y[fi];
934 strcpy(dft.voi[0].voiname, dft.voi[1].voiname);
935 strcpy(dft.voi[0].name, dft.voi[1].name);
936 dft.voiNr=1;
937 ret=dftWrite(&dft, bkgfile);
938 if(ret) {
939 fprintf(stderr, "Error in writing %s: %s\n", bkgfile, dfterrmsg);
940 imgEmpty(&rimg);
941 dftEmpty(&dft); return(62);
942 }
943 if(verbose>0) fprintf(stdout, "Background TAC written in %s\n", bkgfile);
944 }
945
946
947 /*
948 * Save the noncorrected vessel peak, if required
949 */
950 if(maxfile[0]) {
951 if(verbose>1) printf("saving noncorrected vessel peak tac\n");
952 snprintf(tmp, 512, "# Image-derived non-corrected peak TAC from %s\n", imgfile);
953 strcpy(dft.comments, tmp);
954 {
955 char prname[64];
956 tpcProgramName(argv[0], 0, 0, prname, 64);
957 snprintf(tmp, 512, "# Program: %s\n", prname);
958 strcat(dft.comments, tmp);
959 }
960 snprintf(tmp, 512, "# FWHM: %g mm\n", FWHM);
961 strcat(dft.comments, tmp);
962 snprintf(tmp, 512, "# vessel_diameter: %g mm\n", 2.0*rad);
963 strcat(dft.comments, tmp);
964 for(fi=0; fi<dft.frameNr; fi++) dft.voi[0].y[fi]=dft.voi[2].y[fi];
965 strcpy(dft.voi[0].voiname, "Peak");
966 strcpy(dft.voi[0].name, dft.voi[0].voiname);
967 dft.voiNr=1;
968 ret=dftWrite(&dft, maxfile);
969 if(ret) {
970 fprintf(stderr, "Error in writing %s: %s\n", maxfile, dfterrmsg);
971 imgEmpty(&rimg);
972 dftEmpty(&dft); return(63);
973 }
974 if(verbose>0)
975 fprintf(stdout, "Noncorrected vessel peak TAC written in %s\n", maxfile);
976 }
977
978 /* Free memory */
979 dftEmpty(&dft); imgEmpty(&rimg);
980
981 return(0);
982}
983/*****************************************************************************/
984
985/*****************************************************************************/
1002double func(int parNr, double *p, void *fdata)
1003{
1004 int xi, yi, pi, n=0, ret;
1005 double cbkg[1], cart[1], rad, xart, yart, FWHM, d, ss=0.0;
1006 double pa[MAX_PARAMETERS], penalty=1.0;
1007 int model;
1008
1009 if(fdata) {}
1010
1011 /* Check parameters */
1012 if(0) {
1013 for(pi=0; pi<parNr; pi++) printf(" p[%d]=%g", pi, p[pi]);
1014 printf("\n");
1015 }
1016 modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
1017
1018 /* Simulate the 2D matrix */
1019 cbkg[0]=pa[0]; cart[0]=pa[1];
1020 xart=pa[2]; yart=pa[3]; rad=pa[4]; FWHM=pa[5];
1021 model=0; if(vessel_model==VM_GAUSSIAN) model=1;
1022 ret=idiSimulateTubeImgPlane(model, &psimg, 0, xart, yart, rad, FWHM,
1023 cbkg, cart);
1024 if(ret!=0) {
1025 if(1) fprintf(stderr, " error in idiSimulateTubeImagePlane()\n");
1026 return(nan(""));
1027 }
1028
1029 if(vessel_model==VM_GAUSSIAN) {
1030 double s=FWHM/2.354820;
1031 s/=pmimg.sizex;
1032 ret=imgGaussianFIRFilter(&psimg, s, s, 0, 1.0E-06, 0);
1033 if(ret!=0) {
1034 if(1) fprintf(stderr, " error in imgGaussianFIRFilter()\n");
1035 return(nan(""));
1036 }
1037 }
1038
1039 /* Calculate SS/n between simulated and measured image matrix */
1040 for(yi=0; yi<psimg.dimy; yi++) {
1041 for(xi=0; xi<psimg.dimx; xi++) {
1042 d=psimg.m[0][yi][xi][0]-pmimg.m[0][yi][xi][0];
1043 ss+=d*d; n++;
1044 }
1045 }
1046 if(n>0) ss/=(double)n;
1047 ss*=penalty;
1048 return(ss);
1049}
1050/*****************************************************************************/
1051
1052/*****************************************************************************/
int imgRingMask(IMG *img, int zi, double cx, double cy, double r1, double r2, double mv, double *smv, int verbose)
Definition circle.c:77
int imgCircleMask(IMG *img, int zi, double cx, double cy, double r, double mv, double *smv, int verbose)
Definition circle.c:16
int modelCheckParameters(int par_nr, double *lower_p, double *upper_p, double *test_p, double *accept_p, double *penalty)
Definition constraints.c:15
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
void dftEmpty(DFT *data)
Definition dft.c:20
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
int imgMaskPixelTACs(IMG *img, IMG *mask, double thrs, DFT *dft, int verbose)
Definition idimask.c:17
int IMG_TEST
Definition img.c:6
int imgExistentTimes(IMG *img)
Definition img.c:613
unsigned long long imgNaNs(IMG *img, int fix)
Definition img.c:658
int imgExtractRange(IMG *img1, IMG_RANGE r, IMG *img2)
Definition img.c:548
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgFrameIntegral(IMG *img, int first, int last, IMG *iimg, int verbose)
Definition imgarithm.c:346
int imgArithmConst(IMG *img, float operand, char operation, float ulimit, int verbose)
Definition imgarithm.c:100
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
int imgMaskTAC(IMG *img, IMG *mask, double *tac, int verbose)
Definition imgeval.c:126
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
int imgGaussianFIRFilter(IMG *img, float xsd, float ysd, float zsd, double tolerance, int verbose)
Definition imgfilter.c:18
int imgAvg(IMG *img, IMG_RANGE *r, float *avg)
Definition imgminmax.c:503
int imgRangeMinMax(IMG *img, IMG_RANGE *r, IMG_PIXEL *maxp, float *maxv, IMG_PIXEL *minp, float *minv)
Definition imgminmax.c:71
int imgGetPeak(IMG *img, float beforeTime, IMG_PIXEL *p, int verbose)
Definition imgminmax.c:294
int tiffWriteImg(IMG *img, int plane, int frame, float *maxvalue, int colorscale, char *fname, int matXdim, int matYdim, int verbose, char *status)
Definition imgtiff.c:15
Header file for libtpccurveio.
#define DFT_TIME_STARTEND
Header file for libtpcidi.
double rcPeakPET(double FWHM, double R)
Definition recovery.c:24
int idiSimulateTubeImgPlane(int simmet, IMG *img, int zi, double cx, double cy, double r, double FWHM, double *cbkg, double *cblo)
Definition vessel.c:143
int imgGetConcWeightedPeakPos(IMG *img, float thrs, IMG_PIXEL *pos, int verbose)
Definition peak.c:14
Header file for libtpcimgio.
int VOL_TEST
Definition vol.c:6
#define IMG_TYPE_IMAGE
Header file for libtpcimgp.
#define PET_GRAYSCALE
Definition libtpcimgp.h:32
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
Definition proginfo.c:101
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
Header file for libtpcmodel.
int tgo(double *lowlim, double *uplim, double(*objf)(int, double *, void *), void *objfData, int dim, int neighNr, double *fmin, double *gmin, int samNr, int tgoNr, int verbose)
Definition tgo.c:39
int TGO_LOCAL_INSIDE
Definition tgo.c:29
#define MAX_PARAMETERS
Definition libtpcmodel.h:31
int TGO_LOCAL_OPT
Definition tgo.c:31
int TGO_SQUARED_TRANSF
Definition tgo.c:27
double dmean(double *data, int n, double *sd)
Definition median.c:73
double dmedian(double *data, int n)
Definition median.c:48
Header file for libtpcmodext.
int dftAllocateWithIMG(DFT *dft, int tacNr, IMG *img)
Definition misc_model.c:296
int timetype
Voi * voi
char comments[_DFT_COMMENT_LEN+1]
int voiNr
int frameNr
float * pixel
float sizex
unsigned short int dimx
char type
float **** m
unsigned short int dimt
float sizey
float * start
unsigned short int dimz
unsigned short int dimy
float * end
const char * statmsg
float * mid
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]