TPCCLIB
Loading...
Searching...
No Matches
dftio.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "libtpccurveio.h"
10#include <unistd.h>
11/*****************************************************************************/
14/*****************************************************************************/
15
16/*****************************************************************************/
24 char *filename,
26 DFT *data
27) {
28 const int verbose=0;
29 if(verbose>0) {printf("%s(%s, dft)\n", __func__, filename); fflush(stdout);}
30
31 FILE *fp;
32 char *cptr, *line, *lptr, temp[128];
33 int ret, i, j, c, type=0, voiNr=0, frameNr=0, longest=0;
34 double f;
35 IFT ift;
36
37
38 /* Empty data */
39 if(data==NULL) {strcpy(dfterrmsg, "invalid data"); return 1;}
40 dftEmpty(data);
41
42 /* Check if file can be opened for read; then close it for now */
43 if(verbose>1) {printf("opening file\n"); fflush(stdout);}
44 fp=fopen(filename, "r");
45 if(fp==NULL) {strcpy(dfterrmsg, "cannot open file"); return 1;}
46 fclose(fp);
47
48 /* Try to identify the file format */
49 type=dftFormat(filename); if(verbose>1) printf(" type := %d\n", type);
50 if(type==DFT_FORMAT_UNKNOWN) {
51 strcpy(dfterrmsg, "unknown file format"); return 1;
52 } else if(type==DFT_FORMAT_FIT) {
53 strcpy(dfterrmsg, "cannot read fit file"); return 1;
54 }
55
56 /* Read some special formats */
57 if(type==DFT_FORMAT_NCI) { // TPC format before DFT
58 if(verbose>1) {printf("calling roikbqRead()\n"); fflush(stdout);}
59 ret=roikbqRead(filename, data); if(ret!=0) return ret;
60 dftFrametimes(data);
61 return(0);
62 } else if(type==DFT_FORMAT_IDWC) {
63 if(verbose>1) {printf("calling idwcRead()\n"); fflush(stdout);}
64 ret=idwcRead(filename, data); if(ret!=0) return ret;
65 if(strlen(data->studynr)==0) studynr_from_fname(filename, data->studynr);
66 return(0);
67 } else if(type==DFT_FORMAT_IF) {
68 if(verbose>1) {printf("calling iftRead()\n"); fflush(stdout);}
69 ret=ifRead(filename, data); if(ret!=0) return ret;
70 if(strlen(data->studynr)==0) studynr_from_fname(filename, data->studynr);
71 return(0);
72 } else if(type==DFT_FORMAT_CSV_INT || type==DFT_FORMAT_CSV_UK) {
73 CSV csv;
74 csvInit(&csv); //CSV_TEST=100;
75 if(verbose>1) {printf("calling csvRead()\n"); fflush(stdout);}
76 ret=csvRead(&csv, filename);
77 if(ret==0) ret=csv2dft(&csv, data);
78 csvEmpty(&csv);
79 if(ret==0) {
80 /* Try to read information from an interfile-type header */
81 IFT ift; iftInit(&ift);
82 if(iftRead(&ift, filename, 1, 0)==0 && ift.keyNr>0) dft_fill_hdr_from_IFT(data, &ift);
83 iftEmpty(&ift);
84 /* study number, too */
85 if(strlen(data->studynr)==0) studynr_from_fname(filename, data->studynr);
86 /* Set DFT comments */
87 dftSetComments(data);
88 return(0);
89 }
90 // if not ok, then just drop through with plain format
92 }
93
94 /* Try to read supported TAC formats, not the others */
95 if(type!=DFT_FORMAT_PLAIN && type!=DFT_FORMAT_STANDARD &&
96 type!=DFT_FORMAT_IFT && type!=DFT_FORMAT_PMOD
97 ) {
98 strcpy(dfterrmsg, "unsupported file format"); return 1;
99 }
100
101 /* Try to read information from an interfile-type header */
102 if(verbose>1) {printf("calling iftRead()\n"); fflush(stdout);}
103 iftInit(&ift);
104 if(iftRead(&ift, filename, 1, 0)!=0) iftEmpty(&ift);
105
106 /* Open file */
107 if(verbose>1) {printf("re-opening file\n"); fflush(stdout);}
108 fp=fopen(filename, "r");
109 if(fp==NULL) {
110 strcpy(dfterrmsg, "cannot open file"); iftEmpty(&ift); return 1;
111 }
112
113 /* Get the length of the longest line */
114 i=0; while((c=fgetc(fp))!=EOF) {
115 if(c==10 || c==13) {if(i>longest) longest=i; i=0;} else i++;}
116 if(i>longest) longest=i;
117 rewind(fp); longest+=2;
118 if(verbose>1) {printf(" longest := %d\n", longest); fflush(stdout);}
119
120 /* and allocate memory for string of that length */
121 line=(char*)malloc((longest+1)*sizeof(char));
122 if(line==NULL) {strcpy(dfterrmsg, "out of memory"); iftEmpty(&ift); fclose(fp); return 2;}
123
124 /* Get the frame number */
125 i=0; while(fgets(line, longest, fp)!=NULL && *line) {
126 if(line[0]=='#') continue;
127 cptr=strchr(line, '#'); if(cptr!=NULL) *cptr=(char)0;
128 for(j=0; j<(int)strlen(line); j++)
129 if(isalnum((int)line[j]) || line[j]=='.') {i++; break;}
130 }
131 rewind(fp); frameNr=i;
132 if(type==DFT_FORMAT_STANDARD) frameNr-=4; /* title lines */
133 if(type==DFT_FORMAT_PMOD) frameNr-=1;
134 if(verbose>1) {printf("frameNr := %d\n", frameNr); fflush(stdout);}
135 if(frameNr<1) {
136 strcpy(dfterrmsg, "contains no data");
137 iftEmpty(&ift); free(line); fclose(fp); return 1;
138 }
139
140 /* Get the number of curves */
141 /* find first line that is not an empty or a comment line */
142 while(fgets(line, longest, fp)!=NULL) {
143 if(line[0]=='#') continue;
144 /* If PMOD file, then read it from the title */
145 if(type==DFT_FORMAT_PMOD) {voiNr=dftGetPmodTitle(NULL, line); break;}
146 /* In plain data file that is first frame, which starts with time */
147 /* In normal DFT file that is 1st title line, which starts with 'DFT' */
148 char *nline; nline=strdup(line); lptr=nline;
149 cptr=strtok(lptr, " \t\n\r"); if(cptr==NULL) {free(nline); continue;}
150 voiNr=0; while((cptr=strtok(NULL, " \t\n\r"))!=NULL) voiNr++;
151 free(nline);
152 break;
153 }
154 rewind(fp);
155 if(verbose>1) {printf("voiNr := %d\n", voiNr); fflush(stdout);}
156 if(voiNr<1) {
157 strcpy(dfterrmsg, "contains no curves");
158 iftEmpty(&ift); free(line); fclose(fp); return 1;
159 }
160
161 /* Allocate memory for data */
162 if(verbose>1) {printf("allocating memory\n"); fflush(stdout);}
163 if(dftSetmem(data, frameNr, voiNr)) {
164 strcpy(dfterrmsg, "out of memory");
165 iftEmpty(&ift); free(line); fclose(fp); return 2;
166 }
167
168 /* For plain data files, set defaults for title data */
169 if(type==DFT_FORMAT_PLAIN || type==DFT_FORMAT_IFT) {
170 if(verbose>1) {printf("setting title defaults for plain data\n"); fflush(stdout);}
171 int u, n; u=voiNr; n=1; while((u/=10)>=1) n++;
173 for(i=0; i<voiNr; i++) {
174 snprintf(data->voi[i].voiname, MAX_REGIONSUBNAME_LEN+1, "%0*d", n, i+1);
175 strcpy(data->voi[i].name, data->voi[i].voiname);
176 }
177 /* Default: times in minutes, and frame mid time */
178 data->timeunit=TUNIT_UNKNOWN; data->timetype=DFT_TIME_MIDDLE;
179 }
180
181 /*
182 * Try to read information from an interfile-type header
183 */
184 if(ift.keyNr>0) {
185 if(verbose>1) {printf("calling dft_fill_hdr_from_IFT\n"); fflush(stdout);}
186 dft_fill_hdr_from_IFT(data, &ift);
187 }
188 iftEmpty(&ift);
189
190 /* Try to read information from a single title line in PMOD files */
191 if(type==DFT_FORMAT_PMOD) {
192 if(fgets(line, longest, fp)==NULL) {
193 strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 101;}
194 if(verbose>1) {printf("calling dftGetPmodTitle\n"); fflush(stdout);}
195 dftGetPmodTitle(data, line);
196 // do not rewind!
197 }
198
199 /*
200 * Read DFT title lines, if they exist
201 */
202 i=0;
203 if(type==DFT_FORMAT_STANDARD) {
204 if(verbose>1) {printf("reading DFT title lines\n"); fflush(stdout);}
205 do {
206 if(fgets(line, longest, fp)==NULL) {
207 strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 102;}
208 lptr=line;
209 /* Check for comment line */
210 if(line[0]=='#') { /* Read comment only if there is space left */
211 strlcat(data->comments, line, _DFT_COMMENT_LEN);
212 continue;
213 }
214 cptr=strchr(line, '#'); if(cptr!=NULL) *cptr=(char)0;
215 /* Read first token, and check for empty lines as well */
216 cptr=strtok(lptr, " \t\n\r"); if(cptr==NULL) continue; else i++;
217 if(i==1) { /* VOI names */
218 for(j=0; j<voiNr; j++) {
219 cptr=strtok(NULL, " \t\n\r");
220 if(cptr==NULL) {strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 103;}
221 if(strlen(cptr)>1 || *cptr!='.') {
222 strncpy(data->voi[j].name, cptr, MAX_REGIONNAME_LEN);
223 data->voi[j].name[MAX_REGIONNAME_LEN]=(char)0;
224 strncpy(data->voi[j].voiname, cptr, MAX_REGIONSUBNAME_LEN);
225 data->voi[j].voiname[MAX_REGIONSUBNAME_LEN]=(char)0;
226 /* if name is long, then divide it into name subfields */
227 if(strlen(cptr)>MAX_REGIONSUBNAME_LEN) {
229 data->voi[j].hemisphere[MAX_REGIONSUBNAME_LEN]=(char)0;
230 if(strlen(cptr)>2*MAX_REGIONSUBNAME_LEN) {
231 strncpy(data->voi[j].place, cptr+2*MAX_REGIONSUBNAME_LEN, MAX_REGIONSUBNAME_LEN);
232 data->voi[j].place[MAX_REGIONSUBNAME_LEN]=(char)0;
233 }
234 }
235 } else {
236 int u, n; u=voiNr; n=1; while((u/=10)>=1) n++; if(n>6) n=6;
237 snprintf(data->voi[j].voiname, 7, "%0*d", n, j+1);
238 strcpy(data->voi[j].name, data->voi[j].voiname);
239 }
240 }
241 } else if(i==2) { /* 2nd VOI names (hemispheres) */
242 if(strcmp(cptr, ".")!=0) {
243 strlcpy(data->studynr, cptr, MAX_STUDYNR_LEN);
244 } else strcpy(data->studynr, "");
245 for(j=0; j<voiNr; j++) {
246 if((cptr=strtok(NULL, " \t\n\r"))==NULL) {
247 strcpy(dfterrmsg, "missing field on 2nd line");
248 free(line); fclose(fp); return 104;
249 }
250 if(strlen(cptr)>1 || *cptr!='.') {
251 strncpy(data->voi[j].hemisphere, cptr, MAX_REGIONSUBNAME_LEN);
252 data->voi[j].hemisphere[MAX_REGIONSUBNAME_LEN]=(char)0;
253 strcat(data->voi[j].name, " ");
254 strlcat(data->voi[j].name, data->voi[j].hemisphere, MAX_REGIONNAME_LEN);
255 } else {
256 strlcat(data->voi[j].name, " .", MAX_REGIONNAME_LEN+1);
257 }
258 }
259 /* check that there are no more contents */
260 if((cptr=strtok(NULL, " \t\n\r"))!=NULL) {
261 strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 105;}
262 } else if(i==3) { /* unit and VOI place (planes) */
263 /* first, copy the unit */
264 strlcpy(data->unit, cptr, 13); //data->unit[12]=(char)0;
265 /* then, copy the names */
266 int len, ii=0;
267 j=0;
268 while(j<voiNr) {
269 if((cptr=strtok(NULL, " \t\n\r"))==NULL) {
270 strcpy(dfterrmsg, "missing field on 3rd line");
271 free(line); fclose(fp); return 106;
272 }
273 len=strlen(cptr);
274 /* check if cunit consists of two parts */
275 if(ii==0 && cptr[0]=='(' && cptr[len-1]==')') {ii++; continue;}
276 /* copy the name */
277 if(len>1 || *cptr!='.') {
278 strlcpy(data->voi[j].place, cptr, MAX_REGIONSUBNAME_LEN+1);
279 //data->voi[j].place[MAX_REGIONSUBNAME_LEN]=(char)0;
280 strcat(data->voi[j].name, " ");
281 strlcat(data->voi[j].name, data->voi[j].place, MAX_REGIONNAME_LEN+1);
282 } else {
283 strlcat(data->voi[j].name, " .", MAX_REGIONNAME_LEN+1);
284 }
285 j++; ii++;
286 }
287 } else if(i==4) { /* time type, time unit, and VOI sizes */
288 /* time type */
289 if(strcasecmp(cptr, "Time")==0) data->timetype=DFT_TIME_MIDDLE;
290 else if(strcasecmp(cptr, "Times")==0) data->timetype=DFT_TIME_STARTEND;
291 else if(strcasecmp(cptr, "Start")==0) data->timetype=DFT_TIME_START;
292 else if(strcasecmp(cptr, "End")==0) data->timetype=DFT_TIME_END;
293 else if(strcasecmp(cptr, "Distance")==0) data->timetype=DFT_TIME_MIDDLE;
294 else if(strcasecmp(cptr, "Distances")==3) data->timetype=DFT_TIME_STARTEND;
295 else {strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 108;}
296 /* time unit */
297 if((cptr=strtok(NULL, " \t\n\r"))==NULL) {
298 strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 109;}
299 strcpy(temp, ""); j=sscanf(cptr, "(%127s)", temp);
300 j=strlen(temp)-1; if(j>=0 && temp[j]==')') temp[j]=(char)0;
301 data->timeunit=petTunitId(temp);
302 if(data->timeunit<0) {
303 strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 110;}
304 /* volumes */
305 for(j=0; j<voiNr; j++) {
306 if((cptr=strtok(NULL, " \t\n\r"))==NULL) {
307 strcpy(dfterrmsg, "wrong format"); free(line); fclose(fp); return 111;}
308 if(strlen(cptr)==1 && *cptr=='.') data->voi[j].size=0.0;
309 else data->voi[j].size=atof_dpi(cptr);
310 }
311 }
312 } while(i<4); // Standard DFT title lines are now read
313 }
314
315 /* Read data lines */
316 if(verbose>1) {printf("reading data lines\n"); fflush(stdout);}
317 i=0; while(fgets(line, longest, fp)!=NULL) {
318
319 /* Check for comment line */
320 if(line[0]=='#') { /* Read comment only if there is space left */
321 strlcat(data->comments, line, _DFT_COMMENT_LEN);
322 continue;
323 }
324 // remove end-of-line comment
325 cptr=strchr(line, '#'); if(cptr!=NULL) *cptr=(char)0;
326
327 /* Read first token, and check for empty lines as well */
328 char *nline; nline=strdup(line); lptr=nline;
329 cptr=strtok(lptr, " \t\n\r"); if(cptr==NULL) {free(nline); continue;}
330 if(i<frameNr) {
331 /* Read time(s) */
332 if(atof_with_check(cptr, &f)!=0) {
333 strcpy(dfterrmsg, "wrong format");
334 free(line); free(nline); fclose(fp); return 130;
335 }
336 if(data->timetype==DFT_TIME_STARTEND) {
337 data->x1[i]=f; cptr=strtok(NULL, " \t\n\r");
338 if(atof_with_check(cptr, &data->x2[i])!=0) {
339 strcpy(dfterrmsg, "wrong format");
340 free(line); free(nline); fclose(fp); return 131;
341 }
342 data->x[i]=0.5*(data->x1[i]+data->x2[i]);
343 } else data->x[i]=f;
344 /* curve data */
345 for(j=0; j<voiNr; j++) {
346 if((cptr=strtok(NULL, " \t\n\r"))==NULL) {
347 strcpy(dfterrmsg, "wrong format");
348 free(line); free(nline); fclose(fp); return 132;
349 }
350 if(strlen(cptr)==1 && *cptr=='.')
351 data->voi[j].y[i]=nan("");
352 else {
353 if(atof_with_check(cptr, &data->voi[j].y[i])!=0) {
354 strcpy(dfterrmsg, "wrong format");
355 free(line); free(nline); fclose(fp); return 133;
356 }
357 c=dec_nr(cptr);
359 }
360 }
361 }
362 free(nline);
363 i++;
364 }
365 if(i!=frameNr) {strcpy(dfterrmsg, "wrong format"); fclose(fp); free((char*)line); return 134;}
366
367 /* Close file */
368 fclose(fp); free((char*)line);
369
370 /* Set voiNr and frameNr, and type */
371 data->voiNr=voiNr; data->frameNr=frameNr;
372 if(type==DFT_FORMAT_IFT) {
374 } else if(type==DFT_FORMAT_PMOD) {
375 data->_type=type; // keeping PMOD format
376 // unless TAC names could not be read
377 for(i=0; i<data->voiNr; i++) if(strlen(data->voi[i].name)<1) {
378 data->_type=DFT_FORMAT_PLAIN; break;}
379 } else {
380 data->_type=type;
381 }
382
383 /* Set study number from file name, if necessary */
384 if(strlen(data->studynr)==0) studynr_from_fname(filename, data->studynr);
385
386 /* If weight 'voi' was read, move it to its own place */
387 for(i=0; i<data->voiNr; i++) if(!strcasecmp(data->voi[i].voiname, "weight")) {
388 data->isweight=1;
389 for(j=0; j<data->frameNr; j++) data->w[j]=data->voi[i].y[j];
390 /* Move the following VOIs one step backwards */
391 for(c=i+1; c<data->voiNr; c++) if(dftCopyvoi(data, c, c-1)) {
392 strcpy(dfterrmsg, "cannot read weight"); return 4;}
393 data->voiNr--;
394 break;
395 }
396 /* If no weights were found, set uniform weight */
397 if(!data->isweight) for(i=0; i<data->frameNr; i++) data->w[i]=1.0;
398
399 /* Calculate frame mid times, or frame start and end times;
400 this works only if time units are known */
401 dftFrametimes(data);
402
403 /* Make again the full ROI names from the separate sub parts */
404 for(i=0; i<data->voiNr; i++)
405 rnameCatenate(data->voi[i].name, MAX_REGIONNAME_LEN, data->voi[i].voiname,
406 data->voi[i].hemisphere, data->voi[i].place, ' ');
407
408
409 if(CSV_TEST>100) dftPrint(data);
410 return(0);
411}
412/*****************************************************************************/
413
414/*****************************************************************************/
424 char *fname
425) {
426 if(CSV_TEST>0) {printf("%s('%s')\n", __func__, fname); fflush(stdout);}
427
428 FILE *fp;
429 char tmp[256];
430 int c;
431
432
433 /* Open file */
434 fp=fopen(fname, "r"); if(fp==NULL) return DFT_FORMAT_UNKNOWN;
435
436 /* Binary data? */
437 while((c=fgetc(fp))!=EOF) {
438 if(isalnum(c) || isspace(c) || isgraph(c)) continue;
439 if(c>=160) continue;
440 if(CSV_TEST>1) {printf(" invalid character %d\n", c); fflush(stdout);}
441 fclose(fp); return DFT_FORMAT_UNKNOWN;
442 }
443 rewind(fp);
444
445 /* File with one title line without comment mark? */
446 while(fgets(tmp, 10, fp) != NULL) {if(strlen(tmp)) break;}
447 if(strncasecmp(tmp, "Time[", 5)==0) {fclose(fp); return DFT_FORMAT_PMOD;}
448 if(strncasecmp(tmp, "Start[", 6)==0) {fclose(fp); return DFT_FORMAT_PMOD;}
449 if(strcasestr(tmp, "Start\tEnd\t")!=NULL) {fclose(fp); return DFT_FORMAT_PMOD;}
450 rewind(fp);
451
452 /* Read the first line that is not empty or comment line */
453 while(fgets(tmp, 32, fp) != NULL) {
454 if(strlen(tmp)==0) continue;
455 if(tmp[0]=='#') continue;
456 if(strncmp(tmp, "//", 2)==0) continue;
457 break;
458 }
459 rewind(fp);
460
461 /* Check for identification strings */
462 if(strncasecmp(tmp, "DFT", 3)==0) {fclose(fp); return DFT_FORMAT_STANDARD;}
463 else if(strncasecmp(tmp, "FIT1", 3)==0) {fclose(fp); return DFT_FORMAT_FIT;}
464 else if(strncasecmp(tmp, "cpt", 3)==0) {fclose(fp); return DFT_FORMAT_NCI;}
465
466 /* Identify certain file name extensions */
467 if(fncasematch(fname, "*.idwc")==1 || fncasematch(fname, "*.idw")==1) {
468 fclose(fp); return DFT_FORMAT_IDWC;}
469 if(fncasematch(fname, "*.if")==1) {fclose(fp); return DFT_FORMAT_IF;}
470
471 fclose(fp);
472
473 /* Try to read as CSV */
474 CSV csv; csvInit(&csv);
475 if(csvRead(&csv, fname)==0) {
476 int format=DFT_FORMAT_UNKNOWN;
477 if(csv.separator==';') format=DFT_FORMAT_CSV_INT;
478 else if(csv.separator==',') format=DFT_FORMAT_CSV_UK;
479 else if(csv.separator=='\t') {
480 int i, commas=0, dots=0;
481 for(i=0; i<csv.nr; i++) {
482 if(strchr(csv.c[i].content, ',')!=NULL) commas++;
483 else if(strchr(csv.c[i].content, '.')!=NULL) dots++;
484 }
485 if(dots>commas) format=DFT_FORMAT_CSV_UK; else format=DFT_FORMAT_CSV_INT;
486 }
487 if(CSV_TEST>1) printf(" format=%d\n", format);
488 csvEmpty(&csv);
489 if(format!=DFT_FORMAT_UNKNOWN) return(format);
490 }
491
492 return DFT_FORMAT_PLAIN;
493}
494/*****************************************************************************/
495
496/*****************************************************************************/
503int dftType(FILE *fp)
504{
505 char tmp[256];
506 int c;
507
508 /* Find first line that is not empty or comment line */
509 rewind(fp);
510 while(fgets(tmp, 4, fp) != NULL) {if(strlen(tmp) && tmp[0]!='#') break;}
511 rewind(fp);
512
513 /* Check for identification strings */
514 if(strncasecmp(tmp, "DFT", 3)==0) return 1;
515 else if(strncasecmp(tmp, "FIT1", 3)==0) return 3;
516 else if(strncasecmp(tmp, "cpt", 3)==0) return 4;
517
518 /* Binary data? */
519 while((c=fgetc(fp))!=EOF)
520 if(!isalnum(c) && !isspace(c) && !isgraph(c) && c!=169) {
521 rewind(fp); return 0;
522 }
523
524 /* File with one title line without comment mark? */
525 rewind(fp);
526 while(fgets(tmp, 10, fp) != NULL) {if(strlen(tmp)) break;}
527 if(strncasecmp(tmp, "Time", 4)==0) {rewind(fp); return 5;}
528
529 rewind(fp); return 2;
530}
531/*****************************************************************************/
532
533/*****************************************************************************/
538void dftPrint(DFT *data)
539{
540 int voi, frame;
541
542 printf("Number of curves: %d Number of data points: %d\n",
543 data->voiNr, data->frameNr);
544 printf("Study: '%s' Unit: '%s'\n", data->studynr, data->unit);
545 printf("Time unit and type: %d %d\n", data->timeunit, data->timetype);
546 if(strlen(data->radiopharmaceutical))
547 printf("Radiopharmaceutical: %s\n", data->radiopharmaceutical);
548 if(strlen(data->isotope)) printf("Isotope: %s\n", data->isotope);
549 if(strlen(data->scanStartTime))
550 printf("Scan start time: %s\n", data->scanStartTime);
551 if(strlen(data->injectionTime))
552 printf("Injection time: %s\n", data->injectionTime);
554 printf("Corrected for physical decay: yes\n");
556 printf("Corrected for physical decay: no\n");
557 printf("_datasize = %d\n", data->_dataSize);
558 for(voi=0; voi<data->voiNr; voi++) {
559 if(strlen(data->voi[voi].name)>0)
560 printf("\nROI name: '%s' Size: %g\n",
561 data->voi[voi].name, data->voi[voi].size);
562 else
563 printf("\nROI name: '%s' '%s' '%s' Size: %g\n",
564 data->voi[voi].voiname, data->voi[voi].hemisphere, data->voi[voi].place,
565 data->voi[voi].size);
566 for(frame=0; frame<data->frameNr; frame++) {
567 printf("%03d: %11.3e %11.3e %11.3e %11.3e %11.3e %11.3e\n",
568 frame+1, data->x[frame], data->x1[frame], data->x2[frame],
569 data->voi[voi].y[frame], data->voi[voi].y2[frame],
570 data->voi[voi].y3[frame]);
571 }
572 }
573 printf("Comments:\n");
574 if(strlen(data->comments)>0) printf("%s\n", data->comments);
575 printf("Weights:\n");
576 if(data->isweight)
577 for(frame=0; frame<data->frameNr; frame++)
578 printf(" %03d %11.3e %11.3e %11.3e\n", frame+1,
579 data->x1[frame], data->x2[frame], data->w[frame]);
580 else
581 printf(" contains no weights.\n");
582 return;
583}
584/*****************************************************************************/
585
586/*****************************************************************************/
596 DFT *data,
599 char *filename
600) {
601 int i, j, n, sw, mfw, prec;
602 char tmp[1024], tmp2[128], is_stdout=0;
603 FILE *fp;
604
605
606 /* Check that there is some data to write */
607 if(data->voiNr<1 || data->frameNr<1) {strcpy(dfterrmsg, "no data"); return 1;}
608
609 /* If format if DFT_FORMAT_HTML or extension is *.HTM(L),
610 write in HTML format */
611 if(data->_type==DFT_FORMAT_HTML || fncasematch(filename, "*.htm")==1 || fncasematch(filename, "*.html")==1) {
612 return(dftWriteHTML(data, filename, 1));
613 }
614
615 /* Check if writing to stdout */
616 if(!strcasecmp(filename, "stdout")) is_stdout=1;
617
618 /* Set minimum field width and precision for concentrations */
619 mfw=11; if(DFT_NR_OF_DECIMALS>3) mfw+=DFT_NR_OF_DECIMALS-3;
620 prec=0; if(DFT_NR_OF_DECIMALS>prec) prec=DFT_NR_OF_DECIMALS;
621
622 /* Check if file exists; backup, if necessary */
623 if(!is_stdout) (void)backupExistingFile(filename, NULL, NULL);
624
625 /* Open output file */
626 if(is_stdout) fp=(FILE*)stdout;
627 else if((fp = fopen(filename, "w")) == NULL) {strcpy(dfterrmsg, "cannot open file"); return 2;}
628
629 /* Write title lines */
630 if(data->_type==DFT_FORMAT_STANDARD) {
631 /* 1st line with filetype identification string and region names */
632 n=fprintf(fp, "%s", DFT_VER);
633 if(n==0) {strcpy(dfterrmsg, "disk full"); if(!is_stdout) fclose(fp); return 3;}
634 for(i=0; i<data->voiNr; i++) fprintf(fp,"\t%s", data->voi[i].voiname);
635 if(data->isweight) fprintf(fp,"\t%s", "weight");
636 fprintf(fp, "\n");
637 /* 2nd line with study identification and 2nd name (hemisphere) */
638 if(strlen(data->studynr)) strlcpy(tmp, data->studynr, 11); else strcpy(tmp, ".");
639 fprintf(fp, "%s", tmp);
640 for(i=0; i<data->voiNr; i++) {
641 if(strlen(data->voi[i].hemisphere)) strcpy(tmp, data->voi[i].hemisphere);
642 else strcpy(tmp, ".");
643 fprintf(fp, "\t%s", tmp);
644 }
645 if(data->isweight) fprintf(fp,"\t%s", ".");
646 fprintf(fp, "\n");
647 /* 3rd line with unit and plane names */
648 if(strlen(data->unit)) strcpy(tmp, data->unit); else strcpy(tmp, ".");
649 fprintf(fp, "%s", tmp);
650 for(i=0; i<data->voiNr; i++) {
651 if(strlen(data->voi[i].place)) strcpy(tmp, data->voi[i].place);
652 else strcpy(tmp, ".");
653 fprintf(fp, "\t%s", tmp);
654 }
655 if(data->isweight) fprintf(fp,"\t%s", ".");
656 fprintf(fp, "\n");
657 /* 4th line with time type & unit and region volumes */
658 switch(data->timetype) {
659 case DFT_TIME_MIDDLE:
660 if(data->timeunit==TUNIT_MM || data->timeunit==TUNIT_UM || data->timeunit==TUNIT_CM)
661 strcpy(tmp, "Distance ");
662 else
663 strcpy(tmp, "Time ");
664 break;
665 case DFT_TIME_START: strcpy(tmp, "Start "); break;
666 case DFT_TIME_END: strcpy(tmp, "End "); break;
668 if(data->timeunit==TUNIT_MM || data->timeunit==TUNIT_UM || data->timeunit==TUNIT_CM)
669 strcpy(tmp, "Distances ");
670 else
671 strcpy(tmp, "Times ");
672 break;
673 }
674 snprintf(tmp2, 128, "(%s)", petTunit(data->timeunit)); strcat(tmp, tmp2);
675 fprintf(fp, "%s", tmp);
676 for(i=0; i<data->voiNr; i++) {
677 if(data->voi[i].size>=0.0) sprintf(tmp, "%.*e", prec, data->voi[i].size);
678 else strcpy(tmp, ".");
679 fprintf(fp, "\t%s", tmp);
680 }
681 if(data->isweight) fprintf(fp,"\t%s", ".");
682 fprintf(fp, "\n");
683 } else if(data->_type==DFT_FORMAT_PMOD) { // write PMOD title line
684 char *cptr, tunit[128], cunit[128]; // Set units to format accepted by PMOD
685 if(data->timeunit==TUNIT_SEC) strcpy(tunit, "seconds");
686 else if(data->timeunit==TUNIT_MIN) strcpy(tunit, "minutes");
687 else strcpy(tunit, petTunit(data->timeunit));
688 if(petCunitId(data->unit)==CUNIT_UNITLESS) strcpy(cunit, "1/1"); else strcpy(cunit, data->unit);
689 cptr=strstr(cunit, "mL"); if(cptr!=NULL) {*cptr='c'; cptr++; *cptr='c';}
690 if(data->timetype==DFT_TIME_STARTEND) fprintf(fp, "start[%s]\tend[%s]", tunit, cunit);
691 else fprintf(fp, "time[%s]", tunit);
692 for(i=0; i<data->voiNr; i++) {
693 /* write roi names, must not include spaces */
694 char *s=strdup(data->voi[i].name);
695 strReplaceChar(s, ' ', '-'); fprintf(fp, "\t%s", s); free(s);
696 /* write calibration unit when necessary */
697 if(i==0 && data->timetype!=DFT_TIME_STARTEND) fprintf(fp, "[%s]", cunit);
698 }
699 if(data->isweight) fprintf(fp,"\t%s", "weight");
700 fprintf(fp, "\n");
701 }
702
703 /* Make sure that only frame mid times are saved without titles */
704 if(data->_type==DFT_FORMAT_PLAIN && data->timetype!=DFT_TIME_MIDDLE) sw=0;
705 else sw=data->timetype;
706
707 /* Write data */
708 for(j=0; j<data->frameNr; j++) {
709 /* Time(s) */
710 switch(sw) {
711 case 0: fprintf(fp, "%.5f", data->x[j]); break;
712 case 1: fprintf(fp, "%.5f", data->x1[j]); break;
713 case 2: fprintf(fp, "%.5f", data->x2[j]); break;
714 case 3: fprintf(fp, "%.5f\t%.5f", data->x1[j], data->x2[j]); break;
715 }
716 /* y values */
717 for(i=0; i<data->voiNr; i++) {
718 if(!isnan(data->voi[i].y[j])) sprintf(tmp, "%.*e", prec, data->voi[i].y[j]);
719 else strcpy(tmp, ".");
720 fprintf(fp, "\t%s", tmp);
721 }
722 if(data->isweight) {
723 if(data->_type==DFT_FORMAT_STANDARD || data->_type==DFT_FORMAT_PMOD) {
724 if(!isnan(data->w[j])) sprintf(tmp, "%.*e", prec, data->w[j]);
725 else strcpy(tmp, ".");
726 fprintf(fp,"\t%s", tmp);
727 }
728 }
729 n=fprintf(fp, "\n");
730 if(n==0) {strcpy(dfterrmsg, "disk full"); if(!is_stdout) fclose(fp); return 3;}
731 }
732
733 /* Write comments */
734 if(1) { //data->_type!=DFT_FORMAT_PMOD) {
735 n=strnlen(data->comments, _DFT_COMMENT_LEN);
736 if(n) for(i=0; i<n; i++) {
737 if(i>0 && data->comments[i]=='#' && (data->comments[i-1]!='\n' && data->comments[i-1]!='\r'))
738 fputc('\n', fp);
739 fputc(data->comments[i], fp);
740 }
741 }
742
743 /* Close file */
744 if(!is_stdout) {fflush(fp); fclose(fp);}
745
746 return 0;
747}
748/*****************************************************************************/
749
750/*****************************************************************************/
759 DFT *dft,
761 char *fname,
763 int orientation
764) {
765 int ri, fi, is_stdout=0, ret;
766 char tmp[FILENAME_MAX];
767 FILE *fp;
768
769
770 /* Check input */
771 strcpy(dfterrmsg, "invalid input to dftWriteHTML()");
772 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return(1);
773 if(fname==NULL || strlen(fname)<1) return(1);
774 strcpy(dfterrmsg, "");
775 /* Check if writing to stdout */
776 if(!strcasecmp(fname, "stdout")) is_stdout=1;
777
778 /* Check if file exists; backup, if necessary */
779 if(!is_stdout && access(fname, 0) != -1) {
780 strcpy(tmp, fname); strcat(tmp, BACKUP_EXTENSION); rename(fname, tmp);}
781 strcpy(dfterrmsg, "cannot write file");
782
783 /* Open output file */
784 if(is_stdout) fp=(FILE*)stdout;
785 else if((fp=fopen(fname, "w"))==NULL) {strcpy(dfterrmsg, "cannot open file"); return(2);}
786
787 /* Write XHTML 1.1 doctype and head */
789 strcpy(dfterrmsg, "disk full"); if(!is_stdout) fclose(fp); return(3);
790 }
791
792 /* Start writing the body of the HTML file */
793 ret=fprintf(fp, "<body>\n");
794 if(ret==0) {strcpy(dfterrmsg, "disk full"); if(!is_stdout) fclose(fp); return(3);}
795
796 /* Start the div for table, and the table */
797 fprintf(fp, "\n<div id=\"table\">\n");
798 fprintf(fp, "<table>\n");
799
800 /* Write the title lines, if there are titles, into the head of the table */
801 if(dft->_type!=DFT_FORMAT_PLAIN) {
802 fprintf(fp, "<thead>\n");
803 if(orientation!=2) {
804 /* Empty cell and Region names */
805 fprintf(fp, "<tr><td> </td>\n");
806 for(ri=0; ri<dft->voiNr; ri++) {
807 char *senc=strEncodeForXML(dft->voi[ri].voiname);
808 if(senc==NULL) fprintf(fp, "<th>%s</th>\n", dft->voi[ri].voiname);
809 else {fprintf(fp, "<th>%s</th>\n", senc); free(senc);}
810 }
811 fprintf(fp, "</tr>\n");
812 /* Study number and Hemispheres */
813 fprintf(fp, "<tr><th>%s</th>\n", dft->studynr);
814 for(ri=0; ri<dft->voiNr; ri++) {
815 char *senc=strEncodeForXML(dft->voi[ri].hemisphere);
816 if(senc==NULL) fprintf(fp, "<th>%s</th>\n", dft->voi[ri].hemisphere);
817 else {fprintf(fp, "<th>%s</th>\n", senc); free(senc);}
818 }
819 fprintf(fp, "</tr>\n");
820 /* Unit and Places */
821 fprintf(fp, "<tr><th>%s</th>\n", dft->unit);
822 for(ri=0; ri<dft->voiNr; ri++) {
823 char *senc=strEncodeForXML(dft->voi[ri].place);
824 if(senc==NULL) fprintf(fp, "<th>%s</th>\n", dft->voi[ri].place);
825 else {fprintf(fp, "<th>%s</th>\n", senc); free(senc);}
826 }
827 fprintf(fp, "</tr>\n");
828 /* Time unit and Volumes */
829 fprintf(fp, "<tr><th>%s</th>\n", petTunit(dft->timeunit));
830 for(ri=0; ri<dft->voiNr; ri++)
831 fprintf(fp, "<th>%g</th>\n", dft->voi[ri].size);
832 fprintf(fp, "</tr>\n");
833 } else if(orientation==2) {
834 /* Study number and Unit */
835 fprintf(fp, "<tr><th>%s</th>\n", dft->studynr);
836 fprintf(fp, "<th>%s</th></tr>\n", dft->unit);
837 }
838 /* End the head of table */
839 fprintf(fp, "</thead>\n");
840 }
841
842 /* Write the DFT data into the body of the table */
843 fprintf(fp, "<tbody>\n");
844
845 /* If transposed, write titles */
846 if(orientation==2) {
847 fprintf(fp, "<tr><th>Region</th><th>Hemisphere</th><th>Plane</th>\n");
848 fprintf(fp, "<th>Volume</th></tr>\n");
849 }
850 if(orientation!=2) { /* Not transposed */
851 for(fi=0; fi<dft->frameNr; fi++) {
852 if(fi%2) strcpy(tmp, "evenframe"); else strcpy(tmp, "oddframe");
853 /* Time */
854 fprintf(fp, "<tr class=\"%s\"><th>%g</th>\n", tmp, dft->x[fi]);
855 /* Values */
856 for(ri=0; ri<dft->voiNr; ri++)
857 fprintf(fp, "<th>%g</th>", dft->voi[ri].y[fi]);
858 fprintf(fp, "</tr>\n");
859 }
860 } else { /* transposed */
861 for(ri=0; ri<dft->voiNr; ri++) {
862 if(ri%2) strcpy(tmp, "evenframe"); else strcpy(tmp, "oddframe");
863 fprintf(fp, "<tr class=\"%s\">", tmp);
864 /* Region names */
865 char *senc;
866 senc=strEncodeForXML(dft->voi[ri].voiname);
867 if(senc==NULL) fprintf(fp, "<th>%s</th>", dft->voi[ri].voiname);
868 else {fprintf(fp, "<th>%s</th>", senc); free(senc);}
869 senc=strEncodeForXML(dft->voi[ri].hemisphere);
870 if(senc==NULL) fprintf(fp, "<th>%s</th>", dft->voi[ri].hemisphere);
871 else {fprintf(fp, "<th>%s</th>", senc); free(senc);}
872 senc=strEncodeForXML(dft->voi[ri].place);
873 if(senc==NULL) fprintf(fp, "<th>%s</th>\n", dft->voi[ri].place);
874 else {fprintf(fp, "<th>%s</th>\n", senc); free(senc);}
875 /* Region volume */
876 fprintf(fp, "<td>%g</td>\n", dft->voi[ri].size);
877 /* Values */
878 for(fi=0; fi<dft->frameNr; fi++) {
879 fprintf(fp, "<td>%g</td>", dft->voi[ri].y[fi]);
880 }
881 fprintf(fp, "</tr>\n");
882 }
883 }
884 /* End the table body and table */
885 fprintf(fp, "</tbody></table>\n");
886
887 /* Stop writing the body of the HTML file, and end the file */
888 fprintf(fp, "</div>\n");
889 ret=fprintf(fp, "</body></html>\n\n");
890 if(ret==0) {
891 strcpy(dfterrmsg, "disk full");
892 if(!is_stdout) fclose(fp);
893 return(3);
894 }
895
896 /* Close file */
897 if(!is_stdout) {fflush(fp); fclose(fp);}
898 strcpy(dfterrmsg, "");
899
900 return(0);
901}
902/*****************************************************************************/
903
904/*****************************************************************************/
909 FILE *fp
910) {
911 int n;
912 if(fp==NULL) return(1);
913 n=fprintf(fp, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" ");
914 n+=fprintf(fp, "\"https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n");
915 if(n<20) return(2);
916 n=fprintf(fp, "<html xmlns=\"https://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n\n");
917 if(n<20) return(2);
918 return(0);
919}
920/*****************************************************************************/
921
922/*****************************************************************************/
928 FILE *fp,
930 char *author_name
931) {
932 int n;
933 if(fp==NULL) return(1);
934
935 n=fprintf(fp, "<head>\n"); if(n<6) return(2);
936 fprintf(fp, " <title>PET data</title>\n");
937 fprintf(fp, " <meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\" />\n");
938 fprintf(fp, " <meta http-equiv=\"content-language\" content=\"en-gb\" />\n");
939 fprintf(fp, " <meta name=\"author\" content=\"%s\" />\n", author_name);
940 fprintf(fp, " <meta name=\"ProgId\" content=\"Excel.Sheet\" />\n");
941 fprintf(fp, " <link rel=\"icon\" href=\"https://www.turkupetcentre.net/favicon.ico\" type=\"image/x-icon\" />\n");
942 fprintf(fp, " <link rel=\"shortcut icon\" href=\"https://www.turkupetcentre.net/favicon.ico\" type=\"image/x-icon\" />\n");
943 /* write local CSS with basic settings in case that external CSS is not available */
944 fprintf(fp, " <style type=\"text/css\">\n");
945 fprintf(fp, " thead {background-color:#999999; color:black;}\n");
946 fprintf(fp, " table {text-align:left; width:100%%; border-collapse:collapse; empty-cells:show;}\n");
947 fprintf(fp, " td {border:1px solid black;}\n");
948 fprintf(fp, " .oddframe {background-color:#FFFFFF; color:black;}\n");
949 fprintf(fp, " .evenframe {background-color:#CCCCCC; color:black;}\n");
950 fprintf(fp, " #regcontainer ul {margin-left:0; padding-left:0;}\n");
951 fprintf(fp, " #regcontainer ul li {display:inline; list-style-type:none;}\n");
952 fprintf(fp, " #regcontainer a {padding:2px 4px;}\n");
953 fprintf(fp, " <!--table\n");
954 fprintf(fp, " {mso-displayed-decimal-separator:\"\\.\";\n");
955 fprintf(fp, " mso-displayed-thousand-separator:\" \";}\n");
956 fprintf(fp, " -->\n");
957 fprintf(fp, " </style>\n");
958 /* load external CSS with more fancy settings */
959 fprintf(fp, " <link rel=\"stylesheet\" type=\"text/css\" ");
960 fprintf(fp, "href=\"https://www.turkupetcentre.net/dft.css\" />\n");
961 fprintf(fp, "</head>\n");
962 if(n<7) return(2);
963 return(0);
964}
965/*****************************************************************************/
966
967/*****************************************************************************/
973 DFT *dft,
975 IFT *ift
976) {
977 int ki, ri, ok_nr=0, ret;
978 char keystr[256], *cptr;
979
980 //printf("dft_fill_hdr_from_IFT()\n");
981
982 /* Check for study number */
983 strcpy(keystr, "studynr"); ki=iftGet(ift, keystr, 0);
984 if(ki==-1) {strcpy(keystr, "study number"); ki=iftGet(ift, keystr, 0);}
985 if(ki==-1) {strcpy(keystr, "study_number"); ki=iftGet(ift, keystr, 0);}
986 if(ki>=0) {
987 strlcpy(dft->studynr, ift->item[ki].value, MAX_STUDYNR_LEN);
988 ok_nr++;
989 }
990
991 /* Check for time unit */
992 strcpy(keystr, "timeunit"); ki=iftGet(ift, keystr, 0);
993 if(ki==-1) {strcpy(keystr, "time unit"); ki=iftGet(ift, keystr, 0);}
994 if(ki==-1) {strcpy(keystr, "time_unit"); ki=iftGet(ift, keystr, 0);}
995 if(ki==-1) {strcpy(keystr, "Time units"); ki=iftGet(ift, keystr, 0);}
996 if(ki>=0) {
997 ret=petTunitId(ift->item[ki].value);
998 if(ret>=0 && ret!=TUNIT_UNKNOWN) {dft->timeunit=ret; ok_nr++;}
999 }
1000
1001 /* Check for sample unit */
1002 strcpy(keystr, "unit"); ki=iftGet(ift, keystr, 0);
1003 if(ki==-1) {strcpy(keystr, "Activity units"); ki=iftGet(ift, keystr, 0);}
1004 if(ki>=0) {
1005 strncpy(dft->unit, ift->item[ki].value, 12); dft->unit[12]=(char)0;
1006 ok_nr++;
1007 }
1008
1009 /* Check for region names */
1010 ri=0;
1011 do {
1012 strcpy(keystr, "voiname"); ki=iftGetNth(ift, keystr, ri+1, 0);
1013 if(ki>=0) {
1014 strncpy(dft->voi[ri].name, ift->item[ki].value, MAX_REGIONNAME_LEN);
1015 dft->voi[ri].name[MAX_REGIONNAME_LEN]=(char)0;
1016 rnameSplit(ift->item[ki].value, dft->voi[ri].voiname,
1017 dft->voi[ri].hemisphere, dft->voi[ri].place, MAX_REGIONSUBNAME_LEN);
1018 }
1019 ri++; ok_nr++;
1020 } while(ki>=0 && ri<dft->_voidataNr);
1021
1022 /* Check for region volumes */
1023 strcpy(keystr, "sizes"); ki=iftGet(ift, keystr, 0);
1024 if(ki==-1) {strcpy(keystr, "volumes"); ki=iftGet(ift, keystr, 0);}
1025 if(ki>=0 && strlen(ift->item[ki].value)) {
1026 ri=0; cptr=strtok(ift->item[ki].value, " ;\t");
1027 while(cptr!=NULL && ri<dft->_voidataNr) {
1028 if(strcmp(cptr, ".")==0) {ri++; continue;}
1029 dft->voi[ri++].size=atof_dpi(cptr);
1030 cptr=strtok(NULL, " ;\t");
1031 }
1032 ok_nr++;
1033 }
1034
1035 /* Check for the name of radiopharmaceutical */
1036 strcpy(keystr, "radiopharmaceutical"); ki=iftGet(ift, keystr, 0);
1037 if(ki>=0 && strlen(ift->item[ki].value)) {
1038 strncpy(dft->radiopharmaceutical, ift->item[ki].value, 31);
1039 dft->radiopharmaceutical[31]=(char)0;
1040 ok_nr++;
1041 }
1042
1043 /* Check for isotope name */
1044 strcpy(keystr, "isotope"); ki=iftGet(ift, keystr, 0);
1045 if(ki>=0 && strlen(ift->item[ki].value)) {
1046 strncpy(dft->isotope, ift->item[ki].value, 6); dft->isotope[6]=(char)0;
1047 ok_nr++;
1048 }
1049
1050 /* Check if there is anything about correction for physical decay */
1051 strcpy(keystr, "decay_correction"); ki=iftGet(ift, keystr, 0);
1052 if(ki==-1) {strcpy(keystr, "decay correction"); ki=iftGet(ift, keystr, 0);}
1053 if(ki>=0 && strlen(ift->item[ki].value)) {
1054 if(strncasecmp(ift->item[ki].value, "Yes", 1)==0) {
1055 dft->decayCorrected=DFT_DECAY_CORRECTED; ok_nr++;
1056 } else if(strncasecmp(ift->item[ki].value, "No", 1)==0) {
1058 }
1059 }
1060
1061 /* Check for injection time */
1062 strcpy(keystr, "injection time"); ki=iftGet(ift, keystr, 0);
1063 if(ki==-1) {strcpy(keystr, "injection_time"); ki=iftGet(ift, keystr, 0);}
1064 if(ki>=0 && strlen(ift->item[ki].value)) {
1065 /* check if time is in correct format; otherwise try to correct it */
1066 if(ift->item[ki].value[4]=='-' && ift->item[ki].value[7]=='-' &&
1067 ift->item[ki].value[13]==':' && ift->item[ki].value[16]==':') {
1068 strncpy(dft->injectionTime, ift->item[ki].value, 19);
1069 dft->injectionTime[19]=(char)0; ok_nr++;
1070 } else if(ift->item[ki].value[2]=='.' && ift->item[ki].value[5]=='.' &&
1071 ift->item[ki].value[13]==':' && ift->item[ki].value[16]==':') {
1072 sprintf(dft->injectionTime, "%4.4s-%2.2s-%2.2s %8.8s",
1073 ift->item[ki].value+6, ift->item[ki].value+3, ift->item[ki].value,
1074 ift->item[ki].value+11);
1075 ok_nr++;
1076 }
1077 }
1078
1079 /* Check for scan start time */
1080 strcpy(keystr, "scan start time"); ki=iftGet(ift, keystr, 0);
1081 if(ki==-1) {strcpy(keystr, "scan_start_time"); ki=iftGet(ift, keystr, 0);}
1082 if(ki==-1) {strcpy(keystr, "scan_start"); ki=iftGet(ift, keystr, 0);}
1083 if(ki==-1) {strcpy(keystr, "scan start"); ki=iftGet(ift, keystr, 0);}
1084 if(ki>=0 && strlen(ift->item[ki].value)) {
1085 /* check if time is in correct format; otherwise try to correct it */
1086 if(ift->item[ki].value[4]=='-' && ift->item[ki].value[7]=='-' &&
1087 ift->item[ki].value[13]==':' && ift->item[ki].value[16]==':') {
1088 strncpy(dft->scanStartTime, ift->item[ki].value, 19);
1089 dft->scanStartTime[19]=(char)0; ok_nr++;
1090 } else if(ift->item[ki].value[2]=='.' && ift->item[ki].value[5]=='.' &&
1091 ift->item[ki].value[13]==':' && ift->item[ki].value[16]==':') {
1092 sprintf(dft->scanStartTime, "%4.4s-%2.2s-%2.2s %8.8s",
1093 ift->item[ki].value+6, ift->item[ki].value+3, ift->item[ki].value,
1094 ift->item[ki].value+11);
1095 ok_nr++;
1096 }
1097 }
1098
1099 return(ok_nr);
1100}
1101/*****************************************************************************/
1102
1103/*****************************************************************************/
1112 DFT *dft,
1114 char *title_line
1115) {
1116 //printf("dftGetPmodTitle()\n");
1117 //printf(" '%s'\n", title_line);
1118 //if(dft==NULL) printf(" dft=NULL\n");
1119
1120 int ti=0, ri, ret, tabs=0, timetype=DFT_TIME_MIDDLE;
1121 char *cptr, *cptr2, rname[MAX_REGIONNAME_LEN+1];
1122 char unit[MAX_UNITS_LEN+1], separs[8];
1123
1124 /* Check the input */
1125 if(strlen(title_line)<1) return 1;
1126
1127 /* Count the nr of tabs in title line */
1128 cptr=title_line; while(*cptr) {if(*cptr=='\t') tabs++; cptr++;}
1129 /* If tabs found, then do not use space as field separator */
1130 if(tabs>0) strcpy(separs, "\t\n\r"); else strcpy(separs, " \t\n\r");
1131
1132 /* Make a copy of title line */
1133 char ntl[1+strlen(title_line)], *tl;
1134 strcpy(ntl, title_line); tl=ntl;
1135 cptr=strtok(tl, separs); if(cptr==NULL) return 2;
1136 ti=ri=0;
1137 while(cptr!=NULL) {
1138 if(ti==0) {
1139 if(strlen(cptr)>6 && strncasecmp(cptr, "Time[", 5)==0) {
1140 strncpy(unit, cptr+5, MAX_UNITS_LEN); unit[MAX_UNITS_LEN]=(char)0;
1141 cptr2=strchr(unit, ']'); if(cptr2!=NULL) *cptr2=(char)0;
1142 if(dft!=NULL) dft->timeunit=petTunitId(unit);
1143 timetype=DFT_TIME_MIDDLE;
1144 } else if(strlen(cptr)>6 && strncasecmp(cptr, "start[", 6)==0) {
1145 strncpy(unit, cptr+6, MAX_UNITS_LEN); unit[MAX_UNITS_LEN]=(char)0;
1146 cptr2=strchr(unit, ']'); if(cptr2!=NULL) *cptr2=(char)0;
1147 if(dft!=NULL) dft->timeunit=petTunitId(unit);
1148 timetype=DFT_TIME_STARTEND;
1149 }
1150 } else if(ti==1 && timetype==DFT_TIME_STARTEND) {
1151 if(strlen(cptr)>5 && strncasecmp(cptr, "end[", 4)==0) {
1152 strncpy(unit, cptr+4, MAX_UNITS_LEN); unit[MAX_UNITS_LEN]=(char)0;
1153 cptr2=strchr(unit, ']'); if(cptr2!=NULL) *cptr2=(char)0;
1154 ret=petCunitId(unit);
1155 if(ret!=CUNIT_UNKNOWN && dft!=NULL) strcpy(dft->unit, petCunit(ret));
1156 }
1157 } else {
1158 // get tac name
1159 strncpy(rname, cptr, MAX_REGIONNAME_LEN);
1160 rname[MAX_REGIONNAME_LEN]=(char)0;
1161 cptr2=strchr(rname, '['); if(cptr2!=NULL) *cptr2=(char)0;
1162 while((cptr2=strchr(rname, '_'))!=NULL) *cptr2=' ';
1163 if(dft!=NULL && ri<dft->_voidataNr) strcpy(dft->voi[ri].name, rname);
1164 // get unit
1165 cptr2=strchr(cptr, '[');
1166 if(cptr2!=NULL) {
1167 strncpy(unit, cptr2+1, MAX_UNITS_LEN); unit[MAX_UNITS_LEN]=(char)0;
1168 cptr2=strchr(unit, ']'); if(cptr2!=NULL) *cptr2=(char)0;
1169 ret=petCunitId(unit);
1170 if(ret!=CUNIT_UNKNOWN && dft!=NULL) strcpy(dft->unit, petCunit(ret));
1171 }
1172 ri++;
1173 }
1174 ti++;
1175 cptr=strtok(NULL, separs);
1176 }
1177 if(dft==NULL) {
1178 return(ri);
1179 }
1180
1181 dft->timetype=timetype;
1182
1183 //for(int i=0; i<dft->_voidataNr; i++) printf(" '%s'\n", dft->voi[i].name);
1184
1185 /* Split ROI names */
1186 ti=ri;
1187 for(ri=0; ri<ti; ri++)
1188 rnameSplit(dft->voi[ri].name, dft->voi[ri].voiname,
1189 dft->voi[ri].hemisphere, dft->voi[ri].place, MAX_REGIONSUBNAME_LEN);
1190
1191 return(0);
1192}
1193/*****************************************************************************/
1194
1195/*****************************************************************************/
1196
int backupExistingFile(char *filename, char *backup_ext, char *status)
Definition backup.c:14
int CSV_TEST
Definition csv.c:6
void csvInit(CSV *csv)
Definition csv.c:13
void csvEmpty(CSV *csv)
Definition csv.c:24
int csv2dft(CSV *csv, DFT *dft)
Definition csv.c:200
int csvRead(CSV *csv, char *fname)
Definition csv.c:42
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 dec_nr(char *str)
Definition decpoint.c:81
char dfterrmsg[64]
Definition dft.c:6
void dftSetComments(DFT *dft)
Definition dft.c:1326
int dftCopyvoi(DFT *data, int from, int to)
Definition dft.c:472
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
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int DFT_NR_OF_DECIMALS
Definition dftio.c:13
int dftFormat(char *fname)
Definition dftio.c:422
int dft_fill_hdr_from_IFT(DFT *dft, IFT *ift)
Definition dftio.c:971
void dftPrint(DFT *data)
Definition dftio.c:538
int dftType(FILE *fp)
Definition dftio.c:503
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
int dftWriteXHTML11_doctype(FILE *fp)
Definition dftio.c:908
int dftWriteXHTML11_head(FILE *fp, char *author_name)
Definition dftio.c:926
int dftWriteHTML(DFT *dft, char *fname, int orientation)
Definition dftio.c:757
int dftGetPmodTitle(DFT *dft, char *title_line)
Definition dftio.c:1109
int fncasematch(const char *fname, const char *key)
Definition filename.c:100
int idwcRead(char *filename, DFT *dft)
Definition idwc.c:77
int ifRead(char *filename, DFT *dft)
Definition if.c:78
void iftEmpty(IFT *ift)
Definition ift.c:60
void iftInit(IFT *ift)
Definition ift.c:45
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
Definition iftfile.c:24
int iftGet(IFT *ift, char *key, int verbose)
Definition iftsrch.c:15
int iftGetNth(IFT *ift, char *key, int n, int verbose)
Definition iftsrch.c:48
Header file for libtpccurveio.
#define DFT_DECAY_NOTCORRECTED
#define DFT_FORMAT_PMOD
#define DFT_FORMAT_CSV_INT
int roikbqRead(char *fname, DFT *dft)
Definition ncifile.c:95
#define DFT_FORMAT_CSV_UK
#define DFT_TIME_MIDDLE
#define DFT_FORMAT_STANDARD
#define DFT_DECAY_CORRECTED
#define DFT_FORMAT_IF
#define DFT_TIME_END
#define DFT_FORMAT_FIT
#define BACKUP_EXTENSION
#define DFT_FORMAT_IDWC
#define DFT_FORMAT_HTML
#define DFT_TIME_START
#define DFT_FORMAT_NCI
#define DFT_FORMAT_PLAIN
#define DFT_TIME_STARTEND
#define DFT_FORMAT_UNKNOWN
#define DFT_FORMAT_IFT
int rnameCatenate(char *rname, int max_rname_len, char *name1, char *name2, char *name3, char space)
Definition rname.c:189
int petCunitId(const char *unit)
Definition petunits.c:74
char * petCunit(int cunit)
Definition petunits.c:211
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
char * strEncodeForXML(const char *s)
Definition strext.c:364
void strReplaceChar(char *str, char c1, char c2)
Definition strext.c:159
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
char * strcasestr(const char *haystack, const char *needle)
Definition strext.c:279
int studynr_from_fname(char *fname, char *studynr)
Definition studynr.c:119
size_t strlcat(char *dst, const char *src, size_t dstsize)
Definition strext.c:206
int petTunitId(const char *timeunit)
Definition petunits.c:187
#define MAX_UNITS_LEN
Definition libtpcmisc.h:95
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
char * content
char separator
CSV_item * c
char scanStartTime[20]
char decayCorrected
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
char injectionTime[20]
int frameNr
int isweight
char isotope[8]
double * x
char unit[MAX_UNITS_LEN+1]
char radiopharmaceutical[32]
int keyNr
Definition libtpcmisc.h:270
IFT_KEY_AND_VALUE * item
Definition libtpcmisc.h:279
double size
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
double * y3
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]