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

I/O functions for PMOD TAC file format. 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 tacWritePMOD (TAC *tac, FILE *fp, int extra, TPCSTATUS *status)
int tacReadPMOD (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)

Detailed Description

I/O functions for PMOD TAC file format.

Definition in file pmodio.c.

Function Documentation

◆ tacReadPMOD()

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

Read PMOD format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWritePMOD, tacRead
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to CSV from which data is read; if it contains only one column, then it is assumed to represent the first y column and x column is not filled.
hdrPointer to possible header data, which, if available, is processed and copied to TAC too; enter NULL if not available.
statusPointer to status data; enter NULL if not needed.

Definition at line 146 of file pmodio.c.

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}
double atofVerified(const char *s)
Definition decpoint.c:75
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
char * strdup(const char *s)
Definition stringext.c:185
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
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
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 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
int tacWMove(TAC *tac, int ow, TPCSTATUS *status)
Definition tacw.c:75
#define MAX_TACNAME_LEN
Max length of TAC ID name (not including trailing zero).
@ UNIT_UNKNOWN
Unknown unit.
@ 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.
int unitIdentify(const char *s)
Definition units.c:162
@ TAC_FORMAT_PMOD
PMOD TAC format.
Definition tpctac.h:33

Referenced by tacRead().

◆ tacWritePMOD()

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

Write TAC data into specified file pointer in PMOD.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadPMOD, tacWrite
Parameters
tacPointer to TAC structure, contents of which are to be written.
fpFile pointer to write to.
extraWrite (1) or do not write (0) also extra header fields found in IFT; note that these are not supported by other than TPC SW.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file pmodio.c.

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}
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
Definition iftio.c:98
void strReplaceChar(char *s, char c1, char c2)
Definition stringext.c:134
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155
int keyNr
Definition tpcift.h:47
double * w
Definition tpctac.h:111
void tacEnsureNames(TAC *tac)
Definition tacname.c:50
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
@ UNIT_MIN
minutes
@ UNIT_UNITLESS
Unitless.
@ UNIT_SEC
seconds
@ TPCERROR_CANNOT_WRITE
Cannot write file.
char * unitName(int unit_code)
Definition units.c:143

Referenced by tacWrite().