Adding y-axis to multiple offset ytics in gnuplot? - gnuplot

I am searching for a while to get my plot done as I like to have it. Actually, I have a left y-axis and two right y-axis based on the example given here: How to plot multiple y-axes? The information I got there did the job as I would like to have it. However, in my plot I would like to have the y-axis for the 2nd y-values on the right hand side too. I was searching around and found this one: multiple Y axis - margin which is not related to gnuplot. So right now I don't know how to do it except, I will use a vector and build the axis myself which might be not accurate in terms of positioning and not the best way to go. The question now is, if I can move the right border of the graph using an offset like I do it with the ytics and ylabels? The help of gnuplot does not provide anything for the »border« but I might also search at the wrong place.
The picture and gnuplot script is given below. However, I am not allowed to show the graphs but it does not play a role here. To sum up: I would like to have the red added line in my eps file at the end and I am wondering if this is possible without using arrows and building it myself. In addition I hope that this question may be relevant for others and was not asked and solved previously. Otherwise my search-investigation was bad. Thank you in advance.
#!/bin/gnuplot
#
# Tobias Holzmann
# 05.09.2017
# Multiplot for 3 y-axis
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
clear
reset
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
set output "PowerControl.tex"
set terminal epslatex
set key nobox
set ytics out
set y2tics out
set ytics nomirror
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
set style line 1 lw 1.7 lc rgb 'black' ps 0.7 pt 7
set style line 2 lw 1.5 lc rgb 'black'
set style line 3 lw 1.3 lc rgb 'black' dashtype 4
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
set multiplot
set xrange [0:60]
set rmargin screen 0.8
set lmargin screen 0.10
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
set xlabel "Time [s]"
set ylabel "Amount of inserted energy [-]"
set ylabel offset 3,0
set yrange [0:.4]
set ytics \
("None" 0.00, "" 0.05, "" 0.1, "" 0.15, "Moderate" 0.2, \
"" 0.25, "" 0.3, "" 0.35, "High" 0.4)
unset y2tics
set key at graph 0.95,0.22
set key height 0.3
plot \
"timePower" using 1:2 w lp ls 1 t 'Energy insertion'
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#unset ytics
#unset xtics
unset ylabel
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
set grid
set y2tics 10
set y2tics out
set y2range [0:80]
set y2label "Von Mises Stress [MPa]"
set key at graph 0.95,0.315
set key height 6
plot \
"timeVonMises" using 1:2 w l ls 2 t 'Von Mises Stress' axis x1y2
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
unset grid
unset ytics
unset ylabel
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
set y2tics 75
set y2range [0:600]
set y2tics offset 8, 0
set y2label "Maximum Temperature [$^{\\circ} $C]" offset 8,0
set key at graph 0.95,0.10
set key height 0.3
plot \
"timeTMax" using 1:($2-273.15) w l ls 3 t 'Temperature' axis x1y2
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
unset multiplot
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Multiplot with Gnuplot without 2nd y-axis
PS: Based on my low level of reputation points, I am not allowed to put the picture directly (unfortunately).

For the last data set you can first draw the data without showing the y2 axis, and then make a separate plot that shows only the y2 axis and no data. You are then free to position the two plots relative to one another. It is important to make sure that both plots use the same height (which can be done be setting the top and bottom margins) and the same numerical range (which is trivial if you fix the range, or you can use writeback/restore if you want to use autoscaling of the y2 axis).
Example:
reset
set multiplot
# first, draw the graph without y2 axis
set tmargin 1
set bmargin 3
set rmargin 20
set xtics nomirror
unset ytics
unset y2tics
unset key
set border 1 # draw only the bottom border (the x axis)
set y2range [] writeback # use autoscaling for y2 and store the range
plot sin(x) axes x1y2
# now draw only the y2 axis, with the range from the previous plot
set y2range restore
set rmargin 10
set border 8 # draw only the right border (the y2 axis)
unset xtics
set y2tics
plot 1/0 axes x1y2
unset multiplot
gives

After checking the manpage of gnuplot etc. I think there is no possibility how I would like to have it. However, a fast an easy workaround is using (as already mentioned vectors with do [] {}. My suggestion is as follows:
set arrow 1 from graph 1.20,0 to graph 1.20,1 nohead lw 1
do for [i=0:8] {
set arrow from graph 1.20,i/8. to graph 1.21,i/8. nohead lw 1
}
The outcome is given in the picture above (or link). Maybe someone can use it for the individual plots one may want to make. If someone knows an better solution, please let us know.
Kind regards
Tobias
3rd y-axis with arrows and do

Related

How to determine the minimum grid length | Numerical Plasma physics

I am learning particle-in-cell (PIC) python code. PIC currently represents one of the most important plasma simulation tools. It is particularly suited to the study of kinetic or non-Maxwellian effects.
Given the following dispersion relation
I found the range of wave numbers k for which the oscillation frequency is imaginary to be -|\frac{w}{v_0}| < k < |\frac{w}{v_0}|
What I am trying to understand is how to find the minimum grid length L_{min} as a function of \frac{v_0}{w}. L_{min} indicates the needed minimum grid length to support such unstable modes.
I think we should be able to study the plasma behaviour for both L < L_{min} and L > L_{min}. I was told I should adjust the number of simulation particles to grid points to improve the statistics. Besides, the number of particles per cell (i.e. npart/ngrid) should be fixed and should be much greater than 1, in order to reduce numerical noise. The runtime needed (here in units of ω_p^−1) to observe the instability can be estimated from the maximum growth rate.
Here's the full python 3 code I am working with. Please note I have little experience with coding so I might ask lots of follow up questions. Thank you.
#! /usr/bin/python
#
# Python script for computing and plotting single charged particle
# trajectories in prescribed electric and magnetic fields.
# Roughly equivalent to boris.m matlab program
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider, Button, RadioButtons
from mpl_toolkits.mplot3d import Axes3D
import os
import os.path
import sys
from sys import exit
from time import sleep
# ===================================
#
# Function to integrate particle trajectory
# in given E, B fields
#
# ===================================
def integrate(E0, B0, vz0):
global dt, v0, x0, xp, yp, zp, qom, larmor, nsteps
wc=qom*B0 # cyclotron frequency
larmor=vperp/wc
print ("Cyclotron frequency =",wc)
print ("Perpendicular velocity v_p=",vperp)
print ("Larmor radius=",larmor)
norm = 1. # choose whether to normalise plot axes dimensions to Larmor radius
trun=5*2*np.pi/wc # total runtime
dt=.1/wc # timestep - adjust to current B-field
nsteps=int(trun/dt) # timesteps
E=np.array([0.,E0,0.]) # initial E-field
B=np.array([0.,0.,B0]) # initial B-field
u=np.array([0.,0.,0.]) # intermediate velocity
h=np.array([0.,0.,0.]) # normalized B-field
xp[0]=x0[0]
yp[0]=x0[1]
zp[0]=x0[2]
v0[2]=vz0 # z-component
v=v0+.5*dt*qom*(E+np.cross(v0,B)) # shift initial velocity back 1/2 step
x=x0
for itime in range(1,nsteps):
x=x+dt*v
xp[itime]=x[0] /norm
yp[itime]=x[1] /norm
zp[itime]=x[2] /norm
tp[itime]=itime*dt
#
# Boris mover: solves dv/dt = q/m*(E + vxB) to 2nd order accuracy in dt
#
qomdt2 = dt*qom/2
h = qomdt2*B
s=2*h/(1+np.dot(h,h))
u = v + qomdt2*E
up=u+np.cross(u+np.cross(u,h),s)
v=up+qomdt2*E
# vxp[itime] = v[0]
# ===================================
# Make 2D plots of particle orbit
#
# ===================================
def plot_track2D():
global xp,yp,nsteps,ax1
fig = plt.figure(figsize=(8,8)) # initialize plot
xmin=np.min(xp)
xmax=np.max(xp)
ymin=np.min(yp)
ymax=np.max(yp)
fig.add_subplot(221) # 1st subplot in 2x2 arrangement
plt.cla()
plt.grid(True, which='both')
plt.xlim( (xmin, xmax) )
plt.ylim( (ymin, ymax) )
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.plot(xp[0:nsteps],yp[0:nsteps],c='b')
fig.add_subplot(222) # 2nd subplot
# fig.add_subplot(223) # 2nd subplot
# fig.add_subplot(224) # 2nd subplot
plt.draw()
plt.savefig('./particle_orbit.png') # Save plot to file
# ===================================
#
# Make 3D plot of particle orbit
#
# ===================================
def plot_track3D():
global xp,yp,zp,nsteps,ax1
xmin=np.min(xp)
xmax=np.max(xp)
ymin=np.min(yp)
ymax=np.max(yp)
zmin=np.min(zp)
zmax=np.max(zp)
ax1.cla()
plt.ion()
plt.grid(True, which='both')
ax1.set_xlim( (xmin, xmax) )
ax1.set_ylim( (ymin, ymax) )
ax1.set_zlim( (zmin, zmax) )
ax1.set_xlabel('$x $ [m]')
ax1.set_ylabel('$y $ [m]')
ax1.set_zlabel('$z $ [m]')
#ax1.set_aspect(1.)
ax1.scatter(xp,yp,zp,c=tp,marker='o') # tracks coloured by elapsed time since start
plt.draw()
# =============================================
#
# Main program
#
# =============================================
print ("Charged particle orbit solver")
plotboxsize = 8.
animated = True
x0=np.array([0.,0.,0.]) # initial coords
vz0=0.
v0=np.array([-1e2,0.,vz0]) # initial velocity
vperp = np.sqrt(v0[0]**2+v0[2]**2)
E0=0.
B0=.1
e=1.602176e-19 # electron charge
m=9.109e-31 # electron mass
qom=e/m # charge/mass ratio
wc=qom*B0 # cyclotron frequency
larmor=vperp/wc
print (wc,vperp,larmor)
trun=5*2*np.pi/wc # total runtime
dt=.1/wc # timestep - adjust to current B-field
nsteps=int(trun/dt) # timesteps
B1=np.array([0.,0.,0.1]) # gradient B perturbation
#wc=qom*np.linalg.norm(B) # cyclotron frequency
#nsteps=2
tp = np.zeros(nsteps) # variables to store particle tracks
xp = np.zeros(nsteps)
yp = np.zeros(nsteps)
zp = np.zeros(nsteps)
vxp = np.zeros(nsteps)
vyp = np.zeros(nsteps)
vzp = np.zeros(nsteps)
# Compute orbit
integrate(E0, B0, vz0)
# 2D orbit plotter
plot_track2D()
exit(0) # Quit script before 3D plot - comment out to continue!
# Start 3D interactive mode with sliders for B, E and v0
plt.ion() # Turn on interactive plot display
fig = plt.figure(figsize=(8,8))
# Get instance of Axis3D
ax1 = fig.add_subplot(111, projection='3d')
# Get current rotation angle
print (ax1.azim)
# Set initial view to x-y plane
ax1.view_init(elev=90,azim=0)
ax1.set_xlabel('$x $[microns]')
ax1.set_ylabel('$y $[microns]')
ax1.set_zlabel('$z $[microns]')
plot_track3D()
#filename = 'a0_45/parts_p0000.%0*d'%(6, ts)
#plot_from_file(filename):
axcolor = 'lightgoldenrodyellow'
axe0 = fig.add_axes([0.1, 0.95, 0.3, 0.03])#, facecolor=axcolor) # box position, color & size
axb0 = fig.add_axes([0.5, 0.95, 0.3, 0.03])#, facecolor=axcolor)
axv0 = fig.add_axes([0.1, 0.9, 0.3, 0.03])#, facecolor=axcolor)
sefield = Slider(axe0, 'Ey [V/m]', -5.0,5.0, valinit=E0)
sbfield = Slider(axb0, 'Bz [T]', -1.0, 1.0, valinit=B0)
svz = Slider(axv0, 'vz [m/s]', 0.0, 1.0, valinit=0.)
def update(val):
E0 = sefield.val
B0 = sbfield.val
vz0 = svz.val
integrate(E0,B0,vz0)
plot_track3D()
plt.draw()
sefield.on_changed(update)
sbfield.on_changed(update)
svz.on_changed(update)
resetax = fig.add_axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
def reset(event):
global ax1
sefield.reset()
sbfield.reset()
svz.reset()
ax1.cla()
ax1.set_xlabel('$x $[microns]')
ax1.set_ylabel('$y $[microns]')
ax1.set_xlim( (0., 10.) )
# ax1.set_ylim( (-sigma, sigma) )
ax1.grid(True, which='both')
plt.draw()
button.on_clicked(reset)
#plt.show()
plt.show(block=False)
$$x=3$$
From algorithmic stability concerns there are only upper bounds on the two variables grid length and time step, dx and dt taken together. Put very informally, in one time step a particle must not travel a longer distance than from a grid cell to one of its direct neighbours. There is no lower limit on grid spacing until you come into conflict with the resolution of your numerical data type or run out of computing memory, or the time to execute one simulation run takes far too long.

Merging Plot with the same scale in gunplot

I am having some troubles getting the desired results when using Multiplot with a specified size and margins. I have attached a picture shows the issue when plotting my data. I am interested in merging plots with the same scale. For that I specified xsize= 0.40, ysize= 0.90, and xinit= 0.10 as in the code below. When the data files were plotted, the y-axis of the right plot was a bit lower than that of the left plot. If I was not looping, everything seems to work as expected. I even tried to move xsize= 0.40, ysize= 0.90, and xinit= 0.10 inside the for loop but no luck.
set term png
xsize= 0.40
ysize= 0.90
xinit= 0.10
do for [i=1:files] {
set output sprintf("Picture(x=-%d).png",i)
set multiplot layout 1,2
# Reset keys
unset rmargin
unset lmargin
# Set individual keys
set size xsize, ysize # Plot size in relation with canvas
set lmargin at screen xinit # x inital possition 0.10
set rmargin at screen xinit + xsize # x final possition 0.50
set xlabel "x[m]" offset 2,0 # Displace xlabel to the center of canvas
set ylabel "y[m]"
plot filename(i) using 4:3 with lines notitle
# Reset keys
unset rmargin # Clears the past x position
unset lmargin
unset label # Clears the past label
unset ytics # Removes the y axis tics
unset ylabel # Removes the y axis label
set size xsize, ysize # Plot size in relation with canvas
set lmargin at screen xinit+xsize # x inital possition 0.50
set rmargin at screen 1 - xinit # x final possition 0.90
plot filename(i) using 6:3 with lines notitle
unset multiplot
}
I wonder what could be the issue in my code. Thanks for the help.
For your use case you should use the spacing and margins options for multiplot:
set multiplot layout 1,2 margins 0.1,0.1,0.05,0.05 spacing 0,0

GnuPlot splot function with 2d points

I basically want to draw 2d color surface (or contour plot)
of rosenbrock function f(x,y) = (a-x)^2 + b * (y-x*x) ^2
and append some points (x,y) on this image.
Sample file with points looks as follows:
#x #y
15.00000 12.00000
8.00000 9.00000
The thing is, both graphs do not share the same coordinate system on output image:
coordinate systems do not overlap on each other
gnuplot code:
#!/usr/bin/env gnuplot
reset
set terminal png size 700,700
enhanced set output 'output.png'
set tmargin screen 1
set bmargin screen 0
set border 0 back
set size square
xr=20
yr=20
set xrange [-xr:xr]
set yrange [-yr:yr]
unset key #disablegraph name
unset colorbox
set surface
set multiplot
set view map
set cntrparam levels 10# contour tenderness
set style data pm3d
set pm3d
set contour
a=1 #rosenbrock parameter
b=1 #rosenbrock parameter
#set isosamples 50
splot (a-x) * (a-x) + b * (y-x*x) * (y-x*x) # 2d rosenbrock
unset view
unset pm3d
plot 'data.dat' pt 5, 'data.dat' using 1:2:($0+1) with labels offset 1 notitle
mixing 2d and surface plots with multiplot is usually a mess. I guess you probably don't need multiplot in this simple case. Maybe something like this is enough:
set size square
xr=20
yr=20
set xrange [-xr:xr]
set yrange [-yr:yr]
unset key
unset colorbox
set surface
set pm3d map
set contour
set cntrparam levels 10# contour tenderness
rosenbrock(x,y,a,b)= (a-x) * (a-x) + b * (y-x*x) * (y-x*x)
splot rosenbrock(x,y,1,1) w pm3d, 'data.dat' u 1:2:0 w p pt 5, 'data.dat' using 1:2:(1):($0+1) with labels offset 1,1 notitle

Gnuplot: part of axis missing in multiplot

I try to make a figure using multiplot, but some axes are weird (see figure). I use epslatex to generate a standalone tex file. It looks like a "box" limits the axis, but I cannot figure out what the corresponding option is.
The code used to generate the figure is below.
reset
set term epslatex color standalone header \
"\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage{cmbright}\n"
set output 'correlations.tex'
set pm3d at b
set pm3d map
unset surface
set pm3d corners2color c4
eps = 1.e-6
f(x)=(log(abs(x)/eps+1))*sgn(x)
set palette functions 2*(gray), 1-2*abs((gray)-.5), 2-2*(gray)
zmax = 1
set cbrange [f(-zmax):f(zmax)]
SX=0.8; SY=0.8
set bmargin 0; set tmargin 0; set lmargin 0; set rmargin 0
X0=0.1; Y0=0.1
DX=0.46; DY=0.64
set size X0+SX+DX,Y0+SY+DY
set origin 0,0
#
# Multiplot
#
set multiplot
#
# bottom left
#
set origin X0,Y0
unset colorbox
unset key
set size square SX,SY
xmax = 5
xshift = 0
set xrange [-xmax-xshift:xmax-xshift]
set yrange [-xmax:xmax]
set xlabel '$x_\parallel$'
set ylabel '$x_\perp$'
set xtics -5,5,5
set ytics -5,5,5
datafile = '../Résultats/correl_pm_smooth2f1.0cutoff5.0xMax5.0nX61.dat'
splot datafile u 1:2:(f($3)) w l t '',\
datafile u 1:(-$2):(f($3)) w l t ''
#
# top left
#
set origin X0,Y0+DY
set xlabel ''
set ylabel ''
set xtics ("" -5, "" 0., "" 5)
datafile = '../Résultats/correl_pm_smooth2f0.0cutoff5.0xMax5.0nX61.dat'
splot datafile u 1:2:(f($3)) w l t '',\
datafile u 1:(-$2):(f($3)) w l t ''
#
# top right
#
set origin X0+DX,Y0+DY
set xtics ("" -5, "" 0., "" 5)
set ytics ("" -5, "" 0., "" 5)
datafile = '../Résultats/correl_pm_smooth2f0.5cutoff5.0xMax5.0nX61.dat'
splot datafile u 1:2:(f($3)) w l t '',\
datafile u 1:(-$2):(f($3)) w l t ''
set origin X0+DX,Y0
set colorbox
set xtics -5,5,5
datafile = '../Résultats/correl_pm_smooth2f5.0cutoff5.0xMax5.0nX61.dat'
splot datafile u 1:2:(f($3)) w l t '',\
datafile u 1:(-$2):(f($3)) w l t ''
unset multiplot
I found the answer. With the epslatex terminal, the size and position of the various items refer to the size of the canvas and should thus be contained in the 1x1 box.
Changing the size of the terminal is done via "set term epslatex size 5,5…".

how to calculate or set size of gnuplot margins + labels + legend

We have a large spectrogram that needs to be pixel perfect (1 row = 100ms of data, 1 column = 1 frequency bin of a fft). I use the below code to calculate the size of the plot:
set terminal unknown
sedcmd="<(sed -n '1p;" .rowstart. "," .rowend. "p' " .filename. ".csv)"
plot sedcmd nonuniform matrix using 2:1:3 notitle with image
xspan = GPVAL_DATA_X_MAX - GPVAL_DATA_X_MIN
yspan = GPVAL_DATA_Y_MAX - GPVAL_DATA_Y_MIN
set terminal png size (rowend-rowstart),yspan
sedcmd="<(sed -n '1p;" .rowstart. "," .rowend. "p' " .filename. ".csv)"
plot sedcmd nonuniform matrix using 2:1:3 notitle with image
rowstart and rowend are variables passed in to gnuplot which represent the frequency bins. This works fine with one exception, it doesn't account for the space needed for the legend and labels. How can I either calculate, or set the pixels so that:
[ylabels][ PLOT ][LEGEND]
[ xlabels ]
PLOT will be the exact size I specify (ie: 1000x1000)
EDIT: final calculation code for the plotsize and margins:
# margins and plotsize
rowstart = 2457 # rowstart/end represent the fft bins
rowend = 5734 # plot is actually rotated 90deg (rows are cols)
cols = 6970 # number of ms in plot (plotted rows)
plotwidth = (rowend - rowstart) +1
plotheight = cols
lm = 1200.00
rm = 600
tbmargin = 200.00
width = plotwidth + (lm + rm)
height = plotheight + (tbmargin * 2)
set lmargin at screen lm / width
set rmargin at screen 1 - (rm / width)
set tmargin at screen tbmargin / height
set bmargin at screen 1 - (tbmargin / height)
show margin
If you know the exact size of the plot you want it helps a lot. If you want a 1000x1000 plot, you can start with:
s = 1250 # size of plot
set terminal pngcairo size 1250,1250
set output 'spectrogram.png'
# difference between l/r and t/b margins = (0.9-0.1)*1250 = 1000 px
set lmargin at screen 0.1
set rmargin at screen 0.9
set bmargin at screen 0.1
set tmargin at screen 0.9
plot ...
I find that doing some basic algebra and using the *margin commands is very helpful when fiddling with pixel-perfect plot shapes (examples here and here).
There may be a 1 px difference or so--I am not sure if the axes are drawn from 0 to 1 px or -1 to 0 as far as the plot edges are concerned.

Resources