Repository: bokeh/bokeh

Issue:
compat/seaborn/sinerror.py is broken
Really weird because seems to work before the last release and it is not working now...

Something interesting to mention... sometimes it appears OK, seems to be a random factor involved in some way...

![sin](https://cloud.githubusercontent.com/assets/1640669/7997874/759bb452-0b0a-11e5-8627-a4143a11922c.png)



Discussion:
There is no traceback in the python or the js side...
pinging @bokeh/core for ideas... :wink:

Pretty sure it has to do with lack of control over glyph rendering order  

There still seem to be issues here. Somehow the render order is still not being controlled. I wonder if this is on the python side tho. For reference, here are two screen caps of the violin plot taken one after the other:
![screen shot 2015-06-27 at 9 41 03 am](https://cloud.githubusercontent.com/assets/1078448/8392442/d1252486-1cb0-11e5-8bfb-8d46a7e1f15b.png)

![screen shot 2015-06-27 at 9 40 54 am](https://cloud.githubusercontent.com/assets/1078448/8392445/d43adb70-1cb0-11e5-8973-b3046916df7f.png)

@damianavila is it possible there is some indeterminacy in the order that renderers are generated  by `mplexporer` or `mpl.to_bokeh`?

As an aside it would be nice if the outlines could be handled by the patches glyph itself, but I am guessing thesis a result of how sns/mpl do things

Here's another one I haven't seen before
![screen shot 2015-06-27 at 9 52 49 am](https://cloud.githubusercontent.com/assets/1078448/8392488/50d13c8c-1cb2-11e5-8aba-3936f8bf2b6b.png)

@damianavila @fpliger @canavandl no the problem is that we are constructing uneven column data sources. This is from the `sinerror.py` code:

```
In [31]: col_lengths = [len(x) for x in p.select(ColumnDataSource)[0].data.values()]

In [32]: print(min(col_lengths), max(col_lengths))
2 100
```

That's why only two of the circle are getting draw, and why only two of the points in the line are drawn. Basically it will stop with the shortest sequence. 

I am guessing the problem is in our `mpl` code, it needs to not try and use the same `ColumnDataSource` all the time.

I'm not sure if this is the same problem affecting the violin plot or not. 

>  uneven column data sources

We need to validate this... and I see you opened a PR on this matter, thanks!

> I'm not sure if this is the same problem affecting the violin plot or not.

It could be, we need to investigate on this side...

seaborn 0.6 changed the violin plot quite a bit, to the point that we can basically no longer process them. I think we well need a pretty thorough review of our MPL compat soon, possibly choosing some features to try and commit back to `mplexporter`. 

> I think we well need a pretty thorough review of our MPL compat soon, possibly choosing some features to try and commit back to mplexporter.

Yes, I agree...


Resolving patch:
diff --git a/bokeh/mpl.py b/bokeh/mpl.py
--- a/bokeh/mpl.py
+++ b/bokeh/mpl.py
@@ -49,7 +49,6 @@ def __init__(self, pd_obj, xkcd):
         self.fig = None
         self.pd_obj = pd_obj
         self.xkcd = xkcd
-        self.source = ColumnDataSource()
         self.xdr = DataRange1d()
         self.ydr = DataRange1d()
         self.non_text = [] # to save the text we don't want to convert by draw_text
@@ -169,8 +168,9 @@ def draw_line(self, data, coordinates, style, label, mplobj=None):
             x, y = xkcd_line(x, y)
 
         line = Line()
-        line.x = self.source.add(x)
-        line.y = self.source.add(y)
+        source = ColumnDataSource()
+        line.x = source.add(x)
+        line.y = source.add(y)
 
         line.line_color = style['color']
         line.line_width = style['linewidth']
@@ -182,7 +182,7 @@ def draw_line(self, data, coordinates, style, label, mplobj=None):
         if self.xkcd:
             line.line_width = 3
 
-        self.plot.add_glyph(self.source, line)
+        self.plot.add_glyph(source, line)
 
     def draw_markers(self, data, coordinates, style, label, mplobj=None):
         "Given a mpl line2d instance create a Bokeh Marker glyph."
@@ -207,8 +207,9 @@ def draw_markers(self, data, coordinates, style, label, mplobj=None):
         except KeyError:
             warnings.warn("Unable to handle marker: %s; defaulting to Circle" % style['marker'])
             marker = Circle()
-        marker.x = self.source.add(x)
-        marker.y = self.source.add(y)
+        source = ColumnDataSource()
+        marker.x = source.add(x)
+        marker.y = source.add(y)
 
         marker.line_color = style['edgecolor']
         marker.fill_color = style['facecolor']
@@ -217,7 +218,7 @@ def draw_markers(self, data, coordinates, style, label, mplobj=None):
         marker.fill_alpha = marker.line_alpha = style['alpha']
         #style['zorder'] # not in Bokeh
 
-        self.plot.add_glyph(self.source, marker)
+        self.plot.add_glyph(source, marker)
 
     def draw_path_collection(self, paths, path_coordinates, path_transforms,
                              offsets, offset_coordinates, offset_order,
@@ -257,7 +258,8 @@ def draw_text(self, text, position, coordinates, style,
             #if mplText.get_weight() in ("bold", "heavy"):
                 #text.text_font_style = bold
 
-            self.plot.add_glyph(self.source, text)
+            source = ColumnDataSource()
+            self.plot.add_glyph(source, text)
 
     def draw_image(self, imdata, extent, coordinates, style, mplobj=None):
         pass
@@ -326,12 +328,13 @@ def make_line_collection(self, col):
             ys = xkcd_ys
 
         multiline = MultiLine()
-        multiline.xs = self.source.add(xs)
-        multiline.ys = self.source.add(ys)
+        source = ColumnDataSource()
+        multiline.xs = source.add(xs)
+        multiline.ys = source.add(ys)
 
-        self.multiline_props(multiline, col)
+        self.multiline_props(source, multiline, col)
 
-        self.plot.add_glyph(self.source, multiline)
+        self.plot.add_glyph(source, multiline)
 
     def make_poly_collection(self, col):
         "Given a mpl collection instance create a Bokeh Patches glyph."
@@ -342,19 +345,20 @@ def make_poly_collection(self, col):
         ys = [polygons[i][1] for i in range(len(polygons))]
 
         patches = Patches()
-        patches.xs = self.source.add(xs)
-        patches.ys = self.source.add(ys)
+        source = ColumnDataSource()
+        patches.xs = source.add(xs)
+        patches.ys = source.add(ys)
 
-        self.patches_props(patches, col)
+        self.patches_props(source, patches, col)
 
-        self.plot.add_glyph(self.source, patches)
+        self.plot.add_glyph(source, patches)
 
-    def multiline_props(self, multiline, col):
+    def multiline_props(self, source, multiline, col):
         "Takes a mpl collection object to extract and set up some Bokeh multiline properties."
         colors = get_props_cycled(col, col.get_colors(), fx=lambda x: mpl.colors.rgb2hex(x))
         widths = get_props_cycled(col, col.get_linewidth())
-        multiline.line_color = self.source.add(colors)
-        multiline.line_width = self.source.add(widths)
+        multiline.line_color = source.add(colors)
+        multiline.line_width = source.add(widths)
         multiline.line_alpha = col.get_alpha()
         offset = col.get_linestyle()[0][0]
         if not col.get_linestyle()[0][1]:
@@ -364,14 +368,14 @@ def multiline_props(self, multiline, col):
         multiline.line_dash_offset = convert_dashes(offset)
         multiline.line_dash = list(convert_dashes(tuple(on_off)))
 
-    def patches_props(self, patches, col):
+    def patches_props(self, source, patches, col):
         "Takes a mpl collection object to extract and set up some Bokeh patches properties."
         face_colors = get_props_cycled(col, col.get_facecolors(), fx=lambda x: mpl.colors.rgb2hex(x))
-        patches.fill_color = self.source.add(face_colors)
+        patches.fill_color = source.add(face_colors)
         edge_colors = get_props_cycled(col, col.get_edgecolors(), fx=lambda x: mpl.colors.rgb2hex(x))
-        patches.line_color = self.source.add(edge_colors)
+        patches.line_color = source.add(edge_colors)
         widths = get_props_cycled(col, col.get_linewidth())
-        patches.line_width = self.source.add(widths)
+        patches.line_width = source.add(widths)
         patches.line_alpha = col.get_alpha()
         patches.fill_alpha = col.get_alpha()
         offset = col.get_linestyle()[0][0]


Test patch: