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

Working with weights in TAC structure. More...

#include "tpcclibConfig.h"
#include "tpcift.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "tpctac.h"

Go to the source code of this file.

Functions

int tacIsWeighted (TAC *tac)
 
int tacWCopy (TAC *tac1, TAC *tac2, int i1, int i2)
 
int tacWMove (TAC *tac, int ow, TPCSTATUS *status)
 
int tacWByFreq (TAC *tac, isotope isot, TPCSTATUS *status)
 
unsigned int tacWSampleNr (TAC *tac)
 
int tacWeightNorm (TAC *tac, TPCSTATUS *status)
 
int tacWeightModerate (TAC *tac, const double minprop, const int doZeroes, const int doNaNs, TPCSTATUS *status)
 
int sifWeight (TAC *sif, isotope isot, TPCSTATUS *status)
 
int tacSetWeights (TAC *tac, weights weightMethod, int weightNr, TPCSTATUS *status)
 

Detailed Description

Working with weights in TAC structure.

Definition in file tacw.c.

Function Documentation

◆ sifWeight()

int sifWeight ( TAC * sif,
isotope isot,
TPCSTATUS * status )

Calculate weights for frames in SIF data based on true counts.

Weights are calculated from formula weight=(frame duration)^2 / (trues in a frame) which is applicable to non-decay corrected data. If weights are to be applied to decay-corrected data, provide function with isotope to use formula weight=(frame duration)^2 / (decay corrected trues in a frame) instead.

Reference: Mazoyer BM, Huesman RH, Budinger TF, Knittel BL. Dynamic PET data analysis. J Comput Assist Tomogr 1986; 10:645-653.

Formula is not applicable to initial frames where trues can be zero or even less, but weights for frames with no trues should still be high for fitting purposes; therefore, in those cases, weight is set to the maximum weight that was calculated from the data.

Weights are normalized to have an average of 1.0 for frames that have weight above zero.

See also
tacWCopy, tacWByFreq, tacWSampleNr, tacReadSIF, tacWeightModerate, tacWeightNorm, tacDecayCorrection, tacIsWeighted, tacSetWeights
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
sifPointer to SIF data, stored in TAC structure. Weights are added to the structure. Data must have at least two columns (TACs), which are assumed to represent prompts and randoms, to calculate trues as prompts - randoms. Counts in SIF are assumed to be not corrected for physical decay. Frame times are assumed to be in seconds.
isotIsotope code, in case the weights are calculated for decay corrected data. Enter ISOTOPE_UNKNOWN if calculating weights for non-corrected data. SIF should contain isotope, too, but that is not used in this function.
statusPointer to status data; enter NULL if not needed

Definition at line 363 of file tacw.c.

377 {
378 int verbose=0; if(status!=NULL) verbose=status->verbose;
379 if(verbose>0) printf("%s(%s)\n", __func__, isotopeName(isot));
380 if(sif==NULL || sif->tacNr<1 || sif->sampleNr<1) {
381 if(sif!=NULL && verbose>2) {
382 printf(" sif.tacNr := %d\n sif.sampleNr := %d\n", sif->tacNr, sif->sampleNr);
383 }
384 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
385 return TPCERROR_NO_DATA;
386 }
388 if(sif->tacNr<2 || !sif->isframe) {
389 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
391 }
392 /* Check times */
393 double xmin, xmax;
394 if(tacXRange(sif, &xmin, &xmax) || !(xmax>xmin)) {
395 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
397 }
398
399 /* Calculate trues */
400 double trues[sif->sampleNr];
401 for(int i=0; i<sif->sampleNr; i++) trues[i]=sif->c[0].y[i]-sif->c[1].y[i];
402 if(verbose>2) {
403 printf("\nTrues:\n");
404 for(int i=0; i<sif->sampleNr; i++) printf("\t%g\n", trues[i]);
405 fflush(stdout);
406 }
407 /* Correct for decay, if requested */
408 if(isot!=ISOTOPE_UNKNOWN) {
409 for(int i=0; i<sif->sampleNr; i++)
410 trues[i]*=decayCorrectionFactorFromIsotope(isot, sif->x1[i]/60., (sif->x2[i]-sif->x1[i])/60.);
411 if(verbose>2) {
412 printf("\nTrues after decay correction:\n");
413 for(int i=0; i<sif->sampleNr; i++) printf("\t%g\n", trues[i]);
414 fflush(stdout);
415 }
416 }
417 /* Calculate weights */
418 double wMax=0.0;
419 for(int i=0; i<sif->sampleNr; i++) {
420 double fdur=sif->x2[i]-sif->x1[i]; if(fdur<0.0) {
421 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
422 return TPCERROR_INVALID_X;
423 }
424 if(trues[i]>0.0) {
425 sif->w[i]=fdur*fdur/trues[i];
426 if(sif->w[i]>wMax) wMax=sif->w[i];
427 } else {
428 sif->w[i]=nan("");
429 }
430 }
431 if(!(wMax>0.0)) {
432 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
434 }
435 if(verbose>1) {printf("\twMax := %g\n", wMax); fflush(stdout);}
436 /* Set maximum weight to frames which had no true counts */
437 for(int i=0; i<sif->sampleNr; i++) if(!(trues[i]>0.0) && isnan(sif->w[i])) sif->w[i]=wMax;
438 if(verbose>2) {
439 printf("\nWeights before normalization:\n");
440 for(int i=0; i<sif->sampleNr; i++) printf("\t%g\n", sif->w[i]);
441 fflush(stdout);
442 }
443
444 /* Normalize weights */
446 if(tacWeightNorm(sif, status)!=TPCERROR_OK) return(status->error);
447
448 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
449 return(TPCERROR_OK);
450}
double decayCorrectionFactorFromIsotope(int isotope, double starttime, double duration)
Definition decay.c:107
char * isotopeName(int isotope_code)
Definition isotope.c:101
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
double * y
Definition tpctac.h:75
int sampleNr
Definition tpctac.h:89
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
double * x1
Definition tpctac.h:99
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacWeightNorm(TAC *tac, TPCSTATUS *status)
Definition tacw.c:237
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ WEIGHTING_ON_COUNTS
Weights based on counts (Mazoyer et al, 1986).
@ TPCERROR_INVALID_XRANGE
Invalid sample time range.
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_INVALID_X
Invalid sample time.
@ TPCERROR_UNSUPPORTED
Unsupported file type.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51

Referenced by tacSetWeights().

◆ tacIsWeighted()

int tacIsWeighted ( TAC * tac)

Check if TAC contains weights as indicated by the 'weighting' field.

See also
tacSetWeights, tacWMove, sifWeight, tacWByFreq, imgHasWeights, tacIsX, tacIsSize
Returns
Returns 1 if weighted, and 0 if not or in case of an error.
Parameters
tacPointer to TAC structure.

Definition at line 24 of file tacw.c.

27 {
28 if(tac==NULL) return(0);
29 if(tac->weighting==WEIGHTING_UNKNOWN || tac->weighting==WEIGHTING_OFF) return(0);
30 if(tac->weighting<WEIGHTING_LAST) return(1);
31 return(0);
32}
@ WEIGHTING_UNKNOWN
Not known; usually assumed that not weighted.

Referenced by parAllocateWithTAC(), tacDecayCorrection(), tacSampleXRange(), tacSetWeights(), tacWeightModerate(), tacWeightNorm(), tacWMove(), tacWriteCSV(), tacWriteDFT(), tacWritePMOD(), tacWriteSheetIntoXML(), and tacWriteXML().

◆ tacSetWeights()

int tacSetWeights ( TAC * tac,
weights weightMethod,
int weightNr,
TPCSTATUS * status )

Set TAC sample weights, based on given weighting scheme.

Weights are normalized to have average weight 1.0, with the sum of weights equals the weightNr or number of frames, whichever is smaller.

See also
tacIsWeighted, tacWSampleNr, tacWCopy, tacWMove, sifWeight, tacWByFreq, tacIsX
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC structure. Data must be sorted by increasing sample times.
weightMethodWeighting scheme: WEIGHTING_ON_COUNTS, WEIGHTING_ON_F, WEIGHTING_ON_FD, WEIGHTING_OFF. With WEIGHTING_UNKNOWN weightNr (below) is applied to weights and remaining weights are re-normalized.
weightNrNumber of samples (frames) to weight; if TAC contains more samples than this, then those are set to have zero weight. Enter a large number to give weight to all available samples.
statusPointer to status data; enter NULL if not needed

Definition at line 462 of file tacw.c.

474 {
475 int verbose=0; if(status!=NULL) verbose=status->verbose;
476 if(verbose>0) {printf("%s(tac, %d, %d)\n", __func__, weightMethod, weightNr); fflush(stdout);}
477
478 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
479 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
480 return TPCERROR_NO_DATA;
481 }
482 if(weightNr<1) weightMethod=WEIGHTING_OFF;
483 if(weightNr>tac->sampleNr) weightNr=tac->sampleNr;
484 int origSampleNr=tac->sampleNr;
485
486 /* Get isotope from TAC data */
487 isotope fisot=tacGetIsotope(tac);
488 if(verbose>3) {printf(" isotope := %s\n", isotopeName(fisot)); fflush(stdout);}
489 if(fisot==ISOTOPE_UNKNOWN) {
490 if(weightMethod==WEIGHTING_ON_COUNTS || weightMethod==WEIGHTING_ON_FD) {
492 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNKNOWN_ISOTOPE);
494 }
495 }
496
497 if(tac->format==TAC_FORMAT_SIF && weightMethod==WEIGHTING_ON_GENERAL)
498 weightMethod=WEIGHTING_ON_COUNTS;
499
500 if(weightMethod==WEIGHTING_OFF) {
501
502 if(verbose>2 && !tacIsWeighted(tac)) {
503 printf(" Note: data did not contain weights.\n"); fflush(stdout);}
505 for(int i=0; i<tac->sampleNr; i++) tac->w[i]=0.0;
506 for(int i=0; i<weightNr; i++) tac->w[i]=1.0;
507 if(verbose>1) {printf(" weights removed.\n"); fflush(stdout);}
508
509 } else if(weightMethod==WEIGHTING_ON_GENERAL) {
510
511 if(verbose>0) {fprintf(stderr, "Error: cannot apply general weighting.\n"); fflush(stderr);}
512 for(int i=0; i<tac->sampleNr; i++) tac->w[i]=0.0;
513 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
514 return TPCERROR_FAIL;
515
516 } else if(weightMethod==WEIGHTING_UNKNOWN) {
517
518 for(int i=weightNr; i<tac->sampleNr; i++) tac->w[i]=0.0;
519
520 if(!tacIsWeighted(tac)) {
521 if(verbose>2) {printf(" Note: data does not contain weights.\n"); fflush(stdout);}
522 for(int i=0; i<weightNr; i++) tac->w[i]=1.0;
523 } else {
524 if(verbose>2) {printf(" Note: data contains weights.\n"); fflush(stdout);}
525 tac->sampleNr=weightNr;
526 int ret=tacWeightNorm(tac, status);
527 tac->sampleNr=origSampleNr;
528 if(ret!=TPCERROR_OK) return(ret);
529 }
530
531 } else if(weightMethod==WEIGHTING_ON_COUNTS) {
532
533 if(verbose>2 && tacIsWeighted(tac)) {
534 printf(" Note: data already contained weights.\n"); fflush(stdout);}
536 for(int i=0; i<tac->sampleNr; i++) tac->w[i]=0.0;
537
538 if(tac->format==TAC_FORMAT_SIF) {
539
540 /* TAC contains SIF data, just add weights */
541 tac->sampleNr=weightNr;
542 int ret=sifWeight(tac, fisot, status);
543 tac->sampleNr=origSampleNr;
544 if(ret!=TPCERROR_OK) return(ret);
546 if(verbose>1) {printf(" weights added.\n"); fflush(stdout);}
547
548 } else {
549
550 double weight_moderate=100.0;
551
552 /* Create temp SIF */
553 if(!unitIsTime(tac->tunit) || !tacIsX(tac)) {
554 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
555 return TPCERROR_INVALID_X;
556 }
557 if(!unitIsRadioactivity(tac->cunit) && !unitIsRAConc(tac->cunit)) {
558 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_UNIT);
560 }
561 TAC sif; tacInit(&sif);
562 if(tacAllocate(&sif, weightNr, 3)!=TPCERROR_OK) {
563 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_DATA);
565 }
566 sif.sampleNr=weightNr;
567 sif.tacNr=2; // 3rd contains trues that is not saved
569 sif.isframe=1; // SIF always contains frame start and end times
570 sif.tunit=tac->tunit;
571 sif.cunit=tac->cunit;
572 tacSetIsotope(&sif, fisot);
573 tacXCopy(tac, &sif, 0, sif.sampleNr-1);
574 int ret=tacXUnitConvert(&sif, UNIT_SEC, status);
575 if(ret!=TPCERROR_OK) {tacFree(&sif); return(ret);}
576 for(int j=0; j<sif.sampleNr; j++) {
577 double sum=0.0, wsum=0.0;
578 for(int i=0; i<tac->tacNr; i++) {
579 if(!isfinite(tac->c[i].y[j])) continue;
580 double w=tac->c[i].size; if(!(w>0.0)) w=1.0;
581 sum+=w*tac->c[i].y[j]; wsum+=w;
582 }
583 if(wsum>0.0) sif.c[0].y[j]=sum/wsum; else sif.c[0].y[j]=0.0;
584 } // next time frame
585 ret=tacDecayCorrection(&sif, fisot, 0, status);
586 if(ret!=TPCERROR_OK) {tacFree(&sif); return(ret);}
587 if(unitIsRadioactivity(sif.cunit)) {
588 ret=tacYUnitConvert(&sif, UNIT_BQ, status);
589 } else {
590 ret=tacYUnitConvert(&sif, UNIT_BQ_PER_ML, status);
591 for(int i=0; i<sif.sampleNr; i++) sif.c[0].y[i]*=1000.; // Counts from one litre
592 sif.cunit=UNIT_BQ;
593 }
594 if(ret!=TPCERROR_OK) {tacFree(&sif); return(ret);}
595 /* Multiply with frame duration (Bq/s -> Bq/frame) */
596 for(int i=0; i<sif.sampleNr; i++) sif.c[0].y[i]*=(sif.x2[i]-sif.x1[i]);
597 sif.cunit=UNIT_COUNTS;
598 /* Set prompts, randoms, and trues */
599 for(int i=0; i<sif.sampleNr; i++) {
600 sif.c[2].y[i]=sif.c[0].y[i];
601 sif.c[1].y[i]=0.0;
602 }
603 /* Calculate weights based on approximated SIF data */
604 ret=sifWeight(&sif, fisot, status);
605 if(ret==TPCERROR_OK) ret=tacWeightNorm(&sif, status);
606 if(ret!=TPCERROR_OK) {tacFree(&sif); return(ret);}
607
608 double prop=0.0; if(weight_moderate>1.0) prop=1.0/weight_moderate;
609 ret=tacWeightModerate(&sif, prop, 0, 0, status);
610 if(ret!=TPCERROR_OK) {tacFree(&sif); return(ret);}
611
612 /* Copy weights into TAC */
613 {
614 int j;
615 for(j=0; j<sif.sampleNr; j++) tac->w[j]=sif.w[j];
616 for( ; j<tac->sampleNr; j++) tac->w[j]=0.0;
617 }
618 tacFree(&sif);
620 if(verbose>1) {printf(" weights added.\n"); fflush(stdout);}
621
622 }
623
624 } else if(weightMethod==WEIGHTING_ON_F) {
625
626 if(verbose>2 && tacIsWeighted(tac)) {
627 printf(" Note: data already contained weights.\n"); fflush(stdout);}
629 for(int i=0; i<tac->sampleNr; i++) tac->w[i]=0.0;
630 tac->sampleNr=weightNr;
631 int ret=tacWByFreq(tac, ISOTOPE_UNKNOWN, status);
632 if(ret==TPCERROR_OK) ret=tacWeightNorm(tac, status);
633 tac->sampleNr=origSampleNr;
634 if(ret!=TPCERROR_OK) return(ret);
635 if(verbose>1) {printf(" weights added.\n"); fflush(stdout);}
636
637 } else if(weightMethod==WEIGHTING_ON_FD) {
638
639 if(verbose>2 && tacIsWeighted(tac)) {
640 printf(" Note: data already contained weights.\n"); fflush(stdout);}
642 for(int i=0; i<tac->sampleNr; i++) tac->w[i]=0.0;
643 tac->sampleNr=weightNr;
644 int ret=tacWByFreq(tac, fisot, status);
645 if(ret==TPCERROR_OK) ret=tacWeightNorm(tac, status);
646 tac->sampleNr=origSampleNr;
647 if(ret!=TPCERROR_OK) return(ret);
648 if(verbose>1) {printf(" weights added.\n"); fflush(stdout);}
649
650 } else {
651 if(verbose>0) {fprintf(stderr, "Error: invalid weighting scheme.\n"); fflush(stderr);}
652 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
653 return TPCERROR_FAIL;
654 }
655
656 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
657 return(TPCERROR_OK);
658}
double size
Definition tpctac.h:71
Definition tpctac.h:87
tacformat format
Definition tpctac.h:93
int cunit
Definition tpctac.h:105
int tunit
Definition tpctac.h:109
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
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 tacWByFreq(TAC *tac, isotope isot, TPCSTATUS *status)
Definition tacw.c:134
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacx.c:24
int tacIsX(TAC *d)
Verify if TAC structure contains reasonable x values (times).
Definition tacx.c:226
@ WEIGHTING_ON_FD
Weights based on decay and sample frequency or frame length (Thiele et al, 2008).
@ WEIGHTING_ON_GENERAL
Weighted or weights are available, but not specified.
@ WEIGHTING_ON_F
Weights based on sample frequency or frame length.
int unitIsRAConc(int u)
Definition units.c:726
@ UNIT_COUNTS
counts
@ UNIT_SEC
seconds
@ UNIT_BQ
Becquerel.
@ UNIT_BQ_PER_ML
Bq/mL.
@ TPCERROR_FAIL
General error.
@ TPCERROR_INCOMPATIBLE_UNIT
Incompatible units.
@ TPCERROR_UNKNOWN_ISOTOPE
Unknown isotope.
@ TPCERROR_INCOMPATIBLE_DATA
Incompatible data.
int unitIsRadioactivity(int u)
Definition units.c:444
int unitIsTime(int u)
Definition units.c:359
isotope
Definition tpcisotope.h:50
@ TAC_FORMAT_SIF
Scan information file.
Definition tpctac.h:43

◆ tacWByFreq()

int tacWByFreq ( TAC * tac,
isotope isot,
TPCSTATUS * status )

Add weight to TAC data based on sample frequency or time frame length.

Weights are scaled so that weight sum = sample number. Any existing weighting is overwritten.

See also
tacSetWeights, tacIsWeighted, sifWeight, tacWSampleNr, tacWCopy, tacWMove, tacWeightModerate
Returns
Return enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC struct where weights will be added.
Note
Samples/frames must be sorted by sample time, but duplicate samples are allowed.
Parameters
isotIsotope code, in case the weights are calculated for decay corrected data. Enter ISOTOPE_UNKNOWN if calculating weights for non-corrected data, or when decay correction is ignored.
statusPointer to status data; enter NULL if not needed

Definition at line 134 of file tacw.c.

144 {
145 int verbose=0; if(status!=NULL) verbose=status->verbose;
146 if(verbose>0) printf("%s(%s)\n", __func__, isotopeName(isot));
147 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
148 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
149 return TPCERROR_NO_DATA;
150 }
151
153 if(tac->sampleNr==1) {tac->w[0]=1.0; return(TPCERROR_OK);}
154
155 if(tac->isframe!=0) { /* weights based on frame lengths */
157
158 for(int i=0; i<tac->sampleNr; i++) {
159 tac->w[i]=tac->x2[i]-tac->x1[i];
160 }
161
162 } else { /* weights based on sample distance */
164
165 int i, i1, i2;
166 double t, t1, t2, f;
167 for(i=0; i<tac->sampleNr; i++) {
168 t=t1=t2=tac->x[i];
169 /* Find the closest sample time before this one */
170 for(i1=i; i1>=0; i1--) {t1=tac->x[i1]; if(t1<t) break;}
171 /* Find the closest sample time after this one */
172 for(i2=i; i2<tac->sampleNr; i2++) {t2=tac->x[i2]; if(t2>t) break;}
173 /* Mean sample distance */
174 f=0.0;
175 if(t1<t) f+=t-t1; else f+=t2-t;
176 if(t2>t) f+=t2-t; else f+=t-t1;
177 f*=0.5; if(f<=0.0) f=1.0;
178 tac->w[i]=f;
179 }
180
181 }
182
183 /* Account for decay correction, if requested */
184 if(isot!=ISOTOPE_UNKNOWN) {
186 double lambda=lambdaFromIsotope(isot);
187 if(tac->tunit==UNIT_SEC) lambda/=60.; else if(tac->tunit==UNIT_MSEC) lambda/=60000.;
188 if(tac->isframe!=0) {
189 for(int i=0; i<tac->sampleNr; i++)
190 tac->w[i]*=decayCorrectionFactorFromLambda(-lambda, tac->x1[i], (tac->x2[i]-tac->x1[i]));
191 } else {
192 for(int i=0; i<tac->sampleNr; i++)
193 tac->w[i]*=decayCorrectionFactorFromLambda(-lambda, tac->x[i], 0.0);
194 }
195 }
196
197 /* Scale weights so that sum of weights equals sample number */
198 double sumw=0.0;
199 for(int i=0; i<tac->sampleNr; i++) if(isfinite(tac->w[i])) sumw+=tac->w[i];
200 if(!(sumw>0.0)) {
201 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
203 }
204 sumw/=(double)tac->sampleNr;
205 for(int i=0; i<tac->sampleNr; i++) tac->w[i]/=sumw;
206
207 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
208 return(TPCERROR_OK);
209}
double lambdaFromIsotope(int isotope)
Definition decay.c:63
double decayCorrectionFactorFromLambda(double lambda, double starttime, double duration)
Definition decay.c:79
double * x
Definition tpctac.h:97
@ UNIT_MSEC
milliseconds

Referenced by tacSetWeights().

◆ tacWCopy()

int tacWCopy ( TAC * tac1,
TAC * tac2,
int i1,
int i2 )

Copy weights from one TAC structure to another.

See also
tacXCopy, tacWMove, sifWeight, tacWByFreq, tacIsWeighted, tacSetWeights
Author
Vesa Oikonen
Returns
Returns TPCERROR status.
Parameters
tac1Pointer to source TAC structure.
tac2Pointer to target TAC structure.
i1Index of the first sample to copy.
i2Index of the last sample to copy.

Definition at line 41 of file tacw.c.

50 {
51 if(tac1==NULL || tac2==NULL) return(TPCERROR_FAIL);
52 if(i1<0 || i1>i2) return(TPCERROR_FAIL);
53 if(i2>=tac1->_sampleNr || i2>=tac2->_sampleNr) return(TPCERROR_FAIL);
54
55 for(int i=i1; i<=i2; i++) {
56 tac2->w[i]=tac1->w[i];
57 }
58 tac2->weighting=tac1->weighting;
59 return(TPCERROR_OK);
60}
int _sampleNr
Definition tpctac.h:121

Referenced by tacDuplicate(), and tacExtract().

◆ tacWeightModerate()

int tacWeightModerate ( TAC * tac,
const double minprop,
const int doZeroes,
const int doNaNs,
TPCSTATUS * status )

Moderate weights so that the min weight is not less than given proportion of the maximum weight.

After moderation, all weights are normalized to have and average of one.

See also
sifWeight, tacWeighNorm, tacWCopy, tacWByFreq, tacWSampleNr, tacReadSIF
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC structure (which can contain SIF or TAC data).
minpropThe minimum proportion of frame weight to maximum frame weight. Must be less than one. If proportion is lower than this limit, then weight is set to proportion times maximum. Setting minimum proportion to zero or less does not change any weights, but weights are still normalized. By default, zero weights or NaNs are not changed.
doZeroesSet zero weights, too, to the minimum proportion of maximum frame weight.
doNaNsSet NaN weights, too, to the minimum proportion of maximum frame weight.
statusPointer to status data; enter NULL if not needed

Definition at line 277 of file tacw.c.

291 {
292 int verbose=0; if(status!=NULL) verbose=status->verbose;
293 if(verbose>0) printf("%s(%g, %d, %d)\n", __func__, minprop, doZeroes, doNaNs);
294 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
295 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
296 return TPCERROR_NO_DATA;
297 }
298 if(!isfinite(minprop) || minprop>=1.0) {
299 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
301 }
302 if(!tacIsWeighted(tac)) {
303 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_WEIGHTS);
304 return TPCERROR_NO_WEIGHTS;
305 }
306
307 double wMax=nan("");
308 for(int i=0; i<tac->sampleNr; i++) if(isfinite(tac->w[i])) {
309 if(!isfinite(wMax)) {wMax=tac->w[i]; continue;}
310 if(tac->w[i]>wMax) wMax=tac->w[i];
311 }
312 if(verbose>2) {printf("weight_maximum := %g\n", wMax); fflush(stdout);}
313 if(!isfinite(wMax) || wMax<=0.0) {
314 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_WEIGHTS);
315 return TPCERROR_NO_WEIGHTS;
316 }
317
318 double wLimit=minprop*wMax;
319 if(verbose>2) {printf("weight_limit := %g\n", wLimit); fflush(stdout);}
320
321 int n=0;
322 if(wLimit>0.0) {
323 for(int i=0; i<tac->sampleNr; i++) {
324 if(tac->w[i]==0.0) {
325 if(doZeroes) {tac->w[i]=wLimit; n++;}
326 continue;
327 }
328 if(isnan(tac->w[i])) {
329 if(doNaNs) {tac->w[i]=wLimit; n++;}
330 continue;
331 }
332 if(tac->w[i]<wLimit) {tac->w[i]=wLimit; n++;}
333 }
334 }
335 if(verbose>1 && minprop>0.0) {printf(" %d weight(s) set to %g.\n", n, wLimit); fflush(stdout);}
336
337 return(tacWeightNorm(tac, status));
338}
@ TPCERROR_NO_WEIGHTS
File contains no weights.

Referenced by tacSetWeights().

◆ tacWeightNorm()

int tacWeightNorm ( TAC * tac,
TPCSTATUS * status )

Scale weights so that average weight is 1.0, and the sum of weights equals the nr of frames.

See also
tacWeightModerate,sifWeight, tacWCopy, tacWByFreq, tacWSampleNr, tacReadSIF
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC structure (which can contain SIF or TAC data).
statusPointer to status data; enter NULL if not needed

Definition at line 237 of file tacw.c.

242 {
243 int verbose=0; if(status!=NULL) verbose=status->verbose;
244 if(verbose>0) printf("%s()\n", __func__);
245 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
246 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
247 return TPCERROR_NO_DATA;
248 }
249 if(!tacIsWeighted(tac)) {
250 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_WEIGHTS);
251 return TPCERROR_NO_WEIGHTS;
252 }
253
254 double wSum=0.0; int wNr=0;
255 for(int i=0; i<tac->sampleNr; i++)
256 if(isfinite(tac->w[i]) && tac->w[i]>0.0) {wSum+=tac->w[i]; wNr++;}
257 if(wNr==0 || !(wSum>0.0)) {
258 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
260 }
261 double wMean=wSum/(double)wNr;
262 for(int i=0; i<tac->sampleNr; i++)
263 if(isfinite(tac->w[i]) && tac->w[i]>0.0) tac->w[i]/=wMean;
264
265 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
266 return TPCERROR_OK;
267}

Referenced by sifWeight(), tacDecayCorrection(), tacSetWeights(), and tacWeightModerate().

◆ tacWMove()

int tacWMove ( TAC * tac,
int ow,
TPCSTATUS * status )

Identify column containing weights in TAC structure, and move weights to the correct place.

TAC name starting with string 'weight' is identified as weight column.

Sets tac->weighting to WEIGHTING_ON or WEIGHTING_OFF, depending on whether weight column was found or not.

See also
tacWCopy, tacSetWeights
Author
Vesa Oikonen
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC structure.
owOverwrite (1) or do not overwrite (0) existing weights.
statusPointer to status data; enter NULL if not needed

Definition at line 75 of file tacw.c.

82 {
83 int verbose=0; if(status!=NULL) verbose=status->verbose;
84 if(verbose>0) printf("%s()\n", __func__);
85 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
86 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
87 return TPCERROR_NO_DATA;
88 }
89 int ret;
90
92
93 /* Search for the weight column */
94 int wc=-1;
95 for(int i=0; i<tac->tacNr; i++) {
96 if(strncasecmp(tac->c[i].name, "WEIGHT", 6)!=0) continue;
97 if(wc<0) wc=i;
98 else if(ow==0) {
99 /* Error if found more than one */
100 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_DUPLICATE_DATA);
102 }
103 }
104 /* Error if not found */
105 if(wc<0) {
106 if(ow) tac->weighting=WEIGHTING_OFF;
107 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_WEIGHTS);
108 return TPCERROR_NO_WEIGHTS;
109 }
110 /* Error if overwriting not allowed */
111 if(ow==0 && tacIsWeighted(tac)) {
112 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_DUPLICATE_DATA);
114 }
115 /* Copy weights to their right place */
116 for(int i=0; i<tac->sampleNr; i++) tac->w[i]=tac->c[wc].y[i];
118 /* Then delete the original column */
119 ret=tacDeleteTACC(tac, wc);
120 statusSet(status, __func__, __FILE__, __LINE__, ret);
121 return(ret);
122}
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
int tacDeleteTACC(TAC *d, int i)
Definition tacorder.c:310
@ TPCERROR_DUPLICATE_DATA
File contains duplicate data.

Referenced by tacReadCarimasTxt(), tacReadCSV(), tacReadDFT(), and tacReadPMOD().

◆ tacWSampleNr()

unsigned int tacWSampleNr ( TAC * tac)

Get the number of samples in TAC that have weight > 0. Missing (NaN) sample values are included as long as weight is not missing. If weights are not set, then nr of all samples is returned.

Returns
The number of samples with weight above zero.
See also
tacWByFreq, aicSS, parFreeNr, tacWeightModerate, tacIsWeighted, tacSetWeights
Parameters
tacPointer to the TAC struct.

Definition at line 219 of file tacw.c.

222 {
223 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) return((unsigned int)0);
224 if(tac->weighting==WEIGHTING_OFF) return((unsigned int)tac->sampleNr);
225 unsigned int n=0;
226 for(int i=0; i<tac->sampleNr; i++) if(tac->w[i]>0.0) n++;
227 if(n==0 && tac->weighting==WEIGHTING_UNKNOWN) n=(unsigned int)tac->sampleNr;
228 return(n);
229}