Skip to content

Commit 259782c

Browse files
committed
Fixed HTML repr on Jupyter and finished example map styles notebook
1 parent 8b51378 commit 259782c

24 files changed

+1639
-127
lines changed

MANIFEST.in

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
include requirements.txt
2+
include ./pymaps/styles/*.*
3+
include ./pymaps/templates/*.*

build/lib/pymaps/#pygmaps.py

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
from operator import add
2+
3+
from bs4 import BeautifulSoup
4+
from IPython.core.display import display, HTML
5+
from jsbeautifier import beautify
6+
import pandas as pd
7+
8+
9+
def info_window(values):
10+
data = ''.join([f'<dt>{k}</dt><dd>{v}</dd>' for k, v in values.items()])
11+
return f'<dl>{data}</dl>'
12+
13+
14+
class LatLng(str):
15+
''' A LatLng is a point in geographical coordinates: latitude and
16+
longitude. '''
17+
def __new__(self, lat, lng):
18+
self.lat = lat
19+
self.lng = lng
20+
return str.__new__(self, f'{{lat: {lat}, lng: {lng}}}')
21+
22+
23+
class Marker(str):
24+
''' A marker identifies a location on a map.
25+
Parameters:
26+
* location (tuple or list, default None) – Latitude and Longitude of Map (Northing, Easting).
27+
'''
28+
def __new__(self, location=None, icon=None, title='', gmap='map', info_window=None):
29+
30+
self.attributes = {}
31+
self.attributes['position'] = LatLng(*position)
32+
self.attributes['map'] = gmap
33+
34+
if title != '':
35+
self.attributes['title'] = f'"{title}"'
36+
37+
if icon is not None:
38+
self.attributes['icon'] = f'"{icon}"'
39+
40+
self.template = self.fill_template(self.attributes)
41+
self.template = self.add_info_window(info_window, self.template)
42+
43+
return str.__new__(self, self.template)
44+
45+
def fill_template(attr):
46+
template = 'var marker = new google.maps.Marker({{{}}}); @infowindow'
47+
args = ',\n '.join([f'{k}: {v}' for k, v in attr.items()])
48+
return template.format(args)
49+
50+
def add_info_window(info_window, template):
51+
if info_window is not None:
52+
func = f'attachInfoWindow(marker, "{info_window}");'
53+
return template.replace('@infowindow', func)
54+
return template.replace('@infowindow', '')
55+
56+
def __repr__(self):
57+
return beautify(self.template)
58+
59+
def __str__(self):
60+
return beautify(self.template)
61+
62+
63+
class Map():
64+
def __init__(self, api_key, markers, map_type='roadmap', height='250px', width='100%', zoom=4, icon=None, labels=None,
65+
title='', info_windows=None, show_zoomcontrol=True, show_pegman=True):
66+
self.template = open('template.html').read()
67+
self.api_key = api_key
68+
self.map_type = map_type
69+
self.height = height
70+
self.width = width
71+
self.zoom = zoom
72+
self.markers = markers
73+
self.add_markers(self.markers, icon=icon, labels=labels, info_windows=info_windows)
74+
self.title = title
75+
self.show_pegman = show_pegman
76+
self.show_zoomcontrol = show_zoomcontrol
77+
78+
def add_markers(self, markers, icon=None, labels=None, info_windows=None):
79+
if isinstance(markers, pd.core.frame.DataFrame):
80+
for n, pos in enumerate(markers.itertuples(index=False)):
81+
label = ''
82+
info = None
83+
if labels is not None:
84+
label = labels[n]
85+
86+
if info_windows is not None:
87+
info = info_windows[n]
88+
89+
marker = Marker(pos, icon=icon, title=label, info_window=info)
90+
91+
self.template = self.template.replace('@marker', f'{marker}\n@marker')
92+
93+
@property
94+
def center(self):
95+
if isinstance(self.markers, pd.core.frame.DataFrame):
96+
return LatLng(*self.markers.mean())
97+
elif isinstance(self.markers[0], (float, int)):
98+
center = self.markers
99+
else:
100+
if len(self.markers) > 1:
101+
center = [sum(i) / len(self.markers)
102+
for i in [i for i in zip(*self.markers)]]
103+
else:
104+
center = self.markers[0]
105+
return LatLng(*center)
106+
107+
@property
108+
def html(self):
109+
html = self.template.replace('@marker', '')
110+
html = html.replace('@api_key', self.api_key)
111+
html = html.replace('@map_height', self.height)
112+
html = html.replace('@map_width', self.width)
113+
html = html.replace('@map_center', self.center)
114+
html = html.replace('@map_zoom', str(self.zoom))
115+
html = html.replace('@map_type', f'"{self.map_type}"')
116+
html = html.replace('@title', str(self.title))
117+
html = html.replace('@map_showpegman', str(self.show_pegman).lower())
118+
assert isinstance(self.show_zoomcontrol, bool)
119+
html = html.replace('@map_showzoomcontrol', str(self.show_zoomcontrol).lower())
120+
return html
121+
122+
def show(self):
123+
return display(HTML(self.html))
124+
125+
def __repr__(self):
126+
return BeautifulSoup(self.html, 'html.parser').prettify()

build/lib/pymaps/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = '0.0.17'

build/lib/pymaps/marker.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import jinja2
2+
3+
from .utils import position_to_latLng
4+
5+
6+
class Marker():
7+
'''A marker identifies a location on a map. By default, a marker uses a
8+
standard image. Markers can display custom images using the icon
9+
parameter.'''
10+
def __init__(self, position):
11+
self._map = 'map'
12+
self.position = position_to_latLng(position)
13+
pass

build/lib/pymaps/pymaps.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import base64
2+
import json
3+
import os
4+
5+
from jinja2 import Environment, FileSystemLoader
6+
7+
from .utils import position_to_latLng
8+
9+
10+
this_dir, _ = os.path.split(__file__)
11+
TEMPLATE_DIR = 'templates'
12+
TEMPLATE_FILE = 'template.j2'
13+
TEMPLATE = os.path.join(this_dir, TEMPLATE_DIR, TEMPLATE_FILE)
14+
15+
16+
def render(tpl_path, context):
17+
path, filename = os.path.split(tpl_path)
18+
loader = FileSystemLoader(path or './')
19+
env = Environment(loader=loader)
20+
return env.get_template(filename).render(context)
21+
22+
23+
def load_style(stylename):
24+
STYLES_DIR = os.path.join(this_dir, 'styles')
25+
stylefile = os.path.join(STYLES_DIR, stylename + '.txt')
26+
with open(stylefile) as f:
27+
style = f.read()
28+
return style
29+
30+
31+
class Map():
32+
'''Create a Map with Google Maps Javascript API
33+
34+
Returns
35+
-------
36+
pyGmaps Map Object
37+
38+
Examples
39+
--------
40+
'''
41+
42+
def __init__(self, location=None, map_type='roadmap', style=None,
43+
width='100%',
44+
height='500px', zoom_start=10, show_pegman=True,
45+
show_zoom_control=True, disable_default_ui=False,
46+
title=None, api_key=""):
47+
self.template_file = TEMPLATE
48+
if not location:
49+
# If location is not passed we center and zoom out.
50+
self.location = position_to_latLng([0, 0])
51+
self.zoom_start = 1
52+
else:
53+
self.location = position_to_latLng(location)
54+
self.zoom_start = zoom_start
55+
self.map_type = map_type
56+
if style:
57+
self.style = load_style(style)
58+
else:
59+
self.style = style
60+
self.width = width
61+
self.height = height
62+
self.api_key = api_key
63+
self.show_pegman = int(show_pegman)
64+
self.show_zoom_control = int(show_zoom_control)
65+
self.disable_default_ui = int(disable_default_ui)
66+
self.title = title
67+
self.html = render(self.template_file, self.__dict__)
68+
69+
def _repr_html_(self):
70+
'''Displays the Map in a Jupyter notebook'''
71+
HTML = ("data:text/html;charset=utf-8;base64," +
72+
base64.b64encode(self.html.encode('utf8')).decode('utf8'))
73+
iframe = ('<iframe src="{}" style="height:{};width:{};border:none !important">'
74+
'</iframe>')
75+
return iframe.format(HTML, self.height, self.width)

0 commit comments

Comments
 (0)