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

I/O functions for CSV and TSV 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 tacWriteCSV (TAC *tac, FILE *fp, int extra, tacformat format, TPCSTATUS *status)
int tacReadCSV (TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
int tacReadInveonCSV (TAC *tac, CSV *csv, TPCSTATUS *status)
int tacReadCarimasTxt (TAC *tac, CSV *csv, TPCSTATUS *status)

Detailed Description

I/O functions for CSV and TSV TAC file format.

Definition in file taccsv.c.

Function Documentation

◆ tacReadCarimasTxt()

int tacReadCarimasTxt ( TAC * tac,
CSV * csv,
TPCSTATUS * status )

Read Carimas TXT TAC format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadCSV, 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.
statusPointer to status data; enter NULL if not needed.

Definition at line 631 of file taccsv.c.

639 {
640 int verbose=0; if(status!=NULL) verbose=status->verbose;
641 if(verbose>0) printf("%s()\n", __func__);
642 if(tac==NULL) {
643 if(verbose>0) printf("tac := NULL\n");
644 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
645 return TPCERROR_FAIL;
646 }
647
648 tacFree(tac);
649
650 if(verbose>2) {
651 printf("csv.row_nr := %d\n", csv->row_nr);
652 printf("csv.col_nr := %d\n", csv->col_nr);
653 }
654 if(csv==NULL || csv->row_nr<6 || csv->col_nr<2) {
655 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
656 return TPCERROR_NO_DATA;
657 }
658
659 /* Check that data indeed is CSV TAC data */
660 if(strcasecmp(csvCell(csv, 1, 0), "Num Voxels")!=0 ||
661 strncasecmp(csvCell(csv, 2, 0), "Volume (mm^3)", 6)!=0 ||
662 strncasecmp(csvCell(csv, 3, 0), "Times(s)", 5)!=0 )
663 {
664 if(verbose>0) {
665 printf("cell[%d][%d] := '%s'\n", 1, 0, csvCell(csv, 1, 0));
666 printf("cell[%d][%d] := '%s'\n", 2, 0, csvCell(csv, 2, 0));
667 printf("cell[%d][%d] := '%s'\n", 3, 0, csvCell(csv, 3, 0));
668 }
669 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
671 }
672
673 char *cptr;
674 int ret, fi, ri, oknr;
675
676 /* Allocate memory for TAC data */
677 ret=tacAllocate(tac, csv->row_nr-4, csv->col_nr-1);
678 statusSet(status, __func__, __FILE__, __LINE__, ret);
679 if(ret!=TPCERROR_OK) return ret;
680 tac->tacNr=csv->col_nr-1; tac->sampleNr=csv->row_nr-4;
681 tac->isframe=1;
682 // initiate the format, may be changed later if necessary
684
685 /* Get time unit from the 4th nonempty title line, inside parens */
686 tac->tunit=UNIT_UNKNOWN;
687 cptr=csvCell(csv, 3, 0);
688 if(cptr!=NULL && strncasecmp(cptr, "Times(s)", 5)==0) {
689 char *tmp=strdup(cptr+5);
690 strCleanPars(tmp); tac->tunit=unitIdentify(tmp);
691 free(tmp);
692 }
693
694 /* Get concentration unit the first title line, inside parens */
695 tac->cunit=UNIT_UNKNOWN;
696 cptr=csvCell(csv, 0, 1);
697 if(cptr!=NULL && strchr(cptr, '(')!=0) {
698 char *tmp=strdup(strchr(cptr, '('));
699 strCleanPars(tmp); tac->cunit=unitIdentify(tmp);
700 free(tmp);
701 }
702
703 /* Read TAC names from the first title line */
704 if(verbose>4) printf("reading VOI names\n");
705 ret=oknr=0;
706 for(ri=0; ri<tac->tacNr; ri++) {
707 cptr=csvCell(csv, 0, ri+1); if(!cptr) {ret++; break;}
708 if(strlen(cptr)==0) break;
709 strlcpy(tac->c[ri].name, cptr, MAX_TACNAME_LEN+1);
710 cptr=strchr(tac->c[ri].name, '('); if(cptr) *cptr='\0';
711 if(strcmp(tac->c[ri].name, ".")==0) strcpy(tac->c[ri].name, "");
712 oknr++;
713 }
714 if(ret || oknr<1) {
715 if(verbose>0) printf("could not read TAC names.\n");
716 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
718 }
719 /* Set tacNr, in case that txt file had empty fields */
720 tac->tacNr=oknr;
721 if(verbose>2) printf(" tacNr=%d\n", tac->tacNr);
722
723 /* Get VOI volumes from the 3rd line */
724 if(verbose>4) printf("reading VOI volumes\n");
725 ret=oknr=0;
726 for(ri=0; ri<tac->tacNr; ri++) {
727 cptr=csvCell(csv, 2, ri+1); if(!cptr) {ret++; break;}
728 if(atofCheck(cptr, &tac->c[ri].size)!=0) tac->c[ri].size=nan("");
729 oknr++;
730 }
731 if(ret || oknr<1) {
732 if(verbose>0) printf("could not read TAC volumes.\n");
733 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
735 }
736
737 /* Copy x and y data from CSV into TAC struct */
738 if(verbose>4) printf("reading x and y values\n");
739 ret=oknr=0;
740 for(fi=0; fi<tac->sampleNr; fi++) {
741 /* Frame times */
742 cptr=csvCell(csv, fi+4, 0); if(!cptr) {ret++; break;}
743 if(sscanf(cptr, "%lf - %lf", &tac->x1[fi], &tac->x2[fi])!=2) {ret++; break;}
744 /* Concentrations */
745 for(ri=0; ri<tac->tacNr; ri++) {
746 cptr=csvCell(csv, fi+4, ri+1); if(!cptr) {ret++; break;}
747 ret=atofCheck(cptr, &tac->c[ri].y[fi]); if(ret) break;
748 }
749 oknr++;
750 }
751 if(ret || oknr<1) {
752 if(verbose>0) printf("could not read data.\n");
753 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
755 }
756 if(verbose>2) printf(" sampleNr=%d\n", tac->sampleNr);
757
758 /* Set middle sample times */
759 if(tac->isframe)
760 for(fi=0; fi<tac->sampleNr; fi++)
761 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
762
763 /* Move column containing weights to its correct place in the struct */
764 ret=tacWMove(tac, 1, status);
765 if(ret!=TPCERROR_OK && ret!=TPCERROR_NO_WEIGHTS) {
766 statusSet(status, __func__, __FILE__, __LINE__, ret);
767 return(ret);
768 }
769 if(tac->tacNr<1) {
770 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
771 return TPCERROR_NO_DATA;
772 }
773
774 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
775 return(TPCERROR_OK);
776}
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:358
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
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
void strCleanPars(char *s)
Definition stringext.c:476
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
int row_nr
Definition tpccsv.h:44
int col_nr
Definition tpccsv.h:46
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
double size
Definition tpctac.h:71
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
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 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_CARIMAS_TXT
Carimas txt format (reading supported).
Definition tpctac.h:47

Referenced by tacRead().

◆ tacReadCSV()

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

Read CSV TAC format from CSV struct into TAC struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacWriteCSV, tacRead, tacReadCarimasTxt
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, if processed and copied to TAC too; enter NULL if not available.
statusPointer to status data; enter NULL if not needed.

Definition at line 212 of file taccsv.c.

223 {
224 int verbose=0; if(status!=NULL) verbose=status->verbose;
225 if(tac==NULL) {
226 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
227 return TPCERROR_FAIL;
228 }
229 if(verbose>0) printf("%s()\n", __func__);
230
231 tacFree(tac);
232
233 if(csv==NULL || csv->row_nr<2 || csv->col_nr<2) {
234 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
235 return TPCERROR_NO_DATA;
236 }
237
238 /* Check from the first field that data indeed is CSV TAC data */
239 if(strcasecmp(csv->c[0].content, "TAC")!=0) {
240 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
242 }
243
244 /* Get time type from the title line */
245 int i, isframe=-1;
246 for(i=2; i<csv->nr; i++) if(csv->c[i].row==1 && csv->c[i].col==0) break;
247 if(strncasecmp(csv->c[i].content, "time", 4)==0) isframe=0;
248 else if(strncasecmp(csv->c[i].content, "start", 5)==0 &&
249 strncasecmp(csv->c[i+1].content, "end", 3)==0) isframe=1;
250 if(isframe<0) {
251 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
253 }
254
255 /* Allocate memory for TAC data */
256 int n, ret;
257 n=csv->col_nr-1; if(isframe==1) n--;
258 if(n<1) {
259 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
261 }
262 ret=tacAllocate(tac, csv->row_nr-2, n);
263 statusSet(status, __func__, __FILE__, __LINE__, ret);
264 if(ret!=TPCERROR_OK) return ret;
265 tac->tacNr=n; tac->sampleNr=csv->row_nr-2;
266 tac->isframe=isframe;
267 // initiate the format, may be changed later if necessary
268 if(csv->separator=='\t') tac->format=TAC_FORMAT_TSV_UK;
269 else if(csv->separator==',') tac->format=TAC_FORMAT_CSV_INT;
270 else tac->format=TAC_FORMAT_CSV_UK;
271
272 /* Copy header to TAC struct */
273 iftDuplicate(hdr, &tac->h);
274
275 /* Read study id from the second field */
276 tacSetHeaderStudynr(&tac->h, csv->c[1].content);
277
278 /* Get time unit from the first title field, inside parens */
279 char *cptr;
280 for(i=2; i<csv->nr; i++) if(csv->c[i].row==1 && csv->c[i].col==0) break;
281 cptr=strchr(csv->c[i].content, '[');
282 if(cptr==NULL) {
283 tac->tunit=UNIT_UNKNOWN;
284 } else {
285 char *tmp=strdup(cptr+1);
286 cptr=strrchr(tmp, ']'); if(cptr!=NULL) *cptr='\0';
287 tac->tunit=unitIdentify(tmp);
288 free(tmp);
289 }
290
291 /* Get concentration unit from 2nd or 3rd field, inside parens */
292 i++; if(isframe) i++;
293 cptr=strchr(csv->c[i].content, '[');
294 if(cptr==NULL) {
295 tac->cunit=UNIT_UNKNOWN;
296 } else {
297 char *tmp=strdup(cptr+1);
298 cptr=strrchr(tmp, ']'); if(cptr!=NULL) *cptr='\0';
299 tac->cunit=unitIdentify(tmp);
300 free(tmp);
301 }
302
303 /* Read TAC names from the title line */
304 n=0;
305 for(; i<csv->nr; i++) {
306 if(csv->c[i].row!=1 || n>=tac->tacNr) break;
307 /* Copy TAC name, removing unit if necessary */
308 if(strchr(csv->c[i].content, '[')) {
309 char *tmp=strdup(csv->c[i].content);
310 cptr=strchr(tmp, '['); *cptr='\0';
311 strlcpy(tac->c[n].name, tmp, MAX_TACNAME_LEN+1);
312 free(tmp);
313 } else {
314 strlcpy(tac->c[n].name, csv->c[i].content, MAX_TACNAME_LEN+1);
315 }
316 if(strcmp(tac->c[n].name, ".")==0) strcpy(tac->c[n].name, "");
317 n++;
318 }
319 if(n<1) {
320 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
322 }
323 tac->tacNr=n;
324 if(verbose>2) printf(" tacNr=%d\n", tac->tacNr);
325
326 /* Copy x and y data from CSV into TAC struct */
327 int fi=0, ri=0, oknr=0, maxfi=0;
328 ret=0;
329 double v;
330 for(i=2; i<csv->nr; i++) if(csv->c[i].row==2) break;
331 for(; i<csv->nr; i++) {
332 if(verbose>10)
333 printf("i=%d\trow=%d\tcol=%d\t'%s'\n", i, csv->c[i].row, csv->c[i].col, csv->c[i].content);
334 if(csv->c[i].col==0 && strcasecmp(csv->c[i].content, "volume")==0)
335 break; // stop if VOI volume line is encountered
336 fi=csv->c[i].row-2; if(fi<0 || fi>=tac->sampleNr) {ret++; continue;}
337 if(fi>maxfi) maxfi=fi;
338 if(csv->c[i].col<0) {ret++; continue;}
339 ri=csv->c[i].col-1; if(tac->isframe) ri--;
340 if(ri>=tac->tacNr) {ret++; continue;}
341 v=atofVerified(csv->c[i].content); if(!isnan(v)) oknr++;
342 if(verbose>10) printf(" -> fi=%d\tri=%d\t=\t%g\n", fi, ri, v);
343 if(ri<0) {
344 if(tac->isframe) {
345 if(ri==-2) tac->x1[fi]=v; else if(ri==-1) tac->x2[fi]=v;
346 } else tac->x[fi]=v;
347 } else tac->c[ri].y[fi]=v;
348 /* check whether we have decimal comma or dot */
350 if(strHaveDecimalComma(csv->c[i].content)) {
352 else tac->format=TAC_FORMAT_CSV_INT;
353 }
354 }
355 }
356 tac->sampleNr=maxfi+1;
357 if(verbose>2) printf(" sampleNr=%d\n", tac->sampleNr);
358 if(verbose>0 && ret>0) printf("%d error(s) in reading CSV file format.\n", ret);
359 if(oknr<1) {
360 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
362 }
363 /* Set middle sample times when necessary */
364 if(tac->isframe)
365 for(fi=0; fi<tac->sampleNr; fi++)
366 tac->x[fi]=0.5*(tac->x1[fi]+tac->x2[fi]);
367
368 /* Get VOI volumes from the following line */
369 if(i<csv->nr && strcasecmp(csv->c[i].content, "volume")==0) {
370 if(tac->isframe) i++;
371 for(ri=0; ri<tac->tacNr; ri++) {
372 if(csv->c[i+ri].row!=csv->c[i].row) break;
373 tac->c[ri].size=atofVerified(csv->c[i+ri].content);
374 }
375 }
376
377 /* If units are not known, try to read units from header */
378 if(tac->cunit==UNIT_UNKNOWN) tacGetHeaderUnit(tac, NULL);
379 else tacSetHeaderUnit(&tac->h, UNIT_UNKNOWN);
380 if(tac->tunit==UNIT_UNKNOWN) tacGetHeaderTimeunit(tac, NULL);
382
383 /* Move column containing weights to its correct place in the struct */
384 ret=tacWMove(tac, 1, status);
385 if(ret!=TPCERROR_OK && ret!=TPCERROR_NO_WEIGHTS) {
386 statusSet(status, __func__, __FILE__, __LINE__, ret);
387 return(ret);
388 }
389 if(tac->tacNr<1) {
390 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
391 return TPCERROR_NO_DATA;
392 }
393
394 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
395 return(TPCERROR_OK);
396}
double atofVerified(const char *s)
Definition decpoint.c:75
int strHaveDecimalComma(const char *s)
Definition decpoint.c:115
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
int col
Definition tpccsv.h:28
int row
Definition tpccsv.h:26
char * content
Definition tpccsv.h:30
char separator
Definition tpccsv.h:49
CSV_item * c
Definition tpccsv.h:38
int nr
Definition tpccsv.h:42
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
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 tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
int tacSetHeaderUnit(IFT *h, int u)
Definition tacift.c:112
@ TAC_FORMAT_CSV_INT
International CSV.
Definition tpctac.h:34
@ TAC_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Definition tpctac.h:37
@ TAC_FORMAT_TSV_INT
International TSV (comma as decimal separator).
Definition tpctac.h:36
@ TAC_FORMAT_CSV_UK
UK CSV.
Definition tpctac.h:35

Referenced by tacRead().

◆ tacReadInveonCSV()

int tacReadInveonCSV ( TAC * tac,
CSV * csv,
TPCSTATUS * status )

Read Inveon TAC format from CSV struct into TAC struct.

Note that there are several Inveon TAC formats, and not all are supported.

Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC struct, contents of which are to be written.
csvPointer to Inveon CSV from which data is read.
statusPointer to status data; enter NULL if not needed

Definition at line 405 of file taccsv.c.

412 {
413 int verbose=0; if(status!=NULL) verbose=status->verbose;
414 if(tac==NULL) {
415 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
416 return TPCERROR_FAIL;
417 }
418 if(verbose>0) printf("%s()\n", __func__);
419
420 int ret;
421
422 tacFree(tac);
423
424 if(csv==NULL || csv->row_nr<2 || csv->col_nr<5) {
425 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
426 return TPCERROR_NO_DATA;
427 }
428
429 /* Check from the first row that data indeed is CSV TAC data */
430 if(strstr(csv->c[0].content, " - Time")==NULL ||
431 strstr(csv->c[2].content, "(upper bound)")==NULL ||
432 strstr(csv->c[3].content, "(lower bound)")==NULL ||
433 strstr(csv->c[4].content, "(standard deviation)")==NULL) {
434 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
436 }
437
438
439 /* Allocate memory for TAC data */
440 ret=tacAllocate(tac, csv->row_nr-1, csv->col_nr/5);
441 statusSet(status, __func__, __FILE__, __LINE__, ret);
442 if(ret!=TPCERROR_OK) return ret;
443 tac->tacNr=csv->col_nr/5; tac->sampleNr=csv->row_nr-1;
445
446 /* This format has only frame middle time */
447 tac->isframe=0;
448
449 /* Read TAC names and units */
450 char *cptr, buf[1024];
451 ret=0;
452 for(int ri=0; ri<tac->tacNr; ri++) {
453 int ci=5*ri;
454 strlcpy(buf, csv->c[ci].content, 1024);
455 cptr=strcasestr(buf, " - Time"); if(cptr==NULL) {ret++; break;}
456 *cptr=(char)0; strlcpy(tac->c[ri].name, buf, MAX_TACNAME_LEN);
457 if(ri==0) { // Time unit only from the first column
458 cptr=strcasestr(csv->c[ci].content, "Time (");
459 if(cptr!=NULL) {
460 strlcpy(buf, cptr+6, 1024);
461 cptr=strchr(buf, ')'); if(cptr!=NULL) *cptr=(char)0;
462 tac->tunit=unitIdentify(buf);
463 }
464 }
465 if(ri==0) { // Concentration unit only from the first TAC
466 ci++;
467 cptr=strcasestr(csv->c[ci].content, " - ");
468 if(cptr!=NULL) {
469 strlcpy(buf, cptr+3, 1024);
470 cptr=strchr(buf, ','); if(cptr!=NULL) *cptr=(char)0;
471 tac->cunit=unitIdentify(buf);
472 }
473 }
474 }
475
476 /* Read one line at a time */
477 for(int si=0; si<tac->sampleNr; si++) {
478 ret=atofCheck(csvCell(csv, 1+si, 0), &tac->x[si]); if(ret) break;
479 for(int ri=0; ri<tac->tacNr; ri++) {
480 ret=atofCheck(csvCell(csv, 1+si, 1+5*ri), &tac->c[ri].y[si]); if(ret) break;
481 }
482 }
483
484
485 if(tac->tacNr<1) {
486 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
487 return TPCERROR_NO_DATA;
488 }
489
491
492 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
493 return(TPCERROR_OK);
494}
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155
@ TAC_FORMAT_PMOD
PMOD TAC format.
Definition tpctac.h:33
@ TAC_FORMAT_INVEON
Inveon format (reading supported).
Definition tpctac.h:45

Referenced by tacRead().

◆ tacWriteCSV()

int tacWriteCSV ( TAC * tac,
FILE * fp,
int extra,
tacformat format,
TPCSTATUS * status )

Write TAC data into specified file pointer in CSV TAC format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacReadCSV, tacWrite
Parameters
tacPointer to TAC struct, contents of which are to be written
fpFile pointer
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.
formatFile format code; accepted values are TAC_FORMAT_CSV_UK, TAC_FORMAT_CSV_INT, TAC_FORMAT_TSV_UK, TAC_FORMAT_TSV_INT, and TAC_FORMAT_UNKNOWN (0); this last one uses format inside TAC struct, or if that is invalid, then the default format TAC_FORMAT_CSV_UK
statusPointer to status data; enter NULL if not needed

Definition at line 26 of file taccsv.c.

41 {
42 int verbose=0; if(status!=NULL) verbose=status->verbose;
43 if(verbose>0) printf("%s()\n", __func__);
44 if(fp==NULL) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
47 }
48 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
49 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
50 return TPCERROR_NO_DATA;
51 }
52
53 int ret;
54
55 /* Create local copy of headers, which will be edited here and written
56 into CSV file, to preserve the original headers with TAC struct */
57 if(verbose>99) iftWrite(&tac->h, stdout, NULL);
58 IFT localh; iftInit(&localh);
59 ret=iftDuplicate(&tac->h, &localh);
60 if(ret) {
61 statusSet(status, __func__, __FILE__, __LINE__, ret);
62 return ret;
63 }
64
65 CSV csv;
66 csvInit(&csv);
67 if(csvAllocate(&csv, (tac->tacNr+3)*(tac->sampleNr+1))) {
68 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
69 iftFree(&localh); return TPCERROR_FAIL;
70 }
71
72 /* Check and set the CSV format */
73 int tointl=0; // Decimal point (0) or comma (1)
74 if(format==TAC_FORMAT_UNKNOWN) format=tac->format;
75 if(format==TAC_FORMAT_UNKNOWN) format=TAC_FORMAT_CSV_UK;
76 if(format==TAC_FORMAT_CSV_UK) {
77 tointl=0; csv.separator=',';
78 } else if(format==TAC_FORMAT_CSV_INT) {
79 tointl=1; csv.separator=';';
80 } else if(format==TAC_FORMAT_TSV_UK) {
81 tointl=0; csv.separator='\t';
82 } else if(format==TAC_FORMAT_TSV_INT) {
83 tointl=1; csv.separator='\t';
84 } else {
85 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
86 iftFree(&localh); return TPCERROR_INVALID_FORMAT;
87 }
88
89 /* Make sure that TAC names are available */
90 tacEnsureNames(tac);
91
92 /* Fill CSV struct */
93 char tmp[1024];
94
95 if(verbose>1) printf(" writing header\n");
96
97 /* Add file format ID */
98 ret=csvPutString(&csv, "TAC", 0);
99 if(ret!=TPCERROR_OK) {
100 statusSet(status, __func__, __FILE__, __LINE__, ret);
101 csvFree(&csv); iftFree(&localh); return ret;
102 }
103
104 /* Add study number */
105 tacGetHeaderStudynr(&tac->h, tmp, NULL);
106 ret=csvPutString(&csv, tmp, 0);
107 if(ret!=TPCERROR_OK) {
108 statusSet(status, __func__, __FILE__, __LINE__, ret);
109 csvFree(&csv); iftFree(&localh); return ret;
110 }
111
112
113 if(verbose>1) printf(" writing data table title\n");
114
115 if(tac->isframe==0) {
116 sprintf(tmp, "time[%s]", unitName(tac->tunit));
117 ret=csvPutString(&csv, tmp, 1);
118 } else {
119 sprintf(tmp, "start[%s]", unitName(tac->tunit));
120 ret=csvPutString(&csv, tmp, 1);
121 sprintf(tmp, "end[%s]", unitName(tac->tunit));
122 if(!ret) ret=csvPutString(&csv, tmp, 0);
123 }
124 if(ret!=TPCERROR_OK) {
125 statusSet(status, __func__, __FILE__, __LINE__, ret);
126 csvFree(&csv); iftFree(&localh); return ret;
127 }
128
129 for(int ri=0; ri<tac->tacNr; ri++) {
130 /* add TAC names, first one with unit */
131 if(ri==0) {
132 sprintf(tmp, "%s[%s]", tac->c[ri].name, unitName(tac->cunit));
133 } else {
134 sprintf(tmp, "%s", tac->c[ri].name);
135 }
136 ret=csvPutString(&csv, tmp, 0); if(ret) break;
137 }
138 if(ret!=TPCERROR_OK) {
139 statusSet(status, __func__, __FILE__, __LINE__, ret);
140 csvFree(&csv); iftFree(&localh); return ret;
141 }
142 if(tacIsWeighted(tac)) {
143 ret=csvPutString(&csv, "weight", 0);
144 if(ret!=TPCERROR_OK) {
145 statusSet(status, __func__, __FILE__, __LINE__, ret);
146 csvFree(&csv); iftFree(&localh); return ret;
147 }
148 }
149
150 if(verbose>1) printf("writing data table\n");
151
152 for(int fi=0; fi<tac->sampleNr; fi++) {
153 /* Time(s) (x, or x1 and x2) */
154 if(tac->isframe==0) {
155 ret=csvPutDouble(&csv, tac->x[fi], 1, tointl);
156 } else {
157 ret=csvPutDouble(&csv, tac->x1[fi], 1, tointl);
158 if(!ret) ret=csvPutDouble(&csv, tac->x2[fi], 0, tointl);
159 }
160 if(ret!=TPCERROR_OK) break;
161 /* Concentrations (y values) */
162 for(int ri=0; ri<tac->tacNr; ri++) {
163 ret=csvPutDouble(&csv, tac->c[ri].y[fi], 0, tointl); if(ret) break;
164 }
165 /* Weight */
166 if(tacIsWeighted(tac)) {
167 ret=csvPutDouble(&csv, tac->w[fi], 0, tointl); if(ret) break;
168 }
169 } // next sample
170 if(ret!=TPCERROR_OK) {
171 statusSet(status, __func__, __FILE__, __LINE__, ret);
172 csvFree(&csv); iftFree(&localh); return ret;
173 }
174
175 /* Add VOI volumes, if available */
176 if(tacIsSize(tac)) {
177 ret=csvPutString(&csv, "volume", 1);
178 if(tac->isframe && !ret) ret=csvPutString(&csv, "", 0);
179 for(int ri=0; ri<tac->tacNr && !ret; ri++) {
180 ret=csvPutDouble(&csv, tac->c[ri].size, 0, tointl);
181 }
182 if(ret!=TPCERROR_OK) {
183 statusSet(status, __func__, __FILE__, __LINE__, ret);
184 csvFree(&csv); iftFree(&localh); return ret;
185 }
186 }
187
188 /* Write CSV */
189 ret=csvWrite(&csv, 0, fp, status);
190 csvFree(&csv);
191 if(ret!=TPCERROR_OK) {iftFree(&localh); return ret;}
192
193 /* Write extra header */
194 // scan start time etc should be added to the first line I think
195 if(extra && localh.keyNr>0) {
196 int ret=iftWrite(&localh, fp, status);
197 if(ret!=TPCERROR_OK) {iftFree(&localh); return ret;}
198 }
199
200 iftFree(&localh);
201 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
202 return(TPCERROR_OK);
203}
void csvInit(CSV *csv)
Definition csv.c:22
int csvAllocate(CSV *csv, int nr)
Definition csv.c:58
int csvPutString(CSV *csv, const char *s, int newline)
Definition csv.c:144
int csvPutDouble(CSV *csv, double v, int newline, int tointl)
Definition csv.c:193
void csvFree(CSV *csv)
Definition csv.c:38
int csvWrite(CSV *csv, int regular, FILE *fp, TPCSTATUS *status)
Definition csvio.c:52
void iftFree(IFT *ift)
Definition ift.c:37
void iftInit(IFT *ift)
Definition ift.c:21
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
Definition iftio.c:98
Definition tpccsv.h:36
Definition tpcift.h:43
int keyNr
Definition tpcift.h:47
double * w
Definition tpctac.h:111
int tacIsSize(TAC *d)
Definition tac.c:335
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:26
void tacEnsureNames(TAC *tac)
Definition tacname.c:50
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
@ TPCERROR_CANNOT_WRITE
Cannot write file.
char * unitName(int unit_code)
Definition units.c:143
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28

Referenced by tacWrite().