These are random notes as I'm understanding how ggplot is put together (and
also learn a bit more concretely about GG itself).

The geom_abline example shows how if the data supplied to the geom function is vector with regards to the dimensionality of the geom, then it broadcasts.  I wonder how R is implementing this under the hood, or if it's some special case code.

Some functions have parameters that control the widget's appearance, and which can oftentimes accept any aesthetic.


-----------


  Data(mydata):
    PanelGrid:
      cols: f1   # These are attributes of the PanelGrid itself
      rows: f2
      
      # These aesthetic parameters are templates for the geoms contained
      # within the PanelGrid.  There is a separate instance of each geom
      # for each of the factors in each of the aesthetic parameters below.
      # When multiple parameters are faceted like this, there is a cartesian
      # product of possibilities created.
      color: f3
      size: f4

      # To avoid the Cartesian product/combinatoric explosion of different
      # factors, use the set algebra operators:
      color: f3 + f4
      size: f3 + f4

      # Alternatively:
      color, size, linedash: f3 / f4

      ## It is also possible to define an explicit named grouping 

      # Basic plot:
      Dot:
        x: m1
        y: m2

      # Inheritance from other plots, via naming
      scatter = Dot(x=m1, y=m2)
      Wedge(scatter):   # inherits x,y from scatter
        r1 = m3
        r2 = m4
        color = m5

      # Composition - referencing other instances of a data series
      Area:
        left: m1
        right: m1+10
        
        bottom: m2+parent(PanelGrid).index

      # Related panels - walk up the containment hierarchy


------------

    with bokeh.Data(mydata):
        grid = bokeh.facet_grid(cols=factor1, rows=factor2)
        grid.style(color=factor3, size=factor4)

        # Alternatives:
        # grid.style(bokeh.style(color=factor3+factor4))
        # grid.style(bokeh.style(color=bokeh.blend(f3, f4)))

        d = bokeh.dot(x=m1, y=m2)
        a = bokeh.area(left=d.x, top=d.y)
        grid.add(d, a)

        # Alternatively:
        d = panel.dot(x=m1, y=m2)
        grid.area(left=d.x, top=d.y)
            

    # Alternatively, without using withhacks:
    scene = bokeh.scene(mydata)
    grid = scene.facet_grid(cols="factor1", rows="factor2")


Creating a dot plot and applying it to a rendering site with greater dimensionality will automatically vectorize it over the outer dimensions:

    scene = bokeh.scene(mydata)

    # Assuming mydata has fields f1, f2, m1, m2, then the following
    # code would produce a single scatter plot with all the m1 and m2
    # values from all f1 and f2 values:
    scene.add(bokeh.dot(x="m1", y="m2"))

    # The following would create several colored scatter plots in the
    # same panel, with colors corresponding to the factors of f1
    d = bokeh.dot(x="m1", y="m2")
    scene.style(color="f1")
    scene.add(d)


Since so much of the code operates on objects that are representing the scene graph, there is an explicit command to trigger rendering of the scene:

    scene.render()

This causes the scene graph to be processed, new viewmodels to be created, and actual data to be loaded and rendered.

For animated and interactive purposes, this sort of one-shot rendering is not the most efficient model, and it should instead be broken down into two different things:

    scene.create_pipeline()
    scene.update_pipeline()

The latter is meant to mostly deal with just the data updates in the system, and does not need to do some of the object creation that is in create_pipeline.  It mainly pumps new data to the actual output renderers, and then requests a repaint from the host graphics/GUI system.





