TPCCLIB
Loading...
Searching...
No Matches
tacweigh.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 <string.h>
14#include <math.h>
15#include <unistd.h>
16/*****************************************************************************/
17#include "tpcextensions.h"
18#include "tpccsv.h"
19#include "tpcift.h"
20#include "tpctac.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Add or remove the sample (time frame) weighting information to TAC file for",
26 "parameter estimations and curve fitting using formula (Mazoyer et al, 1986):",
27 " weight=(frame duration)^2 / (decay corrected trues in a frame)",
28 "or optionally:",
29 " weight=(frame duration),",
30 "or:",
31 " weight=(frame duration)*exp(-t*ln(2)/halflife),",
32 " ",
33 "TACs are assumed to be corrected for decay, and SIFs not corrected.",
34 "The relative weights are adjusted using a scan information file (SIF),",
35 "or TACs in the file (volume weighted average of all TACs or given TAC);",
36 "in the latter case the units in TAC file must be set correctly.",
37 " ",
38 "Usage: @P [Options] tacfile [sif | tacname]",
39 " ",
40 "Options:",
41 " -rm",
42 " Existing weights are removed.",
43 " -list",
44 " Weights are not calculated, but existing weights are printed on screen.",
45 " Return code is non-zero if data does not contain weights.",
46 " -wf | -wfd",
47 " With -wf Weights are based only on frame length or sampling interval.",
48 " With -wfd the late frames are given less weight by using formula:",
49 " weight=(frame duration)*exp(-t*ln(2)/halflife) (Thiele et al, 2008).",
50 " -i=<Isotope code>",
51 " Isotope, for example C-11, in case it is not found inside SIF or TAC",
52 " file. Isotope is only needed with SIF, and with option -wfd.",
53 " -moderate=<ratio>",
54 " Weights are moderated by limiting the ratio of maximum and minimum",
55 " weights to the given ratio (100 by default). Weights that are lower",
56 " than maximum/ratio are set to maximum/ratio. Enter zero to not",
57 " moderate the weights. Otherwise ratio must be larger than one.",
58 " -sif=<Filename>",
59 " SIF data based on TAC file is written in given file; cannot be used",
60 " if SIF is given as argument.",
61 " -stdoptions", // List standard options like --help, -v, etc
62 " ",
63 "Note that absolute weights cannot be calculated. Relative weights are",
64 "scaled so that average weight is 1.0 for frames that have weight above 0.",
65 " ",
66 "Reference:",
67 "1. Mazoyer BM, Huesman RH, Budinger TF, Knittel BL. Dynamic PET data",
68 " analysis. J Comput Assist Tomogr 1986; 10:645-653.",
69 "2. Thiele F, Buchert R. Evaluation of non-uniform weighting in non-linear",
70 " regression for pharmacokinetic neuroreceptor modelling.",
71 " Nucl Med Commun. 2008; 29:179-188.",
72 " ",
73 "See also: sifcat, sifisot, taclist, imgweigh, tacframe, imghead, tacdecay",
74 " ",
75 "Keywords: TAC, SIF, modelling, weighting, fitting",
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/*****************************************************************************/
94int main(int argc, char **argv)
95{
96 int ai, help=0, version=0, verbose=1;
97 char siffile[FILENAME_MAX], tacfile[FILENAME_MAX], newsif[FILENAME_MAX];
98 double weight_moderate=100.0;
99 int weight_method=WEIGHTING_ON_COUNTS;
100 int remove_weights=0;
101 int print_weights=0;
103
104
105 /*
106 * Get arguments
107 */
108 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
109 siffile[0]=tacfile[0]=newsif[0]=(char)0;
110 /* Options */
111 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
112 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
113 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
114 if(strncasecmp(cptr, "LIST", 1)==0) {
115 print_weights=1; continue;
116 } else if(strcasecmp(cptr, "RM")==0 || strcasecmp(cptr, "DEL")==0) {
117 remove_weights=1; continue;
118 } else if(strncasecmp(cptr, "I=", 2)==0) {
119 if((isot=isotopeIdentify(cptr+2))==ISOTOPE_UNKNOWN) {
120 fprintf(stderr, "Error: invalid isotope '%s'.\n", cptr+2); return(1);}
121 continue;
122 } else if(strncasecmp(cptr, "SIF=", 4)==0) {
123 cptr+=4; strlcpy(newsif, cptr, FILENAME_MAX); if(strlen(newsif)>0) continue;
124 } else if(strncasecmp(cptr, "moderate=", 9)==0) {
125 cptr+=9; weight_moderate=atofVerified(cptr);
126 if(weight_moderate>1.0) continue;
127 if(weight_moderate<=0.0) continue;
128 } else if(strcasecmp(cptr, "WF")==0) {
129 weight_method=WEIGHTING_ON_F; continue;
130 } else if(strcasecmp(cptr, "WFD")==0) {
131 weight_method=WEIGHTING_ON_FD; continue;
132 }
133 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
134 return(1);
135 } else break; // tac name argument may start with '-'
136
137 /* Print help or version? */
138 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
139 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
140 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
141
142 TPCSTATUS status; statusInit(&status);
143 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
144 status.verbose=verbose-1;
145
146 /* Process other arguments, starting from the first non-option */
147 if(ai<argc) {strlcpy(tacfile, argv[ai++], FILENAME_MAX);}
148 if(ai<argc) {strlcpy(siffile, argv[ai++], FILENAME_MAX);}
149 if(ai<argc) {
150 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
151 return(1);
152 }
153 if(siffile[0] && (weight_method==WEIGHTING_ON_F || weight_method==WEIGHTING_ON_FD)) {
154 fprintf(stderr, "Warning: using options -wf and -wfd with SIF is not recommended.\n");
155 }
156
157 /* Is something missing? */
158 if(!tacfile[0]) {
159 fprintf(stderr, "Error: missing file name; use option --help\n");
160 return(1);
161 }
162
163 /* In verbose mode print arguments and options */
164 if(verbose>1) {
165 printf("tacfile := %s\n", tacfile);
166 //printf("siffile := %s\n", siffile); // may actually be TAC name
167 if(newsif[0]) printf("newsif := %s\n", newsif);
168 printf("print_weights := %d\n", print_weights);
169 printf("remove_weights := %d\n", remove_weights);
170 printf("weight_method := %d\n", weight_method);
171 if(isot!=ISOTOPE_UNKNOWN) printf("isotope := %s\n", isotopeName(isot));
172 printf("moderate := %g\n", weight_moderate);
173 fflush(stdout);
174 }
175
176
177
178 /*
179 * Read TAC data
180 */
181 if(verbose>1) {fprintf(stdout, "reading %s\n", tacfile); fflush(stdout);}
182 TAC tac; tacInit(&tac);
183 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
184 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), tacfile);
185 tacFree(&tac); return(2);
186 }
187 if(verbose>2) {
188 printf("weighting := %d\n", tac.weighting);
189 printf("fileformat := %s\n", tacFormattxt(tac.format));
190 printf("tacNr := %d\n", tac.tacNr);
191 printf("sampleNr := %d\n", tac.sampleNr);
192 printf("xunit := %s\n", unitName(tac.tunit));
193 printf("yunit := %s\n", unitName(tac.cunit));
194 if(tac.isframe) printf("frames := yes\n"); else printf("frames := no\n");
195 fflush(stdout);
196 }
197 if(verbose>2) {
198 printf("contains_weights := ");
199 if(tacIsWeighted(&tac)) printf("yes\n"); else printf("no\n");
200 fflush(stdout);
201 }
202
203
204 /*
205 * Print existing weights, if required, and quit
206 */
207 if(print_weights!=0) {
208 if(verbose>2) printf("printing existing weights\n");
209 if(!tacIsWeighted(&tac)) {
210 printf("contains_weights := no\n");
211 //printf("%s does not contain weights.\n", tacfile);
212 tacFree(&tac); return(100);
213 } else if(tac.isframe) {
214 printf("start[]\tend[]\tweight\n");
215 for(int i=0; i<tac.sampleNr; i++) printf("%g\t%g\t%.4e\n", tac.x1[i], tac.x2[i], tac.w[i]);
216 tacFree(&tac); return(0);
217 } else {
218 printf("time[]\tweight\n");
219 for(int i=0; i<tac.sampleNr; i++) printf("%g\t%.4e\n", tac.x[i], tac.w[i]);
220 tacFree(&tac); return(0);
221 }
222 }
223
224 /* Check if datafile contains information on decay correction */
226 if(fdc==DECAY_UNKNOWN) {
227 if(verbose>1) printf("Note: status of current decay correction is not known.\n");
228 } else if(fdc==DECAY_CORRECTED) {
229 if(verbose>1) fprintf(stderr, "Note: physical decay is corrected in %s.\n", tacfile);
230 } else if(fdc==DECAY_NOTCORRECTED) {
231 fprintf(stderr, "Note: physical decay is not corrected in %s.\n", tacfile);
232 }
233
234 /* If datafile contains valid isotope, then check that it is the same as given by user. */
235 /* Not all methods need isotope. */
236 /* No problem if isotope is not yet known, because it may be in SIF */
237 {
238 isotope fisot=tacGetIsotope(&tac);
239 if(verbose>3) {printf("tac.isotope := %s\n", isotopeName(fisot)); fflush(stdout);}
240 if(isot==ISOTOPE_UNKNOWN && fisot==ISOTOPE_UNKNOWN) {
241 if(!siffile[0] && (weight_method==WEIGHTING_ON_COUNTS || weight_method==WEIGHTING_ON_FD)) {
242 fprintf(stderr, "Error: valid isotope not specified.\n");
243 tacFree(&tac); return(1);
244 }
245 } else if(isot==ISOTOPE_UNKNOWN && fisot!=ISOTOPE_UNKNOWN) {
246 isot=fisot;
247 if(verbose>1) printf("isotope := %s\n", isotopeName(isot));
248 } else if(isot!=ISOTOPE_UNKNOWN && fisot==ISOTOPE_UNKNOWN) {
249 fisot=isot;
250 tacSetIsotope(&tac, fisot);
251 //if(verbose>1) printf("isotope := %s\n", isotopeName(isot));
252 }
253 if(isot!=fisot && (weight_method==WEIGHTING_ON_COUNTS || weight_method==WEIGHTING_ON_FD)) {
254 fprintf(stderr, "Error: different isotope in %s\n", tacfile);
255 tacFree(&tac); return(3);
256 }
257 }
258
259
260
261 /*
262 * Remove the stored weights, if requested
263 */
264 if(remove_weights!=0) {
265 if(verbose>1) printf("removing weights\n");
266 if(!tacIsWeighted(&tac)) {
267 printf("%s does not contain weights.\n", tacfile);
268 tacFree(&tac); return(0);
269 }
271 if(verbose>1) printf("saving modified %s\n", tacfile);
272 FILE *fp; fp=fopen(tacfile, "w");
273 if(fp==NULL) {
274 fprintf(stderr, "Error: cannot open file for writing\n");
275 tacFree(&tac); return(11);
276 }
277 int ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
278 fclose(fp);
279 if(ret!=TPCERROR_OK) {
280 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
281 tacFree(&tac); return(12);
282 }
283 /* Tell user what we did */
284 if(verbose>0) printf("Weights removed in %s\n", tacfile);
285 tacFree(&tac); return(0);
286 }
287
288
289 /*
290 * Try to read SIF or identify specified 'head' TAC
291 */
292 TAC sif; tacInit(&sif);
293 int headIndex=-1;
294 if(siffile[0]) { /* User gave either SIF or TAC name */
295 /* Check if this is SIF file */
296 if(verbose>1) {fprintf(stdout, "trying to read %s\n", siffile); fflush(stdout);}
297 int ret=tacRead(&sif, siffile, &status);
298 if(ret==TPCERROR_OK) {
299 if(verbose>2) {
300 printf("sif.weighting := %d\n", sif.weighting);
301 printf("sif.fileformat := %s\n", tacFormattxt(sif.format));
302 printf("sif.tacNr := %d\n", sif.tacNr);
303 printf("sif.sampleNr := %d\n", sif.sampleNr);
304 printf("sif.xunit := %s\n", unitName(sif.tunit));
305 printf("sif.yunit := %s\n", unitName(sif.cunit));
306 if(sif.isframe) printf("sif.frames := yes\n"); else printf("sif.frames := no\n");
307 fflush(stdout);
308 }
309 if(sif.format!=TAC_FORMAT_SIF) {
310 fprintf(stderr, "Error: file is not in SIF format.\n");
311 tacFree(&tac); tacFree(&sif); return(4);
312 }
313 if(verbose>1) printf("%s is SIF\n", siffile);
314 /* tacReadSIF() adds column for trues but does not include it in tacNr */
315 if(sif.tacNr!=2 || sif._tacNr!=3) {
316 fprintf(stderr, "Error: invalid SIF.\n");
317 tacFree(&tac); tacFree(&sif); return(4);
318 }
319 double promptMax, randomMax;
320 if(tacYRange(&sif, 0, NULL, &promptMax, NULL, NULL, NULL, NULL) ||
321 tacYRange(&sif, 1, NULL, &randomMax, NULL, NULL, NULL, NULL))
322 {
323 fprintf(stderr, "Error: invalid SIF.\n");
324 tacFree(&tac); tacFree(&sif); return(4);
325 }
326 if(verbose>2) printf(" promptMax := %g\n randomMax := %g\n", promptMax, randomMax);
327 if(!(promptMax>0.0)) {
328 if(weight_method==WEIGHTING_ON_COUNTS) {
329 fprintf(stderr, "Error: SIF does not contain prompts.\n");
330 tacFree(&tac); tacFree(&sif); return(4);
331 }
332 fprintf(stderr, "Warning: SIF does not contain prompts.\n"); fflush(stderr);
333 }
334 if(!(randomMax>0.0)) {
335 fprintf(stderr, "Warning: SIF does not contain randoms.\n"); fflush(stderr);
336 }
337 } else { // siffile is not an existing file; check if it is a TAC name
338 if(verbose>1) fprintf(stdout, "trying to find TAC %s\n", siffile);
339 int n=tacSelectTACs(&tac, siffile, 1, &status);
340 if(n<1) {
341 fprintf(stderr, "Error: no TAC matching '%s' was found.\n", siffile);
342 tacFree(&tac); return(4);
343 }
344 if(n>1) {
345 if(verbose>1) printf(" %d TACs match '%s'.\n", n, siffile);
346 headIndex=tacSelectBestReference(&tac);
347 } else {
348 for(int i=0; i<tac.tacNr; i++) if(tac.c[i].sw) {headIndex=i; break;}
349 }
350 if(headIndex>=0) {
351 if(verbose>0) printf("headTAC := %s\n", tac.c[headIndex].name);
352 } else {
353 fprintf(stderr, "Error: no single TAC matching '%s' was found.\n", siffile);
354 tacFree(&tac); return(4);
355 }
356 strcpy(siffile, "");
357 }
358 }
359
360
361 /*
362 * If we have a SIF, then try to find isotope inside it,
363 * and check that time frames match the TAC data.
364 */
365 if(sif.sampleNr>0) {
366 isotope fisot=tacGetIsotope(&sif);
367 if(verbose>3) {printf("sif.isotope := %s\n", isotopeName(fisot)); fflush(stdout);}
368 if(isot==ISOTOPE_UNKNOWN && fisot==ISOTOPE_UNKNOWN) {
369 fprintf(stderr, "Error: valid isotope not specified.\n");
370 tacFree(&tac); tacFree(&sif); return(3);
371 }
372 if(isot==ISOTOPE_UNKNOWN && fisot!=ISOTOPE_UNKNOWN) {
373 isot=fisot;
374 tacSetIsotope(&tac, fisot);
375 if(verbose>1) printf("isotope := %s\n", isotopeName(isot));
376 } else if(isot!=ISOTOPE_UNKNOWN && fisot==ISOTOPE_UNKNOWN) {
377 fisot=isot;
378 tacSetIsotope(&sif, fisot);
379 }
380 if(isot!=fisot) {
381 fprintf(stderr, "Error: different isotope in %s\n", siffile);
382 tacFree(&tac); tacFree(&sif); return(4);
383 }
384 if(isot==ISOTOPE_UNKNOWN && (weight_method==WEIGHTING_ON_COUNTS || weight_method==WEIGHTING_ON_FD))
385 {
386 fprintf(stderr, "Error: isotope is required with SIF and selected weighting method.\n");
387 tacFree(&tac); tacFree(&sif); return(4);
388 }
389 if(sif.sampleNr!=tac.sampleNr || !tacXMatch(&tac, &sif, verbose-5)) {
390 fprintf(stderr, "Error: frame times in TAC and SIF do not match.\n");
391 tacFree(&tac); tacFree(&sif); return(4);
392 }
393 }
394
395 /* If user wants to save SIF, it must be saved with no decay decay correction, and therefore
396 we must know the isotope */
397 if(newsif[0] && isot==ISOTOPE_UNKNOWN) {
398 fprintf(stderr, "Error: isotope is required for making SIF.\n");
399 tacFree(&tac); tacFree(&sif); return(1);
400 }
401
402
403
404 /*
405 * If SIF was not given, then create SIF data from regional data.
406 * Count-related data is computed here for the SIF even if user just
407 * wants the weights to be based on frame lengths.
408 */
409 if(!siffile[0]) {
410 if(verbose>1) printf("creating SIF data from regional data\n");
411 /* Make sure that TAC time units are known */
412 if(!unitIsTime(tac.tunit)) {
413 /* Try to guess the unit */
414 double xmin, xmax;
415 if(tacXRange(&tac, &xmin, &xmax)) {
416 fprintf(stderr, "Error: invalid sample times.\n");
417 tacFree(&tac); return(2);
418 }
419 if(xmax<=60.0) {
420 tac.tunit=UNIT_MIN;
421 fprintf(stderr, "Warning: unknown time unit; assumed min.\n");
422 } else if(xmax>360.0) {
423 tac.tunit=UNIT_SEC;
424 fprintf(stderr, "Warning: unknown time unit; assumed sec.\n");
425 } else {
426 fprintf(stderr, "Error: unknown time unit.\n");
427 tacFree(&tac); return(2);
428 }
429 }
430 /* Make sure that TAC calibration units are known, if we need them */
431 if(weight_method==WEIGHTING_ON_COUNTS) {
432 if(tac.cunit==UNIT_UNKNOWN) {
433 fprintf(stderr, "Error: unknown calibration unit.\n");
434 tacFree(&tac); return(2);
435 }
436 if(!unitIsRadioactivity(tac.cunit) && !unitIsRAConc(tac.cunit)) {
437 fprintf(stderr, "Error: invalid unit %s.\n", unitName(tac.cunit));
438 tacFree(&tac); return(2);
439 }
440 } else if(newsif[0]) { // needed for making SIF
441 if(tac.cunit==UNIT_UNKNOWN) {
442 fprintf(stderr, "Error: unknown calibration unit.\n");
443 tacFree(&tac); return(2);
444 }
445 if(!unitIsRadioactivity(tac.cunit) && !unitIsRAConc(tac.cunit)) {
446 fprintf(stderr, "Error: invalid unit %s.\n", unitName(tac.cunit));
447 tacFree(&tac); return(2);
448 }
449 }
450 /* Allocate memory for SIF data */
451 if(tacAllocate(&sif, tac.sampleNr, 3)!=TPCERROR_OK) {
452 fprintf(stderr, "Error: cannot prepare data for SIF.\n");
453 tacFree(&tac); tacFree(&sif); return(6);
454 }
455 sif.sampleNr=tac.sampleNr;
456 sif.tacNr=2; // 3rd contains trues that is not saved
457 /* Set SIF compatible titles into TAC struct */
458 strcpy(sif.c[0].name, "Prompts");
459 strcpy(sif.c[1].name, "Randoms");
460 strcpy(sif.c[2].name, "Trues"); // computed, not saved
461 /* Set basic header information */
463 sif.isframe=tac.isframe; // For now, but SIF always contains frame start and end times
464 sif.tunit=tac.tunit;
465 sif.cunit=tac.cunit;
466 tacSetIsotope(&sif, isot);
467 /* Study number is needed when SIF is saved */
468 {
469 char studynr[MAX_STUDYNR_LEN+1];
470 if(tacGetHeaderStudynr(&tac.h, studynr, &status)==TPCERROR_OK)
471 tacSetHeaderStudynr(&sif.h, studynr);
472 }
473 /* Copy times, and convert to seconds */
474 tacXCopy(&tac, &sif, 0, tac.sampleNr-1);
475 if(tacXUnitConvert(&sif, UNIT_SEC, &status)!=TPCERROR_OK) {
476 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
477 tacFree(&tac); tacFree(&sif); return(6);
478 }
479 /* Guess frame start and end times, if not present in data */
480 if(tacSetX(&sif, &status)!=TPCERROR_OK) {
481 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
482 tacFree(&tac); tacFree(&sif); return(6);
483 }
484 sif.isframe=1; // SIF always contains frame start and end times
485 /* Estimate SIF counts */
486 if(headIndex>=0) {
487 /* If 'head' region name was given, then copy it to sif */
488 for(int i=0; i<tac.sampleNr; i++) sif.c[0].y[i]=tac.c[headIndex].y[i];
489 } else {
490 /* otherwise we must calculate the size weighted average of all TACs */
491 for(int j=0; j<tac.sampleNr; j++) {
492 double sum=0.0, wsum=0.0;
493 for(int i=0; i<tac.tacNr; i++) {
494 if(!isfinite(tac.c[i].y[j])) continue;
495 double w=tac.c[i].size; if(!(w>0.0)) w=1.0;
496 sum+=w*tac.c[i].y[j]; wsum+=w;
497 }
498 if(wsum>0.0) sif.c[0].y[j]=sum/wsum; else sif.c[0].y[j]=0.0;
499 } // next time frame
500 }
501 /* Remove decay correction, if isotope is known. If isotope is known, 'trues' are decay
502 corrected for weight calculation in sifWeight(), although values in SIF will not
503 be changed. */
504 if(isot!=ISOTOPE_UNKNOWN) {
505 if(tacDecayCorrection(&sif, isot, 0, &status)!=TPCERROR_OK) {
506 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
507 tacFree(&tac); tacFree(&sif); return(6);
508 }
509 }
510 if(unitIsRadioactivity(sif.cunit)) {
511 if(tacYUnitConvert(&sif, UNIT_BQ, &status)!=TPCERROR_OK) {
512 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
513 tacFree(&tac); tacFree(&sif); return(6);
514 }
515 } else if(unitIsRAConc(sif.cunit)) {
516 if(tacYUnitConvert(&sif, UNIT_BQ_PER_ML, &status)!=TPCERROR_OK) {
517 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
518 tacFree(&tac); tacFree(&sif); return(6);
519 }
520 for(int i=0; i<sif.sampleNr; i++) sif.c[0].y[i]*=1000.; // Counts from one litre
521 sif.cunit=UNIT_BQ;
522 }
523 /* Multiply with frame duration (Bq/s -> Bq/frame) */
524 for(int i=0; i<sif.sampleNr; i++) sif.c[0].y[i]*=(sif.x2[i]-sif.x1[i]);
525 sif.cunit=UNIT_COUNTS;
526 /* Set prompts, randoms, and trues */
527 for(int i=0; i<sif.sampleNr; i++) {
528 sif.c[2].y[i]=sif.c[0].y[i];
529 sif.c[1].y[i]=0.0;
530 }
531 /* Save the SIF, if requested */
532 if(newsif[0]) {
533 if(verbose>1) printf("writing %s\n", newsif);
534 FILE *fp; fp=fopen(newsif, "w");
535 if(fp==NULL) {
536 fprintf(stderr, "Error: cannot open file for writing (%s)\n", newsif);
537 tacFree(&tac); tacFree(&sif); return(11);
538 }
539 if(tacWriteSIF(&sif, fp, 0, &status)!=TPCERROR_OK) {
540 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
541 fclose(fp); tacFree(&tac); tacFree(&sif); return(12);
542 }
543 fclose(fp);
544 if(verbose>=0) printf("%s saved.\n", newsif);
545 }
546 }
547
548
549 /*
550 * Calculate weights into SIF
551 */
552 if(verbose>1) {printf("calculating weights from SIF data\n"); fflush(stdout);}
553 if(weight_method==WEIGHTING_ON_COUNTS) {
554 if(sifWeight(&sif, isot, &status)!=TPCERROR_OK) {
555 fprintf(stderr, "Error: cannot calculate weights.\n");
556 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
557 tacFree(&tac); tacFree(&sif); return(4);
558 }
559 } else if(weight_method==WEIGHTING_ON_F) {
560 if(tacWByFreq(&sif, ISOTOPE_UNKNOWN, &status)!=TPCERROR_OK) {
561 fprintf(stderr, "Error: cannot calculate weights.\n");
562 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), tacfile);
563 tacFree(&tac); tacFree(&sif); return(4);
564 }
565 } else if(weight_method==WEIGHTING_ON_FD) {
566 if(tacWByFreq(&sif, isot, &status)!=TPCERROR_OK) {
567 fprintf(stderr, "Error: cannot calculate weights.\n");
568 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), tacfile);
569 tacFree(&tac); tacFree(&sif); return(4);
570 }
571 } else {
572 fprintf(stderr, "Error: invalid settings.\n");
573 tacFree(&tac); tacFree(&sif); return(4);
574 }
575 /* Moderate weights, if required */
576 if(weight_moderate>0.0) {
577 if(verbose>1) {printf("moderate and normalize weights\n"); fflush(stdout);}
578 double prop=0.0; if(weight_moderate>1.0) prop=1.0/weight_moderate;
579 if(tacWeightModerate(&sif, prop, 0, 0, &status)!=TPCERROR_OK) {
580 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
581 tacFree(&tac); tacFree(&sif); return(8);
582 }
583 } else {
584 /* Just normalize weights */
585 if(verbose>1) {printf("normalize weights\n"); fflush(stdout);}
586 if(tacWeightNorm(&sif, &status)!=TPCERROR_OK) {
587 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
588 tacFree(&tac); tacFree(&sif); return(9);
589 }
590 }
591 /* Copying weights into TAC */
592 tacWCopy(&sif, &tac, 0, tac.sampleNr-1);
593 tacFree(&sif);
594
595 /*
596 * Save TAC file with weights
597 */
598 {
599 /* Some file formats cannot save weights */
601 if(verbose>1) printf("saving modified %s\n", tacfile);
602 FILE *fp; fp=fopen(tacfile, "w");
603 if(fp==NULL) {
604 fprintf(stderr, "Error: cannot open file for writing\n");
605 tacFree(&tac); return(21);
606 }
607 int ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
608 fclose(fp);
609 if(ret!=TPCERROR_OK) {
610 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
611 tacFree(&tac); return(22);
612 }
613 /* Tell user what we did */
614 if(verbose>0) printf("Weights added in %s\n", tacfile);
615 }
616
617 tacFree(&tac);
618
619 return(0);
620}
621/*****************************************************************************/
622
623/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
char * isotopeName(int isotope_code)
Definition isotope.c:101
int isotopeIdentify(const char *isotope)
Definition isotope.c:145
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
int tacWriteSIF(TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
Definition sifio.c:26
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
char sw
Definition tpctac.h:77
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
double size
Definition tpctac.h:71
Definition tpctac.h:87
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
double * w
Definition tpctac.h:111
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
weights weighting
Definition tpctac.h:115
double * x2
Definition tpctac.h:101
unit tunit
Definition tpctac.h:109
int _tacNr
Definition tpctac.h:119
double * x1
Definition tpctac.h:99
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
void tacFree(TAC *tac)
Definition tac.c:106
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
void tacInit(TAC *tac)
Definition tac.c:24
int tacGetIsotope(TAC *tac)
Definition tacdc.c:25
int tacDecayCorrection(TAC *tac, int isotope, int mode, TPCSTATUS *status)
Definition tacdc.c:59
void tacSetIsotope(TAC *tac, int isotope)
Definition tacdc.c:41
decaycorrection tacGetHeaderDecayCorrection(IFT *h)
Definition tacift.c:548
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:26
int tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
char * tacFormattxt(tacformat c)
Definition tacio.c:98
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
Definition tacio.c:332
int tacSelectTACs(TAC *d, const char *region_name, int reset, TPCSTATUS *status)
Definition tacselect.c:24
int tacSelectBestReference(TAC *d)
Definition tacselect.c:139
int tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:72
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
int sifWeight(TAC *sif, isotope isot, TPCSTATUS *status)
Definition tacw.c:363
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
int tacWeightModerate(TAC *tac, const double minprop, const int doZeroes, const int doNaNs, TPCSTATUS *status)
Definition tacw.c:277
int tacWeightNorm(TAC *tac, TPCSTATUS *status)
Definition tacw.c:237
int tacWCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacw.c:41
int tacWByFreq(TAC *tac, isotope isot, TPCSTATUS *status)
Definition tacw.c:134
int tacXMatch(TAC *d1, TAC *d2, const int verbose)
Check whether sample (frame) times are the same (or very close to) in two TAC structures.
Definition tacx.c:249
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacx.c:24
int tacSetX(TAC *d, TPCSTATUS *status)
Set TAC x values based on x1 and x2 values, or guess x1 and x2 values based on x values.
Definition tacx.c:653
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Definition tacy.c:26
Header file for library libtpccsv.
Header file for library libtpcextensions.
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ WEIGHTING_ON_FD
Weights based on decay and sample frequency or frame length (Thiele et al, 2008).
@ WEIGHTING_ON_F
Weights based on sample frequency or frame length.
@ WEIGHTING_ON_COUNTS
Weights based on counts (Mazoyer et al, 1986).
int unitIsRAConc(int u)
Definition units.c:726
@ UNIT_MIN
minutes
@ UNIT_UNKNOWN
Unknown unit.
@ UNIT_COUNTS
counts
@ UNIT_SEC
seconds
@ UNIT_BQ
Becquerel.
@ UNIT_BQ_PER_ML
Bq/mL.
@ TPCERROR_OK
No error.
int unitIsRadioactivity(int u)
Definition units.c:444
char * unitName(int unit_code)
Definition units.c:143
#define MAX_STUDYNR_LEN
Define max study number length.
int unitIsTime(int u)
Definition units.c:359
Header file for library libtpcift.
decaycorrection
Definition tpcisotope.h:78
@ DECAY_UNKNOWN
Not known; usually assumed that data is corrected.
Definition tpcisotope.h:79
@ DECAY_NOTCORRECTED
Data is not corrected for physical decay.
Definition tpcisotope.h:80
@ DECAY_CORRECTED
Data is corrected for physical decay.
Definition tpcisotope.h:81
isotope
Definition tpcisotope.h:50
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28
@ TAC_FORMAT_PMOD
PMOD TAC format.
Definition tpctac.h:33
@ TAC_FORMAT_SIMPLE
x and y's with space delimiters
Definition tpctac.h:29
@ TAC_FORMAT_SIF
Scan information file.
Definition tpctac.h:43