title: Multiple questions with Object-Oriented Bokeh [OBSOLETE]
body: <hr>
  
  <hr>
  
  <hr>
  
  <p><strong><em>NOTE: This question concerns the "first generation" Bokeh server, which has been deprecated and removed for several years. Nothing in this question or its answers is relevant to any version of Bokeh >= 0.11</em></strong></p>
  
  <p><strong>For detailed information about using the modern, supported Bokeh Server, see the <a href="https://bokeh.pydata.org/en/latest/docs/user_guide/server.html" rel="nofollow noreferrer">Running a Bokeh Server</a> chapter of the User's Guide.</strong> </p>
  
  <hr>
  
  <hr>
  
  <hr>
  
  <p>I'm trying to understand <a href="http://bokeh.pydata.org/en/latest/" rel="nofollow noreferrer">Bokeh</a> for an interactive app that I'm building. I'm looking at the <a href="https://github.com/ContinuumIO/bokeh/tree/master/examples/" rel="nofollow noreferrer">Bokeh examples</a>, and I see that most of the examples are written all in the global namespace, but the ones in the "app" subdirectory are written in a nice, object-oriented style, where the main class inhereits from a Property class like HBox.</p>
  
  <p>This is going to be a mish-mash of questions because I don't think this way of programming Bokeh was very well-documented. The first thing I encountered was that the plot didn't draw unless I included <code>extra_generated_classes</code>.</p>
  
  <ol>
  <li><p><strong>What does extra_generated_classes do?</strong></p>
  
  <p>Secondly, it looks like the event loop <code>setup_events</code> is called on startup before <code>create</code> and subsequently every time the plot triggers an event.</p></li>
  <li><p><strong>Why does setup_events need to register callbacks each time an event is triggered? And why doesn't it wait for create to finish before attempting to register them the first time?</strong></p>
  
  <p>The last thing I'm unsure about is how to force a redraw of a Glyph here. The slider demo works for me, and I'm trying to do basically the same thing, except with a scatterplot instead of a line.</p>
  
  <p>I set a pdb trace at the very end of my <code>update_data</code>, and I can guarantee that <code>self.source</code> matches <code>self.plot.renderers[-1].data_source</code> and that both of them have been tweaked from the start. However, <code>self.plot</code> itself doesn't change.</p></li>
  <li><p><strong>What is the object-oriented approach's equivalent to calling store_objects to update the plot?</strong></p>
  
  <p>I'm especially confused by this third one, because it doesn't look like the sliders_app example needs anything like that. For clarification, I'm trying to make a variable number of widgets/sliders, so this is what my code looks like:</p></li>
  </ol>
  
  <p><strong>class attributes:</strong></p>
  
  <pre><code>extra_generated_classes = [['ScatterBias', 'ScatterBias', 'HBox']]
  maxval = 100.0
  
  inputs = Instance(bkw.VBoxForm)
  outputs = Instance(bkw.VBoxForm)
  plots = Dict(String, Instance(Plot))
  source = Instance(ColumnDataSource)
  
  
  cols = Dict(String, String)
  widgets = Dict(String, Instance(bkw.Slider))
  # unmodified source
  df0 = Instance(ColumnDataSource)
  </code></pre>
  
  <p><strong>initialize method</strong></p>
  
  <pre><code>@classmethod
  def create(cls):
      obj = cls()
  
      ##############################
      ## load DataFrame
      ##############################
      df = pd.read_csv('data/crime2013_tagged_clean.csv', index_col='full_name')
      obj.cols = {'x': 'Robbery', 
              'y': 'Violent crime total',
              'pop': 'Population'
              }
  
      cols = obj.cols
  
      # only keep interested values
      df2= df.ix[:, cols.values()]
  
      # drop empty rows
      df2.dropna(axis=0, inplace=True)
  
      df0 = df2.copy()
      df0.reset_index(inplace=True)
      # keep copy of original data
      obj.source = ColumnDataSource(df2)
      obj.df0 = ColumnDataSource(df0)
  
      ##############################
      ## draw scatterplot
      ##############################
  
      obj.plots = {
              'robbery': scatter(x=cols['x'],
                  y=cols['y'], 
                  source=obj.source,
                  x_axis_label=cols['x'],
                  y_axis_label=cols['y']),
              'pop': scatter(x=cols['pop'], 
                  y=cols['y'], 
                  source=obj.source,
                  x_axis_label=cols['pop'],
                  y_axis_label=cols['y'],
                  title='%s by %s, Adjusted by by %s'%(cols['y'], 
                      cols['pop'], cols['pop'])),
          }
  
      obj.update_data()
      ##############################
      ## draw inputs
      ##############################
      # bokeh.plotting.scatter 
      ## TODO: refactor so that any number of control variables are created
      # automatically. This involves subsuming c['pop'] into c['ctrls'], which
      # would be a dictionary mapping column names to their widget titles 
      pop_slider = obj.make_widget(bkw.Slider, dict(
              start=-obj.maxval, 
              end=obj.maxval, 
              value=0, 
              step=1, 
              title='Population'), 
          cols['pop'])
  
      ##############################
      ## make layout
      ##############################
      obj.inputs = bkw.VBoxForm(
              children=[pop_slider]
              )
  
      obj.outputs = bkw.VBoxForm(
              children=[obj.plots['robbery']]
          )
  
      obj.children.append(obj.inputs)
      obj.children.append(obj.outputs)
  
      return obj
  </code></pre>
  
  <p><strong>update_data</strong></p>
  
  <pre><code>def update_data(self):
      """Update y by the amount designated by each slider"""
      logging.debug('update_data')
      c = self.cols
      ## TODO:: make this check for bad input; especially with text boxes
      betas = { 
              varname: getattr(widget, 'value')/self.maxval 
              for varname, widget in self.widgets.iteritems()
              }
  
      df0 = pd.DataFrame(self.df0.data)
      adj_y = []
      for ix, row in df0.iterrows():
          ## perform calculations and generate new y's
          adj_y.append(self.debias(row))
  
      self.source.data[c['y']] = adj_y
      assert len(adj_y) == len(self.source.data[c['x']])
      logging.debug('self.source["y"] now contains debiased data')
  
      import pdb; pdb.set_trace()
  </code></pre>
  
  <p>Note that I am sure that the event handler gets setup and triggered correctly. I just don't know how to make the changed source data reflect in the scatterplot.</p>