Reputation: 613
I have a unique data set (the number of rows and columns can vary case to case.)
0.0 0 0 0 0 0 0
0.5 0 0 0 0 0 0
2.0 156.626 156.626 138.354 138.354 138.354 138.354
2.5 156.626 156.626 138.354 138.354 138.354 138.354
4.0 287.268 287.268 289.808 289.808 271.829 276.304
4.5 287.268 287.268 289.808 289.808 271.829 276.304
6.0 418.931 426.263 418.933 426.259 273.572 273.559
6.5 418.931 426.263 418.933 426.259 273.572 273.559
8.0 417.211 417.21 417.207 417.211 417.207 417.212
8.5 417.211 417.21 417.207 417.211 417.207 417.212
As you see it have a unique combination of data set (constant and then change, constant and then change.) I want to plot the constant data set in the solid straight line without any dash-type and the data which is not in straight line will be in different dash-type.
I need a script (either gnuplot or matplotlib) that can plot the data as per attached figure. In this figure I have shown only three lines, as an example.
I have created below gnuplot script that give me my required plot ( but it does not give me the horizontal lines, solid without any dash type.
CASE = "New.dat"
Xi=-2 ; Xf=22; Xs=1
AYf=500 ; AYs=100
reset
set terminal postscript eps enhanced size 20cm,20cm color solid lw 3 "Times-Bold" 40
set output "data.eps"
set multiplot \
layout 1,1 rowsfirst \
title "{/:Bold=40 }" \
margins screen 0.15,0.85,0.11,0.950 \
spacing screen 0.00,0.03
set key spacing 1.2
set mxtics 2
set mytics 2
unset key
unset arrow
set arrow from Xi ,0.00 to Xf,000 nohead lw 3.5 lc rgb "blue" lt 0
set xrange [Xi:Xf]
set yrange [-50:AYf]
set key at graph 0.63, 0.95 font "Times-bold, 30"
set xtics Xi,Xs,Xf format ""
set ytics 0,AYs,AYf format "%g" font "Times-bold, 40"
plot CASE u 1:2 title "Path-1" w l lc 1 lw 3 dashtype 2 , CASE u 1:3 title "Path-2" w l lc 2 lw 3 dashtype 3 , CASE u 1:4 title "Path-3" w l lc 4 lw 3 dashtype 4 , CASE u 1:5 title "Path-4" w l lc 6 lw 3 dashtype 5, CASE u 1:6 title "Path-5" w l lc 7 lw 3 dashtype 6 , CASE u 1:7 title "Path-6" w l lc 9 lw 3 dashtype 9
Upvotes: 1
Views: 242
Reputation: 26158
In gnuplot I would do it like this. Draw your data twice
with lines
and different dashtypewith vectors
but only if the y-value doesn't change.It is a bit difficult to distinguish the dashed lines because some of them are on top of each other. You need to optimize this a bit.
Code:
### plot intermittent horizontal lines
reset session
$Data <<EOD
0.0 0 0 0 0 0 0
0.5 0 0 0 0 0 0
2.0 156.626 156.626 138.354 138.354 138.354 138.354
2.5 156.626 156.626 138.354 138.354 138.354 138.354
4.0 287.268 287.268 289.808 289.808 271.829 276.304
4.5 287.268 287.268 289.808 289.808 271.829 276.304
6.0 418.931 426.263 418.933 426.259 273.572 273.559
6.5 418.931 426.263 418.933 426.259 273.572 273.559
8.0 417.211 417.21 417.207 417.211 417.207 417.212
8.5 417.211 417.21 417.207 417.211 417.207 417.212
EOD
set key top left
set datafile missing NaN # apparently necessary for gnuplot 5.2.2
plot for [i=2:7] $Data u 1:i w l lw 2 lc i-1 dt i title sprintf("Path %d",i-1), \
for [i=2:7] y1=x1=NaN $Data u (x0=x1,x1=column(1),x0):(y0=y1,y1=column(i)):(x1-x0):(y0==y1?0:NaN) w vectors lw 4 lc i-1 nohead notitle
### end of code
Result:
Upvotes: 1
Reputation: 1413
Calculate the indices which correspond to the plateau and increasing segments of your data. Then plot it segment-wise. This is the plot for the first path. To plot all paths you can use another for-loop. Maybe there is an easier solution, but this should work.
# path data
x = np.array([0. , 0.5, 2. , 2.5, 4. , 4.5, 6. , 6.5, 8. , 8.5])
y = np.array([0., 0., 156.626, 156.626, 287.268, 287.268, 418.931, 418.931, 417.211, 417.211])
# indices of plateau and increasing
idx_plat = np.where(np.diff(y) == 0)[0]
idx_incr = np.where(np.diff(y) != 0)[0]
# color for first path
color = 'C0'
# text setup
texts = ['A', 'B', 'C', 'D', 'E']
off = 10 # y offset for text
# plot plateau and increasing segments in a loop
for i in range(len(idx_plat) - 1):
x_sub = x[idx_plat[i]:idx_plat[i+1]]
y_sub = y[idx_plat[i]:idx_plat[i+1]]
plt.plot(x_sub, y_sub, linestyle = '--', color = color)
# annotate text
plt.text(x_sub.mean(), y_sub[0] + off, texts[i])
for j in range(len(idx_incr) - 1):
x_sub = x[idx_incr[j]:idx_incr[j+1]]
y_sub = y[idx_incr[j]:idx_incr[j+1]]
plt.plot(x_sub, y_sub, linestyle = '-', color = color)
# plot last segment twice with label to create legend
plt.plot(x_sub, y_sub, linestyle = '-', color = color, label = label)
plt.legend(loc = 'best')
Upvotes: 0