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

Header file for libtpcabss. More...

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

Go to the source code of this file.

Enumerations

enum  ABSS_DEVICE {
  ABSS_UNKNOWN , ABSS_SCANDITRONICS , ABSS_GEMS , ABSS_ALLOGG_OLD ,
  ABSS_ALLOGG
}

Functions

ABSS_DEVICE abssIdFromFName (const char *fname)
int abssWrite (TAC *d, FILE *fp, TPCSTATUS *status)
int abssAboveZero (TAC *abss, int *n1, int *n2, int *n)
int abssHigherCounts (TAC *abss, int *n1, int *n2)
int abssCalculateRatio (TAC *abss, double *ratio, int *n)
int abssFixChannel (TAC *abss, int channel, double ratio)
int abssCalculateCps (TAC *abss)
int abssChannelMean (TAC *abss, double *mean)

Detailed Description

Header file for libtpcabss.

Defines for ABSS library.

Author
Vesa Oikonen

Definition in file tpcabss.h.

Enumeration Type Documentation

◆ ABSS_DEVICE

Individual ID number for automatic blood sampling system (ABSS), so that appropriate calibration, dead-time and dispersion correction coefficients can be applied.

Definition at line 30 of file tpcabss.h.

30 {
31 ABSS_UNKNOWN, ABSS_SCANDITRONICS, ABSS_GEMS,
32 ABSS_ALLOGG_OLD, ABSS_ALLOGG
ABSS_DEVICE
Definition tpcabss.h:30

Function Documentation

◆ abssAboveZero()

int abssAboveZero ( TAC * abss,
int * n1,
int * n2,
int * n )

Calculate the number of ABSS samples with positive counts.

See also
tacRead, abssWrite, abssHigherCounts, abssCalculateRatio, abssFixChannel
Returns
Returns <>0 in case of an error.
Parameters
abssPointer to TAC struct containing raw ABSS data.
n1Number of positive samples in channel 1 is written in here; enter NULL if not needed.
n2Number of positive samples in channel 2 is written in here; enter NULL if not needed.
nNumber of samples with positive counts in either of channels; enter NULL if not needed.

Definition at line 23 of file abss.c.

35 {
36 if(n1!=NULL) *n1=0;
37 if(n2!=NULL) *n2=0;
38 if(n!=NULL) *n=0;
39 /* Check the data */
40 if(abss==NULL || abss->tacNr<1 || abss->sampleNr<1) return(1);
41 if(abss->format!=TAC_FORMAT_ABSS_ALLOGG &&
45 {
46 return(2);
47 }
48
49 /* Set the data columns */
50 int c1, c2;
53 {
54 c1=0; c2=1;
55 } else {
56 c1=0; c2=3;
57 }
58 if(c2>=abss->tacNr) {return(3);}
59
60 /* Count the samples with positive counts */
61 int m1, m2, m;
62 m1=m2=m=0;
63 for(int i=0; i<abss->sampleNr; i++) {
64 if(abss->c[c1].y[i]>0.0) m1++;
65 if(abss->c[c2].y[i]>0.0) m2++;
66 if(abss->c[c1].y[i]>0.0 || abss->c[c2].y[i]>0.0) m++;
67 }
68 if(n1!=NULL) *n1=m1;
69 if(n2!=NULL) *n2=m2;
70 if(n!=NULL) *n=m;
71
72 return(0);
73}
double * y
Definition tpctac.h:75
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
TACC * c
Definition tpctac.h:117
int tacNr
Definition tpctac.h:91
@ TAC_FORMAT_ABSS_ALLOGG
ALLOGG ABSS data; reading supported.
Definition tpctac.h:56
@ TAC_FORMAT_ABSS_GEMS
GEMS ABSS data; reading supported.
Definition tpctac.h:54
@ TAC_FORMAT_ABSS_ALLOGG_OLD
ALLOGG ABSS data (old format); reading supported.
Definition tpctac.h:55
@ TAC_FORMAT_ABSS_SCANDITRONICS
Scanditronics ABSS data; reading supported.
Definition tpctac.h:53

◆ abssCalculateCps()

int abssCalculateCps ( TAC * abss)

Divide the ABSS coincident counts by frame duration.

See also
tacRead, abssWrite, abssCalculateRatio, abssFixChannel
Returns
Returns <>0 in case of an error.
Parameters
abssPointer to TAC struct containing raw ABSS data.

Definition at line 244 of file abss.c.

247 {
248 /* Check the data */
249 if(abss==NULL || abss->tacNr<1 || abss->sampleNr<1) return(1);
250 if(abss->format!=TAC_FORMAT_ABSS_ALLOGG &&
254 {
255 return(2);
256 }
257
258 /* Set the data columns */
259 int c1, c2;
260 if(abss->format==TAC_FORMAT_ABSS_ALLOGG ||
262 {
263 c1=0; c2=1;
264 } else {
265 c1=0; c2=3;
266 }
267 if(c2>=abss->tacNr) {return(3);}
268
269 /* Count the cps for both channels */
270 double fdur;
271 for(int i=0; i<abss->sampleNr; i++) {
272 fdur=abss->x2[i]-abss->x1[i]; if(!(fdur>0.0)) continue;
273 abss->c[c1].y[i]/=fdur;
274 abss->c[c2].y[i]/=fdur;
275 }
276
277 return(0);
278}
double * x2
Definition tpctac.h:101
double * x1
Definition tpctac.h:99

◆ abssCalculateRatio()

int abssCalculateRatio ( TAC * abss,
double * ratio,
int * n )

Calculate the number of ABSS samples with positive counts.

See also
tacRead, abssWrite, abssFixChannel
Returns
Returns <>0 in case of an error.
Parameters
abssPointer to TAC struct containing raw ABSS data.
ratioChannel1-to-channel2 is written in here.
nNumber of samples which could be used in calculation of the ratio; enter NULL if not needed.

Definition at line 134 of file abss.c.

142 {
143 if(ratio!=NULL) *ratio=nan("");
144 if(n!=NULL) *n=0;
145 /* Check the data */
146 if(abss==NULL || abss->tacNr<1 || abss->sampleNr<1) return(1);
147 if(abss->format!=TAC_FORMAT_ABSS_ALLOGG &&
151 {
152 return(2);
153 }
154
155 /* Set the data columns */
156 int c1, c2;
157 if(abss->format==TAC_FORMAT_ABSS_ALLOGG ||
159 {
160 c1=0; c2=1;
161 } else {
162 c1=0; c2=3;
163 }
164 if(c2>=abss->tacNr) {return(3);}
165
166 /* Count the cps sum for both channels */
167 double s1, s2, v1, v2, fdur, r;
168 s1=s2=0.0;
169 int m=0;
170 for(int i=0; i<abss->sampleNr; i++) {
171 fdur=abss->x2[i]-abss->x1[i]; if(!(fdur>0.0)) continue;
172 v1=abss->c[c1].y[i]/fdur; v2=abss->c[c2].y[i]/fdur;
173 if(!isfinite(v1) || !isfinite(v2)) continue;
174 s1+=v1; s2+=v2; m++;
175 }
176 if(m<1) {return(4);}
177
178 /* Calculate the ratio of sums */
179 r=s1/s2; if(!isfinite(r)) {return(5);}
180 if(ratio!=NULL) *ratio=r;
181 if(n!=NULL) *n=m;
182
183 return(0);
184}

◆ abssChannelMean()

int abssChannelMean ( TAC * abss,
double * mean )

Compute the mean of the two channels in Scanditronics or GEMS ABSS data stored in TAC struct.

If data is collected with Allogg, then column two is copied to 'mean' as such. Data is not divided by frame duration in this function.

See also
tacRead, abssCalculateCps, abssCalculateRatio
Returns
Returns <>0 in case of an error.
Parameters
abssPointer to TAC struct containing raw ABSS data.
meanPointer to double array, at least of length abss->sampleNr.

Definition at line 292 of file abss.c.

297 {
298 /* Check the data */
299 if(abss==NULL || abss->tacNr<1 || abss->sampleNr<1) return(1);
300 if(abss->format!=TAC_FORMAT_ABSS_ALLOGG &&
304 {
305 return(2);
306 }
307 if(mean==NULL) return(3);
308
309 /* Set the data columns */
310 int c1, c2;
311 if(abss->format==TAC_FORMAT_ABSS_ALLOGG ||
313 {
314 c1=0; c2=1;
315 } else {
316 c1=0; c2=3;
317 }
318 if(c2>=abss->tacNr) {return(3);}
319
320 /* If Allogg, the just copy, and then return */
321 if(abss->format==TAC_FORMAT_ABSS_ALLOGG ||
323 {
324 for(int i=0; i<abss->sampleNr; i++) mean[i]=abss->c[c2].y[i];
325 return(0);
326 }
327
328 /* Otherwise, compute the average for each sample frame */
329 for(int i=0; i<abss->sampleNr; i++) {
330 mean[i]=0.5*(abss->c[c1].y[i]+abss->c[c2].y[i]);
331 }
332
333 return(0);
334}

◆ abssFixChannel()

int abssFixChannel ( TAC * abss,
int channel,
double ratio )

Calculate the number of ABSS samples with positive counts.

See also
abssAboveZero, abssCalculateRatio, tacRead, abssWrite, abssCalculateRatio
Returns
Returns <>0 in case of an error.
Parameters
abssPointer to TAC struct containing raw ABSS data.
channelChannel to fix; either 1 or 2.
ratioCorrect channel1-to-channel2 ratio.

Definition at line 192 of file abss.c.

199 {
200 /* Check the data */
201 if(abss==NULL || abss->tacNr<1 || abss->sampleNr<1) return(1);
202 if(abss->format!=TAC_FORMAT_ABSS_ALLOGG &&
206 {
207 return(2);
208 }
209 if(channel!=1 && channel!=2) return(3);
210 if(!isfinite(ratio) || ratio<=0.0) return(4);
211
212 /* Set the data columns */
213 int c1, c2;
214 if(abss->format==TAC_FORMAT_ABSS_ALLOGG ||
216 {
217 c1=0; c2=1;
218 } else {
219 c1=0; c2=3;
220 }
221 if(c2>=abss->tacNr) {return(5);}
222
223 /* Fix the samples */
224 double f;
225 if(channel==1) {
226 f=ratio;
227 for(int i=0; i<abss->sampleNr; i++)
228 abss->c[c1].y[i]=f*abss->c[c2].y[i];
229 } else {
230 f=1.0/ratio;
231 for(int i=0; i<abss->sampleNr; i++)
232 abss->c[c2].y[i]=f*abss->c[c1].y[i];
233 }
234
235 return(0);
236}

◆ abssHigherCounts()

int abssHigherCounts ( TAC * abss,
int * n1,
int * n2 )

Calculate the number of ABSS samples which are positive and higher than the counts from the other channel.

See also
abssAboveZero, abssCalculateRatio, tacRead, abssWrite
Returns
Returns <>0 in case of an error.
Parameters
abssPointer to TAC struct containing raw ABSS data.
n1Number of samples in channel 1 that are positive and higher than counts from channel 2.
n2Number of samples in channel 2 that are positive and higher than counts from channel 1.

Definition at line 82 of file abss.c.

91 {
92 if(n1!=NULL) *n1=0;
93 if(n2!=NULL) *n2=0;
94 /* Check the data */
95 if(abss==NULL || abss->tacNr<1 || abss->sampleNr<1) return(1);
96 if(abss->format!=TAC_FORMAT_ABSS_ALLOGG &&
100 {
101 return(2);
102 }
103
104 /* Set the data columns */
105 int c1, c2;
106 if(abss->format==TAC_FORMAT_ABSS_ALLOGG ||
108 {
109 c1=0; c2=1;
110 } else {
111 c1=0; c2=3;
112 }
113 if(c2>=abss->tacNr) {return(3);}
114
115 /* Count the samples */
116 int m1, m2, m;
117 m1=m2=m=0;
118 for(int i=0; i<abss->sampleNr; i++) {
119 if(abss->c[c1].y[i]>abss->c[c2].y[i] && abss->c[c1].y[i]>0.0) m1++;
120 if(abss->c[c2].y[i]>abss->c[c1].y[i] && abss->c[c2].y[i]>0.0) m2++;
121 }
122 if(n1!=NULL) *n1=m1;
123 if(n2!=NULL) *n2=m2;
124
125 return(0);
126}

◆ abssIdFromFName()

ABSS_DEVICE abssIdFromFName ( const char * fname)

Identify ABSS device based on filename.

Returns
the enum ABSS_DEVICE, which is ABSS_UNKNOWN if format cannot be identified.
See also
tacRead, abssWrite
Parameters
fnameABSS data filename

Definition at line 30 of file abssio.c.

33 {
34 if(fname==NULL || strnlen(fname, 10)<5) return(ABSS_UNKNOWN);
35 /* Get pointer to the extension, starting with the dot */
36 char *cptr=filenameGetExtension(fname);
37 if(cptr==NULL) return(ABSS_UNKNOWN);
38 if(strcasecmp(cptr, ".lis")==0) return(ABSS_SCANDITRONICS);
39 if(strcasecmp(cptr, ".bld")==0) return(ABSS_GEMS);
40 if(strcasecmp(cptr, ".alg")==0) return(ABSS_ALLOGG_OLD);
41 if(strcasecmp(cptr, ".txt")==0) return(ABSS_ALLOGG);
42 return(ABSS_UNKNOWN);
43}
char * filenameGetExtension(const char *s)
Get the last extension of a file name.
Definition filename.c:178
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566

◆ abssWrite()

int abssWrite ( TAC * d,
FILE * fp,
TPCSTATUS * status )

Write ABSS data into file opened for writing.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacRead, tacInit, tacFree, abssIdFromFName
Author
Vesa Oikonen
Parameters
dPointer to ABSS data, stored in TAC struct, contents of which are to be written
fpOutput file pointer
statusPointer to status data; enter NULL if not needed

Definition at line 53 of file abssio.c.

61 {
62 int verbose=0; if(status!=NULL) verbose=status->verbose;
63 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
64 if(fp==NULL) {
65 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
67 }
68 if(d==NULL || d->sampleNr<1 || d->tacNr<1) {
69 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
70 return TPCERROR_NO_DATA;
71 }
72
73 char buf[1024];
74 int ret=TPCERROR_OK;
75
77
78 ret=TPCERROR_OK;
79
80 /* Write the header */
81 int ii;
82 d->h.space_before_eq=0; d->h.space_after_eq=1; /* Set no space before ':' */
83 ii=iftFindKey(&d->h, "Protocol", 0);
84 if(ii>=0) ret=iftWriteItem(&d->h, ii, fp, status);
85 if(ret!=TPCERROR_OK) {
86 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
87 }
88
89 if(tacGetHeaderStudynr(&d->h, buf, NULL)!=TPCERROR_OK) {
90 ii=iftFindKey(&d->h, "Patient", 0);
91 if(ii>=0) strlcpy(buf, d->h.item[ii].value, 256); else strcpy(buf, "");
92 }
93 fprintf(fp, "# Patient: %s\n", buf);
94
95 if(tacGetHeaderIsotope(&d->h, buf, NULL)==TPCERROR_OK) {
96 double hl=isotopeHalflife(isotopeIdentify(buf));
97 if(!isnan(hl)) sprintf(buf, "%f", hl); else strcpy(buf, "");
98 } else {
99 ii=iftFindKey(&d->h, "Isotope half-life", 0);
100 if(ii>=0) strlcpy(buf, d->h.item[ii].value, 256); else strcpy(buf, "");
101 }
102 fprintf(fp, "# Isotope half-life: %s\n", buf);
103
104 fprintf(fp, "# Start Interv 1st detector pair");
105 fprintf(fp, " 2nd detector pair AUX\n");
106 fprintf(fp, "# time time coinc singl1 singl2");
107 fprintf(fp, " coinc singl1 singl2 counts\n");
108
109 ii=iftFindKey(&d->h, "sampler_start_time", 0);
110 if(ii>=0) {
111 fprintf(fp, "# %s\n", d->h.item[ii].value);
112 } else if(tacGetHeaderScanstarttime(&d->h, buf, NULL)==TPCERROR_OK) {
113 fprintf(fp, "# %s\n", buf);
114 }
115
116
117 /* Write the sample data */
118 double sod=0.0; /* Time from start of the day */
119 if(tacGetHeaderScanstarttime(&d->h, buf, NULL)==TPCERROR_OK) {
120 struct tm tmsod;
121 if(!strDateTimeRead(buf, &tmsod))
122 sod=3600.*tmsod.tm_hour+60.*tmsod.tm_min+tmsod.tm_sec;
123 }
124 int i, j;
125 for(i=0; i<d->sampleNr; i++) {
126 fprintf(fp, "%9.1f %9.1f %9.1f", sod+d->x1[i], d->x1[i], d->x2[i]-d->x1[i]);
127 for(j=0; j<7; j++) {
128 if(j<d->tacNr) fprintf(fp, " %7.0f", d->c[j].y[i]);
129 else fprintf(fp, " %7.0f", 0.0);
130 }
131 if(fprintf(fp, "\n")<1) {ret=TPCERROR_CANNOT_WRITE; break;}
132 }
133 if(ret!=TPCERROR_OK) {
134 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
135 }
136
137 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
138 return(TPCERROR_OK);
139 }
140
141
143
144 ret=TPCERROR_OK;
145
146 /* Write the header */
147 fprintf(fp, "# Scanditronics Automated Blood Measurement System\n");
148 int ii;
149 d->h.space_before_eq=0; d->h.space_after_eq=1; /* Set no space before ':' */
150 ii=iftFindKey(&d->h, "Protocol", 0);
151 if(ii>=0) ret=iftWriteItem(&d->h, ii, fp, status);
152 if(ret!=TPCERROR_OK) {
153 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
154 }
155
156 fprintf(fp, "# Start Interv 1st detector pair");
157 fprintf(fp, " 2nd detector pair AUX\n");
158 fprintf(fp, "# time time coinc singl1 singl2");
159 fprintf(fp, " coinc singl1 singl2 counts\n");
160
161 ii=iftFindKey(&d->h, "sampler_start_time", 0);
162 if(ii>=0) {
163 fprintf(fp, "# %s\n", d->h.item[ii].value);
164 } else if(tacGetHeaderScanstarttime(&d->h, buf, NULL)==TPCERROR_OK) {
165 fprintf(fp, "# %s\n", buf);
166 }
167
168
169 /* Write the sample data */
170 time_t t=0.0;
171 if(tacGetHeaderScanstarttime(&d->h, buf, NULL)==TPCERROR_OK) {
172 //printf("scanstarttime=%s\n", buf);
173 struct tm tmsod;
174 if(!strDateTimeRead(buf, &tmsod)) t=mktime(&tmsod);
175 }
176 int i, j;
177 for(i=0; i<d->sampleNr; i++) {
178 fprintf(fp, "%13.1f %9.1f %9.1f",
179 d->x1[i]+(unsigned long int)t, d->x1[i], d->x2[i]-d->x1[i]);
180 for(j=0; j<7; j++) {
181 if(j<d->tacNr) fprintf(fp, " %7.0f", d->c[j].y[i]);
182 else fprintf(fp, " %7.0f", 0.0);
183 }
184 if(fprintf(fp, "\n")<1) {ret=TPCERROR_CANNOT_WRITE; break;}
185 }
186 if(ret!=TPCERROR_OK) {
187 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
188 }
189
190 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
191 return(TPCERROR_OK);
192 }
193
194
196
197 ret=TPCERROR_OK;
198
199 if(d->tacNr<2) {
200 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
201 return(TPCERROR_NO_DATA);
202 }
203
204 /* Write the header */
205 fprintf(fp, "# Allogg1\n");
206 int ii;
207 d->h.space_before_eq=0; d->h.space_after_eq=1; /* Set no space before ':' */
208
209 ii=iftFindKey(&d->h, "Protocol", 0);
210 if(ii>=0) ret=iftWriteItem(&d->h, ii, fp, status);
211 if(ret!=TPCERROR_OK) {
212 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
213 }
214
215 ii=iftFindKey(&d->h, "Discriminators", 0);
216 if(ii>=0) ret=iftWriteItem(&d->h, ii, fp, status);
217 if(ret!=TPCERROR_OK) {
218 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
219 }
220
221 if(tacGetHeaderScanstarttime(&d->h, buf, NULL)==TPCERROR_OK) {
222 fprintf(fp, "# %s\n", buf);
223 }
224
225 ii=iftSearchKey(&d->h, "Background", 0);
226 if(ii>=0) ret=iftWriteItem(&d->h, ii, fp, status);
227 if(ret!=TPCERROR_OK) {
228 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
229 }
230
231 /* Start time in format HHMMSS */
232 if(tacGetHeaderScanstarttime(&d->h, buf, NULL)==TPCERROR_OK) {
233 fprintf(fp, "\n%2.2s%2.2s%2.2s\n", buf+11, buf+14, buf+17);
234 } else {
235 fprintf(fp, "\n000000\n");
236 }
237
238 /* Write the sample data */
239 for(int i=0; i<d->sampleNr; i++) {
240 if(fprintf(fp, "%6.1f %5.0f %5.0f\n",
241 d->x2[i], d->c[0].y[i], d->c[1].y[i]) < 10)
242 {
243 ret=TPCERROR_CANNOT_WRITE; break;
244 }
245 }
246 if(ret!=TPCERROR_OK) {
247 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
248 }
249
250 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
251 return(TPCERROR_OK);
252 }
253
254
256
257 if(d->tacNr<2) {
258 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
259 return(TPCERROR_NO_DATA);
260 }
261
262 int ii;
263 //d->h.space_before_eq=0; d->h.space_after_eq=1; /* Set no space before ':' */
264 ret=TPCERROR_OK;
265
266 /* Write the background */
267 ii=iftSearchKey(&d->h, "background counts", 0);
268 if(ii>=0 &&
269 fprintf(fp, "%s :\t%s\n", d->h.item[ii].key, d->h.item[ii].value)<10)
270 {
271 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
273 }
274
275 /* Write the header */
276 fprintf(fp, "//Heading\n");
277
278 ii=iftFindKey(&d->h, "System ID", 0);
279 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
280 ii=iftFindKey(&d->h, "User name", 0);
281 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
282 ii=iftFindKey(&d->h, "Run number", 0);
283 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
284 ii=iftFindKey(&d->h, "Patient ID", 0);
285 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
286 ii=iftFindKey(&d->h, "HalfTime", 0);
287 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
288 ii=iftFindKey(&d->h, "Tube length", 0);
289 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
290 ii=iftFindKey(&d->h, "Pump speed", 0);
291 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
292 ii=iftFindKey(&d->h, "DeadTimeSingles", 0);
293 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
294 ii=iftFindKey(&d->h, "DeadTimeCoincidents", 0);
295 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
296 ii=iftFindKey(&d->h, "DiscriminatorSingles", 0);
297 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
298 ii=iftFindKey(&d->h, "DiscriminatorCoincidents", 0);
299 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
300 ii=iftFindKey(&d->h, "EffectivitySingles", 0);
301 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
302 ii=iftFindKey(&d->h, "EffectivityCoincidents", 0);
303 if(ii>=0) fprintf(fp, "%s:\t%s\n", d->h.item[ii].key, d->h.item[ii].value);
304
305 /* Write the data */
306 if(fprintf(fp, "//Data\n")<6) {
307 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
309 }
310 fprintf(fp, "Absolute time\t");
311 fprintf(fp, "Time after start [s]\t");
312 fprintf(fp, "Singles [cnt]\t");
313 fprintf(fp, "Coincidents [cnt]\t");
314 fprintf(fp, "Singles count rate [kBq/ml]\t");
315 fprintf(fp, "Coincidents count rate [kBq/ml]\t");
316 fprintf(fp, "Singles count rate DTC [kBq/ml]\t");
317 fprintf(fp, "Coincidents count rate DTC [kBq/ml]\t");
318 fprintf(fp, "Singles DTC&decay [kBq/ml]\t");
319 fprintf(fp, "Coincidents DTC&decay [kBq/ml]\n");
320 struct tm tmtod;
321 if(tacGetHeaderScanstarttime(&d->h, buf, NULL)==TPCERROR_OK) {
322 //printf("scanstarttime=%s\n", buf);
323 strDateTimeRead(buf, &tmtod);
324 }
325 int i, j;
326 for(i=0; i<d->sampleNr; i++) {
327 if(i>0) tmAdd(d->x1[i]-d->x1[i-1], &tmtod);
328 if(strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &tmtod)==0)
329 strcpy(buf, "1970-01-01 00:00:00");
330 fprintf(fp, "%s\t%.1f\t%.0f\t%.0f",
331 buf, d->x1[i], d->c[0].y[i], d->c[1].y[i]);
332 for(j=2; j<8; j++) {
333 if(j<d->tacNr) fprintf(fp, "\t%.12f", d->c[j].y[i]);
334 else fprintf(fp, "\t%f", 0.0);
335 }
336 if(fprintf(fp, "\n")<1) {ret=TPCERROR_CANNOT_WRITE; break;}
337 }
338 if(ret!=TPCERROR_OK) {
339 statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);
340 }
341
342 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
343 return(TPCERROR_OK);
344 }
345
346
347 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
348 return(TPCERROR_UNSUPPORTED);
349}
int strDateTimeRead(const char *str, struct tm *date)
Definition datetime.c:350
void tmAdd(int s, struct tm *d)
Definition datetime.c:500
int iftSearchKey(IFT *ift, const char *s, int start_index)
Definition iftfind.c:86
int iftFindKey(IFT *ift, const char *key, int start_index)
Definition iftfind.c:30
int iftWriteItem(IFT *ift, int item, FILE *fp, TPCSTATUS *status)
Definition iftio.c:25
double isotopeHalflife(int isotope_code)
Definition isotope.c:62
int isotopeIdentify(const char *isotope)
Definition isotope.c:145
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
char * value
Definition tpcift.h:37
char * key
Definition tpcift.h:32
IFT_ITEM * item
Definition tpcift.h:57
int space_after_eq
Definition tpcift.h:55
int space_before_eq
Definition tpcift.h:53
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
int verbose
Verbose level, used by statusPrint() etc.
int tacGetHeaderScanstarttime(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:372
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:26
int tacGetHeaderIsotope(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:290
@ TPCERROR_UNSUPPORTED
Unsupported file type.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_CANNOT_WRITE
Cannot write file.