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

I/O functions for automatic blood sampling system (ABSS) 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 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)

Detailed Description

I/O functions for automatic blood sampling system (ABSS) files.

Definition in file tacabss.c.

Function Documentation

◆ tacReadAllogg()

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

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
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
int iftSearchValue(IFT *ift, const char *s, int start_index)
Definition iftfind.c:114
int iftFindKey(IFT *ift, const char *key, int start_index)
Definition iftfind.c:30
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
char comment
Definition tpcift.h:27
char * value
Definition tpcift.h:37
char * key
Definition tpcift.h:32
IFT_ITEM * item
Definition tpcift.h:57
int type
Definition tpcift.h:51
int keyNr
Definition tpcift.h:47
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
double * x2
Definition tpctac.h:101
unit tunit
Definition tpctac.h:109
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 tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
@ UNIT_COUNTS
counts
@ UNIT_SEC
seconds
@ TPCERROR_NO_DATETIME
File contains no date or time.
@ TPCERROR_FAIL
General error.
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_MISSING_DATA
File contains missing values.
@ TAC_FORMAT_ABSS_ALLOGG
ALLOGG ABSS data; reading supported.
Definition tpctac.h:56

Referenced by tacRead().

◆ tacReadGEMS()

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

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
int tacReadScanditronics(TAC *tac, IFT *hdr, TPCSTATUS *status)
Definition tacabss.c:326
@ TAC_FORMAT_ABSS_GEMS
GEMS ABSS data; reading supported.
Definition tpctac.h:54

Referenced by tacRead(), and tacReadScanditronics().

◆ tacReadOldAllogg()

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

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
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
@ TAC_FORMAT_ABSS_ALLOGG_OLD
ALLOGG ABSS data (old format); reading supported.
Definition tpctac.h:55

Referenced by tacRead().

◆ tacReadScanditronics()

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

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
int tacReadGEMS(TAC *tac, IFT *hdr, TPCSTATUS *status)
Definition tacabss.c:516
@ TAC_FORMAT_ABSS_SCANDITRONICS
Scanditronics ABSS data; reading supported.
Definition tpctac.h:53

Referenced by tacRead(), and tacReadGEMS().