TPCCLIB
Loading...
Searching...
No Matches
tacfitplot.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6#include "tpcclibConfig.h"
7/*****************************************************************************/
8#include <stdio.h>
9#include <stdlib.h>
10#include <math.h>
11#include <time.h>
12#include <string.h>
13/*****************************************************************************/
14#include "tpcextensions.h"
15#include "tpctac.h"
16#include "libtpcsvg.h"
17/*****************************************************************************/
18#include "tpctacmod.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
29 TAC *tac1,
31 TAC *tac2,
33 const char *main_title,
35 const double x1,
37 const double x2,
39 const double y1,
41 const double y2,
43 const char *fname,
45 TPCSTATUS *status
46) {
47 int verbose=0; if(status!=NULL) verbose=status->verbose;
48 if(verbose>0) printf("%s()\n", __func__);
49 /* Check data */
50 if(tac1==NULL || tac2==NULL || tac1->tacNr<1 || tac2->tacNr<1 ||
51 tac1->sampleNr<1 || tac2->sampleNr<1)
52 {
53 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
54 return TPCERROR_NO_DATA;
55 }
56 if(fname==NULL || strnlen(fname, 1)<1) {
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
59 }
60 if(tac1->tacNr!=tac2->tacNr) {
61 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_DATA);
63 }
64 if(status!=NULL && status->forgiving==0) {
65 // any strict tests in here
66 }
67
68 int ret, n, ri, si, ei;
69 char x_title[64], y_title[64], tac_id[32], tac_title[64];
70 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2, f;
71 struct svg_viewports viewports; svg_init_viewports(&viewports);
72 int max_color_nr=0, color_nr=0;
73 int max_symbol_nr=0, symbol_nr=0;
74 SVG_LEGENDS legends; svg_init_legends(&legends);
75 FILE *fp_svg=NULL;
76
77 int is_label=0; if(tac1->tacNr>1) is_label=1;
78
79 /* Determine the plot min and max x values */
80 if(tacSampleXRange(tac1, &tx1, &tx2)) {
81 if(verbose>0) {printf(" tac1 failed\n"); fflush(stdout);}
82 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
84 }
85 minx=tx1; maxx=tx2;
86 if(tacSampleXRange(tac2, &tx1, &tx2)) {
87 if(verbose>0) {printf(" tac2 failed\n"); fflush(stdout);}
88 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
90 }
91 if(minx>tx1) minx=tx1;
92 if(maxx<tx2) maxx=tx2;
93 if(minx>0.0) {double f=maxx-minx; minx-=0.05*f; if(minx<0.0) minx=0.0;}
94 if(!isnan(x1)) minx=x1;
95 if(!isnan(x2)) maxx=x2;
96 if(verbose>10) printf(" minx := %g\n maxx:=%g\n", minx, maxx);
97
98 /* Determine the plot min and max y values inside the x range */
99 if(tacYRangeInXRange(tac1, -1, minx, maxx, &ty1, &ty2, NULL, NULL, NULL, NULL)) {
100 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
102 }
103 miny=ty1; maxy=ty2;
104 if(tacYRangeInXRange(tac2, -1, minx, maxx, &ty1, &ty2, NULL, NULL, NULL, NULL)) {
105 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
107 }
108 if(miny>ty1) miny=ty1;
109 if(maxy<ty2) maxy=ty2;
110 if(miny>0.0) {f=maxy-miny; miny-=0.05*f; if(miny<0.0) miny=0.0;}
111 if(!isnan(y1)) miny=y1;
112 if(!isnan(y2)) maxy=y2;
113 if(verbose>1) printf(" miny := %g\n maxy:=%g\n", miny, maxy);
114
115 /* Calculate the axis ticks */
116 viewports.x.min=minx; viewports.x.max=maxx;
117 viewports.y.min=miny; viewports.y.max=maxy;
118 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
119 ret=svg_calculate_axes(&viewports, verbose-11);
120 if(ret) {
121 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
123 }
124
125 /* Set x and y axis titles based on activity and time units */
126 strcpy(x_title, "");
127 if(unitIsTime(tac1->tunit))
128 sprintf(x_title, "Time (%s)", unitName(tac1->tunit));
129 else if(tac1->tunit!=UNIT_UNKNOWN)
130 strcpy(x_title, unitName(tac1->tunit));
131 strcpy(y_title, "");
132 if(tac1->cunit!=UNIT_UNKNOWN) strcpy(y_title, unitName(tac1->cunit));
133
134 /* Set the plot window and window area sizes */
135 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
136 strlen(x_title), is_label, &viewports, verbose-13);
137 if(ret) {
138 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
140 }
141
142 /* Initiate graphics file */
143 fp_svg=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-13);
144 if(fp_svg==NULL) {
145 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
147 }
148
149 /* Put the graph titles into their own viewports */
150 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, NULL,verbose-13);
151 if(!ret)
152 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, NULL, verbose-13);
153 if(!ret)
154 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, NULL, verbose-13);
155
156 /* Put the plot into its own viewport */
157 if(!ret)
158 ret=svg_start_plot_viewport(fp_svg, &viewports, NULL, verbose-13);
159
160 /* Start coordinate area viewport */
161 if(!ret)
162 ret=svg_start_coordinate_viewport(fp_svg, &viewports, NULL, verbose-13);
163
164 /* Write plot axes */
165 if(!ret) ret=svg_write_axes(fp_svg, &viewports, NULL, verbose-13);
166
167 if(ret) {
168 fclose(fp_svg);
169 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
171 }
172
173 /*
174 * Draw the plots
175 */
176 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
177 if(verbose>3) printf("max_color_nr := %d\n", max_color_nr);
178 max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
179 if(verbose>3) printf("max_symbol_nr := %d\n", max_symbol_nr);
180 if(tac1->tacNr==1) color_nr=0; else color_nr=1;
181 symbol_nr=0;
182 for(ri=0, n=0; ri<tac1->tacNr; ri++) {
183 sprintf(tac_id, "plot_%d", n);
184 strcpy(tac_title, tac1->c[ri].name);
185 /* Draw the fitted line */
186 for(si=0; si<tac2->sampleNr; si++) if(!isnan(tac2->c[ri].y[si])) break;
187 for(ei=tac2->sampleNr-1; ei>=si; ei--) if(!isnan(tac2->c[ri].y[ei])) break;
188 if((ei-si)>0) {
189 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
190 tac2->x+si, tac2->c[ri].y+si, 1+ei-si,
191 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLOPEN,
192 NULL, verbose-13);
193 if(ret) {
194 svg_legend_empty(&legends); fclose(fp_svg);
195 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
197 }
198 }
199 /* Draw the measured points */
200 ret=svg_write_tac(fp_svg, &viewports, 2, tac_id, tac_title,
201 tac1->x, tac1->c[ri].y, tac1->sampleNr,
202 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
203 NULL, verbose-13);
204 if(ret) {
205 svg_legend_empty(&legends); fclose(fp_svg);
206 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
208 }
209 /* Set legend too, if requested */
210 if(is_label!=0) {
211 int si=0, ci=0; // remainder works only if 2nd operator > 0
212 if(max_symbol_nr>0) si=symbol_nr%max_symbol_nr;
213 if(max_color_nr>0) ci=color_nr%max_color_nr;
214
215 svg_legend_add(&legends, 0, si, SYMBOLFILLED, ci, tac_title);
216 }
217 /* Prepare for the next plot */
218 color_nr++; n++;
219 if(color_nr==max_color_nr) {symbol_nr++; color_nr=0;}
220 if(symbol_nr==max_symbol_nr) symbol_nr=0;
221 }
222
223 /* Close the coordinate viewport */
224 ret=svg_end_coordinate_viewport(fp_svg, NULL, verbose-13);
225
226 /* Write the axis ticks */
227 if(!ret) {
228 if(svg_write_xticks(fp_svg, &viewports, NULL, verbose-13)!=0) ret=1;}
229 if(!ret) {
230 if(svg_write_yticks(fp_svg, &viewports, NULL, verbose-13)!=0) ret=1;}
231
232 /* Close the plot viewport */
233 if(!ret) ret=svg_end_plot_viewport(fp_svg, NULL, verbose-13);
234
235 if(ret) {
236 fclose(fp_svg); svg_legend_empty(&legends);
237 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
239 }
240
241 /* Make the plot legends into their own viewport */
242 ret=0;
243 if(viewports.label_area_viewport.is!=0) {
244 if(verbose>2) printf("creating plot legends\n");
245 ret=svg_create_legends(fp_svg, &viewports, &legends, NULL, verbose-13);
246 }
247 svg_legend_empty(&legends);
248 if(ret) {
249 fclose(fp_svg);
250 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
252 }
253
254 /* Close the SVG file */
255 ret=svg_close(fp_svg, NULL, verbose-13);
256 if(ret) {
257 fclose(fp_svg);
258 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
260 }
261
262 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
263 return(TPCERROR_OK);
264}
265/*****************************************************************************/
266
267/*****************************************************************************/
275 TAC *tac,
277 const char *main_title,
279 const double x1,
281 const double x2,
283 const double y1,
285 const double y2,
287 const char *fname,
289 TPCSTATUS *status
290) {
291 int verbose=0; if(status!=NULL) verbose=status->verbose;
292 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
293 /* Check data */
294 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
295 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
296 return TPCERROR_NO_DATA;
297 }
298 if(fname==NULL || strnlen(fname, 1)<1) {
299 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
301 }
302 if(status!=NULL && status->forgiving==0) {
303 // any strict tests in here
304 }
305
306 int ret, n, ri, si, ei;
307 char x_title[64], y_title[64], tac_id[32], tac_title[64];
308 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2, f;
309 struct svg_viewports viewports; svg_init_viewports(&viewports);
310 unsigned int max_color_nr=0, color_nr=0;
311 unsigned int max_symbol_nr=0, symbol_nr=0;
312 SVG_LEGENDS legends; svg_init_legends(&legends);
313 FILE *fp_svg=NULL;
314
315
316 int is_label=0; if(tac->tacNr>1) is_label=1;
317
318 /* Determine the plot min and max x values */
319 if(tacSampleXRange(tac, &tx1, &tx2)) {
320 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
322 }
323 minx=tx1; maxx=tx2;
324 if(minx>0.0) {double f=maxx-minx; minx-=0.05*f; if(minx<0.0) minx=0.0;}
325 if(!isnan(x1)) minx=x1;
326 if(!isnan(x2)) maxx=x2;
327 if(verbose>1) {
328 printf(" minx := %g\n maxx := %g\n", minx, maxx); fflush(stdout);}
329
330 /* Determine the plot min and max y values inside the x range */
331 if(tacYRangeInXRange(tac, -1, minx, maxx, &ty1, &ty2, NULL, NULL, NULL, NULL)) {
332 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
334 }
335 miny=ty1; maxy=ty2;
336 if(miny>0.0) {f=maxy-miny; miny-=0.05*f; if(miny<0.0) miny=0.0;}
337 if(!isnan(y1)) miny=y1;
338 if(!isnan(y2)) maxy=y2;
339 if(verbose>1) {
340 printf(" miny := %g\n maxy := %g\n", miny, maxy); fflush(stdout);}
341
342 /* Calculate the axis ticks */
343 viewports.x.min=minx; viewports.x.max=maxx;
344 viewports.y.min=miny; viewports.y.max=maxy;
345 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
346 ret=svg_calculate_axes(&viewports, verbose-3);
347 if(ret) {
348 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
350 }
351
352 /* Set x and y axis titles based on activity and time units */
353 strcpy(x_title, "");
354 if(unitIsTime(tac->tunit))
355 sprintf(x_title, "Time (%s)", unitName(tac->tunit));
356 else if(tac->tunit!=UNIT_UNKNOWN)
357 strcpy(x_title, unitName(tac->tunit));
358 strcpy(y_title, "");
359 if(tac->cunit!=UNIT_UNKNOWN) strcpy(y_title, unitName(tac->cunit));
360
361 /* Set the plot window and window area sizes */
362 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
363 strlen(x_title), is_label, &viewports, verbose-3);
364 if(ret) {
365 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
367 }
368
369 /* Initiate graphics file */
370 fp_svg=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-3);
371 if(fp_svg==NULL) {
372 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
374 }
375
376 /* Put the graph titles into their own viewports */
377 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, NULL,verbose-3);
378 if(!ret)
379 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, NULL, verbose-3);
380 if(!ret)
381 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, NULL, verbose-3);
382
383 /* Put the plot into its own viewport */
384 if(!ret)
385 ret=svg_start_plot_viewport(fp_svg, &viewports, NULL, verbose-3);
386
387 /* Start coordinate area viewport */
388 if(!ret)
389 ret=svg_start_coordinate_viewport(fp_svg, &viewports, NULL, verbose-3);
390
391 /* Write plot axes */
392 if(!ret) ret=svg_write_axes(fp_svg, &viewports, NULL, verbose-3);
393
394 if(ret) {
395 fclose(fp_svg);
396 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
398 }
399
400 /*
401 * Draw the plots
402 */
403 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
404 if(verbose>3) {printf("max_color_nr := %d\n", max_color_nr); fflush(stdout);}
405 if(tac->tacNr==1) color_nr=0; else color_nr=1;
406 symbol_nr=0;
407 for(ri=0, n=0; ri<tac->tacNr; ri++) {
408 sprintf(tac_id, "plot_%d", n);
409 strcpy(tac_title, tac->c[ri].name);
410 /* Draw the line */
411 for(si=0; si<tac->sampleNr; si++) if(!isnan(tac->c[ri].y[si])) break;
412 for(ei=tac->sampleNr-1; ei>=si; ei--) if(!isnan(tac->c[ri].y[ei])) break;
413 if((ei-si)>0) {
414 unsigned int ci, si; // remainder works only if 2nd operator > 0
415 if(max_color_nr<1) ci=0; else ci=color_nr % max_color_nr;
416 if(max_symbol_nr<1) si=0; else si=symbol_nr % max_symbol_nr;
417 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
418 tac->x+si, tac->c[ri].y+si, 1+ei-si,
419 svgColorName(ci), si, SYMBOLFILLED,
420 NULL, verbose-3);
421 if(ret) {
422 svg_legend_empty(&legends); fclose(fp_svg);
423 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
425 }
426 }
427 /* Set legend too, if requested */
428 if(is_label!=0) {
429 unsigned int ci, si; // remainder works only if 2nd operator > 0
430 if(max_color_nr<1) ci=0; else ci=color_nr % max_color_nr;
431 if(max_symbol_nr<1) si=0; else si=symbol_nr % max_symbol_nr;
432 svg_legend_add(&legends, 0, si, SYMBOLFILLED, ci, tac_title);
433 }
434 /* Prepare for the next plot */
435 color_nr++; n++;
436 if(color_nr==max_color_nr) color_nr=0;
437 }
438
439 /* Close the coordinate viewport */
440 ret=svg_end_coordinate_viewport(fp_svg, NULL, verbose-3);
441
442 /* Write the axis ticks */
443 if(!ret) {
444 if(svg_write_xticks(fp_svg, &viewports, NULL, verbose-3)!=0) ret=1;}
445 if(!ret) {
446 if(svg_write_yticks(fp_svg, &viewports, NULL, verbose-3)!=0) ret=1;}
447
448 /* Close the plot viewport */
449 if(!ret) ret=svg_end_plot_viewport(fp_svg, NULL, verbose-3);
450
451 if(ret) {
452 fclose(fp_svg); svg_legend_empty(&legends);
453 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
455 }
456
457 /* Make the plot legends into their own viewport */
458 ret=0;
459 if(viewports.label_area_viewport.is!=0) {
460 if(verbose>2) {printf("creating plot legends\n"); fflush(stdout);}
461 ret=svg_create_legends(fp_svg, &viewports, &legends, NULL, verbose-3);
462 }
463 svg_legend_empty(&legends);
464 if(ret) {
465 fclose(fp_svg);
466 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
468 }
469
470 /* Close the SVG file */
471 ret=svg_close(fp_svg, NULL, verbose-3);
472 if(ret) {
473 fclose(fp_svg);
474 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
476 }
477
478 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
479 return(TPCERROR_OK);
480}
481/*****************************************************************************/
482
483/*****************************************************************************/
494 MTAC *mtac,
496 const char *main_title,
498 const char *fname,
500 TPCSTATUS *status
501) {
502 int verbose=0; if(status!=NULL) verbose=status->verbose;
503 if(verbose>0) {printf("%s(MTAC, '%s', '%s')\n", __func__, main_title, fname); fflush(stdout);}
504 /* Check data */
505 if(mtac==NULL || mtac->nr<1) {
506 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
507 return TPCERROR_NO_DATA;
508 }
509 if(fname==NULL || strnlen(fname, 1)<1) {
510 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
512 }
513 if(status!=NULL && status->forgiving==0) {
514 // any strict tests in here
515 }
516 if(verbose>1) {printf("%d plot(s)\n", mtac->nr); fflush(stdout);}
517
518 /* Do we show plot legends? */
519 int is_label=0; if(mtac->nr>1) is_label=1;
520
521 /* Get the plot x and y range */
522 double minx=nan(""), maxx=nan(""), miny=nan(""), maxy=nan(""), maxly=nan("");
523 for(int i=0; i<mtac->nr; i++) {
524 if(mtac->tac[i].tacNr<3) continue;
525 double x1, x2, y1, y2;
526 if(tacSampleXRange(&mtac->tac[i], &x1, &x2)!=0) continue;
527 if(isfinite(x1) && !(x1>minx)) minx=x1;
528 if(isfinite(x2) && !(x2<maxx)) maxx=x2;
529 if(tacYRange(mtac->tac+i, -1, &y1, &y2, NULL, NULL, NULL, NULL)!=0) continue;
530 if(isfinite(y1) && !(y1>miny)) miny=y1;
531 if(isfinite(y2) && !(y2<maxy)) maxy=y2;
532 /* Get the y maximum from fitted line alone */
533 if(tacYRange(mtac->tac+i, 2, &y1, &y2, NULL, NULL, NULL, NULL)!=0) continue;
534 if(isfinite(y2) && !(y2<maxly)) maxly=y2;
535 }
536 if(verbose>1) {
537 printf("x-range := %g - %g\n", minx, maxx);
538 printf("y-range := %g - %g (%g for the line)\n", miny, maxy, maxly);
539 }
540 if(!(maxx>minx) || !(maxy>miny)) {
541 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
542 return TPCERROR_NO_DATA;
543 }
544 /* Limit the y range to maximal line value plus 1/40 of y range */
545 {
546 double yrange=maxy-miny;
547 double ylim=maxly+0.025*yrange;
548 if(maxy>ylim) maxy=ylim;
549 if(verbose>2) printf(" yrange := %g\n ylim := %g\n maxy := %g\n", yrange, ylim, maxy);
550 }
551
552 /* Start setting viewports */
553 struct svg_viewports viewports; svg_init_viewports(&viewports);
554 viewports.x.min=minx; viewports.x.max=maxx;
555 viewports.y.min=miny; viewports.y.max=maxy;
556 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
557
558 /* Calculate the axis ticks */
559 if(svg_calculate_axes(&viewports, verbose-3)) {
560 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
562 }
563
564 /* Set x and y axis titles based on activity and time units */
565 char x_title[64], y_title[64];
566 strcpy(x_title, ""); strcpy(y_title, "");
567
568 /* Set the plot window and window area sizes; ticks should be set before this */
569 if(svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
570 strlen(x_title), is_label, &viewports, verbose-3))
571 {
572 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
574 }
575
576 /* Initiate graphics file */
577 FILE *fp=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-3);
578 if(fp==NULL) {
579 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
581 }
582
583
584 /* Put the graph titles into their own viewports */
585 if(svg_create_main_title(fp, main_title, "", &viewports, NULL,verbose-3)) {
586 fclose(fp);
587 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
589 }
590 if(svg_create_yaxis_title(fp, y_title, &viewports, NULL, verbose-3)) {
591 fclose(fp);
592 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
594 }
595 if(svg_create_xaxis_title(fp, x_title, &viewports, NULL, verbose-3)) {
596 fclose(fp);
597 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
599 }
600
601 /* Put the plot into its own viewport */
602 if(svg_start_plot_viewport(fp, &viewports, NULL, verbose-3)) {
603 fclose(fp);
604 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
606 }
607
608 /* Start coordinate area viewport */
609 if(svg_start_coordinate_viewport(fp, &viewports, NULL, verbose-3)) {
610 fclose(fp);
611 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
613 }
614
615 /* Write plot axes */
616 if(svg_write_axes(fp, &viewports, NULL, verbose-3)) {
617 fclose(fp);
618 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
620 }
621
622
623 /*
624 * Draw the plots
625 */
626 SVG_LEGENDS legends; svg_init_legends(&legends);
627
628 int max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
629 if(verbose>3) {printf("max_color_nr := %d\n", max_color_nr); fflush(stdout);}
630 int color_nr; if(mtac->nr==1) color_nr=0; else color_nr=1;
631 int max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
632 if(verbose>3) printf("max_symbol_nr := %d\n", max_symbol_nr);
633 int n=0, symbol_nr=0;
634 for(int ri=0; ri<mtac->nr; ri++) {
635 if(mtac->tac[ri].tacNr<3) continue;
636 char tac_id[32], tac_title[64];
637 sprintf(tac_id, "plot_%d", n);
638 strcpy(tac_title, mtac->tac[ri].c[0].name);
639
640
641 /* Draw the measured points */
642 int ret=svg_write_tac(fp, &viewports, 2, tac_id, tac_title,
643 mtac->tac[ri].x, mtac->tac[ri].c[1].y, mtac->tac[ri].sampleNr,
644 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLOPEN,
645 NULL, verbose-3);
646 if(!ret) ret=svg_write_tac(fp, &viewports, 2, tac_id, tac_title,
647 mtac->tac[ri].x, mtac->tac[ri].c[0].y, mtac->tac[ri].sampleNr,
648 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
649 NULL, verbose-3);
650 /* Draw the regression line */
651 if(!ret) ret=svg_write_tac(fp, &viewports, 1, tac_id, tac_title,
652 mtac->tac[ri].x, mtac->tac[ri].c[2].y, mtac->tac[ri].sampleNr,
653 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLOPEN,
654 NULL, verbose-3);
655 if(ret) {
656 svg_legend_empty(&legends); fclose(fp);
657 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
659 }
660
661
662 /* Set legend too, if requested */
663 if(is_label!=0) {
664 unsigned int ci, si; // remainder works only if 2nd operator > 0
665 if(max_color_nr<1) ci=0; else ci=color_nr % max_color_nr;
666 if(max_symbol_nr<1) si=0; else si=symbol_nr % max_symbol_nr;
667 svg_legend_add(&legends, 0, si, SYMBOLFILLED, ci, tac_title);
668 }
669 /* Prepare for the next plot */
670 color_nr++; n++;
671 if(color_nr==max_color_nr) color_nr=0;
672 }
673
674
675
676 /* Close the coordinate viewport */
677 if(svg_end_coordinate_viewport(fp, NULL, verbose-3)) {
678 fclose(fp); svg_legend_empty(&legends);
679 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
681 }
682
683 /* Write the axis ticks */
684 if(svg_write_xticks(fp, &viewports, NULL, verbose-3)!=0 ||
685 svg_write_yticks(fp, &viewports, NULL, verbose-3)!=0)
686 {
687 fclose(fp); svg_legend_empty(&legends);
688 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
690 }
691
692 /* Close the plot viewport */
693 if(svg_end_plot_viewport(fp, NULL, verbose-3)) {
694 fclose(fp); svg_legend_empty(&legends);
695 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
697 }
698
699 /* Make the plot legends into their own viewport */
700 if(viewports.label_area_viewport.is!=0) {
701 if(verbose>2) {printf("creating plot legends\n"); fflush(stdout);}
702 int ret=svg_create_legends(fp, &viewports, &legends, NULL, verbose-3);
703 if(ret) {
704 fclose(fp); svg_legend_empty(&legends);
705 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
707 }
708 }
709 svg_legend_empty(&legends);
710
711 /* Close the SVG file */
712 if(svg_close(fp, NULL, verbose-3)) {
713 fclose(fp);
714 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
716 }
717
718 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
719 return(TPCERROR_OK);
720}
721/*****************************************************************************/
722
723/*****************************************************************************/
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
Definition tpctac.h:149
TAC * tac
Definition tpctac.h:151
int nr
Definition tpctac.h:153
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
Definition tpctac.h:87
double * x
Definition tpctac.h:97
int sampleNr
Definition tpctac.h:89
int cunit
Definition tpctac.h:105
TACC * c
Definition tpctac.h:117
int tunit
Definition tpctac.h:109
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
int forgiving
Force level, 0 for strict tests for data units etc.
int mtgaPlotSVG(MTAC *mtac, const char *main_title, const char *fname, TPCSTATUS *status)
Definition tacfitplot.c:489
int tacPlotLineSVG(TAC *tac, const char *main_title, const double x1, const double x2, const double y1, const double y2, const char *fname, TPCSTATUS *status)
Definition tacfitplot.c:273
int tacPlotFitSVG(TAC *tac1, TAC *tac2, const char *main_title, const double x1, const double x2, const double y1, const double y2, const char *fname, TPCSTATUS *status)
Definition tacfitplot.c:27
int tacSampleXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:162
int tacYRangeInXRange(TAC *d, int i, const double xmin, const double xmax, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct, including only samples with x (times) insid...
Definition tacy.c:99
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Definition tacy.c:26
Header file for library libtpcextensions.
@ UNIT_UNKNOWN
Unknown unit.
@ TPCERROR_INVALID_XRANGE
Invalid sample time range.
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_OK
No error.
@ TPCERROR_INVALID_FILENAME
Invalid file name.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_INCOMPATIBLE_DATA
Incompatible data.
@ TPCERROR_CANNOT_WRITE
Cannot write file.
char * unitName(int unit_code)
Definition units.c:143
int unitIsTime(int u)
Definition units.c:359
Header file for library libtpctac.
Header file for libtpctacmod.