TPCCLIB
Loading...
Searching...
No Matches
result.c
Go to the documentation of this file.
1
6char reserrmsg[64];
7/*****************************************************************************/
8#include "libtpccurveio.h"
9#include <unistd.h>
10/*****************************************************************************/
11/* Local functions */
13int resQSortComp(const void *f1, const void *f2);
14int resQSortName(const void *voi1, const void *voi2);
16/*****************************************************************************/
17
18/*****************************************************************************/
24 RES *res
25) {
26 if(res==NULL) return;
27 if(res->_voidataNr>0) {
28 free((char*)(res->voi));
29 res->_voidataNr=0;
30 }
31 res->voiNr=0;
32 res->parNr=0;
33 res->studynr[0]=(char)0;
34 for(int pi=0; pi<MAX_RESPARAMS; pi++) {
35 strcpy(res->parname[pi], ""); strcpy(res->parunit[pi], "");}
36 res->titleline[0]=res->unitline[0]=(char)0;
37 res->program[0]=(char)0; res->refroi[0]=(char)0; res->datarange[0]=(char)0;
38 res->datanr=0; res->fitmethod[0]=(char)0;
39 res->datafile[0]=res->reffile[0]=(char)0;
40 res->plasmafile[0]=res->plasmafile2[0]=res->bloodfile[0]=(char)0;
41 res->density=res->lc=res->concentration=res->beta=0.0;
42 res->Vb=-1.0;
43 res->fA=-1.0;
44 res->E=-1.0;
45}
46/*****************************************************************************/
47
48/*****************************************************************************/
54 RES *res
55) {
56 if(res==NULL) return;
57 memset(res, 0, sizeof(RES));
58 res->_voidataNr=0; res->voiNr=0; res->parNr=0;
59 //res->Vb=-1.0;
60 //res->fA=-1.0;
61 //res->E=-1.0;
62 resEmpty(res);
63}
64/*****************************************************************************/
65
66/*****************************************************************************/
72 RES *res,
74 int voiNr
75) {
76 int ri, pi;
77
78 /* Check that there is something to do */
79 if(res==NULL || voiNr<1) return(1);
80
81 /* Clear previous data, but only if necessary */
82 if(res->_voidataNr>0 || res->voiNr>0) resEmpty(res);
83
84 /* Allocate memory for regional curves */
85 res->voi=(ResVOI*)calloc(voiNr, sizeof(ResVOI));
86 if(res->voi==NULL) return(2);
87 res->_voidataNr=voiNr;
88
89 /* Set SDs and CLs to NA */
90 for(ri=0; ri<res->_voidataNr; ri++) for(pi=0; pi<MAX_RESPARAMS; pi++)
91 res->voi[ri].sd[pi]=res->voi[ri].cl1[pi]=res->voi[ri].cl2[pi]=nan("");
92
93 return(0);
94}
95/*****************************************************************************/
96
97/*****************************************************************************/
109 RES *res
110) {
111 int i, len, n;
112 char *cptr, tmp[1024], *lptr;
113
114 if(RESULT_TEST>0) printf("resFixParnames(*res)\n");
115 if(res==NULL) return;
116 if(res->parNr<1) return;
118
119 /* If new string lists are filled, then copy those to old representation */
120 for(i=n=0; i<res->parNr; i++) {
121 len=strlen(res->parname[i]); if(len<1) continue;
122 if(strcmp(res->parname[i], ".")==0) continue;
123 n++;
124 }
125 if(n>0) { // copy names and units
126 strcpy(res->titleline, "");
127 for(i=0; i<res->parNr; i++) {
128 if(1023<(1+strlen(res->titleline)+strlen(res->parname[i]))) break;
129 if(i>0) strcat(res->titleline, " ");
130 len=strlen(res->parname[i]);
131 if(len<1) strcat(res->titleline, ".");
132 else strcat(res->titleline, res->parname[i]);
133 }
134 strcpy(res->unitline, "");
135 for(i=0; i<res->parNr; i++) {
136 if(1023<(1+strlen(res->unitline)+strlen(res->parunit[i]))) break;
137 if(i>0) strcat(res->unitline, " ");
138 len=strlen(res->parunit[i]);
139 if(len<1) strcat(res->unitline, ".");
140 else strcat(res->unitline, res->parunit[i]);
141 }
142 if(RESULT_TEST>1) {
143 printf("Parameter names and units:\n");
144 for(i=0; i<res->parNr; i++)
145 printf(" %d: '%s' '%s'\n", i+1, res->parname[i], res->parunit[i]);
146 printf("Created titleline: %s\n", res->titleline);
147 printf("Created unitline: %s\n", res->unitline);
148 }
149 return;
150 }
151
152 /* If new string lists are not filled, then get them from deprecated strings */
153 for(i=0; i<res->parNr; i++) {
154 strcpy(res->parname[i], "");
155 strcpy(res->parunit[i], "");
156 }
157 strcpy(tmp, res->titleline); lptr=tmp; cptr=strtok(lptr, " \t\n\r");
158 i=0; while(cptr!=NULL && i<res->parNr) {
159 if(strcmp(cptr, ".")==0) {i++; continue;}
160 strncpy(res->parname[i], cptr, MAX_RESPARNAME_LEN);
161 res->parname[i][MAX_RESPARNAME_LEN]=(char)0;
162 cptr=strtok(NULL, " \t\n\r"); i++;
163 }
164 strcpy(tmp, res->unitline); lptr=tmp; cptr=strtok(lptr, " \t\n\r");
165 i=0; while(cptr!=NULL && i<res->parNr) {
166 if(strcmp(cptr, ".")==0) {i++; continue;}
167 strncpy(res->parunit[i], cptr, MAX_RESPARNAME_LEN);
168 res->parunit[i][MAX_RESPARNAME_LEN]=(char)0;
169 cptr=strtok(NULL, " \t\n\r"); i++;
170 }
171 if(RESULT_TEST>1) {
172 printf("Original titleline: %s\n", res->titleline);
173 printf("Original unitline: %s\n", res->unitline);
174 printf("Resolved parameter names and units:\n");
175 for(i=0; i<res->parNr; i++)
176 printf(" %d: '%s' '%s'\n", i+1, res->parname[i], res->parunit[i]);
177 }
178 return;
179}
180/*****************************************************************************/
181
182/*****************************************************************************/
188 RES *res
189) {
190 resWrite(res, "stdout", 0);
191}
192/*****************************************************************************/
193
194/*****************************************************************************/
201 char *filename,
203 RES *res,
205 int verbose
206) {
207 FILE *fp;
208 char *cptr, line[1024], *lptr, tmp[1024];
209 int i, n;
210 fpos_t file_loc;
211
212
213 if(verbose>0) printf("resRead(%s, *res);\n", filename);
214 if(res==NULL) return(1);
215 /* Empty data */
216 resEmpty(res);
217 res->isweight=-1; /* unknown */
218
219 /* Open file; note that 'b' is required for fgetpos() and fsetpos() to work
220 correctly */
221 fp=fopen(filename, "rb");
222 if(fp==NULL) {strcpy(reserrmsg, "cannot open file"); return(1);}
223
224 /*
225 * Read data, each result set separately, saving only the first one
226 */
227 strcpy(reserrmsg, "wrong format");
228
229 /* Read program name */
230 if(verbose>1) printf("reading program name\n");
231 while(fgets(line, 1024, fp)!=NULL) {
232 /* Ignore empty and comment lines */
233 if(strlen(line)<4 || line[0]=='#') continue; else break;
234 }
235 /* Check for string (c) or (C) */
236 if(strstr(line, "(c)") || strstr(line, "(C)")) {
237 i=strlen(line)-1; while(i>0 && isspace(line[i])) i--; line[i+1]=(char)0;
238 if(i<4) {fclose(fp); return(2);}
239 strcpy(res->program, line);
240 } else {fclose(fp); return(2);}
241
242 /* Read calculation date and time */
243 if(verbose>1) printf("reading date and time\n");
244 while(fgets(line, 1024, fp)!=NULL) if(strlen(line)>2 && line[0]!='#') break;
245 if(strncasecmp(line, "Date:", 5)) {fclose(fp); return(4);}
246 cptr=&line[5]; while(isblank(cptr[0])) cptr++;
247 if(cptr!=NULL) {
248 if(verbose>3) printf("date_str := %s", cptr);
249 struct tm st;
250 if(get_datetime(cptr, &st, verbose-3)==0) res->time=timegm(&st);
251 else if(get_date(cptr, &st)==0) res->time=timegm(&st);
252 else res->time=(time_t)0;
253 }
254
255 /* Read studynr, datafiles, ref region, data range, etc */
256 if(verbose>1) printf("reading headers\n");
257 do {
258 /* Omit comment and too short lines */
259 while((lptr=fgets(line, 1024, fp))!=NULL) {
260 if(strlen(line)>2 && line[0]!='#') break;
261 if(lptr!=NULL && verbose>6)
262 printf("omitted line[%d] := %s", (int)strlen(line), line);
263 }
264 if(lptr==NULL) break;
265 strcpy(tmp, line);
266 n=0; if(verbose>3) printf("line[%d] := %s", (int)strlen(line), line);
267 if(strncasecmp(line, "Study", 5)==0) {
268 lptr=&tmp[6]; cptr=strtok(lptr, " \t\n\r"); n=1;
269 if(cptr!=NULL && strlen(cptr)<1024) {
270 strlcpy(res->studynr, cptr, MAX_STUDYNR_LEN+1);
271 }
272 } else if(strncasecmp(line, "Data file", 9)==0) {
273 lptr=&tmp[10]; cptr=strtok(lptr, " \t\n\r"); n=1;
274 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->datafile, cptr);
275 } else if(strncasecmp(line, "ROI file", 8)==0) {
276 lptr=&tmp[9]; cptr=strtok(lptr, " \t\n\r"); n=1;
277 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->datafile, cptr);
278 } else if(strncasecmp(line, "Plasma file", 11)==0) {
279 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
280 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->plasmafile, cptr);
281 cptr=res->plasmafile+strlen(res->plasmafile)-1;
282 while(isspace((int)*cptr)) {*cptr=(char)0; cptr--;}
283 } else if(strncasecmp(line, "2nd Plasma file", 15)==0) {
284 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
285 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->plasmafile2, cptr);
286 cptr=res->plasmafile2+strlen(res->plasmafile2)-1;
287 while(isspace((int)*cptr)) {*cptr=(char)0; cptr--;}
288 } else if(strncasecmp(line, "Blood file", 10)==0) {
289 lptr=&tmp[11]; cptr=strtok(lptr, " \t\n\r"); n=1;
290 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->bloodfile, cptr);
291 } else if(strncasecmp(line, "Reference file", 14)==0) {
292 lptr=&tmp[15]; cptr=strtok(lptr, " \t\n\r"); n=1;
293 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->reffile, cptr);
294 } else if(strncasecmp(line, "Reference region", 16)==0) {
295 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
296 if(cptr!=NULL && strlen(cptr)<64) strcpy(res->refroi, cptr);
297 cptr=res->refroi+strlen(res->refroi)-1;
298 while(isspace((int)*cptr)) {*cptr=(char)0; cptr--;}
299 } else if(strncasecmp(line, "Fit time", 8)==0 || strncasecmp(line, "Data range", 10)==0) {
300 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
301 if(cptr!=NULL && strlen(cptr)<128) strcpy(res->datarange, cptr);
302 cptr=res->datarange+strlen(res->datarange)-1;
303 while(isspace((int)*cptr)) {*cptr=(char)0; cptr--;}
304 } else if(strncasecmp(line, "Data nr", 7)==0) {
305 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
306 if(cptr!=NULL) res->datanr=atoi(cptr);
307 } else if(strncasecmp(line, "Fit method", 10)==0) {
308 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
309 if(cptr!=NULL && strlen(cptr)<128) strcpy(res->fitmethod, cptr);
310 cptr=res->fitmethod+strlen(res->fitmethod)-1;
311 while(isspace((int)*cptr)) {*cptr=(char)0; cptr--;}
312 } else if(strncasecmp(line, "Tissue density", 14)==0) {
313 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
314 if(cptr!=NULL) res->density=atof_dpi(cptr);
315 } else if(strncasecmp(line, "Lumped constant", 15)==0) {
316 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
317 if(cptr!=NULL) res->lc=atof_dpi(cptr);
318 } else if(strncasecmp(line, "Concentration", 13)==0) {
319 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
320 if(cptr!=NULL) res->concentration=atof_dpi(cptr);
321 } else if(strncasecmp(line, "Beta", 4)==0) {
322 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
323 if(cptr!=NULL) res->beta=atof_dpi(cptr);
324 } else if(strncasecmp(line, "Vb", 2)==0) {
325 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
326 if(cptr!=NULL) res->Vb=atof_dpi(cptr);
327 } else if(strncasecmp(line, "fA", 2)==0) {
328 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
329 if(cptr!=NULL) res->fA=atof_dpi(cptr);
330 } else if(strncasecmp(line, "Extraction", 10)==0) {
331 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
332 if(cptr!=NULL) res->E=atof_dpi(cptr);
333 } else if(strncasecmp(line, "Weighting", 9)==0) {
334 cptr=strchr(tmp, ':')+1; while(isspace((int)*cptr)) cptr++; n=1;
335 if(strncasecmp(cptr, "yes", 1)==0) res->isweight=1;
336 else if(strncasecmp(cptr, "no", 1)==0) res->isweight=0;
337 else res->isweight=-1;
338 } else if(strncasecmp(line, "Data was weighted", 17)==0) {
339 res->isweight=1; n=1;
340 } else if(strncasecmp(line, "Data was not weighted", 21)==0) {
341 res->isweight=0; n=1;
342 } else if(strncasecmp(line, "Region", 6)==0) {
343 /* Header end, stop here */
344 n=0;
345 } else { /* Ignore all other header lines */
346 n=1;
347 }
348 } while(n);
349 if(verbose>6) printf("quit reading headers\n");
350
351 /* Read the result parameter title line */
352 if(verbose>1) printf("reading parameter titles\n");
353 if(verbose>6) printf("using previously read line[%d] := %s", (int)strlen(line), line);
354 if(strncasecmp(line, "Region", 6)) {fclose(fp); return(10);}
355 strcpy(tmp, line);
356 lptr=strpbrk(tmp+6, " \n\r\t"); if(lptr==NULL) {fclose(fp); return(10);}
357 cptr=strtok(lptr, " \n\r\t");
358 n=0;
359 if(cptr!=NULL) {
360 if(strcmp(cptr, ".")!=0) {
361 strncpy(res->parname[n], cptr, MAX_RESPARNAME_LEN);
362 res->parname[n][MAX_RESPARNAME_LEN]=(char)0;
363 } else {strcpy(res->parname[n], "");}
364 if(verbose>5) printf(" parname[%d] := '%s'\n", n, res->parname[n]);
365 n++;
366 } else {strcpy(res->parname[n], "");}
367 while(cptr!=NULL) {
368 cptr=strtok(NULL, " \n\r\t");
369 if(cptr!=NULL && n<MAX_RESPARAMS) {
370 if(strcmp(cptr, ".")!=0) {
371 strncpy(res->parname[n], cptr, MAX_RESPARNAME_LEN);
372 res->parname[n][MAX_RESPARNAME_LEN]=(char)0;
373 } else {strcpy(res->parname[n], "");}
374 if(verbose>5) printf(" parname[%d] := '%s'\n", n, res->parname[n]);
375 n++;
376 }
377 }
378 res->parNr=n; if(verbose>1) printf("parNr := %d\n", res->parNr);
379
380 /* Read the result parameter unit line */
381 if(verbose>2) printf("seeking unit line...\n");
382 if(fgetpos(fp, &file_loc)!=0) {fclose(fp); return(20);}
383 while(fgets(line, 1024, fp)!=NULL && strlen(line)<3) {
384 if(verbose>6) printf("omitted line[%d] := %s", (int)strlen(line), line);
385 /* save the file position where unit line or results really start */
386 if(fgetpos(fp, &file_loc)!=0) {fclose(fp); return(20);}
387 }
388 if(verbose>5) printf("possible unit line[%d]: %s", (int)strlen(line), line);
389 if(strncasecmp(line, "# Units :", 7)==0 ||
390 strncasecmp(line, "Units : ", 7)==0 ||
391 strncasecmp(line, "# Units: ", 7)==0 ||
392 strncasecmp(line, "Units: ", 6)==0)
393 {
394 if(verbose>1) printf("reading parameter units\n");
395 strcpy(tmp, line); lptr=strchr(tmp+5, ':');
396 if(lptr!=NULL) lptr++; else lptr=strpbrk(tmp+6, " \n\r\t");
397 cptr=strtok(lptr, " \n\r\t"); n=0;
398 if(cptr!=NULL) {
399 if(strcmp(cptr, ".")!=0) {
400 strncpy(res->parunit[n], cptr, MAX_RESPARNAME_LEN);
401 res->parunit[n][MAX_RESPARNAME_LEN]=(char)0;
402 } else {strcpy(res->parunit[n], "");}
403 if(verbose>5) printf(" parunit[%d] := '%s'\n", n, res->parunit[n]);
404 n++;
405 } else {strcpy(res->parunit[n], "");}
406 while(cptr!=NULL) {
407 cptr=strtok(NULL, " \n\r\t");
408 if(cptr!=NULL && n<MAX_RESPARAMS) {
409 if(strcmp(cptr, ".")!=0) {
410 strncpy(res->parunit[n], cptr, MAX_RESPARNAME_LEN);
411 res->parunit[n][MAX_RESPARNAME_LEN]=(char)0;
412 } else strcpy(res->parunit[n], "");
413 if(verbose>5) printf(" parunit[%d] := '%s'\n", n, res->parunit[n]);
414 n++;
415 }
416 }
417 } else {
418 if(verbose>5) printf(" ... not identified as unit line.\n");
419 /* move file pointer to the previous place */
420 if(fsetpos(fp, &file_loc)!=0) {fclose(fp); return(20);}
421 }
422
423 /* Read the nr of result lines */
424 if(verbose>1) printf("reading nr of results\n");
425 /* Set bookmark to the start of result lines */
426 if(fgetpos(fp, &file_loc)!=0) {fclose(fp); return(21);}
427 n=0;
428 while(fgets(line, 1024, fp)!=NULL) {
429 if(verbose>6) printf("line[%d] := %s", (int)strlen(line), line);
430 if(line[0]=='#' || line[0]==';') continue;
431 i=strlen(line); if(i<2) continue; if(i<3) break;
432 n++;
433 }
434 /* Return file pointer to the start of result lines */
435 if(fsetpos(fp, &file_loc)!=0) {fclose(fp); return(22);}
436 if(verbose>1) printf("nr of result lines is %d\n", n);
437 if(n<1) {
438 strcpy(reserrmsg, "invalid result lines");
439 fclose(fp); return(23);
440 }
441
442 /* Allocate memory for regional results */
443 if(verbose>2) printf("allocating memory\n");
444 if(resSetmem(res, n)) {
445 strcpy(reserrmsg, "cannot allocate memory");
446 fclose(fp); return(25);
447 }
448
449 /* Read regional results */
450 if(verbose>1) printf("reading results to memory\n");
451 int separtab=0; // 0=space as separator, 1=tab as separator
452 char separstr[12];
453 res->voiNr=0;
454 while(fgets(line, 1024, fp)!=NULL) {
455 if(verbose>6) printf("line[%d] := %s", (int)strlen(line), line);
456 if(line[0]=='#' || line[0]==';') continue;
457 i=strlen(line); if(i<2) continue; if(i<3) break;
458 strcpy(tmp, line);
459 if(verbose>2) printf("reading result %d\n", 1+res->voiNr);
460
461 /* Read region names */
462 if(strchr(tmp, '\t')==NULL) separtab=0; else separtab=1;
463 if(separtab) strcpy(separstr, "\t\n\r"); else strcpy(separstr, " \t\n\r");
464 int tokenNr=strTokenNr(tmp, separstr);
465 if(verbose>20) printf(" tokenNr := %d\n", tokenNr);
466 if(!separtab) { // old format with space as separator
467 if(verbose>20) printf("separator: space\n");
468 n=strTokenNCpy(tmp, separstr, 1, res->voi[res->voiNr].voiname, MAX_REGIONSUBNAME_LEN+1);
469 if(n==0) {fclose(fp); return(31);}
470 n=strTokenNCpy(tmp, separstr, 2, res->voi[res->voiNr].hemisphere, MAX_REGIONSUBNAME_LEN+1);
471 if(n==0) {fclose(fp); return(31);}
472 n=strTokenNCpy(tmp, separstr, 3, res->voi[res->voiNr].place, MAX_REGIONSUBNAME_LEN+1);
473 if(n==0) {fclose(fp); return(31);}
475 res->voi[res->voiNr].hemisphere, res->voi[res->voiNr].place, ' ');
476 } else { // space can exist only in TAC name
477 if(verbose>20) printf("separator: tab\n");
478 n=strTokenNCpy(tmp, separstr, 1, res->voi[res->voiNr].name, MAX_REGIONNAME_LEN+1);
479 if(n==0) {fclose(fp); return(31);}
480 rnameSplit(res->voi[res->voiNr].name, res->voi[res->voiNr].voiname,
481 res->voi[res->voiNr].hemisphere, res->voi[res->voiNr].place, MAX_REGIONSUBNAME_LEN);
482 }
483 if(strcmp(res->voi[res->voiNr].voiname, ".")==0) res->voi[res->voiNr].voiname[0]=(char)0;
484 if(strcmp(res->voi[res->voiNr].hemisphere, ".")==0) res->voi[res->voiNr].hemisphere[0]=(char)0;
485 if(strcmp(res->voi[res->voiNr].place, ".")==0) res->voi[res->voiNr].place[0]=(char)0;
486 if(verbose>18) {
487 printf(" voiname := '%s'\n", res->voi[res->voiNr].voiname);
488 printf(" hemisphere := '%s'\n", res->voi[res->voiNr].hemisphere);
489 printf(" place := '%s'\n", res->voi[res->voiNr].place);
490 }
491
492 /* Read results, continuing from the pointer after region names */
493 int tokeni=2; if(!separtab) tokeni=4;
494 char buf[128];
495 for(i=0; i<MAX_RESPARAMS && tokeni<=tokenNr; i++, tokeni++) {
496 n=strTokenNCpy(tmp, separstr, tokeni, buf, 128);
497 if(n==0) {fclose(fp); return(32);}
498 if(strlen(buf)==1 && buf[0]=='.') res->voi[res->voiNr].parameter[i]=nan("");
499 else res->voi[res->voiNr].parameter[i]=atof_dpi(buf);
500 }
501 if(verbose>5) printf(" for '%s' parNr:=%d\n", res->voi[res->voiNr].name, i);
502 //if(res->voiNr==0) {res->parNr=i;} else if(i<res->parNr) res->parNr=i;
503 if(i<res->parNr) {
504 if(verbose>0)
505 printf("Warning: smaller parNr %d on region '%s'\n", i, res->voi[res->voiNr].name);
506 res->parNr=i;
507 }
508
509 /* If 'region' name implies that this was confidence limit or sd, then */
510 /* move the values into correct places, and do not increase the voiNr */
511 if(res->voiNr==0) {res->voiNr++; continue;}
512 if(strcasecmp(res->voi[res->voiNr].voiname, "CL")==0) {
513 if(strcmp(res->voi[res->voiNr].hemisphere, "95%")==0) {
514 if(strcasecmp(res->voi[res->voiNr].place, "Lower")==0)
515 for(i=0; i<res->parNr; i++)
516 res->voi[res->voiNr-1].cl1[i]=res->voi[res->voiNr].parameter[i];
517 else if(strcasecmp(res->voi[res->voiNr].place, "Upper")==0)
518 for(i=0; i<res->parNr; i++)
519 res->voi[res->voiNr-1].cl2[i]=res->voi[res->voiNr].parameter[i];
520 continue;
521 }
522 } else if(strcasecmp(res->voi[res->voiNr].voiname, "SD")==0) {
523 for(i=0; i<res->parNr; i++)
524 res->voi[res->voiNr-1].sd[i]=res->voi[res->voiNr].parameter[i];
525 continue;
526 }
527 res->voiNr++;
528 }
529 if(res->parNr==0) {fclose(fp); return(33);}
530 if(verbose>0) printf("nr of results: %d ; nr of parameters: %d\n", res->voiNr, res->parNr);
531
532 /* Seek for other results in the same file */
533 while(fgets(line, 1024, fp)!=NULL) {
534 /* Ignore empty and comment lines */
535 if(strlen(line)<3 || line[0]=='#') continue; else break;
536 }
537 /* Check again for string (c) or (C) */
538 if(strstr(line, "(c)") || strstr(line, "(C)")) {
539 fprintf(stderr,
540 "Warning: %s contains more than one set of results; only the 1st one is used.\n", filename);
541 }
542
543 /* Close file */
544 fclose(fp);
545 strcpy(reserrmsg, "");
546
547 /* Fill studynr if it was not found in file */
548 if(!res->studynr[0]) studynr_from_fname(filename, res->studynr);
549 /* Set also deprecated parameter name and unit representations, for now */
550 resFixParnames(res);
551
552 return(0);
553}
554/*****************************************************************************/
555
556/*****************************************************************************/
567 RES *res,
569 char *filename,
571 int verbose
572) {
573 int i, j, n;
574 char tmp[1024], is_stdout=0, *cptr;
575 FILE *fp;
576 int partype[MAX_RESPARAMS]; /* 0=int, 1=double, 2=exp */
577 int colwidth[MAX_RESPARAMS];
578 double *p;
579
580
581 if(verbose>1) printf("resWrite(*res, %s, %d)\n", filename, verbose);
582 /* Check that there is some data to write */
583 if(res==NULL) {strcpy(reserrmsg, "error in result data"); return(1);}
584 if(res->voiNr<1) {strcpy(reserrmsg, "no result data"); return(1);}
585
586 /* Write results in HTML format, if necessary */
587 cptr=strrchr(filename, '.');
588 if(cptr!=NULL && (!strncasecmp(cptr, ".htm", 4)))
589 return(resWriteHTML(res, filename, verbose));
590
591 /* Check if writing to stdout */
592 if(!strcasecmp(filename, "stdout")) is_stdout=1;
593
594 /* Check if file exists; backup, if necessary */
595 if(!is_stdout) (void)backupExistingFile(filename, NULL, NULL);
596
597 resFixParnames(res);
598
599 /* Open output file */
600 if(is_stdout) fp=(FILE*)stdout;
601 else if((fp = fopen(filename, "w")) == NULL) {
602 strcpy(reserrmsg, "cannot open file"); return(2);}
603
604 /* Program name */
605 n=fprintf(fp, "%s\n\n", res->program);
606 if(n==0) {
607 strcpy(reserrmsg, "disk full");
608 if(!is_stdout) fclose(fp);
609 return(3);
610 }
611
612 /* Write calculation date and time */
613 if(!ctime_r_int(&res->time, tmp)) strcpy(tmp, "1900-01-01 00:00:00");
614 fprintf(fp, "Date:\t%s\n", tmp);
615
616 /* Write the studynr */
617 if(res->studynr[0]) fprintf(fp, "Study:\t%s\n", res->studynr);
618
619 /* Write the names of the original datafiles */
620 if(res->datafile[0]) fprintf(fp, "Data file:\t%s\n", res->datafile);
621 if(res->plasmafile[0]) fprintf(fp, "Plasma file:\t%s\n", res->plasmafile);
622 if(res->plasmafile2[0]) fprintf(fp, "2nd Plasma file:\t%s\n", res->plasmafile2);
623 if(res->bloodfile[0]) fprintf(fp, "Blood file:\t%s\n", res->bloodfile);
624 if(res->reffile[0]) fprintf(fp, "Reference file:\t%s\n", res->reffile);
625 if(res->refroi[0]) fprintf(fp, "Reference region:\t%s\n", res->refroi);
626
627 /* Write data range etc */
628 if(res->datarange[0]) fprintf(fp, "Data range:\t%s\n", res->datarange);
629 if(res->datanr>0) fprintf(fp, "Data nr:\t%d\n", res->datanr);
630 if(res->fitmethod[0]) fprintf(fp, "Fit method:\t%s\n", res->fitmethod);
631
632 /* Write constants */
633 if(res->density>0.0) fprintf(fp, "Tissue density:\t%g\n", res->density);
634 if(res->lc>0.0) fprintf(fp, "Lumped constant:\t%g\n", res->lc);
635 if(res->concentration>0.0)
636 fprintf(fp, "Concentration:\t%g\n", res->concentration);
637 if(res->beta>0.0) fprintf(fp, "Beta:\t%g\n", res->beta);
638 if(res->Vb>=0.0) fprintf(fp, "Vb:\t%g %%\n", res->Vb);
639 if(res->fA>=0.0) fprintf(fp, "fA:\t%g %%\n", res->fA);
640 if(res->E>=0.0) fprintf(fp, "Extraction:\t%g\n", res->E);
641
642 /* Weighting */
643 if(res->isweight>0) strcpy(tmp, "yes");
644 else if(res->isweight==0) strcpy(tmp, "no");
645 else strcpy(tmp, "unknown");
646 fprintf(fp, "Weighting:\t%s\n", tmp);
647
648 /* Determine column widths: */
649 for(j=0; j<res->parNr; j++) colwidth[j]=1;
650 /* should column be printed as integers (0), floats (1) or exponentials (2)? */
651 for(j=0; j<res->parNr; j++) {
652 partype[j]=resParameterPrintType(res, j);
653 }
654 /* min width required by titles */
655 for(j=0; j<res->parNr; j++) colwidth[j]=strlen(res->parname[j]);
656 if(verbose>2) {
657 printf("col widths after titles were checked:\n");
658 for(i=0; i<res->parNr; i++)
659 printf(" par%d : partype=%d colwidth=%d\n", i+1, partype[i], colwidth[i]);
660 }
661 /* min width required by units */
662 for(j=0; j<res->parNr; j++) {
663 n=strlen(res->parunit[j]); if(n>colwidth[j]) colwidth[j]=n;
664 }
665 if(verbose>2) {
666 printf("col widths after units were checked:\n");
667 for(i=0; i<res->parNr; i++)
668 printf(" par%d : partype=%d colwidth=%d\n", i+1, partype[i], colwidth[i]);
669 }
670 /* widths required by result values */
671 for(i=0; i<res->voiNr; i++) {
672 p=res->voi[i].parameter;
673 for(j=0; j<res->parNr; j++) {
674 if(isnan(p[j])) continue;
675 if(p[j]>=0) n=4; else n=3;
676 switch(partype[j]) {
677 case 0: sprintf(tmp, "%.0f", p[j]); break;
678 case 1: sprintf(tmp, "%.*f", n, p[j]); break;
679 case 2:
680 default: sprintf(tmp, "%.*e", n, p[j]); break;
681 }
682 n=strlen(tmp); if(n>colwidth[j]) colwidth[j]=n;
683 }
684 }
685 if(verbose>2) {
686 printf("col widths after result values were checked:\n");
687 for(i=0; i<res->parNr; i++)
688 printf(" par%d : partype=%d colwidth=%d\n", i+1, partype[i], colwidth[i]);
689 }
690
691 /* Title line */
692 if(verbose>4) {
693 printf(" writing title line with %d parameter(s)\n", res->parNr);
694 fflush(stdout);
695 }
696 fprintf(fp, "\n%s\t", "Region");
697 for(i=0; i<res->parNr; i++) {
698 if(strlen(res->parname[i])<1) strcpy(tmp, ".");
699 else strcpy(tmp, res->parname[i]);
700 fprintf(fp, "\t%s", tmp);
701 }
702 fprintf(fp, "\n");
703
704 /* Write units, if they exist, currently as comment line */
705 for(i=j=0; i<res->parNr; i++) if(strlen(res->parunit[i])>0) j++;
706 if(j>0) {
707 if(verbose>4) {
708 printf(" writing units line with %d parameter(s)\n", j);
709 fflush(stdout);
710 }
711 fprintf(fp, "%s", "# Units:");
712 //fprintf(fp, "%s ", "# Units :");
713 for(i=0; i<res->parNr; i++) {
714 if(strlen(res->parunit[i])<1) strcpy(tmp, ".");
715 else strcpy(tmp, res->parunit[i]);
716 fprintf(fp, "\t%s", tmp);
717 }
718 fprintf(fp, "\n");
719 }
720 fflush(fp);
721
722 /* Write regional results */
723 if(verbose>4) {
724 printf(" writing %d regional results\n", res->voiNr); fflush(stdout);
725 }
726 for(i=0; i<res->voiNr; i++) {
727 if(verbose>6) {printf(" writing region %d\n", 1+i); fflush(stdout);}
728#if(1) // new version
729 if(res->voi[i].name[0]) {
730 fprintf(fp, "%s", res->voi[i].name);
731 } else {
732 if(res->voi[i].voiname[0]) strcpy(tmp, res->voi[i].voiname); else strcpy(tmp, ".");
733 fprintf(fp, "%.*s ", MAX_REGIONSUBNAME_LEN, tmp);
734 if(res->voi[i].hemisphere[0]) strcpy(tmp, res->voi[i].hemisphere); else strcpy(tmp, ".");
735 fprintf(fp, "%.*s ", MAX_REGIONSUBNAME_LEN, tmp);
736 if(res->voi[i].place[0]) strcpy(tmp, res->voi[i].place); else strcpy(tmp, ".");
737 fprintf(fp, "%.*s", MAX_REGIONSUBNAME_LEN, tmp);
738 }
739#else // previous version
740 if(res->voi[i].voiname[0])
741 strcpy(tmp, res->voi[i].voiname); else strcpy(tmp, ".");
742 fprintf(fp, "%.*s ", MAX_REGIONSUBNAME_LEN, tmp);
743 if(res->voi[i].hemisphere[0])
744 strcpy(tmp, res->voi[i].hemisphere); else strcpy(tmp, ".");
745 fprintf(fp, "%.*s ", MAX_REGIONSUBNAME_LEN, tmp);
746 if(res->voi[i].place[0])
747 strcpy(tmp, res->voi[i].place); else strcpy(tmp, ".");
748 fprintf(fp, "%.*s", MAX_REGIONSUBNAME_LEN, tmp);
749#endif
750 p=res->voi[i].parameter;
751 for(j=0; j<res->parNr; j++) {
752 if(verbose>15) {printf(" writing par %d\n", 1+j); fflush(stdout);}
753 if(isnan(p[j])) {fprintf(fp, "\t."); continue;}
754 switch(partype[j]) {
755 case 0: fprintf(fp, "\t%.0f", p[j]); break;
756 case 1:
757 if(p[j]>=0) n=4; else n=3;
758 fprintf(fp, "\t%.*f", n, p[j]);
759 break;
760 default:
761 if(p[j]>=0) n=4; else n=3;
762 fprintf(fp, "\t%.*e", n, p[j]);
763 break;
764 }
765 }
766 fprintf(fp, "\n"); fflush(fp);
767 /* Write SD's, if they exist */
768 if(verbose>25) {printf(" sd?\n"); fflush(stdout);}
769 //if(res->voi[i].sd==NULL) {printf("NULL\n"); fflush(stdout);}
770 if(verbose>25) {printf(" parNr=%d\n", res->parNr); fflush(stdout);}
771 n=0; for(int j=0; j<res->parNr; j++) {if(!isnan(res->voi[i].sd[j])) n++;}
772 if(verbose>25) {printf(" n=%d\n", n); fflush(stdout);}
773 if(n>0) {
774 fprintf(fp, "SD . .");
775 for(j=0; j<res->parNr; j++) {
776 if(verbose>15) {printf(" writing sd %d\n", 1+j); fflush(stdout);}
777 if(!isnan(res->voi[i].sd[j])) {
778 switch(partype[j]) {
779 case 0: fprintf(fp, "\t%.0f", res->voi[i].sd[j]); break;
780 case 1:
781 if(res->voi[i].sd[j]>=0) n=4; else n=3;
782 fprintf(fp, "\t%.*f", n, res->voi[i].sd[j]);
783 break;
784 default:
785 if(res->voi[i].sd[j]>=0) n=4; else n=3;
786 fprintf(fp, "\t%.*e", n, res->voi[i].sd[j]);
787 break;
788 }
789 } else {
790 fprintf(fp, "\t.");
791 }
792 }
793 fprintf(fp, "\n"); fflush(fp);
794 }
795 /* Write lower confidence limits, if they exist */
796 if(verbose>25) {printf(" cl1?\n"); fflush(stdout);}
797 n=0; for(int j=0; j<res->parNr; j++) if(!isnan(res->voi[i].cl1[j])) n++;
798 if(verbose>25) {printf(" n=%d\n", n); fflush(stdout);}
799 if(n>0) {
800 fprintf(fp, "CL 95%% Lower");
801 for(j=0; j<res->parNr; j++) {
802 if(verbose>15) {printf(" writing CL1 %d\n", 1+j); fflush(stdout);}
803 if(!isnan(res->voi[i].cl1[j])) {
804 switch(partype[j]) {
805 case 0: fprintf(fp, "\t%.0f", res->voi[i].cl1[j]); break;
806 case 1:
807 if(res->voi[i].cl1[j]>=0) n=4; else n=3;
808 fprintf(fp, "\t%.*f", n, res->voi[i].cl1[j]);
809 break;
810 default:
811 if(res->voi[i].cl1[j]>=0) n=4; else n=3;
812 fprintf(fp, "\t%.*e", n, res->voi[i].cl1[j]);
813 break;
814 }
815 } else {
816 fprintf(fp, "\t.");
817 }
818 }
819 fprintf(fp, "\n");
820 }
821 /* Write upper confidence limits, if they exist */
822 if(verbose>25) {printf(" cl2?\n"); fflush(stdout);}
823 n=0; for(int j=0; j<res->parNr; j++) if(!isnan(res->voi[i].cl2[j])) n++;
824 if(verbose>25) {printf(" n=%d\n", n); fflush(stdout);}
825 if(n>0) {
826 fprintf(fp, "CL 95%% Upper");
827 for(j=0; j<res->parNr; j++) {
828 if(verbose>15) {printf(" writing CL2 %d\n", 1+j); fflush(stdout);}
829 if(!isnan(res->voi[i].cl2[j])) {
830 switch(partype[j]) {
831 case 0: fprintf(fp, "\t%.0f", res->voi[i].cl2[j]); break;
832 case 1:
833 if(res->voi[i].cl2[j]>=0) n=4; else n=3;
834 fprintf(fp, "\t%.*f", n, res->voi[i].cl2[j]);
835 break;
836 default:
837 if(res->voi[i].cl2[j]>=0) n=4; else n=3;
838 fprintf(fp, "\t%.*e", n, res->voi[i].cl2[j]);
839 break;
840 }
841 } else {
842 fprintf(fp, "\t.");
843 }
844 }
845 fprintf(fp, "\n"); fflush(fp);
846 }
847 } /* next region */
848
849 /* Close file */
850 if(!is_stdout) {fflush(fp); fclose(fp);}
851 strcpy(reserrmsg, "");
852 if(verbose>1) {printf("resWrite() done.\n"); fflush(stdout);}
853
854 return(0);
855}
856/*****************************************************************************/
857
858/*****************************************************************************/
867 RES *res,
869 char *fname,
871 int verbose
872) {
873 int n, is_stdout=0;
874 char tmp[1024];
875 FILE *fp;
876
877
878 if(verbose>0) printf("resWriteHTML(*res, %s, %d)\n", fname, verbose);
879 /* Check that there is some data to write */
880 if(res==NULL) {strcpy(reserrmsg, "error in result data"); return(1);}
881 if(res->voiNr<1) {strcpy(reserrmsg, "no result data"); return(1);}
882 /* Check if writing to stdout */
883 if(!strcasecmp(fname, "stdout")) is_stdout=1;
884
885 resFixParnames(res);
886
887 /* Check if file exists; backup, if necessary */
888 if(!is_stdout && access(fname, 0) != -1) {
889 strcpy(tmp, fname); strcat(tmp, BACKUP_EXTENSION);
890 if(access(tmp, 0)!=-1) remove(tmp);
891 rename(fname, tmp);
892 }
893 strcpy(reserrmsg, "cannot write file");
894
895 /* Open output file */
896 if(is_stdout) fp=(FILE*)stdout;
897 else if((fp=fopen(fname, "w"))==NULL) {
898 strcpy(reserrmsg, "cannot open file"); return(2);}
899
900 /* Write XHTML 1.1 doctype and head */
902 strcpy(reserrmsg, "disk full");
903 if(!is_stdout) fclose(fp);
904 return(3);
905 }
906
907 /* Start writing the body of the HTML file */
908 fprintf(fp, "\n<body>\n");
909
910 /* Start the div for tables */
911 fprintf(fp, "\n<div id=\"tables\">\n");
912
913 /* Write results into a table */
914 if(resWriteHTML_table(res, fp)!=0) {
915 strcpy(reserrmsg, "disk full");
916 if(!is_stdout) fclose(fp);
917 return(3);
918 }
919
920 /* Stop writing the body of the HTML file, and end the file */
921 fprintf(fp, "</div>\n");
922 n=fprintf(fp, "</body></html>\n\n");
923 if(n==0) {
924 strcpy(reserrmsg, "disk full");
925 if(!is_stdout) fclose(fp);
926 return(3);
927 }
928
929 /* Close file */
930 if(!is_stdout) {fflush(fp); fclose(fp);}
931 strcpy(reserrmsg, "");
932
933 return(0);
934}
935/*****************************************************************************/
936
937/*****************************************************************************/
943 FILE *fp
944) {
945 int n;
946 if(fp==NULL) return(1);
947 n=fprintf(fp, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" ");
948 n+=fprintf(fp, "\"https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n");
949 if(n<20) return(2);
950 n=fprintf(fp,"<html xmlns=\"https://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n\n");
951 if(n<20) return(2);
952 return(0);
953}
954/*****************************************************************************/
955
956/*****************************************************************************/
962 FILE *fp,
964 char *author_name
965) {
966 int n;
967 if(fp==NULL) return(1);
968
969 n=fprintf(fp, "<head>\n"); if(n<6) return(2);
970 fprintf(fp, " <title>Tabulated PET results</title>\n");
971 fprintf(fp, " <meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\" />\n");
972 fprintf(fp, " <meta http-equiv=\"content-language\" content=\"en-gb\" />\n");
973 fprintf(fp, " <meta name=\"description\" content=\"Regional PET results\" />\n");
974 fprintf(fp, " <meta name=\"author\" content=\"%s\" />\n", author_name);
975 fprintf(fp, " <meta name=\"ProgId\" content=\"Excel.Sheet\" />\n");
976 fprintf(fp, " <link rel=\"icon\" href=\"https://www.turkupetcentre.net/favicon.ico\" type=\"image/x-icon\" />\n");
977 fprintf(fp, " <link rel=\"shortcut icon\" href=\"https://www.turkupetcentre.net/favicon.ico\" type=\"image/x-icon\" />\n");
978 /* write local CSS with basic settings in case external CSS is not available */
979 fprintf(fp, " <style type=\"text/css\">\n");
980 fprintf(fp, " thead {background-color:#999999; color:black;}\n");
981//fprintf(fp, " table {text-align:left; width:100%%; border-collapse:colla");
982 fprintf(fp, " table {text-align:left; border-collapse:collapse; empty-cells:show;}\n");
983//fprintf(fp, " td {border:1px solid black;}\n");
984 fprintf(fp, " .oddroi {background-color:#FFFFFF; color:black;}\n");
985 fprintf(fp, " .evenroi {background-color:#CCCCCC; color:black;}\n");
986 fprintf(fp, " .sd {background-color:#999999; color:blue;}\n");
987 fprintf(fp, " .cl1 {background-color:#999999; color:green;}\n");
988 fprintf(fp, " .cl2 {background-color:#999999; color:green;}\n");
989 fprintf(fp, " .oddstudy {background-color:#FFFFFF; color:black;}\n");
990 fprintf(fp, " .evenstudy {background-color:#CCCCCC; color:black;}\n");
991 fprintf(fp, " .oddsum {background-color:#999999; color:black;}\n");
992 fprintf(fp, " .evensum {background-color:#CCCCCC; color:black;}\n");
993 fprintf(fp, " #regcontainer ul {margin-left:0; padding-left:0;}\n");
994 fprintf(fp, " #regcontainer ul li {display:inline; list-style-type:none;}\n");
995 fprintf(fp, " #regcontainer a {padding:2px 4px;}\n");
996 fprintf(fp, " <!--table\n");
997 fprintf(fp, " {mso-displayed-decimal-separator:\"\\.\";\n");
998 fprintf(fp, " mso-displayed-thousand-separator:\" \";}\n");
999 fprintf(fp, " -->\n");
1000 fprintf(fp, " </style>\n");
1001 /* load external CSS with more fancy settings */
1002 fprintf(fp, " <link rel=\"stylesheet\" type=\"text/css\" href=\"https://www.turkupetcentre.net/result.css\" />\n");
1003 fprintf(fp, "</head>\n");
1004 if(n<7) return(2);
1005 return(0);
1006}
1007/*****************************************************************************/
1008
1009/*****************************************************************************/
1015 RES *res,
1017 FILE *fp
1018) {
1019 int i, j, n;
1020 char *cptr, tmp[1024];
1021 int partype[MAX_RESPARAMS]; /* 0=int, 1=double, 2=exp */
1022 double *p;
1023
1024 if(RESULT_TEST>0) printf("resWriteHTML_table(*res, fp)\n");
1025 if(fp==NULL || res==NULL) return(1);
1026
1027 /* Write the title lines to the head of table */
1028 fprintf(fp, "<table>\n");
1029 fprintf(fp, "<thead>\n");
1030 /* Program name */
1031 strcpy(tmp, res->program);
1032 cptr=strcasestr(tmp, "(c)");
1033 if(cptr!=NULL) {
1034 *cptr=(char)0;
1035 i=strlen(tmp)-1; while(i>0 && isspace(tmp[i])) i--; tmp[i+1]=(char)0;
1036 }
1037 if(tmp[0])
1038 fprintf(fp, "<tr align=left><th>Program:</th><td>%s</td></tr>\n", tmp);
1039 /* Write calculation date and time */
1040 if(!ctime_r_int(&res->time, tmp)) strcpy(tmp, "1900-01-01 00:00:00");
1041 fprintf(fp, "<tr align=left><th>Date:</th><td>%s</td></tr>\n", tmp);
1042 /* Write the studynr */
1043 if(res->studynr[0])
1044 fprintf(fp, "<tr align=left><th>Study:</th><td>%s</td></tr>\n", res->studynr);
1045 /* Write the names of the original datafiles */
1046 if(res->datafile[0])
1047 fprintf(fp, "<tr align=left><th>Data file:</th><td>%s</td></tr>\n", res->datafile);
1048 if(res->plasmafile[0])
1049 fprintf(fp, "<tr align=left><th>Plasma file:</th><td>%s</td></tr>\n", res->plasmafile);
1050 if(res->plasmafile2[0])
1051 fprintf(fp, "<tr align=left><th>2nd Plasma file:</th><td>%s</td></tr>\n", res->plasmafile2);
1052 if(res->bloodfile[0])
1053 fprintf(fp, "<tr align=left><th>Blood file:</th><td>%s</td></tr>\n", res->bloodfile);
1054 if(res->reffile[0])
1055 fprintf(fp, "<tr align=left><th>Reference file:</th><td>%s</td></tr>\n", res->reffile);
1056 if(res->refroi[0])
1057 fprintf(fp, "<tr align=left><th>Reference region:</th><td>%s</td></tr>\n", res->refroi);
1058 /* Write data range etc */
1059 if(res->datarange[0])
1060 fprintf(fp, "<tr align=left><th>Data range:</th><td>%s</td></tr>\n", res->datarange);
1061 if(res->datanr>0)
1062 fprintf(fp, "<tr align=left><th>Data nr:</th><td>%d</td></tr>\n", res->datanr);
1063 if(res->fitmethod[0])
1064 fprintf(fp, "<tr align=left><th>Fit method:</th><td>%s</td></tr>\n", res->fitmethod);
1065 /* Write constants */
1066 if(res->density>0.0)
1067 fprintf(fp, "<tr align=left><th>Tissue density:</th><td>%g</td></tr>\n", res->density);
1068 if(res->lc>0.0)
1069 fprintf(fp, "<tr align=left><th>Lumped constant:</th><td>%g</td></tr>\n", res->lc);
1070 if(res->concentration>0.0)
1071 fprintf(fp, "<tr align=left><th>Concentration:</th><td>%g</td></tr>\n", res->concentration);
1072 if(res->beta>0.0)
1073 fprintf(fp, "<tr align=left><th>Beta:</th><td>%g</td></tr>\n", res->beta);
1074 if(res->Vb>=0.0)
1075 fprintf(fp, "<tr align=left><th>Vb:</th><td>%g %%</td></tr>\n", res->Vb);
1076 if(res->fA>=0.0)
1077 fprintf(fp, "<tr align=left><th>fA:</th><td>%g %%</td></tr>\n", res->fA);
1078 if(res->E>0.0)
1079 fprintf(fp, "<tr align=left><th>Extraction:</th><td>%g</td></tr>\n", res->E);
1080 /* Weighting */
1081 if(res->isweight>0) strcpy(tmp, "yes");
1082 else if(res->isweight==0) strcpy(tmp, "no");
1083 else strcpy(tmp, "unknown");
1084 fprintf(fp, "<tr align=left><th>Weighting:</th><td>%s</td></tr>\n", tmp);
1085 /* End the head of table */
1086 fprintf(fp, "</thead>\n");
1087
1088 /* Collect info on column types */
1089 for(j=0; j<res->parNr; j++) {
1090 /* should column be printed as integers, floats or exponentials? */
1091 partype[j]=resParameterPrintType(res, j);
1092 }
1093
1094 /* Write the result data to the table body */
1095 fprintf(fp, "<tbody>\n");
1096 /* Write the result title line */
1097 fprintf(fp,"<tr align=left><th>Region</th>\n");
1098 for(i=0; i<res->parNr; i++) fprintf(fp, "<th>%s</th>", res->parname[i]);
1099 fprintf(fp, "</tr>\n");
1100 /* Write regional results */
1101 for(i=0; i<res->voiNr; i++) {
1102 if(i%2) strcpy(tmp, "evenroi"); else strcpy(tmp, "oddroi");
1103 fprintf(fp, "<tr class=\"%s\">", tmp);
1104 char *senc=strEncodeForXML(res->voi[i].name);
1105 if(senc==NULL) fprintf(fp, "<th>%s</th>", res->voi[i].name);
1106 else {fprintf(fp, "<th>%s</th>", senc); free(senc);}
1107 p=res->voi[i].parameter;
1108 for(j=0; j<res->parNr; j++) switch(partype[j]) {
1109 case 0: fprintf(fp, "<td>%.0f</td>", p[j]); break;
1110 case 1: fprintf(fp, "<td>%.4f</td>", p[j]); break;
1111 default: fprintf(fp, "<td>%.4E</td>", p[j]); break;
1112 }
1113 fprintf(fp, "</tr>\n");
1114 /* Write SD's, if they exist */
1115 p=res->voi[i].sd; for(j=n=0; j<res->parNr; j++) if(!isnan(p[j])) n++;
1116 if(n>0) {
1117 fprintf(fp, "<tr class=\"sd\">");
1118 fprintf(fp, "<th>%s</th>", "SD");
1119 for(j=0; j<res->parNr; j++) {
1120 if(!isnan(p[j])) switch(partype[j]) {
1121 case 0: fprintf(fp, "<td>%.0f</td>", p[j]); break;
1122 case 1: fprintf(fp, "<td>%.4f</td>", p[j]); break;
1123 default: fprintf(fp, "<td>%.4E</td>", p[j]); break;
1124 } else fprintf(fp, "<td></td>");
1125 }
1126 fprintf(fp, "</tr>\n");
1127 }
1128 /* Write lower confidence limits, if they exist */
1129 p=res->voi[i].cl1; for(j=n=0; j<res->parNr; j++) if(!isnan(p[j])) n++;
1130 if(n>0) {
1131 fprintf(fp, "<tr class=\"cl1\">");
1132 fprintf(fp, "<th>CL95%%L</th>");
1133 for(j=0; j<res->parNr; j++) {
1134 if(!isnan(p[j])) switch(partype[j]) {
1135 case 0: fprintf(fp, "<td>%.0f</td>", p[j]); break;
1136 case 1: fprintf(fp, "<td>%.4f</td>", p[j]); break;
1137 default: fprintf(fp, "<td>%.4E</td>", p[j]); break;
1138 } else fprintf(fp, "<td></td>");
1139 }
1140 fprintf(fp, "</tr>\n");
1141 }
1142 /* Write upper confidence limits, if they exist */
1143 p=res->voi[i].cl2; for(j=n=0; j<res->parNr; j++) if(!isnan(p[j])) n++;
1144 if(n>0) {
1145 fprintf(fp, "<tr class=\"cl2\">");
1146 fprintf(fp, "<th>CL95%%U</th>");
1147 for(j=0; j<res->parNr; j++) {
1148 if(!isnan(p[j])) switch(partype[j]) {
1149 case 0: fprintf(fp, "<td>%.0f</td>", p[j]); break;
1150 case 1: fprintf(fp, "<td>%.4f</td>", p[j]); break;
1151 default: fprintf(fp, "<td>%.4E</td>", p[j]); break;
1152 } else fprintf(fp, "<td></td>");
1153 }
1154 fprintf(fp, "</tr>\n");
1155 }
1156 }
1157 /* End the body of the table and table */
1158 fprintf(fp, "</tbody></table>\n");
1159
1160 return(0);
1161}
1162/*****************************************************************************/
1163
1164/*****************************************************************************/
1170 char *fname,
1171 char *studyNumber
1172) {
1173 return(studynr_from_fname(fname, studyNumber));
1174}
1175/*****************************************************************************/
1176
1177/*****************************************************************************/
1188 double *data,
1190 int nr,
1192 double *median,
1194 double *min,
1196 double *max
1197) {
1198 /* Check the arguments */
1199 if(data==NULL) return(1);
1200 if(nr<1) return(2);
1201 /* Sort data in increasing order */
1202 qsort(data, nr, sizeof(double), resQSortComp);
1203 /* Get minimum and maximum */
1204 if(min!=NULL) *min=data[0];
1205 if(max!=NULL) *max=data[nr-1];
1206 /* Calculate median */
1207 if(median!=NULL) {
1208 if(nr%2) *median=data[(nr-1)/2];
1209 else *median=0.5*(data[(nr/2)-1]+data[nr/2]);
1210 }
1211 return(0);
1212}
1213/*****************************************************************************/
1214
1215/*****************************************************************************/
1224 double *data,
1226 int nr,
1228 double *mean,
1230 double *sd
1231) {
1232 int i;
1233 double sum, ssum, v;
1234
1235 /* Check the arguments */
1236 if(data==NULL) return(1);
1237 if(nr<1) return(2);
1238 /* Calculate avg and sd */
1239 for(i=0, sum=ssum=0.0; i<nr; i++) {
1240 sum+=data[i]; ssum+=data[i]*data[i];
1241 }
1242 if(mean!=NULL) *mean=sum/(double)nr;
1243 if(sd!=NULL) {
1244 if(nr>1) v=(ssum-sum*sum/(double)nr)/(double)(nr-1); else v=0.0;
1245 if(v>0.0) *sd=sqrt(v); else *sd=0.0;
1246 }
1247 return(0);
1248}
1249/*****************************************************************************/
1250
1251/*****************************************************************************/
1253int resQSortComp(const void *f1, const void *f2)
1254{
1255 if(*(double*)f1<*(double*)f2) return(-1);
1256 else if(*(double*)f1>*(double*)f2) return(1);
1257 else return(0);
1258}
1260/*****************************************************************************/
1261
1262/*****************************************************************************/
1267 /* Pointer to RES struct. */
1268 RES *res
1269) {
1270 if(res==NULL || res->voiNr<=1) return;
1271 qsort(res->voi, res->voiNr, sizeof(ResVOI), resQSortName);
1272 return;
1273}
1274/*****************************************************************************/
1275
1276/*****************************************************************************/
1278int resQSortName(const void *voi1, const void *voi2)
1279{
1280 int res;
1281
1282 res=strcasecmp( ((const ResVOI*)voi1)->voiname, ((const ResVOI*)voi2)->voiname );
1283 if(res!=0) return(res);
1284 res=strcasecmp( ((const ResVOI*)voi1)->hemisphere, ((const ResVOI*)voi2)->hemisphere );
1285 if(res!=0) return(res);
1286 res=strcasecmp( ((const ResVOI*)voi1)->place, ((const ResVOI*)voi2)->place );
1287 return(res);
1288}
1290/*****************************************************************************/
1291
1292/*****************************************************************************/
1298 /* Pointer to RES struct to copy header from. */
1299 RES *res1,
1300 /* Pointer to RES struct to copy header to. */
1301 RES *res2
1302) {
1303 int i;
1304
1305 if(res1==NULL || res2==NULL) return(1);
1306 strcpy(res2->program, res1->program);
1307 res2->time=res1->time;
1308 res2->parNr=res1->parNr;
1309 strcpy(res2->studynr, res1->studynr);
1310 strcpy(res2->datafile, res1->datafile);
1311 strcpy(res2->reffile, res1->reffile);
1312 strcpy(res2->plasmafile, res1->plasmafile);
1313 strcpy(res2->plasmafile2, res1->plasmafile2);
1314 strcpy(res2->bloodfile, res1->bloodfile);
1315 strcpy(res2->refroi, res1->refroi);
1316 strcpy(res2->datarange, res1->datarange);
1317 res2->datanr=res1->datanr;
1318 strcpy(res2->fitmethod, res1->fitmethod);
1319 res2->density=res1->density;
1320 res2->lc=res1->lc;
1321 res2->concentration=res1->concentration;
1322 res2->beta=res1->beta;
1323 res2->Vb=res1->Vb;
1324 res2->fA=res1->fA;
1325 res2->E=res1->E;
1326 res2->isweight=res1->isweight;
1327 for(i=0; i<res1->parNr; i++) {
1328 strcpy(res2->parname[i], res1->parname[i]);
1329 strcpy(res2->parunit[i], res1->parunit[i]);
1330 }
1331 strcpy(res2->titleline, res1->titleline);
1332 strcpy(res2->unitline, res1->unitline);
1333 return(0);
1334}
1335/*****************************************************************************/
1336
1337/*****************************************************************************/
1344 RES *res,
1346 int voi
1347) {
1348 int i;
1349
1350 /* Check that region exists */
1351 if(res==NULL || voi>res->voiNr-1 || voi<0) return(1);
1352 /* If it is the last one, then just decrease the voiNr */
1353 if(voi==res->voiNr) {res->voiNr--; return(0);}
1354 /* Otherwise we have to move the following regions in its place */
1355 for(i=voi+1; i<res->voiNr; i++)
1356 memcpy(&res->voi[i-1], &res->voi[i], sizeof(ResVOI));
1357 res->voiNr--;
1358 return(0);
1359}
1360/*****************************************************************************/
1361
1362/*****************************************************************************/
1371 RES *data,
1373 char *name
1374) {
1375 unsigned int i, j, n;
1376 char *p, n1[128], n2[128], n3[128], tmp[128], sname[1024], *lptr;
1377
1378 if(data==NULL) return(-1);
1379 /* Select all, if no string was specified */
1380 if(name==NULL || strlen(name)==0) {
1381 for(i=0; i<(unsigned int)data->voiNr; i++) data->voi[i].sw=1;
1382 return(data->voiNr);
1383 }
1384 /* Make a copy of 'name' and use it */
1385 strcpy(sname, name); lptr=sname;
1386 /* Check if string contains several substrings (hemisphere and place) */
1387 n1[0]=n2[0]=n3[0]=(char)0;
1388 p=strtok(lptr, " ,;\n\t|"); if(p!=NULL) strcpy(n1, p); else return(-1);
1389 p=strtok(NULL, " ,;\n\t|"); if(p!=NULL) {
1390 strcpy(n2, p); p=strtok(NULL, " ,;\n\t|"); if(p!=NULL) strcpy(n3, p);}
1391 /* Convert strings to lowercase */
1392 for(i=0; i<strlen(n1); i++) n1[i]=tolower(n1[i]);
1393 for(i=0; i<strlen(n2); i++) n2[i]=tolower(n2[i]);
1394 for(i=0; i<strlen(n3); i++) n3[i]=tolower(n3[i]);
1395 /* Search through the data */
1396 for(i=0, n=0; i<(unsigned int)data->voiNr; i++) {
1397 data->voi[i].sw=0;
1398 snprintf(tmp, 128, "%s%s%s", data->voi[i].voiname, data->voi[i].hemisphere,
1399 data->voi[i].place);
1400 for(j=0; j<strlen(tmp); j++) tmp[j]=tolower(tmp[j]);
1401 if(strstr(tmp, n1)==NULL) continue;
1402 if(n2[0] && strstr(tmp, n2)==NULL) continue;
1403 if(n3[0] && strstr(tmp, n3)==NULL) continue;
1404 data->voi[i].sw=1; n++;
1405 }
1406 return(n);
1407}
1408/*****************************************************************************/
1409
1410/*****************************************************************************/
1419 RES *res,
1421 char *region_name,
1423 int reset
1424) {
1425 int ri, match_nr=0;
1426
1427 /* Check the input */
1428 if(res==NULL || res->voiNr<1 || strlen(region_name)<1) return(-1);
1429 /* Reset all selections if required */
1430 if(reset!=0) for(ri=0; ri<res->voiNr; ri++) res->voi[ri].sw=0;
1431 /* Check each VOI */
1432 for(ri=0; ri<res->voiNr; ri++) {
1433 if(rnameMatch(res->voi[ri].name, ri+1, region_name)!=0) {
1434 res->voi[ri].sw=1; match_nr++;
1435 }
1436 }
1437 return(match_nr);
1438}
1439/*****************************************************************************/
1440
1441/*****************************************************************************/
1449 RES *res,
1451 int parIndex
1452) {
1453 int vi, partype=0;
1454 double x, m=0.0, pint;
1455
1456 if(res==NULL || res->voiNr<1 || parIndex<0 || parIndex>=res->parNr)
1457 return(-1);
1458 for(vi=0; vi<res->voiNr; vi++) {
1459 x=res->voi[vi].parameter[parIndex];
1460 if(modf(x, &pint)!=0.0) partype=1;
1461 x=fabs(x); if(x>m) m=x;
1462 }
1463 if(partype==1 && (m>=10.0 || m<0.1)) partype=2;
1464 return(partype);
1465}
1466/*****************************************************************************/
1467
1468/*****************************************************************************/
1475 RES *res
1476) {
1477 int ri, rj;
1478
1479 if(res==NULL) return(-1);
1480 if(res->voiNr<2) return(0);
1481 for(ri=0; ri<res->voiNr-1; ri++) for(rj=ri+1; rj<res->voiNr; rj++)
1482 if(strcasecmp(res->voi[ri].name, res->voi[rj].name)==0) return(1);
1483 return(0);
1484}
1485/*****************************************************************************/
1486
1487/*****************************************************************************/
1496 RES *res1,
1498 RES *res2
1499) {
1500 if(res1==NULL || res2==NULL) return(1);
1501 if(res1->voiNr!=res2->voiNr) return(3);
1502 if(res1->parNr!=res2->parNr) return(4);
1503 if(strcasecmp(res1->datafile, res2->datafile)!=0) return(6);
1504 if(strcasecmp(res1->reffile, res2->reffile)!=0) return(7);
1505 if(strcasecmp(res1->plasmafile, res2->plasmafile)!=0) return(8);
1506 if(strcasecmp(res1->plasmafile2, res2->plasmafile2)!=0) return(9);
1507 if(strcasecmp(res1->bloodfile, res2->bloodfile)!=0) return(10);
1508 if(strcasecmp(res1->refroi, res2->refroi)!=0) return(11);
1509 if(strcasecmp(res1->datarange, res2->datarange)!=0) return(12);
1510 if(res1->isweight!=res2->isweight) return(13);
1511 if(res1->density!=res2->density) return(14);
1512 if(res1->lc!=res2->lc) return(15);
1513 if(res1->beta!=res2->beta) return(16);
1514 if(res1->concentration!=res2->concentration) return(17);
1515 if(res1->Vb!=res2->Vb) return(18);
1516 if(res1->datanr!=res2->datanr) return(19);
1517 if(strcasecmp(res1->fitmethod, res2->fitmethod)!=0) return(20);
1518 if(res1->fA!=res2->fA) return(21);
1519 if(res1->E!=res2->E) return(22);
1520 /* Less important */
1521 if(strcasecmp(res1->studynr, res2->studynr)!=0) return(5);
1522 return(0);
1523}
1524/*****************************************************************************/
1525
1526/*****************************************************************************/
1533 RES *res1,
1535 RES *res2
1536) {
1537 int ri, m=0;
1538
1539 if(res1==NULL || res2==NULL || res1->voiNr!=res2->voiNr) return(1);
1540 for(ri=0; ri<res1->voiNr; ri++) {
1541 m=0;
1542// if(strcmp(res1->voi[ri].name, res2->voi[ri].name)!=0) return(1);
1543 if(strcmp(res1->voi[ri].voiname, res2->voi[ri].voiname)!=0) m++;
1544 if(strcmp(res1->voi[ri].hemisphere, res2->voi[ri].hemisphere)!=0) m++;;
1545 if(strcmp(res1->voi[ri].place, res2->voi[ri].place)!=0) m++;
1546 if(m>0) {
1547 if(RESULT_TEST>5) {
1548 printf(" '%s' vs '%s'\n", res1->voi[ri].voiname, res2->voi[ri].voiname);
1549 printf(" '%s' vs '%s'\n", res1->voi[ri].hemisphere, res2->voi[ri].hemisphere);
1550 printf(" '%s' vs '%s'\n", res1->voi[ri].place, res2->voi[ri].place);
1551 }
1552 return(1);
1553 }
1554 }
1555 return(0);
1556}
1557/*****************************************************************************/
1558
1559/*****************************************************************************/
1566 RES *res1,
1568 RES *res2
1569) {
1570 int i;
1571
1572 if(res1==NULL || res2==NULL || res1->parNr!=res2->parNr) return(1);
1573
1574 resFixParnames(res1);
1575 resFixParnames(res2);
1576
1577 for(i=0; i<res1->parNr; i++) {
1578 if(strcasecmp(res1->parname[i], res2->parname[i])!=0) {
1579 if(RESULT_TEST>1)
1580 printf(" Parameter names '%s' and '%s' do not match\n",
1581 res1->parname[i], res2->parname[i]);
1582 return(1);
1583 }
1584 if(strcasecmp(res1->parunit[i], res2->parunit[i])!=0) {
1585 if(RESULT_TEST>1)
1586 printf(" Parameter units '%s' and '%s' do not match\n",
1587 res1->parunit[i], res2->parunit[i]);
1588 return(1);
1589 }
1590 }
1591 return(0);
1592}
1593/*****************************************************************************/
1594
1595/*****************************************************************************/
1602 RES *res1,
1604 RES *res2,
1606 int test_par,
1608 double test_limit,
1610 int test_sd
1611) {
1612 int ri, pi;
1613 double s, v1, v2;
1614
1615 if(res1==NULL || res2==NULL || res1->voiNr!=res2->voiNr) return(1);
1616 if(res1->parNr!=res2->parNr) {
1617 if(test_par<0) return(1);
1618 if(test_par+1>res1->parNr || test_par+1>res2->parNr) return(1);
1619 }
1620 for(ri=0; ri<res1->voiNr; ri++) {
1621 for(pi=0; pi<res1->parNr; pi++) {
1622 if(test_par>=0 && test_par!=pi) continue;
1623 v1=res1->voi[ri].parameter[pi]; v2=res2->voi[ri].parameter[pi];
1624 if(isnan(v1) && isnan(v2)) continue; // ok if both are NaN
1625 /* Parameter values */
1626 if(RESULT_TEST>5) printf("pi=%d ri=%d\n", pi, ri);
1627 if(RESULT_TEST>5) printf(" %g vs %g\n", v1, v2);
1628 s=fabs(v1+v2); if(isnan(s)) return(2); // Either one is NaN
1629 if(test_limit<=0.0) { // values are requested to match exactly
1630 if(v1!=v2) return(2);
1631 } if(s==0.0 || v1==0.0 || v2==0.0) { // relative matching cant be done
1632 if(fabs(v1-v2)>test_limit) return(2);
1633 } else { // test relative difference against given limit
1634 if(fabs((v1-v2)/s)>test_limit) return(2);
1635 }
1636 if(test_sd!=0) {
1637 /* SD */
1638 v1=res1->voi[ri].sd[pi]; v2=res2->voi[ri].sd[pi];
1639 if(RESULT_TEST>5) printf(" SD: %g vs %g\n", v1, v2);
1640 if(isnan(v1) && isnan(v2)) {
1641 // both are NA, that is ok
1642 } else if(isnan(v1) || isnan(v2)) {
1643 // one is NA, that is not ok
1644 return(3);
1645 } else if(test_limit<=0.0) { // values are requested to match exactly
1646 if(v1!=v2) return(3);
1647 } if(s==0.0) { // relative matching cant be done
1648 if(fabs(v1-v2)>test_limit) return(3);
1649 } else { // test relative difference against given limit
1650 if(fabs((v1-v2)/s)>test_limit) return(3);
1651 }
1652 /* CL1 */
1653 v1=res1->voi[ri].cl1[pi]; v2=res2->voi[ri].cl1[pi];
1654 if(RESULT_TEST>5) printf(" CL1: %g vs %g\n", v1, v2);
1655 if(isnan(v1) && isnan(v2)) {
1656 // both are NA, that is ok
1657 } else if(isnan(v1) || isnan(v2)) {
1658 // one is NA, that is not ok
1659 return(4);
1660 } else if(test_limit<=0.0) { // values are requested to match exactly
1661 if(v1!=v2) return(4);
1662 } if(s==0.0) { // relative matching cant be done
1663 if(fabs(v1-v2)>test_limit) return(4);
1664 } else { // test relative difference against given limit
1665 if(fabs((v1-v2)/s)>test_limit) return(4);
1666 }
1667 /* CL2 */
1668 v1=res1->voi[ri].cl2[pi]; v2=res2->voi[ri].cl2[pi];
1669 if(RESULT_TEST>5) printf(" CL2: %g vs %g\n", v1, v2);
1670 if(isnan(v1) && isnan(v2)) {
1671 // both are NA, that is ok
1672 } else if(isnan(v1) || isnan(v2)) {
1673 // one is NA, that is not ok
1674 return(5);
1675 } else if(test_limit<=0.0) { // values are requested to match exactly
1676 if(v1!=v2) return(5);
1677 } if(s==0.0) { // relative matching cant be done
1678 if(fabs(v1-v2)>test_limit) return(5);
1679 } else { // test relative difference against given limit
1680 if(fabs((v1-v2)/s)>test_limit) return(5);
1681 }
1682 }
1683 }
1684 }
1685 return(0);
1686}
1687/******************************************************************************/
1688
1689/******************************************************************************/
1696 RES *res1,
1698 RES *res2,
1700 int test_par,
1702 double test_limit,
1704 int test_sd
1705) {
1706 int ri, pi;
1707 double s, v1, v2;
1708
1709 if(res1==NULL || res2==NULL || res1->voiNr!=res2->voiNr) return(1);
1710 if(res1->parNr!=res2->parNr) {
1711 if(test_par<0) return(1);
1712 if(test_par+1>res1->parNr || test_par+1>res2->parNr) return(1);
1713 }
1714 if(test_limit<0.0) return(1);
1715 for(ri=0; ri<res1->voiNr; ri++) {
1716 for(pi=0; pi<res1->parNr; pi++) {
1717 if(test_par>=0 && test_par!=pi) continue;
1718 v1=res1->voi[ri].parameter[pi]; v2=res2->voi[ri].parameter[pi];
1719 if(isnan(v1) && isnan(v2)) continue;
1720 /* Parameter values */
1721 if(RESULT_TEST>5) printf("pi=%d ri=%d\n", pi, ri);
1722 if(RESULT_TEST>5) printf(" %g vs %g\n", v1, v2);
1723 s=fabs(v1-v2);
1724 if(isnan(s) || s>test_limit) return(2);
1725 if(test_sd!=0) {
1726 /* SD */
1727 v1=res1->voi[ri].sd[pi]; v2=res2->voi[ri].sd[pi];
1728 if(isnan(v1) && !isnan(v2)) return(3);
1729 if(!isnan(v1) && isnan(v2)) return(3);
1730 if(!isnan(v1) && !isnan(v2)) {
1731 if(RESULT_TEST>8) printf(" SD: %g vs %g\n", v1, v2);
1732 s=fabs(v1-v2); if(s>test_limit) return(3);
1733 }
1734 /* CL1 */
1735 v1=res1->voi[ri].cl1[pi]; v2=res2->voi[ri].cl1[pi];
1736 if(isnan(v1) && !isnan(v2)) return(4);
1737 if(!isnan(v1) && isnan(v2)) return(4);
1738 if(!isnan(v1) && !isnan(v2)) {
1739 if(RESULT_TEST>8) printf(" CL1: %g vs %g\n", v1, v2);
1740 s=fabs(v1-v2); if(s>test_limit) return(4);
1741 }
1742 /* CL2 */
1743 v1=res1->voi[ri].cl2[pi]; v2=res2->voi[ri].cl2[pi];
1744 if(isnan(v1) && !isnan(v2)) return(5);
1745 if(!isnan(v1) && isnan(v2)) return(5);
1746 if(!isnan(v1) && !isnan(v2)) {
1747 if(RESULT_TEST>8) printf(" CL2: %g vs %g\n", v1, v2);
1748 s=fabs(v1-v2); if(s>test_limit) return(5);
1749 }
1750 }
1751 }
1752 }
1753 return(0);
1754}
1755/*****************************************************************************/
1756
1757/*****************************************************************************/
1765 RES *res
1766) {
1767 int ri, m=0, n=0;
1768
1769 if(res==NULL) return(-1);
1770 if(res->voiNr<1) return(-1);
1771 for(ri=0; ri<res->voiNr; ri++) {
1772 if(strlen(res->voi[ri].hemisphere)>0 &&
1773 strcmp(res->voi[ri].hemisphere, ".")!=0)
1774 m++;
1775 if(strlen(res->voi[ri].place)>0 &&
1776 strcmp(res->voi[ri].place, ".")!=0)
1777 n++;
1778 }
1779 ri=0; if(m>0) ri+=1; if(n>0) ri+=2;
1780 return(ri);
1781}
1782/*****************************************************************************/
1783
1784/*****************************************************************************/
int backupExistingFile(char *filename, char *backup_ext, char *status)
Definition backup.c:14
int get_datetime(char *str, struct tm *date, int verbose)
Definition datetime.c:322
char * ctime_r_int(const time_t *t, char *buf)
Convert calendard time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
Definition datetime.c:110
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
Definition datetime.c:69
int get_date(char *str, struct tm *date)
Definition datetime.c:377
double atof_dpi(char *str)
Definition decpoint.c:59
Header file for libtpccurveio.
#define MAX_RESPARNAME_LEN
#define MAX_RESPARAMS
#define BACKUP_EXTENSION
int rnameCatenate(char *rname, int max_rname_len, char *name1, char *name2, char *name3, char space)
Definition rname.c:189
int rnameMatch(char *rname, int rnr, char *test_str)
Definition rname.c:144
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
int strTokenNCpy(const char *str1, const char *str2, int i, char *str3, int count)
Definition strext.c:45
int strTokenNr(const char *str1, const char *str2)
Definition strext.c:17
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
#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
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341
char reserrmsg[64]
Definition result.c:6
void resInit(RES *res)
Definition result.c:52
int resSetmem(RES *res, int voiNr)
Definition result.c:70
int resMatchRegions(RES *res1, RES *res2)
Definition result.c:1531
int resMean(double *data, int nr, double *mean, double *sd)
Definition result.c:1222
int resSelectRegions(RES *res, char *region_name, int reset)
Definition result.c:1417
void resSortByName(RES *res)
Definition result.c:1266
int resCopyMHeader(RES *res1, RES *res2)
Definition result.c:1297
void resPrint(RES *res)
Definition result.c:186
int resWriteXHTML11_head(FILE *fp, char *author_name)
Definition result.c:960
int resFName2study(char *fname, char *studyNumber)
Definition result.c:1169
int resParameterPrintType(RES *res, int parIndex)
Definition result.c:1447
int resWriteXHTML11_doctype(FILE *fp)
Definition result.c:941
void resFixParnames(RES *res)
Definition result.c:107
int resMatchParameternames(RES *res1, RES *res2)
Definition result.c:1564
int resIsDuplicateNames(RES *res)
Definition result.c:1473
int resWrite(RES *res, char *filename, int verbose)
Definition result.c:565
int resSelect(RES *data, char *name)
Definition result.c:1369
int resDelete(RES *res, int voi)
Definition result.c:1342
int resRNameSubfieldExists(RES *res)
Definition result.c:1763
int resRead(char *filename, RES *res, int verbose)
Definition result.c:199
int resMatchParameters(RES *res1, RES *res2, int test_par, double test_limit, int test_sd)
Definition result.c:1600
int resWriteHTML_table(RES *res, FILE *fp)
Definition result.c:1013
int resWriteHTML(RES *res, char *fname, int verbose)
Definition result.c:865
int resMatchHeader(RES *res1, RES *res2)
Definition result.c:1494
int resMatchParametersAbs(RES *res1, RES *res2, int test_par, double test_limit, int test_sd)
Definition result.c:1694
void resEmpty(RES *res)
Definition result.c:22
int RESULT_TEST
Definition result.c:5
int resMedian(double *data, int nr, double *median, double *min, double *max)
Definition result.c:1186
double E
double density
char plasmafile2[FILENAME_MAX]
char titleline[1024]
char studynr[MAX_STUDYNR_LEN+1]
double concentration
int parNr
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
double fA
int voiNr
int _voidataNr
int datanr
double beta
char unitline[1024]
ResVOI * voi
double Vb
char program[1024]
char plasmafile[FILENAME_MAX]
char datarange[128]
int isweight
double lc
char datafile[FILENAME_MAX]
char reffile[FILENAME_MAX]
char fitmethod[128]
char refroi[64]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char bloodfile[FILENAME_MAX]
time_t time
double parameter[MAX_RESPARAMS]
double cl2[MAX_RESPARAMS]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]
double cl1[MAX_RESPARAMS]
char name[MAX_REGIONNAME_LEN+1]
double sd[MAX_RESPARAMS]
char voiname[MAX_REGIONSUBNAME_LEN+1]