code: ''' An interactive plot of the ``sin`` function. This example demonstrates
  adding widgets and ``CustomJS`` callbacks that can update a plot.
  
  .. bokeh-example-metadata::
      :apis: bokeh.plotting.Figure.line, bokeh.layouts.column, bokeh.layouts.row, bokeh.models.callbacks.CustomJS, bokeh.models.widgets.sliders.Slider
      :refs: :ref:`userguide_interaction_jscallbacks` > :ref:`userguide_interaction_jscallbacks_customjs`
      :keywords: javascript callback
  
  '''
  import numpy as np
  
  from bokeh.layouts import column, row
  from bokeh.models import CustomJS, Slider
  from bokeh.plotting import ColumnDataSource, figure, show
  
  x = np.linspace(0, 10, 500)
  y = np.sin(x)
  
  source = ColumnDataSource(data=dict(x=x, y=y))
  
  plot = figure(y_range=(-10, 10), width=400, height=400)
  
  plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
  
  amp_slider = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
  freq_slider = Slider(start=0.1, end=10, value=1, step=.1, title="Frequency")
  phase_slider = Slider(start=0, end=6.4, value=0, step=.1, title="Phase")
  offset_slider = Slider(start=-5, end=5, value=0, step=.1, title="Offset")
  
  callback = CustomJS(args=dict(source=source, amp=amp_slider, freq=freq_slider, phase=phase_slider, offset=offset_slider),
                      code="""
      const data = source.data;
      const A = amp.value;
      const k = freq.value;
      const phi = phase.value;
      const B = offset.value;
      const x = data['x']
      const y = data['y']
      for (let i = 0; i < x.length; i++) {
          y[i] = B + A*Math.sin(k*x[i]+phi);
      }
      source.change.emit();
  """)
  
  amp_slider.js_on_change('value', callback)
  freq_slider.js_on_change('value', callback)
  phase_slider.js_on_change('value', callback)
  offset_slider.js_on_change('value', callback)
  
  layout = row(
      plot,
      column(amp_slider, freq_slider, phase_slider, offset_slider),
  )
  
  show(layout)
  
apis: numpy.sin numpy.linspace