mplleaflet
mplleaflet copied to clipboard
contourf error
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 ?
Hi @quai20 - can you provide a short example demonstrating this?
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
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

contour plotting with mplleaflet
Got the same error. Added this to the code to bypass it.
elif code == 'L' or code == 'Z' or code == 'S':
The same issue here for me..
@anderl80 check link above: https://github.com/jwass/mplleaflet/issues/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? =)
@jwass , please make changes in the code
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:
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:
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
@disarticulate Can you post a pull request with the change to fix this?
ask and you shall receive https://github.com/jwass/mplleaflet/pull/51
@disarticulate You rock! Thanks. I'll try to push a new release next few days.
I hope I don't offend anyone, but https://github.com/jwass/mplleaflet/pull/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 https://github.com/jwass/mplleaflet/pull/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.