TPCCLIB
Loading...
Searching...
No Matches
abssfch.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <math.h>
15/*****************************************************************************/
16#include "tpcextensions.h"
17#include "tpctac.h"
18#include "tpcabss.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
22static char *info[] = {
23 "Scanditronics and GEMS on-line blood sampler have sometimes failed to",
24 "correctly record the count data from either of the two channels, seen as",
25 "substantially lower or zero counts.",
26 "Use this program to calculate the channel1-to-channel2 ratio of coincidence",
27 "counts, or, to correct the data from failed channel using user-provided",
28 "correct channel1-to-channel2 ratio.",
29 " ",
30 "Usage: @P [options] abssfile [ratio]",
31 " ",
32 "Options:",
33 " -o=<filename>",
34 " Name for corrected file; by default the original file is overwritten.",
35 " -fix=<channel>",
36 " Set the channel (1 or 2) to fix; by default the channel with lower",
37 " counts is fixed.",
38 " -stdoptions", // List standard options like --help, -v, etc
39 " ",
40 "Example 1: calculate channel1-to-channel2 ratio.",
41 " @P us1328.bld",
42 "Example 2: correct the failed data with given channel1-to-channel2 ratio.",
43 " @P -o=us1328_corr.bld us1328.bld 0.982",
44 " ",
45 "See also: abssexam, absscal, abssbkg, absszero, absstime",
46 " ",
47 "Keywords: input, blood, calibration, ABSS",
48 0};
49/*****************************************************************************/
50
51/*****************************************************************************/
52/* Turn on the globbing of the command line, since it is disabled by default in
53 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
54 In Unix&Linux wildcard command line processing is enabled by default. */
55/*
56#undef _CRT_glob
57#define _CRT_glob -1
58*/
59int _dowildcard = -1;
60/*****************************************************************************/
61
62/*****************************************************************************/
66int main(int argc, char **argv)
67{
68 int ai, help=0, version=0, verbose=1;
69 char abssfile[FILENAME_MAX], outfile[FILENAME_MAX];
70 char *cptr;
71 double chRatio=nan("");
72 int chFix=0;
73 int ret;
74
75
76 /*
77 * Get arguments
78 */
79 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
80 abssfile[0]=outfile[0]=(char)0;
81 /* Options */
82 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
83 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
84 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
85 if(strncasecmp(cptr, "O=", 2)==0 && strlen(cptr)>2) {
86 strlcpy(outfile, cptr+2, FILENAME_MAX); continue;
87 } else if(strncasecmp(cptr, "FIX=", 4)==0 && strlen(cptr)>4) {
88 chFix=atoi(cptr+4); if(chFix==1 || chFix==2) continue;
89 }
90 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
91 return(1);
92 } else break;
93
94 TPCSTATUS status; statusInit(&status);
95 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
96 status.verbose=verbose-3;
97
98 /* Print help or version? */
99 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
100 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
101 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
102
103 /* Process other arguments, starting from the first non-option */
104 if(ai<argc) strlcpy(abssfile, argv[ai++], FILENAME_MAX);
105 if(ai<argc) {
106 if(atofCheck(argv[ai], &chRatio) || chRatio<=0.0) {
107 fprintf(stderr, "Error: invalid channel ratio '%s'.\n", argv[ai]);
108 return(1);
109 }
110 ai++;
111 }
112 if(ai<argc) {
113 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
114 return(1);
115 }
116 /* Did we get all the information that we need? */
117 if(!abssfile[0]) {
118 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
119 return(1);
120 }
121 if(!outfile[0]) strcpy(outfile, abssfile);
122 if(chFix!=0 && isnan(chRatio)) {
123 fprintf(stderr, "Error: missing channel ratio.\n");
124 return(1);
125 }
126
127
128 /* In verbose mode print arguments and options */
129 if(verbose>1) {
130 printf("abssfile := %s\n", abssfile);
131 if(!isnan(chRatio)) printf("chRatio := %g\n", chRatio);
132 if(chFix!=0) printf("chFix := %d\n", chFix);
133 printf("outfile := %s\n", outfile);
134 fflush(stdout);
135 }
136
137 /*
138 * Read ABSS file
139 */
140 if(verbose>1) printf("reading %s\n", abssfile);
141 TAC abss; tacInit(&abss);
142 ret=tacRead(&abss, abssfile, &status);
143 if(ret!=TPCERROR_OK) {
144 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
145 tacFree(&abss); return(2);
146 }
147 if(verbose>1) {
148 printf("sampleNr := %d\n", abss.sampleNr);
149 }
150 if(verbose>2) {
151 printf("fileformat := %d\n", abss.format);
152 printf("tacNr := %d\n", abss.tacNr);
153 }
154 if(abss.format!=TAC_FORMAT_ABSS_ALLOGG &&
158 {
159 fprintf(stderr, "Error: not valid ABSS format.\n");
160 tacFree(&abss); return(2);
161 }
162 if(verbose>100) abssWrite(&abss, stdout, NULL);
163 if(abss.tacNr<1 || abss.sampleNr<1) {
164 fprintf(stderr, "Error: not valid ABSS format.\n");
165 tacFree(&abss); return(2);
166 }
167 /* This program is useful only for Scanditronics/GEMS sampler */
168 if(abss.format!=TAC_FORMAT_ABSS_GEMS &&
170 {
171 fprintf(stderr, "Error: not applicable to provided ABSS system.\n");
172 tacFree(&abss); return(2);
173 }
174
175 /*
176 * Check for dead channels
177 */
178 if(verbose>1) printf("checking for dead channels\n");
179 int n1, n2, n;
180 n1=n2=n=0;
181 ret=abssAboveZero(&abss, &n1, &n2, &n);
182 if(ret!=0) {
183 fprintf(stderr, "Error: not valid ABSS format.\n");
184 tacFree(&abss); return(3);
185 }
186 if(verbose>1) {
187 printf("positive_samples[1] := %d\n", n1);
188 printf("positive_samples[2] := %d\n", n2);
189 printf("positive_samples := %d\n", n);
190 fflush(stdout);
191 }
192 if(n<1) {
193 fprintf(stderr, "Error: bad ABSS data.\n"); fflush(stderr);
194 tacFree(&abss); return(4);
195 }
196 if(n<abss.sampleNr/10) {
197 fprintf(stderr, "Warning: bad ABSS data.\n"); fflush(stderr);
198 }
199 int c1ok, c2ok;
200 if(n1<=n/2) c1ok=0; else c1ok=1;
201 if(n2<=n/2) c2ok=0; else c2ok=1;
202 /* If both channels have problems, then we can do nothing */
203 if(!c1ok && !c2ok) {
204 fprintf(stderr, "Error: bad ABSS data.\n"); fflush(stderr);
205 tacFree(&abss); return(4);
206 }
207 if(verbose>0 && !c1ok) printf("channel1 is dead\n");
208 if(verbose>0 && !c2ok) printf("channel2 is dead\n");
209 /* Check that user did not want to fix the only decent channel */
210 if(chFix==1 && !c2ok) {
211 fprintf(stderr, "Error: channel2 cannot be used to fix channel1.\n");
212 tacFree(&abss); return(4);
213 }
214 if(chFix==2 && !c1ok) {
215 fprintf(stderr, "Error: channel1 cannot be used to fix channel2.\n");
216 tacFree(&abss); return(4);
217 }
218
219
220 /*
221 * If neither channel is dead, then check which one gave more often
222 * lower counts
223 */
224 if(c1ok && c2ok) {
225 ret=abssHigherCounts(&abss, &n1, &n2);
226 if(ret!=0) {
227 fprintf(stderr, "Error: not valid ABSS format.\n");
228 tacFree(&abss); return(3);
229 }
230 if(verbose>1) {
231 printf("higher_samples[1] := %d\n", n1);
232 printf("higher_samples[2] := %d\n", n2);
233 fflush(stdout);
234 }
235 }
236
237
238 /*
239 * Calculate the channel ratio, and (usually) print it in stdout
240 */
241 if(verbose>1) {printf("calculating the ratio\n"); fflush(stdout);}
242 /* Ratio can only be calculated if both channels are okeish */
243 if(isnan(chRatio) && (c1ok+c2ok)<2) {
244 fprintf(stderr, "Error: cannot compute channel ratio.\n"); fflush(stderr);
245 tacFree(&abss); return(4);
246 }
247 double ratio=1.0;
248 if((c1ok+c2ok)==2) {
249 int nratio;
250 ret=abssCalculateRatio(&abss, &ratio, &nratio);
251 if(ret==0) {
252 if(verbose>1 || nratio<10) {
253 printf("channel ratio calculated from %d samples.\n", nratio);
254 fflush(stdout);
255 }
256 if(isnan(chRatio) || verbose>0) {
257 fprintf(stdout, "Ch1/Ch2 := %.6f\n", ratio);
258 fflush(stdout);
259 }
260 } else {
261 if(isnan(chRatio)) {
262 fprintf(stderr, "Error: cannot compute channel ratio.\n");
263 fflush(stderr); tacFree(&abss); return(5);
264 }
265 ratio=1.0;
266 }
267 }
268
269 /* If user did not give the true Ch1/Ch2, then quit */
270 if(isnan(chRatio)) {
271 if(verbose>1) printf("Ch1/ch2 not given; no correction done.\n");
272 tacFree(&abss); return(0);
273 }
274
275 /*
276 * Decide which channel to fix, if user did not tell it
277 */
278 if(chFix==0) {
279 if((c1ok+c2ok)==1) {
280 if(c1ok) chFix=2; else chFix=1;
281 } else if(n1>n2 && ratio>1.0) {
282 chFix=2;
283 } else if(n2>n1 && ratio<1.0) {
284 chFix=1;
285 } else {
286 fprintf(stderr, "Error: not sure which channel to fix.\n");
287 fflush(stderr); tacFree(&abss); return(6);
288 }
289 if(verbose>1) printf("chFix := %d\n", chFix);
290 }
291
292 /*
293 * Fix one of the channels
294 */
295 if(verbose>1) {printf("fixing channel %d\n", chFix); fflush(stdout);}
296 ret=abssFixChannel(&abss, chFix, chRatio);
297 if(ret!=0) {
298 fprintf(stderr, "Error: cannot fix channel counts.\n");
299 fflush(stderr); tacFree(&abss); return(7);
300 }
301 if(verbose>3) {
302 /* Compute the channel ratio again */
303 if(abssCalculateRatio(&abss, &ratio, NULL)==0) {
304 printf("channel ratio after correction := %g\n", ratio);
305 fflush(stdout);
306 }
307 }
308
309 /* Write the corrected data */
310 if(verbose>1) {
311 printf("writing corrected data file in %s\n", outfile); fflush(stdout);}
312 FILE *fp;
313 fp=fopen(outfile, "w");
314 if(fp==NULL) {
315 fprintf(stderr, "Error: cannot open file for writing.\n");
316 tacFree(&abss); return(11);
317 }
318 ret=abssWrite(&abss, fp, &status);
319 fclose(fp);
320 if(ret!=TPCERROR_OK) {
321 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
322 tacFree(&abss); return(12);
323 }
324 if(verbose>0) {
325 printf("corrected data written in %s\n", outfile);
326 fflush(stdout);
327 }
328
329 tacFree(&abss);
330 return(0);
331}
332/*****************************************************************************/
333
334/*****************************************************************************/
int abssAboveZero(TAC *abss, int *n1, int *n2, int *n)
Definition abss.c:23
int abssHigherCounts(TAC *abss, int *n1, int *n2)
Definition abss.c:82
int abssFixChannel(TAC *abss, int channel, double ratio)
Definition abss.c:192
int abssCalculateRatio(TAC *abss, double *ratio, int *n)
Definition abss.c:134
int abssWrite(TAC *d, FILE *fp, TPCSTATUS *status)
Definition abssio.c:53
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
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
Definition tpctac.h:87
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
void tacFree(TAC *tac)
Definition tac.c:106
void tacInit(TAC *tac)
Definition tac.c:24
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
Header file for libtpcabss.
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
Header file for library libtpctac.
@ 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