17
17
from .element import Element , Figure , JavascriptLink , CssLink , MacroElement
18
18
from .map import Layer , Icon , Marker , Popup
19
19
20
+
20
21
class WmsTileLayer (Layer ):
21
22
def __init__ (self , url , name = None ,
22
23
format = None , layers = None , transparent = True ,
@@ -49,6 +50,7 @@ def __init__(self, url, name=None,
49
50
{% endmacro %}
50
51
""" ) # noqa
51
52
53
+
52
54
class RegularPolygonMarker (Marker ):
53
55
def __init__ (self , location , color = 'black' , opacity = 1 , weight = 2 ,
54
56
fill_color = 'blue' , fill_opacity = 1 ,
@@ -128,6 +130,7 @@ def render(self, **kwargs):
128
130
JavascriptLink ("https://cdnjs.cloudflare.com/ajax/libs/leaflet-dvf/0.2/leaflet-dvf.markers.min.js" ), # noqa
129
131
name = 'dvf_js' )
130
132
133
+
131
134
class Vega (Element ):
132
135
def __init__ (self , data , width = None , height = None ,
133
136
left = "0%" , top = "0%" , position = 'relative' ):
@@ -137,13 +140,16 @@ def __init__(self, data, width=None, height=None,
137
140
"""
138
141
super (Vega , self ).__init__ ()
139
142
self ._name = 'Vega'
140
- self .data = data .to_json () if hasattr (data ,'to_json' ) else data
141
- if isinstance (self .data ,text_type ) or isinstance (data ,binary_type ):
143
+ self .data = data .to_json () if hasattr (data , 'to_json' ) else data
144
+ # FIXME:
145
+ if isinstance (self .data , text_type ) or isinstance (data , binary_type ):
142
146
self .data = json .loads (self .data )
143
147
144
148
# Size Parameters.
145
- self .width = _parse_size (self .data .get ('width' ,'100%' ) if width is None else width )
146
- self .height = _parse_size (self .data .get ('height' ,'100%' ) if height is None else height )
149
+ self .width = _parse_size (self .data .get ('width' , '100%' ) if
150
+ width is None else width )
151
+ self .height = _parse_size (self .data .get ('height' , '100%' ) if
152
+ height is None else height )
147
153
self .left = _parse_size (left )
148
154
self .top = _parse_size (top )
149
155
self .position = position
@@ -191,6 +197,7 @@ def render(self, **kwargs):
191
197
vg.parse.spec(spec, function(chart) { chart({el:div}).update(); });}""" ), # noqa
192
198
name = 'vega_parse' )
193
199
200
+
194
201
class GeoJson (MacroElement ):
195
202
def __init__ (self , data , style_function = None ):
196
203
"""
@@ -220,20 +227,22 @@ def __init__(self, data, style_function=None):
220
227
>>> # Providing string.
221
228
>>> GeoJson(open('foo.json').read())
222
229
223
- >>> # Providing a style_function that put all states in green, but Alabama in blue.
224
- >>> style_function=lambda x: {'fillColor': '#0000ff' if x['properties']['name']=='Alabama' else '#00ff00'}
230
+ >>> # Provide a style_function that color all states green but Alabama.
231
+ >>> style_function = lambda x: {'fillColor': '#0000ff' if
232
+ ... x['properties']['name']=='Alabama' else
233
+ ... '#00ff00'}
225
234
>>> GeoJson(geojson, style_function=style_function)
226
235
"""
227
236
super (GeoJson , self ).__init__ ()
228
237
self ._name = 'GeoJson'
229
- if hasattr (data ,'read' ):
238
+ if hasattr (data , 'read' ):
230
239
self .embed = True
231
240
self .data = json .load (data )
232
- elif isinstance (data ,dict ):
241
+ elif isinstance (data , dict ):
233
242
self .embed = True
234
243
self .data = data
235
244
elif isinstance (data , text_type ) or isinstance (data , binary_type ):
236
- if data .lstrip ()[0 ] in '[{' : # This is a GeoJSON inline string
245
+ if data .lstrip ()[0 ] in '[{' : # This is a GeoJSON inline string
237
246
self .embed = True
238
247
self .data = json .loads (data )
239
248
else : # This is a filename
@@ -242,18 +251,19 @@ def __init__(self, data, style_function=None):
242
251
elif data .__class__ .__name__ in ['GeoDataFrame' , 'GeoSeries' ]:
243
252
self .embed = True
244
253
if hasattr (data , '__geo_interface__' ):
245
- # We have a GeoPandas 0.2 object
246
- self .data = json .loads (json .dumps (data .to_crs (epsg = '4326' ).__geo_interface__ ))
254
+ # We have a GeoPandas 0.2 object.
255
+ self .data = json .loads (json .dumps (data .to_crs (epsg = '4326' ).__geo_interface__ )) # noqa
247
256
elif hasattr (data , 'columns' ):
248
257
# We have a GeoDataFrame 0.1
249
258
self .data = json .loads (data .to_crs (epsg = '4326' ).to_json ())
250
259
else :
251
- raise ValueError ('Unable to transform this object to a GeoJSON.' )
260
+ msg = 'Unable to transform this object to a GeoJSON.'
261
+ raise ValueError (msg )
252
262
else :
253
263
raise ValueError ('Unhandled object {!r}.' .format (data ))
254
264
255
265
if style_function is None :
256
- style_function = lambda x : {}
266
+ def style_function ( x ): return {}
257
267
self .style_function = style_function
258
268
259
269
self ._template = Template (u"""
@@ -268,14 +278,13 @@ def __init__(self, data, style_function=None):
268
278
def style_data (self ):
269
279
if 'features' not in self .data .keys ():
270
280
# Catch case when GeoJSON is just a single Feature or a geometry.
271
- if not (isinstance (self .data , dict ) and 'geometry' in self .data .keys ()):
281
+ if not (isinstance (self .data , dict ) and 'geometry' in self .data .keys ()): # noqa
272
282
# Catch case when GeoJSON is just a geometry.
273
- self .data = {'type' : 'Feature' , 'geometry' : self .data }
274
- self .data = {'type' : 'FeatureCollection' , 'features' : [self .data ]}
283
+ self .data = {'type' : 'Feature' , 'geometry' : self .data }
284
+ self .data = {'type' : 'FeatureCollection' , 'features' : [self .data ]}
275
285
276
286
for feature in self .data ['features' ]:
277
- feature .setdefault ('properties' ,{}).setdefault ('style' ,{}).update (
278
- self .style_function (feature ))
287
+ feature .setdefault ('properties' , {}).setdefault ('style' , {}).update (self .style_function (feature )) # noqa
279
288
return json .dumps (self .data , sort_keys = True )
280
289
281
290
def _get_self_bounds (self ):
@@ -287,14 +296,14 @@ def _get_self_bounds(self):
287
296
288
297
if 'features' not in self .data .keys ():
289
298
# Catch case when GeoJSON is just a single Feature or a geometry.
290
- if not (isinstance (self .data , dict ) and 'geometry' in self .data .keys ()):
299
+ if not (isinstance (self .data , dict ) and 'geometry' in self .data .keys ()): # noqa
291
300
# Catch case when GeoJSON is just a geometry.
292
- self .data = {'type' : 'Feature' , 'geometry' : self .data }
293
- self .data = {'type' : 'FeatureCollection' , 'features' : [self .data ]}
301
+ self .data = {'type' : 'Feature' , 'geometry' : self .data }
302
+ self .data = {'type' : 'FeatureCollection' , 'features' : [self .data ]}
294
303
295
- bounds = [[None ,None ],[None ,None ]]
304
+ bounds = [[None , None ], [None , None ]]
296
305
for feature in self .data ['features' ]:
297
- for point in iter_points (feature .get ('geometry' ,{}).get ('coordinates' ,{})):
306
+ for point in iter_points (feature .get ('geometry' , {}).get ('coordinates' , {})): # noqa
298
307
bounds = [
299
308
[
300
309
none_min (bounds [0 ][0 ], point [1 ]),
@@ -307,6 +316,7 @@ def _get_self_bounds(self):
307
316
]
308
317
return bounds
309
318
319
+
310
320
class TopoJson (MacroElement ):
311
321
def __init__ (self , data , object_path , style_function = None ):
312
322
"""
@@ -328,7 +338,7 @@ def __init__(self, data, object_path, style_function=None):
328
338
self .object_path = object_path
329
339
330
340
if style_function is None :
331
- style_function = lambda x : {}
341
+ def style_function ( x ): return {}
332
342
self .style_function = style_function
333
343
334
344
self ._template = Template (u"""
@@ -341,18 +351,17 @@ def __init__(self, data, object_path, style_function=None):
341
351
{{this.get_name()}}.setStyle(function(feature) {return feature.properties.style;});
342
352
343
353
{% endmacro %}
344
- """ )
354
+ """ ) # noqa
345
355
346
356
def style_data (self ):
347
357
def recursive_get (data , keys ):
348
358
if len (keys ):
349
359
return recursive_get (data .get (keys [0 ]), keys [1 :])
350
360
else :
351
361
return data
352
- geometries = recursive_get (self .data , self .object_path .split ('.' ))['geometries' ]
362
+ geometries = recursive_get (self .data , self .object_path .split ('.' ))['geometries' ] # noqa
353
363
for feature in geometries :
354
- feature .setdefault ('properties' ,{}).setdefault ('style' ,{}).update (
355
- self .style_function (feature ))
364
+ feature .setdefault ('properties' , {}).setdefault ('style' , {}).update (self .style_function (feature )) # noqa
356
365
return json .dumps (self .data , sort_keys = True )
357
366
358
367
def render (self , ** kwargs ):
@@ -373,10 +382,10 @@ def _get_self_bounds(self):
373
382
if not self .embed :
374
383
raise ValueError ('Cannot compute bounds of non-embedded TopoJSON.' )
375
384
376
- xmin ,xmax ,ymin ,ymax = None , None , None , None
385
+ xmin , xmax , ymin , ymax = None , None , None , None
377
386
378
387
for arc in self .data ['arcs' ]:
379
- x ,y = 0 ,0
388
+ x , y = 0 , 0
380
389
for dx , dy in arc :
381
390
x += dx
382
391
y += dy
@@ -386,16 +395,17 @@ def _get_self_bounds(self):
386
395
ymax = none_max (y , ymax )
387
396
return [
388
397
[
389
- self .data ['transform' ]['translate' ][0 ] + self .data ['transform' ]['scale' ][0 ] * xmin ,
390
- self .data ['transform' ]['translate' ][1 ] + self .data ['transform' ]['scale' ][1 ] * ymin ,
398
+ self .data ['transform' ]['translate' ][0 ] + self .data ['transform' ]['scale' ][0 ] * xmin , # noqa
399
+ self .data ['transform' ]['translate' ][1 ] + self .data ['transform' ]['scale' ][1 ] * ymin , # noqa
391
400
],
392
401
[
393
- self .data ['transform' ]['translate' ][0 ] + self .data ['transform' ]['scale' ][0 ] * xmax ,
394
- self .data ['transform' ]['translate' ][1 ] + self .data ['transform' ]['scale' ][1 ] * ymax ,
402
+ self .data ['transform' ]['translate' ][0 ] + self .data ['transform' ]['scale' ][0 ] * xmax , # noqa
403
+ self .data ['transform' ]['translate' ][1 ] + self .data ['transform' ]['scale' ][1 ] * ymax , # noqa
395
404
]
396
405
397
406
]
398
407
408
+
399
409
class ColorScale (MacroElement ):
400
410
def __init__ (self , color_domain , color_code , caption = "" ):
401
411
"""
@@ -425,6 +435,7 @@ def render(self, **kwargs):
425
435
JavascriptLink ("https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" ), # noqa
426
436
name = 'd3' )
427
437
438
+
428
439
class MarkerCluster (Layer ):
429
440
"""Adds a MarkerCluster layer on the map."""
430
441
def __init__ (self , overlay = True , control = True ):
@@ -549,6 +560,7 @@ def __init__(self, location, radius=500, color='black',
549
560
{% endmacro %}
550
561
""" )
551
562
563
+
552
564
class LatLngPopup (MacroElement ):
553
565
def __init__ (self ):
554
566
"""
@@ -667,6 +679,7 @@ def _get_self_bounds(self):
667
679
]
668
680
return bounds
669
681
682
+
670
683
class MultiPolyLine (MacroElement ):
671
684
def __init__ (self , locations , color = None , weight = None ,
672
685
opacity = None , latlon = True , popup = None ):
@@ -713,6 +726,7 @@ def __init__(self, locations, color=None, weight=None,
713
726
{{this._parent.get_name()}}.addLayer({{this.get_name()}});
714
727
{% endmacro %}
715
728
""" ) # noqa
729
+
716
730
def _get_self_bounds (self ):
717
731
"""Computes the bounds of the object itself (not including it's children)
718
732
in the form [[lat_min, lon_min], [lat_max, lon_max]]
@@ -731,6 +745,7 @@ def _get_self_bounds(self):
731
745
]
732
746
return bounds
733
747
748
+
734
749
class CustomIcon (Icon ):
735
750
def __init__ (self , icon_image , icon_size = None , icon_anchor = None ,
736
751
shadow_image = None , shadow_size = None , shadow_anchor = None ,
0 commit comments