Skip to content
This repository was archived by the owner on Dec 10, 2019. It is now read-only.

Commit e51cb9e

Browse files
authored
Add leaflet support to project model (#2)
* Add leaflet methods to projects * Include update script
1 parent b4368ce commit e51cb9e

File tree

9 files changed

+257
-0
lines changed

9 files changed

+257
-0
lines changed

MANIFEST.in

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ include LICENSE.txt
33
include CHANGELOG.rst
44

55
recursive-include tests *
6+
recursive-include examples *.ipynb
7+
recursive-include scripts *

examples/Projects.ipynb

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Interacting with projects"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": null,
13+
"metadata": {},
14+
"outputs": [],
15+
"source": [
16+
"from rasterfoundry.api import API\n",
17+
"refresh_token = '<your refresh token>'\n",
18+
"api = API(refresh_token=refresh_token)"
19+
]
20+
},
21+
{
22+
"cell_type": "markdown",
23+
"metadata": {},
24+
"source": [
25+
"## List projects\n",
26+
"\n",
27+
"If you have access to any projects, `api.projects` will return them as a list."
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"projects = api.projects\n",
37+
"projects"
38+
]
39+
},
40+
{
41+
"cell_type": "markdown",
42+
"metadata": {},
43+
"source": [
44+
"## Display a project\n",
45+
"\n",
46+
"You can choose one of your projects with ingested scenes and add it to a leaflet map\n",
47+
"in the browser."
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": null,
53+
"metadata": {},
54+
"outputs": [],
55+
"source": [
56+
"# Change the index in projects[3] to a value within your list of projects\n",
57+
"project1 = projects[3]\n",
58+
"m = project1.get_map()\n",
59+
"project1.add_to(m)\n",
60+
"m"
61+
]
62+
},
63+
{
64+
"cell_type": "markdown",
65+
"metadata": {},
66+
"source": [
67+
"## Compare two projects\n",
68+
"\n",
69+
"If you have two projects with ingested scenes and in the same area, you can compare them with a slider."
70+
]
71+
},
72+
{
73+
"cell_type": "code",
74+
"execution_count": null,
75+
"metadata": {},
76+
"outputs": [],
77+
"source": [
78+
"# Change the index in projects[4] to a value within your list of projects\n",
79+
"project2 = projects[4]\n",
80+
"m2 = project2.get_map()\n",
81+
"project1.compare(project2, m2)\n",
82+
"m2."
83+
]
84+
}
85+
],
86+
"metadata": {
87+
"kernelspec": {
88+
"display_name": "Python 2",
89+
"language": "python",
90+
"name": "python2"
91+
},
92+
"language_info": {
93+
"codemirror_mode": {
94+
"name": "ipython",
95+
"version": 2
96+
},
97+
"file_extension": ".py",
98+
"mimetype": "text/x-python",
99+
"name": "python",
100+
"nbconvert_exporter": "python",
101+
"pygments_lexer": "ipython2",
102+
"version": "2.7.12"
103+
}
104+
},
105+
"nbformat": 4,
106+
"nbformat_minor": 2
107+
}

rasterfoundry/__init__.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Flag to indicate whether notebook support is available
2+
try:
3+
import ipyleaflet # NOQA
4+
NOTEBOOK_SUPPORT = True
5+
except ImportError:
6+
NOTEBOOK_SUPPORT = False

rasterfoundry/decorators.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import logging
2+
3+
from . import NOTEBOOK_SUPPORT
4+
5+
6+
def check_notebook(f):
7+
def no_op():
8+
logging.warn('This function requires jupyter notebook and ipyleaflet')
9+
return
10+
11+
if not NOTEBOOK_SUPPORT:
12+
return no_op
13+
else:
14+
return f

rasterfoundry/models/project.py

+79
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
"""A Project is a collection of zero or more scenes"""
2+
from .. import NOTEBOOK_SUPPORT
3+
4+
if NOTEBOOK_SUPPORT:
5+
from ipyleaflet import (
6+
Map,
7+
SideBySideControl,
8+
TileLayer,
9+
)
10+
11+
from ..decorators import check_notebook # NOQA
212

313

414
class Project(object):
@@ -23,6 +33,75 @@ def __init__(self, project, api):
2333
self.name = project.name
2434
self.id = project.id
2535

36+
@check_notebook
37+
def get_map(self, **kwargs):
38+
"""Return an ipyleaflet map centered on this project's center
39+
40+
Args:
41+
**kwargs: additional arguments to pass to Map initializations
42+
"""
43+
default_url = (
44+
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/'
45+
'light_all/{z}/{x}/{y}.png'
46+
)
47+
return Map(
48+
default_tiles=TileLayer(url=kwargs.get('url', default_url)),
49+
center=self.get_center(),
50+
scroll_wheel_zoom=kwargs.get('scroll_wheel_zoom', True),
51+
**kwargs
52+
)
53+
54+
@check_notebook
55+
def add_to(self, leaflet_map):
56+
"""Add this project to a leaflet map
57+
58+
Args:
59+
leaflet_map (Map): map to add this layer to
60+
"""
61+
62+
leaflet_map.add_layer(self.get_layer())
63+
64+
@check_notebook
65+
def compare(self, other, leaflet_map):
66+
"""Add a slider to compare two projects
67+
68+
This project determines the map center.
69+
70+
Args:
71+
other (Project): the project to compare with this project
72+
leaflet_map (Map): map to add the slider to
73+
"""
74+
75+
control = SideBySideControl(
76+
leftLayer=self.get_layer(), rightLayer=other.get_layer()
77+
)
78+
leaflet_map.add_control(control)
79+
80+
def get_center(self):
81+
"""Get the center of this project's extent"""
82+
coords = self._project.extent.get('coordinates')
83+
if not coords:
84+
raise ValueError(
85+
'Project must have coordinates to calculate a center'
86+
)
87+
x_min = min(
88+
coord[0] + (360 if coord[0] < 0 else 0) for coord in coords[0]
89+
)
90+
x_max = max(
91+
coord[0] + (360 if coord[0] < 0 else 0) for coord in coords[0]
92+
)
93+
y_min = min(coord[1] for coord in coords[0])
94+
y_max = max(coord[1] for coord in coords[0])
95+
center = [(y_min + y_max) / 2., (x_min + x_max) / 2.]
96+
if center[0] > 180:
97+
center[0] = center[0] - 360
98+
return tuple(center)
99+
100+
@check_notebook
101+
def get_layer(self):
102+
"""Returns a TileLayer for display using ipyleaflet"""
103+
return TileLayer(url=self.tms())
104+
26105
def tms(self):
27106
"""Return a TMS URL for a project"""
28107

scripts/update

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Get rid of old install maybe
6+
if [ -d venv ]; then
7+
rm -rf venv
8+
fi
9+
10+
# Reset / grab a new one
11+
virtualenv venv
12+
source venv/bin/activate
13+
pip install jupyter notebook
14+
jupyter nbextension enable --py --sys-prefix widgetsnbextension
15+
16+
pip install -e git+https://github.com/azavea/ipyleaflet#egg=9cfd238
17+
18+
jupyter nbextension install --py --symlink --sys-prefix ipyleaflet
19+
jupyter nbextension enable --py --sys-prefix ipyleaflet
20+
21+
python setup.py develop

setup.cfg

+5
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ universal=1
33

44
[aliases]
55
test=pytest
6+
7+
[check-manifest]
8+
ignore=
9+
examples/.ipynb_checkpoints
10+
examples/.ipynb_checkpoints/*

setup.py

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
'bravado >= 8.4.0'
2828
],
2929
extras_require={
30+
'notebook': [
31+
'notebook == 4.0.0'
32+
],
3033
'dev': [],
3134
'test': [],
3235
},

tests/test_notebook_check.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
def test_warn_without_notebook_support():
2+
import rasterfoundry.decorators
3+
rasterfoundry.decorators.NOTEBOOK_SUPPORT = False
4+
from rasterfoundry.decorators import check_notebook
5+
6+
@check_notebook
7+
def f():
8+
return 'foo'
9+
assert f() is None
10+
11+
12+
def test_no_warn_with_notebook_support():
13+
import rasterfoundry.decorators
14+
rasterfoundry.decorators.NOTEBOOK_SUPPORT = True
15+
from rasterfoundry.decorators import check_notebook
16+
17+
@check_notebook
18+
def f():
19+
return 'foo'
20+
assert f() == 'foo'

0 commit comments

Comments
 (0)