VIIRSdownloader/VIIRSdownloader.py

267 lines
10 KiB
Python
Raw Permalink Normal View History

2022-07-26 14:09:34 +00:00
# -*- coding: utf-8 -*-
"""
2022-07-28 15:06:10 +00:00
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
2022-07-26 14:09:34 +00:00
and displays it on a map.
2022-07-28 15:06:10 +00:00
Description of data displayed:
2022-07-28 13:18:17 +00:00
https://www.earthdata.nasa.gov/learn/find-data/near-real-time/firms/vnp14imgtdlnrt#ed-viirs-375m-attributes
2022-07-28 15:06:10 +00:00
@author: faraway
2022-07-26 14:09:34 +00:00
"""
2022-07-28 13:18:17 +00:00
import argparse
2022-08-09 16:43:27 +00:00
import getpass
2022-07-28 13:18:17 +00:00
import re
2022-07-26 14:09:34 +00:00
import os.path
2022-07-28 15:06:10 +00:00
import pickle
2022-07-26 14:09:34 +00:00
import datetime as dt
2022-07-28 15:06:10 +00:00
import webbrowser
import requests
2022-08-09 16:43:27 +00:00
import geopandas as gpd
2022-07-26 14:09:34 +00:00
import folium
2022-08-09 16:43:27 +00:00
from shapely.geometry import Point
from tqdm import tqdm
from sentinelsat.sentinel import SentinelAPI, geojson_to_wkt
2022-07-26 14:09:34 +00:00
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
2022-08-09 16:43:27 +00:00
from branca.element import Element, JavascriptLink, CssLink
2022-07-26 14:09:34 +00:00
2022-07-28 15:06:10 +00:00
def check_file_format(args_inputfile):
2022-08-09 16:43:27 +00:00
pattern = re.compile(r'local_VIIRS_data-\d{4}-\d{2}-\d{2}.zip')
2022-07-28 13:18:17 +00:00
if not re.match(pattern, args_inputfile):
raise argparse.ArgumentTypeError
return args_inputfile
2022-08-09 16:43:27 +00:00
def get_address(geo_data_frame, date):
2022-07-28 13:18:17 +00:00
address_file = 'adressdump-' + date
if not os.path.exists(address_file):
address_list = []
2022-07-26 14:09:34 +00:00
geolocator = Nominatim(user_agent='blub browser')
reverse = RateLimiter(geolocator.reverse, min_delay_seconds=5)
2022-08-09 16:43:27 +00:00
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)
2022-07-26 14:09:34 +00:00
else:
2022-08-09 16:43:27 +00:00
try:
with open(address_file, 'rb') as file:
address_list = pickle.load(file)
except Exception as e:
SystemExit(e)
2022-07-28 13:18:17 +00:00
return address_list
2022-07-26 14:09:34 +00:00
2022-08-09 16:43:27 +00:00
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')
2022-08-09 16:43:27 +00:00
fire_map = folium.Map(tiles='OpenStreetMap', min_zoom=5,
no_wrap=True, control_scale=(True), crs='EPSG3857')
active_fire = folium.FeatureGroup('Thermal anomalies detected')
2022-07-28 15:06:10 +00:00
if not in_ukraine.empty:
for r in in_ukraine.iterrows():
2022-08-09 16:43:27 +00:00
location = (r[1]['geometry'].coords[0])
2022-07-28 15:06:10 +00:00
folium.Marker(location=location, tooltip=(
2022-08-09 16:43:27 +00:00
r[1].to_string())).add_to(active_fire)
2022-07-28 15:06:10 +00:00
if address_list:
for address in address_list:
if address is not None:
location = (address.raw['lat'], address.raw['lon'])
2022-08-09 16:43:27 +00:00
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)
2022-07-28 15:06:10 +00:00
folium.raster_layers.TileLayer(
tiles=src1,
2022-08-09 16:43:27 +00:00
min_zoom=5,
2022-07-28 15:06:10 +00:00
subdomains='abc',
name='VIIRS CorrectedReflectance_BandsM11-I2-I1',
attr='NASA VIIRS',
overlay=True,
2022-08-09 16:43:27 +00:00
layer='VIIRS_NOAA20_CorrectedReflectance_BandsM11-I2-I1',
2022-07-28 15:06:10 +00:00
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,
2022-08-09 16:43:27 +00:00
min_zoom=5,
subdomains='abc',
2022-08-09 16:43:27 +00:00
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,
2022-08-09 16:43:27 +00:00
min_zoom=5,
subdomains='abc',
2022-08-09 16:43:27 +00:00
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)
2022-08-09 16:43:27 +00:00
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)
2022-07-28 15:06:10 +00:00
return fire_map
2022-08-09 16:43:27 +00:00
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):
2022-07-28 13:18:17 +00:00
if args.inputfile:
local_file = args.inputfile
2022-07-28 15:06:10 +00:00
date = re.search(r'\d{4}-\d{2}-\d{2}', args.inputfile).group(0)
2022-07-28 13:18:17 +00:00
else:
2022-07-28 15:06:10 +00:00
date = str(dt.date.today())
2022-08-09 16:43:27 +00:00
local_file = 'local_VIIRS_data-' + date + '.zip'
2022-07-28 15:06:10 +00:00
if not os.path.exists(local_file):
try:
2022-08-09 16:43:27 +00:00
remote_url = r'https://firms.modaps.eosdis.nasa.gov/data/active_fire/noaa-20-viirs-c2/shapes/zips/J1_VIIRS_C2_Europe_24h.zip'
2022-07-28 15:06:10 +00:00
data = requests.get(remote_url, allow_redirects=True)
2022-07-28 13:18:17 +00:00
try:
with open(local_file, 'wb') as file:
file.write(data.content)
2022-07-28 15:06:10 +00:00
except OSError as e:
raise SystemExit(e)
except requests.exceptions.RequestException as e:
raise SystemExit(e)
2022-07-28 13:18:17 +00:00
html_file = local_file.split('.')[0] + '.html'
2022-08-09 16:43:27 +00:00
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'))
2022-07-28 15:06:10 +00:00
2022-08-09 16:43:27 +00:00
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)
2022-07-28 13:18:17 +00:00
if not args.noreversegeolocation:
2022-07-28 15:06:10 +00:00
address_list = get_address(in_ukraine, date)
2022-07-28 13:18:17 +00:00
else:
address_list = []
2022-08-09 16:43:27 +00:00
fire_map = render_map(args, in_ukraine, address_list, date)
2022-07-28 15:06:10 +00:00
fire_map.save(html_file)
webbrowser.open_new(html_file)
2022-08-09 16:43:27 +00:00
SystemExit(0)
2022-07-26 14:09:34 +00:00
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'))
2022-07-28 13:18:17 +00:00
parser.add_argument(
2022-07-28 15:06:10 +00:00
'-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')
2022-07-28 13:18:17 +00:00
parser.add_argument('-nr', '--noreversegeolocation', action='store_true',
help='Disable reverse geolocation')
2022-08-09 16:43:27 +00:00
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/')
2022-07-28 13:18:17 +00:00
args = parser.parse_args()
main(args)