Assigning satellite data to geo-locations¶
Example: Tracking the International Space Station with Dask¶
In this notebook we will use two APIs:
We will use them to track ISS location and next transit time with respect to a list of cities. To create our charts and parallelise data intelligently, we will use Dask, specifically Dask Delayed.
1. Imports¶
[1]:
import datetime
import logging
from operator import itemgetter
from time import sleep
import httpx
import numpy as np
from dask import delayed
from sklearn.metrics import DistanceMetric
2. Logger¶
[2]:
logger = logging.getLogger()
3. Latitude and longitude pairs from a list of cities¶
[3]:
from geopy.geocoders import Nominatim
def get_lat_long(address):
loc = Nominatim(user_agent="Geopy Library")
get_loc = loc.geocode(address)
return {
"name": get_loc.address,
"lat": get_loc.latitude,
"long": get_loc.longitude,
}
[4]:
get_lat_long("Berlin, Germany")
[4]:
{'name': 'Berlin, Deutschland', 'lat': 52.510885, 'long': 13.3989367}
[5]:
locations = []
for city in [
"Seattle, Washington",
"Miami, Florida",
"Berlin, Germany",
"Singapore",
"Wellington, New Zealand",
"Beirut, Lebanon",
"Beijing, China",
"Nairobi, Kenya",
"Cape Town, South Africa",
"Buenos Aires, Argentina",
]:
locations.append(get_lat_long(city))
sleep(2)
[6]:
locations
[6]:
[{'name': 'Seattle, King County, Washington, United States',
'lat': 47.6038321,
'long': -122.330062},
{'name': 'Miami, Miami-Dade County, Florida, United States',
'lat': 25.7741728,
'long': -80.19362},
{'name': 'Berlin, Deutschland', 'lat': 52.510885, 'long': 13.3989367},
{'name': 'Singapore', 'lat': 1.357107, 'long': 103.8194992},
{'name': 'Wellington, Wellington City, Wellington, 6011, New Zealand / Aotearoa',
'lat': -41.2887953,
'long': 174.7772114},
{'name': 'بيروت, البسطة التحتا, باشورة, محافظة بيروت, لبنان',
'lat': 33.88922645,
'long': 35.50255852895232},
{'name': '北京市, 中国', 'lat': 40.190632, 'long': 116.412144},
{'name': 'Nairobi, Kenya',
'lat': -1.3026148499999999,
'long': 36.82884201813725},
{'name': 'Cape Town, City of Cape Town, Western Cape, 8001, South Africa',
'lat': -33.9288301,
'long': 18.4172197},
{'name': 'Buenos Aires, Comuna 6, Ciudad Autónoma de Buenos Aires, Argentina',
'lat': -34.6083696,
'long': -58.4440583}]
4. Retrieve ISS data and determine transit times of cities¶
[7]:
def get_spaceship_location():
resp = httpx.get("http://api.open-notify.org/iss-now.json")
location = resp.json()["iss_position"]
return {
"lat": float(location.get("latitude")),
"long": float(location.get("longitude")),
}
[8]:
def great_circle_dist(lon1, lat1, lon2, lat2):
dist = DistanceMetric.get_metric("haversine")
lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
ll = [[lat1, lon1], [lat2, lon2]]
kms = 6367
return (kms * dist.pairwise(ll)).max()
[9]:
def iss_dist_from_loc(issloc, loc):
distance = great_circle_dist(
issloc.get("long"),
issloc.get("lat"),
loc.get("long"),
loc.get("lat"),
)
logger.info(f"ISS is {int(distance)}km from {loc.get('name')}")
return distance
[10]:
def iss_pass_near_loc(loc):
resp = httpx.get(
"http://api.open-notify.org/iss-pass.json",
params={"lat": loc.get("lat"), "lon": loc.get("long")},
)
data = resp.json().get("response")[0]
td = datetime.datetime.fromtimestamp(
data.get("risetime"),
tz=datetime.timezone.utc,
) - datetime.datetime.now(tz=datetime.timezone.utc)
m, s = divmod(int(td.total_seconds()), 60)
h, m = divmod(m, 60)
logger.info(
"ISS will pass near %s in %02d:%02d:%02d",
loc.get("name"),
h,
m,
s,
)
return td.total_seconds()
[11]:
iss_dist_from_loc(get_spaceship_location(), locations[2])
INFO:root:ISS is 3057km from Berlin, Deutschland
[11]:
np.float64(3057.10849285221)
[12]:
iss_pass_near_loc(locations[2])
INFO:root:ISS will pass near Berlin, 10117, Germany in 00:25:14
[12]:
1514.253889
5. Creating a delayed pipeline¶
[13]:
output = []
for loc in locations:
issloc = delayed(get_spaceship_location)()
dist = delayed(iss_dist_from_loc)(issloc, loc)
output.append((loc.get("name"), dist))
closest = delayed(lambda x: sorted(x, key=itemgetter(1))[0])(output)
[14]:
closest
[14]:
Delayed('lambda-5ab5a78f-cb72-4168-bce1-f9983fdb8a2e')
6. Show DAG¶
[15]:
closest.visualize()
[15]:
7. compute()¶
[16]:
closest.compute()
INFO:root:ISS is ~4685km from Miami, Miami-Dade County, Florida, USA
INFO:root:ISS is ~15205km from Beirut, Beirut Governorate, Lebanon
INFO:root:ISS is ~5919km from Seattle, King County, Washington, USA
INFO:root:ISS is ~6279km from Autonomous City of Buenos Aires, Comuna 6, Autonomous City of Buenos Aires, Argentina
INFO:root:ISS is ~12625km from Berlin, 10117, Germany
INFO:root:ISS is ~13137km from Cape Town, City of Cape Town, Western Cape, 8001, South Africa
INFO:root:ISS is ~16194km from Singapore
INFO:root:ISS is ~16298km from Nairobi, Kenya
INFO:root:ISS is ~13905km from Beijing, Dongcheng District, Beijing, 100010, China
INFO:root:ISS is ~8405km from Wellington, Wellington City, Wellington, 6011, New Zealand
[16]:
('Miami, Miami-Dade County, Florida, USA', 4685.887400314564)