5#include "tpcclibConfig.h"
42 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
43 if(verbose>0) printf(
"%s()\n", __func__);
57 if(verbose>99)
iftWrite(&tac->
h, stdout, NULL);
61 statusSet(status, __func__, __FILE__, __LINE__, ret);
95 if(verbose>1) printf(
" writing header\n");
100 statusSet(status, __func__, __FILE__, __LINE__, ret);
108 statusSet(status, __func__, __FILE__, __LINE__, ret);
113 if(verbose>1) printf(
" writing data table title\n");
125 statusSet(status, __func__, __FILE__, __LINE__, ret);
129 for(
int ri=0; ri<tac->
tacNr; ri++) {
134 sprintf(tmp,
"%s", tac->
c[ri].
name);
139 statusSet(status, __func__, __FILE__, __LINE__, ret);
145 statusSet(status, __func__, __FILE__, __LINE__, ret);
150 if(verbose>1) printf(
"writing data table\n");
152 for(
int fi=0; fi<tac->
sampleNr; fi++) {
162 for(
int ri=0; ri<tac->
tacNr; ri++) {
163 ret=
csvPutDouble(&csv, tac->
c[ri].
y[fi], 0, tointl);
if(ret)
break;
167 ret=
csvPutDouble(&csv, tac->
w[fi], 0, tointl);
if(ret)
break;
171 statusSet(status, __func__, __FILE__, __LINE__, ret);
179 for(
int ri=0; ri<tac->
tacNr && !ret; ri++) {
183 statusSet(status, __func__, __FILE__, __LINE__, ret);
195 if(extra && localh.
keyNr>0) {
196 int ret=
iftWrite(&localh, fp, status);
224 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
229 if(verbose>0) printf(
"%s()\n", __func__);
239 if(strcasecmp(csv->
c[0].
content,
"TAC")!=0) {
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;
257 n=csv->
col_nr-1;
if(isframe==1) n--;
263 statusSet(status, __func__, __FILE__, __LINE__, ret);
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,
'[');
286 cptr=strrchr(tmp,
']');
if(cptr!=NULL) *cptr=
'\0';
292 i++;
if(isframe) i++;
293 cptr=strchr(csv->
c[i].
content,
'[');
298 cptr=strrchr(tmp,
']');
if(cptr!=NULL) *cptr=
'\0';
305 for(; i<csv->
nr; i++) {
306 if(csv->
c[i].
row!=1 || n>=tac->
tacNr)
break;
308 if(strchr(csv->
c[i].
content,
'[')) {
310 cptr=strchr(tmp,
'['); *cptr=
'\0';
316 if(strcmp(tac->
c[n].
name,
".")==0) strcpy(tac->
c[n].
name,
"");
324 if(verbose>2) printf(
" tacNr=%d\n", tac->
tacNr);
327 int fi=0, ri=0, oknr=0, maxfi=0;
330 for(i=2; i<csv->
nr; i++)
if(csv->
c[i].
row==2)
break;
331 for(; i<csv->
nr; i++) {
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)
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;}
340 if(ri>=tac->
tacNr) {ret++;
continue;}
342 if(verbose>10) printf(
" -> fi=%d\tri=%d\t=\t%g\n", fi, ri, v);
345 if(ri==-2) tac->
x1[fi]=v;
else if(ri==-1) tac->
x2[fi]=v;
347 }
else tac->
c[ri].
y[fi]=v;
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);
366 tac->
x[fi]=0.5*(tac->
x1[fi]+tac->
x2[fi]);
369 if(i<csv->nr && strcasecmp(csv->
c[i].
content,
"volume")==0) {
371 for(ri=0; ri<tac->
tacNr; ri++) {
372 if(csv->
c[i+ri].
row!=csv->
c[i].
row)
break;
386 statusSet(status, __func__, __FILE__, __LINE__, ret);
413 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
418 if(verbose>0) printf(
"%s()\n", __func__);
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) {
441 statusSet(status, __func__, __FILE__, __LINE__, ret);
450 char *cptr, buf[1024];
452 for(
int ri=0; ri<tac->
tacNr; ri++) {
455 cptr=
strcasestr(buf,
" - Time");
if(cptr==NULL) {ret++;
break;}
461 cptr=strchr(buf,
')');
if(cptr!=NULL) *cptr=(char)0;
470 cptr=strchr(buf,
',');
if(cptr!=NULL) *cptr=(char)0;
477 for(
int si=0; si<tac->
sampleNr; si++) {
479 for(
int ri=0; ri<tac->
tacNr; ri++) {
508 int ri, fi, fip, ii, ret;
509 char *cptr, *cptr2, tmp[256];
512 if(CSV_TEST>2) {printf(
"csv2dft_b()\n"); fflush(stdout);}
513 if(csv==NULL || dft==NULL)
return CSV_ERROR;
515 if(csv->
row_nr<4 || csv->
col_nr!=9)
return CSV_INVALIDFORMAT;
519 if(strcasecmp(csv->
c[0].
content,
"#Subject ID")!=0)
return CSV_INVALIDFORMAT;
520 if(strcasecmp(csv->
c[1].
content,
"Subject Weight")!=0)
return CSV_INVALIDFORMAT;
521 if(strcasecmp(csv->
c[2].
content,
"Subject Sex")!=0)
return CSV_INVALIDFORMAT;
522 if(strcasecmp(csv->
c[3].
content,
"Unique Series ID")!=0)
return CSV_INVALIDFORMAT;
523 if(strcasecmp(csv->
c[4].
content,
"Series Date")!=0)
return CSV_INVALIDFORMAT;
524 if(strcasecmp(csv->
c[5].
content,
"Series Description")!=0)
return CSV_INVALIDFORMAT;
527 if(strcasecmp(csv->
c[12].
content,
"#Name")!=0)
return CSV_INVALIDFORMAT;
528 if(strcasecmp(csv->
c[13].
content,
"Volume (mm^3)")!=0)
return CSV_INVALIDFORMAT;
529 if(strcasecmp(csv->
c[14].
content,
"Mean")!=0)
return CSV_INVALIDFORMAT;
530 if(strcasecmp(csv->
c[15].
content,
"SD")!=0)
return CSV_INVALIDFORMAT;
531 if(strcasecmp(csv->
c[16].
content,
"Min")!=0)
return CSV_INVALIDFORMAT;
532 if(strcasecmp(csv->
c[17].
content,
"Max")!=0)
return CSV_INVALIDFORMAT;
533 if(strcasecmp(csv->
c[18].
content,
"Frame Index")!=0)
return CSV_INVALIDFORMAT;
534 if(strncasecmp(csv->
c[19].
content,
"Mid time (sec)", 10)!=0)
return CSV_INVALIDFORMAT;
535 if(strncasecmp(csv->
c[20].
content,
"Duration (sec)", 10)!=0)
return CSV_INVALIDFORMAT;
538 ri=1; fi=0; fip=-1; ii=21; cptr=csv->
c[ii].
content;
540 for(; ii<csv->
nr; ii+=9) {
543 if(strcmp(cptr, cptr2)==0) fi++;
546 if(fip<0) fip=fi;
else if(fi!=fip)
return CSV_INVALIDFORMAT;
554 if(CSV_TEST>2) {printf(
"frame_nr=%d voi_nr=%d\n", fi, ri); fflush(stdout);}
555 ret=dftSetmem(dft, fi, ri);
556 if(ret!=0)
return CSV_OUTOFMEMORY;
557 dft->voiNr=ri; dft->frameNr=fi;
558 dft->timetype=DFT_TIME_STARTEND;
559 dft->_type=DFT_FORMAT_STANDARD;
561 dftUnitToDFT(dft, CUNIT_UNKNOWN); dft->timeunit=TUNIT_UNKNOWN;
562 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]=1.0;
567 if(strstr(csv->
c[ii].
content,
"min")!=NULL) dft->timeunit=TUNIT_MIN;
568 else if(strstr(csv->
c[ii].
content,
"sec")!=NULL) dft->timeunit=TUNIT_SEC;
569 else dft->timeunit=TUNIT_UNKNOWN;
573 cptr=strchr(dft->studynr,
'.');
if(cptr!=NULL) *cptr=(char)0;
574 cptr=strchr(dft->studynr,
',');
if(cptr!=NULL) *cptr=(char)0;
575 cptr=strchr(dft->studynr,
' ');
if(cptr!=NULL) *cptr=(char)0;
577 ii=7;
if(ii>=csv->
nr) {dftEmpty(dft);
return CSV_INVALIDFORMAT;}
579 if(v1>0.0) sprintf(dft->comments,
"# weight := %g\n", v1);
581 ii=10;
if(ii>=csv->
nr) {dftEmpty(dft);
return CSV_INVALIDFORMAT;}
583 sprintf(tmp,
"# scan_start_time := %s\n", csv->
c[ii].
content);
584 strcat(dft->comments, tmp);
587 for(fi=0; fi<dft->frameNr; fi++) {
588 ii= 21 + fi*9 + 7;
if(ii>csv->
nr-2) {dftEmpty(dft);
return CSV_INVALIDFORMAT;}
591 dft->x[fi]=v1; dft->x1[fi]=v1-0.5*v2; dft->x2[fi]=v1+0.5*v2;
594 for(ri=0; ri<dft->voiNr; ri++) {
596 ii= 21 + ri*dft->frameNr*9;
597 if(ii>=csv->
nr) {dftEmpty(dft);
return CSV_INVALIDFORMAT;}
600 rnameSplit(csv->
c[ii].
content, dft->voi[ri].voiname,
601 dft->voi[ri].hemisphere, dft->voi[ri].place,
602 MAX_REGIONSUBNAME_LEN);
604 ii++;
if(ii>=csv->
nr) {dftEmpty(dft);
return CSV_INVALIDFORMAT;}
605 dft->voi[ri].size=atof_dpi(csv->
c[ii].
content);
607 ii++;
for(fi=0; fi<dft->frameNr; fi++) {
608 if((ii+6)>=csv->
nr) {dftEmpty(dft);
return CSV_INVALIDFORMAT;}
610 dft->voi[ri].y[fi]=atof_dpi(csv->
c[ii].
content);
612 dft->voi[ri].y2[fi]=atof_dpi(csv->
c[ii+1].
content);
615 if(dft->x[fi]!=v1) {dftEmpty(dft);
return CSV_INVALIDFORMAT;}
640 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
641 if(verbose>0) printf(
"%s()\n", __func__);
643 if(verbose>0) printf(
"tac := NULL\n");
651 printf(
"csv.row_nr := %d\n", csv->
row_nr);
652 printf(
"csv.col_nr := %d\n", csv->
col_nr);
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 )
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));
674 int ret, fi, ri, oknr;
678 statusSet(status, __func__, __FILE__, __LINE__, ret);
688 if(cptr!=NULL && strncasecmp(cptr,
"Times(s)", 5)==0) {
697 if(cptr!=NULL && strchr(cptr,
'(')!=0) {
698 char *tmp=
strdup(strchr(cptr,
'('));
704 if(verbose>4) printf(
"reading VOI names\n");
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;
710 cptr=strchr(tac->
c[ri].
name,
'(');
if(cptr) *cptr=
'\0';
711 if(strcmp(tac->
c[ri].
name,
".")==0) strcpy(tac->
c[ri].
name,
"");
715 if(verbose>0) printf(
"could not read TAC names.\n");
721 if(verbose>2) printf(
" tacNr=%d\n", tac->
tacNr);
724 if(verbose>4) printf(
"reading VOI volumes\n");
726 for(ri=0; ri<tac->
tacNr; ri++) {
727 cptr=
csvCell(csv, 2, ri+1);
if(!cptr) {ret++;
break;}
732 if(verbose>0) printf(
"could not read TAC volumes.\n");
738 if(verbose>4) printf(
"reading x and y values\n");
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;}
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;
752 if(verbose>0) printf(
"could not read data.\n");
756 if(verbose>2) printf(
" sampleNr=%d\n", tac->
sampleNr);
761 tac->
x[fi]=0.5*(tac->
x1[fi]+tac->
x2[fi]);
766 statusSet(status, __func__, __FILE__, __LINE__, ret);
char * csvCell(CSV *csv, int row, int col)
int csvAllocate(CSV *csv, int nr)
int csvPutString(CSV *csv, const char *s, int newline)
int csvPutDouble(CSV *csv, double v, int newline, int tointl)
int csvWrite(CSV *csv, int regular, FILE *fp, TPCSTATUS *status)
double atofVerified(const char *s)
int strHaveDecimalComma(const char *s)
int atofCheck(const char *s, double *v)
int iftDuplicate(IFT *ift1, IFT *ift2)
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
char * strdup(const char *s)
void strCleanPars(char *s)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
char * strcasestr(const char *haystack, const char *needle)
char name[MAX_TACNAME_LEN+1]
IFT h
Optional (but often useful) header information.
int verbose
Verbose level, used by statusPrint() etc.
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
int tacReadInveonCSV(TAC *tac, CSV *csv, TPCSTATUS *status)
int tacReadCSV(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
int tacWriteCSV(TAC *tac, FILE *fp, int extra, tacformat format, TPCSTATUS *status)
int tacReadCarimasTxt(TAC *tac, CSV *csv, TPCSTATUS *status)
int tacGetHeaderUnit(TAC *tac, TPCSTATUS *status)
int tacGetHeaderTimeunit(TAC *tac, TPCSTATUS *status)
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
int tacSetHeaderTimeunit(IFT *h, int u)
int tacSetHeaderStudynr(IFT *h, const char *s)
int tacSetHeaderUnit(IFT *h, int u)
void tacEnsureNames(TAC *tac)
int tacWMove(TAC *tac, int ow, TPCSTATUS *status)
int tacIsWeighted(TAC *tac)
Header file for library libtpccsv.
#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_NO_WEIGHTS
File contains no weights.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_CANNOT_WRITE
Cannot write file.
int unitIdentify(const char *s)
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for library libtpcisotope.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
@ TAC_FORMAT_CSV_INT
International CSV.
@ TAC_FORMAT_TSV_UK
UK TSV (point as decimal separator)
@ TAC_FORMAT_TSV_INT
International TSV (comma as decimal separator)
@ TAC_FORMAT_PMOD
PMOD TAC format.
@ TAC_FORMAT_CARIMAS_TXT
Carimas txt format (reading supported)
@ TAC_FORMAT_CSV_UK
UK CSV.
@ TAC_FORMAT_INVEON
Inveon format (reading supported)