TPCCLIB
Loading...
Searching...
No Matches
pmodio.c
Go to the documentation of this file.
1
4/*****************************************************************************/
5#include "tpcclibConfig.h"
6/*****************************************************************************/
7#include "tpcift.h"
8#include "tpcisotope.h"
9#include "tpccsv.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <math.h>
14#include <time.h>
15#include <string.h>
16/*****************************************************************************/
17#include "tpctac.h"
18/*****************************************************************************/
19
20/*****************************************************************************/
28 TAC *tac,
30 FILE *fp,
33 int extra,
35 TPCSTATUS *status
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}
138/*****************************************************************************/
139
140/*****************************************************************************/
148 TAC *tac,
151 CSV *csv,
154 IFT *hdr,
156 TPCSTATUS *status
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}
312/*****************************************************************************/
313
314/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
Definition iftio.c:98
int tacReadPMOD(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition pmodio.c:146
int tacWritePMOD(TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
Definition pmodio.c:26
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
void strReplaceChar(char *s, char c1, char c2)
Definition stringext.c:134
char * strdup(const char *s)
Definition stringext.c:185
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155
int col
Definition tpccsv.h:28
int row
Definition tpccsv.h:26
char * content
Definition tpccsv.h:30
Definition tpccsv.h:36
int row_nr
Definition tpccsv.h:44
int col_nr
Definition tpccsv.h:46
CSV_item * c
Definition tpccsv.h:38
int nr
Definition tpccsv.h:42
Definition tpcift.h:43
int keyNr
Definition tpcift.h:47
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
Definition tpctac.h:87
double * x
Definition tpctac.h:97
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
double * w
Definition tpctac.h:111
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 tacGetHeaderUnit(TAC *tac, TPCSTATUS *status)
Definition tacift.c:145
int tacGetHeaderTimeunit(TAC *tac, TPCSTATUS *status)
Definition tacift.c:234
int tacSetHeaderTimeunit(IFT *h, int u)
Definition tacift.c:201
int tacSetHeaderUnit(IFT *h, int u)
Definition tacift.c:112
void tacEnsureNames(TAC *tac)
Definition tacname.c:50
int tacWMove(TAC *tac, int ow, TPCSTATUS *status)
Definition tacw.c:75
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
Header file for library libtpccsv.
#define MAX_TACNAME_LEN
Max length of TAC ID name (not including trailing zero)
@ UNIT_MIN
minutes
@ UNIT_UNKNOWN
Unknown unit.
@ UNIT_UNITLESS
Unitless.
@ UNIT_SEC
seconds
@ TPCERROR_FAIL
General error.
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_WEIGHTS
File contains no weights.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_CANNOT_WRITE
Cannot write file.
int unitIdentify(const char *s)
Definition units.c:162
char * unitName(int unit_code)
Definition units.c:143
Header file for library libtpcift.
Header file for library libtpcisotope.
Header file for library libtpctac.
@ TAC_FORMAT_PMOD
PMOD TAC format.
Definition tpctac.h:33