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

Plot measured and fitted TACs in SVG format. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "tpcextensions.h"
#include "tpctac.h"
#include "libtpcsvg.h"
#include "tpctacmod.h"

Go to the source code of this file.

Functions

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)
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)
int mtgaPlotSVG (MTAC *mtac, const char *main_title, const char *fname, TPCSTATUS *status)

Detailed Description

Plot measured and fitted TACs in SVG format.

Author
Vesa Oikonen

Definition in file tacfitplot.c.

Function Documentation

◆ mtgaPlotSVG()

int mtgaPlotSVG ( MTAC * mtac,
const char * main_title,
const char * fname,
TPCSTATUS * status )

MTGA plots in SVG format.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacPlotLineSVG, tacPlotFitSVG
Author
Vesa Oikonen
Parameters
mtacPointer to MTAC structure, which contains plot data of tissue regions, each in its own TAC structure. TAC must contain the plot x axis values, and three y columns: points included in regression, points not included, and points representing the fitted line.
main_titleString for plot main title, or "".
fnameSVG file name.
statusPointer to status data; enter NULL if not needed.

Definition at line 489 of file tacfitplot.c.

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}
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
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
double * x
Definition tpctac.h:97
int sampleNr
Definition tpctac.h:89
TACC * c
Definition tpctac.h:117
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 tacSampleXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:162
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
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_OK
No error.
@ TPCERROR_INVALID_FILENAME
Invalid file name.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_CANNOT_WRITE
Cannot write file.

◆ tacPlotFitSVG()

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 )

Writes specified range of plots of original and fitted TACs in SVG format.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacPlotLineSVG, mtgaPlotSVG
Author
Vesa Oikonen
Parameters
tac1Measured data points. Frame mid times must be set.
tac2Fitted data points. Times can be different but unit must be the same as in tac1.
main_titleString for plot main title, or "".
x1Start time; NaN if determined from data.
x2End time; NaN if determined from data.
y1Minimum y value; NaN if determined from data.
y2Maximum y value; NaN if determined from data.
fnameSVG file name.
statusPointer to status data; enter NULL if not needed.

Definition at line 27 of file tacfitplot.c.

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}
unit cunit
Definition tpctac.h:105
unit tunit
Definition tpctac.h:109
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
@ UNIT_UNKNOWN
Unknown unit.
@ TPCERROR_INVALID_XRANGE
Invalid sample time range.
@ TPCERROR_INCOMPATIBLE_DATA
Incompatible data.
char * unitName(int unit_code)
Definition units.c:143
int unitIsTime(int u)
Definition units.c:359

◆ tacPlotLineSVG()

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 )

Writes specified range of line plots of TACs in SVG format.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacPlotFitSVG, mtgaPlotSVG
Author
Vesa Oikonen
Parameters
tacTAC data points.
main_titleString for plot main title, or "".
x1Start time; NaN if determined from data.
x2End time; NaN if determined from data.
y1Minimum y value; NaN if determined from data.
y2Maximum y value; NaN if determined from data.
fnameSVG file name.
statusPointer to status data; enter NULL if not needed.

Definition at line 273 of file tacfitplot.c.

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}