TPCCLIB
Loading...
Searching...
No Matches
csv.c
Go to the documentation of this file.
1
5/*****************************************************************************/
7/*****************************************************************************/
8#include "libtpccurveio.h"
9/*****************************************************************************/
10
11/*****************************************************************************/
15 CSV *csv
16) {
17 if(csv==NULL) return;
18 csv->c=NULL;
19 csv->nr=csv->row_nr=csv->col_nr=0;
20 csv->separator=(char)0;
21}
22
26 CSV *csv
27) {
28 int i;
29 if(csv==NULL) return;
30 for(i=0; i<csv->nr; i++)
31 if(csv->c[i].content!=NULL) free(csv->c[i].content);
32 free(csv->c); csv->c=NULL;
33 csv->nr=csv->row_nr=csv->col_nr=0;
34 csv->separator=(char)0;
35}
36/*****************************************************************************/
37
38/*****************************************************************************/
44 CSV *csv,
46 char *fname
47) {
48 if(CSV_TEST>2) {printf("csvRead('%s')\n", fname); fflush(stdout);}
49
50 FILE *fp;
51 int i, nr, ret, nonprintable=0, inside_quotes=0, previous, col_nr=0;
52 const int MAX_CSV_FIELD_LENGTH=1024;
53 char buf[MAX_CSV_FIELD_LENGTH+1];
54 int tabnr, spacenr, commanr;
55
56
57 if(csv==NULL || fname==NULL) return CSV_ERROR;
58 /* Open file */
59 fp=fopen(fname, "r"); if(fp==NULL) return CSV_CANNOTOPEN;
60
61 /* Check the file size */
62 nr=nonprintable=0; while((ret=fgetc(fp))!=EOF) {
63 if(iscntrl(ret) && ret!=13 && ret!=10 && ret!=9) {nonprintable=1; break;}
64 nr++;
65 }
66 if(CSV_TEST>0) printf("filesize := %d\n", nr);
67 if(nr<2) {fclose(fp); return CSV_INVALIDFORMAT;}
68 if(nr>5000000) {fclose(fp); return CSV_TOOBIG;}
69 rewind(fp);
70
71 /* Determine the field separator (unless set outside) */
72 if(csv->separator==(char)0) {
73 /* Check if ; or tab or space or comma character is found outside double quotes */
74 inside_quotes=0; nr=0; tabnr=0; spacenr=0; commanr=0;
75 while((ret=fgetc(fp))!=EOF) {
76 if(ret=='"') {
77 if(inside_quotes==0) inside_quotes=1; else inside_quotes=0;
78 continue;
79 }
80 if(inside_quotes==1) continue;
81 if(ret==';') nr++;
82 else if(ret=='\t') tabnr++;
83 else if(ret==',') commanr++;
84 else if(ret==' ') spacenr++;
85 }
86 if(CSV_TEST>0) {
87 printf("semicolon_nr := %d\n", nr);
88 printf("tab_nr := %d\n", tabnr);
89 printf("comma_nr := %d\n", commanr);
90 printf("space_nr := %d\n", spacenr);
91 }
92 /* If at least one, then assume that ; is the separator, otherwise , or tab */
93 if(nr>0) csv->separator=';';
94 else if(tabnr>0) csv->separator='\t';
95 else if(commanr>spacenr) csv->separator=',';
96 else csv->separator=' ';
97 rewind(fp);
98 }
99 if(CSV_TEST>0) printf("separator := '%c'\n", csv->separator);
100 /* We will not accept space as separator for CSV */
101 if(csv->separator==' ') {fclose(fp); return CSV_INVALIDFORMAT;}
102
103
104 /* Determine the number of fields in CSV file */
105 inside_quotes=0; nr=0; previous=0;
106 while((ret=fgetc(fp))!=EOF) {
107 if((previous==13 || previous==10) && (ret==13 || ret==10)) {previous=ret; continue;}
108 if(ret=='"') {
109 if(inside_quotes==0) inside_quotes=1; else inside_quotes=0;
110 previous=ret; continue;
111 }
112 if(inside_quotes==0) {
113 if(ret==csv->separator) {
114 nr++; previous=ret;
115 continue;
116 }
117 if( (ret==13 || ret==10) && previous!=13 && previous!=10) {
118 nr++; previous=ret;
119 continue;
120 }
121
122 int next=fgetc(fp);
123 if(next!=EOF) {
124 ungetc(next, fp);
125 } else {
126 nr++; previous=ret;
127 continue;
128 }
129
130 } //printf("%c", (char)ret);
131 previous=ret;
132 }
133 rewind(fp); if(CSV_TEST>0) printf("field_nr := %d\n", nr);
134
135 /* Allocate memory for fields */
136 csv->c=(CSV_item*)calloc(nr, sizeof(CSV_item));
137 if(csv->c==NULL) {fclose(fp); return CSV_OUTOFMEMORY;}
138 csv->nr=nr;
139
140 /* Copy field contents from CSV file */
141 if(CSV_TEST>0) printf(" copying contents...\n");
142 inside_quotes=0; nr=0; previous=0; i=0; col_nr=0;
143 while((ret=fgetc(fp))!=EOF) {
144 if((previous==13 || previous==10) && (ret==13 || ret==10)) {previous=ret; continue;}
145 if(ret=='"') {
146 if(inside_quotes==0) inside_quotes=1; else inside_quotes=0;
147 previous=ret; continue;
148 }
149 if(inside_quotes==0) {
150 if(ret==csv->separator) {
151 buf[i]=(char)0; strCleanSpaces(buf); if(CSV_TEST>10) printf("'%s'\n", buf);
152 if(nr>=csv->nr) {printf(" index overflow\n"); break;}
153 csv->c[nr].content=strdup(buf);
154 csv->c[nr].row=1+csv->row_nr; csv->c[nr].col=1+col_nr;
155 i=0; nr++; col_nr++; previous=ret;
156 continue;
157 }
158 if( (ret==13 || ret==10) && previous!=13 && previous!=10) {
159 buf[i]=(char)0; strCleanSpaces(buf); if(CSV_TEST>10) printf("'%s'\n", buf);
160 if(nr>=csv->nr) {printf(" index overflow\n"); break;}
161 csv->c[nr].content=strdup(buf);
162 if(CSV_TEST>10) printf("===\n");
163 col_nr++; if(col_nr>csv->col_nr) csv->col_nr=col_nr;
164 csv->c[nr].row=1+csv->row_nr; csv->c[nr].col=col_nr;
165 i=0; nr++; col_nr=0; previous=ret; csv->row_nr++;
166 continue;
167 }
168
169 int next=fgetc(fp);
170 if(next!=EOF) {
171 ungetc(next, fp);
172 } else {
173 buf[i]=(char)0; strCleanSpaces(buf); if(CSV_TEST>10) printf("'%s'\n", buf);
174 if(nr>=csv->nr) {printf(" index overflow\n"); break;}
175 csv->c[nr].content=strdup(buf);
176 if(CSV_TEST>10) printf("===\n");
177 col_nr++; if(col_nr>csv->col_nr) csv->col_nr=col_nr;
178 csv->c[nr].row=1+csv->row_nr; csv->c[nr].col=col_nr;
179 i=0; nr++; col_nr=0; previous=ret; csv->row_nr++;
180 continue;
181 }
182
183 }
184 if(i<MAX_CSV_FIELD_LENGTH) buf[i]=(char)ret;
185 i++;
186 previous=ret;
187 }
188 if(CSV_TEST>0) printf(" ... copied: nr=%d\n", nr);
189
190
191 fclose(fp);
192 return CSV_OK;
193}
194/*****************************************************************************/
195
196/*****************************************************************************/
202 CSV *csv,
204 DFT *dft
205) {
206 int ret, i, u, n, m;
207
208 if(CSV_TEST>2) {printf("csv2dft()\n"); fflush(stdout);}
209 if(csv==NULL || dft==NULL) return CSV_ERROR;
210 if(csv->row_nr<1 || csv->col_nr<1) return CSV_INVALIDFORMAT;
211
212 /* Is this LinkSet format? */
213 if(strcasecmp(csv->c[0].content, "LinkSet")==0) {
214 ret=csv2dft_linkset(csv, dft);
215 if(ret!=CSV_OK) {
216 if(CSV_TEST>2) printf("reading LinkSet CSV format failed.\n");
217 }
218 return(ret);
219 }
220
221 /* Maybe mat file? */
222 ret=csv2dft_mat(csv, dft);
223 if(ret==CSV_OK) {
224 if(CSV_TEST>2) printf("reading Mat CSV format successful.\n");
225 return(ret);
226 }
227
228 /* Many CSV formats are impossible to identify, therefore we will just
229 try to convert different formats until one succeeds or all are failed */
230 if(CSV_TEST>2) printf("trying to read 1st CSV format\n");
231 ret=csv2dft_a(csv, dft);
232 if(ret!=CSV_OK) {
233 if(CSV_TEST>2) printf("reading 1st CSV format failed; trying 2nd format\n");
234 ret=csv2dft_b(csv, dft);
235 }
236 if(ret!=CSV_OK) {
237 if(CSV_TEST>2) printf("2nd CSV format failed\n");
238 }
239 if(ret!=CSV_OK) {dft->_type=DFT_FORMAT_PLAIN; return ret;}
240 /* Make sure that TAC names are filled */
241 u=dft->voiNr; n=1; while((u/=10)>=1) n++;
243 for(i=0, m=0; i<dft->voiNr; i++) {
244 if(strlen(dft->voi[i].voiname)<1 || strcmp(dft->voi[i].voiname, ".")==0) {
245 snprintf(dft->voi[i].voiname, 7, "%0*d", n, i+1);
246 strcpy(dft->voi[i].name, dft->voi[i].voiname);
247 m++;
248 }
249 }
250 /* If none of TACs had a name, then set DFT plain format */
251 if(m==dft->voiNr) dft->_type=DFT_FORMAT_PLAIN;
252
253 if(CSV_TEST>3) dftPrint(dft);
254 return CSV_OK;
255}
256/*****************************************************************************/
257
258/*****************************************************************************/
264 CSV *csv,
266 DFT *dft
267) {
268 int ri, ci, sci, ii, ret;
269 char *cptr;
270
271 if(CSV_TEST>2) {printf("csv2dft_a()\n"); fflush(stdout);}
272 if(csv==NULL || dft==NULL) return CSV_ERROR;
273 if(csv->row_nr<1 || csv->col_nr<1) return CSV_INVALIDFORMAT;
274
275
276 if(CSV_TEST>2)
277 for(int i=0; i<csv->nr; i++)
278 printf("row=%d col=%d content='%s'\n", csv->c[i].row, csv->c[i].col, csv->c[i].content);
279
280
281 /* Allocate memory for DFT */
282 dftEmpty(dft);
283 if(CSV_TEST>2) {
284 printf("frame_nr=%d voi_nr=%d\n", csv->row_nr, csv->col_nr-1);
285 fflush(stdout);
286 }
287 ret=dftSetmem(dft, csv->row_nr, csv->col_nr-1);
288 if(ret!=0) return CSV_OUTOFMEMORY;
289 /* Set DFT defaults */
292 dft->isweight=0;
293 dftUnitToDFT(dft, CUNIT_UNKNOWN);
294 dft->timeunit=TUNIT_UNKNOWN;
295 for(ri=0; ri<csv->row_nr; ri++) dft->w[ri]=1.0;
296 for(ci=0; ci<csv->col_nr-1; ci++) dft->voi[ci].sw=0;
297
298 /* Fill DFT */
299 ri=0;
300 for(ii=0; ii<csv->nr;) {
301 // goto start of row
302 for(; ii<csv->nr && csv->c[ii].col!=1; ii++) {}
303 if(ii==csv->nr) break;
304 if(CSV_TEST>10) {
305 printf("\nline start at %d\n", ii);
306 printf(" ri=%d\n", ri);
307 fflush(stdout);
308 }
309 // ignore line with empty first column
310 if(csv->c[ii].content==NULL) {
311 if(CSV_TEST>11) {printf(" empty first column\n"); fflush(stdout);}
312 ii++; continue;
313 }
314 // ignore comment line
315 if(csv->c[ii].content[0]=='#') {
316 if(CSV_TEST>11) {printf(" comment line\n"); fflush(stdout);}
317 ii++; continue;
318 }
319 // ignore line that does not start with number
320 // unless it contains TAC titles
321 if(!isdigit(csv->c[ii].content[0]) && csv->c[ii].content[0]!='-') {
322 if(strstr(csv->c[ii].content, "Time")==NULL &&
323 strstr(csv->c[ii].content, "TIME")==NULL &&
324 strstr(csv->c[ii].content, "time")==NULL)
325 {
326 if(CSV_TEST>11) {printf(" not a numerical value or title\n"); fflush(stdout);}
327 ii++; continue;
328 }
330 if(strncasecmp(csv->c[ii].content, "Start time", 10)==0 &&
331 strncasecmp(csv->c[ii+1].content, "End time", 8)==0)
332 {
334 if(CSV_TEST>6) printf("timetype := %d\n", dft->timetype);
335 }
336 if(CSV_TEST>7) {
337 printf("first title field := '%s'\n", csv->c[ii].content);
338 fflush(stdout);
339 }
340 if(strstr(csv->c[ii].content, "min")!=NULL) dft->timeunit=TUNIT_MIN;
341 else if(strstr(csv->c[ii].content, "sec")!=NULL) dft->timeunit=TUNIT_SEC;
342 else dft->timeunit=TUNIT_UNKNOWN;
343 ii++;
344
345 if(dft->timetype==DFT_TIME_MIDDLE) sci=2; else {sci=3; ii++;}
346 for(ci=sci; ci<=csv->col_nr && ii<csv->nr; ci++, ii++) {
347 if(CSV_TEST>2) {
348 printf("col=%d row=%d\n", csv->c[ii].col, csv->c[ii].row);
349 if(CSV_TEST>3) printf("ci=%d ii=%d\n", ci, ii);
350 fflush(stdout);
351 }
352 if(csv->c[ii].col!=ci) {dftEmpty(dft); return CSV_NOTABLE;}
353 if(csv->c[ii].content!=NULL) {
354 /* Check if this column should be omitted from DFT */
355 if(strstr(csv->c[ii].content, " - Time")!=NULL) {
356 if(CSV_TEST>2) printf(" ignored time column.\n");
357 dft->voi[ci-sci].sw=1; continue;
358 }
359 if(strstr(csv->c[ii].content, "(upper bound)")!=NULL) {
360 if(CSV_TEST>2) printf(" ignored upper bound column.\n");
361 dft->voi[ci-sci].sw=2; continue;
362 }
363 if(strstr(csv->c[ii].content, "(lower bound)")!=NULL) {
364 if(CSV_TEST>2) printf(" ignored lower bound column.\n");
365 dft->voi[ci-sci].sw=3; continue;
366 }
367 if(strstr(csv->c[ii].content, "(standard deviation)")!=NULL) {
368 if(CSV_TEST>2) printf(" ignored s.d. column.\n");
369 dft->voi[ci-sci].sw=4; continue;
370 }
371 /* Search calibration unit from name */
372 if(petCunitId(dft->unit)==CUNIT_UNKNOWN) {
373 if(strstr(csv->c[ii].content, "(Bq/ml)")!=NULL)
374 dftUnitToDFT(dft, CUNIT_BQ_PER_ML);
375 else if(strstr(csv->c[ii].content, "(kBq/ml)")!=NULL)
376 dftUnitToDFT(dft, CUNIT_KBQ_PER_ML);
377 else if(strstr(csv->c[ii].content, "(MBq/ml)")!=NULL)
378 dftUnitToDFT(dft, CUNIT_MBQ_PER_ML);
379 else if(strstr(csv->c[ii].content, "(% ID/g)")!=NULL)
380 dftUnitToDFT(dft, CUNIT_PIDM);
381 else if(strstr(csv->c[ii].content, "Bq/ml")!=NULL)
382 dftUnitToDFT(dft, CUNIT_BQ_PER_ML);
383 else if(strstr(csv->c[ii].content, "kBq/ml")!=NULL)
384 dftUnitToDFT(dft, CUNIT_KBQ_PER_ML);
385 else if(strstr(csv->c[ii].content, "MBq/ml")!=NULL)
386 dftUnitToDFT(dft, CUNIT_MBQ_PER_ML);
387 else if(strstr(csv->c[ii].content, "% ID/g")!=NULL)
388 dftUnitToDFT(dft, CUNIT_PIDM);
389 }
390 }
391 if(csv->c[ii].content==NULL) {
392 sprintf(dft->voi[ci-sci].name, "%d", ci-sci+1);
393 strcpy(dft->voi[ci-sci].voiname, dft->voi[ci-sci].name);
394 } else {
395 cptr=strstr(csv->c[ii].content, " - "); if(cptr!=NULL) *cptr=(char)0;
396 strncpy(dft->voi[ci-sci].name, csv->c[ii].content, MAX_REGIONNAME_LEN);
397 dft->voi[ci-sci].name[MAX_REGIONNAME_LEN]=(char)0;
398 rnameSplit(csv->c[ii].content, dft->voi[ci-sci].voiname,
399 dft->voi[ci-sci].hemisphere, dft->voi[ci-sci].place, MAX_REGIONSUBNAME_LEN);
400 }
401 if(CSV_TEST>8) printf("name[%d]=%s\n", ci-sci, dft->voi[ci-sci].name);
402 }
403 }
404
405 // check that allocated DFT frame nr is not exceeded
406 if(ri>=csv->row_nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
407 // read the sample time
408 if(dft->timetype==DFT_TIME_MIDDLE) {
409 dft->x[ri]=atof_dpi(csv->c[ii++].content);
410 if(CSV_TEST>3) printf("x[%d]=%g\n", ri, dft->x[ri]);
411 } else {
412 dft->x1[ri]=atof_dpi(csv->c[ii++].content);
413 dft->x2[ri]=atof_dpi(csv->c[ii++].content);
414 dft->x[ri]=0.5*(dft->x1[ri]+dft->x2[ri]);
415 if(CSV_TEST>3) printf("x1[%d]=%g x2[%d]=%g\n", ri, dft->x1[ri], ri, dft->x2[ri]);
416 }
417 // read the sample values
418 if(dft->timetype==DFT_TIME_MIDDLE) sci=2; else sci=3;
419 for(ci=sci; ci<=csv->col_nr && ii<csv->nr; ci++, ii++) {
420 if(CSV_TEST>2) {
421 printf(" col=%d row=%d\n", csv->c[ii].col, csv->c[ii].row);
422 if(CSV_TEST>3) printf(" ci=%d ii=%d\n", ci, ii);
423 fflush(stdout);
424 }
425 if(csv->c[ii].col!=ci) {dftEmpty(dft); return CSV_NOTABLE;}
426 if(strlen(csv->c[ii].content)==0 || strcmp(csv->c[ii].content, ".")==0)
427 dft->voi[ci-sci].y[ri]=nan("");
428 else
429 dft->voi[ci-sci].y[ri]=atof_dpi(csv->c[ii].content);
430 if(CSV_TEST>4)
431 printf(" y[%d][%d]=%g\n", ri, ci-sci, dft->voi[ci-sci].y[ri]);
432 }
433 ri++; //if(ri>csv->row_nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
434 }
435 if(CSV_TEST>1) printf(" %d frame(s) read from CSV\n", ri);
436 if(ri<1) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
437 dft->frameNr=ri;
438 dft->voiNr=csv->col_nr-1; if(dft->timetype==DFT_TIME_STARTEND) dft->voiNr--;
439
440 /* Remove those DFT VOIs which where above set to be deleted (where sw!=0) */
441 for(ci=dft->voiNr-1, ret=0; ci>=0; ci--) if(dft->voi[ci].sw!=0) {
442 ret=dftDelete(dft, ci); if(ret!=0) break;}
443 if(ret!=0) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
444 if(dft->voiNr<1) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
445
446 /* Calculate frame mid times, or frame start and end times;
447 this works only if time units are known */
448 dftFrametimes(dft);
449
450 return CSV_OK;
451}
452/*****************************************************************************/
453
454/*****************************************************************************/
460 CSV *csv,
462 DFT *dft
463) {
464 int ri, fi, fip, ii, ret;
465 char *cptr, *cptr2, tmp[256];
466 double v1, v2;
467
468 if(CSV_TEST>2) {printf("csv2dft_b()\n"); fflush(stdout);}
469 if(csv==NULL || dft==NULL) return CSV_ERROR;
470 //printf("row_nr=%d col_nr=%d\n", csv->row_nr, csv->col_nr);
471 if(csv->row_nr<4 || csv->col_nr!=9) return CSV_INVALIDFORMAT;
472 dftEmpty(dft);
473
474 /* Check the format; first line (containing titles) */
475 if(strcasecmp(csv->c[0].content, "#Subject ID")!=0) return CSV_INVALIDFORMAT;
476 if(strcasecmp(csv->c[1].content, "Subject Weight")!=0) return CSV_INVALIDFORMAT;
477 if(strcasecmp(csv->c[2].content, "Subject Sex")!=0) return CSV_INVALIDFORMAT;
478 if(strcasecmp(csv->c[3].content, "Unique Series ID")!=0) return CSV_INVALIDFORMAT;
479 if(strcasecmp(csv->c[4].content, "Series Date")!=0) return CSV_INVALIDFORMAT;
480 if(strcasecmp(csv->c[5].content, "Series Description")!=0) return CSV_INVALIDFORMAT;
481
482 /* Check the format; third line (containing titles) */
483 if(strcasecmp(csv->c[12].content, "#Name")!=0) return CSV_INVALIDFORMAT;
484 if(strcasecmp(csv->c[13].content, "Volume (mm^3)")!=0) return CSV_INVALIDFORMAT;
485 if(strcasecmp(csv->c[14].content, "Mean")!=0) return CSV_INVALIDFORMAT;
486 if(strcasecmp(csv->c[15].content, "SD")!=0) return CSV_INVALIDFORMAT;
487 if(strcasecmp(csv->c[16].content, "Min")!=0) return CSV_INVALIDFORMAT;
488 if(strcasecmp(csv->c[17].content, "Max")!=0) return CSV_INVALIDFORMAT;
489 if(strcasecmp(csv->c[18].content, "Frame Index")!=0) return CSV_INVALIDFORMAT;
490 if(strncasecmp(csv->c[19].content, "Mid time (sec)", 10)!=0) return CSV_INVALIDFORMAT;
491 if(strncasecmp(csv->c[20].content, "Duration (sec)", 10)!=0) return CSV_INVALIDFORMAT;
492
493 /* Calculate the number of ROIs and time frames */
494 ri=1; fi=0; fip=-1; ii=21; cptr=csv->c[ii].content;
495 //printf("cell[%d] := '%s'\n", ii, cptr); fflush(stdout);
496 for(; ii<csv->nr; ii+=9) {
497 cptr2=csv->c[ii].content;
498 //printf("cell[%d] := '%s'\n", ii, cptr2); fflush(stdout);
499 if(strcmp(cptr, cptr2)==0) fi++;
500 else {
501 ri++; cptr=cptr2;
502 if(fip<0) fip=fi; else if(fi!=fip) return CSV_INVALIDFORMAT;
503 fi=1;
504 }
505 //printf("ri=%d fi=%d fip=%d\n", ri, fi, fip);
506 }
507 //printf("ri=%d fi=%d\n", ri, fi);
508
509 /* Allocate memory for DFT */
510 if(CSV_TEST>2) {printf("frame_nr=%d voi_nr=%d\n", fi, ri); fflush(stdout);}
511 ret=dftSetmem(dft, fi, ri);
512 if(ret!=0) return CSV_OUTOFMEMORY;
513 dft->voiNr=ri; dft->frameNr=fi;
516 dft->isweight=0;
517 dftUnitToDFT(dft, CUNIT_UNKNOWN); dft->timeunit=TUNIT_UNKNOWN;
518 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]=1.0;
519
520 /* Fill DFT */
521 /* time unit */
522 ii=19;
523 if(strstr(csv->c[ii].content, "min")!=NULL) dft->timeunit=TUNIT_MIN;
524 else if(strstr(csv->c[ii].content, "sec")!=NULL) dft->timeunit=TUNIT_SEC;
525 else dft->timeunit=TUNIT_UNKNOWN;
526 /* study number */
527 ii=6;
528 cptr=csv->c[ii].content; strlcpy(dft->studynr, cptr, MAX_STUDYNR_LEN);
529 cptr=strchr(dft->studynr, '.'); if(cptr!=NULL) *cptr=(char)0;
530 cptr=strchr(dft->studynr, ','); if(cptr!=NULL) *cptr=(char)0;
531 cptr=strchr(dft->studynr, ' '); if(cptr!=NULL) *cptr=(char)0;
532 /* subject weight */
533 ii=7; if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
534 v1=atof_dpi(csv->c[ii].content);
535 if(v1>0.0) sprintf(dft->comments, "# weight := %g\n", v1);
536 /* scan start time */
537 ii=10; if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
538 if(strlen(csv->c[ii].content)>9) {
539 sprintf(tmp, "# scan_start_time := %s\n", csv->c[ii].content);
540 strcat(dft->comments, tmp);
541 }
542 /* frame times */
543 for(fi=0; fi<dft->frameNr; fi++) {
544 ii= 21 + fi*9 + 7; if(ii>csv->nr-2) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
545 //printf("cell[%d] := '%s'\n", ii, csv->c[ii].content); fflush(stdout);
546 v1=atof_dpi(csv->c[ii].content); v2=atof_dpi(csv->c[ii+1].content);
547 dft->x[fi]=v1; dft->x1[fi]=v1-0.5*v2; dft->x2[fi]=v1+0.5*v2;
548 }
549 /* region names, volumes, and concentrations */
550 for(ri=0; ri<dft->voiNr; ri++) {
551 /* ROI name */
552 ii= 21 + ri*dft->frameNr*9;
553 if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
554 //printf("ri=%d cell[%d] := '%s'\n", ri, ii, csv->c[ii].content); fflush(stdout);
555 strncpy(dft->voi[ri].name, csv->c[ii].content, MAX_REGIONNAME_LEN);
556 dft->voi[ri].name[MAX_REGIONNAME_LEN]=(char)0;
557 rnameSplit(csv->c[ii].content, dft->voi[ri].voiname, dft->voi[ri].hemisphere, dft->voi[ri].place,
559 /* Volume */
560 ii++; if(ii>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
561 dft->voi[ri].size=atof_dpi(csv->c[ii].content);
562 /* Frame concentrations */
563 ii++; for(fi=0; fi<dft->frameNr; fi++) {
564 if((ii+6)>=csv->nr) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
565 /* Get concentration */
566 dft->voi[ri].y[fi]=atof_dpi(csv->c[ii].content);
567 /* Get concentration SD (probably not needed) */
568 dft->voi[ri].y2[fi]=atof_dpi(csv->c[ii+1].content);
569 /* check that frame times are correct */
570 v1=atof_dpi(csv->c[ii+5].content);
571 if(dft->x[fi]!=v1) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
572 ii+=9;
573 } // next frame
574 } // next region
575
576 return CSV_OK;
577}
578/*****************************************************************************/
579
580/*****************************************************************************/
586 CSV *csv,
588 DFT *dft
589) {
590 int ri, ci, fi, sci, ii, ret;
591 double v;
592 char *cptr;
593
594 /* Check input data */
595 if(CSV_TEST>2) {printf("csv2dft_linkset()\n"); fflush(stdout);}
596 if(csv==NULL || dft==NULL) return CSV_ERROR;
597 if(csv->nr<2 || csv->row_nr<1 || csv->col_nr<1) return CSV_INVALIDFORMAT;
598 if(strcasecmp(csv->c[0].content, "LinkSet")!=0) return CSV_INVALIDFORMAT;
599 /* Get the ROI nr */
600 for(ii=1, ri=0; ii<csv->nr; ii++) if(csv->c[ii].col==1) {
601 if(csv->c[ii].content==NULL) continue;
602 if(strncmp(csv->c[ii].content, "VOI:", 4)==0) ri++;
603 }
604 if(CSV_TEST>2) {
605 printf("frame_nr=%d voi_nr=%d\n", csv->col_nr-2, ri);
606 fflush(stdout);
607 }
608 if(ri<1 || csv->col_nr<3) return CSV_INVALIDFORMAT;
609 /* Delete previous DFT contents */
610 dftEmpty(dft);
611 /* Allocate memory for DFT */
612 ret=dftSetmem(dft, csv->col_nr-2, ri); if(ret!=0) return CSV_OUTOFMEMORY;
613 dft->voiNr=ri;
614 dft->frameNr=csv->col_nr-2;
615
616 /* Set DFT defaults */
619 dft->isweight=0;
620 dftUnitToDFT(dft, CUNIT_UNKNOWN);
621 dft->timeunit=TUNIT_UNKNOWN;
622 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]=1.0;
623 for(ri=0; ri<dft->voiNr; ri++) dft->voi[ri].sw=0;
624
625 /* Fill DFT contents */
626 for(ri=0; ri<dft->voiNr; ri++) {
627 if(CSV_TEST>3) printf("reading VOI %d\n", 1+ri);
628 /* Search the (ri+1)th VOI */
629 sci=0;
630 for(ii=1; ii<csv->nr; ii++) if(csv->c[ii].col==1) {
631 if(csv->c[ii].content==NULL) continue;
632 if(strncmp(csv->c[ii].content, "VOI:", 4)==0) sci++;
633 if(sci==ri+1) break;
634 }
635 if(sci!=ri+1) break; // not found
636 // ii is not the index of the start of data for one VOI
637 if(CSV_TEST>5) printf(" ri=%d ii=%d row=%d col=%d\n", ri, ii, csv->c[ii].row, csv->c[ii].col);
638 /* Take the ROI number from there in case better name is not found later */
639 strncpy(dft->voi[ri].name, csv->c[ii].content+4, MAX_REGIONNAME_LEN);
640 dft->voi[ri].name[MAX_REGIONNAME_LEN]=(char)0;
641 /* Read time unit from the next field */
642 if(CSV_TEST>4 && ri==0) printf("reading time unit\n");
643 cptr=strchr(csv->c[ii+1].content, '(');
644 if(cptr!=NULL) {
645 ci=petTunitId(cptr+1);
646 if(ri==0) {
647 dft->timeunit=ci;
648 } else if(dft->timeunit!=ci) {
649 if(CSV_TEST>0) printf("different time units.\n");
650 return CSV_INVALIDFORMAT;
651 }
652 }
653 if(CSV_TEST>4 && ri==0) printf("time unit: %s\n", petTunit(dft->timeunit));
654 /* Read the times */
655 for(fi=0; fi<dft->frameNr; fi++) {
656 ci=ii+fi+2; if(ci>=csv->nr) return CSV_INVALIDFORMAT;
657 cptr=csv->c[ci].content;
658 if(atof_with_check(cptr, &v)!=0) return CSV_INVALIDFORMAT;
659 if(ri==0) {
660 dft->x[fi]=v;
661 } else {
662 if(fabs(v-dft->x[fi])>1.0E-003) return CSV_INVALIDFORMAT;
663 }
664 } // next frame time
665 /* First column on the 2nd row should contain the region name */
666 if(CSV_TEST>4) printf("reading VOI name\n");
667 ii+=csv->col_nr; if(ii>=csv->nr) return CSV_INVALIDFORMAT;
668 cptr=csv->c[ii].content;
669 if(cptr!=NULL) {
670 strncpy(dft->voi[ri].name, cptr, MAX_REGIONNAME_LEN);
671 dft->voi[ri].name[MAX_REGIONNAME_LEN]=(char)0;
672 } // default name was set before
673 rnameSplit(dft->voi[ri].name, dft->voi[ri].voiname, dft->voi[ri].hemisphere, dft->voi[ri].place,
675 /* VOI average values should be two rows below this */
676 if(CSV_TEST>4) printf("reading VOI values\n");
677 ii+=2*csv->col_nr; if(ii>=csv->nr) return CSV_INVALIDFORMAT;
678 /* Check that from 2nd column, and get from there the unit, too */
679 ii++; if(ii>=csv->nr) return CSV_INVALIDFORMAT;
680 cptr=csv->c[ii].content; if(cptr==NULL) return CSV_INVALIDFORMAT;
681 if(strncasecmp(cptr, "Average", 7)!=0) return CSV_INVALIDFORMAT;
682 cptr=strchr(csv->c[ii].content, '(');
683 if(cptr!=NULL) {
684 if(CSV_TEST>4 && ri==0)
685 printf("reading activity unit from string: '%s'\n", cptr+1);
686 ci=petCunitId(cptr+1);
687 if(ri==0) {
688 strcpy(dft->unit, petCunit(ci));
689 } else if(ci!=petCunitId(dft->unit)) {
690 if(CSV_TEST>0) printf("different concentration units.\n");
691 return CSV_INVALIDFORMAT;
692 }
693 if(CSV_TEST>5 && ri==0) printf("unit := %s (%d)\n", petCunit(ci), ci);
694 }
695 /* then read the concentrations */
696 for(fi=0; fi<dft->frameNr; fi++) {
697 ci=ii+fi+1; if(ci>=csv->nr) return CSV_INVALIDFORMAT;
698 cptr=csv->c[ci].content;
699 if(atof_with_check(cptr, &v)!=0) return CSV_INVALIDFORMAT;
700 dft->voi[ri].y[fi]=v;
701 } // next frame time
702 }
703 if(ri<dft->voiNr) return CSV_INVALIDFORMAT;
704
705 return CSV_OK;
706}
707/*****************************************************************************/
708
709/*****************************************************************************/
715 CSV *csv,
717 DFT *dft
718) {
719 int ri, fi, ret;
720 char *cptr;
721
722 /* Check input data */
723 if(CSV_TEST>2) {printf("csv2dft_mat()\n"); fflush(stdout);}
724 if(csv==NULL || dft==NULL) return CSV_ERROR;
725 if(csv->nr<4 || csv->row_nr<2 || csv->col_nr<2) return CSV_INVALIDFORMAT;
726 if(!csvIsRegular(csv)) return CSV_INVALIDFORMAT;
727
728 /* Delete previous DFT contents */
729 dftEmpty(dft);
730 /* Allocate memory for DFT */
731 ret=dftSetmem(dft, csv->col_nr-1, csv->row_nr-1); if(ret!=0) return CSV_OUTOFMEMORY;
732 dft->voiNr=csv->row_nr-1;
733 dft->frameNr=csv->col_nr-1;
734 if(CSV_TEST>2) {printf("frame_nr=%d voi_nr=%d\n", dft->frameNr, dft->voiNr); fflush(stdout);}
735
736 /* Set DFT defaults */
739 dft->isweight=0;
740 dftUnitToDFT(dft, CUNIT_UNKNOWN);
741 dft->timeunit=TUNIT_UNKNOWN;
742 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]=1.0;
743 for(ri=0; ri<dft->voiNr; ri++) dft->voi[ri].sw=0;
744
745 if(CSV_TEST>200)
746 for(int i=0; i<csv->nr; i++)
747 printf("row=%d col=%d content='%s'\n", csv->c[i].row, csv->c[i].col, csv->c[i].content);
748
749 /* First cell may contain study number */
750 cptr=csvCell(csv, 1, 1);
751 if(cptr!=NULL && cptr[0] && strnlen(cptr, 20)<20) {
752 strlcpy(dft->studynr, cptr, MAX_STUDYNR_LEN);
753 if(CSV_TEST>3) printf("studynr := %s\n", dft->studynr);
754 }
755
756 /* Fill DFT contents */
757 ret=0;
758 for(ri=0; ri<dft->voiNr; ri++) {
759 if(CSV_TEST>3) printf("reading VOI %d\n", 1+ri);
760 /* Get ROI name */
761 cptr=csvCell(csv, ri+2, 1); //printf("cptr='%s'\n", cptr);
762 if(cptr==NULL) {ret++; break;}
763 int n=strlen(cptr); if(n<3) {ret++; break;}
764 if(cptr[n-1]=='\'') {cptr[n-1]=(char)0; n--;} else {ret++; break;}
765 if(cptr[0]=='\'') {cptr++; n--;} else {ret++; break;}
766 strlcpy(dft->voi[ri].name, cptr, MAX_REGIONNAME_LEN);
767 rnameSplit(dft->voi[ri].name, dft->voi[ri].voiname, dft->voi[ri].hemisphere, dft->voi[ri].place,
769 /* Get concentrations */
770 for(fi=0; fi<dft->frameNr; fi++) {
771 cptr=csvCell(csv, ri+2, fi+2); // printf("cptr='%s'\n", cptr);
772 ret=atof_with_check(cptr, &dft->voi[ri].y[fi]);
773 if(ret) break;
774 }
775 if(ret!=0) break;
776 }
777 if(ret!=0) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
778
779 /* Get frame times */
780 if(CSV_TEST>3) printf("reading frames\n");
781 ret=0;
782 for(fi=0; fi<dft->frameNr; fi++) {
783 cptr=csvCell(csv, 1, fi+2); if(cptr==NULL) {ret++; break;}
784 int n=strlen(cptr); if(n<3) {ret++; break;}
785 char *cptr2=strchr(cptr+1, '-'); if(cptr2!=NULL) {*cptr2=(char)0; cptr2++;}
786 ret=atof_with_check(cptr, &dft->x1[fi]);
787 if(ret==0) ret=atof_with_check(cptr2, &dft->x2[fi]);
788 if(ret) break;
789 dft->x[fi]=0.5*(dft->x1[fi]+dft->x2[fi]);
790 }
791 if(ret!=0) {dftEmpty(dft); return CSV_INVALIDFORMAT;}
792
793 return CSV_OK;
794}
795/*****************************************************************************/
796
797/*****************************************************************************/
805 CSV *csv
806) {
807 if(csv==NULL) return(0);
808 if(csv->nr<2) return(1);
809 int i, r, n=0, m=0;
810 i=0; r=csv->c[i].row; m++;
811 for(i=1; i<csv->nr; i++) {
812 if(r==csv->c[i].row) {m++; continue;}
813 if(n>0 && m!=n) return(0);
814 r=csv->c[i].row; n=m; m=1;
815 }
816 if(n>0 && m!=n) return(0);
817 return(1);
818}
819/*****************************************************************************/
820
821/*****************************************************************************/
829 CSV *csv,
831 int row,
833 int col
834) {
835 if(csv==NULL) return((char*)NULL);
836 for(int i=0; i<csv->nr; i++)
837 if(csv->c[i].row==row && csv->c[i].col==col)
838 return(csv->c[i].content);
839 return((char*)NULL);
840}
841/*****************************************************************************/
842
843/*****************************************************************************/
int csv2dft_a(CSV *csv, DFT *dft)
Definition csv.c:262
int CSV_TEST
Definition csv.c:6
void csvInit(CSV *csv)
Definition csv.c:13
void csvEmpty(CSV *csv)
Definition csv.c:24
int csvIsRegular(CSV *csv)
Definition csv.c:803
int csv2dft_mat(CSV *csv, DFT *dft)
Definition csv.c:713
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:827
int csv2dft(CSV *csv, DFT *dft)
Definition csv.c:200
int csvRead(CSV *csv, char *fname)
Definition csv.c:42
int csv2dft_linkset(CSV *csv, DFT *dft)
Definition csv.c:584
int csv2dft_b(CSV *csv, DFT *dft)
Definition csv.c:458
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
double atof_dpi(char *str)
Definition decpoint.c:59
int dftDelete(DFT *dft, int voi)
Definition dft.c:538
int dftSetmem(DFT *data, int frameNr, int voiNr)
Definition dft.c:57
void dftEmpty(DFT *data)
Definition dft.c:20
void dftFrametimes(DFT *data)
Definition dft.c:340
void dftPrint(DFT *data)
Definition dftio.c:538
void dftUnitToDFT(DFT *dft, int dunit)
Definition dftunit.c:11
Header file for libtpccurveio.
#define DFT_TIME_MIDDLE
#define DFT_FORMAT_STANDARD
#define DFT_FORMAT_PLAIN
#define DFT_TIME_STARTEND
int petCunitId(const char *unit)
Definition petunits.c:74
char * petCunit(int cunit)
Definition petunits.c:211
int strCleanSpaces(char *s)
Definition strext.c:343
int rnameSplit(char *rname, char *name1, char *name2, char *name3, int max_name_len)
Definition rname.c:14
#define MAX_REGIONNAME_LEN
Definition libtpcmisc.h:154
size_t strnlen(const char *s, size_t n)
Definition strext.c:181
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
char * petTunit(int tunit)
Definition petunits.c:226
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
int petTunitId(const char *timeunit)
Definition petunits.c:187
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
char * content
int row_nr
int col_nr
char separator
CSV_item * c
int _type
int timetype
Voi * voi
int timeunit
char studynr[MAX_STUDYNR_LEN+1]
double * w
double * x1
char comments[_DFT_COMMENT_LEN+1]
int voiNr
double * x2
int frameNr
int isweight
double * x
char unit[MAX_UNITS_LEN+1]
double size
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
char sw
double * y
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]