TPCCLIB
Loading...
Searching...
No Matches
tpctac.h File Reference

Header file for library libtpctac. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "tpccsv.h"
#include "tpcift.h"
#include "tpcisotope.h"

Go to the source code of this file.

Data Structures

struct  TACC
 
struct  TAC
 
struct  MTAC
 

Enumerations

enum  tacformat {
  TAC_FORMAT_UNKNOWN , TAC_FORMAT_SIMPLE , TAC_FORMAT_DFT , TAC_FORMAT_IFT ,
  TAC_FORMAT_NCI , TAC_FORMAT_PMOD , TAC_FORMAT_CSV_INT , TAC_FORMAT_CSV_UK ,
  TAC_FORMAT_TSV_INT , TAC_FORMAT_TSV_UK , TAC_FORMAT_CPT , TAC_FORMAT_IDWC ,
  TAC_FORMAT_IF , TAC_FORMAT_XML , TAC_FORMAT_HTML , TAC_FORMAT_SIF ,
  TAC_FORMAT_XELERIS , TAC_FORMAT_INVEON , TAC_FORMAT_AMIDE , TAC_FORMAT_CARIMAS_TXT ,
  TAC_FORMAT_QVIEW , TAC_FORMAT_MAT , TAC_FORMAT_4DM , TAC_FORMAT_HRRT_HC ,
  TAC_FORMAT_HRPLUS_HC , TAC_FORMAT_ABSS_SCANDITRONICS , TAC_FORMAT_ABSS_GEMS , TAC_FORMAT_ABSS_ALLOGG_OLD ,
  TAC_FORMAT_ABSS_ALLOGG , TAC_FORMAT_BINARY , TAC_FORMAT_LAST
}
 

Functions

void tacInit (TAC *tac)
 
void taccInit (TACC *tacc)
 
void tacFree (TAC *tac)
 
void tacFreeExceptHeader (TAC *tac)
 
void taccFree (TACC *tacc)
 
int tacAllocate (TAC *tac, int sampleNr, int tacNr)
 
int tacAllocateMore (TAC *tac, int tacNr)
 
int tacCopyTacc (TACC *d1, TACC *d2, int sampleNr)
 
int tacCopyTaccdata (TACC *d1, TACC *d2, int sampleNr)
 
int tacCopyTacchdr (TACC *d1, TACC *d2)
 
int tacCopyHdr (TAC *tac1, TAC *tac2)
 Copy TAC header data from tac1 to tac2.
 
int tacIsSize (TAC *d)
 
int tacDuplicate (TAC *tac1, TAC *tac2)
 Make a duplicate of TAC structure.
 
int tacExtract (TAC *d1, TAC *d2, const int i)
 Extract the specified TAC from existing TAC structure into a new TAC.
 
int tacAllocateMoreSamples (TAC *tac, int addNr)
 Allocate memory for more samples in TAC data.
 
void mtacInit (MTAC *mtac)
 
void mtacFree (MTAC *mtac)
 
int mtacAllocate (MTAC *mtac, int nr)
 
int mtacAllocateMore (MTAC *mtac, int nr)
 
int mtacAddTAC (MTAC *mtac, TAC *tac)
 
char * tacFormattxt (tacformat c)
 
int tacFormatIdentify (const char *s)
 
char * tacDefaultExtension (tacformat c)
 
int tacFormatDetermine (const char *fname, TPCSTATUS *status)
 
int tacFormatWriteSupported (tacformat format)
 
int tacWrite (TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
 
int tacRead (TAC *d, const char *fname, TPCSTATUS *status)
 
int tacGetHeaderStudynr (IFT *h, char *s, TPCSTATUS *status)
 
int tacSetHeaderStudynr (IFT *h, const char *s)
 
int tacGetHeaderUnit (TAC *tac, TPCSTATUS *status)
 
int tacSetHeaderUnit (IFT *h, int u)
 
int tacGetHeaderTimeunit (TAC *tac, TPCSTATUS *status)
 
int tacSetHeaderTimeunit (IFT *h, int u)
 
int tacGetHeaderIsotope (IFT *h, char *s, TPCSTATUS *status)
 
int tacSetHeaderIsotope (IFT *h, const char *s)
 
int tacGetHeaderScanstarttime (IFT *h, char *s, TPCSTATUS *status)
 
int tacSetHeaderScanstarttime (IFT *h, const char *s)
 
int tacGetHeaderInjectiontime (IFT *h, char *s, TPCSTATUS *status)
 
int tacSetHeaderInjectiontime (IFT *h, const char *s)
 
decaycorrection tacGetHeaderDecayCorrection (IFT *h)
 
int tacSetHeaderDecayCorrection (IFT *h, decaycorrection dc)
 
int tacWriteSimple (TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
 
int tacReadSimple (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
 
int tacNameSplit (const char *rname, char *name1, char *name2, char *name3, unsigned int max_name_len)
 
int tacWriteDFT (TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
 
int tacReadDFT (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
 
int tacWriteSIF (TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
 
int tacReadSIF (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
 
int tacWritePMOD (TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
 
int tacReadPMOD (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
 
int tacReadQView (TAC *tac, CSV *csv, const int grouponly, TPCSTATUS *status)
 
int tacRead4DM (TAC *tac, CSV *csv, TPCSTATUS *status)
 
int tacReadMat (TAC *tac, CSV *csv, TPCSTATUS *status)
 
int tacWriteCSV (TAC *tac, FILE *fp, int extra, tacformat format, TPCSTATUS *status)
 
int tacReadCSV (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
 
int tacReadInveonCSV (TAC *tac, CSV *csv, TPCSTATUS *status)
 
int tacReadCarimasTxt (TAC *tac, CSV *csv, TPCSTATUS *status)
 
int tacReadHRRTHC (TAC *tac, CSV *csv, TPCSTATUS *status)
 
int tacReadHRPLUSHC (TAC *tac, CSV *csv, TPCSTATUS *status)
 
int tacXNaNs (TAC *tac)
 
int tacYNaNs (TAC *tac, const int i)
 
int tacNaNs (TAC *tac)
 
int tacNotNaNs (TAC *tac, const int i)
 
int tacFixNaNs (TAC *tac)
 
int tacNthSample (TAC *tac, const int sn, const int i)
 
int tacSelectTACs (TAC *d, const char *region_name, int reset, TPCSTATUS *status)
 
int tacSelectedTACs (TAC *d)
 
int tacFirstSelected (TAC *d)
 
int tacSelectBestReference (TAC *d)
 
int tacVerifyTimeOrder (TAC *d, TPCSTATUS *status)
 
int tacSortByTime (TAC *d, TPCSTATUS *status)
 
int tacSortByConc (TAC *d, const int i, TPCSTATUS *status)
 
int tacSortByName (TAC *d, TPCSTATUS *status)
 
int tacSortByAUC (TAC *d, TPCSTATUS *status)
 
int tacMoveTACC (TAC *d, int from, int to)
 
int tacSwapTACCs (TAC *d, int i1, int i2)
 
int tacDeleteTACC (TAC *d, int i)
 
int tacMultipleSamples (TAC *d1, const int fixMode, TAC *d2, const int verbose)
 Check TAC data for multiple samples with the same sample time. Optionally replace the multiple samples with their mean.
 
int tacCompareUnit (TAC *d1, TAC *d2, TPCSTATUS *status)
 
int tacCompareNames (TAC *d1, TAC *d2, const int i, TPCSTATUS *status)
 
int tacCompareConc (TAC *d1, TAC *d2, const int i, const double test_abs, const double test_rel, TPCSTATUS *status)
 
int tacCompareTimes (TAC *d1, TAC *d2, const double test_abs, const double test_rel, TPCSTATUS *status)
 
int tacCompareWeights (TAC *d1, TAC *d2, const double test_abs, const double test_rel, TPCSTATUS *status)
 
int tacXUnitConvert (TAC *d, const int u, TPCSTATUS *status)
 
int tacYUnitConvert (TAC *d, const int u, TPCSTATUS *status)
 
int tacYUnitMass2Volume (TAC *tac, const double density, TPCSTATUS *status)
 
int tacYUnitVolume2Mass (TAC *tac, const double density, TPCSTATUS *status)
 
int tacIndividualNames (TAC *tac)
 
void tacEnsureNames (TAC *tac)
 
int tacXCopy (TAC *tac1, TAC *tac2, int i1, int i2)
 
int tacCorrectFrameOverlap (TAC *d, TPCSTATUS *status)
 Correct PET frame start and end times if frames are slightly overlapping or have small gaps in between.
 
int tacXRange (TAC *d, double *xmin, double *xmax)
 Get the range of x values (times) in TAC structure.
 
int tacSampleXRange (TAC *d, double *xmin, double *xmax)
 Get the range of x values (times) in TAC structure.
 
int tacMinX (TAC *d)
 Get the minimum x value in TAC structure.
 
int tacIsX (TAC *d)
 Verify if TAC structure contains reasonable x values (times).
 
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.
 
int tacAddZeroSample (TAC *d, TPCSTATUS *status)
 Add an initial sample to TAC(s) with zero time and concentration.
 
int tacDeleteSample (TAC *d, int i)
 Delete a certain sample (time frame) from TAC structure.
 
int tacDeleteMissingSamples (TAC *d)
 Delete those samples (time frames) from TAC structure, which contain only missing y values, and/or x is NaN.
 
int tacExtractRange (TAC *d1, TAC *d2, double startT, double endT)
 Extract the specified time (x) range from TAC structure.
 
int tacExtractSamples (TAC *d1, TAC *d2, int si, int ei)
 Extract the specified sample range from TAC structure.
 
int tacCheckX1X2X (TAC *d)
 Check that sample (time frame) x, x1, and x2 values are reasonably set when compared to each other in TAC structure.
 
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.
 
int tacGetSampleInterval (TAC *d, double ilimit, double *minfdur, double *maxfdur)
 Get the shortest and longest sampling intervals or frame lengths in TAC structure.
 
int tacToBars (TAC *tac1, TAC *tac2)
 Transform TAC data with frame start and end times into suitable form for plotting with frames as bars.
 
int tacFramesToSteps (TAC *inp, TAC *out, TPCSTATUS *status)
 Transform TAC with frames into TAC with frames represented with stepwise changing dot-to-dot data.
 
int tacIsXContiguous (TAC *d)
 Check that PET TAC frame times are contiguous, without even tiny overlap or gaps in between.
 
int tacSetXContiguous (TAC *d)
 Set PET TAC frame times contiguous, without even tiny overlap or gaps in between.
 
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.
 
int tacYRangeInXRange (TAC *d, int i, const double xmin, const double xmax, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
 Get the range of y values (concentrations) in TAC struct, including only samples with x (times) inside given range.
 
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)
 
int tacGetIsotope (TAC *tac)
 
void tacSetIsotope (TAC *tac, int isotope)
 
int tacDecayCorrection (TAC *tac, int isotope, int mode, TPCSTATUS *status)
 
int tacReadAllogg (TAC *tac, IFT *hdr, TPCSTATUS *status)
 
int tacReadOldAllogg (TAC *tac, IFT *hdr, TPCSTATUS *status)
 
int tacReadScanditronics (TAC *tac, IFT *hdr, TPCSTATUS *status)
 
int tacReadGEMS (TAC *tac, IFT *hdr, TPCSTATUS *status)
 
int tacWriteXML (TAC *tac, FILE *fp, TPCSTATUS *status)
 

Detailed Description

Header file for library libtpctac.

Time-activity curve (TAC) processing and file i/o.

Author
Vesa Oikonen

Definition in file tpctac.h.

Enumeration Type Documentation

◆ tacformat

enum tacformat

TAC file format codes; see tac_format

Enumerator
TAC_FORMAT_UNKNOWN 

Unknown format.

TAC_FORMAT_SIMPLE 

x and y's with space delimiters

TAC_FORMAT_DFT 

Data format of Turku PET Centre.

TAC_FORMAT_IFT 

Interfile-type data (supported for writing)

TAC_FORMAT_NCI 

Old Turku PET Centre format.

TAC_FORMAT_PMOD 

PMOD TAC format.

TAC_FORMAT_CSV_INT 

International CSV.

TAC_FORMAT_CSV_UK 

UK CSV.

TAC_FORMAT_TSV_INT 

International TSV (comma as decimal separator)

TAC_FORMAT_TSV_UK 

UK TSV (point as decimal separator)

TAC_FORMAT_CPT 

CPT format.

TAC_FORMAT_IDWC 

Hammersmith tissue file format.

TAC_FORMAT_IF 

Hammersmith input file format.

TAC_FORMAT_XML 

XML format (supported for writing)

TAC_FORMAT_HTML 

HTML table format (supported for writing)

TAC_FORMAT_SIF 

Scan information file.

TAC_FORMAT_XELERIS 

Xeleris format (reading supported)

TAC_FORMAT_INVEON 

Inveon format (reading supported)

TAC_FORMAT_AMIDE 

Amide format (reading supported)

TAC_FORMAT_CARIMAS_TXT 

Carimas txt format (reading supported)

TAC_FORMAT_QVIEW 

QView CSV TAC format (reading supported)

TAC_FORMAT_MAT 

Matlab matrix TAC format (reading supported)

TAC_FORMAT_4DM 

4DM TAC format (reading supported)

TAC_FORMAT_HRRT_HC 

HRRT head curve format (reading supported)

TAC_FORMAT_HRPLUS_HC 

HR+ head curve format (reading supported)

TAC_FORMAT_ABSS_SCANDITRONICS 

Scanditronics ABSS data; reading supported.

TAC_FORMAT_ABSS_GEMS 

GEMS ABSS data; reading supported.

TAC_FORMAT_ABSS_ALLOGG_OLD 

ALLOGG ABSS data (old format); reading supported.

TAC_FORMAT_ABSS_ALLOGG 

ALLOGG ABSS data; reading supported.

TAC_FORMAT_BINARY 

Binary format (currently not supported)

Definition at line 27 of file tpctac.h.

27 {
58 TAC_FORMAT_LAST
59} tacformat;
tacformat
Definition tpctac.h:27
@ TAC_FORMAT_IF
Hammersmith input file format.
Definition tpctac.h:40
@ TAC_FORMAT_IFT
Interfile-type data (supported for writing)
Definition tpctac.h:31
@ TAC_FORMAT_4DM
4DM TAC format (reading supported)
Definition tpctac.h:50
@ TAC_FORMAT_CPT
CPT format.
Definition tpctac.h:38
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28
@ TAC_FORMAT_CSV_INT
International CSV.
Definition tpctac.h:34
@ TAC_FORMAT_ABSS_ALLOGG
ALLOGG ABSS data; reading supported.
Definition tpctac.h:56
@ TAC_FORMAT_MAT
Matlab matrix TAC format (reading supported)
Definition tpctac.h:49
@ TAC_FORMAT_ABSS_GEMS
GEMS ABSS data; reading supported.
Definition tpctac.h:54
@ TAC_FORMAT_HTML
HTML table format (supported for writing)
Definition tpctac.h:42
@ TAC_FORMAT_TSV_UK
UK TSV (point as decimal separator)
Definition tpctac.h:37
@ TAC_FORMAT_TSV_INT
International TSV (comma as decimal separator)
Definition tpctac.h:36
@ TAC_FORMAT_IDWC
Hammersmith tissue file format.
Definition tpctac.h:39
@ TAC_FORMAT_XML
XML format (supported for writing)
Definition tpctac.h:41
@ TAC_FORMAT_PMOD
PMOD TAC format.
Definition tpctac.h:33
@ TAC_FORMAT_QVIEW
QView CSV TAC format (reading supported)
Definition tpctac.h:48
@ TAC_FORMAT_SIMPLE
x and y's with space delimiters
Definition tpctac.h:29
@ TAC_FORMAT_ABSS_ALLOGG_OLD
ALLOGG ABSS data (old format); reading supported.
Definition tpctac.h:55
@ TAC_FORMAT_CARIMAS_TXT
Carimas txt format (reading supported)
Definition tpctac.h:47
@ TAC_FORMAT_HRPLUS_HC
HR+ head curve format (reading supported)
Definition tpctac.h:52
@ TAC_FORMAT_DFT
Data format of Turku PET Centre.
Definition tpctac.h:30
@ TAC_FORMAT_AMIDE
Amide format (reading supported)
Definition tpctac.h:46
@ TAC_FORMAT_HRRT_HC
HRRT head curve format (reading supported)
Definition tpctac.h:51
@ TAC_FORMAT_ABSS_SCANDITRONICS
Scanditronics ABSS data; reading supported.
Definition tpctac.h:53
@ TAC_FORMAT_CSV_UK
UK CSV.
Definition tpctac.h:35
@ TAC_FORMAT_BINARY
Binary format (currently not supported)
Definition tpctac.h:57
@ TAC_FORMAT_SIF
Scan information file.
Definition tpctac.h:43
@ TAC_FORMAT_XELERIS
Xeleris format (reading supported)
Definition tpctac.h:44
@ TAC_FORMAT_INVEON
Inveon format (reading supported)
Definition tpctac.h:45
@ TAC_FORMAT_NCI
Old Turku PET Centre format.
Definition tpctac.h:32

Function Documentation

◆ mtacAddTAC()

int mtacAddTAC ( MTAC * mtac,
TAC * tac )
extern

Copy given TAC structure into MTAC list.

See also
mtacInit, mtacFree, mtacAllocate, MTAC, TAC
Returns
Returns TPCERROR status.
Parameters
mtacPointer to initiated MTAC structure; any old contents are preserved.
tacPointer to TAC structure to add.

Definition at line 121 of file mtac.c.

126 {
127 if(mtac==NULL || tac==NULL) return TPCERROR_FAIL;
128 /* Make room for the TAC */
129 int ret=mtacAllocateMore(mtac, 1); if(ret!=TPCERROR_OK) return(ret);
130 /* Copy TAC into the end of the list */
131 ret=tacDuplicate(tac, &mtac->tac[mtac->nr]); if(ret!=TPCERROR_OK) return(ret);
132 mtac->nr++;
133 return TPCERROR_OK;
134}
int mtacAllocateMore(MTAC *mtac, int nr)
Definition mtac.c:83
TAC * tac
Definition tpctac.h:151
int nr
Definition tpctac.h:153
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
Definition tac.c:356
@ TPCERROR_FAIL
General error.
@ TPCERROR_OK
No error.

◆ mtacAllocate()

int mtacAllocate ( MTAC * mtac,
int nr )
extern

Allocate memory for TACs in MTAC data structure.

See also
mtacInit, mtacFree, mtacAddTAC
Returns
Returns TPCERROR status.
Parameters
mtacPointer to initiated MTAC structure; any old contents are deleted. Number of TACs is kept at zero, but TACs in the list are initiated.
nrNr of TACs to allocate

Definition at line 56 of file mtac.c.

62 {
63 if(mtac==NULL) return TPCERROR_FAIL;
64 /* Delete any previous contents */
65 mtacFree(mtac);
66 /* If no memory is requested, then just return */
67 if(nr<1) return TPCERROR_OK;
68 /* Allocate the list of TACs */
69 mtac->tac=(TAC*)malloc(nr*sizeof(TAC));
70 if(mtac->tac==NULL) return TPCERROR_OUT_OF_MEMORY;
71 for(int i=0; i<nr; i++) tacInit(&mtac->tac[i]);
72 mtac->_nr=nr;
73 return TPCERROR_OK;
74}
void mtacFree(MTAC *mtac)
Definition mtac.c:38
int _nr
Definition tpctac.h:155
Definition tpctac.h:87
void tacInit(TAC *tac)
Definition tac.c:24
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.

Referenced by mtacAllocateMore().

◆ mtacAllocateMore()

int mtacAllocateMore ( MTAC * mtac,
int nr )
extern

Allocate memory for more TACs in MTAC structure. Previous contents are not changed.

See also
mtacAllocate, mtacInit, mtacFree, mtacAddTAC, MTAC, TAC
Returns
Returns TPCERROR status.
Parameters
mtacPointer to initiated and previously allocated MTAC structure; any old contents are preserved, including nr of TACs.
nrNr of additional TAC structures to allocate; if structure contains unused space for requested TACs already, then nothing is done.

Definition at line 83 of file mtac.c.

90 {
91 if(mtac==NULL) return TPCERROR_FAIL;
92
93 /* If not allocated before, then use mtacAllocate */
94 if(mtac->_nr==0) return(mtacAllocate(mtac, nr));
95
96 /* Check if there is enough space already */
97 int newNr, addNr;
98 newNr=mtac->nr + nr;
99 addNr=newNr - mtac->_nr;
100 if(addNr<=0) return TPCERROR_OK;
101
102 /* Reallocate memory for TACC data */
103 TAC *tacPtr;
104 tacPtr=realloc(mtac->tac, sizeof(TAC)*newNr);
105 if(tacPtr==NULL) return TPCERROR_OUT_OF_MEMORY;
106 mtac->tac=tacPtr;
107
108 /* Update the nr of allocated TACs and initiate new TACs */
109 for(int i=mtac->_nr; i<newNr; i++) tacInit(&mtac->tac[i]);
110 mtac->_nr=newNr;
111
112 return TPCERROR_OK;
113}
int mtacAllocate(MTAC *mtac, int nr)
Definition mtac.c:56

Referenced by mtacAddTAC().

◆ mtacFree()

void mtacFree ( MTAC * mtac)
extern

Free memory allocated for MTAC data. All contents are destroyed.

Precondition
Before first use initialize the MTAC struct with mtacInit().
See also
mtacInit, tacFree
Parameters
mtacPointer to MTAC.

Definition at line 38 of file mtac.c.

41 {
42 if(mtac==NULL) return;
43 /* Free allocated TACs. */
44 for(int i=0; i<mtac->_nr; i++) tacFree(&mtac->tac[i]);
45 free(mtac->tac);
46 // then set everything to zero or NULL again
47 mtacInit(mtac);
48}
void mtacInit(MTAC *mtac)
Definition mtac.c:23
void tacFree(TAC *tac)
Definition tac.c:106

Referenced by mtacAllocate().

◆ mtacInit()

void mtacInit ( MTAC * mtac)
extern

Initiate the MTAC structure before any use.

See also
mtacFree, MTAC, TAC
Parameters
mtacPointer to MTAC.

Definition at line 23 of file mtac.c.

26 {
27 if(mtac==NULL) return;
28 mtac->nr=mtac->_nr=0;
29 mtac->tac=NULL;
30}

Referenced by mtacFree().

◆ sifWeight()

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

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_NO_DATA
File contains no data.
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51

Referenced by tacSetWeights().

◆ tacAddZeroSample()

int tacAddZeroSample ( TAC * d,
TPCSTATUS * status )
extern

Add an initial sample to TAC(s) with zero time and concentration.

If the sample time of the first sample is zero (or smaller) already, then nothing is done. Sort by sample time before calling this.

See also
tacSortByTime, tacAllocateMoreSamples, tacIsX, tacCheckX1X2X, tacMinX, tacInterpolateToEqualLengthFrames
Author
Vesa Oikonen
Returns
Returns TPCERROR status (0 if ok).
Parameters
dPointer to the TAC structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 366 of file tacx.c.

371 {
372 int verbose=0; if(status!=NULL) verbose=status->verbose;
373 if(verbose>0) printf("%s()\n", __func__);
374 if(d==NULL || d->_sampleNr<1 || d->_tacNr<1) {
375 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
376 return TPCERROR_FAIL;
377 }
378
379 /* Check if we already have the zero sample */
380 if(d->sampleNr>0) {
381 if((d->isframe && d->x1[0]<=0.0) || (!d->isframe && d->x[0]<=0.0)) {
382 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
383 return TPCERROR_OK;
384 }
385 }
386
387 /* If we have no samples at all, but space for samples, then just make one */
388 if(d->sampleNr==0 && d->_sampleNr>0) {
389 d->x[0]=d->x1[0]=d->x2[0]=0.0; d->sampleNr=1;
390 for(int j=0; j<d->tacNr; j++) d->c[j].y[0]=0.0;
391 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
392 return TPCERROR_OK;
393 }
394
395 /* Add space for one more sample */
396 int ret;
397 ret=tacAllocateMoreSamples(d, 1);
398 if(ret!=TPCERROR_OK) {statusSet(status, __func__, __FILE__, __LINE__, ret); return ret;}
399
400 /* Move all data to make room for the zero sample */
401 for(int fi=d->sampleNr; fi>0; fi--) {
402 d->x[fi]=d->x[fi-1]; d->x1[fi]=d->x1[fi-1]; d->x2[fi]=d->x2[fi-1];
403 for(int ri=0; ri<d->tacNr; ri++) d->c[ri].y[fi]=d->c[ri].y[fi-1];
404 d->w[fi]=d->w[fi-1];
405 } // previous sample
406 d->sampleNr++;
407 /* ... and then add the zero sample */
408 for(int ri=0; ri<d->tacNr; ri++) d->c[ri].y[0]=0.0;
409 if(!d->isframe) {
410 d->x[0]=d->x1[0]=d->x2[0]=0.0;
411 } else {
412 d->x1[0]=0.0; d->x2[0]=d->x1[1]; d->x[0]=0.5*(d->x1[0]+d->x2[0]);
413 }
414
415 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
416 return TPCERROR_OK;
417}
double * x
Definition tpctac.h:97
int _sampleNr
Definition tpctac.h:121
int _tacNr
Definition tpctac.h:119
int tacAllocateMoreSamples(TAC *tac, int addNr)
Allocate memory for more samples in TAC data.
Definition tac.c:435

Referenced by tacInput2sim().

◆ tacAllocate()

int tacAllocate ( TAC * tac,
int sampleNr,
int tacNr )
extern

Allocate memory for TAC data (and set data pointers inside the structure). Any previous contents are deleted. Contents are set to NaN.

See also
tacAllocateMore, tacDuplicate, tacInit, tacFree
Returns
Returns TPCERROR status.
Parameters
tacPointer to initiated TAC structure data; any old contents are deleted. tacNr and sampleNr inside the structure are set to or kept at zero.
sampleNrNr of samples to allocate.
tacNrNr of concentration arrays (regional TACs) to allocate.

Definition at line 130 of file tac.c.

138 {
139 if(tac==NULL) return TPCERROR_FAIL;
140 /* Delete any previous contents */
141 tacFree(tac);
142 /* If no memory is requested, then just return */
143 if(sampleNr<1 && tacNr<1) return TPCERROR_OK;
144 if(sampleNr<1 || tacNr<1) return TPCERROR_FAIL;
145
146 /* Allocate memory for TACC data */
147 tac->c=(TACC*)malloc(tacNr*sizeof(TACC));
148 if(tac->c==NULL) return TPCERROR_OUT_OF_MEMORY;
149 for(int i=0; i<tacNr; i++) taccInit(&tac->c[i]);
150 tac->_tacNr=tacNr;
151
152 /* Allocate memory for all double arrays */
153 int n; n=sampleNr*(4+tacNr);
154 tac->_data=(double*)calloc(n, sizeof(double));
155 if(tac->_data==NULL) return TPCERROR_OUT_OF_MEMORY;
156 for(int i=0; i<n; i++) tac->_data[i]=nan("");
157 tac->_sampleNr=sampleNr;
158
159 /* Set pointers for curve data */
160 double *d=tac->_data;
161 tac->x=d; d+=sampleNr;
162 tac->x1=d; d+=sampleNr;
163 tac->x2=d; d+=sampleNr;
164 tac->w=d; d+=sampleNr;
165 for(int i=0; i<tacNr; i++) {tac->c[i].y=d; d+=sampleNr;}
166
167 return TPCERROR_OK;
168}
Definition tpctac.h:66
double * _data
Definition tpctac.h:126
void taccInit(TACC *tacc)
Definition tac.c:48

Referenced by bfm1TCM(), bfmSRTM(), imgToSIF(), mfCreateTAC(), tacAllocateMoreSamples(), tacAllocateWithPAR(), tacDelayFit(), tacDuplicate(), tacExtract(), tacExtractRange(), tacExtractSamples(), tacInterpolate(), tacInterpolateToEqualLengthFrames(), tacMultipleSamples(), tacRead4DM(), tacReadAllogg(), tacReadCarimasTxt(), tacReadCSV(), tacReadDFT(), tacReadGEMS(), tacReadHRPLUSHC(), tacReadHRRTHC(), tacReadInveonCSV(), tacReadMat(), tacReadOldAllogg(), tacReadPMOD(), tacReadQView(), tacReadScanditronics(), tacReadSIF(), tacReadSimple(), and tacSetWeights().

◆ tacAllocateMore()

int tacAllocateMore ( TAC * tac,
int tacNr )
extern

Allocate memory for more TACs in TAC data (and set data pointers inside the structure).

Previous contents are not changed. New contents are set to NaN.

See also
tacAllocate, tacAllocateMoreSamples, tacCopyTacc
Returns
Returns TPCERROR status.
Parameters
tacPointer to initiated and previously allocated TAC structure data; any old contents are preserved, including tacNr.
tacNrNr of additional concentration arrays (regional TACs) to allocate; if structure contains unused space for requested TACs already, then nothing is done.

Definition at line 178 of file tac.c.

185 {
186 if(tac==NULL) return TPCERROR_FAIL;
187 if(tac->_sampleNr<1) return TPCERROR_FAIL;
188 /* Check if there is enough space already */
189 int newNr, addNr;
190 newNr=tac->tacNr+tacNr;
191 addNr=newNr-tac->_tacNr;
192 //printf("newNr := %d\naddNr := %d\n", newNr, addNr);
193 if(addNr<=0) return TPCERROR_OK;
194
195 /* Reallocate memory for TACC data */
196 TACC *taccPtr;
197 taccPtr=realloc(tac->c, sizeof(TACC)*newNr);
198 if(taccPtr==NULL) return TPCERROR_OUT_OF_MEMORY;
199 tac->c=taccPtr;
200 /* Reallocate memory for double arrays */
201 double *dPtr;
202 dPtr=realloc(tac->_data, sizeof(double)*(4+newNr)*tac->_sampleNr);
203 if(dPtr==NULL) return TPCERROR_OUT_OF_MEMORY;
204 tac->_data=dPtr;
205 /* If both ok, then update the nr of allocated TACs and initiate new TTACs */
206 for(int i=tac->_tacNr; i<newNr; i++) taccInit(&tac->c[i]);
207 tac->_tacNr=newNr;
208
209 /* Reset pointers for curve data */
210 double *d=tac->_data;
211 tac->x=d; d+=tac->_sampleNr;
212 tac->x1=d; d+=tac->_sampleNr;
213 tac->x2=d; d+=tac->_sampleNr;
214 tac->w=d; d+=tac->_sampleNr;
215 for(int i=0; i<tac->_tacNr; i++) {tac->c[i].y=d; d+=tac->_sampleNr;}
216
217 /* Set new y values to NaN */
218 for(int i=tac->_tacNr-addNr; i<tac->_tacNr; i++)
219 for(int j=0; j<tac->_sampleNr; j++) tac->c[i].y[j]=nan("");
220
221 return TPCERROR_OK;
222}

Referenced by imgToSIF(), tacInterpolateInto(), tacReadReference(), and tacSetX().

◆ tacAllocateMoreSamples()

int tacAllocateMoreSamples ( TAC * tac,
int addNr )
extern

Allocate memory for more samples in TAC data.

Previous contents are not changed. _sampleNr is increased by nr_to_add, but sampleNr is not changed, and the contents of the new last frame(s) are empty (NaN).

See also
tacAllocateMore, tacAddZeroSample, tacDuplicate
Returns
Returns TPCERROR status (0 when successful).
Parameters
tacPointer to initiated and previously allocated TAC structure data; any old contents are preserved, including tacNr and sampleNr.
addNrNr of samples to add; if TAC structure contains unused space for requested samples already, then nothing is done.

Definition at line 435 of file tac.c.

442 {
443 if(addNr<1) return TPCERROR_OK;
444 if(tac==NULL) return TPCERROR_FAIL;
445 if(tac->_sampleNr<1 || tac->_tacNr<1) return TPCERROR_FAIL;
446
447 /* Check if there is enough space already */
448 int newNr;
449 newNr=tac->sampleNr+addNr;
450 addNr=newNr-tac->_sampleNr;
451 if(addNr<=0) return TPCERROR_OK;
452
453 /* Make a temporary copy of the original data */
454 int ret;
455 TAC temp; tacInit(&temp);
456 ret=tacDuplicate(tac, &temp); if(ret!=TPCERROR_OK) return(ret);
457
458 /* Delete and reallocate the original TAC */
459 tacFree(tac);
460 ret=tacAllocate(tac, newNr, temp.tacNr);
461 if(ret!=TPCERROR_OK) {tacFree(&temp); return(ret);}
462 tac->sampleNr=temp.sampleNr;
463 tac->tacNr=temp.tacNr;
464
465 /* Copy the contents */
466 ret=tacCopyHdr(&temp, tac);
467 if(ret!=TPCERROR_OK) {tacFree(&temp); return(ret);}
468 for(int i=0, ret=0; i<temp.tacNr && ret==0; i++)
469 ret=tacCopyTacc(&temp.c[i], &tac->c[i], temp.sampleNr);
470 if(ret!=0) {tacFree(&temp); return TPCERROR_FAIL;}
471 ret=tacXCopy(&temp, tac, 0, temp.sampleNr-1);
472 if(ret!=0) {tacFree(&temp); return TPCERROR_FAIL;}
473
474 tacFree(&temp);
475 return TPCERROR_OK;
476}
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
int tacCopyTacc(TACC *d1, TACC *d2, int sampleNr)
Definition tac.c:233
int tacCopyHdr(TAC *tac1, TAC *tac2)
Copy TAC header data from tac1 to tac2.
Definition tac.c:310
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacx.c:24

Referenced by imgToSIF(), tacAddZeroSample(), tacFramesToSteps(), tacInput2sim(), tacSetXContiguous(), and tacToBars().

◆ taccFree()

void taccFree ( TACC * tacc)
extern

Free memory allocated for TACC data. All contents are destroyed.

Precondition
Before first use initialize the TACC structure with taccInit().
See also
tacFree, taccInit, tacInit, tacAllocate
Author
Vesa Oikonen
Parameters
taccPointer to TACC

Definition at line 68 of file tac.c.

71 {
72 // TACC does not actually contain mallocated or callocated memory,
73 // therefore we can just clear the values
74 taccInit(tacc);
75}

Referenced by tacFree(), and tacFreeExceptHeader().

◆ tacCheckX1X2X()

int tacCheckX1X2X ( TAC * d)
extern

Check that sample (time frame) x, x1, and x2 values are reasonably set when compared to each other in TAC structure.

See also
tacSortByTime, tacIsX, tacAddZeroSample, tacXCopy, tacSetX, tacXNaNs, tacGetSampleInterval, tacIsXContiguous
Author
Vesa Oikonen
Returns
Returns 1 if reasonable, 0 if not.
Parameters
dPointer to the TAC structure. TAC samples must be sorted. TAC isframe setting has no effect here.

Definition at line 621 of file tacx.c.

625 {
626 if(d==NULL || d->sampleNr<1) return(0);
627 int i, n;
628 double x1, x2, x, dx;
629
630 for(i=n=0; i<d->sampleNr; i++) {
631 x1=d->x1[i]; x2=d->x2[i]; dx=x2-x1; x=0.5*(x1+x2);
632 /* if not similar, or both missing (NaN), that is considered as non-match */
633 if(!doubleMatch(x, d->x[i], 0.15*dx)) {n++; break;}
634 /* check that there is not much overlap with previous sample */
635 if(i>0 && (x1+0.15*dx)<d->x2[i-1]) {n++; break;}
636 /* check that there is not much gap on both sides */
637 if(i>0 && i<d->sampleNr-1) {
638 if(x1-0.15*dx>d->x2[i-1] && x2+0.15*dx<d->x1[i+1]) {n++; break;}
639 }
640 }
641 if(n>0) return(0); else return(1);
642}
int doubleMatch(const double v1, const double v2, const double lim)
Definition doubleutil.c:27

Referenced by tacSetX().

◆ taccInit()

void taccInit ( TACC * tacc)
extern

Initiate the TACC structure before any use.

See also
tacInit, taccFreeExceptHeader, tacInit
Author
Vesa Oikonen
Parameters
taccPointer to TACC

Definition at line 48 of file tac.c.

51 {
52 if(tacc==NULL) return;
54 tacc->size=0.0;
55 tacc->sunit=UNIT_UNKNOWN;
56 tacc->y=NULL;
57 tacc->sw=tacc->sw2=0;
58 tacc->name[0]='\0';
59}
tactype type
Definition tpctac.h:69
char sw
Definition tpctac.h:77
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
unit sunit
Definition tpctac.h:73
char sw2
Definition tpctac.h:79
double size
Definition tpctac.h:71
@ UNIT_UNKNOWN
Unknown unit.
@ TACTYPE_UNKNOWN
Content type not known.

Referenced by tacAllocate(), tacAllocateMore(), and taccFree().

◆ tacCompareConc()

int tacCompareConc ( TAC * d1,
TAC * d2,
const int i,
const double test_abs,
const double test_rel,
TPCSTATUS * status )
extern

Check whether TAC concentrations (y values) are the same in two TAC data. Note that units are ignored here.

If either absolute or relative difference is below the limit, the test is reported as passed.

See also
tacCompareUnit, tacCompareTimes.
Returns
0 in case of match, and >0 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to TAC structure.
d2Pointer to TAC structure.
iTAC index [0..tacNr-1] to compare; enter <0 to verify all TACs.
test_absLimit for accepted absolute difference; obligatory.
test_relOptional limit for accepted relative difference |2*(x1-x2)/(x1+x2)| ; set to negative value to not test this; in case of zero mean, this test is assumed to fail, but test for absolute difference may still pass.
statusPointer to status data; enter NULL if not needed.

Definition at line 122 of file taccomp.c.

137 {
138 int verbose=0; if(status!=NULL) verbose=status->verbose;
139 if(verbose>1) printf("%s()\n", __func__);
140
141 /* Check that required data exists */
142 if(d1==NULL || d2==NULL || d1->tacNr<1 || d2->tacNr<1
143 || d1->sampleNr<1 || d2->sampleNr<1) {
144 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
145 return 1;
146 }
147 /* If index is specified, then verify that that TAC is available */
148 if(i>=0 && (i>=d1->tacNr || i>=d2->tacNr)) {
149 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
150 return 1;
151 }
152
153 /* If index is not specified, then tacNr must match */
154 if(i<0 && (d1->tacNr!=d2->tacNr)) {
155 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
156 if(verbose>0) printf("different TAC nr.\n");
157 return(2);
158 }
159
160 /* Sample nr must match */
161 if(d1->sampleNr!=d2->sampleNr) {
162 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
163 if(verbose>0) printf("different sample nr.\n");
164 return(3);
165 }
166
167 /* Compare */
168 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
169 for(int ri=0; ri<d1->tacNr; ri++) if(i<0 || i==ri) {
170 for(int fi=0; fi<d1->sampleNr; fi++) {
171 if(doubleMatch(d1->c[ri].y[fi], d2->c[ri].y[fi], test_abs)==1)
172 continue;
173 if(test_rel>0.0 &&
174 doubleMatchRel(d1->c[ri].y[fi], d2->c[ri].y[fi], test_rel)==1)
175 continue;
176 if(verbose>0) {
177 double s;
178 s=fabs(d1->c[ri].y[fi]-d2->c[ri].y[fi]);
179 printf("tac1.c[%d].y[%d] := %g\n", ri, fi, d1->c[ri].y[fi]);
180 printf("tac2.c[%d].y[%d] := %g\n", ri, fi, d2->c[ri].y[fi]);
181 printf("|diff| := %g\n", s);
182 printf("diff_limit := %g\n", test_abs);
183 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
184 }
185 return(10);
186 }
187 }
188 return(0);
189}
int doubleMatchRel(const double v1, const double v2, const double lim)
Definition doubleutil.c:77

◆ tacCompareNames()

int tacCompareNames ( TAC * d1,
TAC * d2,
const int i,
TPCSTATUS * status )
extern

Check whether TAC names are the same in two TAC data.

Comparison is very strict and even case-sensitive, thus TAC names may need to be preprocessed if this is used for other purpose than SW testing.

Returns
0 in case of match, 1 if no match or error.
Author
Vesa Oikonen
See also
tacSortByName, tacCompareUnit
Parameters
d1Pointer to TAC structure.
d2Pointer to TAC structure.
iTAC index [0..tacNr-1] to compare; enter <0 to verify all TACs.
statusPointer to status data; enter NULL if not needed.

Definition at line 67 of file taccomp.c.

76 {
77 int verbose=0; if(status!=NULL) verbose=status->verbose;
78 if(verbose>1) printf("%s()\n", __func__);
79
80 /* Check that required data exists */
81 if(d1==NULL || d2==NULL || d1->tacNr<1 || d2->tacNr<1) {
82 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
83 return 1;
84 }
85 /* If index is specified, then verify that that TAC is available */
86 if(i>=0 && (i>=d1->tacNr || i>=d2->tacNr)) {
87 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
88 return 1;
89 }
90
91 /* If index is not specified, then tacNr must match */
92 if(i<0 && (d1->tacNr!=d2->tacNr)) {
93 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
94 if(verbose>0) printf("different TAC nr.\n");
95 return(1);
96 }
97
98 /* Compare */
99 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
100 for(int ri=0; ri<d1->tacNr; ri++) if(i<0 || i==ri) {
101 if(strcmp(d1->c[ri].name, d2->c[ri].name)!=0) {
102 if(verbose>0) {
103 printf("tac1.c[%d].name := '%s'\n", ri, d1->c[ri].name);
104 printf("tac2.c[%d].name := '%s'\n", ri, d2->c[ri].name);
105 }
106 return(1);
107 }
108 }
109 return(0);
110}

◆ tacCompareTimes()

int tacCompareTimes ( TAC * d1,
TAC * d2,
const double test_abs,
const double test_rel,
TPCSTATUS * status )
extern

Check whether TAC sample times (x values) are the same in two TAC data. Note that units are ignored here.

If either absolute or relative difference is below the limit, the test is reported as passed.

See also
tacCompareUnit, tacCompareConc, tacSortByTime, tacVerifyTimeOrder.
Returns
0 in case of match, and >0 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to TAC structure.
d2Pointer to TAC structure.
test_absLimit for accepted absolute difference.
test_relOptional limit for accepted relative difference |2*(x1-x2)/(x1+x2)| ; set to negative value to not test this; in case of zero mean, this test is assumed to fail, but test for absolute difference may still pass.
statusPointer to status data; enter NULL if not needed.

Definition at line 201 of file taccomp.c.

214 {
215 int verbose=0; if(status!=NULL) verbose=status->verbose;
216 if(verbose>1) printf("%s()\n", __func__);
217
218 /* Check that required data exists */
219 if(d1==NULL || d2==NULL || d1->sampleNr<1 || d2->sampleNr<1) {
220 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
221 return 1;
222 }
223
224 /* X type must match */
225 if(d1->isframe!=d2->isframe) {
226 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
227 if(verbose>0) printf("different sampling type.\n");
228 return(2);
229 }
230
231 /* Sample nr must match */
232 if(d1->sampleNr!=d2->sampleNr) {
233 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
234 if(verbose>0) printf("different sample nr.\n");
235 return(3);
236 }
237
238 /* Compare */
239 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
240 for(int fi=0; fi<d1->sampleNr; fi++) {
241 if(d1->isframe==0) {
242 if(doubleMatch(d1->x[fi], d2->x[fi], test_abs)==1)
243 continue;
244 if(test_rel>0.0 && doubleMatchRel(d1->x[fi], d2->x[fi], test_rel)==1)
245 continue;
246 if(verbose>0) {
247 double s;
248 s=fabs(d1->x[fi]-d2->x[fi]);
249 printf("tac1.x[%d] := %g\n", fi, d1->x[fi]);
250 printf("tac2.x[%d] := %g\n", fi, d2->x[fi]);
251 printf("|diff| := %g\n", s);
252 printf("diff_limit := %g\n", test_abs);
253 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
254 }
255 return(10);
256 } else {
257 if(doubleMatch(d1->x1[fi], d2->x1[fi], test_abs)==1 &&
258 doubleMatch(d1->x2[fi], d2->x2[fi], test_abs)==1)
259 continue;
260 if(test_rel>0.0 &&
261 doubleMatchRel(d1->x1[fi], d2->x1[fi], test_rel)==1 &&
262 doubleMatchRel(d1->x2[fi], d2->x2[fi], test_rel)==1)
263 continue;
264 if(verbose>0) {
265 printf("tac1.x1[%d] := %g\n", fi, d1->x1[fi]);
266 printf("tac2.x1[%d] := %g\n", fi, d2->x1[fi]);
267 printf("|diff| := %g\n", fabs(d1->x1[fi]-d2->x1[fi]));
268 printf("tac1.x2[%d] := %g\n", fi, d1->x2[fi]);
269 printf("tac2.x2[%d] := %g\n", fi, d2->x2[fi]);
270 printf("|diff| := %g\n", fabs(d1->x2[fi]-d2->x2[fi]));
271 printf("diff_limit := %g\n", test_abs);
272 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
273 }
274 return(11);
275 }
276 }
277 return(0);
278}

◆ tacCompareUnit()

int tacCompareUnit ( TAC * d1,
TAC * d2,
TPCSTATUS * status )
extern

Check whether time and concentration units are the same in two TAC data.

Returns
0 in case of match, 1 if y (concentration) unit is not matching, 2 if x (time) unit is not matching, and 3 if neither is matching.
See also
tacCompareConc, tacCompareTimes
Author
Vesa Oikonen
Parameters
d1Pointer to TAC structure.
d2Pointer to TAC structure.
statusPointer to status data; enter NULL if not needed

Definition at line 27 of file taccomp.c.

34 {
35 int verbose=0; if(status!=NULL) verbose=status->verbose;
36 if(verbose>1) printf("%s()\n", __func__);
37
38 /* Check that required data exists */
39 if(d1==NULL || d2==NULL) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
41 return 3;
42 }
43
44 int ret=0;
45 if(d1->cunit!=d2->cunit) ret+=1;
46 if(d1->tunit!=d2->tunit) ret+=2;
47 if(ret>0 && verbose>0) {
48 printf("tac1.cunit := %s\n", unitName(d1->cunit));
49 printf("tac2.cunit := %s\n", unitName(d2->cunit));
50 printf("tac1.tunit := %s\n", unitName(d1->tunit));
51 printf("tac2.tunit := %s\n", unitName(d2->tunit));
52 }
53 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
54 return(ret);
55}
int cunit
Definition tpctac.h:105
int tunit
Definition tpctac.h:109
char * unitName(int unit_code)
Definition units.c:143

◆ tacCompareWeights()

int tacCompareWeights ( TAC * d1,
TAC * d2,
const double test_abs,
const double test_rel,
TPCSTATUS * status )
extern

Check whether TAC weights are the same in two TAC data.

If either absolute or relative difference is below the limit, the test is reported as passed.

See also
tacCompareTimes, tacCompareConc, tacCompareNames.
Returns
0 in case of match, and >0 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to TAC structure.
d2Pointer to TAC structure.
test_absLimit for accepted absolute difference.
test_relOptional limit for accepted relative difference |2*(w1-w2)/(w1+w2)| ; set to negative value to not test this; in case of zero mean, this test is assumed to fail, but test for absolute difference may still pass.
statusPointer to status data; enter NULL if not needed.

Definition at line 289 of file taccomp.c.

302 {
303 int verbose=0; if(status!=NULL) verbose=status->verbose;
304 if(verbose>1) printf("%s()\n", __func__);
305
306 /* Check that required data exists */
307 if(d1==NULL || d2==NULL || d1->sampleNr<1 || d2->sampleNr<1) {
308 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
309 return 1;
310 }
311
312 /* Weight setting must match */
313 if(d1->weighting!=d2->weighting) {
314 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
315 if(verbose>0) printf("different weighting setting.\n");
316 return(2);
317 }
318
319 /* If no weights, then no checking either */
320 if(d1->weighting==WEIGHTING_OFF && d2->weighting==WEIGHTING_OFF) return(0);
321 if(d1->weighting==WEIGHTING_UNKNOWN && d2->weighting==WEIGHTING_UNKNOWN) return(0);
322
323 /* Sample nr must match */
324 if(d1->sampleNr!=d2->sampleNr) {
325 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
326 if(verbose>0) printf("different sample nr.\n");
327 return(3);
328 }
329
330 /* Compare */
331 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
332 for(int fi=0; fi<d1->sampleNr; fi++) {
333 if(doubleMatch(d1->w[fi], d2->w[fi], test_abs)==1) continue;
334 if(test_rel>0.0 && doubleMatchRel(d1->w[fi], d2->w[fi], test_rel)==1) continue;
335 if(verbose>0) {
336 double s;
337 s=fabs(d1->w[fi]-d2->w[fi]);
338 printf("tac1.w[%d] := %g\n", fi, d1->w[fi]);
339 printf("tac2.w[%d] := %g\n", fi, d2->w[fi]);
340 printf("|diff| := %g\n", s);
341 printf("diff_limit := %g\n", test_abs);
342 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
343 }
344 return(10);
345 }
346 return(0);
347}
@ WEIGHTING_UNKNOWN
Not known; usually assumed that not weighted.

◆ tacCopyHdr()

int tacCopyHdr ( TAC * tac1,
TAC * tac2 )
extern

Copy TAC header data from tac1 to tac2.

Information regarding data size or weighting is not copied. IFT contents are copied if available. Previous IFT contents are deleted.

See also
tacCopyTacchdr, tacIsWeighted, tacWCopy
Returns
Returns TPCERROR status.
Parameters
tac1Pointer to source TAC structure.
tac2Pointer to target TAC structure.

Definition at line 310 of file tac.c.

315 {
316 /* Check that required data exists */
317 if(tac1==NULL || tac2==NULL) return TPCERROR_FAIL;
318 /* Copy TAC header fields */
319 tac2->format=tac1->format;
320 tac2->isframe=tac1->isframe;
321 tac2->cunit=tac1->cunit;
322 tac2->tunit=tac1->tunit;
323 //tac2->weighting=tac1->weighting;
324 /* Copy IFT */
325 iftFree(&tac2->h); iftDuplicate(&tac1->h, &tac2->h);
326 return TPCERROR_OK;
327}
void iftFree(IFT *ift)
Definition ift.c:37
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
tacformat format
Definition tpctac.h:93
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141

Referenced by tacAllocateMoreSamples(), tacDuplicate(), tacExtract(), tacExtractRange(), tacExtractSamples(), tacInterpolate(), tacInterpolateToEqualLengthFrames(), and tacMultipleSamples().

◆ tacCopyTacc()

int tacCopyTacc ( TACC * d1,
TACC * d2,
int sampleNr )
extern

Copy TACC contents (y data and its header) from tacc1 to tacc2.

These may be inside different TAC structures, therefore sampleNr is needed.

See also
tacCopyTacchdr, tacCopyTaccdata, tacXCopy, tacWCopy, tacDuplicate, tacCopyHdr, tacAllocateMore, tacDeleteTACC, tacSwapTACCs
Returns
Returns TPCERROR status.
Parameters
d1Pointer to source TACC structure.
d2Pointer to target TACC structure.
sampleNrSample (frame) number.

Definition at line 233 of file tac.c.

240 {
241 int ret;
242
243 /* Check that required data exists */
244 if(d1==NULL || d2==NULL) return TPCERROR_FAIL;
245 /* Copy TACC header */
246 ret=tacCopyTacchdr(d1, d2); if(ret!=TPCERROR_OK) return ret;
247 /* Copy TACC data */
248 ret=tacCopyTaccdata(d1, d2, sampleNr); if(ret!=TPCERROR_OK) return ret;
249 return TPCERROR_OK;
250}
int tacCopyTaccdata(TACC *d1, TACC *d2, int sampleNr)
Definition tac.c:260
int tacCopyTacchdr(TACC *d1, TACC *d2)
Definition tac.c:282

Referenced by tacAllocateMoreSamples(), tacDuplicate(), tacExtract(), and tacReadReference().

◆ tacCopyTaccdata()

int tacCopyTaccdata ( TACC * d1,
TACC * d2,
int sampleNr )
extern

Copy TACC y data from tacc1 to tacc2.

These may be inside different TAC structures, therefore sampleNr is needed.

See also
tacCopyTacchdr, tacXCopy, tacWCopy
Returns
Returns TPCERROR status.
Parameters
d1Pointer to source TACC structure.
d2Pointer to target TACC structure.
sampleNrSample (frame) nr.

Definition at line 260 of file tac.c.

267 {
268 /* Check that required data exists */
269 if(d1==NULL || d2==NULL) return TPCERROR_FAIL;
270 if(sampleNr<1) return TPCERROR_OK;
271 /* Copy data array contents */
272 for(int i=0; i<sampleNr; i++) d2->y[i]=d1->y[i];
273 return TPCERROR_OK;
274}

Referenced by tacCopyTacc().

◆ tacCopyTacchdr()

int tacCopyTacchdr ( TACC * d1,
TACC * d2 )
extern

Copy TACC header data from tacc1 to tacc2.

See also
tacCopyHdr, tacCopyTaccdata, tacCopyTacc
Returns
Returns TPCERROR status.
Parameters
d1Pointer to source TACVOI structure.
d2Pointer to target TACVOI structure.

Definition at line 282 of file tac.c.

287 {
288 /* Check that required data exists */
289 if(d1==NULL || d2==NULL) return TPCERROR_FAIL;
290 /* Copy TACC header fields */
291 d2->type=d1->type;
292 d2->size=d1->size;
293 d2->sunit=d1->sunit;
294 d2->sw=d1->sw;
295 d2->sw2=d1->sw2;
296 strcpy(d2->name, d1->name);
297 return TPCERROR_OK;
298}

Referenced by tacCopyTacc(), tacExtractRange(), tacExtractSamples(), tacInterpolate(), tacInterpolateInto(), tacInterpolateToEqualLengthFrames(), and tacMultipleSamples().

◆ tacCorrectFrameOverlap()

int tacCorrectFrameOverlap ( TAC * d,
TPCSTATUS * status )
extern

Correct PET frame start and end times if frames are slightly overlapping or have small gaps in between.

Large gap is not corrected and it does not lead to an error. If TAC file does not contain frame start and end times, but just mid time point, then this function does nothing but check that samples are in correct order. Data must be sorted for increasing sample time before calling this function, otherwise an error is returned.

See also
tacIsX, tacXRange, tacVerifyTimeOrder, tacSortByTime, tacXCopy, tacMultipleSamples, tacFramesToSteps
Returns
If overlap is considerable (>20%), or another error is encountered, function returns a non-zero enum tpcerror value. Otherwise 0 (TPCERROR_OK) is returned.
Author
Vesa Oikonen
Test
Add tests.
Parameters
dPointer to TAC data which is sorted by increasing sample time.
statusPointer to status data; enter NULL if not needed.

Definition at line 65 of file tacx.c.

70 {
71 int verbose=0; if(status!=NULL) verbose=status->verbose;
72 if(verbose>0) printf("%s()\n", __func__);
73 if(d==NULL) {
74 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
75 return TPCERROR_FAIL;
76 }
77 /* If no frame start and end times, then just check the order */
78 if(d->isframe==0) {
79 if(tacVerifyTimeOrder(d, status)) {
80 if(verbose>0) fprintf(stderr, "Error: sample times are not in order.\n");
81 return(status->error);
82 }
83 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
84 return TPCERROR_OK;
85 }
86 /* Check each frame */
87 double overlap, flen1, flen2, overlap_limit=0.0;
88 for(int fi=0; fi<d->sampleNr-1; fi++) {
89 overlap=d->x2[fi]-d->x1[fi+1];
90 if(overlap==0.0) continue; // no gap or overlap
91 /* Calculate the frame length of current frame and the next frame */
92 flen1=d->x2[fi]-d->x1[fi]; flen2=d->x2[fi+1]-d->x1[fi+1];
93 if(flen1<0.0 || flen2<0.0) return(1);
94 /* Set the limit */
95 if(flen1<flen2) overlap_limit=0.2*flen1; else overlap_limit=0.2*flen2;
96 /* Check if gap or overlap is too large to be fixed automatically */
97 if(overlap<-overlap_limit) continue; // gap is too large, then do nothing
98 if(overlap>overlap_limit) { // overlap is too large: error
99 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OVERLAPPING_DATA);
101 }
102 /* Correct the small gap/overlap by making frame durations more similar */
103 if(overlap>0.0) { // overlap
104 if(flen1>flen2) d->x2[fi]=d->x1[fi+1]; else d->x1[fi+1]=d->x2[fi];
105 } else { // gap
106 if(flen1>flen2) d->x1[fi+1]=d->x2[fi]; else d->x2[fi]=d->x1[fi+1];
107 }
108 }
109
110 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
111 return TPCERROR_OK;
112}
int tacVerifyTimeOrder(TAC *d, TPCSTATUS *status)
Definition tacorder.c:25
@ TPCERROR_OVERLAPPING_DATA
Overlapping data.

Referenced by tacReadModelingData().

◆ tacDecayCorrection()

int tacDecayCorrection ( TAC * tac,
int isotope,
int mode,
TPCSTATUS * status )
extern

Correct TAC data for physical decay, or remove the decay correction. Sample weights, if available, are modified, too.

See also
tacGetHeaderDecayCorrection, tacGetIsotope, tacGetHeaderIsotope, decayCorrectionFactorFromIsotope, tacDelay
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to TAC structure; status of decay correction in TAC is not verified, but set in this function. TAC must contain valid sample time unit.
isotopeIsotope code.
mode0=Remove decay correction; 1=Correct for decay.
statusPointer to status data; enter NULL if not needed.

Definition at line 59 of file tacdc.c.

69 {
70 int verbose=0; if(status!=NULL) verbose=status->verbose;
71 if(verbose>0) printf("%s()\n", __func__);
72 /* check that data exists */
73 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1) {
74 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
75 return TPCERROR_NO_DATA;
76 }
77 /* check time unit */
78 if(!unitIsTime(tac->tunit)) {
79 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNKNOWN_UNIT);
81 }
82 /* check isotope and get halflife */
83 double f, lambda, halflife=isotopeHalflife(isotope); // halflife in min
84 if(isotope==ISOTOPE_UNKNOWN || isnan(halflife)) {
85 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNKNOWN_ISOTOPE);
87 }
88 /* convert halflife to the same unit that the TAC data has */
90 if(!isnan(f)) halflife*=f;
91 /* calculate the lambda */
92 lambda=lambdaFromHalflife(halflife);
93 if(mode==0) lambda=-lambda;
94 if(verbose>2) {
95 printf("halflife := %g\n", halflife);
96 printf("lambda := %g\n", lambda);
97 }
98
99
100 /*
101 * Decay correction / removal
102 */
103 if(verbose>2) {
104 if(mode!=0) printf("decay correction\n"); else printf("removing decay correction\n");
105 fflush(stdout);
106 }
107 for(int i=0; i<tac->sampleNr; i++) {
108 /* Calculate decay correction factor */
109 if(tac->isframe) {
110 if(isnan(tac->x1[i]) || isnan(tac->x2[i])) continue;
111 f=decayCorrectionFactorFromLambda(lambda, tac->x1[i], tac->x2[i]-tac->x1[i]);
112 } else {
113 if(isnan(tac->x[i])) continue;
114 f=decayCorrectionFactorFromLambda(lambda, tac->x[i], 0.0);
115 }
116 if(verbose>6) printf(" %10.4f -> %e\n", tac->x[i], f);
117 /* Correct all TACs */
118 for(int j=0; j<tac->tacNr; j++) tac->c[j].y[i]*=f;
119 /* Opposite correction for weights, if available */
122 tac->w[i]/=f;
123 }
124 if(tacIsWeighted(tac)) tacWeightNorm(tac, NULL);
127
128 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
129 return(TPCERROR_OK);
130}
double lambdaFromHalflife(double halflife)
Definition decay.c:47
double decayCorrectionFactorFromLambda(double lambda, double starttime, double duration)
Definition decay.c:79
double isotopeHalflife(int isotope_code)
Definition isotope.c:62
int tacSetHeaderDecayCorrection(IFT *h, decaycorrection dc)
Definition tacift.c:578
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
@ 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.
@ UNIT_MIN
minutes
@ TPCERROR_UNKNOWN_UNIT
Unknown data unit.
@ TPCERROR_UNKNOWN_ISOTOPE
Unknown isotope.
double unitConversionFactor(const int u1, const int u2)
Definition units.c:487
int unitIsTime(int u)
Definition units.c:359
@ 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

Referenced by tacSetWeights().

◆ tacDefaultExtension()

char * tacDefaultExtension ( tacformat c)
extern

Return pointer to default TAC filename extension, including the dot, based on the TAC format code.

Returns
pointer to the filename extension string.
See also
tpcformat, tacFormattxt, tacFormatWriteSupported
Author
Vesa Oikonen
Parameters
cTAC format code.

Definition at line 144 of file tacio.c.

147 {
148 if(c<TAC_FORMAT_UNKNOWN || c>=TAC_FORMAT_LAST) return NULL;
149 return (char*)tac_fn_ext[c];
150}

◆ tacDeleteMissingSamples()

int tacDeleteMissingSamples ( TAC * d)
extern

Delete those samples (time frames) from TAC structure, which contain only missing y values, and/or x is NaN.

See also
tacDeleteSample, tacExtractRange, tacIsX, tacXNaNs, tacFixNaNs, tacIsXContiguous
Returns
Returns TPCERROR status (0 if ok).
Parameters
dPointer to the TAC structure.

Definition at line 450 of file tacx.c.

453 {
454 if(d==NULL) return TPCERROR_FAIL;
455 int fi, ri, n, delthat=0;
456 fi=d->sampleNr-1;
457 while(fi>=0) {
458 delthat=0;
459 /* check the x value(s) for this sample */
460 if(d->isframe) {
461 if(!isfinite(d->x1[fi]) || !isfinite(d->x2[fi])) delthat=1;
462 } else {
463 if(!isfinite(d->x[fi])) delthat=1;
464 }
465 /* check the y value(s) for this sample */
466 for(ri=n=0; ri<d->tacNr; ri++) if(isfinite(d->c[ri].y[fi])) n++;
467 if(n==0) delthat=1;
468 if(delthat!=0) {
469 /* delete sample */
470 tacDeleteSample(d, fi);
471 }
472 /* go to previous sample */
473 fi--;
474 }
475 return TPCERROR_OK;
476}
int tacDeleteSample(TAC *d, int i)
Delete a certain sample (time frame) from TAC structure.
Definition tacx.c:426

Referenced by tacMultipleSamples().

◆ tacDeleteSample()

int tacDeleteSample ( TAC * d,
int i )
extern

Delete a certain sample (time frame) from TAC structure.

See also
tacAllocateMoreSamples, tacExtractRange, tacDeleteMissingSamples, tacMultipleSamples
Author
Vesa Oikonen
Returns
Returns TPCERROR status (0 if ok).
Parameters
dPointer to the TAC structure.
iIndex of the sample to delete, [0..sampleNr-1].

Definition at line 426 of file tacx.c.

431 {
432 if(d==NULL || i<0 || i>=d->sampleNr) return TPCERROR_FAIL;
433 int fi, ri;
434 for(fi=i+1; fi<d->sampleNr; fi++) {
435 d->x[fi-1]=d->x[fi]; d->x1[fi-1]=d->x1[fi]; d->x2[fi-1]=d->x2[fi];
436 for(ri=0; ri<d->tacNr; ri++) d->c[ri].y[fi-1]=d->c[ri].y[fi];
437 d->w[fi-1]=d->w[fi];
438 }
439 d->sampleNr--;
440 return TPCERROR_OK;
441}

Referenced by tacDeleteMissingSamples(), and tacMultipleSamples().

◆ tacDeleteTACC()

int tacDeleteTACC ( TAC * d,
int i )
extern

Delete specified TACC inside TAC structure, moving the positions of other TACCs accordingly.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSwapTACCs, tacMoveTACC
Parameters
dPointer to TAC data. Main header is not changed, but tacNr is decreased.
iTACC index [0..tacNr-1].

Definition at line 310 of file tacorder.c.

315 {
316 /* Check that region exists */
317 if(d==NULL || i<0 || i>=d->tacNr) return(TPCERROR_FAIL);
318 /* If the last TACC is to be deleted, then just decrease the tacNr */
319 if(i==d->tacNr-1) {d->tacNr--; return(TPCERROR_OK);}
320 /* Otherwise move it to the last position, and then decrease tacNr */
321 if(tacMoveTACC(d, i, d->tacNr-1)!=TPCERROR_OK) return(TPCERROR_FAIL);
322 d->tacNr--;
323 return(TPCERROR_OK);
324}
int tacMoveTACC(TAC *d, int from, int to)
Definition tacorder.c:250

Referenced by tacReadReference(), and tacWMove().

◆ tacDuplicate()

int tacDuplicate ( TAC * tac1,
TAC * tac2 )
extern

Make a duplicate of TAC structure.

In the duplicate, space is allocated only for the tacNr and sampleNr specified in the original TAC.

See also
tacExtract, tacAllocate, tacCopyHdr, tacCopyTacc, tacXCopy, tacDeleteTACC
Returns
Returns TPCERROR status (0 when successful).
Parameters
tac1Pointer to the source TAC.
tac2Pointer to the target TAC; must be initiated; any old contents are deleted.

Definition at line 356 of file tac.c.

361 {
362 if(tac1==NULL || tac2==NULL) return TPCERROR_FAIL;
363 if(tac1->sampleNr<1 || tac1->tacNr<1) return TPCERROR_FAIL;
364
365 /* Empty the duplicate */
366 tacFree(tac2);
367
368 int ret;
369
370 /* Allocate memory for tac2 */
371 ret=tacAllocate(tac2, tac1->sampleNr, tac1->tacNr);
372 if(ret!=TPCERROR_OK) return(ret);
373 tac2->sampleNr=tac1->sampleNr;
374 tac2->tacNr=tac1->tacNr;
375
376 /* Copy the contents */
377 ret=tacCopyHdr(tac1, tac2);
378 if(ret!=TPCERROR_OK) return(ret);
379 for(int i=0, ret=0; i<tac1->tacNr && ret==0; i++)
380 ret=tacCopyTacc(&tac1->c[i], &tac2->c[i], tac1->sampleNr);
381 if(ret!=0) return TPCERROR_FAIL;
382 ret=tacXCopy(tac1, tac2, 0, tac1->sampleNr-1);
383 if(ret!=0) return TPCERROR_FAIL;
384 ret=tacWCopy(tac1, tac2, 0, tac1->sampleNr-1);
385 if(ret!=0) return TPCERROR_FAIL;
386
387 return TPCERROR_OK;
388}
int tacWCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacw.c:41

Referenced by mtacAddTAC(), tacAllocateMoreSamples(), tacDelayFit(), tacExtractRange(), tacExtractSamples(), tacFramesToSteps(), tacInput2sim(), tacIntegrate(), tacIntegrateFE(), tacMultipleSamples(), tacReadReference(), tacSetX(), tacSetXContiguous(), and tacToBars().

◆ tacEnsureNames()

void tacEnsureNames ( TAC * tac)
extern

Ensure that TAC structure contains a name for each TAC. If not available, then TAC index+1 is written as name.

See also
tacIndividualNames, tacSelectTACs, tacSelectBestReference, roinameMatch
Author
Vesa Oikonen
Parameters
tacPointer to TAC structure.

Definition at line 50 of file tacname.c.

53 {
54 if(tac==NULL || tac->tacNr<1) return;
55 int ri, u, n;
56 u=tac->tacNr; n=1; while((u/=10)>=1) n++;
58 for(ri=0; ri<tac->tacNr; ri++) {
59 if(!roinameExists(tac->c[ri].name))
60 sprintf(tac->c[ri].name, "%0*d", n, 1+ri);
61 }
62 return;
63}
int roinameExists(char *roiname)
Verifies whether TAC name exists or not.
Definition roiname.c:158
#define MAX_TACNAME_LEN
Max length of TAC ID name (not including trailing zero)

Referenced by tacWriteCSV(), tacWriteDFT(), tacWritePMOD(), tacWriteSheetIntoXML(), and tacWriteXML().

◆ tacExtract()

int tacExtract ( TAC * d1,
TAC * d2,
const int i )
extern

Extract the specified TAC from existing TAC structure into a new TAC.

See also
tacDuplicate, tacDeleteTACC, tacCopyTacc, tacExtractSamples
Returns
Returns TPCERROR status (0 if ok).
Parameters
d1Pointer to the source TAC structure. Not modified.
d2Pointer to the target TAC structure; any previous contents are deleted.
See also
tacInit, tacFree
Parameters
iIndex of the TAC to extract [0..tacNr-1].

Definition at line 396 of file tac.c.

404 {
405 if(d1==NULL || d2==NULL) return TPCERROR_FAIL;
406 if(d1->sampleNr<1 || d1->tacNr<1) return TPCERROR_NO_DATA;
407 if(i<0 || i>=d1->tacNr) return TPCERROR_INVALID_VALUE;
408
409 /* Remove any old contents in target structure */
410 tacFree(d2);
411
412 /* Allocate space for the new TAC */
413 int ret=tacAllocate(d2, d1->sampleNr, 1); if(ret!=TPCERROR_OK) return(ret);
414 d2->sampleNr=d1->sampleNr;
415 d2->tacNr=1;
416
417 /* Copy contents */
418 ret=tacCopyHdr(d1, d2); if(ret!=TPCERROR_OK) {tacFree(d2); return(ret);}
419 ret=tacXCopy(d1, d2, 0, d1->sampleNr-1); if(ret!=TPCERROR_OK) {tacFree(d2); return(ret);}
420 ret=tacCopyTacc(d1->c+i, d2->c, d1->sampleNr); if(ret!=TPCERROR_OK) {tacFree(d2); return(ret);}
421 ret=tacWCopy(d1, d2, 0, d1->sampleNr-1); if(ret!=TPCERROR_OK) {tacFree(d2); return(ret);}
422
423 return(TPCERROR_OK);
424}

◆ tacExtractRange()

int tacExtractRange ( TAC * d1,
TAC * d2,
double startT,
double endT )
extern

Extract the specified time (x) range from TAC structure.

See also
tacDeleteSample, tacDeleteMissingSamples, tacExtractSamples, tacCheckX1X2X, tacGetSampleInterval
Author
Vesa Oikonen
Returns
Returns TPCERROR status (0 if ok).
Parameters
d1Pointer to the source TAC structure. Data must be sorted by ascending x.
d2Pointer to the target TAC structure; any previous contents are deleted. The source TAC pointer can be given for in-place extraction.
See also
tacInit, tacFree
Parameters
startTStart time of data that is preserved (in same units as in TAC)
endTEnd time of data that is preserved (in same units as in TAC)

Definition at line 486 of file tacx.c.

497 {
498 if(d1==NULL || d2==NULL) return TPCERROR_FAIL;
499 if(d1->sampleNr<1) return TPCERROR_NO_DATA;
500 if(endT<startT) return TPCERROR_INVALID_VALUE;
501
502 /* Duplicate source TAC, in case target points to the same data */
503 TAC tac; tacInit(&tac); if(tacDuplicate(d1, &tac)!=TPCERROR_OK) return TPCERROR_FAIL;
504
505 /* Remove any old contents in target structure */
506 tacFree(d2);
507
508 /* Get the range of TAC frame middle times */
509 double beg, end;
510 if(tac.isframe) {
511 beg=0.5*(tac.x1[0]+tac.x2[0]);
512 end=0.5*(tac.x1[tac.sampleNr-1]+tac.x2[tac.sampleNr-1]);
513 } else {
514 beg=tac.x[0]; end=tac.x[tac.sampleNr-1];
515 }
516
517 /* Check whether required range is outside the TAC range */
518 if(startT>=end || endT<beg) {tacFree(&tac); return TPCERROR_NO_DATA;}
519
520 /* If the whole TAC is inside required range, then just copy it */
521 if(startT<=beg && endT>=end) {
522 int ret=tacDuplicate(&tac, d2);
523 tacFree(&tac); return(ret);
524 }
525
526 /* Count how many samples are inside the required range */
527 /* And get the first and last sample indices */
528 int i, n=0, i1=-1, i2=-1;
529 double x;
530 for(i=0; i<tac.sampleNr; i++) {
531 if(tac.isframe) x=0.5*(tac.x1[i]+tac.x2[i]); else x=tac.x[i];
532 if(x<startT) continue;
533 if(x>endT) break;
534 i2=i; if(i1<0) i1=i;
535 n++;
536 }
537 if(n==0 || i1<0 || i2<i1) {tacFree(&tac); return TPCERROR_NO_DATA;}
538
539 /* Allocate memory for the data to be extracted */
540 int ret;
541 ret=tacAllocate(d2, n, tac.tacNr); if(ret!=TPCERROR_OK) {tacFree(&tac); return(ret);}
542 d2->sampleNr=n;
543 d2->tacNr=tac.tacNr;
544
545 /* Copy the contents */
546 ret=tacCopyHdr(&tac, d2); if(ret!=TPCERROR_OK) {tacFree(&tac); return(ret);}
547 for(int j=0, ret=0; j<tac.tacNr && ret==0; j++)
548 ret=tacCopyTacchdr(&tac.c[j], &d2->c[j]);
549 if(ret!=TPCERROR_OK) {tacFree(&tac); return(ret);}
550 d2->isframe=tac.isframe;
551 d2->weighting=tac.weighting;
552 for(i=i1, n=0; i<=i2 && n<d2->sampleNr; i++, n++) {
553 d2->x[n]=tac.x[i]; d2->x1[n]=tac.x1[i]; d2->x2[n]=tac.x2[i];
554 d2->w[n]=tac.w[i];
555 for(int j=0; j<tac.tacNr; j++) d2->c[j].y[n]=tac.c[j].y[i];
556 }
557 tacFree(&tac);
558 return TPCERROR_OK;
559}

◆ tacExtractSamples()

int tacExtractSamples ( TAC * d1,
TAC * d2,
int si,
int ei )
extern

Extract the specified sample range from TAC structure.

See also
tacExtractRange, tacDeleteSample, tacDeleteMissingSamples, tacInit, tacFree
Author
Vesa Oikonen
Returns
Returns TPCERROR status (0 if ok).
Parameters
d1Pointer to the source TAC structure. Data must be sorted by ascending x.
d2Pointer to the target TAC structure; any previous contents are deleted.
siIndex of first sample to extract.
eiIndex of last sample to extract.

Definition at line 568 of file tacx.c.

577 {
578 if(d1==NULL || d2==NULL) return TPCERROR_FAIL;
579 if(d1->sampleNr<1) return TPCERROR_NO_DATA;
580 if(si<0 || ei<si || si>d1->sampleNr-1) return TPCERROR_INVALID_VALUE;
581 if(ei>d1->sampleNr-1) ei=d1->sampleNr-1;
582
583 /* Remove any old contents in target struct */
584 tacFree(d2);
585
586 /* If the whole TAC is inside required range, then just copy it */
587 if(si==0 && ei==d1->sampleNr-1) return(tacDuplicate(d1, d2));
588
589 /* Count how many samples are inside the required range */
590 int n=1+ei-si; if(n==0) return TPCERROR_NO_DATA;
591
592 /* Allocate memory for the data to be extracted */
593 int ret=tacAllocate(d2, n, d1->tacNr); if(ret!=TPCERROR_OK) return(ret);
594 d2->sampleNr=n;
595 d2->tacNr=d1->tacNr;
596
597 /* Copy the contents */
598 ret=tacCopyHdr(d1, d2); if(ret!=TPCERROR_OK) return(ret);
599 for(int j=0, ret=0; j<d1->tacNr && ret==0; j++) ret=tacCopyTacchdr(&d1->c[j], &d2->c[j]);
600 if(ret!=TPCERROR_OK) return(ret);
601 d2->isframe=d1->isframe;
602 d2->weighting=d1->weighting;
603 for(int i=si, n=0; i<=ei && n<d2->sampleNr; i++, n++) {
604 d2->x[n]=d1->x[i]; d2->x1[n]=d1->x1[i]; d2->x2[n]=d1->x2[i];
605 d2->w[n]=d1->w[i];
606 for(int j=0; j<d1->tacNr; j++) d2->c[j].y[n]=d1->c[j].y[i];
607 }
608
609 return TPCERROR_OK;
610}

◆ tacFirstSelected()

int tacFirstSelected ( TAC * d)
extern

Get the index of first selected TAC (sw!=0) in TAC structure.

Returns
the index of first selected TACs, or <0 if not found.
See also
tacSelectedTACs, tacSelectTACs, tacSelectBestReference
Parameters
dPointer to TAC data.

Definition at line 122 of file tacselect.c.

125 {
126 if(d==NULL || d->tacNr<1) return(-1);
127 for(int i=0; i<d->tacNr; i++) if(d->c[i].sw!=0) return(i);
128 return(-1);
129}

◆ tacFixNaNs()

int tacFixNaNs ( TAC * tac)
extern

Fix missing y values in TAC structure by interpolation. X values cannot be fixed. Extrapolation of the last missing values is not possible, but beginning can be estimated assuming first point (0,0).

See also
tacXNaNs, tacYNaNs, tacNotNaNs, tacDeleteMissingSamples
Returns
Returns 0 if missing values could be filled with reasonable values.
Parameters
tacPointer to TAC structure.

Definition at line 121 of file tacnan.c.

124 {
125 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1) return(1);
126 if(tacXNaNs(tac)>0) return(2);
127
128 int ri, fi, fj;
129 double x1, x2, y1, y2, x, y;
130 /* If NaNs with negative sample times, then set value to zero */
131 for(fi=0; fi<tac->sampleNr; fi++) {
132 if(tac->isframe) x=0.5*(tac->x1[fi]+tac->x2[fi]); else x=tac->x[fi];
133 if(x>0.0) continue;
134 for(ri=0; ri<tac->tacNr; ri++)
135 if(!isfinite(tac->c[ri].y[fi])) tac->c[ri].y[fi]=0.0;
136 }
137 /* Go through the data, finding previous and next good value */
138 for(ri=0; ri<tac->tacNr; ri++) if(tacYNaNs(tac, ri)>0) {
139 x1=x2=y1=y2=nan("");
140 for(fi=0; fi<tac->sampleNr; fi++) {
141 if(tac->isframe) x=0.5*(tac->x1[fi]+tac->x2[fi]); else x=tac->x[fi];
142 /* Save previous good point */
143 if(isfinite(tac->c[ri].y[fi])) {y1=tac->c[ri].y[fi]; x1=x; continue;}
144 /* We have missing value if we are here */
145 /* Search for the next good point after this NaN */
146 x2=y2=nan("");
147 for(fj=fi+1; fj<tac->sampleNr; fj++) {
148 if(!isfinite(tac->c[ri].y[fj])) continue;
149 if(tac->isframe) x2=0.5*(tac->x1[fj]+tac->x2[fj]); else x2=tac->x[fj];
150 y2=tac->c[ri].y[fj];
151 break;
152 }
153 /* If no good points after current point, then that is bad */
154 if(!isfinite(x2)) return(3);
155 /* If the point before is not available, then use (0,0) */
156 if(!isfinite(x1)) x1=y1=0.0;
157 /* Now, interpolate value for current point */
158 if(x2==x1) y=0.5*(y1+y2); else y=y2-(x2-x)*(y2-y1)/(x2-x1);
159 tac->c[ri].y[fi]=y;
160 } // next sample
161 } // next TAC
162
163 return(0);
164}
int tacYNaNs(TAC *tac, const int i)
Definition tacnan.c:47
int tacXNaNs(TAC *tac)
Definition tacnan.c:23

◆ tacFormatDetermine()

int tacFormatDetermine ( const char * fname,
TPCSTATUS * status )
extern

Determine the format of TAC file.

Note
Not all formats are identified, and identification does not mean that reading the format would be supported.
Returns
the format number, or TAC_FORMAT_UNKNOWN if not identified or in case of an error.
Author
Vesa Oikonen
See also
tacDefaultExtension, tacFormatIdentify, tacFormatWriteSupported
Parameters
fnamePointer to the file name; this string is not modified.
statusPointer to status data; enter NULL if not needed

Definition at line 161 of file tacio.c.

166 {
167 int verbose=0; if(status!=NULL) verbose=status->verbose;
168
169 if(fname==NULL || strlen(fname)<1) {
170 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
171 return TAC_FORMAT_UNKNOWN;
172 }
173 if(verbose>1) {printf("%s(%s)\n", __func__, fname); fflush(stdout);}
174 int format=TAC_FORMAT_UNKNOWN;
175
176 /* Open file; note that 'b' is required for fgetpos() and fsetpos() to work correctly */
177 FILE *fp;
178 fp=fopen(fname, "rb");
179 if(fp==NULL) {
180 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
181 return format;
182 }
183
184 /* Binary data? */
185 int ret;
186 size_t fsize=asciiFileSize(fp, &ret);
187 if(verbose>3) {printf(" fsize := %zu\n", fsize); fflush(stdout);}
188 if(fsize<1) {
189 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
190 fclose(fp); return format;
191 }
192 if(ret==1) {
193 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
194 fclose(fp); return TAC_FORMAT_BINARY;
195 }
196
197 /* Read file to a string */
198 char *data;
199 data=asciiFileRead(fp, NULL, fsize+1); rewind(fp);
200 if(data==NULL) {
201 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
202 fclose(fp); return format;
203 }
204 /* Check if one of Inveon formats */
205 if(strncasecmp(data, "#Subject ID,Subject Weight,Subject Sex,Unique Series ID,Series Date,Series Description", 20)==0 ||
206 strncasecmp(data, "#Subject ID;Subject Weight;Subject Sex;Unique Series ID;Series Date;Series Description", 20)==0) {
207 format=TAC_FORMAT_INVEON;
208 }
209
210 /* Read the first non-comment line */
211 int i=0, j;
212 char *cptr, *line=NULL;
213 cptr=data;
214 while((line=strTokenDup(cptr, "\n\r", &j))!=NULL) {
215 if(!asciiCommentLine(line, NULL) && strlen(line)>1) break;
216 free(line); cptr+=j; i++;
217 }
218 free(data);
219 if(line==NULL) {
220 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
221 fclose(fp); return format;
222 }
223
224 /* Check for identification strings */
225 if(verbose>1) {printf(" checking for magic number\n"); fflush(stdout);}
226 if(strncasecmp(line, "DFT", 3)==0) {
227 format=TAC_FORMAT_DFT;
228 } else if(strncasecmp(line, "cpt", 3)==0) {
229 format=TAC_FORMAT_NCI;
230 } else if(strcmp(line, "directory,file name,num,slice,mean,sd,cov,max,min,pixel,total,group")==0) {
231 format=TAC_FORMAT_QVIEW;
232 } else if(strncmp(line, "PatientName,", 12)==0) {
233 format=TAC_FORMAT_4DM;
234 } else if(strstr(line, " - Time")!=NULL && strstr(line, "(upper bound)")!=NULL &&
235 strstr(line, "(lower bound)")!=NULL && strstr(line, "(standard deviation)")!=NULL) {
236 format=TAC_FORMAT_INVEON;
237 }
238 free(line);
239 if(format!=TAC_FORMAT_UNKNOWN) {
240 if(verbose>0) {printf(" identified as %s file\n", tacFormattxt(format)); fflush(stdout);}
241 fclose(fp); return format;
242 }
243
244 /* Identify certain file name extensions */
245 if(verbose>1) {printf(" checking file name extension\n"); fflush(stdout);}
246 cptr=strrchr(fname, '.'); if(cptr!=NULL) cptr++;
247 if(verbose>1 && cptr!=NULL) printf(" extension := %s\n", cptr);
248 if(strcasecmp(cptr, "IDWC")==0 || strcasecmp(cptr, "IDW")==0) {
249 format=TAC_FORMAT_IDWC;
250 } else if(strcasecmp(cptr, "IF")==0) {
251 format=TAC_FORMAT_IF;
252 } else if(strcasecmp(cptr, "XML")==0) {
253 format=TAC_FORMAT_XML;
254 } else if(strcasecmp(cptr, "SIF")==0) {
255 format=TAC_FORMAT_SIF;
256 } else if(strcasecmp(cptr, "LIS")==0) {
258 } else if(strcasecmp(cptr, "ALG")==0) {
260 }
261 if(format!=TAC_FORMAT_UNKNOWN) {
262 if(verbose>0) {printf(" identified as %s file\n", tacFormattxt(format)); fflush(stdout);}
263 fclose(fp); return format;
264 }
265
266#if(0)
267 /* Try to read as CSV (or TSV) file */
268 int ret;
269 FILE *fp;
270 if(fp==NULL) {
271 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
273 }
274 CSV csv; csvInit(&csv);
275 ret=csvRead(&csv, fp, status);
276
277#endif
278
279
280 fclose(fp);
281 if(verbose>0) {printf(" format not identified\n"); fflush(stdout);}
282 return format;
283}
void csvInit(CSV *csv)
Definition csv.c:22
int csvRead(CSV *csv, FILE *fp, TPCSTATUS *status)
Definition csvio.c:124
char * asciiFileRead(FILE *fp, char *data, size_t maxlen)
int asciiCommentLine(const char *line, int *cont)
size_t asciiFileSize(FILE *fp, int *nonprintable)
char * strTokenDup(const char *s1, const char *s2, int *next)
Definition stringext.c:413
Definition tpccsv.h:36
char * tacFormattxt(tacformat c)
Definition tacio.c:98
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TPCERROR_CANNOT_OPEN
Cannot open file.

◆ tacFormatIdentify()

int tacFormatIdentify ( const char * s)
extern

Identify the string representation of the TAC file format.

Returns
enum tacformat, or 0 (enum TAC_FORMAT_UNKNOWN) if not identified.
Author
Vesa Oikonen
See also
tpcformat, tacFormattxt, tacDefaultExtension
Parameters
sTAC format as a string.

Definition at line 113 of file tacio.c.

116 {
117 if(s==NULL || strlen(s)<1) return TAC_FORMAT_UNKNOWN;
118 /* Try if string can be found directly in the table */
119 for(int i=0; i<TAC_FORMAT_LAST; i++) {
120 if(strcasecmp(tac_format[i], s)==0) return i;
121 }
122 /* Format string is not following TPC standard, lets try something else */
123 if( strcasecmp(s, "dat")==0) return TAC_FORMAT_TSV_UK;
124 else if(strcasecmp(s, "txt")==0) return TAC_FORMAT_TSV_UK;
125 else if(strcasecmp(s, "tac")==0) return TAC_FORMAT_PMOD;
126 else if(strcasecmp(s, "bld")==0) return TAC_FORMAT_PMOD;
127 else if(strcasecmp(s, "htm")==0) return TAC_FORMAT_HTML;
128 else if(strcasecmp(s, "csv")==0) return TAC_FORMAT_CSV_UK;
129 else if(strcasecmp(s, "tsv")==0) return TAC_FORMAT_TSV_UK;
130 else if(strcasecmp(s, "lis")==0) return TAC_FORMAT_ABSS_SCANDITRONICS;
131 else if(strcasecmp(s, "alg")==0) return TAC_FORMAT_ABSS_ALLOGG_OLD;
132
133 return TAC_FORMAT_UNKNOWN;
134}

◆ tacFormattxt()

char * tacFormattxt ( tacformat c)
extern

Return pointer to TAC file format description with the format code.

Returns
pointer to the TAC file format string.
See also
tpcformat, tacFormatIdentify, tacDefaultExtension
Author
Vesa Oikonen
Parameters
cTAC format code.

Definition at line 98 of file tacio.c.

101 {
102 if(c<TAC_FORMAT_UNKNOWN || c>=TAC_FORMAT_LAST) return NULL;
103 return (char*)tac_format[c];
104}

Referenced by tacFormatDetermine(), tacRead(), and tacWrite().

◆ tacFormatWriteSupported()

int tacFormatWriteSupported ( tacformat format)
extern

Check whether writing of specified TAC format is supported.

Returns
1 if supported, 0 if not.
See also
tacWrite, tacFormatDetermine, tacRead
Parameters
formatFile format code, for example TAC->format.

Definition at line 291 of file tacio.c.

294 {
295 int ret=0;
296 switch(format) {
298 ret=1;
299 break;
300 case TAC_FORMAT_DFT:
301 ret=1;
302 break;
303 case TAC_FORMAT_PMOD:
304 ret=1;
305 break;
310 ret=1;
311 break;
312 case TAC_FORMAT_SIF:
313 ret=1;
314 break;
315 case TAC_FORMAT_XML:
316 ret=1;
317 break;
318 default:
319 ret=0;
320 }
321 return(ret);
322}

◆ tacFramesToSteps()

int tacFramesToSteps ( TAC * inp,
TAC * out,
TPCSTATUS * status )
extern

Transform TAC with frames into TAC with frames represented with stepwise changing dot-to-dot data.

See also
tacInterpolate, tacToBars, tacAUC, tacDelay, tacInterpolateToEqualLengthFrames, liInterpolate
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
inpPointer to source TAC structure.
Precondition
Data must be sorted by increasing x. There must be no gaps or overlap between frames.
See also
tacSortByTime, tacSetXContiguous
Parameters
outPointer to the initiated target TAC structure; any previous contents are deleted.
statusPointer to status data; enter NULL if not needed.

Definition at line 942 of file tacx.c.

952 {
953 int verbose=0; if(status!=NULL) verbose=status->verbose;
954 if(verbose>0) printf("%s()\n", __func__);
955 if(inp==NULL || out==NULL) {
956 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
957 return TPCERROR_FAIL;
958 }
959 /* Check the function input */
960 if(inp->sampleNr<1 || inp->tacNr<1) {
961 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
962 return TPCERROR_NO_DATA;
963 }
964
965 /* Check that input does not have any missing values */
966 if(tacNaNs(inp)>0) {
967 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
969 }
970
971 /* Check that there are no gaps or overlap between frames */
972 {
973 //printf(" checking that there are no gaps or overlap\n"); fflush(stdout);
974 int ret=tacIsXContiguous(inp);
975 statusSet(status, __func__, __FILE__, __LINE__, ret);
976 if(ret!=TPCERROR_OK) return(ret);
977 }
978
979 /* First, duplicate the TAC data */
980 //printf(" copying data\n"); fflush(stdout);
981 if(tacDuplicate(inp, out)!=TPCERROR_OK) {
982 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
983 return TPCERROR_FAIL;
984 }
985
986 /* If frame start and end times are NOT present, then consider that work is done */
987 if(inp->isframe==0) return(TPCERROR_OK);
988
989 /* Add room for more frames */
990 //printf(" allocating memory for output\n"); fflush(stdout);
991 if(tacAllocateMoreSamples(out, 2+2*out->sampleNr)!=0) {
992 tacFree(out);
993 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
995 }
996
997 /* Make separate 'samples' for each frame start and end time */
998 out->isframe=0;
999 out->sampleNr=0;
1000 /* Add zero sample at zero time if data starts later */
1001 if(inp->x1[0]>0.01*(inp->x2[0]-inp->x1[0])) {
1002 if(verbose>10) printf(" add zero sample\n");
1003 out->x[0]=0.0;
1004 for(int ri=0; ri<out->tacNr; ri++) out->c[ri].y[0]=0.0;
1005 out->sampleNr++;
1006 }
1007 /* Add zero sample at the start of the first frame */
1008 if(verbose>10) printf(" add first frame zero sample\n");
1009 out->x[out->sampleNr]=inp->x1[0];
1010 for(int ri=0; ri<out->tacNr; ri++) out->c[ri].y[out->sampleNr]=0.0;
1011 out->sampleNr++;
1012
1013 /* Add frame start and end times */
1014 for(int fi=0; fi<inp->sampleNr; fi++) {
1015 if(verbose>10) printf(" frame %d: %g - %g\n", 1+fi, inp->x1[fi], inp->x2[fi]);
1016 /* add start sample, if any of y values differs from previous one */
1017 out->x[out->sampleNr]=out->x[out->sampleNr-1];
1018// if(fi==0) out->x[out->sampleNr]=inp->x1[fi];
1019// else out->x[out->sampleNr]=out->x[out->sampleNr-1];
1020 int dn=0;
1021 for(int ri=0; ri<out->tacNr; ri++) {
1022 out->c[ri].y[out->sampleNr]=inp->c[ri].y[fi];
1023 if(out->c[ri].y[out->sampleNr]!=out->c[ri].y[out->sampleNr-1]) dn++;
1024 }
1025 if(dn>0) out->sampleNr++;
1026 /* add end sample */
1027 out->x[out->sampleNr]=inp->x2[fi];
1028 for(int ri=0; ri<out->tacNr; ri++)
1029 out->c[ri].y[out->sampleNr]=inp->c[ri].y[fi];
1030 out->sampleNr++;
1031 }
1032
1033 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
1034 return(TPCERROR_OK);
1035}
int tacNaNs(TAC *tac)
Definition tacnan.c:71
int tacIsXContiguous(TAC *d)
Check that PET TAC frame times are contiguous, without even tiny overlap or gaps in between.
Definition tacx.c:1130
@ TPCERROR_MISSING_DATA
File contains missing values.

Referenced by tacAUC(), and tacDelay().

◆ tacFree()

void tacFree ( TAC * tac)
extern

Free memory allocated for TAC data. All contents are destroyed, including any header data.

Precondition
Before first use initialize the TAC structure with tacInit().
See also
tacFreeExceptHeader, tacInit, tacAllocate, tacDuplicate, tacDeleteTACC
Author
Vesa Oikonen
Parameters
tacPointer to TAC

Definition at line 106 of file tac.c.

109 {
110 if(tac==NULL) return;
111 free(tac->_data);
112 // Free allocated TACC contents; actually not necessary, but lets do it
113 // for consistency */
114 for(int i=0; i<tac->_tacNr; i++) taccFree(&tac->c[i]);
115 // Free the TACC list
116 free(tac->c);
117 // Free the header data
118 iftFree(&tac->h);
119 // then set everything to zero or NULL again
120 tacInit(tac);
121}
void taccFree(TACC *tacc)
Definition tac.c:68

Referenced by bfm1TCM(), bfmSRTM(), freeDelayFitData(), imgReadNifti(), imgWriteNifti(), mfCreateTAC(), mtacFree(), tacAllocate(), tacAllocateMoreSamples(), tacAUC(), tacDelay(), tacDuplicate(), tacExtract(), tacExtractRange(), tacExtractSamples(), tacFramesToSteps(), tacInput2sim(), tacIntegrate(), tacIntegrateFE(), tacInterpolate(), tacInterpolateToEqualLengthFrames(), tacMultipleSamples(), tacRead(), tacRead4DM(), tacReadAllogg(), tacReadCarimasTxt(), tacReadCSV(), tacReadDFT(), tacReadGEMS(), tacReadHRPLUSHC(), tacReadHRRTHC(), tacReadInveonCSV(), tacReadMat(), tacReadModelingData(), tacReadModelingInput(), tacReadOldAllogg(), tacReadPMOD(), tacReadQView(), tacReadReference(), tacReadScanditronics(), tacReadSIF(), tacReadSimple(), tacSetWeights(), tacSetX(), tacSetXContiguous(), and tacToBars().

◆ tacFreeExceptHeader()

void tacFreeExceptHeader ( TAC * tac)
extern

Free memory allocated for TAC data. All contents are destroyed, except the header data in IFT structure.

Precondition
Before first use initialize the TAC structure with tacInit().
See also
tacFree, tacInit, tacAllocate, tacDuplicate
Parameters
tacPointer to TAC

Definition at line 84 of file tac.c.

87 {
88 if(tac==NULL) return;
89 free(tac->_data);
90 // Free allocated TACC contents; actually not necessary, but lets do it
91 // for consistency */
92 for(int i=0; i<tac->_tacNr; i++) taccFree(&tac->c[i]);
93 // Free the TACC list
94 free(tac->c);
95 // then set everything to zero or NULL again
96 tacInit(tac);
97}

◆ tacGetHeaderDecayCorrection()

decaycorrection tacGetHeaderDecayCorrection ( IFT * h)
extern

Get the status of decay correction from TAC struct header.

Returns
enum DECAY_UNKNOWN, DECAY_NOTCORRECTED, or DECAY_CORRECTED.
Author
Vesa Oikonen
See also
tacSetHeaderDecayCorrection, tacGetHeaderIsotope, tacDecayCorrection
Parameters
hPointer to TAC header structure.

Definition at line 548 of file tacift.c.

551 {
552 if(h==NULL) return(DECAY_UNKNOWN);
553
554 /* Find the item index */
555 int i;
556 i=iftFindKey(h, "decay_correction", 0);
557 if(i<0) i=iftFindKey(h, "decay correction", 0);
558 if(i<0) return(DECAY_UNKNOWN);
559
560 /* Check the contents */
561 if(h->item[i].value==NULL || strlen(h->item[i].value)<1)
562 return(DECAY_UNKNOWN);
563 if(strncasecmp(h->item[i].value, "YES", 1)==0) return(DECAY_CORRECTED);
564 if(strncasecmp(h->item[i].value, "NO", 1)==0) return(DECAY_NOTCORRECTED);
565 if(strcasecmp(h->item[i].value, "ON")==0) return(DECAY_CORRECTED);
566 if(strcasecmp(h->item[i].value, "OFF")==0) return(DECAY_NOTCORRECTED);
567 return(DECAY_UNKNOWN);
568}
int iftFindKey(IFT *ift, const char *key, int start_index)
Definition iftfind.c:30
char * value
Definition tpcift.h:37
IFT_ITEM * item
Definition tpcift.h:57
@ DECAY_UNKNOWN
Not known; usually assumed that data is corrected.
Definition tpcisotope.h:79

◆ tacGetHeaderInjectiontime()

int tacGetHeaderInjectiontime ( IFT * h,
char * s,
TPCSTATUS * status )
extern

Get injection time from TAC structure header.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSetHeaderInjectiontime, tacSetHeaderScanstarttime, tacDecayCorrection, tacGetHeaderIsotope
Parameters
hPointer to TAC header structure.
sPointer to preallocated string of length 19+1 (at least); enter NULL if you only want to test if header contains injection time.
statusPointer to status data; enter NULL if not needed.

Definition at line 462 of file tacift.c.

470 {
471 int verbose=0; if(status!=NULL) verbose=status->verbose;
472 if(s!=NULL) *s='\0';
473 if(h==NULL) {
474 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
475 return TPCERROR_NO_DATA;
476 }
477 if(verbose>0) printf("%s()\n", __func__);
478
479 /* Find the item index */
480 int i;
481 i=iftFindKey(h, "injection_time", 0);
482 if(i<0) i=iftFindKey(h, "injection time", 0);
483 if(i<0) i=iftFindKey(h, "injectiontime", 0);
484 if(i<0) {
485 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
486 return TPCERROR_NO_KEY;
487 }
488 /* Check that item has content */
489 size_t len;
490 if(h->item[i].value==NULL) len=0;
491 else len=strlen(h->item[i].value);
492 if(len<1) {
493 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
494 return TPCERROR_NO_VALUE;
495 }
496 if(len>19) {
497 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
499 }
500 /* All fine, then copy it */
501 if(s!=NULL) strcpy(s, h->item[i].value);
502
503 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
504 return(TPCERROR_OK);
505}
@ TPCERROR_NO_VALUE
Value not found.
@ TPCERROR_NO_KEY
Key not found.

◆ tacGetHeaderIsotope()

int tacGetHeaderIsotope ( IFT * h,
char * s,
TPCSTATUS * status )
extern

Get isotope from TAC struct header.

See also
tacGetIsotope, tacDecayCorrection, isotopeIdentify, tacGetHeaderDecayCorrection
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
hPointer to TAC header structure.
sPointer to preallocated string of length MAX_ISOTOPE_LEN+1 (at least); enter NULL if you only want to test if header contains isotope code.
statusPointer to status data; enter NULL if not needed.

Definition at line 290 of file tacift.c.

298 {
299 int verbose=0; if(status!=NULL) verbose=status->verbose;
300 if(s!=NULL) *s='\0';
301 if(h==NULL) {
302 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
303 return TPCERROR_NO_DATA;
304 }
305 if(verbose>0) printf("%s()\n", __func__);
306
307 /* Find the item index */
308 int i;
309 i=iftFindKey(h, "isotope", 0);
310 if(i<0) {
311 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
312 return TPCERROR_NO_KEY;
313 }
314 /* Check that item has content */
315 size_t len;
316 if(h->item[i].value==NULL) len=0;
317 else len=strlen(h->item[i].value);
318 if(len<1) {
319 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
320 return TPCERROR_NO_VALUE;
321 }
322 if(len>MAX_ISOTOPE_LEN) {
323 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
325 }
326 /* All fine, then copy isotope */
327 if(s!=NULL) strlcpy(s, h->item[i].value, MAX_ISOTOPE_LEN);
328
329 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
330 return(TPCERROR_OK);
331}
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
#define MAX_ISOTOPE_LEN
Max string length for PET isotope.
Definition tpcisotope.h:41

Referenced by abssWrite(), tacGetIsotope(), tacReadSIF(), and tacWriteSIF().

◆ tacGetHeaderScanstarttime()

int tacGetHeaderScanstarttime ( IFT * h,
char * s,
TPCSTATUS * status )
extern

Get scan start time from TAC structure header.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSetHeaderScanstarttime, tacGetHeaderInjectiontime, tacDecayCorrection, tacGetHeaderIsotope
Parameters
hPointer to TAC header structure.
sPointer to preallocated string of length 19+1 (at least); enter NULL if you only want to test if header contains scan start time.
statusPointer to status data; enter NULL if not needed.

Definition at line 372 of file tacift.c.

380 {
381 int verbose=0; if(status!=NULL) verbose=status->verbose;
382 if(s!=NULL) *s='\0';
383 if(h==NULL) {
384 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
385 return TPCERROR_NO_DATA;
386 }
387 if(verbose>0) printf("%s()\n", __func__);
388
389 /* Find the item index */
390 int i;
391 i=iftFindKey(h, "scan_start_time", 0);
392 if(i<0) i=iftFindKey(h, "scan start time", 0);
393 if(i<0) i=iftFindKey(h, "scan_start", 0);
394 if(i<0) i=iftFindKey(h, "scan start", 0);
395 if(i<0) i=iftFindKey(h, "scantime", 0);
396 if(i<0) {
397 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
398 return TPCERROR_NO_KEY;
399 }
400 /* Check that item has content */
401 size_t len;
402 if(h->item[i].value==NULL) len=0;
403 else len=strlen(h->item[i].value);
404 if(len<1) {
405 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
406 return TPCERROR_NO_VALUE;
407 }
408 if(len>19) {
409 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
411 }
412 /* All fine, then copy it */
413 if(s!=NULL) strcpy(s, h->item[i].value);
414
415 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
416 return(TPCERROR_OK);
417}

Referenced by abssWrite(), imgFromSIF(), tacReadSIF(), and tacWriteSIF().

◆ tacGetHeaderStudynr()

int tacGetHeaderStudynr ( IFT * h,
char * s,
TPCSTATUS * status )
extern

Get study number from TAC struct header.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSetHeaderStudynr, parIsStudyNr
Parameters
hPointer to TAC header struct
sPointer to preallocated string of length MAX_STUDYNR_LEN+1 (at least); enter NULL if you only want to test whether header contains studynr
statusPointer to status data; enter NULL if not needed

Definition at line 26 of file tacift.c.

34 {
35 int verbose=0; if(status!=NULL) verbose=status->verbose;
36 if(s!=NULL) *s='\0';
37 if(h==NULL) {
38 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
39 return TPCERROR_NO_DATA;
40 }
41 if(verbose>0) printf("%s()\n", __func__);
42
43 /* Find the item index */
44 int i;
45 i=iftFindKey(h, "studynr", 0);
46 if(i<0) i=iftFindKey(h, "study_number", 0);
47 if(i<0) i=iftFindKey(h, "study number", 0);
48 if(i<0) {
49 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
50 return TPCERROR_NO_KEY;
51 }
52 /* Check that item has content */
53 size_t len;
54 if(h->item[i].value==NULL) len=0;
55 else len=strlen(h->item[i].value);
56 if(len<1) {
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
58 return TPCERROR_NO_VALUE;
59 }
60 if(len>MAX_STUDYNR_LEN) {
61 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
63 }
64 /* All fine, then copy studynr */
65 if(s!=NULL) strlcpy(s, h->item[i].value, MAX_STUDYNR_LEN);
66
67 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
68 return(TPCERROR_OK);
69}
#define MAX_STUDYNR_LEN
Define max study number length.

Referenced by abssWrite(), imgFromSIF(), tacRead(), tacReadSIF(), tacWriteCSV(), tacWriteDFT(), and tacWriteSIF().

◆ tacGetHeaderTimeunit()

int tacGetHeaderTimeunit ( TAC * tac,
TPCSTATUS * status )
extern

Get time (x) unit from TAC struct header and write to main TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to TAC struct
statusPointer to status data; enter NULL if not needed

Definition at line 234 of file tacift.c.

239 {
240 int verbose=0; if(status!=NULL) verbose=status->verbose;
241 if(tac==NULL) {
242 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
243 return TPCERROR_FAIL;
244 }
245 if(verbose>0) printf("%s()\n", __func__);
246 tac->tunit=UNIT_UNKNOWN;
247
248 /* Find the item index */
249 int i;
250 i=iftFindKey(&tac->h, "timeunit", 0);
251 if(i<0) i=iftFindKey(&tac->h, "time_unit", 0);
252 if(i<0) i=iftFindKey(&tac->h, "time unit", 0);
253 if(i<0) i=iftFindKey(&tac->h, "time units", 0);
254 if(i<0) {
255 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
256 return TPCERROR_NO_KEY;
257 }
258 /* Check that item has content */
259 size_t len;
260 if(tac->h.item[i].value==NULL) len=0;
261 else len=strlen(tac->h.item[i].value);
262 if(len<1) {
263 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
264 return TPCERROR_NO_VALUE;
265 }
266
267 /* Identify unit string */
268 tac->tunit=unitIdentify(tac->h.item[i].value);
269
270 /* Delete unit strings from header */
272
273 /* If unit was unknown, then return error */
274 if(tac->tunit==UNIT_UNKNOWN) {
275 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
277 }
278 /* Otherwise ok */
279 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
280 return(TPCERROR_OK);
281}
int tacSetHeaderTimeunit(IFT *h, int u)
Definition tacift.c:201
int unitIdentify(const char *s)
Definition units.c:162

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

◆ tacGetHeaderUnit()

int tacGetHeaderUnit ( TAC * tac,
TPCSTATUS * status )
extern

Get concentration (y) unit from TAC struct header and write to main TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to TAC struct
statusPointer to status data; enter NULL if not needed

Definition at line 145 of file tacift.c.

150 {
151 int verbose=0; if(status!=NULL) verbose=status->verbose;
152 if(tac==NULL) {
153 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
154 return TPCERROR_FAIL;
155 }
156 if(verbose>0) printf("%s()\n", __func__);
157 tac->cunit=UNIT_UNKNOWN;
158
159 /* Find the item index */
160 int i;
161 i=iftFindKey(&tac->h, "unit", 0);
162 if(i<0) i=iftFindKey(&tac->h, "calibration_unit", 0);
163 if(i<0) i=iftFindKey(&tac->h, "activity_units", 0);
164 if(i<0) i=iftFindKey(&tac->h, "activity units", 0);
165 if(i<0) {
166 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
167 return TPCERROR_NO_KEY;
168 }
169 /* Check that item has content */
170 size_t len;
171 if(tac->h.item[i].value==NULL) len=0;
172 else len=strlen(tac->h.item[i].value);
173 if(len<1) {
174 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_VALUE);
175 return TPCERROR_NO_VALUE;
176 }
177
178 /* Identify unit string */
179 tac->cunit=unitIdentify(tac->h.item[i].value);
180
181 /* Delete unit strings from header */
183
184 /* If unit was unknown, then return error */
185 if(tac->cunit==UNIT_UNKNOWN) {
186 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
188 }
189 /* Otherwise ok */
190 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
191 return(TPCERROR_OK);
192}
int tacSetHeaderUnit(IFT *h, int u)
Definition tacift.c:112

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

◆ tacGetIsotope()

int tacGetIsotope ( TAC * tac)
extern

Read isotope code from TAC header.

See also
tacGetHeaderIsotope, tacSetIsotope, isotopeIdentify, tacDecayCorrection
Author
Vesa Oikonen
Returns
Returns isotope code, or ISOTOPE_UNKNOWN, if not found.
Parameters
tacPointer to source TAC structure.

Definition at line 25 of file tacdc.c.

28 {
29 if(tac==NULL) return(ISOTOPE_UNKNOWN);
30 char buf[MAX_ISOTOPE_LEN+1];
31 if(tacGetHeaderIsotope(&tac->h, buf, NULL)!=TPCERROR_OK) return(ISOTOPE_UNKNOWN);
32 return(isotopeIdentify(buf));
33}
int isotopeIdentify(const char *isotope)
Definition isotope.c:145
int tacGetHeaderIsotope(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:290

Referenced by imgFromSIF(), tacReadModelingData(), tacReadReference(), and tacSetWeights().

◆ tacGetSampleInterval()

int tacGetSampleInterval ( TAC * d,
double ilimit,
double * minfdur,
double * maxfdur )
extern

Get the shortest and longest sampling intervals or frame lengths in TAC structure.

Data is not modified. Data must be sorted by increasing x.

See also
tacXRange, tacIsX, tacCheckX1X2X, tacInterpolateToEqualLengthFrames
Author
Vesa Oikonen
Returns
Returns <>0 in case of failure.
Parameters
dPointer to TAC structure.
ilimitInterval limit: smaller sampling intervals of frame lengths are not accepted; use this to prevent 0 interval in case of step functions or zero length frames; enter NaN if not applied.
minfdurPointer to variable for minimum interval (NULL if not needed).
maxfdurPointer to variable for maximum interval (NULL if not needed).

Definition at line 832 of file tacx.c.

843 {
844 if(minfdur!=NULL) *minfdur=nan("");
845 if(maxfdur!=NULL) *maxfdur=nan("");
846 /* Check the data */
847 if(d==NULL || d->sampleNr<1) return(1);
848 double mi=nan(""), ma=nan("");
849 if(d->isframe) {
850 for(int i=0; i<d->sampleNr; i++) {
851 double f=d->x2[i]-d->x1[i];
852 if(!isnan(ilimit) && !(f>=ilimit)) continue;
853 if(isnan(mi) || f<mi) mi=f;
854 if(isnan(ma) || f>ma) ma=f;
855 }
856 } else {
857 for(int i=1; i<d->sampleNr; i++) {
858 double f=d->x[i]-d->x[i-1];
859 if(!isnan(ilimit) && !(f>=ilimit)) continue;
860 if(isnan(mi) || f<mi) mi=f;
861 if(isnan(ma) || f>ma) ma=f;
862 }
863 if(isnan(mi) || isnan(ma)) { // as the last resort use the time of first sample
864 double f=d->x[0];
865 if(f>0.0 && !isnan(ilimit) && f>=ilimit) {
866 if(isnan(mi)) mi=f;
867 if(isnan(ma)) ma=f;
868 }
869 }
870 }
871 if(minfdur!=NULL) *minfdur=mi;
872 if(maxfdur!=NULL) *maxfdur=ma;
873
874 if(minfdur!=NULL && isnan(mi)) return(2);
875 if(maxfdur!=NULL && isnan(ma)) return(2);
876
877 return(0);
878}

Referenced by tacInterpolateToEqualLengthFrames().

◆ tacIndividualNames()

int tacIndividualNames ( TAC * tac)
extern

Verifies that TAC structure contains a name for each TAC, and no other TAC has the same name.

Returns
1 if individual names exist, 0 if not.
Author
Vesa Oikonen
See also
tacSelectTACs, tacSelectBestReference, roinameMatch, tacEnsureNames
Parameters
tacPointer to TAC structure.

Definition at line 24 of file tacname.c.

27 {
28 if(tac==NULL || tac->tacNr<1) return(0);
29 int ri, rj;
30 /* First check that names do exist */
31 for(ri=0; ri<tac->tacNr; ri++) {
32 if(!roinameExists(tac->c[ri].name)) return(0);
33 }
34 /* If just one TAC, then its name is individual */
35 if(tac->tacNr==1) return(1);
36 /* Otherwise compare each of the names */
37 for(ri=0; ri<tac->tacNr-1; ri++)
38 for(rj=ri+1; rj<tac->tacNr; rj++)
39 if(strcasecmp(tac->c[ri].name, tac->c[rj].name)==0) return(0);
40 return(1);
41}

◆ tacInit()

void tacInit ( TAC * tac)
extern

Initiate the TAC structure before any use.

See also
tacFree, tacFreeExceptHeader, tacAllocate, tacDuplicate
Author
Vesa Oikonen
Parameters
tacPointer to TAC

Definition at line 24 of file tac.c.

27 {
28 if(tac==NULL) return;
29 tac->sampleNr=tac->_sampleNr=0;
30 tac->tacNr=tac->_tacNr=0;
32 tac->isframe=0;
33 tac->x=tac->x1=tac->x2=NULL;
34 tac->cunit=tac->tunit=UNIT_UNKNOWN;
35 tac->w=NULL;
37 tac->c=NULL;
38 tac->_data=NULL;
39 iftInit(&tac->h);
40}
void iftInit(IFT *ift)
Definition ift.c:21

Referenced by bfm1TCM(), imgReadNifti(), imgWriteNifti(), initDelayFitData(), mtacAllocate(), mtacAllocateMore(), tacAllocateMoreSamples(), tacAUC(), tacDelay(), tacExtractRange(), tacFree(), tacFreeExceptHeader(), tacInput2sim(), tacMultipleSamples(), tacReadModelingData(), tacReadModelingInput(), tacReadReference(), tacSetWeights(), tacSetX(), and tacSetXContiguous().

◆ tacIsSize()

int tacIsSize ( TAC * d)
extern

Check if any of TAC sets has VOI size (volume).

Returns
1 if size(s) exist, and 0 if not (or in case of an error).
See also
tacIsWeighted, tacIsX
Parameters
dPointer to TAC structure.

Definition at line 335 of file tac.c.

338 {
339 if(d==NULL || d->tacNr<1) return(0);
340 for(int ri=0; ri<d->tacNr; ri++) {
341 if(isnan(d->c[ri].size)) continue;
342 if(d->c[ri].size<=0.0) continue;
343 return(1);
344 }
345 return(0);
346}

Referenced by tacWriteCSV().

◆ tacIsWeighted()

int tacIsWeighted ( TAC * tac)
extern

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}

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

◆ tacIsX()

int tacIsX ( TAC * d)
extern

Verify if TAC structure contains reasonable x values (times).

Data is not modified. Data does not need to be sorted. Data can contain NaNs, as long as some x values are available. Note that x values are considered not to exist even when there is only one sample with x=0.

See also
tacXRange, tacSetX, tacXCopy, tacCheckX1X2X, tacXNaNs, tacFixNaNs, tacMultipleSamples, tacVerifyTimeOrder, tacIsWeighted, tacIsXContiguous
Author
Vesa Oikonen
Returns
Returns 1 if x values are present, 0 if not (all zeroes or missing).
Parameters
dPointer to TAC structure; not modified.

Definition at line 226 of file tacx.c.

229 {
230 if(d==NULL || d->sampleNr<1) return(0);
231 double a, b;
232 if(tacXRange(d, &a, &b)) return(0);
233 if(fabs(a)<1.0E-30 && fabs(b)<1.0E-30) return(0);
234 if(fabs(a)<1.0E-30 && fabs(a-b)<1.0E-30) return(0);
235 return(1);
236}

Referenced by tacInterpolateToEqualLengthFrames(), tacMultipleSamples(), tacReadReference(), tacSetWeights(), and tacSetX().

◆ tacIsXContiguous()

int tacIsXContiguous ( TAC * d)
extern

Check that PET TAC frame times are contiguous, without even tiny overlap or gaps in between.

See also
tacSetXContiguous, tacIsX, tacXRange, tacVerifyTimeOrder, tacSortByTime, tacXCopy, tacMultipleSamples
Returns
If no overlap or gaps, TPCERROR_OK (0) is returned.
Author
Vesa Oikonen
Parameters
dPointer to TAC data which is sorted by increasing sample time.

Definition at line 1130 of file tacx.c.

1133 {
1134 if(d==NULL) return TPCERROR_FAIL;
1135 if(tacXNaNs(d)>0) return(TPCERROR_INVALID_X);
1136
1137 /* If no frame start and end times, then just check the order */
1138 if(d->isframe==0) {
1139 if(tacVerifyTimeOrder(d, NULL)) return(TPCERROR_INVALID_XRANGE);
1140 return TPCERROR_OK;
1141 }
1142
1143 /* Check each frame */
1144 for(int fi=0; fi<d->sampleNr-1; fi++) {
1145 double e=d->x2[fi]-d->x1[fi+1];
1146 if(e<0.0) return(TPCERROR_LARGE_GAP);
1147 if(e>0.0) return(TPCERROR_OVERLAPPING_DATA);
1148 }
1149
1150 return(TPCERROR_OK);
1151}
@ TPCERROR_LARGE_GAP
Large gap in data.

Referenced by tacFramesToSteps(), and tacSetXContiguous().

◆ tacMinX()

int tacMinX ( TAC * d)
extern

Get the minimum x value in TAC structure.

Data does not need to be sorted, and it can contain missing x and y values (NaNs).

See also
tacSampleXRange, tacIsX, tacAddZeroSample
Returns
Returns the index of sample with min x, or -1 in case of an error.
Parameters
dPointer to the TAC structure; not modified.

Definition at line 201 of file tacx.c.

204 {
205 if(d==NULL || !(d->sampleNr>0)) return(-1);
206 int imin=-1; double xmin=nan("");
207 for(int i=0; i<d->sampleNr; i++) {
208 double t1; if(d->isframe) t1=0.5*(d->x1[i]+d->x2[i]); else t1=d->x[i];
209 if(!isfinite(t1)) continue;
210 if(!isfinite(xmin) || imin<0 || t1<xmin) {xmin=t1; imin=i; continue;}
211 }
212 return(imin);
213}

Referenced by tacMultipleSamples().

◆ tacMoveTACC()

int tacMoveTACC ( TAC * d,
int from,
int to )
extern

Move TACC from one position to another inside TAC structure, moving the positions of other TACCs accordingly.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSwapTACCs, tacDeleteTACC, tacCopyTacc
Parameters
dPointer to TAC data. Main header and tacNr are not changed.
fromTACC index [0.._tacNr-1]
toTACC index [0.._tacNr-1]

Definition at line 250 of file tacorder.c.

257 {
258 int i;
259 TACC tacc;
260 size_t taccSize;
261
262 if(d==NULL || from<0 || to<0) return(TPCERROR_FAIL);
263 if(from>=d->_tacNr || to>=d->_tacNr) return(TPCERROR_FAIL);
264 if(from==to) return(TPCERROR_OK); // nothing to do
265 taccSize=sizeof(TACC);
266 memcpy(&tacc, d->c+from, taccSize);
267 if(from>to) for(i=from; i>to; i--)
268 memcpy(d->c+i, d->c+(i-1), taccSize);
269 else for(i=from; i<to; i++)
270 memcpy(d->c+i, d->c+(i+1), taccSize);
271 memcpy(d->c+i, &tacc, taccSize);
272 return(TPCERROR_OK);
273}

Referenced by tacDeleteTACC().

◆ tacMultipleSamples()

int tacMultipleSamples ( TAC * d1,
const int fixMode,
TAC * d2,
const int verbose )
extern

Check TAC data for multiple samples with the same sample time. Optionally replace the multiple samples with their mean.

Data does no need to be sorted before calling this. Output is not necessarily sorted either.

See also
tacCorrectFrameOverlap, tacCompareTimes, tacSortByTime, tacIsX, tacDeleteSample
Returns
If fixMode is zero, then returns 1 if multiple samples are found, and 0 if not. If fixMode is 1, then returns 0 if successful, and otherwise >0.
Parameters
d1Pointer to the input TAC structure; optionally modified.
fixModeJust inspect for multiple samples (0), or replace those with mean (1).
d2Pointer to the output TAC structure; enter NULL if just inspecting. To replace the contents of input TAC, enter the same pointer here.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 336 of file tacorder.c.

346 {
347 if(verbose>0) {printf("\n%s(%d)\n", __func__, fixMode); fflush(stdout);}
348
349 /* Check data */
350 if(fixMode!=0 && (d1==NULL || d2==NULL || d1->sampleNr<1)) return(2);
351 if(d1==NULL || d1->sampleNr<2 || !tacIsX(d1)) return(0);
352
353 /* Set limit for similarity of sample times; the same sample times can have been saved in
354 files with variable precision. */
355 const double simlim=1.0E-03; if(verbose>1) printf(" limit := %g\n", simlim);
356
357 /* Check if there are any multiple samples */
358 int isMultiple=0;
359 for(int i=0; i<d1->sampleNr-1 && !isMultiple; i++) {
360 double t1; if(d1->isframe) t1=0.5*(d1->x1[i]+d1->x2[i]); else t1=d1->x[i];
361 for(int j=i+1; j<d1->sampleNr; j++) {
362 double t2; if(d1->isframe) t2=0.5*(d1->x1[j]+d1->x2[j]); else t2=d1->x[j];
363 double dt=fabs(t2-t1);
364 if(verbose>4) printf(" |%g - %g| = %g\n", t1, t2, dt);
365 if(dt<simlim) {isMultiple=1; break;}
366 }
367 }
368 if(verbose>1) {printf(" isMultiple := %d\n", isMultiple); fflush(stdout);}
369 if(fixMode==0) return(isMultiple); // done, if fixing not asked for
370
371 /* If there were no multiples, copy the input to output and quit */
372 if(!isMultiple) {
373 TAC itac; tacInit(&itac);
374 if(tacDuplicate(d1, &itac)!=TPCERROR_OK) return(3);
375 if(tacDuplicate(&itac, d2)!=TPCERROR_OK) {tacFree(&itac); return(3);}
376 tacFree(&itac); return(0);
377 }
378
379 /* Ok there are multiples that need to be fixed. */
380 /* We'll start by making a copy of the input data, and removing any existing data in
381 the output; copy is needed, because output structure can be the same as input */
382 TAC itac; tacInit(&itac); if(tacDuplicate(d1, &itac)!=TPCERROR_OK) return(4);
383 tacFree(d2);
384 /* Delete missing samples from the input */
385 tacDeleteMissingSamples(&itac); if(verbose>2) printf(" itac.sampleNr := %d\n", itac.sampleNr);
386 /* Allocate memory for the output data */
387 if(tacAllocate(d2, itac.sampleNr, itac.tacNr)!=TPCERROR_OK) {tacFree(&itac); return(5);}
388 if(tacCopyHdr(&itac, d2)!=TPCERROR_OK) {tacFree(&itac); return(6);}
389 for(int r=0; r<itac.tacNr; r++)
390 if(tacCopyTacchdr(&itac.c[r], &d2->c[r])!=TPCERROR_OK) {tacFree(&itac); return(7);}
392 d2->tacNr=itac.tacNr;
393
394 /* Go through the input data */
395 while(itac.sampleNr>0) {
396 /* Find the smallest sample time */
397 int i=tacMinX(&itac); if(i<0) break;
398 if(verbose>3) printf(" smallest x[%d]=%g\n", i, itac.x[i]);
399 /* Copy values to the first free output sample */
400 for(int r=0; r<itac.tacNr; r++) d2->c[r].y[d2->sampleNr]=0.0;
401 int rn[itac.tacNr]; for(int r=0; r<itac.tacNr; r++) rn[r]=0;
402 for(int r=0; r<itac.tacNr; r++)
403 if(isfinite(itac.c[r].y[i])) {
404 d2->c[r].y[d2->sampleNr]=itac.c[r].y[i];
405 rn[r]++;
406 }
407 d2->x[d2->sampleNr]=itac.x[i]; d2->x1[d2->sampleNr]=itac.x1[i]; d2->x2[d2->sampleNr]=itac.x2[i];
408 double t1; if(itac.isframe) t1=0.5*(itac.x1[i]+itac.x2[i]); else t1=itac.x[i];
409 /* Delete the sample from input */
410 tacDeleteSample(&itac, i);
411 /* Search the input for matching sample times */
412 while(itac.sampleNr>0) {
413 /* Find the smallest sample time left */
414 int i=tacMinX(&itac); if(i<0) break;
415 if(verbose>3) printf(" smallest x[%d]=%g\n", i, itac.x[i]);
416 double t2; if(itac.isframe) t2=0.5*(itac.x1[i]+itac.x2[i]); else t2=itac.x[i];
417 double dt=fabs(t2-t1); if(verbose>4) printf(" |%g - %g| = %g\n", t1, t2, dt);
418 if(!(dt<simlim)) break; // if this is not close enough, then none will be
419 /* Add values to the first free output sample */
420 for(int r=0; r<itac.tacNr; r++)
421 if(isfinite(itac.c[r].y[i])) {
422 d2->c[r].y[d2->sampleNr]+=itac.c[r].y[i];
423 rn[r]++;
424 }
425 /* Delete also this sample from input */
426 tacDeleteSample(&itac, i);
427 }
428 /* Divide values by the summed number of samples */
429 for(int r=0; r<itac.tacNr; r++) d2->c[r].y[d2->sampleNr]/=(double)rn[r];
430 /* Move to next output sample */
431 d2->sampleNr++;
432 }
433 tacFree(&itac);
434
435 /* Check that we got something left */
436 if(d2->sampleNr<1) return(10);
437
438 return(0);
439}
int tacDeleteMissingSamples(TAC *d)
Delete those samples (time frames) from TAC structure, which contain only missing y values,...
Definition tacx.c:450
int tacMinX(TAC *d)
Get the minimum x value in TAC structure.
Definition tacx.c:201
int tacIsX(TAC *d)
Verify if TAC structure contains reasonable x values (times).
Definition tacx.c:226

◆ tacNameSplit()

int tacNameSplit ( const char * rname,
char * name1,
char * name2,
char * name3,
unsigned int max_name_len )
extern

Split TAC name into 1-3 subparts of given max length.

Returns
Returns the number of subparts; note that number is 3 if third subpart is found even if 1st and/or 2nd subparts were not found.
See also
roinameSubpart
Parameters
rnameTAC name to split
name1Pointer to 1st subname (usually anatomical region); NULL if not needed
name2Pointer to 2nd subname (usually hemisphere); NULL if not needed
name3Pointer to 3rd subname (usually image plane); NULL if not needed
max_name_lenMax length of subnames, excluding terminal null

Definition at line 26 of file dftio.c.

37 {
38 /* Initiate subnames */
39 if(name1!=NULL) strcpy(name1, "");
40 if(name2!=NULL) strcpy(name2, "");
41 if(name3!=NULL) strcpy(name3, "");
42
43 /* Check input */
44 if(max_name_len<1) return 0;
45 if(rname==NULL || *rname=='\0') return 0;
46
47 /* Work with a copy of TAC name */
48 char *temp=strdup(rname);
49
50 /* Remove any quotes and trailing and initial spaces */
51 if(strClean(temp)) {free(temp); return 0;}
52 //printf("temp='%s'\n", temp);
53
54 /* Allocate memory for local subnames */
55 int fullLen=(int)strlen(rname);
56 char sname[3][fullLen+1];
57
58 /* Determine the subpart delimiters so that subpart number would be optimal */
59 char space[32];
60 strcpy(space, " \t");
61 int n=strTokenNr(temp, space);
62 if(n<3) {strcat(space, "_"); n=strTokenNr(temp, space);}
63 if(n<3) {strcat(space, "-"); n=strTokenNr(temp, space);}
64 //printf("n=%d space='%s'\n", n, space);
65
66 /* get subparts */
67 char *cptr=temp; int i;
68 n=0; i=0;
69 while(n<3 && *cptr!='\0') {
70 //printf(" cptr='%s' n=%d i=%d\n", cptr, n, i);
71 /* If delimiter */
72 if(strspn(cptr, space)>0) {
73 /* then end this subpart */
74 sname[n][i]='\0';
75 /* and prepare for the next */
76 n++; i=0;
77 cptr++; continue;
78 }
79 sname[n][i]=*cptr;
80 cptr++; i++;
81 }
82 if(n<3) {sname[n][i]='\0'; n++;}
83 for( ; n<3 ;n++) strcpy(sname[n], "");
84
85 for(i=0; i<3; i++) {
86 /* If name was '.' then replace it with empty string */
87 if(strcmp(sname[i], ".")==0) strcpy(sname[i], "");
88 //printf(" -> '%s'\n", sname[i]);
89 }
90
91 /* If subname2 is empty and subname1 is too long, then divide it */
92 if(sname[1][0]=='\0' && strlen(sname[0])>max_name_len)
93 strlcpy(sname[1], &sname[0][max_name_len], fullLen+1);
94 /* If subname3 is empty and subname2 is too long, then divide it */
95 if(sname[2][0]=='\0' && strlen(sname[1])>max_name_len)
96 strlcpy(sname[2], &sname[1][max_name_len], fullLen+1);
97
98 /* Fill the output strings */
99 char *nptr;
100 for(i=n=0; i<3; i++) {
101 //printf(" -> '%s'\n", sname[i]);
102 if(i==0) nptr=name1; else if(i==1) nptr=name2; else nptr=name3;
103 if(strlen(sname[i])>0) n=i+1;
104 if(nptr==NULL) continue;
105 strlcpy(nptr, sname[i], max_name_len+1);
106 }
107
108 free(temp);
109 return n;
110}
int strTokenNr(const char *s1, const char *s2)
Definition stringext.c:25
char * strdup(const char *s)
Definition stringext.c:185
int strClean(char *s)
Definition stringext.c:389

Referenced by tacWriteDFT().

◆ tacNaNs()

int tacNaNs ( TAC * tac)
extern

Check TAC structure for missing sample times and values.

See also
tacXNaNs, tacYNaNs, tacNotNaNs, tacFixNaNs
Returns
Returns the number of missing values that were found.
Parameters
tacPointer to TAC structure.

Definition at line 71 of file tacnan.c.

74 {
75 return(tacXNaNs(tac)+tacYNaNs(tac, -1));
76}

Referenced by tacFramesToSteps(), tacInterpolate(), tacInterpolateInto(), tacReadModelingData(), and tacReadModelingInput().

◆ tacNotNaNs()

int tacNotNaNs ( TAC * tac,
const int i )
extern

Check TAC structure for missing sample times and values.

See also
tacNaNs, tacXNaNs, tacYNaNs, tacFixNaNs
Returns
Returns the number of samples which do not contain missing x or y values.
Parameters
tacPointer to TAC structure.
iIndex of TAC to test; <0 to test all TACs.

Definition at line 84 of file tacnan.c.

89 {
90 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1 || i>=tac->tacNr) return(0);
91
92 int ri, fi, nan_nr=0;
93 for(fi=0; fi<tac->sampleNr; fi++) {
94 /* First, check x value(s) */
95 if(tac->isframe) {
96 if(!isfinite(tac->x1[fi])) {nan_nr++; continue;}
97 if(!isfinite(tac->x2[fi])) {nan_nr++; continue;}
98 } else {
99 if(!isfinite(tac->x[fi])) {nan_nr++; continue;}
100 }
101 /* If ok, then check y value(s) */
102 if(i>=0) {
103 if(!isfinite(tac->c[i].y[fi])) nan_nr++;
104 continue;
105 }
106 for(ri=0; ri<tac->tacNr; ri++)
107 if(!isfinite(tac->c[ri].y[fi])) {nan_nr++; break;}
108 } // next sample
109 return(tac->sampleNr-nan_nr);
110}

◆ tacNthSample()

int tacNthSample ( TAC * tac,
const int sn,
const int i )
extern

Search the Nth sample (1..n) in TAC structure which does not contain missing x or y values. Use tacNotNaNs to get the number of existing samples in TAC.

See also
tacNotNaNs, tacFixNaNs
Returns
Returns the sample index, or <1 if not available.
Parameters
tacPointer to TAC structure.
snNumber (1..n) of sample to search for; 1 to search for the first one, tacNotNaNs(&tac, -1) to search for the last one.
iIndex of TAC to test; <0 to test all TACs

Definition at line 173 of file tacnan.c.

181 {
182 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1 || i>=tac->tacNr) return(-1);
183 if(sn<1 || sn>tac->sampleNr) return(-1);
184
185 int ri, fi, n=0;
186 for(fi=0; fi<tac->sampleNr; fi++) {
187 /* First, check x value(s) */
188 if(tac->isframe) {
189 if(!isfinite(tac->x1[fi]) || !isfinite(tac->x2[fi])) continue;
190 } else {
191 if(!isfinite(tac->x[fi])) continue;
192 }
193 /* If ok, then check y value(s) */
194 if(i>=0) {
195 if(!isfinite(tac->c[i].y[fi])) continue;
196 } else {
197 for(ri=0; ri<tac->tacNr; ri++) if(!isfinite(tac->c[ri].y[fi])) break;
198 if(ri!=tac->tacNr) continue;
199 }
200 n++;
201 if(n==sn) return(fi);
202 } // next sample, if necessary
203 return(-1);
204}

◆ tacRead()

int tacRead ( TAC * d,
const char * fname,
TPCSTATUS * status )
extern

Read TAC file contents into TAC data structure.

This function reads simple data format (time + data columns), DFT format, PMOD format, Hammersmith formats (IDWC and IF), and some CSV formats.

Author
Vesa Oikonen
Returns
code tpcerror, TPCERROR_OK (0) when successful.
See also
tacInit, tacWrite, tacFormatDetermine, csvRead, iftRead
Parameters
dPointer to initiated TAC struct where TAC data will be written; any old content is deleted.
fnamePointer to the filename; this string is not modified.
statusPointer to status data; enter NULL if not needed.

Definition at line 413 of file tacio.c.

420 {
421 int verbose=0; if(status!=NULL) verbose=status->verbose;
422 if(fname==NULL || strlen(fname)<1 || d==NULL) {
423 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
424 return TPCERROR_FAIL;
425 }
426 if(verbose>1) printf("%s(%s)\n", __func__, fname);
427 int format=TAC_FORMAT_UNKNOWN;
428
429 /* Delete any previous data */
430 tacFree(d);
431
432 /* Open the file */
433 FILE *fp;
434 fp=fopen(fname, "r");
435 if(fp==NULL) {
436 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
438 }
439
440 /* Verify that file does not contain binary data */
441 {
442 int n, binpart;
443 n=asciiFileSize(fp, &binpart);
444 if(verbose>4) printf("file_size := %d\n", n);
445 if(n<2 || binpart!=0) {
446 if(verbose>0) {
447 printf("file_size := %d\n", n);
448 printf("binpart := %d\n", binpart);
449 fflush(stdout);
450 }
451 fclose(fp);
452 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
454 }
455 }
456
457 /* Try to read the file as CSV file */
458 int ret;
459 CSV csv; csvInit(&csv);
460 rewind(fp);
461 ret=csvRead(&csv, fp, status);
462 fclose(fp);
463 if(ret!=TPCERROR_OK) {csvFree(&csv); return ret;}
464 if(verbose>20) {
465 printf("\n --- CSV contents ---\n");
466 csvWrite(&csv, 0, stdout, status);
467 fflush(stdout);
468 }
469
470 /* Try to identify file format from a magic number in the start */
471 if(verbose>1) printf("checking for magic number\n");
472 if(strncasecmp(csv.c[0].content, "DFT", 3)==0) {
473 format=TAC_FORMAT_DFT;
474 } else if(strncasecmp(csv.c[0].content, "cpt", 3)==0) {
475 format=TAC_FORMAT_NCI;
476 } else if(csv.nr>8 && strcasecmp(csv.c[0].content, "time")==0 &&
477 strcasecmp(csv.c[1].content, "prompt")==0 &&
478 strcasecmp(csv.c[2].content, "delayed")==0 &&
479 strcasecmp(csv.c[3].content, "p_rate")==0) {
481 } else if(strncasecmp(csv.c[0].content, "Time", 4)==0) {
482 format=TAC_FORMAT_PMOD;
483 } else if(strncasecmp(csv.c[0].content, "Start", 5)==0) {
484 format=TAC_FORMAT_PMOD;
485 } else if(strncasecmp(csv.c[0].content, "<?xml version", 6)==0) {
486 format=TAC_FORMAT_XML;
487 } else if(csv.nr>12 && strcasecmp(csv.c[0].content, "directory")==0 &&
488 strcasecmp(csv.c[1].content, "file name")==0 &&
489 strcasecmp(csv.c[2].content, "num")==0 &&
490 strcasecmp(csv.c[3].content, "slice")==0 &&
491 strcasecmp(csv.c[4].content, "mean")==0 &&
492 strcasecmp(csv.c[5].content, "sd")==0 &&
493 strcasecmp(csv.c[6].content, "cov")==0 &&
494 strcasecmp(csv.c[7].content, "max")==0 &&
495 strcasecmp(csv.c[8].content, "min")==0 &&
496 strcasecmp(csv.c[9].content, "pixel")==0 &&
497 strcasecmp(csv.c[10].content, "total")==0 &&
498 strcasecmp(csv.c[11].content, "group")==0) {
499 format=TAC_FORMAT_QVIEW;
500 } else if(csv.nr>10 && strcasecmp(csv.c[0].content, "PatientName")==0 &&
501 strcasecmp(csv.c[2].content, "Patient MRN")==0 ) {
502 format=TAC_FORMAT_4DM;
503 } else if(csv.nr>5 && strstr(csv.c[0].content, " - Time")!=NULL &&
504 strstr(csv.c[2].content, "(upper bound)")!=NULL &&
505 strstr(csv.c[3].content, "(lower bound)")!=NULL &&
506 strstr(csv.c[4].content, "(standard deviation)")!=NULL) {
507 format=TAC_FORMAT_INVEON;
508 } else if(strcasecmp(csv.c[0].content, "TAC")==0) {
509 if(csv.separator=='\t') format=TAC_FORMAT_TSV_UK;
510 else if(csv.separator==',') format=TAC_FORMAT_CSV_INT;
511 else format=TAC_FORMAT_CSV_UK;
512 // CSV subformat may not be strictly correct yet
513 } else if(csv.nr>4 && strcasecmp(csv.c[0].content, "Singles")==0 &&
514 strcasecmp(csv.c[1].content, "Randoms")==0 &&
515 strcasecmp(csv.c[2].content, "Prompts")==0 &&
516 strncasecmp(csv.c[3].content, "Time(ms)", 4)==0) {
517 format=TAC_FORMAT_HRRT_HC;
518 } else if(csvCell(&csv, 1, 0) && strcasecmp(csvCell(&csv, 1, 0), "Num Voxels")==0 )
519 {
521 }
522
523 /* If not identified, then try certain file name extensions. */
524 /* Extension is not always reliable, therefore magic nr is tried first */
525 if(format==TAC_FORMAT_UNKNOWN) {
526 if(verbose>1) printf("checking file name extension\n");
527 char *cptr, *extension;
528 cptr=filenameGetExtension(fname);
529 if(cptr!=NULL && strlen(cptr)>1) extension=strdup(cptr+1);
530 else extension=strdup("");
531 if(verbose>1) printf("extension := '%s'\n", extension);
532 cptr=extension;
533 if(strcasecmp(cptr, "IDWC")==0 || strcasecmp(cptr, "IDW")==0) {
534 format=TAC_FORMAT_IDWC;
535 } else if(strcasecmp(cptr, "IF")==0) {
536 format=TAC_FORMAT_IF;
537 } else if(strcasecmp(cptr, "XML")==0) {
538 format=TAC_FORMAT_XML;
539 } else if(strcasecmp(cptr, "HTML")==0 || strcasecmp(cptr, "HTM")==0) {
540 format=TAC_FORMAT_HTML;
541 } else if(strcasecmp(cptr, "SIF")==0) {
542 format=TAC_FORMAT_SIF;
543 } else if(strcasecmp(cptr, "HC")==0) {
544 format=TAC_FORMAT_HRRT_HC;
545 } else if(strcasecmp(cptr, "R")==0) {
547 }
548 free(extension);
549 }
550
551 /* If still unknown, read all data as IFT */
552 IFT hdr; iftInit(&hdr);
553 if(format==TAC_FORMAT_UNKNOWN) {
554 if(verbose>2) {printf("reading all data in IFT structure\n"); fflush(stdout);}
555 fp=fopen(fname, "r");
556 if(fp!=NULL) {iftRead(&hdr, fp, 0, 1, status); fclose(fp);}
557 }
558 if(format==TAC_FORMAT_UNKNOWN) {
559 /* Try Allogg ABSS */
560 if(iftSearchValue(&hdr, "//Heading", 0)>=0 &&
561 iftSearchValue(&hdr, "//Data", 0)>=0 &&
562 iftFindPair(&hdr, "System ID", "ABSS09282", 0)>=0)
563 {
565 /* Try Scanditronics and GEMS ABSS */
566 } else if(iftSearchValue(&hdr, "AUX", 0)>=0 && iftSearchValue(&hdr, "1st detector pair", 0)>=0) {
567 if(iftSearchValue(&hdr, "Scanditronics", 0)>=0)
569 else
571 } else if(iftFindKey(&hdr, "Discriminators", 0)>=0) { // Try old Allogg
573 /* Try another Inveon format */
574 } else if(iftSearchValue(&hdr, "Subject Weight", 0)>=0 && iftSearchValue(&hdr, "Subject Sex", 0)>=0) {
575 format=TAC_FORMAT_INVEON;
576 }
577 }
578
579 /* Try to identify as Mat file */
580 if(format==TAC_FORMAT_UNKNOWN && csvIsRegular(&csv) && csv.row_nr>1 && csv.col_nr>1) {
581 if(verbose>2) printf("\nRegular CSV, therefore trying Mat file format\n");
582 /* Starting from second row, each first cell should be inside '' */
583 int ok=1; char *c; int len;
584 for(int r=1; r<csv.row_nr; r++) {
585 c=csvCell(&csv, r, 0); if(c==NULL) {ok=0; break;}
586 len=strlen(c); if(len<2) {ok=0; break;} // should be at least ''
587 if(c[0]!='\'' || c[len-1]!='\'') {ok=0; break;}
588 }
589 if(ok) format=TAC_FORMAT_MAT;
590 }
591
592 /* more formats should be identified here */
593 if(format==TAC_FORMAT_UNKNOWN) {
594 if(verbose>10) {
595 printf("\n FORMAT NOT IDENTIFIED \n");
596 printf("\n --- CSV contents ---\n");
597 csvWrite(&csv, 0, stdout, status);
598 fflush(stdout);
599 }
600 }
601
602 /* If not identified, then try to read as simple data */
603 if(format==TAC_FORMAT_UNKNOWN) format=TAC_FORMAT_SIMPLE;
604
605 if(verbose>1) {printf(" file format: %s\n", tacFormattxt(format)); fflush(stdout);}
606
607
608 /* Read the supported formats */
609 /* Certain formats may contain additional header information in comment
610 lines; read comment headers to be added into TAC struct for further
611 processing; ABSS formats use the previously read whole IFT data.
612 Header may not exist, therefore do not worry about errors here.
613 */
614 switch(format) {
616 iftFree(&hdr);
617 fp=fopen(fname, "r");
618 if(fp!=NULL) {iftRead(&hdr, fp, 0, 2, status); fclose(fp);}
619 ret=tacReadSimple(d, &csv, &hdr, status);
620 break;
621 case TAC_FORMAT_DFT:
622 iftFree(&hdr);
623 fp=fopen(fname, "r");
624 if(fp!=NULL) {iftRead(&hdr, fp, 0, 2, status); fclose(fp);}
625 ret=tacReadDFT(d, &csv, &hdr, status);
626 break;
627 case TAC_FORMAT_PMOD:
628 iftFree(&hdr);
629 fp=fopen(fname, "r");
630 if(fp!=NULL) {iftRead(&hdr, fp, 0, 2, status); fclose(fp);}
631 ret=tacReadPMOD(d, &csv, &hdr, status);
632 break;
633 case TAC_FORMAT_QVIEW:
634 ret=tacReadQView(d, &csv, 0, status);
635 break;
636 case TAC_FORMAT_MAT:
637 ret=tacReadMat(d, &csv, status);
638 break;
639 case TAC_FORMAT_4DM:
640 ret=tacRead4DM(d, &csv, status);
641 break;
646 iftFree(&hdr);
647 fp=fopen(fname, "r");
648 if(fp!=NULL) {iftRead(&hdr, fp, 0, 2, status); fclose(fp);}
649 ret=tacReadCSV(d, &csv, &hdr, status);
650 break;
652 ret=tacReadCarimasTxt(d, &csv, status);
653 break;
655 ret=tacReadInveonCSV(d, &csv, status);
656 break;
657 case TAC_FORMAT_SIF:
658 iftFree(&hdr);
659 fp=fopen(fname, "r");
660 if(fp!=NULL) {iftRead(&hdr, fp, 0, 2, status); fclose(fp);}
661 ret=tacReadSIF(d, &csv, &hdr, status);
662 break;
664 ret=tacReadHRRTHC(d, &csv, status);
665 break;
667 ret=tacReadHRPLUSHC(d, &csv, status);
668 break;
670 //iftFree(&hdr);
671 //fp=fopen(fname, "r");
672 //if(fp!=NULL) {iftRead(&hdr, fp, 0, 1, status); fclose(fp);}
673 ret=tacReadAllogg(d, &hdr, status);
674 break;
676 ret=tacReadOldAllogg(d, &hdr, status);
677 break;
679 ret=tacReadScanditronics(d, &hdr, status);
680 break;
682 ret=tacReadGEMS(d, &hdr, status);
683 break;
684 default:
685 /* The rest of formats are not supported */
686 if(verbose>0) printf("identified as %s file\n", tacFormattxt(format));
688 statusSet(status, __func__, __FILE__, __LINE__, ret);
689 }
690 csvFree(&csv); iftFree(&hdr);
691 if(ret!=TPCERROR_OK) {tacFree(d); return(ret);}
692
693 /* Set study number, if not yet set, based on file name */
694 if(verbose>1) printf("checking studynr\n");
695 if(tacGetHeaderStudynr(&d->h, NULL, status)!=TPCERROR_OK) {
696 if(verbose>2) printf("studynr not found in %s\n", fname);
697 char studynr[MAX_STUDYNR_LEN+1];
698 /* Only valid studynr is accepted */
699 ret=studynrFromFilename(fname, studynr, 1);
700 if(ret==0) {
701 if(verbose>2) printf("studynr based on filename: %s\n", studynr);
702 ret=tacSetHeaderStudynr(&d->h, studynr);
703 } else if(verbose>1)
704 fprintf(stderr, "Error: cannot get valid studynr from filename.\n");
705 }
706
707 /* Set y unit, if not yet set, based on file name */
708 if(verbose>1) printf("checking concentration units\n");
709 if(d->cunit==UNIT_UNKNOWN) {
710 d->cunit=unitIdentifyFilename(fname);
711 if(d->cunit!=UNIT_UNKNOWN && verbose>1) {
712 printf("concentration units based on filename := %s\n", unitName(d->cunit)); fflush(stdout);
713 }
714 }
715
716 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
717 return(TPCERROR_OK);
718}
int csvIsRegular(CSV *csv)
Definition csv.c:292
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:358
void csvFree(CSV *csv)
Definition csv.c:38
int csvWrite(CSV *csv, int regular, FILE *fp, TPCSTATUS *status)
Definition csvio.c:52
int tacReadDFT(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition dftio.c:300
char * filenameGetExtension(const char *s)
Get the last extension of a file name.
Definition filename.c:178
int tacReadHRPLUSHC(TAC *tac, CSV *csv, TPCSTATUS *status)
Definition hcio.c:114
int tacReadHRRTHC(TAC *tac, CSV *csv, TPCSTATUS *status)
Definition hcio.c:25
int iftSearchValue(IFT *ift, const char *s, int start_index)
Definition iftfind.c:114
int iftFindPair(IFT *ift, const char *key, const char *value, int start_index)
Definition iftfind.c:55
int iftRead(IFT *ift, FILE *fp, int is_key_required, int is_comment_accepted, TPCSTATUS *status)
Definition iftio.c:130
int tacReadMat(TAC *tac, CSV *csv, TPCSTATUS *status)
Definition matio.c:25
int tacReadPMOD(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition pmodio.c:146
int tacReadQView(TAC *tac, CSV *csv, const int grouponly, TPCSTATUS *status)
Definition qviewio.c:27
int tacReadSIF(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition sifio.c:129
int tacReadSimple(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition simpleio.c:97
char * content
Definition tpccsv.h:30
int row_nr
Definition tpccsv.h:44
int col_nr
Definition tpccsv.h:46
char separator
Definition tpccsv.h:49
CSV_item * c
Definition tpccsv.h:38
int nr
Definition tpccsv.h:42
Definition tpcift.h:43
int studynrFromFilename(const char *fname, char *studynr, int force)
Definition studynr.c:79
int tacReadScanditronics(TAC *tac, IFT *hdr, TPCSTATUS *status)
Definition tacabss.c:326
int tacReadGEMS(TAC *tac, IFT *hdr, TPCSTATUS *status)
Definition tacabss.c:516
int tacReadAllogg(TAC *tac, IFT *hdr, TPCSTATUS *status)
Definition tacabss.c:26
int tacReadOldAllogg(TAC *tac, IFT *hdr, TPCSTATUS *status)
Definition tacabss.c:173
int tacReadInveonCSV(TAC *tac, CSV *csv, TPCSTATUS *status)
Definition taccsv.c:405
int tacReadCSV(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition taccsv.c:212
int tacReadCarimasTxt(TAC *tac, CSV *csv, TPCSTATUS *status)
Definition taccsv.c:631
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:26
int tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
int unitIdentifyFilename(const char *s)
Definition units.c:311

Referenced by imgReadNifti(), imgWriteNifti(), tacReadModelingData(), tacReadModelingInput(), and tacReadReference().

◆ tacRead4DM()

int tacRead4DM ( TAC * tac,
CSV * csv,
TPCSTATUS * status )
extern

Read 4DM CSV format from CSV structure into TAC structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacRead, tacWrite, tacInit
Parameters
tacPointer to TAC structure, contents of which are to be written.
csvPointer to CSV from which data is read.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file 4dmio.c.

33 {
34 int verbose=0; if(status!=NULL) verbose=status->verbose;
35 if(tac==NULL) {
36 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
37 return TPCERROR_FAIL;
38 }
39 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
40
41 tacFree(tac);
42
43 if(csv==NULL || csv->row_nr<4 || csv->col_nr<2) {
44 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
45 return TPCERROR_NO_DATA;
46 }
47
48 int ret=0;
49
50 /* Check from the first column that data indeed is 4DM data */
51 if(strcasecmp(csv->c[0].content, "PatientName")!=0 ||
52 strcasecmp(csv->c[2].content, "Patient MRN")!=0)
53 {
54 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
56 }
57
58 /* Find the frame number from specific field */
59 int frameNr=0;
60 {
61 int i=csvFindField(csv, "Number of Frames", 4);
62 if(i<0 || i>=csv->nr-1) {
63 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
65 }
66 i++;
67 strClean(csv->c[i].content);
68 frameNr=atoi(csv->c[i].content);
69 if(verbose>1) printf("frameNr := %d\n", frameNr);
70 if(frameNr<1) {
71 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
72 return TPCERROR_NO_DATA;
73 }
74 }
75
76 /* Estimate the number of ROIs */
77 int maxTacNr=0;
78 {
79 int i=4;
80 do {
81 i=csvSearchField(csv, "TAC ROI ", ++i);
82 if(i<0) break;
83 if(csv->c[i].col==0) maxTacNr++;
84 } while(i<csv->nr);
85 if(verbose>1) printf("maxTacNr := %d\n", maxTacNr);
86 if(maxTacNr<1) {
87 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
88 return TPCERROR_NO_DATA;
89 }
90 }
91
92 /* Allocate memory for TAC data */
93 ret=tacAllocate(tac, frameNr, maxTacNr);
94 statusSet(status, __func__, __FILE__, __LINE__, ret);
95 if(ret!=TPCERROR_OK) return(ret);
96 tac->isframe=1;
97 tac->sampleNr=frameNr;
98
99 /* Copy frame start times from CSV into TAC structure */
100 {
101 int i=csvSearchField(csv, "Frame Start Times", 4);
102 char tmp[64];
103 strncpyCleanSpaces(tmp, csv->c[i].content+17, 30); strCleanPars(tmp);
104 tac->tunit=unitIdentify(tmp);
105 if(verbose>2) printf("tunit := %s\n", unitName(tac->tunit));
106 int row=csv->c[i].row;
107 int fails=0;
108 for(int fi=0; fi<tac->sampleNr; fi++) {
109 i++;
110 if(csv->c[i].row!=row) {fails++; break;}
111 strClean(csv->c[i].content);
112 tac->x1[fi]=atofVerified(csv->c[i].content);
113 }
114 if(fails>0) {
115 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
117 }
118 }
119
120 /* Get frame durations from CSV to write frame end times into TAC structure */
121 {
122 int i=csvSearchField(csv, "Frame Durations", 4);
123 int row=csv->c[i].row;
124 int fails=0;
125 for(int fi=0; fi<tac->sampleNr; fi++) {
126 i++;
127 if(csv->c[i].row!=row) {fails++; break;}
128 strClean(csv->c[i].content);
129 tac->x2[fi]=tac->x1[fi]+atofVerified(csv->c[i].content);
130 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
131 }
132 if(fails>0) {
133 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
135 }
136 }
137
138 /* Copy ROI data from CSV into TAC structure */
139 tac->tacNr=0;
140 {
141 int i=4;
142 while((i=csvSearchField(csv, "TAC ROI ", i))>0) {
143 int row=csv->c[i].row;
144 strlcpy(tac->c[tac->tacNr].name, csv->c[i].content+8, MAX_TACNAME_LEN+1);
145 int fails=0, goods=0;
146 for(int fi=0; fi<tac->sampleNr; fi++) {
147 i++;
148 if(csv->c[i].row!=row) {fails++; break;}
149 strClean(csv->c[i].content);
150 tac->c[tac->tacNr].y[fi]=atofVerified(csv->c[i].content);
151 if(isnormal(tac->c[tac->tacNr].y[fi])) goods++; // zero is not accepted here on purpose
152 }
153 if(fails==0 && goods>0) tac->tacNr++;
154 }
155 if(tac->tacNr<1) {
156 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
157 return TPCERROR_NO_DATA;
158 }
159 }
160
161 /* Get concentration units */
162 {
163 int i=csvSearchField(csv, "TAC FA Blood LV ", 4);
164 if(i>=0) {
165 char tmp[64];
166 strncpyCleanSpaces(tmp, csv->c[i].content+16, 64); strCleanPars(tmp);
167 tac->cunit=unitIdentify(tmp);
168 if(verbose>2) printf("cunit := %s\n", unitName(tac->cunit));
169 }
170 }
171
172 /* Get isotope */
173 {
175 int i=csvFindField(csv, "Radionuclide Name", 4);
176 if(i>=0 && i<csv->nr-1 && csv->c[i].row==csv->c[i+1].row) {
177 char *buf=strTokenDup(csv->c[++i].content, " ", NULL);
179 free(buf);
180 }
182 if(verbose>2) printf("isotope := %s\n", isotopeName(isotope));
183 }
184
185 if(tac->sampleNr<1 || tac->tacNr<1) {
186 tacFree(tac);
187 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
189 }
190
192
193 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
194 return(TPCERROR_OK);
195}
int csvFindField(CSV *csv, const char *s, int start_index)
Definition csvfind.c:27
int csvSearchField(CSV *csv, const char *s, int start_index)
Definition csvfind.c:50
double atofVerified(const char *s)
Definition decpoint.c:75
void strCleanPars(char *s)
Definition stringext.c:476
int strncpyCleanSpaces(char *s1, const char *s2, int maxlen)
Definition stringext.c:265
int col
Definition tpccsv.h:28
int row
Definition tpccsv.h:26
void tacSetIsotope(TAC *tac, int isotope)
Definition tacdc.c:41

◆ tacReadAllogg()

int tacReadAllogg ( TAC * tac,
IFT * hdr,
TPCSTATUS * status )
extern

Read Allogg #2 ABSS data from IFT struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacInit, tacRead, tacReadOldAllogg
Parameters
tacPointer to TAC struct, contents of which are to be written.
hdrPointer to IFT to read data from.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file tacabss.c.

33 {
34 int verbose=0; if(status!=NULL) verbose=status->verbose;
35 if(tac==NULL) {
36 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
37 return TPCERROR_FAIL;
38 }
39 tacFree(tac);
40 if(hdr==NULL || hdr->keyNr<2) {
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
42 return TPCERROR_NO_DATA;
43 }
44 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
45
46 /* Check whether IFT even can contain Allogg data */
47 int ii;
48 /* Find the line '//Heading' */
49 ii=iftSearchValue(hdr, "//Heading", 0);
50 if(ii<0) {
51 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
53 }
54 /* Find the line '//Data' */
55 ii=iftSearchValue(hdr, "//Data", 0);
56 if(ii<0) {
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
59 }
60 /* Sample data should start after this index (right after title) */
61 if(verbose>3) {
62 printf("found '%s' at ii=%d\n", hdr->item[ii].value, ii);
63 fflush(stdout);
64 }
65 /* Allocate memory for TAC data */
66 int ret;
67 ret=tacAllocate(tac, hdr->keyNr-ii, 8);
68 statusSet(status, __func__, __FILE__, __LINE__, ret);
69 if(ret!=TPCERROR_OK) return(ret);
70 tac->tacNr=8;
71 /* Set basic header information */
73 tac->isframe=1; // Allogg data always contains frame start and end times
74 tac->tunit=UNIT_SEC;
75 tac->cunit=UNIT_COUNTS;
76 /* Set TAC names into TAC struct */
77 strcpy(tac->c[0].name, "Singles");
78 strcpy(tac->c[1].name, "Coincidents");
79 strcpy(tac->c[2].name, "Singles-count-rate");
80 strcpy(tac->c[3].name, "Coincidents-count-rate");
81 strcpy(tac->c[4].name, "Singles-count-rate-DTC");
82 strcpy(tac->c[5].name, "Coincidents-count-rate-DTC");
83 strcpy(tac->c[6].name, "Singles-DTC-decay");
84 strcpy(tac->c[7].name, "Coincidents-DTC-decay");
85
86 /* Find the first line starting with valid date and time */
87 struct tm start_time;
88 ii++;
89 for(; ii<hdr->keyNr; ii++) {
90 if(strDateTimeRead(hdr->item[ii].value, &start_time)==0) break;
91 }
92 if(ii==hdr->keyNr) {
93 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
95 }
96 /* Save the start time of the first sample to be saved later in TAC header */
97 char scan_start_time[32];
98 if(strftime(scan_start_time, 20, "%Y-%m-%d %H:%M:%S", &start_time)==0) {
99 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
100 return(TPCERROR_NO_DATETIME);
101 }
102 /* Go through the lines, extracting sample data, and deleting data lines
103 from the header; stop storing sample data after first invalid line */
104 if(verbose>2) {printf(" reading data lines...\n"); fflush(stdout);}
105 int i=0, n, stopped=0;
106 while(ii<hdr->keyNr && i<tac->_sampleNr) {
107 if(stopped) {iftDelete(hdr, ii); continue;}
108 if(hdr->item[ii].value[0]=='#') {ii++; continue;}
109 if(hdr->item[ii].value==NULL) {iftDelete(hdr, ii); continue;}
110 if(strnlen(hdr->item[ii].key, 3)>0) {
111 iftDelete(hdr, ii); stopped=1; continue;
112 }
113 if(strDateTimeRead(hdr->item[ii].value, &start_time)!=0) {
114 iftDelete(hdr, ii); stopped=1; continue;
115 }
116 //printf("reading sample '%s'\n", hdr->item[ii].value+20); fflush(stdout);
117 n=sscanf(hdr->item[ii].value+20, "%lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
118 &tac->x1[i],
119 &tac->c[0].y[i], &tac->c[1].y[i], &tac->c[2].y[i], &tac->c[3].y[i],
120 &tac->c[4].y[i], &tac->c[5].y[i], &tac->c[6].y[i], &tac->c[7].y[i]
121 );
122 if(n==9) i++; else stopped=1;
123 iftDelete(hdr, ii);
124 }
125 tac->sampleNr=i;
126 if(verbose>2) printf(" %d data line(s) read.\n", i);
127 if(i<1) {
128 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
129 return(TPCERROR_NO_DATA);
130 }
131
132 /* Calculate frame end and mid times */
133 for(i=0; i<tac->sampleNr-1; i++) {
134 tac->x2[i]=tac->x1[i+1];
135 tac->x[i]=0.5*(tac->x1[i]+tac->x2[i]);
136 }
137 /* last sample */
138 if(tac->sampleNr>1) {
139 tac->x2[i]=tac->x1[i]+(tac->x2[i-1]-tac->x1[i-1]);
140 } else {
141 tac->x2[i]=tac->x1[i]+1.0;
142 }
143 tac->x[i]=0.5*(tac->x1[i]+tac->x2[i]);
144
145 /* Delete more lines from the header */
146 ii=iftSearchValue(hdr, "//Heading", 0); if(ii>=0) iftDelete(hdr, ii);
147 ii=iftSearchValue(hdr, "//Data", 0); if(ii>=0) iftDelete(hdr, ii);
148 ii=iftSearchValue(hdr, "Absolute time", 0); if(ii>=0) iftDelete(hdr, ii);
149 /* Set all header lines to comments */
150 for(ii=0; ii<hdr->keyNr; ii++) hdr->item[ii].comment=1;
151 /* Copy the header contents to TAC (deletes previous contents) */
152 (void)iftDuplicate(hdr, &tac->h);
153 tac->h.type=3;
154 /* Copy study number to the TAC header */
155 ii=iftFindKey(hdr, "Run number", 0);
156 if(ii>=0 && strnlen(hdr->item[ii].value, 5)>0)
157 (void)tacSetHeaderStudynr(&tac->h, hdr->item[ii].value);
158 /* Copy the start time of the first sample to the TAC header */
159 (void)tacSetHeaderScanstarttime(&tac->h, scan_start_time);
160
161
162 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
163 return(TPCERROR_OK);
164}
int strDateTimeRead(const char *str, struct tm *date)
Definition datetime.c:350
int iftDelete(IFT *ift, int index)
Definition ift.c:206
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
char comment
Definition tpcift.h:27
char * key
Definition tpcift.h:32
int type
Definition tpcift.h:51
int keyNr
Definition tpcift.h:47
int tacSetHeaderScanstarttime(IFT *h, const char *s)
Definition tacift.c:427
@ UNIT_COUNTS
counts
@ UNIT_SEC
seconds
@ TPCERROR_NO_DATETIME
File contains no date or time.

Referenced by tacRead().

◆ tacReadCarimasTxt()

int tacReadCarimasTxt ( TAC * tac,
CSV * csv,
TPCSTATUS * status )
extern

Read Carimas TXT TAC format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadCSV, tacRead
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read; if it contains only one column, then it is assumed to represent the first y column and x column is not filled.
statusPointer to status data; enter NULL if not needed.

Definition at line 631 of file taccsv.c.

639 {
640 int verbose=0; if(status!=NULL) verbose=status->verbose;
641 if(verbose>0) printf("%s()\n", __func__);
642 if(tac==NULL) {
643 if(verbose>0) printf("tac := NULL\n");
644 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
645 return TPCERROR_FAIL;
646 }
647
648 tacFree(tac);
649
650 if(verbose>2) {
651 printf("csv.row_nr := %d\n", csv->row_nr);
652 printf("csv.col_nr := %d\n", csv->col_nr);
653 }
654 if(csv==NULL || csv->row_nr<6 || csv->col_nr<2) {
655 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
656 return TPCERROR_NO_DATA;
657 }
658
659 /* Check that data indeed is CSV TAC data */
660 if(strcasecmp(csvCell(csv, 1, 0), "Num Voxels")!=0 ||
661 strncasecmp(csvCell(csv, 2, 0), "Volume (mm^3)", 6)!=0 ||
662 strncasecmp(csvCell(csv, 3, 0), "Times(s)", 5)!=0 )
663 {
664 if(verbose>0) {
665 printf("cell[%d][%d] := '%s'\n", 1, 0, csvCell(csv, 1, 0));
666 printf("cell[%d][%d] := '%s'\n", 2, 0, csvCell(csv, 2, 0));
667 printf("cell[%d][%d] := '%s'\n", 3, 0, csvCell(csv, 3, 0));
668 }
669 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
671 }
672
673 char *cptr;
674 int ret, fi, ri, oknr;
675
676 /* Allocate memory for TAC data */
677 ret=tacAllocate(tac, csv->row_nr-4, csv->col_nr-1);
678 statusSet(status, __func__, __FILE__, __LINE__, ret);
679 if(ret!=TPCERROR_OK) return ret;
680 tac->tacNr=csv->col_nr-1; tac->sampleNr=csv->row_nr-4;
681 tac->isframe=1;
682 // initiate the format, may be changed later if necessary
684
685 /* Get time unit from the 4th nonempty title line, inside parens */
686 tac->tunit=UNIT_UNKNOWN;
687 cptr=csvCell(csv, 3, 0);
688 if(cptr!=NULL && strncasecmp(cptr, "Times(s)", 5)==0) {
689 char *tmp=strdup(cptr+5);
690 strCleanPars(tmp); tac->tunit=unitIdentify(tmp);
691 free(tmp);
692 }
693
694 /* Get concentration unit the first title line, inside parens */
695 tac->cunit=UNIT_UNKNOWN;
696 cptr=csvCell(csv, 0, 1);
697 if(cptr!=NULL && strchr(cptr, '(')!=0) {
698 char *tmp=strdup(strchr(cptr, '('));
699 strCleanPars(tmp); tac->cunit=unitIdentify(tmp);
700 free(tmp);
701 }
702
703 /* Read TAC names from the first title line */
704 if(verbose>4) printf("reading VOI names\n");
705 ret=oknr=0;
706 for(ri=0; ri<tac->tacNr; ri++) {
707 cptr=csvCell(csv, 0, ri+1); if(!cptr) {ret++; break;}
708 if(strlen(cptr)==0) break;
709 strlcpy(tac->c[ri].name, cptr, MAX_TACNAME_LEN+1);
710 cptr=strchr(tac->c[ri].name, '('); if(cptr) *cptr='\0';
711 if(strcmp(tac->c[ri].name, ".")==0) strcpy(tac->c[ri].name, "");
712 oknr++;
713 }
714 if(ret || oknr<1) {
715 if(verbose>0) printf("could not read TAC names.\n");
716 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
718 }
719 /* Set tacNr, in case that txt file had empty fields */
720 tac->tacNr=oknr;
721 if(verbose>2) printf(" tacNr=%d\n", tac->tacNr);
722
723 /* Get VOI volumes from the 3rd line */
724 if(verbose>4) printf("reading VOI volumes\n");
725 ret=oknr=0;
726 for(ri=0; ri<tac->tacNr; ri++) {
727 cptr=csvCell(csv, 2, ri+1); if(!cptr) {ret++; break;}
728 if(atofCheck(cptr, &tac->c[ri].size)!=0) tac->c[ri].size=nan("");
729 oknr++;
730 }
731 if(ret || oknr<1) {
732 if(verbose>0) printf("could not read TAC volumes.\n");
733 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
735 }
736
737 /* Copy x and y data from CSV into TAC struct */
738 if(verbose>4) printf("reading x and y values\n");
739 ret=oknr=0;
740 for(fi=0; fi<tac->sampleNr; fi++) {
741 /* Frame times */
742 cptr=csvCell(csv, fi+4, 0); if(!cptr) {ret++; break;}
743 if(sscanf(cptr, "%lf - %lf", &tac->x1[fi], &tac->x2[fi])!=2) {ret++; break;}
744 /* Concentrations */
745 for(ri=0; ri<tac->tacNr; ri++) {
746 cptr=csvCell(csv, fi+4, ri+1); if(!cptr) {ret++; break;}
747 ret=atofCheck(cptr, &tac->c[ri].y[fi]); if(ret) break;
748 }
749 oknr++;
750 }
751 if(ret || oknr<1) {
752 if(verbose>0) printf("could not read data.\n");
753 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
755 }
756 if(verbose>2) printf(" sampleNr=%d\n", tac->sampleNr);
757
758 /* Set middle sample times */
759 if(tac->isframe)
760 for(fi=0; fi<tac->sampleNr; fi++)
761 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
762
763 /* Move column containing weights to its correct place in the struct */
764 ret=tacWMove(tac, 1, status);
765 if(ret!=TPCERROR_OK && ret!=TPCERROR_NO_WEIGHTS) {
766 statusSet(status, __func__, __FILE__, __LINE__, ret);
767 return(ret);
768 }
769 if(tac->tacNr<1) {
770 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
771 return TPCERROR_NO_DATA;
772 }
773
774 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
775 return(TPCERROR_OK);
776}
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
int tacWMove(TAC *tac, int ow, TPCSTATUS *status)
Definition tacw.c:75
@ TPCERROR_NO_WEIGHTS
File contains no weights.

Referenced by tacRead().

◆ tacReadCSV()

int tacReadCSV ( TAC * tac,
CSV * csv,
IFT * hdr,
TPCSTATUS * status )
extern

Read CSV TAC format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWriteCSV, tacRead, tacReadCarimasTxt
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read; if it contains only one column, then it is assumed to represent the first y column and x column is not filled.
hdrPointer to possible header data, which, if available, if processed and copied to TAC too; enter NULL if not available.
statusPointer to status data; enter NULL if not needed.

Definition at line 212 of file taccsv.c.

223 {
224 int verbose=0; if(status!=NULL) verbose=status->verbose;
225 if(tac==NULL) {
226 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
227 return TPCERROR_FAIL;
228 }
229 if(verbose>0) printf("%s()\n", __func__);
230
231 tacFree(tac);
232
233 if(csv==NULL || csv->row_nr<2 || csv->col_nr<2) {
234 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
235 return TPCERROR_NO_DATA;
236 }
237
238 /* Check from the first field that data indeed is CSV TAC data */
239 if(strcasecmp(csv->c[0].content, "TAC")!=0) {
240 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
242 }
243
244 /* Get time type from the title line */
245 int i, isframe=-1;
246 for(i=2; i<csv->nr; i++) if(csv->c[i].row==1 && csv->c[i].col==0) break;
247 if(strncasecmp(csv->c[i].content, "time", 4)==0) isframe=0;
248 else if(strncasecmp(csv->c[i].content, "start", 5)==0 &&
249 strncasecmp(csv->c[i+1].content, "end", 3)==0) isframe=1;
250 if(isframe<0) {
251 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
253 }
254
255 /* Allocate memory for TAC data */
256 int n, ret;
257 n=csv->col_nr-1; if(isframe==1) n--;
258 if(n<1) {
259 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
261 }
262 ret=tacAllocate(tac, csv->row_nr-2, n);
263 statusSet(status, __func__, __FILE__, __LINE__, ret);
264 if(ret!=TPCERROR_OK) return ret;
265 tac->tacNr=n; tac->sampleNr=csv->row_nr-2;
266 tac->isframe=isframe;
267 // initiate the format, may be changed later if necessary
268 if(csv->separator=='\t') tac->format=TAC_FORMAT_TSV_UK;
269 else if(csv->separator==',') tac->format=TAC_FORMAT_CSV_INT;
270 else tac->format=TAC_FORMAT_CSV_UK;
271
272 /* Copy header to TAC struct */
273 iftDuplicate(hdr, &tac->h);
274
275 /* Read study id from the second field */
276 tacSetHeaderStudynr(&tac->h, csv->c[1].content);
277
278 /* Get time unit from the first title field, inside parens */
279 char *cptr;
280 for(i=2; i<csv->nr; i++) if(csv->c[i].row==1 && csv->c[i].col==0) break;
281 cptr=strchr(csv->c[i].content, '[');
282 if(cptr==NULL) {
283 tac->tunit=UNIT_UNKNOWN;
284 } else {
285 char *tmp=strdup(cptr+1);
286 cptr=strrchr(tmp, ']'); if(cptr!=NULL) *cptr='\0';
287 tac->tunit=unitIdentify(tmp);
288 free(tmp);
289 }
290
291 /* Get concentration unit from 2nd or 3rd field, inside parens */
292 i++; if(isframe) i++;
293 cptr=strchr(csv->c[i].content, '[');
294 if(cptr==NULL) {
295 tac->cunit=UNIT_UNKNOWN;
296 } else {
297 char *tmp=strdup(cptr+1);
298 cptr=strrchr(tmp, ']'); if(cptr!=NULL) *cptr='\0';
299 tac->cunit=unitIdentify(tmp);
300 free(tmp);
301 }
302
303 /* Read TAC names from the title line */
304 n=0;
305 for(; i<csv->nr; i++) {
306 if(csv->c[i].row!=1 || n>=tac->tacNr) break;
307 /* Copy TAC name, removing unit if necessary */
308 if(strchr(csv->c[i].content, '[')) {
309 char *tmp=strdup(csv->c[i].content);
310 cptr=strchr(tmp, '['); *cptr='\0';
311 strlcpy(tac->c[n].name, tmp, MAX_TACNAME_LEN+1);
312 free(tmp);
313 } else {
314 strlcpy(tac->c[n].name, csv->c[i].content, MAX_TACNAME_LEN+1);
315 }
316 if(strcmp(tac->c[n].name, ".")==0) strcpy(tac->c[n].name, "");
317 n++;
318 }
319 if(n<1) {
320 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
322 }
323 tac->tacNr=n;
324 if(verbose>2) printf(" tacNr=%d\n", tac->tacNr);
325
326 /* Copy x and y data from CSV into TAC struct */
327 int fi=0, ri=0, oknr=0, maxfi=0;
328 ret=0;
329 double v;
330 for(i=2; i<csv->nr; i++) if(csv->c[i].row==2) break;
331 for(; i<csv->nr; i++) {
332 if(verbose>10)
333 printf("i=%d\trow=%d\tcol=%d\t'%s'\n", i, csv->c[i].row, csv->c[i].col, csv->c[i].content);
334 if(csv->c[i].col==0 && strcasecmp(csv->c[i].content, "volume")==0)
335 break; // stop if VOI volume line is encountered
336 fi=csv->c[i].row-2; if(fi<0 || fi>=tac->sampleNr) {ret++; continue;}
337 if(fi>maxfi) maxfi=fi;
338 if(csv->c[i].col<0) {ret++; continue;}
339 ri=csv->c[i].col-1; if(tac->isframe) ri--;
340 if(ri>=tac->tacNr) {ret++; continue;}
341 v=atofVerified(csv->c[i].content); if(!isnan(v)) oknr++;
342 if(verbose>10) printf(" -> fi=%d\tri=%d\t=\t%g\n", fi, ri, v);
343 if(ri<0) {
344 if(tac->isframe) {
345 if(ri==-2) tac->x1[fi]=v; else if(ri==-1) tac->x2[fi]=v;
346 } else tac->x[fi]=v;
347 } else tac->c[ri].y[fi]=v;
348 /* check whether we have decimal comma or dot */
350 if(strHaveDecimalComma(csv->c[i].content)) {
352 else tac->format=TAC_FORMAT_CSV_INT;
353 }
354 }
355 }
356 tac->sampleNr=maxfi+1;
357 if(verbose>2) printf(" sampleNr=%d\n", tac->sampleNr);
358 if(verbose>0 && ret>0) printf("%d error(s) in reading CSV file format.\n", ret);
359 if(oknr<1) {
360 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
362 }
363 /* Set middle sample times when necessary */
364 if(tac->isframe)
365 for(fi=0; fi<tac->sampleNr; fi++)
366 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
367
368 /* Get VOI volumes from the following line */
369 if(i<csv->nr && strcasecmp(csv->c[i].content, "volume")==0) {
370 if(tac->isframe) i++;
371 for(ri=0; ri<tac->tacNr; ri++) {
372 if(csv->c[i+ri].row!=csv->c[i].row) break;
373 tac->c[ri].size=atofVerified(csv->c[i+ri].content);
374 }
375 }
376
377 /* If units are not known, try to read units from header */
378 if(tac->cunit==UNIT_UNKNOWN) tacGetHeaderUnit(tac, NULL);
379 else tacSetHeaderUnit(&tac->h, UNIT_UNKNOWN);
380 if(tac->tunit==UNIT_UNKNOWN) tacGetHeaderTimeunit(tac, NULL);
382
383 /* Move column containing weights to its correct place in the struct */
384 ret=tacWMove(tac, 1, status);
385 if(ret!=TPCERROR_OK && ret!=TPCERROR_NO_WEIGHTS) {
386 statusSet(status, __func__, __FILE__, __LINE__, ret);
387 return(ret);
388 }
389 if(tac->tacNr<1) {
390 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
391 return TPCERROR_NO_DATA;
392 }
393
394 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
395 return(TPCERROR_OK);
396}
int strHaveDecimalComma(const char *s)
Definition decpoint.c:115
int tacGetHeaderUnit(TAC *tac, TPCSTATUS *status)
Definition tacift.c:145
int tacGetHeaderTimeunit(TAC *tac, TPCSTATUS *status)
Definition tacift.c:234

Referenced by tacRead().

◆ tacReadDFT()

int tacReadDFT ( TAC * tac,
CSV * csv,
IFT * hdr,
TPCSTATUS * status )
extern

Read DFT format from CSV structure into TAC structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWriteDFT, tacWrite
Parameters
tacPointer to TAC structure, into which are to be written; any previous contents are deleted.
csvPointer to CSV from which data is read; it must contain at least one or two x columns and one y column.
hdrPointer to possible header data, which, if available, is copied to TAC as a processed version; enter NULL if not available
statusPointer to status data; enter NULL if not needed

Definition at line 300 of file dftio.c.

311 {
312 int verbose=0; if(status!=NULL) verbose=status->verbose;
313 if(tac==NULL) {
314 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
315 return TPCERROR_FAIL;
316 }
317 tacFree(tac);
318 if(csv==NULL || csv->row_nr<5 || csv->col_nr<2) {
319 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
320 return TPCERROR_NO_DATA;
321 }
322 if(verbose>0) printf("%s()\n", __func__);
323
324 /* Verify the magic number first */
325 if(strncasecmp(csv->c[0].content, "DFT", 3)!=0) {
326 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
328 }
329
330 int ret, i, j, m, n, isframe=0, is2cunit=0, is2tunit=0, tunit;
331 char *cptr;
332
333 /* Get some important information from title lines first */
334 for(i=0; i<csv->nr; i++) if(csv->c[i].col==0 && csv->c[i].row==3) break;
335 if(i==csv->nr) {
336 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
338 }
339 /* Do we have one or two x columns */
340 // note that time unit may or may not be included in this field, depending
341 // on field separator
342 if(strncasecmp(csv->c[i].content, "Times", 5)==0) isframe=1;
343 else if(strncasecmp(csv->c[i].content, "Time", 4)==0) isframe=0;
344 else if(strncasecmp(csv->c[i].content, "Distances", 9)==0) isframe=1;
345 else if(strncasecmp(csv->c[i].content, "Distance", 8)==0) isframe=0;
346 else {
347 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
349 }
350 if(verbose>2) printf(" isframe=%d\n", isframe);
351 /* Get time unit from first or second field, inside parens */
352 cptr=strchr(csv->c[i].content, '(');
353 if(cptr==NULL) cptr=strchr(csv->c[i].content, '[');
354 if(cptr==NULL) {cptr=strchr(csv->c[i+1].content, '('); is2tunit=1;}
355 if(cptr==NULL) {cptr=strchr(csv->c[i+1].content, '['); is2tunit=1;}
356 if(cptr==NULL) {
357 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
359 } else {
360 char *tmp=strdup(cptr); strCleanPars(tmp); tunit=unitIdentify(tmp);
361 free(tmp);
362 }
363
364 /* Allocate memory for TAC data */
365 m=csv->row_nr-4;
366 n=csv->col_nr-1; if(isframe) n--;
367 if(n<1 || m<1) {
368 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
370 }
371 ret=tacAllocate(tac, m, n);
372 statusSet(status, __func__, __FILE__, __LINE__, ret);
373 if(ret!=TPCERROR_OK) return ret;
374 tac->tacNr=n; tac->sampleNr=m; // these may be refined later
375 tac->isframe=isframe;
376 tac->tunit=tunit;
377
378 /* Copy header to TAC struct */
379 iftDuplicate(hdr, &tac->h);
380
381 /* Read first title line, jumping over magic number */
382 n=0;
383 for(i=1; i<csv->nr; i++) {
384 if(csv->c[i].row!=0 || n>=tac->tacNr) break;
385 /* Copy TAC name */
386 strlcpy(tac->c[n].name, csv->c[i].content, MAX_TACNAME_LEN+1);
387 if(strcmp(tac->c[n].name, ".")==0) strcpy(tac->c[n].name, "");
388 n++;
389 }
390 if(n<1) {
391 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
393 }
394 tac->tacNr=n;
395 if(verbose>2)
396 printf(" tacNr=%d\n sampleNr=%d\n", tac->tacNr, tac->sampleNr);
397
398 /* Get study number */
399 for(i=0; i<csv->nr; i++) if(csv->c[i].row==1 && csv->c[i].col==0) {
400 if(strlen(csv->c[i].content)>0 && strcmp(csv->c[i].content, ".")!=0)
401 tacSetHeaderStudynr(&tac->h, csv->c[i].content);
402 break;
403 }
404
405 /* Get concentration unit from the first item on line 3 */
406 for(i=0; i<csv->nr; i++) if(csv->c[i].row==2 && csv->c[i].col==0) break;
407 tac->cunit=unitIdentify(csv->c[i].content);
408 /* Carimas may (erroneously) write conc unit in two columns, with actual
409 unit in 2nd column inside parenthesis */
410 if(strInPars(csv->c[i+1].content)
411 && csvRowLength(csv, 2)==csvRowLength(csv, 1)+1)
412 {
413 if(verbose>2) printf(" concentration unit spans two columns\n");
414 is2cunit=1;
415 if(tac->cunit==UNIT_UNKNOWN) {
416 char *tmp=strdup(csv->c[i+1].content);
417 strCleanPars(tmp); tac->cunit=unitIdentify(tmp);
418 free(tmp);
419 }
420 }
421
422
423 /* Catenate additional TAC names if available on lines 2 and 3 */
424 for(int ri=0; ri<tac->tacNr; ri++) {
425 for(i=0; i<csv->nr; i++) if(csv->c[i].row==1 && csv->c[i].col==ri+1) break;
426 for(j=i; j<csv->nr; j++) if(csv->c[j].row==2 && csv->c[j].col==ri+1) break;
427 if(i==csv->nr || j==csv->nr) {
428 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
430 }
431 if(is2cunit) j++; // add one in case cunit spans two columns
432 m=strlen(csv->c[i].content); if(strcmp(csv->c[i].content, ".")==0) m=0;
433 n=strlen(csv->c[j].content); if(strcmp(csv->c[j].content, ".")==0) n=0;
434 if((m+n)>0 && (strlen(tac->c[ri].name)<MAX_TACNAME_LEN-1))
435 strcat(tac->c[ri].name, "_");
436 if(m>0 && (m+strlen(tac->c[ri].name)<MAX_TACNAME_LEN))
437 strcat(tac->c[ri].name, csv->c[i].content);
438 if(n>0 && (strlen(tac->c[ri].name)<MAX_TACNAME_LEN-1))
439 strcat(tac->c[ri].name, "_");
440 if(n>0 && (n+strlen(tac->c[ri].name)<MAX_TACNAME_LEN))
441 strcat(tac->c[ri].name, csv->c[j].content);
442 }
443
444 /* Read sizes from 4th line */
445 n=csvRowLength(csv, 3);
446 for(i=0; i<csv->nr; i++) if(csv->c[i].row==3) {
447 m=csv->c[i].col-1; if(is2tunit) m--;
448 if(m>=0 && m<tac->tacNr) tac->c[m].size=atofVerified(csv->c[i].content);
449 }
450#if(0)
451 for(i=0, m=-1, n=0; i<csv->nr; i++) if(csv->c[i].row==3) {n++; if(m<0) m=i;}
452 if(n==tac->tacNr+1) m+=1;
453 else if(n==tac->tacNr+2) m+=2;
454 else {
455 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
457 }
458 for(int ri=0; ri<tac->tacNr; ri++)
459 tac->c[ri].size=atofVerified(csv->c[m++].content);
460#endif
461
462 /* Copy x and y data from CSV into TAC struct */
463 int fi=0, ri=0, oknr=0;
464 ret=0;
465 double v;
466 for(i=0; i<csv->nr; i++) if(csv->c[i].row==4) break;
467 for(; i<csv->nr; i++) {
468 if(verbose>10)
469 printf("i=%d\trow=%d\tcol=%d\n", i, csv->c[i].row, csv->c[i].col);
470 fi=csv->c[i].row-4; if(fi<0 || fi>=tac->sampleNr) {ret++; continue;}
471 if(csv->c[i].col<0) {ret++; continue;}
472 ri=csv->c[i].col-1;
473 if(tac->isframe) ri--;
474 if(ri>=tac->tacNr) {ret++; continue;}
475 v=atofVerified(csv->c[i].content); if(!isnan(v)) oknr++;
476 if(verbose>10) printf(" -> fi=%d\tri=%d\t=\t%g\n", fi, ri, v);
477 if(ri<0) {
478 if(tac->isframe) {
479 if(ri==-2) tac->x1[fi]=v; else if(ri==-1) tac->x2[fi]=v;
480 } else tac->x[fi]=v;
481 } else tac->c[ri].y[fi]=v;
482 }
483 if(verbose>0 && ret>0)
484 printf("%d error(s) in reading DFT file format.\n", ret);
485 if(oknr<1) {
486 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
488 }
489 /* Set middle sample times when necessary */
490 if(tac->isframe)
491 for(fi=0; fi<tac->sampleNr; fi++)
492 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
493
494 /* If units are not known, try to read units from header */
495 if(tac->cunit==UNIT_UNKNOWN) tacGetHeaderUnit(tac, NULL);
496 else tacSetHeaderUnit(&tac->h, UNIT_UNKNOWN);
497 if(tac->tunit==UNIT_UNKNOWN) tacGetHeaderTimeunit(tac, NULL);
499
500 /* Move column containing weights to its correct place in the struct */
501 ret=tacWMove(tac, 1, status);
502 if(ret!=TPCERROR_OK && ret!=TPCERROR_NO_WEIGHTS) {
503 statusSet(status, __func__, __FILE__, __LINE__, ret);
504 return(ret);
505 }
506 if(tac->tacNr<1) {
507 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
508 return TPCERROR_NO_DATA;
509 }
510
512 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
513 return(TPCERROR_OK);
514}
int csvRowLength(CSV *csv, int row)
Definition csv.c:244
int strInPars(char *s)
Definition stringext.c:453

Referenced by tacRead().

◆ tacReadGEMS()

int tacReadGEMS ( TAC * tac,
IFT * hdr,
TPCSTATUS * status )
extern

Read GEMS ABSS data from IFT struct into TAC struct.

Two date-time strings will be written in header, scan_start_time containing the time of the first sample, and sampler_start_time containing the time given in ABSS file header.

GEMS ABSS format is almost identical to Scanditronics, but the headers and times are processed differently, hence separate functions. If function finds that provided data is actually from Scanditronics, it calls tacReadScanditronics.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacInit, tacRead, tacReadScanditronics, tacReadAllogg
Parameters
tacPointer to TAC struct, contents of which are to be written.
hdrPointer to IFT to read data from.
statusPointer to status data; enter NULL if not needed.

Definition at line 516 of file tacabss.c.

523 {
524 int verbose=0; if(status!=NULL) verbose=status->verbose;
525 if(tac==NULL) {
526 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
527 return TPCERROR_FAIL;
528 }
529 tacFree(tac);
530 if(hdr==NULL || hdr->keyNr<2) {
531 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
532 return TPCERROR_NO_DATA;
533 }
534 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
535
536 /* Check whether IFT contains GEMS (or Scanditronics) data */
537 int format;
538 if(iftSearchValue(hdr, "AUX", 0)<0 ||
539 iftSearchValue(hdr, "1st detector pair", 0)<0)
540 {
541 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
543 }
544 if(iftSearchValue(hdr, "Scanditronics", 0)>=0) {
545 if(verbose>0) printf("data is GEMS but Scanditronics format\n");
546 return(tacReadScanditronics(tac, hdr, status));
547 } else {
549 }
550
551 /* Find the measurement start date, possibly with time;
552 at least the date must be there for calibration. */
553 struct tm start_time;
554 int ii, n;
555 for(ii=0; ii<hdr->keyNr; ii++) {
556 if(strnlen(hdr->item[ii].key, 3)>0) continue;
557 n=strnlen(hdr->item[ii].value, 22);
558 if(n<10 || n>19) continue;
559 //printf("ii=%d '%s' '%s'\n", ii, hdr->item[ii].key, hdr->item[ii].value);
560 if(strDateTimeRead(hdr->item[ii].value, &start_time)!=0) {
561 /* Date and time not found, try only date */
562 if(strDateRead(hdr->item[ii].value, &start_time)!=0) continue;
563 }
564 break;
565 }
566 if(ii==hdr->keyNr) {
567 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
568 return(TPCERROR_NO_DATETIME);
569 }
570 //printf("found '%s' at ii=%d\n", hdr->item[ii].value, ii);
571
572 /* Sample data should start after this index */
573 /* Allocate memory for TAC data */
574 int ret;
575 ret=tacAllocate(tac, hdr->keyNr-ii, 7);
576 statusSet(status, __func__, __FILE__, __LINE__, ret);
577 if(ret!=TPCERROR_OK) return(ret);
578 tac->tacNr=7;
579 /* Set basic header information */
580 tac->format=format;
581 tac->isframe=1; // Data always contains frame start and end times
582 tac->tunit=UNIT_SEC;
583 tac->cunit=UNIT_COUNTS;
584 /* Set TAC names into TAC struct */
585 strcpy(tac->c[0].name, "Detector1-Coinc");
586 strcpy(tac->c[1].name, "Detector1-Singl1");
587 strcpy(tac->c[2].name, "Detector1-Singl2");
588 strcpy(tac->c[3].name, "Detector2-Coinc");
589 strcpy(tac->c[4].name, "Detector2-Singl1");
590 strcpy(tac->c[5].name, "Detector2-Singl2");
591 strcpy(tac->c[6].name, "AUX-counts");
592
593 /* Go through the lines, extracting sample data, and deleting data lines
594 from the header */
595 if(verbose>2) printf(" reading data lines...\n");
596 ii++;
597 int i=0, stopped=0;
598 double time_of_day, first_tod=0.0, time_since_start, meas_interval;
599 while(ii<hdr->keyNr && i<tac->_sampleNr) {
600 if(stopped) {iftDelete(hdr, ii); continue;}
601 if(strnlen(hdr->item[ii].key, 3)>0 || hdr->item[ii].value==NULL) {
602 iftDelete(hdr, ii); continue;}
603 if(hdr->item[ii].value[0]=='#') {iftDelete(hdr, ii); continue;}
604 //printf("ii=%d '%s'\n", ii, hdr->item[ii].value);
605 n=sscanf(hdr->item[ii].value, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
606 &time_of_day, &time_since_start, &meas_interval,
607 &tac->c[0].y[i], &tac->c[1].y[i], &tac->c[2].y[i], &tac->c[3].y[i],
608 &tac->c[4].y[i], &tac->c[5].y[i], &tac->c[6].y[i]);
609 //printf(" n=%d\n", n);
610 if(n!=10) {
611 /* first line may contain the protocol; keep it as comment */
612 if(i==0) {ii++; continue;}
613 /* Later occurrence is considered as an error */
614 stopped=1; iftDelete(hdr, ii); continue;
615 }
616 if(time_of_day==0.0 && meas_interval==0.0) {
617 stopped=1; iftDelete(hdr, ii); continue;}
618 if(i==0) first_tod=time_of_day;
619 tac->x1[i]=time_since_start;
620 tac->x2[i]=time_since_start+meas_interval;
621 i++;
622 iftDelete(hdr, ii);
623 }
624 tac->sampleNr=i;
625 if(verbose>2) printf(" %d data line(s) read.\n", i);
626 if(i<1) {
627 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
628 return(TPCERROR_NO_DATA);
629 }
630 if(verbose>4) printf(" first_tod := %.1lf\n", first_tod);
631
632 /* Calculate frame mid times */
633 for(i=0; i<tac->sampleNr; i++) tac->x[i]=0.5*(tac->x1[i]+tac->x2[i]);
634
635 /* Read scan start time from the first sample, which is used also as
636 sampler start time, if only date was given in the header */
637 char scan_start_time[32], sampler_start_time[32];
638 time_t tim=(time_t)first_tod;
639 struct tm tmtim;
640 if(gmtime_r(&tim, &tmtim)==NULL) {
641 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
642 return(TPCERROR_NO_DATETIME);
643 }
644 /* Check whether also date is here;
645 if yes, this is actually Scanditronics data */
646 if(tmtim.tm_year>71 || tmtim.tm_mday>1) {
647 if(verbose>0) printf("data is not GEMS but Scanditronics format\n");
648 if(verbose>1 &&
649 strftime(scan_start_time, 32, "%Y-%m-%d %H:%M:%S", &tmtim)!=0) {
650 printf("first_sample_time := %s\n", scan_start_time);
651 }
652 tacFree(tac);
653 return(tacReadScanditronics(tac, hdr, status));
654 }
655 if(start_time.tm_hour==0 && start_time.tm_min==0 && start_time.tm_sec==0) {
656 start_time.tm_hour=tmtim.tm_hour;
657 start_time.tm_min=tmtim.tm_min;
658 start_time.tm_sec=tmtim.tm_sec;
659 n=strftime(sampler_start_time, 32, "%Y-%m-%d %H:%M:%S", &start_time);
660 if(n==0) strcpy(sampler_start_time, "");
661 strcpy(scan_start_time, sampler_start_time);
662 } else {
663 n=strftime(sampler_start_time, 32, "%Y-%m-%d %H:%M:%S", &start_time);
664 if(n==0) strcpy(sampler_start_time, "");
665 start_time.tm_hour=tmtim.tm_hour;
666 start_time.tm_min=tmtim.tm_min;
667 start_time.tm_sec=tmtim.tm_sec;
668 n=strftime(scan_start_time, 32, "%Y-%m-%d %H:%M:%S", &start_time);
669 if(n==0) strcpy(scan_start_time, "");
670 }
671 if(!scan_start_time[0]) {
672 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
673 return(TPCERROR_NO_DATETIME);
674 }
675
676
677 /* Set all header lines to comments */
678 for(ii=0; ii<hdr->keyNr; ii++) hdr->item[ii].comment=1;
679 /* Copy the header contents to TAC (deletes previous contents) */
680 (void)iftDuplicate(hdr, &tac->h);
681 tac->h.type=3;
682 /* Set the scan start time in the TAC header */
683 (void)tacSetHeaderScanstarttime(&tac->h, scan_start_time);
684 /* Set the sampler start time in the TAC header */
685 if(sampler_start_time[0])
686 (void)iftPut(&tac->h, "sampler_start_time", sampler_start_time, 1, NULL);
687 /* Copy study number to the TAC header */
688 ii=iftFindKey(hdr, "Patient", 0);
689 if(ii>=0 && strnlen(hdr->item[ii].value, 5)>0)
690 (void)tacSetHeaderStudynr(&tac->h, hdr->item[ii].value);
691
692 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
693 return(TPCERROR_OK);
694}
int strDateRead(const char *str, struct tm *date)
Definition datetime.c:378
struct tm * gmtime_r(const time_t *t, struct tm *tm)
Convert time_t to GMT struct tm.
Definition datetime.c:31
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63

Referenced by tacRead(), and tacReadScanditronics().

◆ tacReadHRPLUSHC()

int tacReadHRPLUSHC ( TAC * tac,
CSV * csv,
TPCSTATUS * status )
extern

Read HR+ head curve (.r) format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read; if it contains only one column, then it is assumed to represent the first y column and x column is not filled.
statusPointer to status data; enter NULL if not needed

Definition at line 114 of file hcio.c.

123 {
124 int verbose=0; if(status!=NULL) verbose=status->verbose;
125 if(tac==NULL) {
126 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
127 return TPCERROR_FAIL;
128 }
129 if(verbose>0) printf("%s()\n", __func__);
130
131 tacFree(tac);
132
133 if(csv==NULL || csv->row_nr<2 || csv->col_nr<8) {
134 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
135 return TPCERROR_NO_DATA;
136 }
137
138 /* Check from the title fields that data indeed is HRRT HC data */
139 int ret=0;
140 if(strcasecmp(csv->c[0].content, "time")!=0) ret++;
141 if(strcasecmp(csv->c[1].content, "prompt")!=0) ret++;
142 if(strcasecmp(csv->c[2].content, "delayed")!=0) ret++;
143 if(strcasecmp(csv->c[3].content, "p_rate")!=0) ret++;
144 if(strcasecmp(csv->c[4].content, "d_rate")!=0) ret++;
145 if(strcasecmp(csv->c[5].content, "dtime")!=0) ret++;
146 if(strcasecmp(csv->c[6].content, "frame")!=0) ret++;
147 if(strcasecmp(csv->c[7].content, "singles")!=0) ret++;
148 if(ret>0) {
149 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
151 }
152
153 /* Allocate memory for TAC data */
154 ret=tacAllocate(tac, csv->row_nr-1, 7);
155 statusSet(status, __func__, __FILE__, __LINE__, ret);
156 if(ret!=TPCERROR_OK) return ret;
157 tac->tacNr=7; tac->sampleNr=csv->row_nr-1;
158 if(verbose>2) printf(" sampleNr=%d\n", tac->sampleNr);
159
160 /* Set time type */
161 tac->isframe=0;
162 /* Set time unit */
163 tac->tunit=UNIT_MSEC;
164 /* Set concentration unit */
165 tac->cunit=UNIT_KCPS;
166
167 /* Set TAC names */
168 strcpy(tac->c[0].name, "prompt");
169 strcpy(tac->c[1].name, "delayed");
170 strcpy(tac->c[2].name, "p_rate");
171 strcpy(tac->c[3].name, "d_rate");
172 strcpy(tac->c[4].name, "dtime");
173 strcpy(tac->c[5].name, "frame");
174 strcpy(tac->c[6].name, "singles");
175
176 /* Copy x and y data from CSV into TAC struct */
177 double v; int oknr=0;
178 for(int i=8; i<csv->nr; i++) {
179 if(csv->c[i].row<1 || csv->c[i].row>tac->sampleNr || csv->c[i].col>7)
180 continue;
181 v=atofVerified(csv->c[i].content); if(!isnan(v)) oknr++;
182 if(csv->c[i].col==0) tac->x[csv->c[i].row-1]=v;
183 else tac->c[csv->c[i].col-1].y[csv->c[i].row-1]=v;
184 }
185 if(oknr<8) {
186 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
187 return TPCERROR_NO_DATA;
188 }
189
190 /* Set file format */
192
193 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
194 return(TPCERROR_OK);
195}
@ UNIT_MSEC
milliseconds
@ UNIT_KCPS
kilocounts/s

Referenced by tacRead().

◆ tacReadHRRTHC()

int tacReadHRRTHC ( TAC * tac,
CSV * csv,
TPCSTATUS * status )
extern

Read HRRT head curve (.hc) format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read; if it contains only one column, then it is assumed to represent the first y column and x column is not filled.
statusPointer to status data; enter NULL if not needed

Definition at line 25 of file hcio.c.

34 {
35 int verbose=0; if(status!=NULL) verbose=status->verbose;
36 if(tac==NULL) {
37 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
38 return TPCERROR_FAIL;
39 }
40 if(verbose>0) printf("%s()\n", __func__);
41
42 tacFree(tac);
43
44 if(csv==NULL || csv->row_nr<2 || csv->col_nr<4) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
46 return TPCERROR_NO_DATA;
47 }
48
49 /* Check from the title fields that data indeed is HRRT HC data */
50 int ret=0;
51 if(strcasecmp(csv->c[0].content, "Singles")!=0) ret++;
52 if(strcasecmp(csv->c[1].content, "Randoms")!=0) ret++;
53 if(strcasecmp(csv->c[2].content, "Prompts")!=0) ret++;
54 if(strncasecmp(csv->c[3].content, "Time(ms)", 4)!=0) ret++;
55 if(ret>0) {
56 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
58 }
59
60 /* Allocate memory for TAC data */
61 ret=tacAllocate(tac, csv->row_nr-1, 3);
62 statusSet(status, __func__, __FILE__, __LINE__, ret);
63 if(ret!=TPCERROR_OK) return ret;
64 tac->tacNr=3; tac->sampleNr=csv->row_nr-1;
65 if(verbose>2) printf(" sampleNr=%d\n", tac->sampleNr);
66
67 /* Set time type */
68 tac->isframe=0;
69 /* Get time unit from the last title field, inside parens */
70 char *cptr=strchr(csv->c[3].content, '(');
71 if(cptr==NULL) {
73 } else {
74 char *tmp=strdup(cptr+1);
75 cptr=strrchr(tmp, ')'); if(cptr!=NULL) *cptr='\0';
76 tac->tunit=unitIdentify(tmp);
77 free(tmp);
78 }
79 /* Set concentration unit */
80 tac->cunit=UNIT_KCPS;
81
82 /* Set TAC names */
83 strcpy(tac->c[0].name, "Singles");
84 strcpy(tac->c[1].name, "Randoms");
85 strcpy(tac->c[2].name, "Prompts");
86
87 /* Copy x and y data from CSV into TAC struct */
88 double v; int oknr=0;
89 for(int i=4; i<csv->nr; i++) {
90 if(csv->c[i].row<1 || csv->c[i].row>tac->sampleNr || csv->c[i].col>3)
91 continue;
92 v=atofVerified(csv->c[i].content); if(!isnan(v)) oknr++;
93 if(csv->c[i].col==3) tac->x[csv->c[i].row-1]=v;
94 else tac->c[csv->c[i].col].y[csv->c[i].row-1]=v;
95 }
96 if(oknr<4) {
97 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
98 return TPCERROR_NO_DATA;
99 }
100
101 /* Set file format */
103
104 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
105 return(TPCERROR_OK);
106}

Referenced by tacRead().

◆ tacReadInveonCSV()

int tacReadInveonCSV ( TAC * tac,
CSV * csv,
TPCSTATUS * status )
extern

Read Inveon TAC format from CSV struct into TAC struct.

Note that there are several Inveon TAC formats, and not all are supported.

Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to Inveon CSV from which data is read.
statusPointer to status data; enter NULL if not needed

Definition at line 405 of file taccsv.c.

412 {
413 int verbose=0; if(status!=NULL) verbose=status->verbose;
414 if(tac==NULL) {
415 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
416 return TPCERROR_FAIL;
417 }
418 if(verbose>0) printf("%s()\n", __func__);
419
420 int ret;
421
422 tacFree(tac);
423
424 if(csv==NULL || csv->row_nr<2 || csv->col_nr<5) {
425 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
426 return TPCERROR_NO_DATA;
427 }
428
429 /* Check from the first row that data indeed is CSV TAC data */
430 if(strstr(csv->c[0].content, " - Time")==NULL ||
431 strstr(csv->c[2].content, "(upper bound)")==NULL ||
432 strstr(csv->c[3].content, "(lower bound)")==NULL ||
433 strstr(csv->c[4].content, "(standard deviation)")==NULL) {
434 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
436 }
437
438
439 /* Allocate memory for TAC data */
440 ret=tacAllocate(tac, csv->row_nr-1, csv->col_nr/5);
441 statusSet(status, __func__, __FILE__, __LINE__, ret);
442 if(ret!=TPCERROR_OK) return ret;
443 tac->tacNr=csv->col_nr/5; tac->sampleNr=csv->row_nr-1;
445
446 /* This format has only frame middle time */
447 tac->isframe=0;
448
449 /* Read TAC names and units */
450 char *cptr, buf[1024];
451 ret=0;
452 for(int ri=0; ri<tac->tacNr; ri++) {
453 int ci=5*ri;
454 strlcpy(buf, csv->c[ci].content, 1024);
455 cptr=strcasestr(buf, " - Time"); if(cptr==NULL) {ret++; break;}
456 *cptr=(char)0; strlcpy(tac->c[ri].name, buf, MAX_TACNAME_LEN);
457 if(ri==0) { // Time unit only from the first column
458 cptr=strcasestr(csv->c[ci].content, "Time (");
459 if(cptr!=NULL) {
460 strlcpy(buf, cptr+6, 1024);
461 cptr=strchr(buf, ')'); if(cptr!=NULL) *cptr=(char)0;
462 tac->tunit=unitIdentify(buf);
463 }
464 }
465 if(ri==0) { // Concentration unit only from the first TAC
466 ci++;
467 cptr=strcasestr(csv->c[ci].content, " - ");
468 if(cptr!=NULL) {
469 strlcpy(buf, cptr+3, 1024);
470 cptr=strchr(buf, ','); if(cptr!=NULL) *cptr=(char)0;
471 tac->cunit=unitIdentify(buf);
472 }
473 }
474 }
475
476 /* Read one line at a time */
477 for(int si=0; si<tac->sampleNr; si++) {
478 ret=atofCheck(csvCell(csv, 1+si, 0), &tac->x[si]); if(ret) break;
479 for(int ri=0; ri<tac->tacNr; ri++) {
480 ret=atofCheck(csvCell(csv, 1+si, 1+5*ri), &tac->c[ri].y[si]); if(ret) break;
481 }
482 }
483
484
485 if(tac->tacNr<1) {
486 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
487 return TPCERROR_NO_DATA;
488 }
489
491
492 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
493 return(TPCERROR_OK);
494}
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155

Referenced by tacRead().

◆ tacReadMat()

int tacReadMat ( TAC * tac,
CSV * csv,
TPCSTATUS * status )
extern

Read Mat format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read.
statusPointer to status data; enter NULL if not needed

Definition at line 25 of file matio.c.

32 {
33 int verbose=0; if(status!=NULL) verbose=status->verbose;
34 if(tac==NULL) {
35 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
36 return TPCERROR_FAIL;
37 }
38 tacFree(tac);
39 if(csv==NULL || csv->row_nr<1 || csv->col_nr<1) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
41 return TPCERROR_NO_DATA;
42 }
43 if(verbose>0) printf("%s()\n", __func__);
44
45 int ret, n;
46
47 /* Check that CSV is of regular size */
48 if(!csvIsRegular(csv)) {
49 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
51 }
52 /* Column and row numbers must be at least 2 */
53 if(csv->col_nr<2 || csv->row_nr<2) {
54 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
56 }
57
58 /* Allocate memory for TAC data */
59 ret=tacAllocate(tac, csv->col_nr-1, csv->row_nr-1);
60 statusSet(status, __func__, __FILE__, __LINE__, ret);
61 if(ret!=TPCERROR_OK) return ret;
62 tac->tacNr=csv->row_nr-1; tac->sampleNr=csv->col_nr-1;
63 tac->isframe=1;
64
65 /* First cell may contain study number */
66 char *cptr=csvCell(csv, 0, 0);
67 if(cptr!=NULL && cptr[0] && strnlen(cptr, 20)<20)
68 tacSetHeaderStudynr(&tac->h, cptr);
69
70 /* Get sample times from the first line */
71 for(int j=0; j<tac->sampleNr; j++) {
72 cptr=csvCell(csv, 0, j+1); if(cptr==NULL) {ret++; break;}
73 n=strlen(cptr); if(n<3) {ret++; break;}
74 char *cptr2=strchr(cptr+1, '-'); if(cptr2!=NULL) {*cptr2=(char)0; cptr2++;}
75 tac->x1[j]=atofVerified(cptr);
76 tac->x2[j]=atofVerified(cptr2);
77 if(isnan(tac->x1[j]) || isnan(tac->x2[j])) {ret++; break;}
78 tac->x[j]=0.5*(tac->x1[j]+tac->x2[j]);
79 }
80 if(ret) {
81 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
83 }
84
85
86 /* Get region names from the first column */
87 ret=0;
88 for(int i=0; i<tac->tacNr; i++) {
89 cptr=csvCell(csv, i+1, 0); if(cptr==NULL) {ret++; break;}
90 n=strlen(cptr); if(n>2 && cptr[n-1]=='\'') {cptr[n-1]=(char)0; n--;}
91 if(n>1 && cptr[0]=='\'') {cptr++; n--;}
92 if(n>0) strlcpy(tac->c[i].name, cptr, MAX_TACNAME_LEN);
93 }
94 if(ret) {
95 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
97 }
98
99 /* Get concentrations */
100 n=0; ret=0;
101 for(int i=0; i<tac->tacNr && ret==0; i++) {
102 for(int j=0; j<tac->sampleNr; j++) {
103 cptr=csvCell(csv, i+1, j+1); if(cptr==NULL) {ret++; break;}
104 tac->c[i].y[j]=atofVerified(cptr); if(!isnan(tac->c[i].y[j])) n++;
105 }
106 }
107 if(ret) {
108 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
110 }
111 if(n<1) {
112 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
113 return TPCERROR_NO_DATA;
114 }
115
116
119
120 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
121 return(TPCERROR_OK);
122}

Referenced by tacRead().

◆ tacReadOldAllogg()

int tacReadOldAllogg ( TAC * tac,
IFT * hdr,
TPCSTATUS * status )
extern

Read Allogg #1 ABSS data from IFT struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacInit, tacRead, tacReadAllogg
Parameters
tacPointer to TAC struct, contents of which are to be written.
hdrPointer to IFT to read data from.
statusPointer to status data; enter NULL if not needed.

Definition at line 173 of file tacabss.c.

180 {
181 int verbose=0; if(status!=NULL) verbose=status->verbose;
182 if(tac==NULL) {
183 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
184 return TPCERROR_FAIL;
185 }
186 tacFree(tac);
187 if(hdr==NULL || hdr->keyNr<2) {
188 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
189 return TPCERROR_NO_DATA;
190 }
191 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
192
193 /* Check whether IFT even can contain Allogg 1 data */
194 int ii;
195 /* Find a specific key */
196 ii=iftFindKey(hdr, "Discriminators", 0);
197 if(ii<0) {
198 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
200 }
201
202 /* Find the measurement start date and time, and store for later use */
203 char scan_start_time[32];
204 int n, year, month, day, hour, min, sec;
205 char buf[128];
206 for(ii=0; ii<hdr->keyNr; ii++) {
207 if(strnlen(hdr->item[ii].key, 3)>0 || hdr->item[ii].value==NULL) continue;
208 if(strDateTimeValid(hdr->item[ii].value, scan_start_time)==0) {
209 n=sscanf(scan_start_time, "%d-%d-%d %d:%d:%d",
210 &year, &month, &day, &hour, &min, &sec);
211 } else {
212 n=strnlen(hdr->item[ii].value, 15);
213 if(n<8 || n>10) continue;
214 //printf("ii=%d '%s' '%s'\n", ii, hdr->item[ii].key, hdr->item[ii].value);
215 n=sscanf(hdr->item[ii].value, "%d-%d-%d", &year, &month, &day);
216 }
217 if(n==3 || n==6) break;
218 }
219 if(ii==hdr->keyNr) {
220 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
221 return(TPCERROR_NO_DATETIME);
222 }
223 //printf("found '%s' at ii=%d\n", hdr->item[ii].value, ii);
224
225 /* Find the measurement start time HHMMSS */
226 for(ii=0; ii<hdr->keyNr; ii++) {
227 if(strnlen(hdr->item[ii].key, 3)>0 || hdr->item[ii].value==NULL) continue;
228 //printf("ii=%d '%s' '%s'\n", ii, hdr->item[ii].key, hdr->item[ii].value);
229 if(strnlen(hdr->item[ii].value, 10)==6) break;
230 }
231 if(ii==hdr->keyNr) {
232 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
233 return(TPCERROR_NO_DATETIME);
234 }
235 //printf("found '%s' at ii=%d\n", hdr->item[ii].value, ii);
236 strlcpy(buf, hdr->item[ii].value, 128); buf[2]=(char)0; hour=atoi(buf);
237 strlcpy(buf, hdr->item[ii].value+2, 128); buf[2]=(char)0; min=atoi(buf);
238 strlcpy(buf, hdr->item[ii].value+4, 128); buf[2]=(char)0; sec=atoi(buf);
239
240 /* Make date and time string and set abss->startTime */
241 sprintf(scan_start_time, "%04d-%02d-%02d %02d:%02d:%02d",
242 year, month, day, hour, min, sec);
243 if(verbose>11) printf(" scan_start_time := %s\n", buf);
244
245 /* Sample data should start after this index */
246 /* Allocate memory for TAC data */
247 int ret;
248 ret=tacAllocate(tac, hdr->keyNr-ii, 2);
249 statusSet(status, __func__, __FILE__, __LINE__, ret);
250 if(ret!=TPCERROR_OK) return(ret);
251 tac->tacNr=2;
252 /* Set basic header information */
254 tac->isframe=1; // Allogg data always contains frame start and end times
255 tac->tunit=UNIT_SEC;
256 tac->cunit=UNIT_COUNTS;
257 /* Set TAC names into TAC struct */
258 strcpy(tac->c[0].name, "Singles");
259 strcpy(tac->c[1].name, "Coincidents");
260
261 /* Go through the lines, extracting sample data, and deleting data lines
262 from the header */
263 if(verbose>2) printf(" reading data lines...\n");
264 ii++;
265 int i=0;
266 while(ii<hdr->keyNr && i<tac->_sampleNr) {
267 if(strnlen(hdr->item[ii].key, 3)>0 || hdr->item[ii].value==NULL) {
268 iftDelete(hdr, ii); continue;}
269 if(hdr->item[ii].value[0]=='#') {iftDelete(hdr, ii); continue;}
270 n=sscanf(hdr->item[ii].value, "%lf %lf %lf",
271 &tac->x2[i], &tac->c[0].y[i], &tac->c[1].y[i]);
272 if(n==3) i++;
273 iftDelete(hdr, ii);
274 }
275 tac->sampleNr=i;
276 if(verbose>2) printf(" %d data line(s) read.\n", i);
277 if(i<1) {
278 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
279 return(TPCERROR_NO_DATA);
280 }
281
282 /* Calculate frame start and mid times */
283 for(i=1; i<tac->sampleNr; i++) {
284 tac->x1[i]=tac->x2[i-1];
285 tac->x[i]=0.5*(tac->x1[i]+tac->x2[i]);
286 }
287 /* first sample */
288 i=0;
289 if(tac->sampleNr>1) {
290 tac->x1[i]=tac->x2[i]-(tac->x2[i+1]-tac->x1[i+1]);
291 } else {
292 tac->x1[i]=0.0;
293 }
294 tac->x[i]=0.5*(tac->x1[i]+tac->x2[i]);
295
296 /* Set all header lines to comments */
297 for(ii=0; ii<hdr->keyNr; ii++) hdr->item[ii].comment=1;
298 /* Copy the header contents to TAC (deletes previous contents) */
299 (void)iftDuplicate(hdr, &tac->h);
300 tac->h.type=3;
301 /* Copy the start time to the TAC header */
302 (void)tacSetHeaderScanstarttime(&tac->h, scan_start_time);
303
304
305 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
306 return(TPCERROR_OK);
307}
int strDateTimeValid(const char *str, char *intdate)
Definition datetime.c:308

Referenced by tacRead().

◆ tacReadPMOD()

int tacReadPMOD ( TAC * tac,
CSV * csv,
IFT * hdr,
TPCSTATUS * status )
extern

Read PMOD format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWritePMOD, tacRead
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read; if it contains only one column, then it is assumed to represent the first y column and x column is not filled.
hdrPointer to possible header data, which, if available, is processed and copied to TAC too; enter NULL if not available.
statusPointer to status data; enter NULL if not needed.

Definition at line 146 of file pmodio.c.

157 {
158 int verbose=0; if(status!=NULL) verbose=status->verbose;
159 if(tac==NULL) {
160 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
161 return TPCERROR_FAIL;
162 }
163 if(verbose>0) printf("%s()\n", __func__);
164
165 tacFree(tac);
166
167 if(csv==NULL || csv->row_nr<2 || csv->col_nr<2) {
168 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
169 return TPCERROR_NO_DATA;
170 }
171
172 /* Check from the first field that data indeed is PMOD data */
173 int isframe=-1;
174 if(strncasecmp(csv->c[0].content, "Time", 4)==0) isframe=0;
175 else if(strncasecmp(csv->c[0].content, "Start", 5)==0 &&
176 strncasecmp(csv->c[1].content, "End", 3)==0) isframe=1;
177 if(isframe<0) {
178 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
180 }
181
182 /* Allocate memory for TAC data */
183 int n, ret;
184 n=csv->col_nr-1; if(isframe==1) n--;
185 if(n<1) {
186 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
188 }
189 ret=tacAllocate(tac, csv->row_nr-1, n);
190 statusSet(status, __func__, __FILE__, __LINE__, ret);
191 if(ret!=TPCERROR_OK) return ret;
192 tac->tacNr=n; tac->sampleNr=csv->row_nr-1;
193 tac->isframe=isframe;
194
195 /* Copy header to TAC structure */
196 iftDuplicate(hdr, &tac->h);
197
198 /* Get time unit from first field, inside parens */
199 char *cptr;
200 cptr=strchr(csv->c[0].content, '[');
201 if(cptr==NULL) { // Standard way of specifying units not found
202 cptr=strchr(csv->c[0].content, '('); // Non-standard way to specify units
203 if(cptr==NULL) { // Not even non-standard way used
204 tac->tunit=UNIT_UNKNOWN;
205 }
206 }
207 if(cptr!=NULL) {
208 char *tmp=strdup(cptr+1);
209 cptr=strrchr(tmp, ']'); if(cptr==NULL) cptr=strrchr(tmp, ')');
210 if(cptr!=NULL) *cptr='\0';
211 tac->tunit=unitIdentify(tmp);
212 free(tmp);
213 }
214
215 /* Get concentration unit from 2nd field, inside parens */
216 cptr=strchr(csv->c[1].content, '[');
217 if(cptr==NULL) {
218 tac->cunit=UNIT_UNKNOWN;
219 } else {
220 char *tmp=strdup(cptr+1);
221 cptr=strrchr(tmp, ']'); if(cptr!=NULL) *cptr='\0';
222 tac->cunit=unitIdentify(tmp);
223 free(tmp);
224 }
225
226 /* Read TAC names from the title line */
227 int i;
228 n=0; if(isframe==0) i=1; else i=2;
229 for(; i<csv->nr; i++) {
230 if(csv->c[i].row!=0 || n>=tac->tacNr) break;
231 /* Copy TAC name, removing unit if necessary */
232 if(strchr(csv->c[i].content, '[')) {
233 char *tmp=strdup(csv->c[i].content);
234 cptr=strchr(tmp, '['); *cptr='\0';
235 strlcpy(tac->c[n].name, tmp, MAX_TACNAME_LEN+1);
236 free(tmp);
237 } else {
238 strlcpy(tac->c[n].name, csv->c[i].content, MAX_TACNAME_LEN+1);
239 }
240 if(strcmp(tac->c[n].name, ".")==0) strcpy(tac->c[n].name, "");
241 n++;
242 }
243 if(n<1) {
244 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
246 }
247 tac->tacNr=n;
248 if(verbose>2) printf(" tacNr=%d\n sampleNr=%d\n", tac->tacNr, tac->sampleNr);
249
250 /* Copy x and y data from CSV into TAC structure */
251 int fi=0, ri=0, oknr=0;
252 ret=0;
253 double v;
254 for(i=0; i<csv->nr; i++) if(csv->c[i].row==1) break;
255 for(; i<csv->nr; i++) {
256 if(verbose>10) printf("i=%d\trow=%d\tcol=%d\n", i, csv->c[i].row, csv->c[i].col);
257 fi=csv->c[i].row-1; if(fi<0 || fi>=tac->sampleNr) {ret++; continue;}
258 if(csv->c[i].col<0) {ret++; continue;}
259 ri=csv->c[i].col-1; if(tac->isframe) ri--;
260 if(ri>=tac->tacNr) {ret++; continue;}
261 v=atofVerified(csv->c[i].content); if(isfinite(v)) oknr++;
262 if(verbose>10) printf(" -> fi=%d\tri=%d\t=\t%g\n", fi, ri, v);
263 if(ri<0) {
264 if(tac->isframe) {
265 if(ri==-2) tac->x1[fi]=v; else if(ri==-1) tac->x2[fi]=v;
266 } else tac->x[fi]=v;
267 } else tac->c[ri].y[fi]=v;
268 }
269 if(verbose>0 && ret>0) printf("%d error(s) in reading PMOD file format.\n", ret);
270 if(oknr<1) {
271 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
273 }
274 /* Set middle sample times when necessary */
275 if(tac->isframe)
276 for(fi=0; fi<tac->sampleNr; fi++)
277 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
278
279 /* Delete any empty columns (no name, no values) from the end */
280 int ci=tac->tacNr-1;
281 while(ci>0) {
282 if(strlen(tac->c[ci].name)>0) break;
283 int i;
284 for(i=0; i<tac->sampleNr; i++) if(isfinite(tac->c[ci].y[i])) break;
285 if(i<tac->sampleNr) break;
286 tac->tacNr--; ci--;
287 }
288
289 /* If units are not known, try to read units from header */
290 if(tac->cunit==UNIT_UNKNOWN) tacGetHeaderUnit(tac, NULL);
291 else tacSetHeaderUnit(&tac->h, UNIT_UNKNOWN);
292 if(tac->tunit==UNIT_UNKNOWN) tacGetHeaderTimeunit(tac, NULL);
294
295 /* Move column containing weights to its correct place in the structure */
296 if(tac->tacNr>1) { // except if file contains only one TAC
297 ret=tacWMove(tac, 1, status);
298 if(ret!=TPCERROR_OK && ret!=TPCERROR_NO_WEIGHTS) {
299 statusSet(status, __func__, __FILE__, __LINE__, ret);
300 return(ret);
301 }
302 }
303 if(tac->tacNr<1) {
304 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
305 return TPCERROR_NO_DATA;
306 }
307
309 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
310 return(TPCERROR_OK);
311}

Referenced by tacRead().

◆ tacReadQView()

int tacReadQView ( TAC * tac,
CSV * csv,
const int grouponly,
TPCSTATUS * status )
extern

Read QView format from CSV struct into TAC struct.

Note that QView TAC format does not contain frame times.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacRead, tacWrite, tacInit
Parameters
tacPointer to TAC structure, contents of which are to be written.
csvPointer to CSV from which data is read.
grouponlyRead TACs of all ROIs (0), or only group means (1).
statusPointer to status data; enter NULL if not needed.

Definition at line 27 of file qviewio.c.

36 {
37 int verbose=0; if(status!=NULL) verbose=status->verbose;
38 if(tac==NULL) {
39 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
40 return TPCERROR_FAIL;
41 }
42 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
43
44 tacFree(tac);
45
46 if(csv==NULL || csv->row_nr<2 || csv->col_nr<12) {
47 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
48 return TPCERROR_NO_DATA;
49 }
50
51 int ret=0;
52
53 /* Check from the first line (title) that data indeed is QView data */
54 if(strcasecmp(csv->c[0].content, "directory")!=0 ||
55 strcasecmp(csv->c[11].content, "group")!=0)
56 {
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
59 }
60
61 /* Find the highest frame number from parens in 'num' field */
62 int maxFrameNr=0;
63 {
64 int fn;
65 char *cptr, *cptr2;
66 for(int ri=1; ri<csv->row_nr; ri++) {
67 cptr=csvCell(csv, ri, 2); if(cptr==NULL) continue;
68 if(verbose>50) printf(" '%s'\n", cptr);
69 cptr2=strchr(cptr, '('); if(cptr2==NULL) continue;
70 fn=atoi(cptr2+1); if(fn>maxFrameNr) maxFrameNr=fn;
71 }
72 }
73 if(verbose>1) printf("maxFrameNr := %d\n", maxFrameNr);
74 if(maxFrameNr<1) {
75 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
77 }
78 /* Estimate the number of TACs */
79 int maxTacNr=(csv->row_nr-1)/maxFrameNr; // row_nr includes the title line
80 if(verbose>1) printf("maxTacNr := %d\n", maxTacNr);
81 if(maxFrameNr<1) {
82 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
84 }
85
86 /* Allocate memory for TAC data; and to be on the safe side, for one extra TAC */
87 ret=tacAllocate(tac, maxFrameNr, maxTacNr);
88 statusSet(status, __func__, __FILE__, __LINE__, ret);
89 if(ret!=TPCERROR_OK) return(ret);
90 tac->isframe=0;
91
92 /* Copy data from CSV into TAC structure */
93 ret=0;
94 for(int i=1; i<csv->row_nr; i++) {
95 /* Read the cells of this CSV line */
96 char *cnum, *cslice, *cmean, *cpixel, *cgroup;
97 cnum=csvCell(csv, i, 2); if(cnum==NULL) continue;
98 cslice=csvCell(csv, i, 3); if(cslice==NULL) continue;
99 cmean=csvCell(csv, i, 4); if(cmean==NULL) continue;
100 cpixel=csvCell(csv, i, 9); if(cpixel==NULL) continue;
101 cgroup=csvCell(csv, i, 11); if(cgroup==NULL) continue;
102 /* Get slice number; if missing, then this is group ROI */
103 int slice;
104 ret=atoiCheck(cslice, &slice);
105 if(ret!=0) {slice=-1; ret=0;}
106 /* If only group ROIs were requested, and this is not group */
107 if(slice>0 && grouponly!=0) continue;
108 /* Depending on previous, get frame number and group name, or frame and ROI number */
109 char *cptr=strchr(cnum, '('); if(cptr==NULL) continue;
110 int fn=atoi(cptr+1); if(fn<1 || fn>maxFrameNr) {ret=1; break;}
111 char tacname[MAX_TACNAME_LEN+1];
112 if(slice<1) { // this is group
113 /* Check group name, and use it as TAC name */
114 if(strnlen(cgroup, 2)<1) {ret=2; break;}
115 strlcpy(tacname, cgroup, MAX_TACNAME_LEN);
116 } else { // this is one roi at one image slice
117 /* Get ROI number */
118 int roinr=atoi(cnum); if(roinr<1) {ret=3; break;}
119 /* If group name exists, the use that and ROI number and slice number to construct TAC name */
120 if(strnlen(cgroup, 2)>0 && strnlen(cgroup, 2)<12) {
121 sprintf(tacname, "%s_roi%d__pl%d", cgroup, roinr, slice);
122 } else {
123 /* Otherwise use ROI number and slice number to construct TAC name */
124 sprintf(tacname, "roi%d__pl%d", roinr, slice);
125 }
126 }
127 /* Get the number of pixels */
128 int pxlnr;
129 ret=atoiCheck(cpixel, &pxlnr); if(ret) {pxlnr=0; ret=0;}
130 /* Get the ROI concentration */
131 double conc=atofVerified(cmean);
132 if(verbose>20) printf("tacname='%s' pxlnr=%d fn=%d conc=%g\n", tacname, pxlnr, fn, conc);
133 /* Determine the TAC index for this; first check if this TAC already is added */
134 int ri;
135 for(ri=0; ri<tac->tacNr; ri++) {
136 if(strcmp(tac->c[ri].name, tacname)==0 && doubleMatch(tac->c[ri].size, (double)pxlnr, 0.1))
137 break;
138 /* if TAC is not yet added, then ri will be set to the first free index */
139 }
140 /* check that ri is not too big */
141 if(ri>=maxTacNr) {ret=4; break;}
142 /* Put value in place */
143 tac->c[ri].y[fn-1]=conc;
144 /* If this was first encounter of this TAC, then set other info, and increase tacNr */
145 if(ri>=tac->tacNr) {
146 strcpy(tac->c[ri].name, tacname);
147 tac->c[ri].size=(double)pxlnr;
148 tac->tacNr++;
149 }
150 /* Increase also sampleNr when necessary */
151 if(fn>tac->sampleNr) tac->sampleNr=fn;
152 }
153 if(ret) {
154 if(verbose>1) printf(" error %d\n", ret);
155 tacFree(tac);
156 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
158 }
159
160 if(tac->sampleNr<1 || tac->tacNr<1) {
161 tacFree(tac);
162 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
164 }
165
166 for(int i=0; i<tac->sampleNr; i++) tac->x[i]=tac->x1[i]=tac->x2[i]=0.0;
167
169
170 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
171 return(TPCERROR_OK);
172}
int atoiCheck(const char *s, int *v)
Definition intutil.c:25

Referenced by tacRead().

◆ tacReadScanditronics()

int tacReadScanditronics ( TAC * tac,
IFT * hdr,
TPCSTATUS * status )
extern

Read Scanditronics ABSS data from IFT struct into TAC struct.

Two date-time strings will be written in header, scan_start_time containing the time of the first sample, and sampler_start_time containing the time given in ABSS file header.

Scanditronics ABSS format is almost identical to GEMS, but the headers and times are processed differently, hence separate functions. If function finds that provided data is actually from GEMS, it calls tacReadGEMS.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacInit, tacRead, tacReadGEMS, tacReadAllogg
Parameters
tacPointer to TAC struct, contents of which are to be written.
hdrPointer to IFT to read data from.
statusPointer to status data; enter NULL if not needed.

Definition at line 326 of file tacabss.c.

333 {
334 int verbose=0; if(status!=NULL) verbose=status->verbose;
335 if(tac==NULL) {
336 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
337 return TPCERROR_FAIL;
338 }
339 tacFree(tac);
340 if(hdr==NULL || hdr->keyNr<2) {
341 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
342 return TPCERROR_NO_DATA;
343 }
344 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
345
346 /* Check whether IFT contains Scanditronics (or GEMS) data */
347 int format;
348 if(iftSearchValue(hdr, "AUX", 0)<0 ||
349 iftSearchValue(hdr, "1st detector pair", 0)<0)
350 {
351 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
353 }
355
356 /* Find the measurement start date, possibly with time; Scanditronics
357 header is not required to contain the date and time, because those are
358 stored as the first column in the sample data. */
359 struct tm start_time; start_time.tm_mday=0;
360 int ii, n;
361 for(ii=0; ii<hdr->keyNr; ii++) {
362 if(strnlen(hdr->item[ii].key, 3)>0) continue;
363 n=strnlen(hdr->item[ii].value, 22);
364 if(n<10 || n>19) continue;
365 //printf("ii=%d '%s' '%s'\n", ii, hdr->item[ii].key, hdr->item[ii].value);
366 if(strDateTimeRead(hdr->item[ii].value, &start_time)!=0) {
367 /* Date and time not found, try only date */
368 if(strDateRead(hdr->item[ii].value, &start_time)!=0) continue;
369 }
370 break;
371 }
372 if(verbose>1) {
373 if(ii==hdr->keyNr) printf(" header does not contain date and time.\n");
374 else printf("found '%s' at ii=%d\n", hdr->item[ii].value, ii);
375 }
376
377 /* Sample data should start after this index */
378 /* Allocate memory for TAC data */
379 int ret;
380 ret=tacAllocate(tac, hdr->keyNr-ii, 7);
381 statusSet(status, __func__, __FILE__, __LINE__, ret);
382 if(ret!=TPCERROR_OK) return(ret);
383 tac->tacNr=7;
384 /* Set basic header information */
385 tac->format=format;
386 tac->isframe=1; // Data always contains frame start and end times
387 tac->tunit=UNIT_SEC;
388 tac->cunit=UNIT_COUNTS;
389 /* Set TAC names into TAC struct */
390 strcpy(tac->c[0].name, "Detector1-Coinc");
391 strcpy(tac->c[1].name, "Detector1-Singl1");
392 strcpy(tac->c[2].name, "Detector1-Singl2");
393 strcpy(tac->c[3].name, "Detector2-Coinc");
394 strcpy(tac->c[4].name, "Detector2-Singl1");
395 strcpy(tac->c[5].name, "Detector2-Singl2");
396 strcpy(tac->c[6].name, "AUX-counts");
397
398 /* Go through the lines, extracting sample data, and deleting data lines
399 from the header */
400 if(verbose>2) printf(" reading data lines...\n");
401 ii++;
402 int i=0, stopped=0;
403 double time_of_day, first_tod=0.0, time_since_start, meas_interval;
404 while(ii<hdr->keyNr && i<tac->_sampleNr) {
405 if(stopped) {iftDelete(hdr, ii); continue;}
406 if(strnlen(hdr->item[ii].key, 3)>0 || hdr->item[ii].value==NULL) {
407 iftDelete(hdr, ii); continue;}
408 if(hdr->item[ii].value[0]=='#') {iftDelete(hdr, ii); continue;}
409 //printf("ii=%d '%s'\n", ii, hdr->item[ii].value);
410 n=sscanf(hdr->item[ii].value, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
411 &time_of_day, &time_since_start, &meas_interval,
412 &tac->c[0].y[i], &tac->c[1].y[i], &tac->c[2].y[i], &tac->c[3].y[i],
413 &tac->c[4].y[i], &tac->c[5].y[i], &tac->c[6].y[i]);
414 //printf(" n=%d\n", n);
415 if(n!=10) {
416 /* first line may contain the protocol; keep it as comment */
417 if(i==0) {ii++; continue;}
418 /* Later occurrence is considered as an error */
419 stopped=1; iftDelete(hdr, ii); continue;
420 }
421 if(time_of_day==0.0 && meas_interval==0.0) {
422 stopped=1; iftDelete(hdr, ii); continue;}
423 if(i==0) first_tod=time_of_day;
424 tac->x1[i]=time_since_start;
425 tac->x2[i]=time_since_start+meas_interval;
426 i++;
427 iftDelete(hdr, ii);
428 }
429 tac->sampleNr=i;
430 if(verbose>2) printf(" %d data line(s) read.\n", i);
431 if(i<1) {
432 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
433 return(TPCERROR_NO_DATA);
434 }
435 if(verbose>4) printf(" first_tod := %.1lf\n", first_tod);
436
437 /* Calculate frame mid times */
438 for(i=0; i<tac->sampleNr; i++) tac->x[i]=0.5*(tac->x1[i]+tac->x2[i]);
439
440 /* Read scan start date and time from the first sample */
441 char scan_start_time[32], sampler_start_time[32];
442 time_t tim=(time_t)first_tod;
443 struct tm tmtim;
444 if(localtime_r(&tim, &tmtim)==NULL) {
445 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
446 return(TPCERROR_NO_DATETIME);
447 }
448 /* Check that also date is here; if not, this is actually GEMS data */
449 if(tmtim.tm_year<73) {
450 if(verbose>0) printf("data is not Scanditronics but GEMS format\n");
451 if(verbose>1 &&
452 strftime(scan_start_time, 32, "%Y-%m-%d %H:%M:%S", &tmtim)!=0) {
453 printf("first_sample_time := %s\n", scan_start_time);
454 }
455 tacFree(tac);
456 return(tacReadGEMS(tac, hdr, status));
457 }
458 /* Set scan_start_time based on the first sample */
459 if(strftime(scan_start_time, 32, "%Y-%m-%d %H:%M:%S", &tmtim)==0) {
460 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATETIME);
461 return(TPCERROR_NO_DATETIME);
462 }
463 /* Set sampler_start_time based on the header, or first sample, if header
464 does not contain the time */
465 if(start_time.tm_mday==0) { // header did not contain date and time
466 strcpy(sampler_start_time, scan_start_time);
467 } else {
468 /* If header contains just the date but not the time, then take the time
469 from samples */
470 if(start_time.tm_hour==0 && start_time.tm_min==0 && start_time.tm_sec==0) {
471 start_time.tm_hour=tmtim.tm_hour;
472 start_time.tm_min=tmtim.tm_min;
473 start_time.tm_sec=tmtim.tm_sec;
474 }
475 if(strftime(sampler_start_time, 32, "%Y-%m-%d %H:%M:%S", &start_time)==0)
476 strcpy(sampler_start_time, scan_start_time);
477 }
478
479
480 /* Set all header lines to comments */
481 for(ii=0; ii<hdr->keyNr; ii++) hdr->item[ii].comment=1;
482 /* Copy the header contents to TAC (deletes previous contents) */
483 (void)iftDuplicate(hdr, &tac->h);
484 tac->h.type=3;
485 /* Set the scan start time in the TAC header */
486 (void)tacSetHeaderScanstarttime(&tac->h, scan_start_time);
487 /* Set the sampler start time in the TAC header */
488 if(sampler_start_time[0])
489 (void)iftPut(&tac->h, "sampler_start_time", sampler_start_time, 1, NULL);
490 /* Copy study number to the TAC header */
491 ii=iftFindKey(hdr, "Patient", 0);
492 if(ii>=0 && strnlen(hdr->item[ii].value, 5)>0)
493 (void)tacSetHeaderStudynr(&tac->h, hdr->item[ii].value);
494
495 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
496 return(TPCERROR_OK);
497}
struct tm * localtime_r(const time_t *t, struct tm *tm)
Convert time_t to local time in struct tm.
Definition datetime.c:54

Referenced by tacRead(), and tacReadGEMS().

◆ tacReadSIF()

int tacReadSIF ( TAC * tac,
CSV * csv,
IFT * hdr,
TPCSTATUS * status )
extern

Read SIF from CSV structure into TAC structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWriteSIF, tacRead, csvRead, TAC, CSV, tacWCopy, tacSetWeights
Parameters
tacPointer to TAC structure, contents of which are to be filled here. tacNr will always be set to 2, even if count data is not available. Trues will be saved or computed into a non-standard 3rd column, which is not included in tacNr, even if column is found in CSV.
csvPointer to CSV from which SIF data is read.
hdrPointer to possible header data, which, if available, if processed and copied to TAC too; enter NULL if not available.
statusPointer to status data; enter NULL if not needed.

Definition at line 129 of file sifio.c.

143 {
144 int verbose=0; if(status!=NULL) verbose=status->verbose;
145 if(verbose>0) {printf("%s(tac, csv, hdr, status)\n", __func__); fflush(stdout);}
146
147
148
149 if(tac==NULL) {
150 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
151 return TPCERROR_FAIL;
152 }
153 tacFree(tac);
154 if(csv==NULL || csv->row_nr<1 || csv->col_nr<1) {
155 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
156 return TPCERROR_NO_DATA;
157 }
158
159 /* Check whether CSV file even can contain SIF data */
160 if(verbose>2) {printf(" checking that CSV contains SIF\n"); fflush(stdout);}
161 int title_item_nr;
162 title_item_nr=csvRowLength(csv, 0);
163 if(title_item_nr==1 && csv->separator!=' ') {
164 if(verbose>1) printf("title_item_nr := %d\n", title_item_nr);
165 if(verbose>2) {printf(" SIF has not space character as column separator; fixing title line\n");}
166 //printf("content='%s'\n", csv->c[0].content);
167 char s1[128]; int n=0;
168 int len=strTokenNCpy(csv->c[0].content, " ,;\t", n+1, s1, 128);
169 if(!(len>0)) {
170 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
172 }
173 n++; //printf("n=%d s1='%s'\n", n, s1);
174 char s[128];
175 while(strTokenNCpy(csv->c[0].content, " ,;\t", n+1, s, 128)>0) {
176 n++; //printf("n=%d s='%s'\n", n, s);
177 if(n==2) csvPutString(csv, s, 1); else csvPutString(csv, s, 0);
178 }
179 if(n>csv->col_nr) csv->col_nr=n;
180 strcpy(csv->c[0].content, s1);
181 int j=1;
182 for(int i=1+csv->nr-n; i<csv->nr; i++) {
183 //printf("content[%d]='%s'\n", i, csv->c[i].content);
184 csv->c[i].row=0; csv->c[i].col=j; j++;
185 }
186 csv->row_nr--;
187 csvReorg(csv, NULL);
188 title_item_nr=csvRowLength(csv, 0);
189 //csvList(csv, stdout);
190 }
191
192 if(csv->row_nr<2 || title_item_nr<5 ) {
193 if(verbose>1) {printf("title_item_nr := %d\n", title_item_nr); csvList(csv, stdout);}
194 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
196 }
197
198 int ret;
199
200 /* Allocate memory for TAC data */
201 if(verbose>2) {printf(" allocating memory\n"); fflush(stdout);}
202 ret=tacAllocate(tac, csv->row_nr-1, 3);
203 statusSet(status, __func__, __FILE__, __LINE__, ret);
204 if(ret!=TPCERROR_OK) return ret;
205 /* Set initial SIF data size */
206 tac->tacNr=2;
207 tac->sampleNr=csv->row_nr-1;
208 /* Set basic header information */
210 tac->isframe=1; // SIF always contains frame start and end times
211 tac->tunit=UNIT_SEC;
212 tac->cunit=UNIT_COUNTS;
213
214 /* Set SIF compatible titles into TAC struct */
215 strcpy(tac->c[0].name, "Prompts");
216 strcpy(tac->c[1].name, "Randoms");
217 strcpy(tac->c[2].name, "Trues"); // computed, not saved
218
219 /* Read SIF title line */
220 if(verbose>2) {printf(" reading SIF header\n"); fflush(stdout);}
221 /* scan start time */
222 char sif_scan_start_time[20];
223 ret=0;
224 if(strlen(csv->c[0].content)<11 && strlen(csv->c[1].content)<9) {
225 char temp[20];
226 strcpy(temp, csv->c[0].content); strcat(temp, " ");
227 strcat(temp, csv->c[1].content);
228 if(verbose>4) printf(" datetime := '%s'\n", temp);
229 ret=strDateTimeValid(temp, sif_scan_start_time);
230 if(ret!=0) {
231 if(verbose>1) printf(" invalid SIF date/time (%d).\n", ret);
232 else if(verbose>0) printf(" invalid SIF date/time.\n");
233 if(ret<0) ret=0; // its common that SIF time is 1/1/1970 etc
234 }
235 } else ret=1;
236 if(ret!=0) {
237 if(verbose>2) {
238 printf(" cell0 := '%s'\n", csv->c[0].content);
239 printf(" cell1 := '%s'\n", csv->c[1].content);
240 }
241 tacFree(tac);
242 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
244 }
245 if(verbose>1) printf("sif_scan_start_time := %s\n", sif_scan_start_time);
246 /* Nr of frames */
247 int frameNr;
248 frameNr=atoi(csv->c[2].content);
249 if(verbose>1) printf("sif_frame_nr := %d\n", frameNr);
250 if(frameNr<1 || frameNr>tac->_sampleNr) {
251 tacFree(tac);
252 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
254 }
255 tac->sampleNr=frameNr;
256 /* Nr of columns */
257 int colNr;
258 colNr=atoi(csv->c[3].content);
259 if(verbose>1) printf("sif_col_nr := %d\n", colNr);
260 if(colNr<2) {
261 tacFree(tac);
262 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
264 }
265 /* SIF version; forget about it */
266 /* Study number; may be missing */
267 char studynr[MAX_STUDYNR_LEN+1]; studynr[0]='\0';
268 if(title_item_nr>5) {
269 strlcpy(studynr, csv->c[5].content, MAX_STUDYNR_LEN+1);
270 if(strcmp(studynr, ".")==0) strcpy(studynr, "");
271 if(verbose>2) printf("sif_studynr := %s\n", studynr);
272 }
273 /* Isotope; may be missing */
274 char isotope[MAX_ISOTOPE_LEN+1]; strcpy(isotope, "unknown");
275 if(title_item_nr>6) {
276 int isocode;
277 isocode=isotopeIdentify(csv->c[6].content);
278 strcpy(isotope, isotopeName(isocode));
279 }
280 if(verbose>1) printf("sif_isotope := %s\n", isotope);
281
282 /* Read SIF frames */
283 if(verbose>2) {printf(" reading SIF frames\n"); fflush(stdout);}
284 ret=0;
285 int fi, ri, ci;
286 double v;
287 for(fi=0; fi<tac->sampleNr; fi++) {
288 ri=fi+1;
289 /* frame start time */
290 ci=0; v=atofVerified(csvCell(csv, ri, ci));
291 if(isnan(v)) {ret++; break;} else tac->x1[fi]=v;
292 /* frame end time */
293 ci=1; v=atofVerified(csvCell(csv, ri, ci));
294 if(isnan(v)) {ret++; break;} else tac->x2[fi]=v;
295 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
296 /* Prompts, randoms, and trues, maybe missing */
297 tac->c[0].y[fi]=0.0;
298 tac->c[1].y[fi]=0.0;
299 tac->c[2].y[fi]=0.0;
300 if(colNr<3) continue;
301 /* so prompts should be there */
302 ci=2; v=atofVerified(csvCell(csv, ri, ci));
303 if(isnan(v)) {ret++; break;} else tac->c[0].y[fi]=v;
304 if(colNr<4) continue;
305 /* so randoms should be there */
306 ci=3; v=atofVerified(csvCell(csv, ri, ci));
307 if(isnan(v)) {ret++; break;} else tac->c[1].y[fi]=v;
308 /* If trues not available, then trues=prompts-randoms */
309 if(colNr<5) {
310 tac->c[2].y[fi]=tac->c[0].y[fi]-tac->c[1].y[fi];
311 continue;
312 }
313 /* so trues should be there */
314 ci=4; v=atofVerified(csvCell(csv, ri, ci));
315 if(isnan(v)) {ret++; break;} else tac->c[2].y[fi]=v;
316 }
317 if(ret!=0) {
318 tacFree(tac);
319 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
321 }
322
323 /* Set TAC header */
324 /* Isotope */
325 if(isotopeIdentify(isotope)<=0 && hdr!=NULL) {
326 /* SIF did not contain valid isotope code, get it from argument hdr */
327 ret=tacGetHeaderIsotope(hdr, isotope, NULL);
328 /* and delete it from hdr */
329 if(ret==TPCERROR_OK) tacSetHeaderIsotope(hdr, NULL);
330 }
332 /* Studynumber */
333 if(!studynr[0] && hdr!=NULL) {
334 /* SIF did not contain studynumber, get it from argument hdr */
335 ret=tacGetHeaderStudynr(hdr, studynr, NULL);
336 /* and delete it from hdr */
337 if(ret==TPCERROR_OK) {
338 if(verbose>2) printf("sifhdr_studynr := %s\n", studynr);
339 tacSetHeaderStudynr(hdr, NULL);
340 }
341 }
342 if(studynr[0]) {
343 if(verbose>3) printf("setting TAC studynr to '%s'\n", studynr);
344 tacSetHeaderStudynr(&tac->h, studynr);
345 }
346 /* Scan start time */
347 if(strDateTimeValid(sif_scan_start_time, NULL)<0 && hdr!=NULL) {
348 /* SIF did not contain valid scan start time, get it from argument hdr */
349 ret=tacGetHeaderScanstarttime(hdr, sif_scan_start_time, NULL);
350 /* and delete it from hdr */
351 if(ret==TPCERROR_OK) tacSetHeaderScanstarttime(hdr, NULL);
352 }
353 if(strDateTimeValid(sif_scan_start_time, NULL)==0)
354 tacSetHeaderScanstarttime(&tac->h, sif_scan_start_time);
355
356 if(verbose>4) {printf(" %s() out\n", __func__); fflush(stdout);}
357 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
358 return(TPCERROR_OK);
359}
int csvPutString(CSV *csv, const char *s, int newline)
Definition csv.c:144
int csvReorg(CSV *d, TPCSTATUS *status)
Definition csv.c:503
int csvList(CSV *csv, FILE *fp)
Definition csvio.c:27
int strTokenNCpy(const char *s1, const char *s2, int i, char *s3, int count)
Definition stringext.c:53
int tacGetHeaderScanstarttime(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:372
int tacSetHeaderIsotope(IFT *h, const char *s)
Definition tacift.c:341

Referenced by tacRead().

◆ tacReadSimple()

int tacReadSimple ( TAC * tac,
CSV * csv,
IFT * hdr,
TPCSTATUS * status )
extern

Read simple format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWriteSimple, tacReadCSV, tacReadMat, tacRead
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read; if it contains only one column, then it is assumed to represent the first y column and x column is not filled.
hdrPointer to possible header data, which, if available, is processed and copied to TAC too; enter NULL if not available.
statusPointer to status data; enter NULL if not needed.

Definition at line 97 of file simpleio.c.

108 {
109 int verbose=0; if(status!=NULL) verbose=status->verbose;
110 if(tac==NULL) {
111 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
112 return TPCERROR_FAIL;
113 }
114 tacFree(tac);
115 if(csv==NULL || csv->row_nr<1 || csv->col_nr<1) {
116 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
117 return TPCERROR_NO_DATA;
118 }
119 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
120
121 /* Check that each row has same number of columns */
122 if(verbose>1) {printf(" verifying CSV regularity\n"); fflush(stdout);}
123 if(!csvIsRegular(csv)) {
124 if(verbose>2) {
125 printf("\n <-- CSV contents (irregular) ---\n");
126 csvWrite(csv, 0, stdout, NULL);
127 printf("\n ------------------------------->\n");
128 printf("col_nr := %d\n", csv->col_nr);
129 printf("row_nr := %d\n", csv->row_nr);
130 if(verbose>3) {
131 for(int i=0; i<csv->row_nr; i++)
132 printf("columns_on_row[%d] := %d\n", 1+i, csvRowLength(csv, i));
133 fflush(stdout);
134 }
135 }
136 /* try to make it regular by removing empty columns from the right */
137 if(verbose>1) {printf(" trying to make it regular\n"); fflush(stdout);}
138 if(csvTrimRight(csv) || !csvIsRegular(csv)) {
139 if(verbose>1) {
140 printf("\n <-- CSV contents (still irregular) ---\n");
141 csvWrite(csv, 0, stdout, NULL);
142 printf("\n ------------------------------->\n");
143 printf("col_nr := %d\n", csv->col_nr);
144 printf("row_nr := %d\n", csv->row_nr);
145 if(verbose>5) {
146 for(int i=0; i<csv->row_nr; i++)
147 printf("columns_on_row[%d] := %d\n", 1+i, csvRowLength(csv, i));
148 fflush(stdout);
149 }
150 }
151 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
153 }
154 }
155
156 /* Check if first line contains fields starting with letter, suggesting title line */
157 int withTitle=0;
158 for(int i=0; i<csv->col_nr; i++) {
159 char *c=csvCell(csv, 0, i);
160 if(c!=NULL && isalpha(c[0])) withTitle++;
161 }
162 if(verbose>1 && withTitle>0) {printf("CSV seems to have title line.\n"); fflush(stdout);}
163 if(withTitle>0) withTitle=1;
164
165 int ret, n, m;
166
167 /* Allocate memory for TAC data */
168 if(verbose>2) {printf(" allocating memory for TAC data\n"); fflush(stdout);}
169 n=csv->col_nr; if(n>1) n--;
170 m=csv->row_nr-withTitle;
171 ret=tacAllocate(tac, m, n);
172 statusSet(status, __func__, __FILE__, __LINE__, ret); if(ret!=TPCERROR_OK) return ret;
173 tac->tacNr=n; tac->sampleNr=m;
174 tac->isframe=0;
175 if(verbose>2) {
176 printf(" tacNr := %d\n", tac->tacNr);
177 printf(" sampleNr := %d\n", tac->sampleNr);
178 fflush(stdout);
179 }
180
181
182 /* Copy title line contents as TAC names */
183 if(withTitle) {
184 if(verbose>2) {printf(" copying TAC names from the title columns\n"); fflush(stdout);}
185 char *c;
186 for(int ri=0; ri<tac->tacNr; ri++) {
187 c=csvCell(csv, 0, 1+ri);
188 if(c!=NULL) strlcpy(tac->c[ri].name, c, MAX_TACNAME_LEN+1);
189 }
190 }
191
192 /* Copy data from CSV into TAC struct */
193 if(verbose>2) {printf(" copying data from CSV to TAC\n"); fflush(stdout);}
194 int fi, ri, oknr=0;
195 char *c;
196 for(fi=0; fi<tac->sampleNr; fi++) {
197 /* Get the x value from the first column */
198 c=csvCell(csv, fi+withTitle, 0);
199 tac->x[fi]=atofVerified(c); if(!isnan(tac->x[fi])) oknr++;
200 /* Get the y values from the next columns */
201 for(ri=0; ri<tac->tacNr; ri++) {
202 c=csvCell(csv, fi+withTitle, 1+ri);
203 tac->c[ri].y[fi]=atofVerified(c); if(!isnan(tac->c[ri].y[fi])) oknr++;
204 }
205 }
206 if(oknr<1) {
207 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
209 }
210
211 /* Copy header to TAC struct */
212 iftDuplicate(hdr, &tac->h);
213
214 /* Try to read units from header */
215 tacGetHeaderUnit(tac, NULL);
216 tacGetHeaderTimeunit(tac, NULL);
217
220
221 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
222 return(TPCERROR_OK);
223}
int csvTrimRight(CSV *csv)
Definition csv.c:321

Referenced by tacRead().

◆ tacSampleXRange()

int tacSampleXRange ( TAC * d,
double * xmin,
double * xmax )
extern

Get the range of x values (times) in TAC structure.

Data is not modified. Data does not need to be sorted. Data can contain NaNs, and x values are omitted if no finite y values exist for that x. If data contains sample weights, samples with zero weight are not included.

See also
tacXRange, tacMinX, tacIsX, tacExtractRange, tacCorrectFrameOverlap, tacYRange, tacSetWeights, tacWSampleNr
Author
Vesa Oikonen
Returns
Returns <>0 in case of failure.
Parameters
dPointer to TAC structure; not modified.
xminPointer to variable for min x value (NULL if not needed).
xmaxPointer to variable for max x value (NULL if not needed).

Definition at line 162 of file tacx.c.

169 {
170 if(xmin!=NULL) *xmin=nan("");
171 if(xmax!=NULL) *xmax=nan("");
172 /* Check the data */
173 if(d==NULL || d->sampleNr<1) return(1);
174 /* Find the min and max time */
175 double mi, ma, *xi, *xa;
176 mi=ma=nan("");
177 if(d->isframe) {xi=d->x1; xa=d->x2;} else xi=xa=d->x;
178 int weighted=tacIsWeighted(d);
179 int i, j;
180 for(i=0; i<d->sampleNr; i++) {
181 if(!isfinite(xi[i]) || !isfinite(xa[i])) continue;
182 if(weighted && !(d->w[i]>0.0)) continue;
183 for(j=0; j<d->tacNr; j++) if(isfinite(d->c[j].y[i])) break;
184 if(j==d->tacNr) continue;
185 if(isnan(mi) || isnan(ma)) {mi=xi[i]; ma=xa[i]; continue;}
186 if(xi[i]<mi) mi=xi[i]; else if(xa[i]>ma) ma=xa[i];
187 }
188 if(xmin!=NULL) *xmin=mi;
189 if(xmax!=NULL) *xmax=ma;
190 if(!isfinite(mi) || !isfinite(ma)) return(2);
191 return(0);
192}

Referenced by mtgaPlotSVG(), tacPlotFitSVG(), tacPlotHistogramSVG(), and tacPlotLineSVG().

◆ tacSelectBestReference()

int tacSelectBestReference ( TAC * d)
extern

Select the best guess of reference region in case that several TACs were matching with tacSelectTACs().

Returns
the index of best region, or <0 in case of an error.
Author
Vesa Oikonen
See also
tacSelectTACs, tacSelectedTACs, tacEnsureNames, roinameMatch, tacIndividualNames
Parameters
dPointer to TAC structure, after using tacSelectTACs().

Definition at line 139 of file tacselect.c.

142 {
143 int ri, len, min_len, i;
144
145 if(d==NULL || d->tacNr<1) return -1;
146 if(tacSelectedTACs(d)<1) return -2;
147 for(ri=0, i=-1, min_len=9999; ri<d->tacNr; ri++) {
148 if(d->c[ri].sw==0) continue;
149 len=strlen(d->c[ri].name);
150 if(strcasestr(d->c[ri].name, "ALL")!=NULL) len-=4;
151 if(strcasestr(d->c[ri].name, "AVG")!=NULL) len-=4;
152 if(strcasestr(d->c[ri].name, "MEAN")!=NULL) len-=5;
153 if(len<min_len) {min_len=len; i=ri;}
154 }
155 if(i<0) return -2; else return i;
156}
int tacSelectedTACs(TAC *d)
Definition tacselect.c:103

Referenced by tacReadReference().

◆ tacSelectedTACs()

int tacSelectedTACs ( TAC * d)
extern

Get the number of selected TACs (sw!=0) in TAC structure.

Returns
the number of selected TACs.
Author
Vesa Oikonen
See also
tacSelectTACs, tacSelectBestReference, roinameMatch, tacIndividualNames
Parameters
dPointer to TAC data.

Definition at line 103 of file tacselect.c.

106 {
107 int ri, n;
108
109 /* Check the input */
110 if(d==NULL || d->tacNr<1) return(0);
111 /* Check each VOI */
112 for(ri=n=0; ri<d->tacNr; ri++) if(d->c[ri].sw!=0) n++;
113 return(n);
114}

Referenced by tacSelectBestReference().

◆ tacSelectTACs()

int tacSelectTACs ( TAC * d,
const char * region_name,
int reset,
TPCSTATUS * status )
extern

Select the TAC(s) that have matching ID name or number.

Returns
the number of newly selected VOIs, or <=0 in case of an error.
Author
Vesa Oikonen
See also
tacSelectedTACs, tacSelectBestReference, roinameMatch, tacIndividualNames
Parameters
dPointer to TAC structure.
region_nameName or TAC number (as string, starting from 1) which is searched; string can be inside quotation marks. Enter NULL to select all TACs, or empty string to select TACs with empty name (which really should not exist).
reset1=Non-matching VOIs are deselected, 0=Old selections are preserved.
statusPointer to status data; enter NULL if not needed.

Definition at line 24 of file tacselect.c.

35 {
36 int verbose=0; if(status!=NULL) verbose=status->verbose;
37 if(verbose>0) printf("%s()\n", __func__);
38 /* Check that required data exists */
39 if(d==NULL || d->tacNr<1) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
41 return 0;
42 }
43
44 int ri, len, match_nr=0;
45
46 /* Check if NULL was given as tac name; if, then select all */
47 if(region_name==NULL) {
48 for(ri=0; ri<d->tacNr; ri++) d->c[ri].sw=1;
49 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
50 return(d->tacNr);
51 }
52
53 /* Reset all selections if required */
54 if(reset!=0) for(ri=0; ri<d->tacNr; ri++) d->c[ri].sw=0;
55
56 /* Remove any quotation marks from name */
57 len=strlen(region_name);
58 char local_name[len+1];
59 if(len>1) len=strncpyClean(local_name, region_name, len+1);
60 else strcpy(local_name, region_name);
61
62 /* If tac name is empty, then select all tacs with missing names */
63 if(len<1) {
64 for(ri=0; ri<d->tacNr; ri++) {
65 if(strlen(d->c[ri].name)==0) {d->c[ri].sw=1; match_nr++; continue;}
66 /* maybe here should also be checked for names consisting of only space characters */
67 }
68 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
69 return(match_nr);
70 }
71
72 /* Check each TAC name */
73 for(ri=0; ri<d->tacNr; ri++) {
74 /* does the name match? */
75 if(roinameMatch(d->c[ri].name, local_name, status)!=0) {
76 d->c[ri].sw=1; match_nr++; continue;
77 }
78 }
79 /* If at least one match was found, then we are ready */
80 if(match_nr>0) {
81 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
82 return(match_nr);
83 }
84
85 /* Next try VOI number, if region_name is suitable */
86 int n;
87 if(sscanf(local_name, "%d", &n)!=1 || n<1 || n>d->tacNr) {
88 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
89 return(0);
90 }
91 d->c[n-1].sw=1; match_nr=1;
92 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
93 return(match_nr);
94}
int roinameMatch(const char *roiname, const char *test_str, TPCSTATUS *status)
Definition roiname.c:183
int strncpyClean(char *s1, const char *s2, int maxlen)
Definition stringext.c:321

Referenced by tacReadReference().

◆ tacSetHeaderDecayCorrection()

int tacSetHeaderDecayCorrection ( IFT * h,
decaycorrection dc )

Set the status of decay correction in TAC structure header. Any previous status is deleted.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacGetHeaderDecayCorrection, tacSetHeaderIsotope, tacDecayCorrection
Parameters
hPointer to TAC header structure.
dcStatus of decay correction: DECAY_UNKNOWN, DECAY_NOTCORRECTED, or DECAY_CORRECTED.

Definition at line 578 of file tacift.c.

583 {
584 if(h==NULL) return TPCERROR_FAIL;
585
586 /* Find and delete previous status */
587 int i=0, start=0;
588 while(1) {
589 i=iftFindKey(h, "decay_correction", start);
590 if(i<0) i=iftFindKey(h, "decay correction", start);
591 if(i<0) break;
592 iftDelete(h, i); if(i>start) start=i;
593 }
594
595 /* Create new key and value */
596 if(dc==DECAY_CORRECTED)
597 return (iftPut(h, "decay_correction", "yes", (char)1, NULL));
598 else if(dc==DECAY_NOTCORRECTED)
599 return (iftPut(h, "decay_correction", "no", (char)1, NULL));
600
601 /* If unknown, then just return */
602 return(TPCERROR_OK);
603}

Referenced by tacDecayCorrection().

◆ tacSetHeaderInjectiontime()

int tacSetHeaderInjectiontime ( IFT * h,
const char * s )
extern

Set injection time in TAC structure header. Any previous injection time items are deleted.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacGetHeaderInjectiontime, tacGetHeaderScanstarttime, tacDecayCorrection, tacSetHeaderIsotope
Author
Vesa Oikonen
Parameters
hPointer to TAC header structure.
sPointer to string containing the injection time in international format YYYY-MM-DD hh:mm:ss ; enter NULL or "" if you only want to delete it in header.

Definition at line 515 of file tacift.c.

521 {
522 if(h==NULL) return TPCERROR_FAIL;
523
524 /* Find and delete previous scan start time(s) */
525 int i=0, start=0;
526 while(1) {
527 i=iftFindKey(h, "injection_time", start);
528 if(i<0) i=iftFindKey(h, "injection time", start);
529 if(i<0) i=iftFindKey(h, "injectiontime", start);
530 if(i<0) break;
531 iftDelete(h, i); if(i>start) start=i;
532 }
533
534 /* If new scan start time is empty, then just return */
535 if(s==NULL || *s=='\0') return(TPCERROR_OK);
536
537 /* Otherwise create new key and value */
538 return (iftPut(h, "injection_time", s, (char)1, NULL));
539}

◆ tacSetHeaderIsotope()

int tacSetHeaderIsotope ( IFT * h,
const char * s )
extern

Set isotope in TAC structure header. Any previous isotope items are deleted.

See also
tacSetIsotope
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
hPointer to TAC header structure.
sPointer to string containing the isotope; enter NULL or "" if you only want to delete isotope in header.

Definition at line 341 of file tacift.c.

347 {
348 if(h==NULL) return TPCERROR_FAIL;
349
350 /* Find and delete previous isotope(s) */
351 int i=0, start=0;
352 while(1) {
353 i=iftFindKey(h, "isotope", start);
354 if(i<0) break;
355 iftDelete(h, i); if(i>start) start=i;
356 }
357
358 /* If new isotope is empty, then just return */
359 if(s==NULL || *s=='\0') return(TPCERROR_OK);
360
361 /* Otherwise create new key and value */
362 return (iftPut(h, "isotope", s, (char)1, NULL));
363}

Referenced by tacReadSIF(), and tacSetIsotope().

◆ tacSetHeaderScanstarttime()

int tacSetHeaderScanstarttime ( IFT * h,
const char * s )
extern

Set scan start time in TAC structure header. Any previous scan start items are deleted.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacGetHeaderScanstarttime, tacSetHeaderInjectiontime, tacDecayCorrection, tacSetHeaderIsotope
Author
Vesa Oikonen
Parameters
hPointer to TAC header structure.
sPointer to string containing the scan start time in international format YYYY-MM-DD hh:mm:ss ; enter NULL or "" if you only want to delete it in header.

Definition at line 427 of file tacift.c.

433 {
434 if(h==NULL) return TPCERROR_FAIL;
435
436 /* Find and delete previous scan start time(s) */
437 int i=0, start=0;
438 while(1) {
439 i=iftFindKey(h, "scan_start_time", start);
440 if(i<0) i=iftFindKey(h, "scan start time", start);
441 if(i<0) i=iftFindKey(h, "scan_start", start);
442 if(i<0) i=iftFindKey(h, "scan start", start);
443 if(i<0) i=iftFindKey(h, "scantime", start);
444 if(i<0) break;
445 iftDelete(h, i); if(i>start) start=i;
446 }
447
448 /* If new scan start time is empty, then just return */
449 if(s==NULL || *s=='\0') return(TPCERROR_OK);
450
451 /* Otherwise create new key and value */
452 return (iftPut(h, "scan_start_time", s, (char)1, NULL));
453}

Referenced by imgToSIF(), tacReadAllogg(), tacReadGEMS(), tacReadOldAllogg(), tacReadScanditronics(), and tacReadSIF().

◆ tacSetHeaderStudynr()

int tacSetHeaderStudynr ( IFT * h,
const char * s )
extern

Set study number in TAC struct header. Any previous studynr items are deleted.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacGetHeaderStudyNr, parSetStudyNr, studynrFromFilename
Parameters
hPointer to TAC header struct
sPointer to string containing the study number; enter NULL or "" if you only want to delete studynr in header

Definition at line 79 of file tacift.c.

85 {
86 if(h==NULL) return TPCERROR_FAIL;
87
88 /* Find and delete previous studynr(s) */
89 int i=0, start=0;
90 while(1) {
91 i=iftFindKey(h, "studynr", start);
92 if(i<0) i=iftFindKey(h, "study_number", start);
93 if(i<0) i=iftFindKey(h, "study number", start);
94 if(i<0) break;
95 iftDelete(h, i); if(i>start) start=i;
96 }
97
98 /* If new studynr is empty, then just return */
99 if(s==NULL || *s=='\0') return(TPCERROR_OK);
100
101 /* Otherwise create new key and value */
102 return (iftPut(h, "studynr", s, (char)1, NULL));
103}

Referenced by imgToSIF(), tacRead(), tacReadAllogg(), tacReadCSV(), tacReadDFT(), tacReadGEMS(), tacReadMat(), tacReadScanditronics(), tacReadSIF(), and tacWriteDFT().

◆ tacSetHeaderTimeunit()

int tacSetHeaderTimeunit ( IFT * h,
int u )
extern

Set time (x) unit in TAC struct header. Any previous x units are deleted.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
hPointer to TAC header struct
uUnit enum

Definition at line 201 of file tacift.c.

206 {
207 if(h==NULL) return TPCERROR_FAIL;
208
209 /* Find and delete previous time unit(s) */
210 int i=0, start=0;
211 while(1) {
212 i=iftFindKey(h, "timeunit", start);
213 if(i<0) i=iftFindKey(h, "time_unit", start);
214 if(i<0) i=iftFindKey(h, "time unit", start);
215 if(i<0) i=iftFindKey(h, "time units", start);
216 if(i<0) break;
217 iftDelete(h, i); if(i>start) start=i;
218 }
219
220 /* If new unit is unknown, then just return */
221 if(u<=UNIT_UNKNOWN || u>=UNIT_LAST) return(TPCERROR_OK);
222
223 /* Otherwise create new key and value */
224 return (iftPut(h, "timeunit", unitName(u), (char)1, NULL));
225}
@ UNIT_LAST
end of list

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

◆ tacSetHeaderUnit()

int tacSetHeaderUnit ( IFT * h,
int u )
extern

Set concentration (y) unit in TAC struct header. Any previous y unit items are deleted.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
hPointer to TAC header struct
uUnit enum

Definition at line 112 of file tacift.c.

117 {
118 if(h==NULL) return TPCERROR_FAIL;
119
120 /* Find and delete previous unit(s) */
121 int i=0, start=0;
122 while(1) {
123 i=iftFindKey(h, "unit", start);
124 if(i<0) i=iftFindKey(h, "calibration_unit", start);
125 if(i<0) i=iftFindKey(h, "activity_units", start);
126 if(i<0) i=iftFindKey(h, "activity units", start);
127 if(i<0) break;
128 iftDelete(h, i); if(i>start) start=i;
129 }
130
131 /* If new unit is unknown, then just return */
132 if(u<=UNIT_UNKNOWN || u>=UNIT_LAST) return(TPCERROR_OK);
133
134 /* Otherwise create new key and value */
135 return (iftPut(h, "unit", unitName(u), (char)1, NULL));
136}

Referenced by tacGetHeaderUnit(), tacReadCSV(), tacReadDFT(), tacReadPMOD(), and tacWriteDFT().

◆ tacSetIsotope()

void tacSetIsotope ( TAC * tac,
int isotope )
extern

Write isotope code into TAC header, overwriting any previous field.

See also
tacSetHeaderIsotope, tacGetIsotope
Author
Vesa Oikonen
Parameters
tacPointer to target TAC structure.
isotopeIsotope code.

Definition at line 41 of file tacdc.c.

46 {
47 if(tac!=NULL) tacSetHeaderIsotope(&tac->h, isotopeName(isotope));
48}

Referenced by imgToSIF(), tacRead4DM(), tacReadModelingData(), tacReadReference(), and tacSetWeights().

◆ tacSetWeights()

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

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}
int tacGetIsotope(TAC *tac)
Definition tacdc.c:25
int tacDecayCorrection(TAC *tac, int isotope, int mode, TPCSTATUS *status)
Definition tacdc.c:59
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 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
@ WEIGHTING_ON_F
Weights based on sample frequency or frame length.
int unitIsRAConc(int u)
Definition units.c:726
@ UNIT_BQ
Becquerel.
@ UNIT_BQ_PER_ML
Bq/mL.
@ TPCERROR_INCOMPATIBLE_UNIT
Incompatible units.
@ TPCERROR_INCOMPATIBLE_DATA
Incompatible data.
int unitIsRadioactivity(int u)
Definition units.c:444

◆ tacSetX()

int tacSetX ( TAC * d,
TPCSTATUS * status )
extern

Set TAC x values based on x1 and x2 values, or guess x1 and x2 values based on x values.

This is not an idiot proof method, but works reasonably well in common cases.

See also
tacSortByTime, tacIsX, tacAddZeroSample, tacXCopy, tacCheckX1X2X, tacXNaNs, tacFixNaNs, tacIsXContiguous
Author
Vesa Oikonen
Returns
Returns TPCERROR status (0 if ok).
Parameters
dPointer to the TAC structure. TAC samples must be sorted for increasing x, if x1 and x2 are to be estimated from x values. TAC tunit should be specified as a time unit that can be internally converted to seconds to get most reliable results.
statusPointer to status data; enter NULL if not needed.

Definition at line 653 of file tacx.c.

661 {
662 int verbose=0; if(status!=NULL) verbose=status->verbose;
663 if(verbose>0) printf("%s()\n", __func__);
664
665 if(d==NULL) {
666 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
667 return TPCERROR_FAIL;
668 }
669 if(d->sampleNr==0) {
670 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
671 return TPCERROR_OK;
672 }
673 /* Check that some x values are there to begin with */
674 if(!tacIsX(d)) {
675 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_X);
676 return TPCERROR_NO_X;
677 }
678
679 /* If x1 and x2 are set, then calculate x for each sample */
680 if(d->isframe) {
681 if(verbose>1) printf("calculating x[] based on x1[] and x2[].\n");
682 int i, n, ret;
683 for(i=n=0; i<d->sampleNr; i++) {
684 d->x[i]=0.5*(d->x1[i]+d->x2[i]);
685 if(isfinite(d->x[i])) n++;
686 }
687 if(n>0) ret=TPCERROR_OK; else ret=TPCERROR_NO_X;
688 statusSet(status, __func__, __FILE__, __LINE__, ret);
689 return(ret);
690 }
691
692 /* We should start guessing x1 and x2 values based on their averages in x */
693 if(verbose>1) printf("estimating x1[] and x2[] based on x[].\n");
694
695 /* If reasonable x1 and x2 values already are set, then quit */
696 if(tacCheckX1X2X(d)) {
697 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
698 return TPCERROR_OK;
699 }
700
701 /* If only one sample, then set x1=0 and x2=2*x, and quit */
702 if(d->sampleNr==1) {
703 if(verbose>2) printf("just one sample.\n");
704 if(d->x[0]<=0.0) {d->x1[0]=2.0*d->x[0]; d->x2[0]=0.0;}
705 else {d->x1[0]=0.0; d->x2[0]=2.0*d->x[0];}
706 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
707 return TPCERROR_OK;
708 }
709
710 /* If only two samples */
711 if(d->sampleNr==2) {
712 if(verbose>2) printf("just two samples.\n");
713 if(d->x[0]>0.0 && 2.0*d->x[0]<0.95*d->x[1]) {
714 d->x1[0]=0.0; d->x2[0]=2.0*d->x[0];
715 d->x1[1]=d->x2[0]; d->x2[1]=d->x2[0]+2.0*(d->x[1]-d->x2[0]);
716 } else {
717 double f; f=d->x[1]-d->x[0];
718 d->x1[0]=d->x[0]-0.5*f; d->x2[0]=d->x[0]+0.5*f;
719 d->x1[1]=d->x2[0]; d->x2[1]=d->x2[0]+2.0*f;
720 }
721 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
722 return TPCERROR_OK;
723 }
724
725 int i, n, ret;
726
727 /* Allocate playground as TAC struct t */
728 TAC t; tacInit(&t);
729 n=d->tacNr; d->tacNr=1; ret=tacDuplicate(d, &t); d->tacNr=n;
730 if(ret==0) ret=tacAllocateMore(&t, 1);
731 if(ret) {
732 statusSet(status, __func__, __FILE__, __LINE__, ret);
733 return(ret);
734 }
735 double *x, *x1, *x2, *fa, *fb;
736 x=t.x; x1=t.x1; x2=t.x2; fa=t.c[0].y; fb=t.c[1].y;
737 n=t.sampleNr;
738
739 /* Convert playground times to sec if possible */
740 tacXUnitConvert(&t, UNIT_SEC, NULL);
741
742 /* Set each x1 and x1 to x */
743 for(i=0; i<n; i++) x1[i]=x2[i]=x[i];
744
745 /* Calculate the min gap, excluding zeroes */
746 double gap, v;
747 gap=nan("");
748 for(i=0; i<n-1; i++) {
749 v=x[i+1]-x[i]; if(!isfinite(v) || v<0.001) continue;
750 if(isnan(gap)) {gap=v; continue;}
751 if(v<gap) gap=v;
752 }
753
754 if(!isfinite(gap)) {
755 tacFree(&t);
756 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_X);
757 return(TPCERROR_NO_X);
758 }
759 if(verbose>2) printf("smallest gap := %g\n", gap);
760 /* Set gap to smallest step value for frame lengths */
761 if(t.tunit!=UNIT_SEC) {
762 gap*=0.01;
763 } else {
764 /* Set to 0.5 sec, unless calculated gap is smaller */
765 if(gap>0.5) gap=0.5;
766 }
767 if(verbose>2) printf("stepsize := %g\n", gap);
768
769 /* Initiate frame lengths to 0 */
770 for(i=0; i<n; i++) fa[i]=fb[i]=0.0;
771 int fixed[n]; for(i=0; i<n; i++) fixed[i]=0;
772
773 /* Iterate until gaps are as small as possible */
774 int anr=0;
775 do {
776 anr=0;
777 /* Set tentative frames to the last accepted frame lengths */
778 for(i=0; i<n; i++) fa[i]=fb[i];
779 /* Add fraction of gap to frames that have not yet been fixed */
780 for(i=0; i<n; i++) if(!fixed[i]) fa[i]+=gap;
781 /* Calculate x1 and x2 based on the tentative frames */
782 for(i=0; i<n; i++) {x1[i]=x[i]-0.5*fa[i]; x2[i]=x[i]+0.5*fa[i];}
783 /* If no overlap, then copy frame */
784 i=0;
785 if(x2[i]<=x1[i+1]+0.001*gap && (x[i]<=0.0 || x1[i]>-0.001*gap)) {
786 fb[i]=fa[i]; if(!fixed[i]) anr++;
787 } else
788 fixed[i]=1;
789 for(i=1; i<n-1; i++) {
790 if(x2[i]<=x1[i+1]+0.001*gap && x1[i]>=x2[i-1]-0.001*gap) {
791 fb[i]=fa[i]; if(!fixed[i]) anr++;} else fixed[i]=1;
792 }
793 if(x1[i]>=x2[i-1]-0.001*gap) {
794 fb[i]=fa[i]; if(!fixed[i]) anr++;} else fixed[i]=1;
795 if(verbose>5) {
796 printf("frames:");
797 for(i=0; i<n; i++) printf(" %g", fb[i]);
798 printf("\n");
799 }
800 } while(anr>0);
801
802 if(verbose>6) {
803 printf("temp frames:");
804 for(i=0; i<n; i++) printf(" %g", fa[i]);
805 printf("\n");
806 }
807
808 /* Calculate final frames */
809 for(i=0; i<n; i++) {x1[i]=x[i]-0.5*fb[i]; x2[i]=x[i]+0.5*fb[i];}
810
811 /* Convert playground to original time units */
812 tacXUnitConvert(&t, d->tunit, NULL);
813
814 /* Copy the guessed x1 and x2 values from playground */
815 t.isframe=1; tacXCopy(&t, d, 0, d->sampleNr-1);
816
817 /* Delete playground TAC */
818 tacFree(&t);
819
820 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
821 return TPCERROR_OK;
822}
int tacAllocateMore(TAC *tac, int tacNr)
Definition tac.c:178
int tacCheckX1X2X(TAC *d)
Check that sample (time frame) x, x1, and x2 values are reasonably set when compared to each other in...
Definition tacx.c:621
@ TPCERROR_NO_X
No sample times.

Referenced by tacInput2sim().

◆ tacSetXContiguous()

int tacSetXContiguous ( TAC * d)
extern

Set PET TAC frame times contiguous, without even tiny overlap or gaps in between.

Tiny overlaps and gaps are fixed by modifying frame times. Large gaps are filled with new frames based on linear interpolation between adjacent frames. Error is returned in case of larger frame overlaps.

See also
tacIsXContiguous, tacIsX, tacXRange, tacVerifyTimeOrder, tacSortByTime, tacMultipleSamples
Returns
If successful, TPCERROR_OK (0) is returned.
Author
Vesa Oikonen
Parameters
dPointer to TAC data which is sorted by increasing sample time.

Definition at line 1166 of file tacx.c.

1169 {
1170 if(d==NULL) return TPCERROR_FAIL;
1171 if(tacXNaNs(d)>0) return(TPCERROR_INVALID_X);
1172
1173 /* If no frame start and end times, then just make the times increasing */
1174 if(d->isframe==0) return(tacSortByTime(d, NULL));
1175
1176 /* If there are no gaps or overlap, then we're done */
1178
1179 /* Make a duplicate for editing */
1180 TAC tac; tacInit(&tac);
1181 int ret=tacDuplicate(d, &tac); if(ret!=TPCERROR_OK) return(ret);
1182
1183 /* Check for small frame overlaps or gaps; fix small, and return error if large overlap */
1184 int fixed=0, large=0;
1185 for(int fi=0; fi<d->sampleNr-1; fi++) {
1186 double dif=d->x1[fi+1]-d->x2[fi]; if(dif==0.0) continue; // not gap or overlap
1187 double fdur1=d->x2[fi]-d->x1[fi];
1188 double fdur2=d->x2[fi+1]-d->x1[fi+1];
1189 if(dif>0) { // gap
1190 if(dif<0.2*fdur1 && dif<0.2*fdur2) { // small gap; increase the shorter frame duration
1191 if(fdur1<fdur2) tac.x2[fi]=d->x1[fi+1]; else tac.x1[fi+1]=d->x2[fi];
1192 fixed++;
1193 } else {
1194 large++; // large gap not fixed yet
1195 }
1196 continue;
1197 }
1198 /* Overlap */
1199 dif=-dif;
1200 if(dif>0.2*fdur1 || dif>0.2*fdur2) { // too large overlap
1201 tacFree(&tac); return(TPCERROR_OVERLAPPING_DATA);
1202 }
1203 /* Reduce the longer frame length */
1204 if(fdur1>fdur2) tac.x2[fi]=d->x1[fi+1]; else tac.x1[fi+1]=d->x2[fi];
1205 fixed++;
1206 }
1207
1208 /* If we fixed something, then copy the fixed frame times */
1209 if(fixed>0) {
1210 for(int i=0; i<d->sampleNr; i++) {
1211 d->x1[i]=tac.x1[i]; d->x2[i]=tac.x2[i]; d->x[i]=0.5*(d->x1[i]+d->x2[i]);
1212 }
1213 }
1214
1215 /* If there were no large gaps, we're done */
1216 if(large==0) {tacFree(&tac); return(TPCERROR_OK);}
1217
1218 /* Fill large gaps with new frames */
1220 if(tacAllocateMoreSamples(d, large)!=0) {
1221 tacFree(&tac); return(TPCERROR_OUT_OF_MEMORY);
1222 }
1223 d->sampleNr=1;
1224 for(int fi=1; fi<tac.sampleNr; fi++) {
1225 double dif=tac.x1[fi]-tac.x2[fi-1];
1226 if(dif>0.0) {
1227 /* Add new frame times */
1228 d->x1[d->sampleNr]=tac.x2[fi-1]; d->x2[d->sampleNr]=tac.x1[fi];
1229 d->x[fi]=0.5*(d->x1[d->sampleNr]+d->x2[d->sampleNr]);
1230 /* Calculate y values for the new frame */
1231 double x1=0.5*(tac.x1[fi-1]+tac.x2[fi-1]);
1232 double x2=0.5*(tac.x1[fi]+tac.x2[fi]);
1233 for(int ri=0; ri<tac.tacNr; ri++) {
1234 double s=(tac.c[ri].y[fi]-tac.c[ri].y[fi-1])/(x2-x1);
1235 d->c[ri].y[d->sampleNr]=tac.c[ri].y[fi-1] + s*(d->x[fi]-x1);
1236 }
1237 d->sampleNr++;
1238 }
1239 /* copy the existing frame */
1240 d->x1[d->sampleNr]=tac.x1[fi]; d->x2[d->sampleNr]=tac.x2[fi];
1241 for(int ri=0; ri<tac.tacNr; ri++) d->c[ri].y[d->sampleNr]=tac.c[ri].y[fi];
1242 d->sampleNr++;
1243 }
1244
1245 tacFree(&tac);
1246 return(TPCERROR_OK);
1247}
int tacSortByTime(TAC *d, TPCSTATUS *status)
Definition tacorder.c:74

◆ tacSortByAUC()

int tacSortByAUC ( TAC * d,
TPCSTATUS * status )
extern

Sort TACs in decreasing order by their area-under-curve (AUC).

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSortByName, tacSortByTime
Parameters
dPointer to TAC structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 205 of file tacorder.c.

210 {
211 int verbose=0; if(status!=NULL) verbose=status->verbose;
212 if(verbose>0) printf("%s()\n", __func__);
213 /* Check that required data exists */
214 if(d==NULL) {
215 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
216 return TPCERROR_NO_DATA;
217 }
218 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
219 if(d->tacNr<2) return TPCERROR_OK;
220 /* Calculate AUCs for each TAC */
221 double auc[d->tacNr], fdur, v;
222 int i, j;
223 for(i=0; i<d->tacNr; i++) {
224 auc[i]=0.0;
225 for(j=0; j<d->sampleNr; j++) {
226 fdur=d->x2[0]-d->x1[0]; v=d->c[i].y[j];
227 if(isnan(fdur) || isnan(v)) continue;
228 auc[i]+=fdur*v;
229 }
230 }
231 /* Sort */
232 double a;
233 for(i=0; i<d->tacNr-1; i++)
234 for(j=i+1; j<d->tacNr; j++)
235 if(auc[j]>auc[i]) {
236 tacSwapTACCs(d, j, i);
237 a=auc[i]; auc[i]=auc[j]; auc[j]=a;
238 }
239 return TPCERROR_OK;
240}
int tacSwapTACCs(TAC *d, int i1, int i2)
Definition tacorder.c:282

◆ tacSortByConc()

int tacSortByConc ( TAC * d,
const int i,
TPCSTATUS * status )
extern

Sort samples (frames) in TAC structure by decreasing sample value.

See also
tacSortByTime, tacSortByAUC
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
dPointer to TAC structure.
iIndex of y column which the sorting is based on.
statusPointer to status data; enter NULL if not needed.

Definition at line 122 of file tacorder.c.

129 {
130 int verbose=0; if(status!=NULL) verbose=status->verbose;
131 if(verbose>0) printf("%s()\n", __func__);
132 /* Check that required data exists */
133 if(d==NULL || d->tacNr<1) {
134 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
135 return TPCERROR_NO_DATA;
136 }
137 if(i<0 || i>=d->_tacNr) {
138 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
139 return TPCERROR_FAIL;
140 }
141 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
142 if(d->sampleNr<1) return TPCERROR_OK;
143
144 TACC *c;
145 int ri, fi, fj;
146 double s, a1, a2;
147 for(fi=0; fi<d->sampleNr-1; fi++) for(fj=fi+1; fj<d->sampleNr; fj++) {
148 a1=d->c[i].y[fi]; a2=d->c[i].y[fj];
149 if(a2<=a1) continue;
150 s=d->x[fi]; d->x[fi]=d->x[fj]; d->x[fj]=s;
151 s=d->x1[fi]; d->x1[fi]=d->x1[fj]; d->x1[fj]=s;
152 s=d->x2[fi]; d->x2[fi]=d->x2[fj]; d->x2[fj]=s;
153 s=d->w[fi]; d->w[fi]=d->w[fj]; d->w[fj]=s;
154 for(ri=0; ri<d->_tacNr; ri++) {
155 c=d->c+ri;
156 s=c->y[fi]; c->y[fi]=c->y[fj]; c->y[fj]=s;
157 }
158 }
159 return TPCERROR_OK;
160}

◆ tacSortByName()

int tacSortByName ( TAC * d,
TPCSTATUS * status )
extern

Sort TACs in alphabetical order by their TAC name.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSortByAUC, tacSortByTime, tacSwapTACCs
Parameters
dPointer to TAC structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 178 of file tacorder.c.

183 {
184 int verbose=0; if(status!=NULL) verbose=status->verbose;
185 if(verbose>0) printf("%s()\n", __func__);
186 /* Check that required data exists */
187 if(d==NULL) {
188 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
189 return TPCERROR_NO_DATA;
190 }
191 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
192 if(d->tacNr<2) return TPCERROR_OK;
193 qsort(d->c, d->tacNr, sizeof(TACC), tacQSortName);
194 return TPCERROR_OK;
195}

◆ tacSortByTime()

int tacSortByTime ( TAC * d,
TPCSTATUS * status )
extern

Sort samples (frames) in TAC structure by increasing sample time.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacVerifyTimeOrder, tacMultipleSamples, tacSortByConc, tacSortByAUC, tacCorrectFrameOverlap, tacDeleteSample, tacIsX, tacMinX
Parameters
dPointer to TAC structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 74 of file tacorder.c.

79 {
80 int verbose=0; if(status!=NULL) verbose=status->verbose;
81 if(verbose>0) printf("%s()\n", __func__);
82 /* Check that required data exists */
83 if(d==NULL || d->tacNr<1) {
84 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
85 return TPCERROR_NO_DATA;
86 }
87 /* All sample times must be available */
88 if(tacXNaNs(d)>0) {
89 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
91 }
92 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
93 if(d->sampleNr<1) return TPCERROR_OK;
94
95 TACC *c;
96 int ri, fi, fj;
97 double s, a1, a2;
98 for(fi=0; fi<d->sampleNr-1; fi++) for(fj=fi+1; fj<d->sampleNr; fj++) {
99 if(d->isframe==0) {a1=d->x[fi]; a2=d->x[fj];}
100 else {a1=0.5*(d->x1[fi]+d->x2[fi]); a2=0.5*(d->x1[fj]+d->x2[fj]);}
101 if(a2>=a1) continue;
102 s=d->x[fi]; d->x[fi]=d->x[fj]; d->x[fj]=s;
103 s=d->x1[fi]; d->x1[fi]=d->x1[fj]; d->x1[fj]=s;
104 s=d->x2[fi]; d->x2[fi]=d->x2[fj]; d->x2[fj]=s;
105 s=d->w[fi]; d->w[fi]=d->w[fj]; d->w[fj]=s;
106 for(ri=0; ri<d->tacNr; ri++) {
107 c=d->c+ri;
108 s=c->y[fi]; c->y[fi]=c->y[fj]; c->y[fj]=s;
109 }
110 }
111 return TPCERROR_OK;
112}

Referenced by tacInput2sim(), tacReadModelingData(), tacReadModelingInput(), and tacSetXContiguous().

◆ tacSwapTACCs()

int tacSwapTACCs ( TAC * d,
int i1,
int i2 )
extern

Change places between two TACCs inside TAC structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacDeleteTACC, tacMoveTACC
Parameters
dPointer to TAC data. Main header and tacNr are not changed.
i1TACC index 1 [0.._tacNr-1]
i2TACC index 2 [0.._tacNr-1]

Definition at line 282 of file tacorder.c.

289 {
290 TACC tacc;
291 size_t taccSize;
292
293 if(d==NULL || i1<0 || i2<0) return(TPCERROR_FAIL);
294 if(i1>=d->_tacNr || i2>=d->_tacNr) return(TPCERROR_FAIL);
295 if(i1==i2) return(TPCERROR_OK); // nothing to do
296 taccSize=sizeof(TACC);
297 memcpy(&tacc, d->c+i1, taccSize);
298 memcpy(d->c+i1, d->c+i2, taccSize);
299 memcpy(d->c+i2, &tacc, taccSize);
300 return(TPCERROR_OK);
301}

Referenced by tacSortByAUC().

◆ tacToBars()

int tacToBars ( TAC * tac1,
TAC * tac2 )
extern

Transform TAC data with frame start and end times into suitable form for plotting with frames as bars.

Attention
Output data must not be used for quantitative purposes.
See also
tacFramesToSteps, tacXRange, tacIsX, tacCheckX1X2X, tacExtractRange, tacSetXContiguous
Returns
Returns <>0 in case of failure.
Parameters
tac1Pointer to input TAC structure; not modified. Must be sorted by increasing x.
tac2Pointer to output TAC structure; must be initiated; any previous content is destroyed.
See also
tacInit, tacFree

Definition at line 888 of file tacx.c.

894 {
895 if(tac1==NULL || tac2==NULL || tac1->sampleNr<1 || tac1->tacNr<1) return(1);
896 /* Make sure that frame start and end times are present */
897 if(tac1->isframe==0) return(2);
898 /* Remove any old contents in target struct */
899 tacFree(tac2);
900
901 /* Make a copy of the TAC data */
902 if(tacDuplicate(tac1, tac2)!=0) return(3);
903 /* Add room for more frames; we plot each frame as its own bar
904 and therefore we may need 4x the original space */
905 if(tacAllocateMoreSamples(tac2, 3*tac1->sampleNr)!=0) return(4);
906
907 /* Make separate 'samples' for each frame start and end time */
908 tac2->isframe=0;
909 int fj=0;
910 for(int fi=0; fi<tac1->sampleNr; fi++) {
911 /* Do nothing if missing values */
912 if(isnan(tac1->x1[fi]) || isnan(tac1->x2[fi])) continue;
913 if(tac1->tacNr==1 && isnan(tac1->c[0].y[fi])) continue;
914 /* Otherwise make bar of each frame */
915 tac2->x[fj]=tac1->x1[fi];
916 for(int ri=0; ri<tac2->tacNr; ri++) tac2->c[ri].y[fj]=0.0;
917 fj++;
918 tac2->x[fj]=tac1->x1[fi];
919 for(int ri=0; ri<tac2->tacNr; ri++) tac2->c[ri].y[fj]=tac1->c[ri].y[fi];
920 fj++;
921 tac2->x[fj]=tac1->x2[fi];
922 for(int ri=0; ri<tac2->tacNr; ri++) tac2->c[ri].y[fj]=tac1->c[ri].y[fi];
923 fj++;
924 tac2->x[fj]=tac1->x2[fi];
925 for(int ri=0; ri<tac2->tacNr; ri++) tac2->c[ri].y[fj]=0.0;
926 fj++;
927 }
928 tac2->sampleNr=fj;
929 if(fj<1) {tacFree(tac2); return(5);}
930 return(0);
931}

◆ tacVerifyTimeOrder()

int tacVerifyTimeOrder ( TAC * d,
TPCSTATUS * status )
extern

Verify that x values (sample or frame times) in TAC structure are ordered by increasing x. Overlapping samples are ok here.

Returns
enum tpcerror (TPCERROR_OK when in increasing order).
0 if in increasing order, >0 otherwise or in case of error.
Author
Vesa Oikonen
See also
tacSortByTime, tacCorrectFrameOverlap, tacMultipleSamples, tacIsX, tacMinX.
Parameters
dPointer to TAC structure; not modified.
statusPointer to status data; enter NULL if not needed

Definition at line 25 of file tacorder.c.

30 {
31 int verbose=0; if(status!=NULL) verbose=status->verbose;
32 if(verbose>0) printf("%s()\n", __func__);
33 /* Check that required data exists */
34 if(d==NULL || d->sampleNr<1) {
35 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
36 return TPCERROR_NO_DATA;
37 }
38 /* All sample times must be available */
39 if(tacXNaNs(d)>0) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
42 }
43 /* Less than two samples are always in order */
44 if(d->sampleNr<2) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
46 return TPCERROR_OK;
47 }
48
49 int fi;
50 double p, s;
51
52 fi=0; if(d->isframe==0) p=d->x[fi]; else p=0.5*(d->x1[fi]+d->x2[fi]);
53 for(fi=1; fi<d->sampleNr; fi++) {
54 if(d->isframe==0) s=d->x[fi]; else s=0.5*(d->x1[fi]+d->x2[fi]);
55 if(s<p) {
56 if(verbose>2) printf("x[%d]=%g\nx[%d]=%g\n", fi-1, p, fi, s);
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OVERLAPPING_DATA);
59 }
60 p=s;
61 }
62 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
63 return TPCERROR_OK;
64}

Referenced by tacCorrectFrameOverlap(), and tacIsXContiguous().

◆ tacWByFreq()

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

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

Referenced by tacSetWeights().

◆ tacWCopy()

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

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}

Referenced by tacDuplicate(), and tacExtract().

◆ tacWeightModerate()

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

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}

Referenced by tacSetWeights().

◆ tacWeightNorm()

int tacWeightNorm ( TAC * tac,
TPCSTATUS * status )
extern

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 )
extern

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}
int tacDeleteTACC(TAC *d, int i)
Definition tacorder.c:310
@ TPCERROR_DUPLICATE_DATA
File contains duplicate data.

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

◆ tacWrite()

int tacWrite ( TAC * tac,
FILE * fp,
tacformat format,
int extra,
TPCSTATUS * status )
extern

Write TAC data into specified file in specified format.

Precondition
Before using this, you may want to call tacFormatWriteSupported().
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacRead, tacFree, tacFormatWriteSupported
Parameters
tacPointer to TAC structure, contents of which are to be written.
fpOutput file pointer.
formatFile format code; enter TAC_FORMAT_UNKNOWN to write data in the format specified inside TAC structure.
extraWrite (1) or do not write (0) also extra header fields found in IFT; not effective with SIF.
statusPointer to status data; enter NULL if not needed.

Definition at line 332 of file tacio.c.

345 {
346 int verbose=0; if(status!=NULL) verbose=status->verbose;
347 if(fp==NULL) {
348 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
350 }
351 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
352 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
353 return TPCERROR_NO_DATA;
354 }
355
356 /* Determine and verify the write format */
357 if(format<=TAC_FORMAT_UNKNOWN || format>=TAC_FORMAT_LAST)
358 format=tac->format;
359 if(format<=TAC_FORMAT_UNKNOWN || format>=TAC_FORMAT_LAST) {
360 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
362 }
363 if(verbose>0) {
364 printf("%s():\n", __func__);
365 printf("writing %d TACs and %d samples in %s format\n",
366 tac->tacNr, tac->sampleNr, tacFormattxt(format));
367 }
368
369 /* Write file */
370 /* Update tacFormatWriteSupported() if you add/remove formats! */
371 int ret;
372 switch(format) {
374 ret=tacWriteSimple(tac, fp, extra, status);
375 break;
376 case TAC_FORMAT_DFT:
377 ret=tacWriteDFT(tac, fp, extra, status);
378 break;
379 case TAC_FORMAT_PMOD:
380 ret=tacWritePMOD(tac, fp, extra, status);
381 break;
386 ret=tacWriteCSV(tac, fp, extra, format, status);
387 break;
388 case TAC_FORMAT_SIF:
389 ret=tacWriteSIF(tac, fp, 0, status);
390 break;
391 case TAC_FORMAT_XML:
392 ret=tacWriteXML(tac, fp, status);
393 break;
394 default:
396 }
397
398 /* Quit */
399 statusSet(status, __func__, __FILE__, __LINE__, ret);
400 return(ret);
401}
int tacWriteDFT(TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
Definition dftio.c:119
int tacWritePMOD(TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
Definition pmodio.c:26
int tacWriteSIF(TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
Definition sifio.c:26
int tacWriteSimple(TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
Definition simpleio.c:26
int tacWriteCSV(TAC *tac, FILE *fp, int extra, tacformat format, TPCSTATUS *status)
Definition taccsv.c:26
int tacWriteXML(TAC *tac, FILE *fp, TPCSTATUS *status)
Definition tacxmlio.c:26
@ TPCERROR_CANNOT_WRITE
Cannot write file.

Referenced by imgWriteNifti().

◆ tacWriteCSV()

int tacWriteCSV ( TAC * tac,
FILE * fp,
int extra,
tacformat format,
TPCSTATUS * status )
extern

Write TAC data into specified file pointer in CSV TAC format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadCSV, tacWrite
Parameters
tacPointer to TAC struct, contents of which are to be written
fpFile pointer
extraWrite (1) or do not write (0) also extra header fields found in IFT; note that these are not supported by other than TPC SW.
formatFile format code; accepted values are TAC_FORMAT_CSV_UK, TAC_FORMAT_CSV_INT, TAC_FORMAT_TSV_UK, TAC_FORMAT_TSV_INT, and TAC_FORMAT_UNKNOWN (0); this last one uses format inside TAC struct, or if that is invalid, then the default format TAC_FORMAT_CSV_UK
statusPointer to status data; enter NULL if not needed

Definition at line 26 of file taccsv.c.

41 {
42 int verbose=0; if(status!=NULL) verbose=status->verbose;
43 if(verbose>0) printf("%s()\n", __func__);
44 if(fp==NULL) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
47 }
48 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
49 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
50 return TPCERROR_NO_DATA;
51 }
52
53 int ret;
54
55 /* Create local copy of headers, which will be edited here and written
56 into CSV file, to preserve the original headers with TAC struct */
57 if(verbose>99) iftWrite(&tac->h, stdout, NULL);
58 IFT localh; iftInit(&localh);
59 ret=iftDuplicate(&tac->h, &localh);
60 if(ret) {
61 statusSet(status, __func__, __FILE__, __LINE__, ret);
62 return ret;
63 }
64
65 CSV csv;
66 csvInit(&csv);
67 if(csvAllocate(&csv, (tac->tacNr+3)*(tac->sampleNr+1))) {
68 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
69 iftFree(&localh); return TPCERROR_FAIL;
70 }
71
72 /* Check and set the CSV format */
73 int tointl=0; // Decimal point (0) or comma (1)
74 if(format==TAC_FORMAT_UNKNOWN) format=tac->format;
75 if(format==TAC_FORMAT_UNKNOWN) format=TAC_FORMAT_CSV_UK;
76 if(format==TAC_FORMAT_CSV_UK) {
77 tointl=0; csv.separator=',';
78 } else if(format==TAC_FORMAT_CSV_INT) {
79 tointl=1; csv.separator=';';
80 } else if(format==TAC_FORMAT_TSV_UK) {
81 tointl=0; csv.separator='\t';
82 } else if(format==TAC_FORMAT_TSV_INT) {
83 tointl=1; csv.separator='\t';
84 } else {
85 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
86 iftFree(&localh); return TPCERROR_INVALID_FORMAT;
87 }
88
89 /* Make sure that TAC names are available */
90 tacEnsureNames(tac);
91
92 /* Fill CSV struct */
93 char tmp[1024];
94
95 if(verbose>1) printf(" writing header\n");
96
97 /* Add file format ID */
98 ret=csvPutString(&csv, "TAC", 0);
99 if(ret!=TPCERROR_OK) {
100 statusSet(status, __func__, __FILE__, __LINE__, ret);
101 csvFree(&csv); iftFree(&localh); return ret;
102 }
103
104 /* Add study number */
105 tacGetHeaderStudynr(&tac->h, tmp, NULL);
106 ret=csvPutString(&csv, tmp, 0);
107 if(ret!=TPCERROR_OK) {
108 statusSet(status, __func__, __FILE__, __LINE__, ret);
109 csvFree(&csv); iftFree(&localh); return ret;
110 }
111
112
113 if(verbose>1) printf(" writing data table title\n");
114
115 if(tac->isframe==0) {
116 sprintf(tmp, "time[%s]", unitName(tac->tunit));
117 ret=csvPutString(&csv, tmp, 1);
118 } else {
119 sprintf(tmp, "start[%s]", unitName(tac->tunit));
120 ret=csvPutString(&csv, tmp, 1);
121 sprintf(tmp, "end[%s]", unitName(tac->tunit));
122 if(!ret) ret=csvPutString(&csv, tmp, 0);
123 }
124 if(ret!=TPCERROR_OK) {
125 statusSet(status, __func__, __FILE__, __LINE__, ret);
126 csvFree(&csv); iftFree(&localh); return ret;
127 }
128
129 for(int ri=0; ri<tac->tacNr; ri++) {
130 /* add TAC names, first one with unit */
131 if(ri==0) {
132 sprintf(tmp, "%s[%s]", tac->c[ri].name, unitName(tac->cunit));
133 } else {
134 sprintf(tmp, "%s", tac->c[ri].name);
135 }
136 ret=csvPutString(&csv, tmp, 0); if(ret) break;
137 }
138 if(ret!=TPCERROR_OK) {
139 statusSet(status, __func__, __FILE__, __LINE__, ret);
140 csvFree(&csv); iftFree(&localh); return ret;
141 }
142 if(tacIsWeighted(tac)) {
143 ret=csvPutString(&csv, "weight", 0);
144 if(ret!=TPCERROR_OK) {
145 statusSet(status, __func__, __FILE__, __LINE__, ret);
146 csvFree(&csv); iftFree(&localh); return ret;
147 }
148 }
149
150 if(verbose>1) printf("writing data table\n");
151
152 for(int fi=0; fi<tac->sampleNr; fi++) {
153 /* Time(s) (x, or x1 and x2) */
154 if(tac->isframe==0) {
155 ret=csvPutDouble(&csv, tac->x[fi], 1, tointl);
156 } else {
157 ret=csvPutDouble(&csv, tac->x1[fi], 1, tointl);
158 if(!ret) ret=csvPutDouble(&csv, tac->x2[fi], 0, tointl);
159 }
160 if(ret!=TPCERROR_OK) break;
161 /* Concentrations (y values) */
162 for(int ri=0; ri<tac->tacNr; ri++) {
163 ret=csvPutDouble(&csv, tac->c[ri].y[fi], 0, tointl); if(ret) break;
164 }
165 /* Weight */
166 if(tacIsWeighted(tac)) {
167 ret=csvPutDouble(&csv, tac->w[fi], 0, tointl); if(ret) break;
168 }
169 } // next sample
170 if(ret!=TPCERROR_OK) {
171 statusSet(status, __func__, __FILE__, __LINE__, ret);
172 csvFree(&csv); iftFree(&localh); return ret;
173 }
174
175 /* Add VOI volumes, if available */
176 if(tacIsSize(tac)) {
177 ret=csvPutString(&csv, "volume", 1);
178 if(tac->isframe && !ret) ret=csvPutString(&csv, "", 0);
179 for(int ri=0; ri<tac->tacNr && !ret; ri++) {
180 ret=csvPutDouble(&csv, tac->c[ri].size, 0, tointl);
181 }
182 if(ret!=TPCERROR_OK) {
183 statusSet(status, __func__, __FILE__, __LINE__, ret);
184 csvFree(&csv); iftFree(&localh); return ret;
185 }
186 }
187
188 /* Write CSV */
189 ret=csvWrite(&csv, 0, fp, status);
190 csvFree(&csv);
191 if(ret!=TPCERROR_OK) {iftFree(&localh); return ret;}
192
193 /* Write extra header */
194 // scan start time etc should be added to the first line I think
195 if(extra && localh.keyNr>0) {
196 int ret=iftWrite(&localh, fp, status);
197 if(ret!=TPCERROR_OK) {iftFree(&localh); return ret;}
198 }
199
200 iftFree(&localh);
201 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
202 return(TPCERROR_OK);
203}
int csvAllocate(CSV *csv, int nr)
Definition csv.c:58
int csvPutDouble(CSV *csv, double v, int newline, int tointl)
Definition csv.c:193
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
Definition iftio.c:98
int tacIsSize(TAC *d)
Definition tac.c:335
void tacEnsureNames(TAC *tac)
Definition tacname.c:50

Referenced by tacWrite().

◆ tacWriteDFT()

int tacWriteDFT ( TAC * tac,
FILE * fp,
int extra,
TPCSTATUS * status )
extern

Write TAC data into specified file pointer in DFT format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWrite, tacReadDFT
Parameters
tacPointer to TAC struct, contents of which are to be written
fpFile pointer
extraWrite (1) or do not write (0) also extra header fields found in IFT
statusPointer to status data; enter NULL if not needed

Definition at line 119 of file dftio.c.

128 {
129 int verbose=0; if(status!=NULL) verbose=status->verbose;
130 if(fp==NULL) {
131 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
133 }
134 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
135 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
136 return TPCERROR_NO_DATA;
137 }
138 if(verbose>0) printf("%s()\n", __func__);
139
140 int ret, prec=6;
141
142 /* Make sure that TAC names are available */
143 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
144 tacEnsureNames(tac);
145
146 /* Create local copy of headers, which will be edited here and written
147 into DFT file, to preserve the original headers with TAC struct */
148 if(verbose>99) iftWrite(&tac->h, stdout, NULL);
149 IFT localh; iftInit(&localh);
150 ret=iftDuplicate(&tac->h, &localh);
151 if(ret) {
152 statusSet(status, __func__, __FILE__, __LINE__, ret);
153 return ret;
154 }
155
156 /* Writing obligatory header lines */
157 if(verbose>1) printf("writing obligatory title lines\n");
158 int n;
159 char subname[7];
160
161 /* 1st line with filetype identification string and region names */
162 n=fprintf(fp, "DFT1"); if(n<1) {
163 iftFree(&localh);
164 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
166 }
167 for(int ri=0; ri<tac->tacNr; ri++) {
168 n=tacNameSplit(tac->c[ri].name, subname, NULL, NULL, 6);
169 fprintf(fp, "\t%s", subname);
170 }
171 if(tacIsWeighted(tac)) fprintf(fp, "\t%s", "weight");
172 n=fprintf(fp, "\n"); if(n<1) {
173 iftFree(&localh);
174 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
176 }
177
178 /* 2nd line with study identification and 2nd subname */
179 if(verbose>2) printf(" writing 2nd title line\n");
180 char tmp[128];
181 n=tacGetHeaderStudynr(&localh, tmp, status);
182 if(n!=TPCERROR_OK) {
183 strcpy(tmp, "."); if(verbose>5) printf("no studynr\n");
184 } else tacSetHeaderStudynr(&localh, ""); // delete studynr from header
185 n=fprintf(fp, "%s", tmp); if(n<1) {
186 iftFree(&localh);
187 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
189 }
190 for(int ri=0; ri<tac->tacNr; ri++) {
191 n=tacNameSplit(tac->c[ri].name, NULL, subname, NULL, 6);
192 if(n<2 || !subname[0]) strcpy(subname, ".");
193 fprintf(fp, "\t%s", subname);
194 }
195 if(tacIsWeighted(tac)) fprintf(fp, "\t%s", ".");
196 n=fprintf(fp, "\n"); if(n<1) {
197 iftFree(&localh);
198 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
200 }
201
202 /* 3rd line with calibration unit and 3rd subname */
203 if(verbose>2) printf(" writing 3rd title line\n");
204 tacSetHeaderUnit(&localh, UNIT_UNKNOWN); // delete any unit(s) from header
205 if(tac->cunit==UNIT_UNKNOWN) strcpy(tmp, ".");
206 else strcpy(tmp, unitName(tac->cunit));
207 n=fprintf(fp, "%s", tmp); if(n<1) {
208 iftFree(&localh);
209 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
211 }
212 for(int ri=0; ri<tac->tacNr; ri++) {
213 n=tacNameSplit(tac->c[ri].name, NULL, NULL, subname, 6);
214 if(n<3 || !subname[0]) strcpy(subname, ".");
215 fprintf(fp, "\t%s", subname);
216 }
217 if(tacIsWeighted(tac)) fprintf(fp, "\t%s", ".");
218 n=fprintf(fp, "\n"); if(n<1) {
219 iftFree(&localh);
220 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
222 }
223
224 /* 4th line with x (time) type & unit and region volumes */
225 if(verbose>2) printf(" writing 4th title line\n");
226 if(unitIsDistance(tac->tunit)) strcpy(tmp, "Distance");
227 else strcpy(tmp, "Time");
228 if(tac->isframe!=0) strcat(tmp, "s");
229 n=fprintf(fp, "%s (%s)", tmp, unitName(tac->tunit)); if(n<1) {
230 iftFree(&localh);
231 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
233 }
234 for(int ri=0; ri<tac->tacNr; ri++) {
235 if(!isnan(tac->c[ri].size)) sprintf(tmp, "%.*e", prec, tac->c[ri].size);
236 else strcpy(tmp, ".");
237 fprintf(fp, "\t%s", tmp);
238 }
239 if(tacIsWeighted(tac)) fprintf(fp,"\t%s", ".");
240 n=fprintf(fp, "\n"); if(n<1) {
241 iftFree(&localh);
242 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
244 }
245
246 /* Write data */
247 if(verbose>1) printf("writing data table\n");
248 double v;
249 n=10;
250 for(int fi=0; fi<tac->sampleNr; fi++) {
251 /* x or x1 and x2) */
252 if(tac->isframe==0) v=tac->x[fi]; else v=tac->x1[fi];
253 if(isnan(v)) n=fprintf(fp, "."); else n=fprintf(fp, "%.5f", v);
254 if(n<1) break;
255 if(tac->isframe!=0) {
256 v=tac->x2[fi];
257 if(isnan(v)) n=fprintf(fp, "\t."); else n=fprintf(fp, "\t%.5f", v);
258 if(n<1) break;
259 }
260 /* Concentrations (y values) */
261 for(int ri=0; ri<tac->tacNr; ri++) {
262 if(isnan(tac->c[ri].y[fi])) n=fprintf(fp, "\t.");
263 else n=fprintf(fp, "\t%.*e", prec, tac->c[ri].y[fi]);
264 if(n<1) break;
265 }
266 if(n<1) break;
267 /* Weight */
268 if(tacIsWeighted(tac)) {
269 if(isnan(tac->w[fi])) n=fprintf(fp, "\t.");
270 else n=fprintf(fp, "\t%.*e", prec, tac->w[fi]);
271 if(n<1) break;
272 }
273 if(n<1) break;
274 n=fprintf(fp, "\n"); if(n<1) break;
275 } // next sample
276 if(n<1) {
277 iftFree(&localh);
278 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
280 }
281
282 /* Write extra header, if requested */
283 if(extra && localh.keyNr>0) {
284 int ret=iftWrite(&localh, fp, status);
285 if(ret!=TPCERROR_OK) {iftFree(&localh); return ret;}
286 }
287
288 iftFree(&localh);
289 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
290 return(TPCERROR_OK);
291}
int tacNameSplit(const char *rname, char *name1, char *name2, char *name3, unsigned int max_name_len)
Definition dftio.c:26
int unitIsDistance(int u)
Definition units.c:339

Referenced by tacWrite().

◆ tacWritePMOD()

int tacWritePMOD ( TAC * tac,
FILE * fp,
int extra,
TPCSTATUS * status )
extern

Write TAC data into specified file pointer in PMOD.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadPMOD, tacWrite
Parameters
tacPointer to TAC structure, contents of which are to be written.
fpFile pointer to write to.
extraWrite (1) or do not write (0) also extra header fields found in IFT; note that these are not supported by other than TPC SW.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file pmodio.c.

36 {
37 int verbose=0; if(status!=NULL) verbose=status->verbose;
38 if(verbose>0) printf("%s()\n", __func__);
39 if(fp==NULL) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
42 }
43 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
44 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
45 return TPCERROR_NO_DATA;
46 }
47
48 char *cptr, tunit[128], cunit[128];
49 int n, prec=6;
50 double v;
51
52 /* Set units to format accepted by PMOD */
53 if(tac->tunit==UNIT_SEC) strcpy(tunit, "seconds");
54 else if(tac->tunit==UNIT_MIN) strcpy(tunit, "minutes");
55 else strcpy(tunit, unitName(tac->tunit));
56 if(tac->cunit==UNIT_UNITLESS) strcpy(cunit, "1/1");
57 else strcpy(cunit, unitName(tac->cunit));
58 if(strcasestr(cunit, "dL")==NULL) {
59 /* Replace mL by cc, but only if unit does not contain 'dL' */
60 cptr=strcasestr(cunit, "mL");
61 if(cptr!=NULL) {*cptr='c'; cptr++; *cptr='c';}
62 }
63
64 /* Make sure that TAC names are available */
65 if(verbose>2) printf("constructing TAC names\n");
66 tacEnsureNames(tac);
67
68 /* Write obligatory header line */
69 if(verbose>2) printf("writing obligatory title lines\n");
70 if(tac->isframe==0) n=fprintf(fp, "time[%s]", tunit);
71 else n=fprintf(fp, "start[%s]\tend[%s]", tunit, cunit);
72 if(n<1) {
73 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
75 }
76 for(int ri=0; ri<tac->tacNr; ri++) {
77 /* write TAC names, must not include space characters */
78 strReplaceChar(tac->c[ri].name, ' ', '-');
79 strReplaceChar(tac->c[ri].name, '\t', '-');
80 n=fprintf(fp, "\t%s", tac->c[ri].name);
81 if(n<1) {
82 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
84 }
85 /* write calibration unit when necessary */
86 if(ri==0 && tac->isframe==0) fprintf(fp, "[%s]", cunit);
87 }
88 if(tacIsWeighted(tac)) fprintf(fp, "\t%s", "weight");
89 n=fprintf(fp, "\n"); if(n<1) {
90 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
92 }
93
94 /* Write data */
95 if(verbose>2) printf("writing data table\n");
96 for(int fi=0, n=0; fi<tac->sampleNr; fi++) {
97 /* Time(s) (x, x1, x2) */
98 if(tac->isframe==0) v=tac->x[fi]; else v=tac->x1[fi];
99 if(!isfinite(v)) n=fprintf(fp, "."); else n=fprintf(fp, "%.5f", v);
100 if(n<1) break;
101 if(tac->isframe!=0) {
102 v=tac->x2[fi];
103 if(!isfinite(v)) n=fprintf(fp, "\t."); else n=fprintf(fp, "\t%.5f", v);
104 if(n<1) break;
105 }
106 /* Concentrations (y values) */
107 for(int ri=0; ri<tac->tacNr; ri++) {
108 if(!isfinite(tac->c[ri].y[fi])) n=fprintf(fp, "\t.");
109 else fprintf(fp, "\t%.*e", prec, tac->c[ri].y[fi]);
110 if(n<1) break;
111 }
112 /* Weight */
113 if(tacIsWeighted(tac)) {
114 if(!isfinite(tac->w[fi])) n=fprintf(fp, "\t.");
115 else n=fprintf(fp, "\t%.*e", prec, tac->w[fi]);
116 if(n<1) break;
117 }
118 if(n>0) n=fprintf(fp, "\n");
119 if(n<1) break;
120 }
121 if(n<1) {
122 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
124 }
125
126
127 /* Write extra header, if requested */
128 if(extra) {
129 if(tac->h.keyNr>0) {
130 int ret=iftWrite(&tac->h, fp, status);
131 if(ret!=TPCERROR_OK) return ret;
132 }
133 }
134
135 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
136 return(TPCERROR_OK);
137}
void strReplaceChar(char *s, char c1, char c2)
Definition stringext.c:134
@ UNIT_UNITLESS
Unitless.

Referenced by tacWrite().

◆ tacWriteSIF()

int tacWriteSIF ( TAC * tac,
FILE * fp,
int extra,
TPCSTATUS * status )
extern

Write SIF data stored in TAC struct in SIF format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadSIF, tacWrite, TAC
Parameters
tacPointer to TAC struct, contents of which are to be written; tacNr can be set to 0 to write only frame times.
fpFile pointer.
extraWrite (1) or do not write (0) also extra header fields found in tac->h; set this to 0, because extra header lines do not follow SIF format.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file sifio.c.

37 {
38 int verbose=0; if(status!=NULL) verbose=status->verbose;
39 if(fp==NULL) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
42 }
43 if(tac==NULL || tac->sampleNr<1) {
44 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
45 return TPCERROR_NO_DATA;
46 }
47 if(verbose>0) printf("%s()\n", __func__);
48
49 int fi, ret, n;
50 int m2s=0; // 1=time units converted from min to sec
51
52 /* Scan start time */
53 char scan_start_time[20];
54 ret=tacGetHeaderScanstarttime(&tac->h, scan_start_time, NULL);
55 if(ret==TPCERROR_OK) {
56 int yy, mm, dd, h, m, s;
57 n=sscanf(scan_start_time, "%d-%d-%d %d:%d:%d", &yy, &mm, &dd, &h, &m, &s);
58 if(n==6)
59 sprintf(scan_start_time, "%d/%d/%04d %02d:%02d:%02d", dd, mm, yy, h, m, s);
60 else strcpy(scan_start_time, "1/1/1970 00:00:00");
61 } else { // use default date & time
62 strcpy(scan_start_time, "1/1/1970 00:00:00");
63 }
64 /* Column nr */
65 int colNr=2; // frame start and end times
66 colNr+=tac->tacNr;
67 /* Study number */
68 char studynr[MAX_STUDYNR_LEN+1];
69 ret=tacGetHeaderStudynr(&tac->h, studynr, NULL);
70 if(ret!=TPCERROR_OK) strcpy(studynr, ".");
71 /* Isotope */
73 ret=tacGetHeaderIsotope(&tac->h, isotope, NULL);
74 if(ret!=TPCERROR_OK) strcpy(studynr, "");
75 /* Write header line */
76 n=fprintf(fp, "%s %d %d 1 %s %s\n", scan_start_time, tac->sampleNr, colNr, studynr, isotope);
77 if(n<7) {
78 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
80 }
81
82 /* Convert frame times to seconds because always sec in SIF */
83 if(tac->tunit==UNIT_MIN) {m2s=1; tacXUnitConvert(tac, UNIT_SEC, status);}
84
85 /* Check if frame times need to printed with decimals */
86 int req_decimals=0;
87 for(fi=1; fi<tac->sampleNr; fi++) {
88 if(round(tac->x1[fi])==round(tac->x1[fi-1])) {req_decimals=1; break;}
89 if(round(tac->x2[fi])==round(tac->x2[fi-1])) {req_decimals=1; break;}
90 }
91
92 /* Write data lines */
93 ret=0;
94 for(fi=0; fi<tac->sampleNr; fi++) {
95 if(req_decimals==0) n=fprintf(fp, "%.0f %.0f", tac->x1[fi], tac->x2[fi]);
96 else n=fprintf(fp, "%.1f %.1f", tac->x1[fi], tac->x2[fi]);
97 if(n<3) {ret++; break;}
98 for(int ci=0; ci<tac->tacNr; ci++) {
99 n=fprintf(fp, " %.0f", tac->c[ci].y[fi]);
100 if(n<2) {ret++; break;}
101 }
102 if(ret==0) fprintf(fp, "\n"); else break;
103 }
104 if(ret!=0) {
105 if(m2s!=0) tacXUnitConvert(tac, UNIT_MIN, status);
106 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
108 }
109
110 /* Convert frame times back to min if necessary */
111 if(m2s!=0) tacXUnitConvert(tac, UNIT_MIN, status);
112
113 /* Write extra information */
114 if(extra!=0) {
115 /* do nothing at least for now */
116 }
117
118 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
119 return(TPCERROR_OK);
120}

Referenced by tacWrite().

◆ tacWriteSimple()

int tacWriteSimple ( TAC * tac,
FILE * fp,
int extra,
TPCSTATUS * status )
extern

Write TAC data into specified file pointer in Simple format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadSimple, tacWriteCSV
Parameters
tacPointer to TAC struct, contents of which are to be written.
fpFile pointer.
extraWrite (1) or do not write (0) also extra header fields found in IFT.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file simpleio.c.

35 {
36 int verbose=0; if(status!=NULL) verbose=status->verbose;
37 if(fp==NULL) {
38 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
40 }
41 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
42 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
43 return TPCERROR_NO_DATA;
44 }
45 if(verbose>0) {printf("%s(%d)\n", __func__, extra); fflush(stdout);}
46
47
48 int fi, ri, n, prec=6;
49 double v;
50
51 /* Write data */
52 for(fi=0; fi<tac->sampleNr; fi++) {
53 /* Time (x) */
54 if(tac->isframe==0) v=tac->x[fi]; else v=0.5*(tac->x1[fi]+tac->x2[fi]);
55 if(isnan(v)) n=fprintf(fp, "."); else n=fprintf(fp, "%.5f", v);
56 if(n<1) {
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
59 }
60 /* Concentrations (y values) */
61 for(ri=0; ri<tac->tacNr; ri++) {
62 if(isnan(tac->c[ri].y[fi])) n=fprintf(fp, " .");
63 else fprintf(fp, " %.*e", prec, tac->c[ri].y[fi]);
64 if(n<1) {
65 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
67 }
68 }
69 n=fprintf(fp, "\n"); if(n<1) {
70 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
72 }
73 }
74
75 /* Write extra header, if requested */
76 if(extra) {
77 if(tac->h.keyNr>0) {
78 int ret=iftWrite(&tac->h, fp, status);
79 if(ret!=TPCERROR_OK) return ret;
80 }
81 /* Write units */
82 if(tac->cunit!=UNIT_UNKNOWN) fprintf(fp, "# unit := %s\n", unitName(tac->cunit));
83 if(tac->tunit!=UNIT_UNKNOWN) fprintf(fp, "# timeunit := %s\n", unitName(tac->tunit));
84 }
85
86 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
87 return(TPCERROR_OK);
88}

Referenced by tacWrite().

◆ tacWriteXML()

int tacWriteXML ( TAC * tac,
FILE * fp,
TPCSTATUS * status )
extern

Write TAC data into specified file pointer in Excel compatible XML format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWrite
Parameters
tacPointer to TAC struct, contents of which are to be written.
fpFile pointer
statusPointer to status data; enter NULL if not needed

Definition at line 26 of file tacxmlio.c.

33 {
34 int verbose=0; if(status!=NULL) verbose=status->verbose;
35 if(verbose>0) printf("%s()\n", __func__);
36 if(fp==NULL) {
37 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
39 }
40 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
42 return TPCERROR_NO_DATA;
43 }
44
45 char *cptr, tunit[128], cunit[128];
46 int n;
47
48 /* Set units to format accepted by PMOD */
49 if(tac->tunit==UNIT_SEC) strcpy(tunit, "seconds");
50 else if(tac->tunit==UNIT_MIN) strcpy(tunit, "minutes");
51 else strcpy(tunit, unitName(tac->tunit));
52 strcpy(cunit, unitName(tac->cunit));
53 if(strcasestr(cunit, "dL")==NULL) {
54 /* Replace mL by cc, but only if unit does not contain 'dL' */
55 cptr=strcasestr(cunit, "mL");
56 if(cptr!=NULL) {*cptr='c'; cptr++; *cptr='c';}
57 }
58
59 /* Make sure that TAC names are available */
60 if(verbose>2) printf("constructing TAC names\n");
61 tacEnsureNames(tac);
62
63 /* Write XML header */
64 n=fprintf(fp, "<?xml version=\"1.0\"?>\n");
65 if(n<1) {
66 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
68 }
69 fprintf(fp, "<ss:Workbook xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">\n");
70 fprintf(fp, " <ss:Styles>\n");
71 fprintf(fp, " <ss:Style ss:ID=\"1\">\n");
72 fprintf(fp, " <ss:Font ss:Bold=\"1\"/>\n");
73 fprintf(fp, " </ss:Style>\n");
74 fprintf(fp, " </ss:Styles>\n");
75 fprintf(fp, " <ss:Worksheet ss:Name=\"Sheet1\">\n");
76 fprintf(fp, " <ss:Table>\n");
77
78 /* Set column widths */
79 n=tac->tacNr+1;
80 if(tac->isframe) n++;
81 if(tacIsWeighted(tac)) n++;
82 for(int i=0; i<n; i++) fprintf(fp, " <ss:Column ss:Width=\"80\"/>\n");
83
84 /* Write the title line */
85 fprintf(fp, " <ss:Row ss:StyleID=\"1\">\n");
86 if(tac->isframe==0) {
87 fprintf(fp, " <ss:Cell>\n");
88 fprintf(fp, " <ss:Data ss:Type=\"String\">time[%s]</ss:Data>\n", tunit);
89 fprintf(fp, " </ss:Cell>\n");
90 } else {
91 fprintf(fp, " <ss:Cell>\n");
92 fprintf(fp, " <ss:Data ss:Type=\"String\">start[%s]</ss:Data>\n", tunit);
93 fprintf(fp, " </ss:Cell>\n");
94 fprintf(fp, " <ss:Cell>\n");
95 fprintf(fp, " <ss:Data ss:Type=\"String\">end[%s]</ss:Data>\n", cunit);
96 fprintf(fp, " </ss:Cell>\n");
97 }
98 for(int ri=0; ri<tac->tacNr; ri++) {
99 /* write TAC names */
100 char *nptr=tac->c[ri].name;
101 char *senc=strEncodeForXML(nptr);
102 if(senc!=NULL) nptr=senc;
103 fprintf(fp, " <ss:Cell>\n");
104 if(ri==0 && tac->isframe==0)
105 fprintf(fp, " <ss:Data ss:Type=\"String\">%s[%s]</ss:Data>\n", nptr, cunit);
106 else
107 fprintf(fp, " <ss:Data ss:Type=\"String\">%s</ss:Data>\n", nptr);
108 fprintf(fp, " </ss:Cell>\n");
109 if(senc!=NULL) free(senc);
110 }
111 if(tacIsWeighted(tac)) {
112 fprintf(fp, " <ss:Cell>\n");
113 fprintf(fp, " <ss:Data ss:Type=\"String\">weight</ss:Data>\n");
114 fprintf(fp, " </ss:Cell>\n");
115 }
116 n=fprintf(fp, " </ss:Row>\n");
117 if(n<1) {
118 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
120 }
121
122 /* Write data */
123 if(verbose>2) printf("writing data table\n");
124 for(int fi=0; fi<tac->sampleNr; fi++) {
125
126 fprintf(fp, " <ss:Row>\n");
127
128 /* Note: missing values are written as empty cells, with string type, because with
129 number type Excel seems to read those as zeroes. */
130
131 /* Time(s) (x, or x1 and x2) */
132 double v; if(tac->isframe==0) v=tac->x[fi]; else v=tac->x1[fi];
133 fprintf(fp, " <ss:Cell>\n");
134 if(isnan(v)) fprintf(fp, " <ss:Data ss:Type=\"String\"></ss:Data>\n");
135 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", v);
136 fprintf(fp, " </ss:Cell>\n");
137
138 if(tac->isframe) {
139 v=tac->x2[fi];
140 fprintf(fp, " <ss:Cell>\n");
141 if(isnan(v)) fprintf(fp, " <ss:Data ss:Type=\"String\"></ss:Data>\n");
142 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", v);
143 fprintf(fp, " </ss:Cell>\n");
144 }
145
146 /* Concentrations (y values) */
147 for(int ri=0; ri<tac->tacNr; ri++) {
148 fprintf(fp, " <ss:Cell>\n");
149 if(isnan(tac->c[ri].y[fi])) fprintf(fp, " <ss:Data ss:Type=\"String\"></ss:Data>\n");
150 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", tac->c[ri].y[fi]);
151 fprintf(fp, " </ss:Cell>\n");
152 }
153
154 /* Weight */
155 if(tacIsWeighted(tac)) {
156 fprintf(fp, " <ss:Cell>\n");
157 if(isnan(tac->w[fi])) fprintf(fp, " <ss:Data ss:Type=\"String\"></ss:Data>\n");
158 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", tac->w[fi]);
159 fprintf(fp, " </ss:Cell>\n");
160 }
161
162 fprintf(fp, " </ss:Row>\n");
163 }
164
165 /* Write XML end part */
166 fprintf(fp, " </ss:Table>\n");
167 fprintf(fp, " </ss:Worksheet>\n");
168 n=fprintf(fp, "</ss:Workbook>\n");
169 if(n<1) {
170 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
172 }
173
174 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
175 return(TPCERROR_OK);
176}
char * strEncodeForXML(const char *s)
Definition stringext.c:731

Referenced by tacWrite().

◆ tacWSampleNr()

unsigned int tacWSampleNr ( TAC * tac)
extern

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}

◆ tacXCopy()

int tacXCopy ( TAC * tac1,
TAC * tac2,
int i1,
int i2 )
extern

Copy x values (frame times) from one TAC structure to another.

See also
tacCompareTimes, tacXMatch, tacIsX, tacCheckX1X2X, tacInterpolate, tacWCopy, tacCopyTacc
Author
Vesa Oikonen
Returns
Returns TPCERROR status.
Parameters
tac1Pointer to source TAC structure.
tac2Pointer to target TAC structure.
i1Index of the first sample time to copy.
i2Index of the last sample time to copy.

Definition at line 24 of file tacx.c.

33 {
34 if(tac1==NULL || tac2==NULL) return(TPCERROR_FAIL);
35 if(i1<0 || i1>i2) return(TPCERROR_FAIL);
36 if(i2>=tac1->_sampleNr || i2>=tac2->_sampleNr) return(TPCERROR_FAIL);
37
38 for(int i=i1; i<=i2; i++) {
39 tac2->x[i]=tac1->x[i];
40 tac2->x1[i]=tac1->x1[i];
41 tac2->x2[i]=tac1->x2[i];
42 }
43 return(TPCERROR_OK);
44}

Referenced by bfm1TCM(), tacAllocateMoreSamples(), tacDuplicate(), tacExtract(), tacInterpolate(), tacReadReference(), tacSetWeights(), and tacSetX().

◆ tacXMatch()

int tacXMatch ( TAC * d1,
TAC * d2,
const int verbose )
extern

Check whether sample (frame) times are the same (or very close to) in two TAC structures.

Data is not modified. Sort by sample time before calling this. The order of TAC structures is not important. If sampleNr is different, then only common number of samples are compared.

See also
tacCompareTimes, tacXCopy, tacSortByTime, tacIsX
Author
Vesa Oikonen
Returns
Returns 1 if times do match, 0 if not.
Parameters
d1Pointer to the first TAC structure; not modified.
d2Pointer to the second TAC structure; time unit does not matter if conversion can be done. Sample nr may be different than in tac1. Contents not modified.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 249 of file tacx.c.

257 {
258 if(verbose>0) printf("\n%s()\n", __func__);
259
260 /* Check data */
261 if(d1==NULL || d2==NULL) return 0;
262 double xmin[2], xmax[2];
263 if(tacXRange(d1, xmin, xmax) || tacXRange(d2, xmin+1, xmax+1)) return(0);
264
265 /* Which has less samples? */
266 int smaller_sampleNr;
267 if(d1->sampleNr<d2->sampleNr) smaller_sampleNr=d1->sampleNr;
268 else smaller_sampleNr=d2->sampleNr;
269 if(verbose>1) printf("smaller_sampleNr := %d\n", smaller_sampleNr);
270 if(smaller_sampleNr<=0) return 0;
271
272 /* Get conversion factors for sample times to get those in sec */
273 double ts1, ts2;
275 if(isnan(ts1)) {
276 if(verbose>1) printf("cannot convert tac1 sample times to sec.\n");
277 ts1=1.0; if(d1->tunit==UNIT_UNKNOWN) ts1=60.0; // assuming min
278 }
280 if(isnan(ts2)) {
281 if(verbose>1) printf("cannot convert tac2 sample times to sec.\n");
282 ts2=1.0; if(d2->tunit==UNIT_UNKNOWN) ts2=60.0; // assuming min
283 }
284 /* Convert time ranges to sec */
285 xmin[0]*=ts1; xmax[0]*=ts1;
286 xmin[1]*=ts2; xmax[1]*=ts2;
287 if(verbose>1) {
288 printf("tac1->isframe := %d\n", d1->isframe);
289 if(verbose>2) printf("time_range1 := %g - %g\n", xmin[0], xmax[0]);
290 printf("tac2->isframe := %d\n", d2->isframe);
291 if(verbose>2) printf("time_range2 := %g - %g\n", xmin[1], xmax[1]);
292 }
293
294 /* Set the accepted time difference */
295 double f, accepted_timedif=2.2; // sec
296 /* With short study the accepted time difference must be shorter */
297 f=xmax[0]-xmin[0]; if((xmax[1]-xmin[1])>f) f=xmax[1]-xmin[1];
298 f*=0.01; if(accepted_timedif>f) accepted_timedif=f;
299 if(verbose>1) {
300 printf("accepted_timedif := %g [s]\n", accepted_timedif);
301 fflush(stdout);
302 }
303
304 /* Compare sample times frame-by-frame */
305 int fi, n=0;
306 if(d1->isframe==0 && d2->isframe==0) {
307 if(verbose>2) {printf("frame mid times\n"); fflush(stdout);}
308 for(fi=0; fi<smaller_sampleNr; fi++) {
309 if(d1->x[fi]*ts1==d2->x[fi]*ts2) continue;
310 if(isnan(d1->x[fi]) && isnan(d2->x[fi])) continue; // match if both NaN
311 if(isnan(d1->x[fi]) || isnan(d2->x[fi])) {n++; continue;} // no match
312 f=fabs(d1->x[fi]*ts1-d2->x[fi]*ts2);
313 if(verbose>3) printf("timedif[%d] := %g\n", fi, f);
314 if(verbose>4) printf(" %g vs %g\n", ts1*d1->x[fi], ts2*d2->x[fi]);
315 if(f>accepted_timedif) n++;
316 }
317 } else if(d1->isframe!=0 && d2->isframe!=0) {
318 if(verbose>2) {printf("frame start and end times\n"); fflush(stdout);}
319 for(fi=0; fi<smaller_sampleNr; fi++) {
320 if(d1->x1[fi]*ts1==d2->x1[fi]*ts2) continue;
321 if(isnan(d1->x1[fi]) && isnan(d2->x1[fi])) continue; // match if both NaN
322 if(isnan(d1->x1[fi]) || isnan(d2->x1[fi])) {n++; continue;} // no match
323 f=fabs(d1->x1[fi]*ts1-d2->x1[fi]*ts2);
324 if(verbose>3) printf("timedif[%d] := %g\n", fi, f);
325 if(verbose>4) printf(" %g vs %g\n", ts1*d1->x1[fi], ts2*d2->x1[fi]);
326 if(f>accepted_timedif) n++;
327 }
328 for(fi=0; fi<smaller_sampleNr; fi++) {
329 if(d1->x2[fi]*ts1==d2->x2[fi]*ts2) continue;
330 if(isnan(d1->x2[fi]) && isnan(d2->x2[fi])) continue; // match if both NaN
331 if(isnan(d1->x2[fi]) || isnan(d2->x2[fi])) {n++; continue;} // no match
332 f=fabs(d1->x2[fi]*ts1-d2->x2[fi]*ts2);
333 if(verbose>3) printf("timedif[%d] := %g\n", fi, f);
334 if(verbose>4) printf(" %g vs %g\n", ts1*d1->x2[fi], ts2*d2->x2[fi]);
335 if(f>accepted_timedif) n++;
336 }
337 } else {
338 if(verbose>2) {printf("mixed frame times\n"); fflush(stdout);}
339 double x1, x2;
340 for(fi=0; fi<smaller_sampleNr; fi++) {
341 if(d1->isframe) x1=0.5*(d1->x1[fi]+d1->x2[fi]); else x1=d1->x[fi];
342 if(d2->isframe) x2=0.5*(d2->x1[fi]+d2->x2[fi]); else x2=d2->x[fi];
343 if(x1*ts1==x2*ts2) continue;
344 if(isnan(x1) && isnan(x2)) continue; // match if both NaN
345 if(isnan(x1) || isnan(x2)) {n++; continue;} // no match
346 f=fabs(x1*ts1-x2*ts2);
347 if(verbose>3) printf("timedif[%d] := %g\n", fi, f);
348 if(verbose>4) printf(" %g vs %g\n", x1, x2);
349 if(f>accepted_timedif) n++;
350 }
351 }
352 if(verbose>2) {printf("nr of different frame times := %d\n", n); fflush(stdout);}
353 if(n==0) return 1; else return 0;
354}

Referenced by tacInterpolate(), tacInterpolateInto(), and tacReadReference().

◆ tacXNaNs()

int tacXNaNs ( TAC * tac)
extern

Check TAC structure for missing sample times (x, or x1 and x2).

See also
tacDeleteMissingSamples, tacIsX, tacSetX
Returns
Returns the number of missing values that were found.
Parameters
tacPointer to TAC structure.

Definition at line 23 of file tacnan.c.

26 {
27 if(tac==NULL || tac->sampleNr<1) return(0);
28
29 int fi, nan_nr=0;
30 if(tac->isframe) {
31 for(fi=0; fi<tac->sampleNr; fi++) {
32 if(!isfinite(tac->x1[fi])) nan_nr++;
33 if(!isfinite(tac->x2[fi])) nan_nr++;
34 }
35 } else {
36 for(fi=0; fi<tac->sampleNr; fi++) {
37 if(!isfinite(tac->x[fi])) nan_nr++;
38 }
39 }
40 return(nan_nr);
41}

Referenced by tacDelay(), tacFixNaNs(), tacInterpolate(), tacInterpolateInto(), tacIsXContiguous(), tacNaNs(), tacSetXContiguous(), tacSortByTime(), and tacVerifyTimeOrder().

◆ tacXRange()

int tacXRange ( TAC * d,
double * xmin,
double * xmax )
extern

Get the range of x values (times) in TAC structure.

Data is not modified. Data does not need to be sorted. Data can contain NaNs, but x values are not omitted if y is NaN and x is not. Samples with zero weight are included.

See also
tacSampleXRange, tacIsX, tacExtractRange, tacCorrectFrameOverlap, tacYRange
Author
Vesa Oikonen
Returns
Returns <>0 in case of failure.
Parameters
dPointer to TAC struct
xminPointer to variable for min x value (NULL if not needed).
xmaxPointer to variable for max x value (NULL if not needed).

Definition at line 124 of file tacx.c.

131 {
132 if(xmin!=NULL) *xmin=nan("");
133 if(xmax!=NULL) *xmax=nan("");
134 /* Check the data */
135 if(d==NULL || d->sampleNr<1) return(1);
136 /* Find the min and max time */
137 double mi, ma, *xi, *xa;
138 mi=ma=nan("");
139 if(d->isframe) {xi=d->x1; xa=d->x2;} else xi=xa=d->x;
140 for(int i=0; i<d->sampleNr; i++) {
141 if(!isfinite(xi[i]) || !isfinite(xa[i])) continue;
142 if(isnan(mi) || isnan(ma)) {mi=xi[i]; ma=xa[i]; continue;}
143 if(xi[i]<mi) mi=xi[i]; else if(xa[i]>ma) ma=xa[i];
144 }
145 if(xmin!=NULL) *xmin=mi;
146 if(xmax!=NULL) *xmax=ma;
147 if(!isfinite(mi) || !isfinite(ma)) return(2);
148 return(0);
149}

Referenced by sifWeight(), tacAUC(), tacDelay(), tacDelayFit(), tacFittime(), tacInterpolate(), tacInterpolateInto(), tacInterpolateToEqualLengthFrames(), tacIsX(), tacReadModelingData(), and tacXMatch().

◆ tacXUnitConvert()

int tacXUnitConvert ( TAC * tac,
const int u,
TPCSTATUS * status )
extern

Convert X values (sample times) in TAC struct to the specified unit.

See also
tacYUnitConvert, unitConversionFactor
Returns
Returns TPCERROR_OK (0) when successful.
Parameters
tacPointer to TAC struct
uEnum unit
statusPointer to status data; enter NULL if not needed

Definition at line 23 of file tacunits.c.

30 {
31 int verbose=0; if(status!=NULL) verbose=status->verbose;
32 if(verbose>0) {printf("%s(%s)\n", __func__, unitName(u)); fflush(stdout);}
33 if(tac==NULL || tac->sampleNr<1) {
34 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
35 return TPCERROR_NO_DATA;
36 }
37
38 /* If both units are unknown, then return suitable error code */
39 if(u==UNIT_UNKNOWN && tac->tunit==UNIT_UNKNOWN) {
40 if(verbose>1) {printf(" unknown x units\n"); fflush(stdout);}
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNKNOWN_UNIT);
43 }
44
45 /* Determine the correction factor */
46 double cf;
47 cf=unitConversionFactor(tac->tunit, u);
48 if(isnan(cf)) {
49 if(verbose>1) {printf(" cannot make x conversion factor\n"); fflush(stdout);}
50 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_UNIT);
52 }
53
54 /* Multiply x values */
55 if(verbose>1) {printf(" converting x with factor %g\n", cf); fflush(stdout);}
56 for(int i=0; i<tac->sampleNr; i++) {
57 tac->x[i]*=cf; tac->x1[i]*=cf; tac->x2[i]*=cf;
58 }
59 /* Set new unit */
60 tac->tunit=u;
61
62 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
63 return(TPCERROR_OK);
64}

Referenced by tacInput2sim(), tacReadModelingData(), tacReadModelingInput(), tacReadReference(), tacSetWeights(), tacSetX(), and tacWriteSIF().

◆ tacYNaNs()

int tacYNaNs ( TAC * tac,
const int i )
extern

Check TAC structure for missing sample values (y).

See also
tacNaNs, tacFixNaNs
Returns
Returns the number of missing values that were found.
Parameters
tacPointer to TAC structure.
iIndex of TAC to test; <0 to test all TACs.

Definition at line 47 of file tacnan.c.

52 {
53 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1 || i>=tac->tacNr) return(0);
54
55 int ri, fi, nan_nr=0;
56 if(i>=0) {
57 for(fi=0; fi<tac->sampleNr; fi++)
58 if(!isfinite(tac->c[i].y[fi])) nan_nr++;
59 return(nan_nr);
60 }
61 for(ri=0; ri<tac->tacNr; ri++)
62 for(fi=0; fi<tac->sampleNr; fi++)
63 if(!isfinite(tac->c[ri].y[fi])) nan_nr++;
64 return(nan_nr);
65}

Referenced by tacDelay(), tacFixNaNs(), and tacNaNs().

◆ tacYRange()

int tacYRange ( TAC * d,
int i,
double * ymin,
double * ymax,
int * smin,
int * smax,
int * imin,
int * imax )
extern

Get the range of y values (concentrations) in TAC struct.

Data is not modified. Data does not need to be sorted. Data can contain NaNs, but y values omitted if corresponding x is NaN.

See also
tacYRangeInXRange, tacXRange, tacYUnitConvert, tacCopyTacc
Author
Vesa Oikonen
Returns
Returns <>0 in case of failure.
Parameters
dPointer to TAC structure.
iIndex of TAC, [0, ..., tacNr-1] ; enter <0 to search for max and/or min from all TACs.
yminPointer to variable for min y value (NULL if not needed).
ymaxPointer to variable for max y value (NULL if not needed).
sminPointer to variable where sample index of min y value will be stored (NULL if not needed).
smaxPointer to variable where sample index of max y value will be stored (NULL if not needed).
iminPointer to variable where tac index of min y value will be stored (NULL if not needed).
imaxPointer to variable where tac index of max y value will be stored (NULL if not needed).

Definition at line 26 of file tacy.c.

43 {
44 if(ymin!=NULL) *ymin=nan("");
45 if(ymax!=NULL) *ymax=nan("");
46 if(smin!=NULL) *smin=-1;
47 if(smax!=NULL) *smax=-1;
48 if(imin!=NULL) *imin=-1;
49 if(imax!=NULL) *imax=-1;
50 /* Check the data */
51 if(d==NULL || d->sampleNr<1) return(1);
52 /* Check the index */
53 if(i>=d->tacNr) return(2);
54
55 /* Find the min and max time */
56 double *xi, *xa;
57 if(d->isframe) {xi=d->x1; xa=d->x2;} else xi=xa=d->x;
58 double mi, ma;
59 mi=ma=nan("");
60 for(int j=0; j<d->sampleNr; j++) {
61 if(isnan(xi[j]) || isnan(xa[j])) continue;
62 for(int k=0; k<d->tacNr; k++) {
63 if(i>=0 && i!=k) continue;
64 if(isnan(mi) || isnan(ma)) {
65 mi=d->c[k].y[j]; ma=d->c[k].y[j];
66 if(smin!=NULL) *smin=j;
67 if(smax!=NULL) *smax=j;
68 if(imin!=NULL) *imin=k;
69 if(imax!=NULL) *imax=k;
70 continue;
71 }
72 if(d->c[k].y[j]<mi) {
73 mi=d->c[k].y[j];
74 if(smin!=NULL) *smin=j;
75 if(imin!=NULL) *imin=k;
76 } else if(d->c[k].y[j]>ma) {
77 ma=d->c[k].y[j];
78 if(smax!=NULL) *smax=j;
79 if(imax!=NULL) *imax=k;
80 }
81 }
82 }
83 if(ymin!=NULL) *ymin=mi;
84 if(ymax!=NULL) *ymax=ma;
85 if(isnan(mi) || isnan(ma)) return(2);
86 return(0);
87}

Referenced by mtgaPlotSVG().

◆ tacYRangeInXRange()

int tacYRangeInXRange ( TAC * d,
int i,
const double xmin,
const double xmax,
double * ymin,
double * ymax,
int * smin,
int * smax,
int * imin,
int * imax )
extern

Get the range of y values (concentrations) in TAC struct, including only samples with x (times) inside given range.

Data is not modified. Data does not need to be sorted. Data can contain NaNs, but y values omitted if corresponding x is NaN.

See also
tacYRange, tacXRange, tacYUnitConvert
Author
Vesa Oikonen
Returns
Returns <>0 in case of failure.
Parameters
dPointer to TAC structure.
iIndex of TAC, [0, ..., tacNr-1] ; enter <0 to search for max and/or min from all TACs.
xminMin x value.
xmaxMax x value.
yminPointer to variable for min y value (NULL if not needed).
ymaxPointer to variable for max y value (NULL if not needed).
sminPointer to variable where sample index of min y value will be stored (NULL if not needed).
smaxPointer to variable where sample index of max y value will be stored (NULL if not needed).
iminPointer to variable where tac index of min y value will be stored (NULL if not needed).
imaxPointer to variable where tac index of max y value will be stored (NULL if not needed).

Definition at line 99 of file tacy.c.

120 {
121 if(ymin!=NULL) *ymin=nan("");
122 if(ymax!=NULL) *ymax=nan("");
123 if(smin!=NULL) *smin=-1;
124 if(smax!=NULL) *smax=-1;
125 if(imin!=NULL) *imin=-1;
126 if(imax!=NULL) *imax=-1;
127 /* Check the data */
128 if(d==NULL || d->sampleNr<1) return(1);
129 /* Check the index */
130 if(i>=d->tacNr) return(2);
131 /* Check x range */
132 if(xmin>xmax) return(3);
133
134 /* Find the min and max time */
135 double *xi, *xa, x;
136 if(d->isframe) {xi=d->x1; xa=d->x2;} else xi=xa=d->x;
137 double mi, ma;
138 mi=ma=nan("");
139 for(int j=0; j<d->sampleNr; j++) {
140 if(isnan(xi[j]) || isnan(xa[j])) continue;
141 x=0.5*(xi[j]+xa[j]); if(x<xmin || x>xmax) continue;
142 for(int k=0; k<d->tacNr; k++) {
143 if(i>=0 && i!=k) continue;
144 if(isnan(mi) || isnan(ma)) {
145 mi=d->c[k].y[j]; ma=d->c[k].y[j];
146 if(smin!=NULL) *smin=j;
147 if(smax!=NULL) *smax=j;
148 if(imin!=NULL) *imin=k;
149 if(imax!=NULL) *imax=k;
150 continue;
151 }
152 if(d->c[k].y[j]<mi) {
153 mi=d->c[k].y[j];
154 if(smin!=NULL) *smin=j;
155 if(imin!=NULL) *imin=k;
156 } else if(d->c[k].y[j]>ma) {
157 ma=d->c[k].y[j];
158 if(smax!=NULL) *smax=j;
159 if(imax!=NULL) *imax=k;
160 }
161 }
162 }
163 if(ymin!=NULL) *ymin=mi;
164 if(ymax!=NULL) *ymax=ma;
165 if(isnan(mi) || isnan(ma)) return(2);
166 return(0);
167}

Referenced by tacPlotFitSVG(), tacPlotHistogramSVG(), and tacPlotLineSVG().

◆ tacYUnitConvert()

int tacYUnitConvert ( TAC * tac,
const int u,
TPCSTATUS * status )
extern

Convert Y values (concentrations) in TAC struct to the specified unit.

See also
tacXUnitConvert, unitConversionFactor
Returns
Returns TPCERROR_OK (0) when successful.
Parameters
tacPointer to TAC struct
uEnum unit
statusPointer to status data; enter NULL if not needed

Definition at line 72 of file tacunits.c.

79 {
80 int verbose=0; if(status!=NULL) verbose=status->verbose;
81 if(verbose>0) printf("%s(%s)\n", __func__, unitName(u));
82 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1) {
83 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
84 return TPCERROR_NO_DATA;
85 }
86
87 /* If both units are unknown, then return suitable error code */
88 if(u==UNIT_UNKNOWN && tac->cunit==UNIT_UNKNOWN) {
89 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNKNOWN_UNIT);
91 }
92
93 /* Determine the correction factor */
94 double cf;
95 cf=unitConversionFactor(tac->cunit, u);
96 if(isnan(cf)) {
97 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_UNIT);
99 }
100
101 /* Multiply y values */
102 for(int j=0; j<tac->tacNr; j++) {
103 for(int i=0; i<tac->sampleNr; i++) {
104 tac->c[j].y[i]*=cf;
105 }
106 }
107 /* Set new unit */
108 tac->cunit=u;
109
110 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
111 return(TPCERROR_OK);
112}

Referenced by tacReadModelingData(), tacReadModelingInput(), tacReadReference(), and tacSetWeights().

◆ tacYUnitMass2Volume()

int tacYUnitMass2Volume ( TAC * tac,
const double density,
TPCSTATUS * status )
extern

Convert Y values (per mass concentrations) in TAC struct to the corresponding per volume concentrations.

See also
tacYUnitVolume2Mass, tacXUnitConvert, tacYUnitConvert, unitConversionFactor
Returns
Returns TPCERROR_OK (0) when successful.
Parameters
tacPointer to TAC struct.
densityDensity (g/mL).
statusPointer to status data; enter NULL if not needed.

Definition at line 169 of file tacunits.c.

176 {
177 int verbose=0; if(status!=NULL) verbose=status->verbose;
178 if(verbose>0) {printf("%s(%g)\n", __func__, density); fflush(stdout);}
179 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1 || !(density>0.0)) {
180 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
181 return TPCERROR_NO_DATA;
182 }
183
184 /* Check that unit contains mass in divider */
185 if(!unitDividerHasMass(tac->cunit)) {
186 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_UNIT);
188 }
189
190 /* Try to convert the unit */
192 if(uu==UNIT_UNKNOWN) {
193 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_UNIT);
195 }
196
197 /* Multiply y values with the density */
198 for(int j=0; j<tac->tacNr; j++) {
199 for(int i=0; i<tac->sampleNr; i++) {
200 tac->c[j].y[i]*=density;
201 }
202 }
203 /* Set new unit */
204 tac->cunit=uu;
205
206 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
207 return(TPCERROR_OK);
208}
int unitDividerMassVolumeConversion(int u)
Definition units.c:775
int unitDividerHasMass(int u)
Definition units.c:694

◆ tacYUnitVolume2Mass()

int tacYUnitVolume2Mass ( TAC * tac,
const double density,
TPCSTATUS * status )
extern

Convert Y values (per volume concentrations) in TAC struct to the corresponding per mass concentrations.

See also
tacYUnitMass2Volume, tacXUnitConvert, tacYUnitConvert, unitConversionFactor
Returns
Returns TPCERROR_OK (0) when successful.
Parameters
tacPointer to TAC struct.
densityDensity (g/mL).
statusPointer to status data; enter NULL if not needed.

Definition at line 121 of file tacunits.c.

128 {
129 int verbose=0; if(status!=NULL) verbose=status->verbose;
130 if(verbose>0) {printf("%s(%g)\n", __func__, density); fflush(stdout);}
131 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1 || !(density>0.0)) {
132 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
133 return TPCERROR_NO_DATA;
134 }
135
136 /* Check that unit contains volume in divider */
137 if(!unitDividerHasVolume(tac->cunit)) {
138 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_UNIT);
140 }
141
142 /* Try to convert the unit */
144 if(uu==UNIT_UNKNOWN) {
145 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_UNIT);
147 }
148
149 /* Divide y values with the density */
150 for(int j=0; j<tac->tacNr; j++) {
151 for(int i=0; i<tac->sampleNr; i++) {
152 tac->c[j].y[i]/=density;
153 }
154 }
155 /* Set new unit */
156 tac->cunit=uu;
157
158 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
159 return(TPCERROR_OK);
160}
int unitDividerHasVolume(int u)
Definition units.c:678