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

I/O functions for CSV files (comma-separated values). More...

#include "libtpccurveio.h"

Go to the source code of this file.

Functions

void csvInit (CSV *csv)
 
void csvEmpty (CSV *csv)
 
int csvRead (CSV *csv, char *fname)
 
int csv2dft (CSV *csv, DFT *dft)
 
int csv2dft_a (CSV *csv, DFT *dft)
 
int csv2dft_b (CSV *csv, DFT *dft)
 
int csv2dft_linkset (CSV *csv, DFT *dft)
 
int csv2dft_mat (CSV *csv, DFT *dft)
 
int csvIsRegular (CSV *csv)
 
char * csvCell (CSV *csv, int row, int col)
 

Variables

int CSV_TEST
 

Detailed Description

I/O functions for CSV files (comma-separated values).

Author
Vesa Oikonen

Definition in file csv.c.

Function Documentation

◆ csv2dft()

int csv2dft ( CSV * csv,
DFT * dft )

Reads different CSV formats into DFT struct

Returns
Returns 0 when successful, otherwise an error code.
Parameters
csvPointer to CSV data to be converted
dftPointer to empty DFT struct which will be allocated and filled here

Definition at line 200 of file csv.c.

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}
int csv2dft_a(CSV *csv, DFT *dft)
Definition csv.c:262
int CSV_TEST
Definition csv.c:6
int csv2dft_mat(CSV *csv, DFT *dft)
Definition csv.c:713
int csv2dft_linkset(CSV *csv, DFT *dft)
Definition csv.c:584
int csv2dft_b(CSV *csv, DFT *dft)
Definition csv.c:458
void dftPrint(DFT *data)
Definition dftio.c:538
#define DFT_FORMAT_PLAIN
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
char * content
int row_nr
int col_nr
CSV_item * c
int _type
Voi * voi
int voiNr
char voiname[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]

Referenced by dftRead().

◆ csv2dft_a()

int csv2dft_a ( CSV * csv,
DFT * dft )

Reads simple and Inveon type 1 data into DFT struct

Returns
Returns 0 when successful, otherwise an error code.
Parameters
csvPointer to CSV data to be converted
dftPointer to empty DFT struct which will be allocated and filled here

Definition at line 262 of file csv.c.

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}
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 dftUnitToDFT(DFT *dft, int dunit)
Definition dftunit.c:11
#define DFT_TIME_MIDDLE
#define DFT_FORMAT_STANDARD
#define DFT_TIME_STARTEND
int petCunitId(const char *unit)
Definition petunits.c:74
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
int timetype
int timeunit
double * w
double * x1
double * x2
int frameNr
int isweight
double * x
char unit[MAX_UNITS_LEN+1]
char sw
double * y
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]

Referenced by csv2dft().

◆ csv2dft_b()

int csv2dft_b ( CSV * csv,
DFT * dft )

Reads Inveon type 2 data into DFT struct

Returns
Returns 0 when successful, otherwise an error code.
Parameters
csvPointer to CSV data to be converted
dftPointer to empty DFT struct which will be allocated and filled here

Definition at line 458 of file csv.c.

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}
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
char studynr[MAX_STUDYNR_LEN+1]
char comments[_DFT_COMMENT_LEN+1]
double size
double * y2

Referenced by csv2dft().

◆ csv2dft_linkset()

int csv2dft_linkset ( CSV * csv,
DFT * dft )

Reads LinkSet data into DFT struct.

Returns
Returns 0 when successful, otherwise an error code.
Parameters
csvPointer to CSV data to be converted
dftPointer to empty DFT struct which will be allocated and filled here

Definition at line 584 of file csv.c.

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}
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
char * petCunit(int cunit)
Definition petunits.c:211
char * petTunit(int tunit)
Definition petunits.c:226
int petTunitId(const char *timeunit)
Definition petunits.c:187

Referenced by csv2dft().

◆ csv2dft_mat()

int csv2dft_mat ( CSV * csv,
DFT * dft )

Reads Mat data into DFT struct.

Returns
Returns 0 when successful, otherwise an error code.
Parameters
csvPointer to CSV data to be converted
dftPointer to empty DFT struct which will be allocated and filled here

Definition at line 713 of file csv.c.

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}
int csvIsRegular(CSV *csv)
Definition csv.c:803
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:827
size_t strnlen(const char *s, size_t n)
Definition strext.c:181

Referenced by csv2dft().

◆ csvCell()

char * csvCell ( CSV * csv,
int row,
int col )

Get the CVS field contents in specified row and column.

Returns
Returns pointer to the content string, or NULL if not found.
Author
Vesa Oikonen
See also
csvRead
Parameters
csvPointer to CSV
rowCSV row index
colCSV column index

Definition at line 827 of file csv.c.

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}

Referenced by csv2dft_mat().

◆ csvEmpty()

void csvEmpty ( CSV * csv)

Free allocated memory in CSV struct

Parameters
csvPointer to CSV struct

Definition at line 24 of file csv.c.

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}
char separator

Referenced by dftFormat(), and dftRead().

◆ csvInit()

void csvInit ( CSV * csv)

Initiate CSV struct

Parameters
csvPointer to CSV struct

Definition at line 13 of file csv.c.

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}

Referenced by dftFormat(), and dftRead().

◆ csvIsRegular()

int csvIsRegular ( CSV * csv)

Check whether CSV is regular, that is, each row contain the same number of columns.

Author
Vesa Oikonen
See also
csvRead
Returns
Returns 1 if CSV is regular, 0 if not.
Parameters
csvPointer to CSV

Definition at line 803 of file csv.c.

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}

Referenced by csv2dft_mat().

◆ csvRead()

int csvRead ( CSV * csv,
char * fname )

Read CSV file.

Returns
Non-zero in case of an error.
Parameters
csvPointer to CSV struct
fnameFilename

Definition at line 42 of file csv.c.

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}
int strCleanSpaces(char *s)
Definition strext.c:343

Referenced by dftFormat(), and dftRead().

Variable Documentation

◆ CSV_TEST

int CSV_TEST

Verbose prints from CSV functions.

Definition at line 6 of file csv.c.

Referenced by csv2dft(), csv2dft_a(), csv2dft_b(), csv2dft_linkset(), csv2dft_mat(), csvRead(), dftFormat(), and dftRead().