Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contourf error #40

Open
quai20 opened this issue May 24, 2017 · 12 comments
Open

contourf error #40

quai20 opened this issue May 24, 2017 · 12 comments

Comments

@quai20
Copy link

quai20 commented May 24, 2017

Hi,
Really great work it's an amazing tool. I managed to make the contour example work and one of my contour plot also. But when I switch the plot to contourf (wich is ok with my plt.show()), mplleaflet crashes with this error :

Traceback (most recent call last):
  File "readnc_kb.py", line 37, in <module>
    mplleaflet.show(path='test.html')
  File "/usr/lib/python2.7/site-packages/mplleaflet/_display.py", line 180, in show
    save_html(fig, fileobj=f, **kwargs)
  File "/usr/lib/python2.7/site-packages/mplleaflet/_display.py", line 131, in save_html
    html = fig_to_html(fig, **kwargs)
  File "/usr/lib/python2.7/site-packages/mplleaflet/_display.py", line 84, in fig_to_html
    exporter.run(fig)
  File "/usr/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.py", line 51, in run
    self.crawl_fig(fig)
  File "/usr/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.py", line 118, in crawl_fig
    self.crawl_ax(ax)
  File "/usr/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.py", line 140, in crawl_ax
    self.draw_collection(ax, collection)
  File "/usr/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.py", line 272, in draw_collection
    mplobj=collection)
  File "/usr/lib/python2.7/site-packages/mplleaflet/mplexporter/renderers/base.py", line 272, in draw_path_collection
    mplobj=mplobj)
  File "/usr/lib/python2.7/site-packages/mplleaflet/leaflet_renderer.py", line 125, in draw_path
    rings = list(iter_rings(data, pathcodes))
  File "/usr/lib/python2.7/site-packages/mplleaflet/utils.py", line 14, in iter_rings
    raise ValueError('Unrecognized code: {}'.format(code))
ValueError: Unrecognized code: Z

Any ideas ?

@jwass
Copy link
Owner

jwass commented May 25, 2017

Hi @quai20 - can you provide a short example demonstrating this?

@quai20
Copy link
Author

quai20 commented May 28, 2017

of course, here's my example :

`#READING
from netCDF4 import Dataset
import numpy as np

my_nc_file = 'NRTOAGL01_20150315_fld_TEMP.nc'
fh = Dataset(my_nc_file, mode='r')

LON=fh.variables['longitude'][:]
LAT=fh.variables['latitude'][:]
TEMP=fh.variables['TEMP'][:]
TEMP=TEMP[0,0,:,:]
fh.close()

#PLOTTING
import matplotlib.pyplot as plt
import mplleaflet

#contouring
xx, yy = np.meshgrid(LON, LAT)
#THIS WORKS WITH plt.show() AND MPLLEAFLET
aa = plt.contour(xx, yy, TEMP,50)
#THIS WORKS WITH plt.show() BUT CRASHES WITH MPLLEAFLET (error above)
#aa = plt.contourf(xx, yy, TEMP,50)

#plt.show()
mplleaflet.show(path='test.html')
`

The data file is here if needed : https://cloud.ifremer.fr/index.php/s/moxThfGrVPQaHWi

@eazytracer
Copy link

eazytracer commented Jul 2, 2017

I am running into the same issue now. I can plot the contour just fine, contourf works with pyplot, but gives the following error with mplleaflet.

ValueErrorTraceback (most recent call last)
<ipython-input-149-87023e0e107a> in <module>()
----> 1 mplleaflet.show()

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/_display.pyc in show(fig, path, **kwargs)
    178     fullpath = os.path.abspath(path)
    179     with open(fullpath, 'w') as f:
--> 180         save_html(fig, fileobj=f, **kwargs)
    181     webbrowser.open('file://' + fullpath)

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/_display.pyc in save_html(fig, fileobj, **kwargs)
    129     if not hasattr(fileobj, 'write'):
    130         raise ValueError("fileobj should be a filename or a writable file")
--> 131     html = fig_to_html(fig, **kwargs)
    132     fileobj.write(html)
    133     fileobj.close()

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/_display.pyc in fig_to_html(fig, template, tiles, crs, epsg, embed_links)
     82     renderer = LeafletRenderer(crs=crs, epsg=epsg)
     83     exporter = Exporter(renderer)
---> 84     exporter.run(fig)
     85 
     86     attribution = _attribution + ' | ' + tiles[1]

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.pyc in run(self, fig)
     49             import matplotlib.pyplot as plt
     50             plt.close(fig)
---> 51         self.crawl_fig(fig)
     52 
     53     @staticmethod

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.pyc in crawl_fig(self, fig)
    116                                        props=utils.get_figure_properties(fig)):
    117             for ax in fig.axes:
--> 118                 self.crawl_ax(ax)
    119 
    120     def crawl_ax(self, ax):

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.pyc in crawl_ax(self, ax)
    138                 self.draw_patch(ax, patch)
    139             for collection in ax.collections:
--> 140                 self.draw_collection(ax, collection)
    141             for image in ax.images:
    142                 self.draw_image(ax, image)

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/mplexporter/exporter.pyc in draw_collection(self, ax, collection, force_pathtrans, force_offsettrans)
    270                                            offset_order=offset_order,
    271                                            styles=styles,
--> 272                                            mplobj=collection)
    273 
    274     def draw_image(self, ax, image):

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/mplexporter/renderers/base.pyc in draw_path_collection(self, paths, path_coordinates, path_transforms, offsets, offset_coordinates, offset_order, styles, mplobj)
    270                            pathcodes=pathcodes, style=style, offset=offset,
    271                            offset_coordinates=offset_coordinates,
--> 272                            mplobj=mplobj)
    273 
    274     def draw_markers(self, data, coordinates, style, label, mplobj=None):

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/leaflet_renderer.pyc in draw_path(self, data, coordinates, pathcodes, style, offset, offset_coordinates, mplobj)
    123             else:
    124                 data = [c.tolist() for c in data]
--> 125             rings = list(iter_rings(data, pathcodes))
    126 
    127             if style['facecolor'] != 'none':

/Users/midgetracer/miniconda3/envs/iris_lab/lib/python2.7/site-packages/mplleaflet/utils.pyc in iter_rings(data, pathcodes)
     12             ring.append(point)
     13         else:
---> 14             raise ValueError('Unrecognized code: {}'.format(code))
     15 
     16     if len(ring):

ValueError: Unrecognized code: Z

Code:

import mplleaflet
from matplotlib.colors import LinearSegmentedColormap
import matplotlib.pyplot as plt
import pygrib
import single_point

files = ["gfs.t12z.pgrb2.0p25.f006",
         "hrrr.t23z.wrfsfcf02.grib2",
         "hrrr.t01z.wrfsfcf06.grib2"]

hrrr = pygrib.open(files[2])

hrrr.seek(0)
ref = hrrr.select(name="Maximum/Composite radar reflectivity")[0]
radar = ref.values
lats, lons = ref.latlons()

clevs = [20,30,40,50,60,70]
cmap = LinearSegmentedColormap.from_list("my_colormap",                    
                                        [[0.063, 0.306, 0.545],
                                        [0.000, 0.804, 0.000],
                                        [0.933, 0.933, 0.000],
                                        [0.804, 0.000, 0.000],
                                        [0.000, 1.000, 1.000]],
                                        N=5,
                                        gamma=1.0)
                                         
cs = plt.contourf(lons, lats, radar, clevs, cmap=cmap)

#plt.show()

mplleaflet.show()

Seems as if a ring isn't completed and is throwing an error perhaps?

contourf plotting with pyplot

screen shot 2017-07-02 at 10 35 46 am

contour plotting with mplleaflet
screen shot 2017-07-02 at 10 17 33 am

@disarticulate
Copy link
Contributor

Got the same error. Added this to the code to bypass it.

elif code == 'L' or code == 'Z' or code == 'S':

@anderl80
Copy link

anderl80 commented Dec 5, 2017

The same issue here for me..

@YaSergo
Copy link

YaSergo commented Dec 6, 2017

@anderl80 check link above: #45
There you can found solution of problem. If you still have problems just ask.

@jwass Maybe it's time to make changes in the code? =)

@techkuz
Copy link

techkuz commented Feb 14, 2018

@jwass , please make changes in the code

@Agnpalm
Copy link

Agnpalm commented Mar 14, 2018

Is this being worked on? I have almost the exact same problem. I'm trying to plot rings, and I get the error Unrecognized code: C

For reference, this is what it looks like in matplotlib:
image

And this is the error:

ValueError                                Traceback (most recent call last)
<ipython-input-65-bae575a61e87> in <module>()
     19 ax.set_ylim([27.5, 50])
     20 
---> 21 mplleaflet.show(fig = ax.figure)
     22 # plt.show()

c:\python36\lib\site-packages\mplleaflet\_display.py in show(fig, path, **kwargs)
    178     fullpath = os.path.abspath(path)
    179     with open(fullpath, 'w') as f:
--> 180         save_html(fig, fileobj=f, **kwargs)
    181     webbrowser.open('file://' + fullpath)

c:\python36\lib\site-packages\mplleaflet\_display.py in save_html(fig, fileobj, **kwargs)
    129     if not hasattr(fileobj, 'write'):
    130         raise ValueError("fileobj should be a filename or a writable file")
--> 131     html = fig_to_html(fig, **kwargs)
    132     fileobj.write(html)
    133     fileobj.close()

c:\python36\lib\site-packages\mplleaflet\_display.py in fig_to_html(fig, template, tiles, crs, epsg, embed_links)
     82     renderer = LeafletRenderer(crs=crs, epsg=epsg)
     83     exporter = Exporter(renderer)
---> 84     exporter.run(fig)
     85 
     86     attribution = _attribution + ' | ' + tiles[1]

c:\python36\lib\site-packages\mplleaflet\mplexporter\exporter.py in run(self, fig)
     49             import matplotlib.pyplot as plt
     50             plt.close(fig)
---> 51         self.crawl_fig(fig)
     52 
     53     @staticmethod

c:\python36\lib\site-packages\mplleaflet\mplexporter\exporter.py in crawl_fig(self, fig)
    116                                        props=utils.get_figure_properties(fig)):
    117             for ax in fig.axes:
--> 118                 self.crawl_ax(ax)
    119 
    120     def crawl_ax(self, ax):

c:\python36\lib\site-packages\mplleaflet\mplexporter\exporter.py in crawl_ax(self, ax)
    138                 self.draw_patch(ax, patch)
    139             for collection in ax.collections:
--> 140                 self.draw_collection(ax, collection)
    141             for image in ax.images:
    142                 self.draw_image(ax, image)

c:\python36\lib\site-packages\mplleaflet\mplexporter\exporter.py in draw_collection(self, ax, collection, force_pathtrans, force_offsettrans)
    270                                            offset_order=offset_order,
    271                                            styles=styles,
--> 272                                            mplobj=collection)
    273 
    274     def draw_image(self, ax, image):

c:\python36\lib\site-packages\mplleaflet\mplexporter\renderers\base.py in draw_path_collection(self, paths, path_coordinates, path_transforms, offsets, offset_coordinates, offset_order, styles, mplobj)
    270                            pathcodes=pathcodes, style=style, offset=offset,
    271                            offset_coordinates=offset_coordinates,
--> 272                            mplobj=mplobj)
    273 
    274     def draw_markers(self, data, coordinates, style, label, mplobj=None):

c:\python36\lib\site-packages\mplleaflet\leaflet_renderer.py in draw_path(self, data, coordinates, pathcodes, style, offset, offset_coordinates, mplobj)
    123             else:
    124                 data = [c.tolist() for c in data]
--> 125             rings = list(iter_rings(data, pathcodes))
    126 
    127             if style['facecolor'] != 'none':

c:\python36\lib\site-packages\mplleaflet\utils.py in iter_rings(data, pathcodes)
     12             ring.append(point)
     13         else:
---> 14             raise ValueError('Unrecognized code: {}'.format(code))
     15 
     16     if len(ring):

ValueError: Unrecognized code: C

And this is the code I'm using to generate it:

import matplotlib.pyplot as plt
from matplotlib.patches import Wedge
from matplotlib.collections import PatchCollection
import mplleaflet

lon = -77.036451
lat = 38.897503

patches = []
ring = Wedge((lon, lat), 10, 0, 360, width=4)
patches.append(ring)

p = PatchCollection(patches, alpha=0.6)

fig, ax = plt.subplots()
ax.add_collection(p)
ax.set_xlim([-87.5, -65])
ax.set_ylim([27.5, 50])

# mplleaflet.show(fig = ax.figure)
plt.show()

The solution given above does not work, since the C code is a Bezier Curve, and treating it like the L command gives a weird shape:
image

If Matplotlib is using Bezier curves it's probably a good idea for mplleaflet to support them as well.

Edit: I did some light debugging. The pathcodes that gets passed to iter_rings in my case is:

'M', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'M', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'M', 'Z'

and the data is this (abbreviated):

[[-67.036451, 38.897503], [-67.036451, 40.210690968073855], [-67.29512039592409, 41.51110983760738], [-67.79765567488712, 42.7243373236509], [-68.30019095385018, 43.93756480969442], [-69.03681907093691, 45.040006694667866]

The main thing to notice is that the first command is the M command (Move to), which takes two parameters. The C command however, takes three sets of pairs as parameters, yet the data (point in the for loop in iter_rings) only contains two parameters.

You can also note that the Z command doesn't take any arguments at all, but the workaround above seems to work anyway since the data is probably an empty list, although I haven't checked. Similarly, the workaround above includes the S command, but that's also a type of Bezier curve and it will most probably produce the wrong result.

I tried changing iter_rings to add a different number of parameters depending on what command it was processing, but that didn't work. I suspect that either there's something wrong with my code, or whatever code is consuming the output of iter_rings doesn't expect data in anything else than pairs, or both.
Anyway, this is my non functioning code:

def iter_rings(data, pathcodes):
    ring = []
    i = 0
    # TODO: Do this smartly by finding when pathcodes changes value and do
    # smart indexing on data, instead of iterating over each coordinate
    for code in pathcodes:
        if code == 'M':
            # Emit the path and start a new one
            if len(ring):
                yield ring
            ring = [data[i:i+2]]
            i += 2
        elif code == 'L':
            ring.append(point)
        elif code == 'Z':
            ring.append([])
        elif code == 'C':
            params = []
            params.extend(data[i:i+2])
            params.extend(',')
            i += 2
            params.extend(data[i:i+2])
            params.extend(',')
            i += 2
            params.extend(data[i:i+2])
            i += 2
            ring.append(params)
        else:
            raise ValueError('Unrecognized code: {}'.format(code))

    if len(ring):
        yield ring

When I look at the HTML output it seems as if the data gets divided into pairs somewhere anyway:

{"type": "Polygon", "coordinates": [[[[-67.036451, 38.897503], [-67.036451, 40.210690968073855]], [[-67.29512039592409, 41.51110983760738], [-67.79765567488712, 42.7243373236509], ",", [-68.30019095385018, 43.93756480969442], [-69.03681907093691, 45.040006694667866], ",", [-69.96538318813452, 45.968570811865476], [-70.89394730533213, 46.897134929063085]], [[-71.99638919030558, 47.633763046149824], [-73.2096166763491, 48.13629832511287], ",", [-74.42284416239262, 48.63883360407591], [-75.72326303192614, 48.897503], ",",
 ... and so on

@jwass
Copy link
Owner

jwass commented Mar 17, 2018

@disarticulate Can you post a pull request with the change to fix this?

disarticulate added a commit to disarticulate/mplleaflet that referenced this issue Mar 17, 2018
I don't know what the other letters are for. But it resolves the error.

Might want to add a test.
@disarticulate
Copy link
Contributor

disarticulate commented Mar 17, 2018

ask and you shall receive
#51

jwass added a commit that referenced this issue Mar 18, 2018
@jwass
Copy link
Owner

jwass commented Mar 18, 2018

@disarticulate You rock! Thanks.
I'll try to push a new release next few days.

@Agnpalm
Copy link

Agnpalm commented Mar 22, 2018

I hope I don't offend anyone, but #51 is not a fix to this issue. I left a comment there as well, but I thought my lengthy comment above in this issue explained pretty well what was wrong. The main issue that should be addressed is that SVG contain codes that take a different amount of parameters, not only 2 like L. With #51 you will still have issues with cirlces and other shapes that use Bezier paths. In my example above the SVG that was emitted contains C and Z codes, neither of which will work correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants