VIIRSdownloader/VIIRSdownloader.py

267 lines
10 KiB
Python

# -*- coding: utf-8 -*-
"""
Downloads the actual active fire csv from
https://firms.modaps.eosdis.nasa.gov/data/active_fire/noaa-20-viirs-c2/csv/J1_VIIRS_C2_Europe_24h.csv
and displays it on a map.
Description of data displayed:
https://www.earthdata.nasa.gov/learn/find-data/near-real-time/firms/vnp14imgtdlnrt#ed-viirs-375m-attributes
@author: faraway
"""
import argparse
import getpass
import re
import os.path
import pickle
import datetime as dt
import webbrowser
import requests
import geopandas as gpd
import folium
from shapely.geometry import Point
from tqdm import tqdm
from sentinelsat.sentinel import SentinelAPI, geojson_to_wkt
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
from branca.element import Element, JavascriptLink, CssLink
def check_file_format(args_inputfile):
pattern = re.compile(r'local_VIIRS_data-\d{4}-\d{2}-\d{2}.zip')
if not re.match(pattern, args_inputfile):
raise argparse.ArgumentTypeError
return args_inputfile
def get_address(geo_data_frame, date):
address_file = 'adressdump-' + date
if not os.path.exists(address_file):
address_list = []
geolocator = Nominatim(user_agent='blub browser')
reverse = RateLimiter(geolocator.reverse, min_delay_seconds=5)
p_bar = tqdm(total=len(geo_data_frame))
for r in geo_data_frame.iterrows():
address_list.append(
reverse(r[1]['geometry'].coords[0], language='en'))
p_bar.update(1)
p_bar.close()
try:
with open(address_file, 'wb') as file:
pickle.dump(address_list, file)
except Exception as e:
SystemExit(e)
else:
try:
with open(address_file, 'rb') as file:
address_list = pickle.load(file)
except Exception as e:
SystemExit(e)
return address_list
def render_map(args, in_ukraine, address_list, date):
src1 = (r'https://gibs.earthdata.nasa.gov/wmts-webmerc/VIIRS_NOAA20_CorrectedReflectance_BandsM11-I2-I1/' +
'default/{time}/GoogleMapsCompatible_Level9/{z}/{y}/{x}.jpg')
src2 = (r'https://gibs.earthdata.nasa.gov/wmts-webmerc/VIIRS_NOAA20_CorrectedReflectance_TrueColor/' +
'default/{time}/GoogleMapsCompatible_Level9/{z}/{y}/{x}.jpg')
src3 = (r'https://gibs.earthdata.nasa.gov/wmts-webmerc/VIIRS_NOAA20_CorrectedReflectance_BandsM3-I3-M11/' +
'default/{time}/GoogleMapsCompatible_Level9/{z}/{y}/{x}.jpg')
fire_map = folium.Map(tiles='OpenStreetMap', min_zoom=5,
no_wrap=True, control_scale=(True), crs='EPSG3857')
active_fire = folium.FeatureGroup('Thermal anomalies detected')
if not in_ukraine.empty:
for r in in_ukraine.iterrows():
location = (r[1]['geometry'].coords[0])
folium.Marker(location=location, tooltip=(
r[1].to_string())).add_to(active_fire)
if address_list:
for address in address_list:
if address is not None:
location = (address.raw['lat'], address.raw['lon'])
folium.CircleMarker(location=location, tooltip=(
str(address.raw['display_name'])),
radius=10).add_to(active_fire)
fire_map.fit_bounds([(44.184598, 22.137059), (52.3797464, 40.2275801)])
ukraine_borders = gpd.read_file('data.zip')
folium.GeoJson(
data=ukraine_borders['geometry'], name='Borders of Ukraine').add_to(fire_map)
folium.raster_layers.TileLayer(
tiles=src1,
min_zoom=5,
subdomains='abc',
name='VIIRS CorrectedReflectance_BandsM11-I2-I1',
attr='NASA VIIRS',
overlay=True,
layer='VIIRS_NOAA20_CorrectedReflectance_BandsM11-I2-I1',
tileMatrixSet='GoogleMapsCompatible_Level9',
time=str(dt.date.fromisoformat(date) - dt.timedelta(days=1)),
tileSize=256,
).add_to(fire_map)
folium.raster_layers.TileLayer(
tiles=src2,
min_zoom=5,
subdomains='abc',
name='VIIRS CorrectedReflectance TrueColor',
attr='NASA VIIRS',
overlay=True,
layer='VIIRS_NOAA20_CorrectedReflectance_TrueColor',
tileMatrixSet='GoogleMapsCompatible_Level9',
time=str(dt.date.fromisoformat(date) - dt.timedelta(days=1)),
tileSize=256,
).add_to(fire_map)
folium.raster_layers.TileLayer(
tiles=src3,
min_zoom=5,
subdomains='abc',
name='VIIRS CorrectedReflectance BandsM3-I3-M11',
attr='NASA VIIRS',
overlay=True,
layer='VIIRS_NOAA20_CorrectedReflectance_BandsM3-I3-M11',
tileMatrixSet='GoogleMapsCompatible_Level9',
time=str(dt.date.fromisoformat(date) - dt.timedelta(days=1)),
tileSize=256,
).add_to(fire_map)
active_fire.add_to(fire_map)
if args.username:
sar_area = download_sars_data(args, date)
sar_area.add_to(fire_map)
folium.map.LayerControl().add_to(fire_map)
#fire_map = playground(fire_map)
return fire_map
def filter_coords(data_frame, bounding):
data_frame = data_frame.astype({'CONFIDENCE': 'string'})
in_ukraine = data_frame[data_frame['LATITUDE'].between(bounding[0], bounding[1])
& data_frame['LONGITUDE'].between(bounding[2],
bounding[3])
& (data_frame['CONFIDENCE'].str.contains('nominal')
| data_frame['CONFIDENCE'].str.contains('high'))]
return in_ukraine
def load_inputfile(args):
if args.inputfile:
local_file = args.inputfile
date = re.search(r'\d{4}-\d{2}-\d{2}', args.inputfile).group(0)
else:
date = str(dt.date.today())
local_file = 'local_VIIRS_data-' + date + '.zip'
if not os.path.exists(local_file):
try:
remote_url = r'https://firms.modaps.eosdis.nasa.gov/data/active_fire/noaa-20-viirs-c2/shapes/zips/J1_VIIRS_C2_Europe_24h.zip'
data = requests.get(remote_url, allow_redirects=True)
try:
with open(local_file, 'wb') as file:
file.write(data.content)
except OSError as e:
raise SystemExit(e)
except requests.exceptions.RequestException as e:
raise SystemExit(e)
html_file = local_file.split('.')[0] + '.html'
try:
geo_data_frame = gpd.read_file(local_file)
except Exception as e:
SystemExit(e)
geo_data_frame['geometry'] = geo_data_frame['geometry'].apply(
lambda row: Point(row.y, row.x))
return local_file, html_file, geo_data_frame, date
def download_sars_data(args, date):
if not args.password:
args.password = getpass.getpass('Password: ')
try:
api = SentinelAPI(args.username, args.password)
except Exception as e:
SystemExit(e)
bounding_geojson = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
22.137059,
44.184598
],
[
40.2275801,
44.184598
],
[
40.2275801,
52.3797464
],
[
22.137059,
52.3797464
],
[
22.137059,
44.184598
]
]
]
}
}
]
}
footprint = geojson_to_wkt(bounding_geojson)
products = api.query(
area=footprint,
date=(dt.date.fromisoformat(date) - dt.timedelta(days=1),
dt.date.fromisoformat(date)),
platformname='Sentinel-1',
producttype='GRD')
geo_data_frame = api.to_geodataframe(products)
geo_data_frame['beginposition'] = geo_data_frame['beginposition'].astype(
str)
geo_data_frame['endposition'] = geo_data_frame['endposition'].astype(str)
geo_data_frame['ingestiondate'] = geo_data_frame['ingestiondate'].astype(
str)
return folium.GeoJson(geo_data_frame.to_json(), name=('Areas covered by SAR'))
def playground(map):
figure = map.get_root()
element = Element('alert("hi there");')
figure.script.add_child(element)
return map
def main(args):
bounding = [44.184598, 52.3797464, 22.137059, 40.2275801]
local_file, html_file, geo_data_frame, date = load_inputfile(args)
in_ukraine = filter_coords(geo_data_frame, bounding)
if not args.noreversegeolocation:
address_list = get_address(in_ukraine, date)
else:
address_list = []
fire_map = render_map(args, in_ukraine, address_list, date)
fire_map.save(html_file)
webbrowser.open_new(html_file)
SystemExit(0)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=('Downloads the actual active fire csv from ' +
'https://firms.modaps.eosdis.nasa.gov/data/active_fire/noaa-20-viirs-c2/csv/J1_VIIRS_C2_Europe_24h.csv ' +
'and displays it on a map. ' +
'Description of data displayed: ' +
'https://www.earthdata.nasa.gov/learn/find-data/near-real-time/firms/vnp14imgtdlnrt#ed-viirs-375m-attributes'))
parser.add_argument(
'-i', '--inputfile', type=check_file_format,
help='Specify the cvs file containing the satellite data to be displayed. INPUTFILE must match local_VIIRS_data-YYYY-MM-DD.csv')
parser.add_argument('-nr', '--noreversegeolocation', action='store_true',
help='Disable reverse geolocation')
parser.add_argument('-u', '--username', type=str,
help='Username for https://scihub.copernicus.eu/')
parser.add_argument('-p', '--password', type=str,
help='Password for https://scihub.copernicus.eu/')
args = parser.parse_args()
main(args)