kivy-garden / garden.matplotlib

Matplotlib backends using kivy
MIT License
103 stars 50 forks source link

grids are not drawn if they are specified for the figure #35

Closed janssen closed 7 years ago

janssen commented 8 years ago

Try

plt.grid(b=True, which='major', axis='both', color='black')
janssen commented 8 years ago

Wonder if this is related to #16. Drawing grid lines is so far above the level of backend_kivy that I'd think nothing else could affect it.

janssen commented 8 years ago

When I switch to FigureCanvasKivyAgg, I get the grid lines.

andnovar commented 8 years ago

I don't think it is related. This is happening with matplotlib > 1.5 . It works fine with 1.4.3. I checked the path collection and seems that the grids are not there anymore together with the background color face.

Kivy screenshot from 2016-04-11 03 27 22

KivyAgg screenshot from 2016-04-11 03 28 14

WX Backend screenshot from 2016-04-11 03 29 32

andnovar commented 8 years ago

Related:--> https://github.com/matplotlib/matplotlib/issues/6289

janssen commented 8 years ago

I notice that the Path.to_polygons() call in RenderKivy.draw_path() returns an empty list of polygons for many of the paths passed to it, e.g.

Path(array([[ 0.5,  0. ],
            [ 0.5,  1. ]]), None) , color None , width 1100.0 , height 794.528043776  => []

I think these are the missing grid lines. Any path with only two vertices that has a 0.0 value for either the x or y coordinate of the first vertex is getting clipped. Or maybe it's any path with only two vertices.

janssen commented 8 years ago

I'm using matplotlib 1.5.1.

janssen commented 8 years ago

I got my grids to draw with two changes:

  1. In RendererKivy.draw_path(), if Path.to_polygons() returns an empty list, build your own polygon:

    if not polygons:
       polygons = [np.array(map(transform.transform_point, path.vertices))]
  2. In RendererKivy.get_graphics(), change

    if _mpl_1_5 and closed:
       points_poly_line = points_line[:-2]
    else:
       points_poly_line = points_line

    to

    if _mpl_1_5 and closed and len(points_line) > 4:
       points_poly_line = points_line[:-2]
    else:
       points_poly_line = points_line
andnovar commented 8 years ago

I think step 2 are both the same. Step 1 can be a temporary solution not sure if it will work for everything.

janssen commented 8 years ago

Sorry, my mistake. I mistyped step 2, and I've edited it to fix it. The key idea is not to trim if there are only two points.

I agree about step 2. The real answer is that the matplotlib developers should fix their to_polygons() method. And my trick won't help with markers, which have the same to_polygons() problem.

andnovar commented 8 years ago

I print both info for path and transform in both 1.4.3 and 1.5.1 --> https://gist.github.com/andnovar/b7f3cf9fde41830d8e5adae406e95e26 to_polygon(path, width, height) accepts width and height for clipping purposes which I was setting to the width and height of the widget. I assumed there won't be any path out of the bounds of the widget. If the width and height are 0 the polygon is being calculated but some are out of bounds.

The method to_polygon works fine. The file path_test.py run different paths from the log and the results are the same in both matplotlib versions. However path and transform arrays are not consistent and seem to be clipped by the algorithm. I suspect the problem is either in:

tess.add_contour(points_line)

or where handling the clip rectangle

newclip = self.handle_clip_rectangle(gc, x, y)

The points are clipped since they are out of 500, 450 like these set of vertices:

[array([[ 100., 60.], [ 100., 540.]])]

[array([[ 720., 60.], [ 720., 540.]])]

The problem seems to be the transform.

janssen commented 8 years ago

From your example, take this line:

The path is 
Path(array([[  0.175,  18.   ],
       [  0.175,  22.   ]]), None) 
 And Transform is 
Affine2D(array([[ 99.2,   0. ,  80. ],
       [  0. ,   9.6,  48. ],
       [  0. ,   0. ,   1. ]])) 
 and polygons from there 
[array([[  97.36,  220.8 ]])] 

That "polygon" is just one point. You can't draw a line with that, can you?

janssen commented 8 years ago

So, what can we do to motivate a fix for this?

dessant commented 8 years ago

We can enable bountysource for the repo, if needed.

janssen commented 8 years ago

Not sure that would help. The problem seems to be with matplotlib's to_polygons() and/or the transform. I looked at the matplotlib code, https://github.com/matplotlib/matplotlib/blob/master/src/_path.h, but couldn't pick out any problems.

janssen commented 8 years ago

I suppose another way to go would be to re-implement the drawing code here to avoid the use of to_polygons().

janssen commented 8 years ago

We have some movement on this. A fix has been added to the matplotlib code; however, it requires that Kivy pass an additional flag to to_polygons(). See the related Matplotlib issue https://github.com/matplotlib/matplotlib/issues/6289. Looks like it won't land until the 2.0 release of matplotlib.

janssen commented 7 years ago

I've created a pull request which fixes this.

janssen commented 7 years ago

I've tested on Windows with the 2.0.0 release of matplotlib. Still no grid lines.

janssen commented 7 years ago

I'll test on Windows again with the latest patches to backend_kivy.py, and see if I can resolve this.

janssen commented 7 years ago

I've now figured out I was testing with the wrong configuration on Windows. This is fixed.