Last active
January 26, 2019 04:59
-
-
Save davidbernat/008d6f0490f40e4ccc52dff6bdb0a61f to your computer and use it in GitHub Desktop.
Starlight Aether SDK application example: Detection Video of GigaFactory Construction from (Freemium) Satellite Imagery
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################### | |
# | |
# First things first. | |
# | |
# Please go to: network.runsonaether.com | |
# | |
# You will be prompted to log in with a | |
# gmail or email address. | |
# | |
# After log-in, you will see all the good | |
# stuff. | |
# 1) our Aether SDK documentation | |
# 2) our examples | |
# 3) your applications and UUID. | |
# | |
# Company url: www.runsonaether.com | |
# www.starlight.ai | |
# | |
# Demos, Pictures, & Videos: | |
# Posted to Twitter: https://twitter.com/astrorobotic | |
# | |
# Medium: https://medium.com/starlightteam | |
# | |
# Thank you, | |
# David Bernat | |
# @astrorobotic | |
# | |
############################################### | |
import aether as ae | |
import numpy as np | |
from aether.user_utils.HelpfulFilters import HelpfulFilters | |
import os | |
import logging | |
logger = logging.getLogger(__name__) | |
############################################### | |
# | |
# | |
# New & Historical Building Starts: Detection of | |
# Construction from (Freemium) Satellite Imagery: | |
# GigaFactory Video | |
# | |
# An example of the Starlight Aether SDK | |
# Starlight: starlight.ai | |
# Aether SDK docs: docs.runsonaether.com | |
# Get a UUID in one-click: apply.runsonaether.com | |
# | |
# Author: David Bernat | |
# Twitter: @astrorobotic | |
# | |
# It will help us if you follow us on Twitter | |
# | |
# Report Issues to: | |
# https://github.com/TeamStarlight/aether-alpha-program | |
# | |
############################################### | |
# To install Aether SDK, simply pip install aether | |
# For documentation: docs.runsonaether.com | |
# Get a UUID in one-click: Log in to apply.runsonaether.com | |
uuid = "YOUR_UUID" | |
ae.GlobalConfig.set_user(uuid) | |
job_name = "gigafactor" | |
out_dir = "ndbi" | |
center = [39.537845, -119.439024] # Gigafactory | |
# center = [34.553544, 113.857867] # Foxconn | |
# center = [32.8, -115.6] # Imperial, CA | |
# center = [40.17208, -75.07299] # Wawa at Bucks County, PA | |
w = 0.05 # degrees, about 150x150 px of LandSat and 450x450 of Sentinel-2 | |
year_range = [2013, 2019] | |
cloud_limits = {"cloud": [0.0, 0.02], "cloud_shadow": [0.0, 0.02], "snowice": [0.0, 0.02]} | |
#################################### | |
# DEMO START | |
#################################### | |
coordinates = [[center[0] - w, center[1] - w], | |
[center[0] - w, center[1] + w], | |
[center[0] + w, center[1] + w], | |
[center[0] + w, center[1] - w], | |
[center[0] - w, center[1] - w]] | |
polygon = ae.AEPolygon(coordinates) | |
resource_name = "landsat" | |
query_parameters = dict( | |
bands=["SWIR1", "NIR", "QA"], | |
spacecraft_id=["LANDSAT_4", "LANDSAT_5", "LANDSAT_8"], | |
cloud_cover=[0.0, 100.0], | |
) | |
# Normalized Differential Build-Up Index | |
def ndbi(spacetime): | |
b_swir = spacetime.bands(0) | |
b_nir = spacetime.bands(1) | |
return spacetime.update((b_swir-b_nir) / (b_swir+b_nir)) | |
########### | |
# App Start | |
########### | |
timestamps = [] | |
stack = [] | |
metadata = None | |
with ae.SkySession() as sky: | |
for year in range(year_range[0], year_range[1]): | |
query_parameters["date_acquired"] = ["{}-01-01".format(year), "{}-12-31".format(year)] | |
sb = sky.Resource(resource_name).search(polygon, query_parameters) | |
logger.info("Year {}: Number of images found: {}, {}".format(year, len(sb.timestamps), sb.timestamps.keys())) | |
to_keep = HelpfulFilters.LandSatCloudFilter(sky, sb, limits=cloud_limits, qa_index=2, polygon=polygon) | |
sb = HelpfulFilters.applyFilterResults(sb, to_keep) | |
logger.info("Year {}: Number of images passing cloud check: {}, {}".format(year, len(sb.timestamps), sb.timestamps.keys())) | |
if len(sb.timestamps) == 0: | |
continue | |
sb = sky.crop(sb) | |
if len(sb.timestamps) == 0: | |
continue | |
spacetime = sky.download(sb, run=[ndbi]) | |
timestamps.extend(sorted(sb.timestamps)) | |
stack.append(spacetime.bands()) | |
if metadata is None: | |
metadata = spacetime.metadata() | |
# Order all the timestamps across searches | |
order_i = range(len(timestamps)) | |
order_i = [x for _, x in sorted(zip(timestamps, order_i))] | |
stack = np.concatenate(stack, axis=0)[order_i] | |
timestamps = [timestamps[i] for i in order_i] | |
spacetime = ae.Spacetime(stack, timestamps, metadata) | |
# Write the essential data to file: | |
if not os.path.exists("{}/{}/".format(out_dir, job_name)): | |
os.makedirs("{}/{}/".format(out_dir, job_name)) | |
with open("{}/{}/{}_timestamps.txt".format(out_dir, job_name, job_name), 'w') as f: | |
for ts in timestamps: | |
f.write("{}\n".format(ts)) | |
np.save("{}/{}/{}_stack.npy".format(out_dir, job_name, job_name), stack) | |
spacetime.generate_gif(range(stack.shape[0]), [0], save_to="{}/{}/{}.gif".format(out_dir, job_name, job_name)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment