I saw some examples like this one:
f(x) = log10(x)
g(x) = 10**x
set nonlinear x via f(x) inverse g(x)
So this one is equivalent to just log-scaling the x.
But I don’t get why we need to write the inverse function?
And also I have this situation:
For data in x>=0 range I need to scale x in a way that it shows in an almost-half plot;
For data in -100<=x<0 I need to scale x in a way that it shows in a small part of plot;
For data in x<-100 I need to scale x in a way as for data in x>=0.
So let’s imagine we have an a4paper and gnuplot creates his plots on it. I want to have a plot result that will be drawn in an x scales like:
If x>=0 1cm = 5
If -100<=x<0 1cm = 100
If x<-100 1cm = 5
(I don’t mean it’s important to me to have only this centimeters, it just says that I need a correlation between delta of two x values and real length between them.)
I’m so sorry I can’t understand this mechanics of scaling.
The forward function tells gnuplot where to draw user coordinate [x,y] on the page. Call that location [x',y']. Only the forward function is needed for this. But the interactive terminals echo back mouse position and allow you to click on the plot for various purposes. In order to know what a mouse click on [x',y'] means, the program has to convert it back to the original [x,y]. For that it needs the inverse function.
For an example of using different scaling functions over different portions of the full plot, see the online demo nonlinear1.dem reproduced below
# This example shows how a nonlinear axis definition can be used to
# create a "broken axis". X coordinates 0-100 are at the left,
# X coordinates 500-1000 are at the right, there is a small gap between them.
# So long as no data points with (100 < x < 500) are plotted, this works as expected.
#
# f(x) maps x axis (discontinuous) to shadow axis coords (continuous linear range [0:1000])
# g(x) maps shadow axis coords to x axis readout
#
set title "A 'broken' x axis can be defined using 'set nonlinear x'"
# Define the broken-axis mapping
axis_gap = 25.
f(x) = (x <= 100) ? x : (x < 500) ? NaN : (x - 400 + axis_gap)
g(x) = (x <= 100) ? x : (x < 100 + axis_gap) ? NaN : (x + 400 - axis_gap)
set xrange [15:600] noextend
set nonlinear x via f(x) inverse g(x)
set xtics 50.
set xtics rotate by -90 nomirror
set ytics nomirror
set border 3
unset key
# Creation of the broken axis marks (this should be automated)
set arrow 500 from 100, graph 0 to 500, graph 0 nohead lt 500 lw 2 lc bgnd front
set arrow 501 from 100, graph 0 length graph .01 angle 75 nohead lw 2 front
set arrow 502 from 100, graph 0 length graph -.01 angle 75 nohead lw 2 front
set arrow 503 from 500, graph 0 length graph .01 angle 75 nohead lw 2 front
set arrow 504 from 500, graph 0 length graph -.01 angle 75 nohead lw 2 front
plot 'silver.dat' with yerrorbars lw 2, '' with lines
Related
I am plotting a curve in gnuplot. I would like to call out a couple of specific points on the curve.
This is what the curve looks like:
Shown below is what I'm hoping to get (but I had to draw in the points and lines to the axes with GIMP). I'd like to call out two specific points on the curve. The first, where Vgs (x-axis) equals -0.5. The second, where Id (y-axis) equals 2.5. If possible, I'd like to also have a dashed line over to the axis to aid in reading the values.
I found a reference that said to try plotting a circle using set object circle and the coordinates, but I must not have it right, because it complains about extra parameters. Browsing the manual is so far unsuccessful. I'm not even sure what term to search for.
Is there an easy way to call out a couple of points on the curve that I've drawn and have it look similar to the screenshot below?
Here are the commands I used to plot the curve:
set xlabel "Vgs (Volts)"
set ylabel "Id (mA)"
set grid
Idss=5
Vgs_off=-1
Id(Vgs) = Idss * (1 - (Vgs / Vgs_off) ) ** 2
plot [Vgs=Vgs_off:0][0:Idss + 1] Id(Vgs)
It's the characteristic curve for a Fairchild J112 JFET if anyone is curious.
Edited to replace the -1 in the denominator with Vgs_off to avoid confusion. This is a value from the JFET's datasheet and just happened to be -1 in this particular case.
ADDENDUM:
After incorporating the pieces from the answer given by #Eldrad, I came up with this much improved representation of the JFET characteristic curve:
Here are the commands used to create it:
# JFET parameters from data sheet
Vgs_off=-1
Idss=5
# JFET characteristic curve
Id(Vgs) = Idss * (1 - (Vgs / Vgs_off) ) ** 2
# Graph properties
set title "I_D vs V_{GS}"
set xlabel "V_{GS} (Volts)"
set ylabel "I_D (mA)"
set grid
set key off
set monochrome
# Plot the characteristic curve
plot [Vgs=Vgs_off:0][0:Idss] Id(Vgs)
# Plot interesting points
set object circle center 0.5 * Vgs_off, Id(0.5 * Vgs_off) radius char 0.33 fillstyle solid fillcolor rgb 'black'
set object circle center 0.293 * Vgs_off, Id(0.293 * Vgs_off) radius char 0.33 fillstyle solid fillcolor rgb 'black'
# Mark interesting points with dashed lines to where they intersect the x and y axes.
set arrow from first 0.5 * Vgs_off, graph 0 to first 0.5 * Vgs_off, graph 1 dashtype "-" nohead
set arrow from graph 0, first Id(0.5 * Vgs_off) to graph 1, first Id(0.5 * Vgs_off) dashtype "-" nohead
set arrow from 0.293 * Vgs_off, graph 0 to 0.293 * Vgs_off, graph 1 dashtype "_" nohead
set arrow from graph 0, first Id(0.293 * Vgs_off) to graph 1, first Id(0.293 * Vgs_off) dashtype "_" nohead
# Label the lines
set label "I_{DSS}" at graph 1.01, graph 1
set label "I_{DSS} / 2" at graph 1.01, graph 0.50
set label "I_{DSS} / 4" at graph 1.01, graph 0.25
set rmargin at screen 0.9
# Update the graph
replot
Getting specific values of a function is straightforward if the function y=f(x) and its inverse x=f(y) have an analytical expression, like it is in your case.
A couple of remarks about your function definition: You should use x as the variable, because this is the default gnuplot is looking for, it also makes the plot command shorter. Also, division by -1 is the same as putting a minus in front, so an easier function definition, including the inverse would be:
Idss = 5.0
Id (x) = Idss * (1 + x)**2
Id_inv (x) = sqrt(x/Idss) -1
Now the dashed lines can be drawn as arrows (check set arrow):
set arrow 11 from first -0.5, graph 0 to first -0.5, first Id(-0.5) lc "red" lw 2 dt 2 nohead
set arrow 12 from first -0.5, Id(-0.5) to graph 0, first Id(-0.5) lc "red" lw 2 dt 2 nohead
set arrow 21 from first Id_inv(2.5), graph 0 to Id_inv(2.5), 2.5 lc "green" lw 2 dt 2 nohead
set arrow 22 from first Id_inv(2.5), 2.5 to graph 0, first 2.5 lc "green" lw 2 dt 2 nohead
I would recommend drawing the horizontal lines to the axis where the tics are actually printed (i.e. to the left side). The reference points are the x- or y-values of the function and the border of the graphs, see the manual about coordinates for a detailed explanation.
You could add specific tic marks at those points:
set xtics add (-0.5, Id_inv(2.5))
set ytics add (Id(-0.5), 2.5)
You also asked about points in your comment and got the correct approach. The size of the circle can be chosen in any coordinate system (I think character is the width of a letter – x? – in the current font, but I'm not 100% sure)
set object 1 circle center -0.5,Id(-0.5) radius first 0.01 fs solid noborder fc "red"
set object 2 circle center Id_inv(2.5),2.5 radius first 0.01 fs solid noborder fc "green"
Now the remaining decoration can be added:
set title "{/:Italic I}_d vs {/:Italic V}_{gs}"
set xlabel "{/:Italic V}_{gs} /V"
set ylabel "{/:Italic I}_d /mA"
set xrange [-1:0]
plot Id(x)
Version 5.2 contains set nonlinear. One can use it to construct broken axes as suggested in the demo here. I am trying to follow the steps for x axis also logarithmic.The current code is below as well as the data. The problem that I cannot figure out is the scaling of the first order after the break, this is illustrated in this plot:
As you can see the problem is between 0.1 and 1. What am I doing wrong?
data="test2.txt"
unset nonlinear x
x1min=1e-6
x1max=1e-5
x2min=1e-1
x2max=1e+3
ymin =1e-1
ymax =1e+3
dx=(x2min - x1max)
set yrange [ymin:ymax]
unset key
set format x "10^{%T}
set xtics font ",12"
set ytics font ",12"
set y2tics font ",12"
axis_gap=1
f(x) = (x <= x1max) ? log10(x) : (x < x2min) ? NaN : log10(x - dx + axis_gap)
g(x) = (x <= x1max) ? 10**x : (x < x1max + axis_gap) ? NaN : 10**(x + dx - axis_gap)
set xrange [x1min:x2max] nereverse nowriteback
set nonlinear x via f(x) inverse g(x)
set logscale y
set xtics (1e-6 0,2e-6 1,3e-6 1,4e-6 1,5e-6 1,6e-6 1,7e-6 1,8e-6 1,9e-6 1,1e-5 0,2e-5 1,3e-5 1,4e-5 1,5e-5 1,6e-5 1,7e-5 1,8e-5 1,9e-5 1,1e-2 0,2e-2 1,3e-2 1,4e-2 1,5e-2 1,6e-2 1,7e-2 1,8e-2 1,9e-2 1,1e-1 0,2e-1 1,3e-1 1,4e-1 1,5e-1 1,6e-1 1,7e-1 1,8e-1 1,9e-1 1,1 0,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9 1,10 0,20 1,30 1,40 1,50 1,60 1,70 1,80 1,90 1,100 0,200 1,300 1,400 1,500 1,600 1,700 1,800 1,900 1,1000 0)
plot data u 1:2
where the data is:
5 0.471238898038469
4.18879020478639e-6 0.7
4.18879020478639e-6 2
4.18879020478639e-6 8.8
4.18879020478639e-6 2.8
1 4.18879020478639e-6
1 4.18879020478639e-6
98.174770424681 1.68
98.174770424681 3.4
0.125663706143592 161.809725
0.125663706143592 425.60861
0.125663706143592 425.60861
0.125663706143592 425.60861
0.125663706143592 483.467845
144 43.14926
1 50.99458
1 51.975245
1 52.95591
1 54.91724
1 57.859235
1 66.68522
1 69.627215
1 78.4532
1.728 32.361945
1.728 40.207265
1.728 41.18793
1.728 43.14926
1.728 45.11059
1.728 48.052585
1.728 54.91724
1.728 65.704555
3.375 46.091255
3.375 50.99458
3.375 54.91724
3.375 56.87857
3.375 57.859235
3.375 64.72389
8 24.516625
8 43.14926
8 46.091255
8 51.975245
8 54.91724
8 59.820565
15.625 47.07192
15.625 48.052585
15.625 50.99458
15.625 52.95591
15.625 55.897905
64 42.168595
64 42.168595
64 48.052585
125 35.30394
125 42.168595
125 50.013915
UPDATE
I start a bounty on this question. And I am adding another example to work with, a simpler one:
unset key
unset nonlinear x
unset nonlinear x2
axis_gap=1
x1min=1
x1max=3
x2min=5
x2max=20
ymin =1e-1
ymax =1e+3
dx=(x2min - x1max)
x1minp=log10(x1min)
x1maxp=log10(x1max)
x2minp=log10(x2min)
x2maxp=log10(x2max)
set yrange [ymin:ymax]
set xrange [x1min:x2max] noreverse nowriteback
f(x) = (x <= x1max) ? log10(x) : (x < x2min) ? NaN : log10(x/(x2min/x1max)*axis_gap)
g(x) = (x <= x1maxp) ? 10**(x) : (x < log10(x1max*axis_gap)) ? NaN : 10**(x) + dx + log10(axis_gap)
set nonlinear x via f(x) inverse g(x)
set logscale y
set xtics (1e0 0,2e0 0,3e0 0,4e0 0,5e0 0,6e0 0,7e0 0,8e0 0,9e0 0,1e1 0,2e1 0)
plot 0 w l
In this version, I finally got the concept of the nonlinear and I rather think in terms of distance of a tick from origin (the gnuplot's invisible axis) which is determined by f(x), where x are numbers from the plotted range and f(x) is the one in set nonlinear x via f(x) inverse g(x), and g(x) gets the number associated with a tick at position x from origin (the number that is put into y(x) y plotted on y-axis and is displayed on x axis above/below the tick). This may sound complicated by I find this much better than some nonlinear visible and linear invisible axes concept, provided I actually understand it correctly this time.
The solution has to not only work without warning: could not confirm linked axis inverse mapping function on both samples but also there needs to be an explanation what is wrong with the functions in this update, ideally in terms of distances and numbers as suggested above rather than visible/invisible gnuplot jargon.
Update 2
I also noticed this, see the pictures.
f(x) = (x <= x1max) ? log10(x) : (x < x2min) ? NaN : log10(x/(x2min/x1max)*axis_gap)
g(x) = (x <= x1maxp) ? 10**(x) : (x < log10(x1max*axis_gap)) ? NaN : 10**(x*(x2min/x1max)) + dx + log10(axis_gap)
You can see that the coordinates displayed in the bottom left of the window behave as expected (axis_gap=1.1) but the tics (and if you plot data points (1 1, 2 1, 3 1, 5 1, 6 1,...)) the have the wrong placement):
Revised answer:
Have a look at the gnuplot documentation:
[new command in version 5.2] This command is similar to the set link
command except that only one of the two linked axes is visible. The
hidden axis remains linear. Coordinates along the visible axis are
mapped by applying g(x) to hidden axis coordinates. f(x) maps the
visible axis coordinates back onto the hidden linear axis.
Example:
set xrange [1:1000]
set nonlinear x via log10(x) inverse 10**x
This
example establishes a log-scaled x axis. It is an alternative way of
achieving the effect of set log x. The hidden axis in this case has
range [0:3], obtained by calculating [log10(xmin):log10(xmax)]. You
must provide both the forward and inverse expressions.
In other words: f(x) is a function which takes your x-data input value and maps it on a linear range. If you set logscale x you already have such a mapping and the function f(x) is simply log10(x). And g(x) is the inverse function 10**x
If you have a broken axis, as in your case, you have to define a suitable mapping function with different regions. Below, I've chosen a continuous function, where BrokenAxisPos is the value (with respect to the axis before the break) where the second axis should start.
See the following graph:
The range x1max to x2min which you want to have omitted is squeezed by the function f(x) into the range x1max to BrokenAxisPos (I set it to 1e-4). It requires some little calculation to get the factors of function f(x) right. For values above x2min, the function f(x) shifts the original x-value by some appropriate value.
And after some litte calculations, g(x) is the inverse of the function f(x).
With the code:
### broken nonlinear (logarithmic) axis
reset session
set size square
data="test2.txt"
x1min=1e-6; x1max=1e-5
x2min=1e-1; x2max=1e+3
ymin =1e-1; ymax =1e+3
unset key
# settings x-axis
unset logscale x
set xrange[x1min:x2max]
set format x "10^{%T}"
set xtics font ",12"
# manually set major xtics
set xtics add ("0.1" 1e-1, "1" 1, "10" 10, "100" 100, "1000" 1000)
set mxtics 10
# settings y-axis
set logscale y
set format y "%g"
set yrange [ymin:ymax]
set ytics font ",12"
set grid xtics, ytics
BrokenAxisPos = 1e-4
m = log10(BrokenAxisPos/x1max)/log10(x2min/x1max)
f(x) = (x <= x1max) ? log10(x) : x<x2min ? log10(x1max**(1-m)*x**m) : log10(x*BrokenAxisPos/x2min)
g(x) = (x <= log10(x1max)) ? 10**x : x<log10(BrokenAxisPos) ? (10**x/x1max**(1-m))**(1/m) : (x2min/BrokenAxisPos)*10**x
set nonlinear x via f(x) inverse g(x)
# manually hide x1,x2 axis and y-gridlines by placing a rectangle
set obj 1 rect from x1max*1.2, graph 0 to x2min*0.8, graph 1 fs solid 1.0 border bgnd front
plot data u 1:2 w p
### end of code
By the way, you can also use discontinuous functions by setting the "gap"-part to NaN, as you and #Ethan did. Then you can simply skip the calculation and use of m.
f(x) = (x <= x1max) ? log10(x) : x<x2min ? NaN : log10(x*BrokenAxisPos/x2min)
g(x) = (x <= log10(x1max)) ? 10**x : x<log10(BrokenAxisPos) ? NaN : (x2min/BrokenAxisPos)*10**x
But then you have to adapt the hiding of the axes from
set obj 1 rect from x1max*1.2, graph 0 to x2min*0.8, graph 1 fs solid 1.0 border bgnd front
to
set obj 1 rect from x1max, graph 0 to x2min, graph 1 fs solid 1.0 border bgnd front
because x1max*1.2 and x2min*0.8 (which are used to still show the x-grid line) will be mapped to NaN.
With continuous f(x) and g(x), you'll get the result:
The logical error in your approach is that to shift along a log-scale axis you need to multiply or divide by the offset, not add or subtract. So your mapping would be something like:
axis_gap = 1.e4
f(x) = (x <= x1max) ? log10(x) : (x < x2min) ? NaN : log10( (x/dx) / axis_gap)
g(x) = (x <= x1max) ? 10**x : (x < x1max + axis_gap) ? NaN : 10**( (x*dx) * axis_gap)
yielding the figure below
I have problem with plotting fitted function.
The part of the ploted function close to zero disappears and connected with the hyperbola or something which should not be there at all. This happen only if I change set xrange to something smaller than 0. I have to do this because I have lot of data points to close zero so it would look very ugly if I would not changed it.
I tried to use conditionals x>0?f(x):1/0 but it does not help. The hyperbola disappear but the function does not continue down as it should.
I use this code:
set terminal postscript eps size 3.5,2.62 enhanced color
set output "a.eps"
set xrange [-1:]
f(x)=a*b*x/(1+a*x)
fit f(x) "./a" via a, b
plot "./a" w p title "", f(x) w l title "Langmuir isotherm"
That is simply a matter of sampling. The default sampling rate is 100 (show samples), which isn't enough to show fast-varying functions. Increase the sampling rate with e.g.
set samples 1000
to have your function plotted correctly.
A second point is, that discontinuities aren't shown properly if no sample is located exactly at that position. Consider the following plot to demonstrate this:
set xrange [-1:1]
set multiplot layout 2,1
set samples 100
plot 1/x
set samples 101
plot 1/x
unset multiplot
So, if you want to plot the function correctly on both sides of the discontinuity, you must either define a small region around the discontinuity as undefined, or you plot the parts on the left and right separately:
set xrange [-1:]
f(x)=a*b*x/(1+a*x)
fit f(x) "./a" via a, b
left(x) = (x < -1/a ? f(x) : 1/0)
right(x) = (x > -1/a ? f(x) : 1/0)
plot "./a" w p title "", left(x) w l lt 2 title "Langmuir isotherm", right(x) w l lt 2 notitle
i'm having some problems with gnuplot
I have to draw a cdf function and i'm interested in the values of variable x when F(x) is equal to 0.1 and 0.9
How can I tell Gnuplot to show me on the x axis the value corresponding to a given value on the y value (in my example those values are 0.1 and 0.9)
thanks
You're basically asking gnuplot to solve an equation. In your particular case, actually two equations: F(x)=0.1 and F(x)=0.9. As far as I know this cannot be done, but I might be wrong. What you can do if you simply want a graphical solution, is make a conditional plot, and ask that when F(x) is very close to 0.1 0.9, gnuplot plots something other than the function.
For example, assume f(x)=x^2 and you want to know "graphically" for which x f(x)=0.1. Then you can request the value abs(f(x) - 0.1) be small, for example < 0.01. Then tell gnuplot to go to zero (just an example!) if this is the case, otherwise plot f(x)=x^2:
f(x)=x**2
set xrange [-2:2]
set samples 1000
plot abs(f(x)-1) < 0.01 ? 0 : f(x)
Which yields:
The two peaks that go to zero mark graphically on the x axis the solution to the equation f(x)=0.1. Of course, you need gnuplot to sample this point in order to see a peak. Thus you need to play with set samples and set xrange.
From your question it is not clear whether you have a function F(x) as expression or just a x,y-data file. I assume that your function is monotonic increasing in x and y.
Two solutions come to my mind:
via simple linear interpolation
via curve fitting
Let's create some test data. For this, let's assume your function is known (as expression) and something like this (check help norm): F(x) = a*norm(b*x + c)
Let's take a = 1; b = 0.8; c = -4. In the example below, sampling will be only 8, just for illustration purpose.
You can easily set samples 200 and you will get the same results as for the curve fitting method below. From gnuplot 5.0 on, you could write the data into a datablock instead of a file on disk.
Data: SO22276755.dat
0 3.16712e-05
1.42857 0.002137
2.85714 0.043238
4.28571 0.283855
5.71429 0.716145
7.14286 0.956762
8.57143 0.997863
10 0.999968
Script 1: (basically works for gnuplot 4.6.0, March 2012)
### interpolate x-values
reset
FILE = "SO22276755.dat"
yis = '0.10 0.90'
yi(n) = real(word(yis,n))
xis = ''
xi(n) = real(word(xis,n))
Interpolate(yi) = (x1-x0)/(y1-y0)*(yi-y0) + x0
getXis(xis) = xis.(n=words(xis), n<words(yis) ? yi=real(word(yis,n+1)) : 0, \
y0<=yi && y1>=yi ? sprintf(" %g",Interpolate(yi)) : '')
set key left top noautotitle
set grid x,y
plot x1=y1=NaN FILE u (x0=x1,x1=$1):(y0=y1,y1=$2,xis=getXis(xis),y1) \
w l lc rgb "blue" ti "data", \
'+' u (xi=xi(int($0+1))):(yi=yi(int($0+1))):\
(sprintf("(%.4g|%.4g)",xi,yi)) every ::0::1 \
w labels point pt 7 lc rgb "red" right offset -1,0 ti "interpolated"
### end of script
Result:
Script 2: (basically works for gnuplot>=4.6.0, March 2012)
With this approach you are fitting your known function F(x) to constant lines, i.e. your desired values 0.1 and 0.9. For this, a file will be created (could be a datablock for gnuplot>=5.0) and it will basically look like this SO22276755.fit:
0 0.1
1 0.1
0 0.9
1 0.9
### interpolate x-values
reset
F(x) = a*norm(b*x+c) # function
a = 1
b = 0.8
c = -4
yis = '0.10 0.90'
yi(n) = real(word(yis,n))
xis = ''
xi(n) = real(word(xis,n))
set key left top noautotitle
set grid x,y
# create fit levels file
LEVELS = "SO22276755.fit"
set table LEVELS
set samples 2
plot for [i=1:words(yis)] '+' u (yi(i))
unset table
xmin = 0
xmax = 10
set xrange[xmin:xmax]
set samples 100
xis = ''
do for [i=1:words(yis)] {
xi = (xmin+xmax)*0.5 # set start value
fit F(xi) LEVELS u 1:2 index i-1 via xi
xis = xis.sprintf(" %g",xi)
}
plot F(x) w l lc rgb "web-green" ti "F(x)", \
'+' u (xi=xi(int($0+1))):(yi=yi(int($0+1))):(sprintf("(%.4g|%.4g)",xi,yi)) \
every ::0::1 w labels point pt 7 lc rgb "red" righ offset -1,0 ti "fitted"
### end of script
Result:
E.g. if I have a graph and want to add vertical lines at every 10 units along the X-axis.
From the Gnuplot documentation. To draw a vertical line from the bottom to the top of the graph at x=3, use:
set arrow from 3, graph 0 to 3, graph 1 nohead
Here is a snippet from my perl script to do this:
print OUTPUT "set arrow from $x1,$y1 to $x1,$y2 nohead lc rgb \'red\'\n";
As you might guess from above, it's actually drawn as a "headless" arrow.
alternatively you can also do this:
p '< echo "x y"' w impulse
x and y are the coordinates of the point to which you draw a vertical bar
You can use the grid feature for the second unused axis x2, which is the most natural way of drawing a set of regular spaced lines.
set grid x2tics
set x2tics 10 format "" scale 0
In general, the grid is drawn at the same position as the tics on the axis. In case the position of the lines does not correspond to the tics position, gnuplot provides an additional set of tics, called x2tics. format "" and scale 0 hides the x2tics so you only see the grid lines.
You can style the lines as usual with linewith, linecolor.
To elaborate on previous answers about the "every x units" part, here is what I came up with:
# Draw 5 vertical lines
n = 5
# ... evenly spaced between x0 and x1
x0 = 1.0
x1 = 2.0
dx = (x1-x0)/(n-1.0)
# ... each line going from y0 to y1
y0 = 0
y1 = 10
do for [i = 0:n-1] {
x = x0 + i*dx
set arrow from x,y0 to x,y1 nohead linecolor "blue" # add other styling options if needed
}