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

I/O functions for Scan Information Files. More...

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

Go to the source code of this file.

Functions

int tacWriteSIF (TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
 
int tacReadSIF (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
 

Detailed Description

I/O functions for Scan Information Files.

Definition in file sifio.c.

Function Documentation

◆ tacReadSIF()

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

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}
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:358
int csvPutString(CSV *csv, const char *s, int newline)
Definition csv.c:144
int csvReorg(CSV *d, TPCSTATUS *status)
Definition csv.c:503
int csvRowLength(CSV *csv, int row)
Definition csv.c:244
int csvList(CSV *csv, FILE *fp)
Definition csvio.c:27
int strDateTimeValid(const char *str, char *intdate)
Definition datetime.c:308
double atofVerified(const char *s)
Definition decpoint.c:75
char * isotopeName(int isotope_code)
Definition isotope.c:101
int isotopeIdentify(const char *isotope)
Definition isotope.c:145
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
int strTokenNCpy(const char *s1, const char *s2, int i, char *s3, int count)
Definition stringext.c:53
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
int col
Definition tpccsv.h:28
int row
Definition tpccsv.h:26
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
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
double * x
Definition tpctac.h:97
tacformat format
Definition tpctac.h:93
int _sampleNr
Definition tpctac.h:121
int sampleNr
Definition tpctac.h:89
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
int cunit
Definition tpctac.h:105
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
int tunit
Definition tpctac.h:109
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.
void tacFree(TAC *tac)
Definition tac.c:106
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
int tacSetHeaderScanstarttime(IFT *h, const char *s)
Definition tacift.c:427
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 tacSetHeaderIsotope(IFT *h, const char *s)
Definition tacift.c:341
int tacGetHeaderIsotope(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:290
int tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
@ UNIT_COUNTS
counts
@ UNIT_SEC
seconds
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_FAIL
General error.
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
#define MAX_STUDYNR_LEN
Define max study number length.
#define MAX_ISOTOPE_LEN
Max string length for PET isotope.
Definition tpcisotope.h:41
isotope
Definition tpcisotope.h:50
@ TAC_FORMAT_SIF
Scan information file.
Definition tpctac.h:43

Referenced by tacRead().

◆ tacWriteSIF()

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

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}
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
@ UNIT_MIN
minutes
@ TPCERROR_CANNOT_WRITE
Cannot write file.

Referenced by tacWrite().