astha
astha

Reputation: 613

How to plot data in straight line and in different line style depending on the data set

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.enter image description here In this figure I have shown only three lines, as an example.

I have created below gnuplot script that give me my required plot (enter image description here 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

This is from theozh's script enter image description here

Upvotes: 1

Views: 242

Answers (2)

theozh
theozh

Reputation: 26158

In gnuplot I would do it like this. Draw your data twice

  1. with lines and different dashtype
  2. and the horizontal lines with 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:

enter image description here

Upvotes: 1

lrsppp
lrsppp

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

Related Questions