1

TL;DR

Is there a way to align corners of different plots in a multiplot setup?

Is there a way to convert axis coordinates to screen coordinates?

Detailed explanation

I'm trying to layout a quite complicated canvas with gnuplot. To achieve what I want, I need to stack different plots on each other exactly.

I did something like :

reset;
set samples 20;
set xrange [-pi:pi]; set yrange [-2:1];
set xlabel "x"; set ylabel "y";
unset key

set multiplot;
plot cos(x) w lp;
plot 2*cos(x+pi) w lp;
unset multiplot;

However, some components like the label, tics and borders are drawn twice. Then, when I do this with the cairolatex terminal the result is not as clear as if I don't stack plots.

Thus, I would like to draw these components for the first plot and then unset labels, tics and borders for the subsequent ones as shown in the snippet below:

set multiplot;
plot cos(x) w lp;

set border ls 4; # Just to distinguish it
unset xlabel; unset ylabel;
unset tics;
plot 2*cos(x+pi) w lp;
unset multiplot;

This generate an image where the next plots are not aligned (on left and bottom) with the first one, as no space is taken by the labels and tics.

Not aligned borders

To address this issue, I need to set the origin and size of the next plots manually. The bottom left corners must be aligned.

From the gnuplot documentation, it is possible the get the screen coordinated of an (X,Y) axis coordinate using:

GRAPH_X = (X - GPVAL_X_MIN) / (GPVAL_X_MAX - GPVAL_X_MIN)
GRAPH_Y = (Y - GPVAL_Y_MIN) / (GPVAL_Y_MAX - GPVAL_Y_MIN)
SCREEN_X = GPVAL_TERM_XMIN + GRAPH_X * (GPVAL_TERM_XMAX - GPVAL_TERM_XMIN)
SCREEN_Y = GPVAL_TERM_YMIN + GRAPH_Y * (GPVAL_TERM_YMAX - GPVAL_TERM_YMIN)
FRAC_X = SCREEN_X * GPVAL_TERM_SCALE / GPVAL_TERM_XSIZE
FRAC_Y = SCREEN_Y * GPVAL_TERM_SCALE / GPVAL_TERM_YSIZE

As we are trying to align the bottom left corner, (X,Y) == (GPVAL_X_MIN, GPVAL_Y_MIN). Thus, GRAPH_* = 0 and SCREEN_(*) = GPVAL_TERM_\1MIN. Thus:

# Multiply by 1.0 to promote variables to floats
FRAC_X = 1.0 * GPVAL_TERM_XMIN * GPVAL_TERM_SCALE / GPVAL_TERM_XSIZE
FRAC_Y = 1.0 * GPVAL_TERM_YMIN * GPVAL_TERM_SCALE / GPVAL_TERM_YSIZE

Resulting snippet:

set multiplot;
plot cos(x) w lp;

FRAC_X = 1.0 * GPVAL_TERM_XMIN * GPVAL_TERM_SCALE / GPVAL_TERM_XSIZE;
FRAC_Y = 1.0 * GPVAL_TERM_YMIN * GPVAL_TERM_SCALE / GPVAL_TERM_YSIZE;
set origin FRAC_X, FRAC_Y;

set border ls 4; # Just to distinguish it
unset xlabel; unset ylabel;
unset tics;
plot 2*cos(x+pi) w lp;
unset multiplot;

But as you can see, resulting plot is not better...

Origin not matching

By the way, I did not find how to define the size to align the top right corners.

Questions

What is wrong with the origin computation? How to align top right corner as well?

Kind regards,

Alexis.

AlexisBRENON
  • 2,921
  • 2
  • 18
  • 30
  • Why do you need to overlap the two plots, for your given example you could simply use `plot cos(x) w lp, 2*cos(x+pi) w lp` – Christoph May 18 '17 at 11:07
  • For this simple example, for sure your answer is the right way to do it. However my problem is related to http://stackoverflow.com/q/43996765/4373898 which need overlapping plots. – AlexisBRENON May 18 '17 at 11:52

2 Answers2

1

You can fix the margins to keep the automatic size after the first plot as follows (see also https://stackoverflow.com/a/19132068/2604213):

fix_margins = 'set margins '.\
    'screen GPVAL_TERM_SCALE * GPVAL_TERM_XMIN/(1.0*GPVAL_TERM_XSIZE), '.\
    'screen GPVAL_TERM_SCALE * GPVAL_TERM_XMAX/(1.0*GPVAL_TERM_XSIZE), '.\
    'screen GPVAL_TERM_SCALE * GPVAL_TERM_YMIN/(1.0*GPVAL_TERM_YSIZE), '.\
    'screen GPVAL_TERM_SCALE * GPVAL_TERM_YMAX/(1.0*GPVAL_TERM_YSIZE)'

set samples 20
set xrange [-pi:pi]; set yrange [-2:1]
set xlabel "x"; set ylabel "y"
unset key

set multiplot
plot cos(x) w lp
eval(fix_margins)
unset tics; unset xlabel; unset ylabel
plot 2*cos(x+pi) w lp
unset multiplot
Community
  • 1
  • 1
Christoph
  • 47,569
  • 8
  • 87
  • 187
  • Thanks for the answer. This seems even easier than what I proposed! However plots do not superpose exactly, there is something like 1 or 2 pixels of difference. I suppose that it is due to some floating point approximation. – AlexisBRENON May 18 '17 at 19:59
0

In order to achieve an exact overlap, I think that an option would be to adjust the margin manually:

set terminal pngcairo
set output 'fig.png'

eps_h = 0.1
eps_w = 0.1

set multiplot
unset key

set lmargin at screen 2*eps_w
set tmargin at screen 1 - eps_h
set rmargin at screen 1 - eps_w
set bmargin at screen eps_h

plot cos(x) w lp lc rgb 'dark-red'

set border ls 4;
unset xlabel
unset ylabel
unset tics

plot 2*cos(x+pi) w lp lc rgb 'royalblue'

which gives: enter image description here

ewcz
  • 12,819
  • 1
  • 25
  • 47