Search code examples
pythonplotly

Adding shapes in plotly - digital signals plotting


I am trying to plot digital signals with a non existing format in plotly, which consists in thin lines in case value = 0, and thick lines in case value = 1. For doing this, I am drawing an horizontal line and adding rectangles in case signal's value=1.

signal

As I have to plot many signals, I am working with subplots. The problem I'm having, is that shapes are only added in first subplot. I would like to know how can I add shapes to any of subplots.

problem

import numpy as np
from plotly.subplots import make_subplots
import plotly.graph_objects as go

#Creating digital signals in array
y=np.zeros((2,40))

x=np.arange(0,4,.1)

y[0,:]=np.sign(np.cos(x*np.pi))
y[1,:]=np.sign(np.cos(x*1.5*np.pi))
y[y==-1]=0


dig_signals = make_subplots(rows=2,cols=1,subplot_titles=["signal 1", "signal 2"]
                            ,shared_xaxes=True,x_title="time [sec]",vertical_spacing=.2)

for k in range(2):
    
    tiempo_flancos=[] #to save the amount of state changes

    if y[k,0]==1:
        tiempo_flancos.append(x[0])
        

    for i in range(1,len(x)):
        if y[k,i]!=y[k,i-1]:
            tiempo_flancos.append(x[i])
            
    
    if y[k,-1]==1:
        tiempo_flancos.append(x[-1])
    
    dictionaries=[] #this list is needed to create shapes in plotly
    for i in range(int(len(tiempo_flancos)/2)):
        dictionaries.append(dict(x0=tiempo_flancos[i*2],y0=.75,
                                 x1=tiempo_flancos[1+i*2],y1=-.75,
                                 line_width=0,fillcolor="steelblue"))

    dig_signals.add_trace(go.Scatter(x=x,y=np.repeat(0,len(x))),row=k+1,col=1)
    dig_signals.update_layout(yaxis=dict(range[-3,3]),showlegend=False,shapes=dictionaries)
    
    dig_signals.update_traces(line_color="steelblue", line_width=2.5)
    dig_signals.update_yaxes(visible=False)


dig_signals

Solution

  • Only a couple of changes to your code: move dictionaries outside the for loop and specify yref

    dictionaries=[]
    
    for k in range(2):
    
    tiempo_flancos=[] #to save the amount of state changes
    
    if y[k,0]==1:
        tiempo_flancos.append(x[0])
        
    
    for i in range(1,len(x)):
        if y[k,i]!=y[k,i-1]:
            tiempo_flancos.append(x[i])
            
    
    if y[k,-1]==1:
        tiempo_flancos.append(x[-1])
    
    for i in range(int(len(tiempo_flancos)/2)):
        dictionaries.append(dict(x0=tiempo_flancos[i*2],y0=.75,
                                 x1=tiempo_flancos[1+i*2],y1=-.75,
                                 line_width=0,fillcolor="steelblue",
                                 yref='y'+str(k+1)))
    
    dig_signals.add_trace(go.Scatter(x=x,y=np.repeat(0,len(x))),row=k+1,col=1)
    dig_signals.update_layout(yaxis=dict(range=[-3,3]),showlegend=False,shapes=dictionaries)
    
    dig_signals.update_traces(line_color="steelblue", line_width=2.5)
    dig_signals.update_yaxes(visible=False)