TPCCLIB
Loading...
Searching...
No Matches
taccsv.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,
38 tacformat format,
40 TPCSTATUS *status
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}
204/*****************************************************************************/
205
206/*****************************************************************************/
214 TAC *tac,
217 CSV *csv,
220 IFT *hdr,
222 TPCSTATUS *status
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}
397/*****************************************************************************/
398
399/*****************************************************************************/
407 TAC *tac,
409 CSV *csv,
411 TPCSTATUS *status
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}
495/*****************************************************************************/
496
497/*****************************************************************************/
498#if(0)
502int csv2dft_b(
504 CSV *csv,
506 DFT *dft
507) {
508 int ri, fi, fip, ii, ret;
509 char *cptr, *cptr2, tmp[256];
510 double v1, v2;
511
512 if(CSV_TEST>2) {printf("csv2dft_b()\n"); fflush(stdout);}
513 if(csv==NULL || dft==NULL) return CSV_ERROR;
514 //printf("row_nr=%d col_nr=%d\n", csv->row_nr, csv->col_nr);
515 if(csv->row_nr<4 || csv->col_nr!=9) return CSV_INVALIDFORMAT;
516 dftEmpty(dft);
517
518 /* Check the format; first line (containing titles) */
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;
525
526 /* Check the format; third line (containing titles) */
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;
536
537 /* Calculate the number of ROIs and time frames */
538 ri=1; fi=0; fip=-1; ii=21; cptr=csv->c[ii].content;
539 //printf("cell[%d] := '%s'\n", ii, cptr); fflush(stdout);
540 for(; ii<csv->nr; ii+=9) {
541 cptr2=csv->c[ii].content;
542 //printf("cell[%d] := '%s'\n", ii, cptr2); fflush(stdout);
543 if(strcmp(cptr, cptr2)==0) fi++;
544 else {
545 ri++; cptr=cptr2;
546 if(fip<0) fip=fi; else if(fi!=fip) return CSV_INVALIDFORMAT;
547 fi=1;
548 }
549 //printf("ri=%d fi=%d fip=%d\n", ri, fi, fip);
550 }
551 //printf("ri=%d fi=%d\n", ri, fi);
552
553 /* Allocate memory for DFT */
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;
560 dft->isweight=0;
561 dftUnitToDFT(dft, CUNIT_UNKNOWN); dft->timeunit=TUNIT_UNKNOWN;
562 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]=1.0;
563
564 /* Fill DFT */
565 /* time unit */
566 ii=19;
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;
570 /* study number */
571 ii=6;
572 cptr=csv->c[ii].content; strlcpy(dft->studynr, cptr, 11);
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;
576 /* subject weight */
577 ii=7; if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
578 v1=atof_dpi(csv->c[ii].content);
579 if(v1>0.0) sprintf(dft->comments, "# weight := %g\n", v1);
580 /* scan start time */
581 ii=10; if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
582 if(strlen(csv->c[ii].content)>9) {
583 sprintf(tmp, "# scan_start_time := %s\n", csv->c[ii].content);
584 strcat(dft->comments, tmp);
585 }
586 /* frame times */
587 for(fi=0; fi<dft->frameNr; fi++) {
588 ii= 21 + fi*9 + 7; if(ii>csv->nr-2) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
589 //printf("cell[%d] := '%s'\n", ii, csv->c[ii].content); fflush(stdout);
590 v1=atof_dpi(csv->c[ii].content); v2=atof_dpi(csv->c[ii+1].content);
591 dft->x[fi]=v1; dft->x1[fi]=v1-0.5*v2; dft->x2[fi]=v1+0.5*v2;
592 }
593 /* region names, volumes, and concentrations */
594 for(ri=0; ri<dft->voiNr; ri++) {
595 /* ROI name */
596 ii= 21 + ri*dft->frameNr*9;
597 if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
598 //printf("ri=%d cell[%d] := '%s'\n", ri, ii, csv->c[ii].content); fflush(stdout);
599 strlcpy(dft->voi[ri].name, csv->c[ii].content, MAX_REGIONNAME_LEN+1);
600 rnameSplit(csv->c[ii].content, dft->voi[ri].voiname,
601 dft->voi[ri].hemisphere, dft->voi[ri].place,
602 MAX_REGIONSUBNAME_LEN);
603 /* Volume */
604 ii++; if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
605 dft->voi[ri].size=atof_dpi(csv->c[ii].content);
606 /* Frame concentrations */
607 ii++; for(fi=0; fi<dft->frameNr; fi++) {
608 if((ii+6)>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
609 /* Get concentration */
610 dft->voi[ri].y[fi]=atof_dpi(csv->c[ii].content);
611 /* Get concentration SD (probably not needed) */
612 dft->voi[ri].y2[fi]=atof_dpi(csv->c[ii+1].content);
613 /* check that frame times are correct */
614 v1=atof_dpi(csv->c[ii+5].content);
615 if(dft->x[fi]!=v1) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
616 ii+=9;
617 } // next frame
618 } // next region
619
620 return CSV_OK;
621}
622#endif
623/*****************************************************************************/
624
625/*****************************************************************************/
633 TAC *tac,
636 CSV *csv,
638 TPCSTATUS *status
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}
777/*****************************************************************************/
778
779/*****************************************************************************/
void csvInit(CSV *csv)
Definition csv.c:22
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:358
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
double atofVerified(const char *s)
Definition decpoint.c:75
int strHaveDecimalComma(const char *s)
Definition decpoint.c:115
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
void iftFree(IFT *ift)
Definition ift.c:37
void iftInit(IFT *ift)
Definition ift.c:21
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
Definition iftio.c:98
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
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
char separator
Definition tpccsv.h:49
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
double size
Definition tpctac.h:71
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 tacIsSize(TAC *d)
Definition tac.c:335
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
int tacReadInveonCSV(TAC *tac, CSV *csv, TPCSTATUS *status)
Definition taccsv.c:405
int tacReadCSV(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition taccsv.c:212
int tacWriteCSV(TAC *tac, FILE *fp, int extra, tacformat format, TPCSTATUS *status)
Definition taccsv.c:26
int tacReadCarimasTxt(TAC *tac, CSV *csv, TPCSTATUS *status)
Definition taccsv.c:631
int tacGetHeaderUnit(TAC *tac, TPCSTATUS *status)
Definition tacift.c:145
int tacGetHeaderTimeunit(TAC *tac, TPCSTATUS *status)
Definition tacift.c:234
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:26
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
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_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.
@ 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.
tacformat
Definition tpctac.h:27
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28
@ 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_PMOD
PMOD TAC format.
Definition tpctac.h:33
@ TAC_FORMAT_CARIMAS_TXT
Carimas txt format (reading supported)
Definition tpctac.h:47
@ TAC_FORMAT_CSV_UK
UK CSV.
Definition tpctac.h:35
@ TAC_FORMAT_INVEON
Inveon format (reading supported)
Definition tpctac.h:45