TPCCLIB
Loading...
Searching...
No Matches
tac2svg.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <unistd.h>
14#include <string.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcmodel.h"
19#include "libtpccurveio.h"
20#include "libtpcsvg.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Make XY plots of PET time-activity curves (TACs) in Scalable Vector Graphics",
26 "(SVG) 1.1. format; specification in https://www.w3.org/TR/SVG/",
27 "SVG files can be viewed with web browsers and processed further using for",
28 "example Inkscape, Batik, and Gimp.",
29 " ",
30 "Usage: @P [Options] svg_file [-L|-S|-B] tac_file1 [-L|-S|-B] tac_file2 ...",
31 " ",
32 "Options:",
33 " -L TACs that are given after this option are plotted with lines only,",
34 " -S TACs that are given after this option are plotted with symbols only,",
35 " -B TACs that are given after this option are plotted with lines and",
36 " symbols (default).",
37 " -x1=<start of x axis>",
38 " -x2=<end of x axis>",
39 " -y1=<start of y axis>",
40 " -y2=<end of y axis>",
41 " -nmt, -nxt, -nyt",
42 " Do not show main title or x or y axis titles.",
43 " -mt=\"<main title>\"",
44 " User-specified string to override any default main title,",
45 " -xt=\"<x axis title>\"",
46 " User-specified string to override any default x axis title,",
47 " -yt=\"<y axis title>\"",
48 " User-specified string to override any default y axis title.",
49 " -legend=<yes|No|auto>",
50 " Show TAC legends (yes), do not show (no, default), or automatically",
51 " determine whether to show or not (auto).",
52 " -color, -bw", // grayscale not supported yet
53 " Create plots with colors (default), or in black-and-white.",
54 /* note that -s means silent only if given as option; but if given after
55 svg filename, it is interpreted as 'plot this with symbols' */
56 " -stdoptions", // List standard options like --help, -v, etc
57 " ",
58 "Normally, SVG graphics file should have extension .svg. Alternatively,",
59 "SVG graphics can be written inline in XHTML file by setting the extension",
60 "to .xhtml.",
61 " ",
62 "Example 1.",
63 " @P gj247.svg -s gj247.tac -l gj247_fitted.tac",
64 " ",
65 "See also: fit2dat, dftscale, dftmax, tac4frpl, tacformat, tacjoin, tac2xml",
66 " ",
67 "Keywords: simulation, modelling, plotting, tool, DFT, TAC, SVG, XML",
68 0};
69/*****************************************************************************/
70
71/*****************************************************************************/
72/* Turn on the globbing of the command line, since it is disabled by default in
73 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
74 In Unix&Linux wildcard command line processing is enabled by default. */
75/*
76#undef _CRT_glob
77#define _CRT_glob -1
78*/
79int _dowildcard = -1;
80/*****************************************************************************/
81
82/*****************************************************************************/
83typedef struct {
84 DFT dft;
85 int type; // 1=line, 2=symbol, 0=both
86} DFTLIST;
87/*****************************************************************************/
88
89/*****************************************************************************/
93int main(int argc, char **argv)
94{
95 int ai, help=0, version=0, verbose=1;
96 int ti, ri, ret, fileNr=0, n, ns, nl, datarg=0;
97 char *cptr, errmsg[128], temp[128];
98 char svgfile[FILENAME_MAX], tacfile[FILENAME_MAX];
99 int do_XHTML=0, plot_fit=0;
100 int show_main_title=1;
101 int show_x_title=1;
102 int show_y_title=1;
103 char main_title[64], x_title[64], y_title[64], tac_id[32], tac_title[64];
104 int color_scale=0; // 0=color, 1=grayscale, 2=monochrome
105 int symbol_fill=1;
106 FILE *fp_svg;
107 struct svg_viewports viewports; svg_init_viewports(&viewports);
108 DFTLIST *dftl;
109 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2;
110 double preset_minx, preset_maxx, preset_miny, preset_maxy;
111 int symbol_nr=0, color_nr=0, color_nr2=0, is_label=0;
112 int max_color_nr, max_symbol_nr;
113 SVG_LEGENDS legends; svg_init_legends(&legends);
114 int use_studynr=0;
115 int use_tacname=0;
116
117
118
119 /*
120 * Get arguments
121 */
122 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
123 svgfile[0]=tacfile[0]=(char)0;
124 main_title[0]=x_title[0]=y_title[0]=(char)0;
125 tac_id[0]=tac_title[0]=(char)0;
126 preset_minx=preset_maxx=preset_miny=preset_maxy=nan("");
127 /* Options */
128 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
129 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
130 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
131 cptr=argv[ai]+1;
132 if(strncasecmp(cptr, "X1=", 3)==0) {
133 preset_minx=atof_dpi(cptr+3); continue;
134 } else if(strncasecmp(cptr, "X2=", 3)==0) {
135 preset_maxx=atof_dpi(cptr+3); continue;
136 } else if(strncasecmp(cptr, "Y1=", 3)==0) {
137 preset_miny=atof_dpi(cptr+3); continue;
138 } else if(strncasecmp(cptr, "Y2=", 3)==0) {
139 preset_maxy=atof_dpi(cptr+3); continue;
140 } else if(strcasecmp(cptr, "L")==0) {
141 continue; // for now, see below
142 } else if(strcasecmp(cptr, "S")==0) {
143 continue; // for now, see below
144 } else if(strcasecmp(cptr, "B")==0) {
145 continue; // for now, see below
146 } else if(strcasecmp(cptr, "XHTML")==0) {
147 do_XHTML=1; continue;
148 } else if(strcasecmp(cptr, "NMT")==0) {
149 show_main_title=0; continue;
150 } else if(strcasecmp(cptr, "NXT")==0) {
151 show_x_title=0; continue;
152 } else if(strcasecmp(cptr, "NYT")==0) {
153 show_y_title=0; continue;
154 } else if(strncasecmp(cptr, "MT=", 3)==0) {
155 ret=strnCopyClean(main_title, cptr+3, 64);
156 if(ret==0) show_main_title=0; else show_main_title=1;
157 continue;
158 } else if(strncasecmp(cptr, "XT=", 3)==0) {
159 ret=strnCopyClean(x_title, cptr+3, 64);
160 if(ret==0) show_x_title=0; else show_x_title=1;
161 continue;
162 } else if(strncasecmp(cptr, "YT=", 3)==0) {
163 ret=strnCopyClean(y_title, cptr+3, 64);
164 if(ret==0) show_y_title=0; else show_y_title=1;
165 continue;
166 } else if(strncasecmp(cptr, "LEGEND=", 7)==0) {
167 cptr+=7;
168 if(strncasecmp(cptr, "YES", 1)==0) {is_label=1; continue;}
169 if(strncasecmp(cptr, "NO", 1)==0) {is_label=0; continue;}
170 if(strncasecmp(cptr, "AUTO", 1)==0) {is_label=2; continue;}
171 } else if(strcasecmp(cptr, "COLOR")==0) {
172 color_scale=0; continue;
173 } else if(strncasecmp(cptr, "GRAY", 2)==0) {
174 color_scale=1; continue;
175 } else if(strncasecmp(cptr, "MONOCHROME", 2)==0 || strcasecmp(cptr, "BW")==0) {
176 color_scale=2; continue;
177 }
178 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
179 return(1);
180 } else break;
181
182 /* Print help or version? */
183 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
184 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
185 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
186
187 /* Process other arguments, starting from the first non-option */
188 for(; ai<argc; ai++) {
189 /* Get SVG filename, and set the argument index for data files */
190 if(!svgfile[0]) {strcpy(svgfile, argv[ai]); datarg=ai+1; continue;}
191 else if(strcasecmp(argv[ai], "-S")==0) continue;
192 else if(strcasecmp(argv[ai], "-B")==0) continue;
193 else if(strcasecmp(argv[ai], "-L")==0) continue;
194 else {
195 /* Check that file(s) do exist */
196 if(access(argv[ai], 0) == -1) {
197 fprintf(stderr, "Error: %s does not exist.\n", argv[ai]);
198 return(2);
199 }
200 /* Count them */
201 fileNr++;
202 }
203 }
204
205 /* Is something missing? */
206 if(!svgfile[0] || fileNr<1) {
207 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
208 return(1);
209 }
210
211 /* Get the output file format by interpreting the extension */
212 cptr=strrchr(svgfile, '.'); if(cptr!=NULL) {
213 cptr++;
214 if(strcasecmp(cptr, "XHTML")==0) {
215 do_XHTML=1;
216 } else if(strcasecmp(cptr, "HTM")==0 || strcasecmp(cptr, "HTML")==0) {
217 fprintf(stderr, "Warning: file with HTM(L) extension will probably not open\n");
218 fprintf(stderr, " correctly in web browsers; use .xhtml instead.\n");
219 do_XHTML=1;
220 } else if(strcasecmp(cptr, "SVG")!=0) {
221 /* If output file name extension is not .svg, then user probably just forgot to give
222 file name for it. Do not allow overwrite! */
223 if(access(svgfile, 0) != -1) {
224 fprintf(stderr, "Error: output file extension is not .svg\n");
225 return(2);
226 }
227 /* If output file extension is not .svg, but file does not exist, then just give a warning */
228 fprintf(stderr, "Warning: filename with other than .svg extension may not\n");
229 fprintf(stderr, " open correctly in other programs.\n");
230 }
231 }
232
233
234 /* In verbose mode print arguments and options */
235 if(verbose>1) {
236 printf("svgfile := %s\n", svgfile);
237 printf("fileNr := %d\n", fileNr);
238 printf("do_XHTML := %d\n", do_XHTML);
239 if(!isnan(preset_minx)) printf("preset_minx := %g\n", preset_minx);
240 if(!isnan(preset_maxx)) printf("preset_maxx := %g\n", preset_maxx);
241 if(!isnan(preset_miny)) printf("preset_miny := %g\n", preset_miny);
242 if(!isnan(preset_maxy)) printf("preset_maxy := %g\n", preset_maxy);
243 printf("show_main_title := %d\n", show_main_title);
244 printf("show_x_title := %d\n", show_x_title);
245 if(show_x_title) printf("requested_x_title := '%s'\n", x_title);
246 printf("show_y_title := %d\n", show_y_title);
247 if(show_y_title) printf("requested_y_title := '%s'\n", y_title);
248 printf("is_label := %d\n", is_label);
249 printf("color_scale := %d\n", color_scale);
250 fflush(stdout);
251 }
252
253
254 /*
255 * Read the TAC file(s), file name(s) from command-line
256 */
257 dftl=(DFTLIST*)calloc(fileNr, sizeof(DFTLIST));
258 if(dftl==NULL) {
259 fprintf(stderr, "Error: out of memory.\n");
260 return(2);
261 }
262 for(ti=0; ti<fileNr; ti++) {
263 dftInit(&dftl[ti].dft);
264 dftl[ti].type=-1;
265 }
266 ti=0;
267 for(ai=datarg; ai<argc; ai++) {
268 if(*argv[ai]=='-') {
269 if(strcasecmp(argv[ai], "-L")==0) dftl[ti].type=1;
270 else if(strcasecmp(argv[ai], "-S")==0) dftl[ti].type=2;
271 else if(strcasecmp(argv[ai], "-B")==0) dftl[ti].type=0;
272 } else {
273 strcpy(tacfile, argv[ai]);
274 if(ti>0 && dftl[ti].type<0) dftl[ti].type=dftl[ti-1].type;
275 if(dftl[ti].type<0) dftl[ti].type=0;
276 if(verbose>0) printf(" reading %s\n", tacfile);
277 if(dftRead(tacfile, &dftl[ti].dft)) {
278 fprintf(stderr, "Error in reading '%s': %s\n", tacfile, dfterrmsg);
279 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
280 free(dftl);
281 return(2);
282 }
283 /* Set study number, if not yet available */
284 if(strlen(dftl[ti].dft.studynr)<1) studynr_from_fname(tacfile, dftl[ti].dft.studynr);
285 ti++;
286 }
287 }
288 fileNr=ti;
289 if(verbose>1) {
290 for(ti=0; ti<fileNr; ti++) {
291 printf("voiNr[%d] := %d\n", ti+1, dftl[ti].dft.voiNr);
292 printf("frameNr[%d] := %d\n", ti+1, dftl[ti].dft.frameNr);
293 printf("type[%d] := %d\n", ti+1, dftl[ti].type);
294 printf("studynr[%d] := %s\n", ti+1, dftl[ti].dft.studynr);
295 }
296 }
297
298 /*
299 * Determine the plot titles
300 */
301 /* Search for common study number for use as main title */
302 if(show_main_title!=0 && !main_title[0]) {
303 for(ti=0; ti<fileNr; ti++) {
304 if(strlen(dftl[ti].dft.studynr)<1) continue;
305 if(strcmp(dftl[ti].dft.studynr, ".")==0) continue;
306 if(strlen(main_title)==0) { // take any string specified as study number
307 strcpy(main_title, dftl[ti].dft.studynr); continue;
308 } else {
309 // if study number was previously set, check that it is the same
310 if(strcasecmp(main_title, dftl[ti].dft.studynr)==0) continue;
311 // if not the same, then we can not set the main_title
312 strcpy(main_title, ""); break;
313 }
314 }
315 }
316 /* Search for common activity unit */
317 ret=n=CUNIT_UNKNOWN;
318 for(ti=0; ti<fileNr; ti++) {
319 n=dftUnitId(dftl[ti].dft.unit); if(n!=CUNIT_UNKNOWN) {ret=n; break;}
320 }
321 if(verbose>1) printf("common_cunit := %d\n", ret);
322 if(ret!=CUNIT_UNKNOWN && ret!=CUNIT_UNITLESS)
323 if(show_y_title!=0 && !y_title[0]) strcpy(y_title, dftUnit(ret));
324 /* If activity unit is known, try to convert all known units to that */
325 if(ret!=CUNIT_UNKNOWN)
326 for(ti=0; ti<fileNr; ti++) dftUnitConversion(&dftl[ti].dft, ret);
327 /* Search for common time unit */
328 ret=TUNIT_UNKNOWN;
329 for(ti=0; ti<fileNr; ti++) {
330 if(dftl[ti].dft.timeunit!=TUNIT_UNKNOWN) {ret=dftl[ti].dft.timeunit; break;}
331 }
332 if(verbose>1) printf("common_tunit := %d\n", ret);
333 if(show_x_title!=0 && !x_title[0]) {
334 if(ret==TUNIT_SEC || ret==TUNIT_MIN)
335 sprintf(x_title, "Time (%s)", petTunit(ret));
336 else if(ret==TUNIT_MM || ret==TUNIT_CM || ret==TUNIT_UM)
337 sprintf(x_title, "Distance (%s)", petTunit(ret));
338 else if(ret!=TUNIT_UNKNOWN && ret!=DFTUNIT_UNITLESS)
339 strcpy(x_title, petTunit(ret));
340 }
341 /* If time unit is known, try to convert all time units to that */
342 if(ret!=TUNIT_UNKNOWN) {
343 for(ti=0; ti<fileNr; ti++) dftTimeunitConversion(&dftl[ti].dft, ret);
344 }
345 if(verbose>1) {
346 printf("main_title := '%s'\n", main_title);
347 printf("x_title := '%s'\n", x_title);
348 printf("y_title := '%s'\n", y_title);
349 }
350
351
352 /* Determine the plot min and max values */
353 minx=maxx=miny=maxy=0;
354 for(ti=0; ti<fileNr; ti++) {
355 ret=dftMinMax(&dftl[ti].dft, &tx1, &tx2, &ty1, &ty2);
356 if(ret) {
357 fprintf(stderr, "Error: insufficient data.\n");
358 if(verbose>1) dftPrint(&dftl[ti].dft);
359 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
360 free(dftl);
361 return(5);
362 }
363 if(ti==0) {
364 minx=tx1; maxx=tx2; miny=ty1; maxy=ty2;
365 } else {
366 if(minx>tx1) minx=tx1;
367 if(maxx<tx2) maxx=tx2;
368 if(miny>ty1) miny=ty1;
369 if(maxy<ty2) maxy=ty2;
370 }
371 }
372 if(verbose>3) printf("minx:=%g\nmaxx:=%g\nminy:=%g\nmaxy:=%g\n", minx, maxx, miny, maxy);
373 /* Replace x range by preset range if acceptable */
374 if(!isnan(preset_minx)) tx1=preset_minx; else tx1=minx;
375 if(!isnan(preset_maxx)) tx2=preset_maxx; else tx2=maxx;
376 if(tx1<tx2) {minx=tx1; maxx=tx2;}
377 /* If x range was changed, then check the y data range inside x range */
378 if(!isnan(preset_minx) || !isnan(preset_maxx)) {
379 miny=maxy=nan("");
380 for(ti=0; ti<fileNr; ti++) {
381 ret=dftMaxY(&dftl[ti].dft, minx, maxx, &ty1, &ty2);
382 if(ret) {
383 fprintf(stderr, "Warning: insufficient data in the range.\n");
384 continue;
385 }
386 if(isnan(miny)) miny=ty1; else if(miny>ty1) miny=ty1;
387 if(isnan(maxy)) maxy=ty2; else if(maxy<ty2) maxy=ty2;
388 }
389 if(verbose>3) printf("in_range_miny:=%g\nin_range_maxy:=%g\n", miny, maxy);
390 if(isnan(miny) || isnan(maxy)) {
391 fprintf(stderr, "Error: insufficient data in the range.\n");
392 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
393 free(dftl);
394 return(5);
395 }
396 }
397
398 /* Replace y range by pre-set range if acceptable */
399 if(!isnan(preset_miny)) ty1=preset_miny; else ty1=miny;
400 if(!isnan(preset_maxy)) ty2=preset_maxy; else ty2=maxy;
401 if(ty1<ty2) {miny=ty1; maxy=ty2;}
402 if(verbose>2) printf("minx:=%g\nmaxx:=%g\nminy:=%g\nmaxy:=%g\n", minx, maxx, miny, maxy);
403
404 /* Calculate the axis ticks */
405 viewports.x.min=minx; viewports.x.max=maxx;
406 if(preset_minx==minx) viewports.x.fixed_min=1; else viewports.x.fixed_min=0;
407 if(preset_maxx==maxx) viewports.x.fixed_max=1; else viewports.x.fixed_max=0;
408 viewports.y.min=miny; viewports.y.max=maxy;
409 if(preset_miny==miny) viewports.y.fixed_min=1; else viewports.y.fixed_min=0;
410 if(preset_maxy==maxy) viewports.y.fixed_max=1; else viewports.y.fixed_max=0;
411 ret=svg_calculate_axes(&viewports, verbose-8);
412 if(ret) {
413 fprintf(stderr, "Error (%d) in setting axis scales.\n", ret);
414 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
415 free(dftl);
416 return(2);
417 }
418 if(verbose>3) {
419 printf("viewports.x.min := %g\n", viewports.x.min);
420 printf("viewports.x.max := %g\n", viewports.x.max);
421 printf("viewports.y.min := %g\n", viewports.y.min);
422 printf("viewports.y.max := %g\n", viewports.y.max);
423 }
424
425 /* Check if TAC titles should contain studynr and/or TAC name */
426 // search the first existing studynr
427 for(ti=n=0; ti<fileNr; ti++, n++)
428 if(strlen(dftl[ti].dft.studynr)>0 && strcmp(dftl[ti].dft.studynr, ".")!=0) break;
429 // search if there exists a different studynr
430 for(; ti<fileNr; ti++)
431 if(strlen(dftl[ti].dft.studynr)>0 && strcmp(dftl[ti].dft.studynr, ".")!=0)
432 if(strcasecmp(dftl[ti].dft.studynr, dftl[n].dft.studynr)!=0) {
433 if(verbose>2)
434 printf(" different studynr: '%s' vs '%s'\n", dftl[n].dft.studynr, dftl[ti].dft.studynr);
435 use_studynr=1; break;
436 }
437 // search if there exists a different region name
438 for(ti=0; ti<fileNr; ti++) {
439 if(ti==0) ri=1; else ri=0;
440 for(; ri<dftl[ti].dft.voiNr; ri++)
441 if(strcasecmp(dftl[ti].dft.voi[ri].name, dftl[0].dft.voi[0].name)!=0) {use_tacname=1; break;}
442 }
443 /* If no different stydynrs or tacnames were found, then use tacname anyway
444 but turn legends off if auto legends were requested */
445 if(use_studynr==0 && use_tacname==0) {
446 use_tacname=1; if(is_label==2) is_label=0;
447 } else {
448 if(is_label==2) is_label=1;
449 }
450
451 /* Set the plot window and window area sizes */
452 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
453 strlen(x_title), is_label, &viewports, verbose-9);
454 if(ret) {
455 fprintf(stderr, "Error (%d) in setting viewports.\n", ret);
456 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
457 free(dftl);
458 return(2);
459 }
460
461 /*
462 * If file exists, then backup it first
463 */
464 if((ret=backupExistingFile(svgfile, NULL, errmsg))!=0) {
465 fprintf(stderr, "Error: %s.\n", errmsg);
466 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
467 free(dftl);
468 return(10);
469 }
470
471 /*
472 * Initiate graphics file
473 */
474 if(verbose>1) printf(" initiating graphics file %s\n", svgfile);
475 if(do_XHTML) {
476 /* Initiate XHTML file for one or more inline SVG plots */
477 fp_svg=svg_xhtml_initiate(svgfile, main_title, errmsg, verbose-8);
478 if(fp_svg==NULL) {
479 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
480 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
481 free(dftl);
482 return(11);
483 }
484 /* Initiate inline SVG */
485 ret=svg_xhtml_svg_open(fp_svg, 0, 0, &viewports, errmsg, verbose-8);
486 if(fp_svg==NULL) {
487 fprintf(stderr, "Error in writing SVG in %s: %s\n", svgfile, errmsg);
488 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
489 free(dftl);
490 return(11);
491 }
492 } else {
493 /* Initiate SVG file */
494 fp_svg=svg_initiate(svgfile, 0, 0, &viewports, errmsg, verbose-8);
495 if(fp_svg==NULL) {
496 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
497 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
498 free(dftl);
499 return(11);
500 }
501 }
502
503 /*
504 * Put the graph title into its own viewport
505 */
506 if(verbose>1) printf("creating main title\n");
507 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, errmsg, verbose-5);
508 if(ret) {
509 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
510 fclose(fp_svg); remove(svgfile);
511 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
512 free(dftl);
513 return(13);
514 }
515
516 /*
517 * Put the axis titles into their own viewports
518 */
519 if(verbose>1) printf("creating axis titles\n");
520 /* y axis */
521 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, errmsg, verbose-4);
522 if(ret) {
523 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
524 fclose(fp_svg); remove(svgfile);
525 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
526 free(dftl);
527 return(14);
528 }
529 /* x axis */
530 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, errmsg, verbose-6);
531 if(ret) {
532 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
533 fclose(fp_svg); remove(svgfile);
534 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
535 free(dftl);
536 return(13);
537 }
538
539 /*
540 * Put the plot into its own viewport
541 */
542 if(verbose>1) printf("starting plot viewport\n");
543 ret=svg_start_plot_viewport(fp_svg, &viewports, errmsg, verbose-9);
544 if(ret) {
545 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
546 fclose(fp_svg); remove(svgfile);
547 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
548 free(dftl);
549 return(21);
550 }
551
552 /*
553 * Start coordinate area viewport
554 */
555 if(verbose>1) printf("starting coordinate area viewport\n");
556 ret=svg_start_coordinate_viewport(fp_svg, &viewports, errmsg, verbose-9);
557 if(ret) {
558 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
559 fclose(fp_svg); remove(svgfile);
560 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
561 free(dftl);
562 return(22);
563 }
564
565 /* Write plot axes */
566 if(verbose>1) printf("writing axes\n");
567 ret=svg_write_axes(fp_svg, &viewports, errmsg, verbose-9);
568 if(ret) {
569 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
570 fclose(fp_svg); remove(svgfile);
571 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
572 free(dftl);
573 return(23);
574 }
575
576 /*
577 * Plot the TACs
578 */
579 if(verbose>1) printf("plotting the TACs\n");
580 if(color_scale==2) { // monochrome
581 max_color_nr=1;
582 } else { // color and grayscale
583 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
584 }
585 if(verbose>1) printf("max_color_nr := %d\n", max_color_nr);
586 max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
587 if(verbose>1) printf("max_symbol_nr := %d\n", max_symbol_nr);
588 /* Start with filled symbols if colors are used, and with open symbols in case of monochrome */
589 if(color_scale==0) symbol_fill=1; else symbol_fill=0;
590 /* Check if equal nr of curves with symbols and lines, and nothing else,
591 then we will use same color for symbols and lines, and only make one common legend */
592 n=nl=ns=0;
593 for(ti=0, n=0; ti<fileNr; ti++) for(ri=0; ri<dftl[ti].dft.voiNr; ri++) {
594 n++; if(dftl[ti].type==1) nl++; else if(dftl[ti].type==2) ns++;}
595 if(nl==ns && n==(nl+ns)) plot_fit=1;
596 if(verbose>1) printf("plot_fit := %d\n", plot_fit);
597 /* plot */
598 for(ti=0, n=0, color_nr=color_nr2=0, symbol_nr=0; ti<fileNr; ti++) { // each TAC file
599 if(verbose>8) printf("ti := %d\n", ti);
600 if(dftl[ti].dft.voiNr>1) color_nr=color_nr2=1; //else color_nr=0;
601 if(verbose>5) printf("type := %d\n", dftl[ti].type);
602 for(ri=0; ri<dftl[ti].dft.voiNr; ri++) { // each TAC in this TAC file
603 if(verbose>8) {
604 printf(" ri := %d\n", ri);
605 printf(" color1 := %d\n", color_nr%max_color_nr);
606 printf(" color2 := %d\n", color_nr2%max_color_nr);
607 }
608 sprintf(tac_id, "plot_%d", n);
609 if(use_studynr==0) strcpy(tac_title, "");
610 else strcpy(tac_title, dftl[ti].dft.studynr);
611 if(use_studynr!=0 && use_tacname!=0) strcat(tac_title, ": ");
612 if(use_tacname!=0) {
613 rnameRmDots(dftl[ti].dft.voi[ri].name, temp);
614 strcat(tac_title, temp);
615 }
616
617 if(plot_fit==0 || dftl[ti].type!=1) { // using color1
618 ret=svg_write_tac(fp_svg, &viewports, dftl[ti].type, tac_id, tac_title,
619 dftl[ti].dft.x, dftl[ti].dft.voi[ri].y, dftl[ti].dft.frameNr,
620 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, symbol_fill,
621 errmsg, verbose-9);
622 } else { // using color2
623 ret=svg_write_tac(fp_svg, &viewports, dftl[ti].type, tac_id, tac_title,
624 dftl[ti].dft.x, dftl[ti].dft.voi[ri].y, dftl[ti].dft.frameNr,
625 svgColorName(color_nr2%max_color_nr), symbol_nr%max_symbol_nr, symbol_fill,
626 errmsg, verbose-9);
627 }
628 if(ret) {
629 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
630 fclose(fp_svg); remove(svgfile);
631 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
632 free(dftl);
633 svg_legend_empty(&legends); return(22);
634 }
635
636 /* Set legend too, if requested */
637 if(is_label!=0) {
638 if(plot_fit==0) // not fit plotting mode, thus plot legends as requested
639 svg_legend_add(&legends, dftl[ti].type, symbol_nr%max_symbol_nr, symbol_fill,
640 color_nr%max_color_nr, tac_title);
641 else if(dftl[ti].type!=1) // fit plotting mode, plot legends with both symbols with lines
642 svg_legend_add(&legends, 0, symbol_nr%max_symbol_nr, symbol_fill,
643 color_nr%max_color_nr, tac_title);
644 }
645
646 /* Prepare for the next TAC */
647 if(plot_fit==0) {
648 color_nr++;
649 symbol_nr++;
650 } else {
651 if(dftl[ti].type!=1) {
652 color_nr++;
653 symbol_nr++;
654 } else {
655 color_nr2++;
656 }
657 }
658
659 /* If black-and-white and all symbols consumed, then switch between open and filled symbols */
660 if(color_scale==2 && symbol_nr==max_symbol_nr) {
661 if(symbol_fill==0) symbol_fill=1; else symbol_fill=0;
662 symbol_nr=0;
663 }
664 /* If all colors and symbols consumed, then switch between open and filled symbols */
665 if(color_scale==0 && color_nr==max_color_nr && symbol_nr==max_symbol_nr) {
666 if(symbol_fill==0) symbol_fill=1; else symbol_fill=0;
667 color_nr=symbol_nr=0;
668 }
669 n++;
670 } /* next region TAC */
671 } /* next DFT */
672
673
674 /* Close the coordinate viewport */
675 if(verbose>1) printf("closing coordinate area viewport\n");
676 ret=svg_end_coordinate_viewport(fp_svg, errmsg, verbose-8);
677 if(ret) {
678 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
679 fclose(fp_svg); remove(svgfile);
680 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
681 free(dftl);
682 svg_legend_empty(&legends); return(28);
683 }
684
685 /* Write the axis ticks */
686 if(verbose>1) printf("writing axis ticks\n");
687 if(svg_write_xticks(fp_svg, &viewports, errmsg, verbose-8)!=0) {
688 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
689 fclose(fp_svg); remove(svgfile);
690 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
691 free(dftl);
692 svg_legend_empty(&legends); return(29);
693 }
694 if(svg_write_yticks(fp_svg, &viewports, errmsg, verbose-8)!=0) {
695 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
696 fclose(fp_svg); remove(svgfile);
697 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
698 free(dftl);
699 svg_legend_empty(&legends); return(30);
700 }
701
702 /* Close the plot viewport */
703 if(verbose>1) printf("closing plot viewport\n");
704 ret=svg_end_plot_viewport(fp_svg, errmsg, verbose-7);
705 if(ret) {
706 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
707 fclose(fp_svg); remove(svgfile);
708 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
709 free(dftl);
710 svg_legend_empty(&legends); return(41);
711 }
712
713 /*
714 * Make the plot legends into their own viewport
715 */
716 if(viewports.label_area_viewport.is!=0) {
717 if(verbose>1) printf("creating plot legends\n");
718 ret=svg_create_legends(fp_svg, &viewports, &legends, errmsg, verbose-6);
719 if(ret) {
720 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
721 fclose(fp_svg); remove(svgfile);
722 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
723 free(dftl);
724 svg_legend_empty(&legends); return(51);
725 }
726 }
727 svg_legend_empty(&legends);
728
729
730 /* TAC data is not needed anymore */
731 for(ti=0; ti<fileNr; ti++) dftEmpty(&dftl[ti].dft);
732 free(dftl);
733
734
735 /* Close the SVG file */
736 if(verbose>1) printf("closing the file\n");
737 if(do_XHTML) {
738 ret=svg_xhtml_svg_close(fp_svg, errmsg, verbose-8);
739 if(ret) {
740 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
741 return(61);
742 }
743 ret=svg_xhtml_close(fp_svg, errmsg, verbose-8);
744 if(ret) {
745 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
746 return(62);
747 }
748 } else {
749 ret=svg_close(fp_svg, errmsg, verbose-6);
750 if(ret) {
751 fprintf(stderr, "Error in creating %s: %s\n", svgfile, errmsg);
752 return(61);
753 }
754 }
755 if(verbose>0) printf(" %s written.\n", svgfile);
756
757 return(0);
758}
759/*****************************************************************************/
760
761/*****************************************************************************/
int backupExistingFile(char *filename, char *backup_ext, char *status)
Definition backup.c:14
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
int dftMinMax(DFT *dft, double *minx, double *maxx, double *miny, double *maxy)
Definition dft.c:974
int dftMaxY(DFT *dft, double t1, double t2, double *miny, double *maxy)
Definition dft.c:1090
void dftEmpty(DFT *data)
Definition dft.c:20
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
void dftPrint(DFT *data)
Definition dftio.c:538
int dftUnitConversion(DFT *dft, int dunit)
Definition dftunit.c:25
int dftTimeunitConversion(DFT *dft, int tunit)
Definition dftunit.c:119
Header file for libtpccurveio.
Header file for libtpcmisc.
int rnameRmDots(char *rname1, char *rname2)
Definition rname.c:99
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
char * petTunit(int tunit)
Definition petunits.c:226
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
int studynr_from_fname(char *fname, char *studynr)
Definition studynr.c:119
int strnCopyClean(char *str1, const char *str2, int maxlen)
Definition quots.c:52
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
Header file for libtpcmodel.
Header file for libtpcsvg.
void svg_legend_empty(SVG_LEGENDS *legends)
Definition svg_legend.c:26
int svg_write_xticks(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:555
void svg_init_legends(SVG_LEGENDS *legends)
Definition svg_legend.c:14
FILE * svg_xhtml_initiate(const char *filename, const char *XHTML_title, char *errmsg, int verbose)
Definition svg_file.c:131
int svg_xhtml_svg_open(FILE *fp, const double height, const double width, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_file.c:231
int svg_create_xaxis_title(FILE *fp, const char *title_text, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_title.c:126
char * svgColorName(const svgColor index)
Definition svg_defs.c:38
int svg_create_main_title(FILE *fp, const char *main_title_text, const char *sub_title_text, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_title.c:17
int svg_legend_add(SVG_LEGENDS *legends, const int plot_type, const int symbol_type, const svgSymbolFill symbol_fill, const int color, const char *text)
Definition svg_legend.c:43
char * svgSymbolName(const svgSymbolType index)
Definition svg_defs.c:67
int svg_xhtml_close(FILE *fp, char *errmsg, int verbose)
Definition svg_file.c:206
int svg_define_viewports(const int main_viewport_width, const int main_viewport_height, const int is_main_title, const int is_yaxis_title, const int is_xaxis_title, const int is_label_area, struct svg_viewports *vp, int verbose)
Definition svg_vport.c:65
int svg_end_plot_viewport(FILE *fp, char *errmsg, int verbose)
Definition svg_plot.c:238
int svg_start_coordinate_viewport(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:276
int svg_create_legends(FILE *fp, struct svg_viewports *vp, SVG_LEGENDS *legends, char *errmsg, int verbose)
Definition svg_legend.c:76
void svg_init_viewports(struct svg_viewports *p)
Definition svg_vport.c:43
FILE * svg_initiate(const char *filename, const double height, const double width, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_file.c:22
int svg_calculate_axes(struct svg_viewports *vp, int verbose)
Definition svg_plot.c:364
int svg_write_axes(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:437
int svg_end_coordinate_viewport(FILE *fp, char *errmsg, int verbose)
Definition svg_plot.c:327
int svg_start_plot_viewport(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:181
int svg_create_yaxis_title(FILE *fp, const char *title_text, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_title.c:197
int svg_write_yticks(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:655
int svg_write_tac(FILE *fp, struct svg_viewports *vp, const int plot_type, const char *tac_id, const char *tac_title, double *x, double *y, const int data_nr, const char *color, const svgSymbolType symbol_type, const svgSymbolFill symbol_fill, char *errmsg, int verbose)
Definition svg_plot.c:746
int svg_xhtml_svg_close(FILE *fp, char *errmsg, int verbose)
Definition svg_file.c:283
int svg_close(FILE *fp, char *errmsg, int verbose)
Definition svg_file.c:107