I managed! Added some buttons. Here is the code. Hope this helps someone in the future. Well, on this I think the problem is solved. Thanks to everyone who helped!
Of course, the most pressing question is always relevant. How to do it faster and better?
If someone can help it will be cool.
import math
import numpy as np
from collections import deque
from bokeh.layouts import gridplot,column, row
from bokeh.io import push_notebook,show,output_notebook
from bokeh.plotting import figure,show,ColumnDataSource
from bokeh.models import CustomJS,Slider, Grid, LinearAxis, MultiLine,Patches,CheckboxButtonGroup
def insert_zeros_in_trace(trace):
time = np.arange(len(trace))
zero_idx = np.where(np.diff(np.signbit(trace)))[0]
time_at_zero = time[zero_idx] - trace[zero_idx] / np.diff(trace)[zero_idx]
trace_z = np.insert(trace, zero_idx+1, 0)
time_z = np.insert(time, zero_idx+1, time_at_zero)
return trace_z, time_z
def add_tags_for_varea(trace,time,level):
trace_tagged=np.insert(trace, 0, 0)
trace_tagged=np.insert(trace_tagged, len(trace_tagged), level)
time_tagged=np.linspace(time[0],time[-1],len(trace_tagged))
return trace_tagged,time_tagged
def Shifting (tr,delta):
tr_new = np.zeros(len(tr))
d = deque(tr)
d.rotate(int(-delta))
tr_new = np.array(d)
return tr_new
step=2
b=-2
w=3
t=np.arange(0,100,0.1)
n=2
W=np.zeros(len(t))
for i in range(len(t)):
W[i]=(t[i]**n)*math.exp(-b*t[i])*np.sin(w*t[i])
W1=W/W.max()
W_v1=np.where(W>0,W,0)
Vareas_mass=[]
Trace_mass=[]
Time_mass=[]
Num_of_traces=30
for k in range(Num_of_traces):
Traces=Shifting (W1,k*30)
Vareas = np.where(Traces>0,Traces,0)
Traces_step1,Time_step1=insert_zeros_in_trace(Traces)
Traces_step2,Time_step2=add_tags_for_varea(Traces_step1,Time_step1,0)
a=np.where(Traces_step2>0,Traces_step2,0)
Trace_mass.append(Traces_step2)
Vareas_mass.append(a)
Time_mass.append(Time_step2)
################################################################################
source_L = ColumnDataSource(dict(
xs=[Trace_mass[i]+2*i for i in range(Num_of_traces)],
ys=[Time_mass[i] for i in range(Num_of_traces)]
)
)
source_copy_L= ColumnDataSource(dict(
xs=[Trace_mass[i]+2*i for i in range(Num_of_traces)],
ys=[Time_mass[i] for i in range(Num_of_traces)]
)
)
source_P = ColumnDataSource(dict(
xs=[Vareas_mass[i]+2*i for i in range(Num_of_traces)],
ys=[Time_mass[i] for i in range(Num_of_traces)]
)
)
source_copy_P= ColumnDataSource(dict(
xs=[Vareas_mass[i]+2*i for i in range(Num_of_traces)],
ys=[Time_mass[i] for i in range(Num_of_traces)]
)
)
################################################################################
plot = figure( plot_width=1600, plot_height=800, x_range=(-5, 63))
gain_slider = Slider(start=-99., end=100., value=1., step=0.01, title="Gain",default_size=(300))
checkbox_button_group = CheckboxButtonGroup(labels=["Wiggle", "Clipping"], active=[0, 0])
glyph_L = MultiLine(xs="xs", ys="ys", line_color="#8073ac", line_width=2)
plot.add_glyph(source_L, glyph_L)
glyph_P = Patches(xs="xs", ys="ys", fill_color="#fb9a99",line_alpha=0.1)
plot.add_glyph(source_P, glyph_P)
callback = CustomJS(args=dict(c=step,source_L=source_L,source_copy_L=source_copy_L , source_P=source_P,source_copy_P=source_copy_P,gain=gain_slider,checkbox_button_group=checkbox_button_group),
code="""
var clip = c-0.1;
var paint = !!checkbox_button_group.active.includes(0);
console.log(paint)
var clipping = !!checkbox_button_group.active.includes(1);
console.log(clipping)
var data_L = source_L.data;
var data_copy_L = source_copy_L.data;
var data_P = source_P.data;
var data_copy_P = source_copy_P.data;
var G = gain.value;
for (var i = 0; i < data_L['xs'].length; i++) {
var Trace_mass_copy_L = data_copy_L['xs'][i]
var Vareas_mass_copy_P = data_copy_P['xs'][i]
var Trace_mass_L = data_L['xs'][i]
var Vareas_mass_P = data_P['xs'][i]
if (paint && clipping || clipping && paint){
for (var j = 0; j < Trace_mass_L.length; j++) {
Trace_mass_L[j]=((Trace_mass_copy_L[j]-c*i)*G);
Vareas_mass_P[j]=((Vareas_mass_copy_P[j]-c*i)*G);
if(Trace_mass_L[j]>=clip){
Trace_mass_L[j]=clip;
}
else if(Trace_mass_L[j]<-clip){
Trace_mass_L[j]=-clip;
}
if(Vareas_mass_P[j]>=clip){
Vareas_mass_P[j]=clip;
}
else if(Vareas_mass_P[j]<-clip){
Vareas_mass_P[j]=-clip;
}
Trace_mass_L[j]=Trace_mass_L[j]+c*i;
Vareas_mass_P[j]=Vareas_mass_P[j]+c*i;
}
}
if (paint && !clipping || !clipping && paint){
for (var j = 0; j < Trace_mass_L.length; j++) {
Trace_mass_L[j]=((Trace_mass_copy_L[j]-c*i)*G);
Vareas_mass_P[j]=((Vareas_mass_copy_P[j]-c*i)*G);
Trace_mass_L[j]=Trace_mass_L[j]+c*i;
Vareas_mass_P[j]=Vareas_mass_P[j]+c*i;
}
}
if (!paint && clipping || clipping && !paint){
for (var j = 0; j < Trace_mass_L.length; j++){
Trace_mass_L[j]=((Trace_mass_copy_L[j]-c*i)*G);
Vareas_mass_P[j] = 0+c*i;
if(Trace_mass_L[j]>=clip){
Trace_mass_L[j]=clip;
}
if(Trace_mass_L[j]<-clip){
Trace_mass_L[j]=-clip;
}
Trace_mass_L[j]=Trace_mass_L[j]+c*i;
}
}
if (!paint && !clipping || !clipping && !paint){
for (var j = 0; j < Trace_mass_L.length; j++) {
Trace_mass_L[j]=((Trace_mass_copy_L[j]-c*i)*G);
Vareas_mass_P[j] = 0+c*i;
Trace_mass_L[j]=Trace_mass_L[j]+c*i;
}
}
}
source_L.change.emit();
source_P.change.emit();
""")
checkbox_button_group.js_on_click(callback)
gain_slider.js_on_change('value', callback)
xaxis = LinearAxis()
plot.add_layout(xaxis, 'above')
yaxis = LinearAxis()
plot.add_layout(yaxis, 'right')
plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker))
plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker))
layout = row(
plot,
column(gain_slider, checkbox_button_group),
)
#curdoc().add_root(plot)
plot.y_range.flipped = True
show(layout)