SmartCane/python_app/python_scripts/old/01_planet_download.py

191 lines
6.7 KiB
Python

# Converted from 01_planet_download.ipynb
# Load packages and connect to SentinelHub
import os
import json
import datetime
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path
from osgeo import gdal
from sentinelhub import MimeType, CRS, BBox, SentinelHubRequest, SentinelHubDownloadClient, \
DataCollection, bbox_to_dimensions, DownloadRequest, SHConfig, BBoxSplitter, read_data, Geometry, SentinelHubCatalog
config = SHConfig()
catalog = SentinelHubCatalog(config=config)
import time
import shutil
import geopandas as gpd
from shapely.geometry import MultiLineString, MultiPolygon, Polygon, box, shape
# SentinelHub credentials
config.sh_client_id = '1a72d811-4f0e-4447-8282-df09608cff44'
config.sh_client_secret = 'FcBlRL29i9ZmTzhmKTv1etSMFs5PxSos'
# DataCollection setup
collection_id = 'c691479f-358c-46b1-b0f0-e12b70a9856c'
byoc = DataCollection.define_byoc(
collection_id,
name='planet_data2',
is_timeless=True)
# Set some variables
project = 'kibos' # or xinavane or chemba_test_8b
# Adjust the number of days needed
days = 9 # change back to 28 which is the default. 3 years is 1095 days.
#delete all the satellite outputs -> then True
empty_folder_question = True
# Paths and folders
BASE_PATH = Path('../laravel_app/storage/app') / os.getenv('PROJECT_DIR', project)
BASE_PATH_SINGLE_IMAGES = Path(BASE_PATH / 'single_images')
folder_for_merged_tifs = str(BASE_PATH / 'merged_tif')
folder_for_virtual_raster = str(BASE_PATH / 'merged_virtual')
geojson_file = Path(BASE_PATH / 'Data' / 'pivot.geojson')
# Check if the folders exist, and if not, create them
if not os.path.exists(BASE_PATH_SINGLE_IMAGES):
os.makedirs(BASE_PATH_SINGLE_IMAGES)
if not os.path.exists(folder_for_merged_tifs):
os.makedirs(folder_for_merged_tifs)
if not os.path.exists(folder_for_virtual_raster):
os.makedirs(folder_for_virtual_raster)
# Evalscript
evalscript_original = """
//VERSION=3
function setup() {
return {
input: [{
bands: ["red", "green", "blue", "nir", "udm1"]
}],
output: {
bands: 4
}
};
}
function evaluatePixel(sample) {
var scaledBlue = [2.5 * sample.blue / 10000];
var scaledGreen = [2.5 * sample.green / 10000];
var scaledRed = [2.5 * sample.red / 10000];
var scaledNIR = [2.5 * sample.nir / 10000];
if (sample.udm1 == 0) {
return [scaledRed, scaledGreen, scaledBlue, scaledNIR];
} else {
return [NaN, NaN, NaN, NaN];
}
}
"""
def get_true_color_request_day(time_interval, bbox, size):
return SentinelHubRequest(
evalscript=evalscript_original,
input_data=[
SentinelHubRequest.input_data(
data_collection=DataCollection.planet_data2,
time_interval=(time_interval, time_interval)
)
],
responses=[
SentinelHubRequest.output_response('default', MimeType.TIFF)
],
bbox=bbox,
size=size,
config=config,
data_folder=str(BASE_PATH_SINGLE_IMAGES / time_interval),
)
def download_function(slot, bbox, size):
list_of_requests = [get_true_color_request_day(slot, bbox, size)]
list_of_requests = [request.download_list[0] for request in list_of_requests]
data = SentinelHubDownloadClient(config=config).download(list_of_requests, max_threads=15)
print(f' Image downloaded for ' + slot + ' and bbox ' + str(bbox))
time.sleep(.1)
def merge_files(slot):
file_list = [f"{x}/response.tiff" for x in Path(BASE_PATH_SINGLE_IMAGES / slot).iterdir()]
folder_for_merged_tifs = str(BASE_PATH / 'merged_tif' / f"{slot}.tif")
folder_for_virtual_raster = str(BASE_PATH / 'merged_virtual' / f"merged{slot}.vrt")
vrt_all = gdal.BuildVRT(folder_for_virtual_raster, file_list)
vrt_all = gdal.BuildVRT(folder_for_virtual_raster, file_list)
gdal.Translate(folder_for_merged_tifs, folder_for_virtual_raster)
days_needed = int(os.environ.get("DAYS", days))
date_str = os.environ.get("DATE")
if date_str:
end = datetime.datetime.strptime(date_str, "%Y-%m-%d").date()
else:
end = datetime.date.today()
start = end - datetime.timedelta(days=days_needed - 1)
slots = [(start + datetime.timedelta(days=i)).strftime('%Y-%m-%d') for i in range(days_needed)]
print('Monthly time windows:\n')
if len(slots) > 10:
for slot in slots[:3]:
print(slot)
print("...")
for slot in slots[-3:]:
print(slot)
else:
for slot in slots:
print(slot)
# Download images
geo_json = gpd.read_file(str(geojson_file))
geometries = [Geometry(geometry, crs=CRS.WGS84) for geometry in geo_json.geometry]
shapely_geometries = [geometry.geometry for geometry in geometries]
bbox_splitter = BBoxSplitter(
shapely_geometries, CRS.WGS84, (5, 5), reduce_bbox_sizes=True
)
print("Area bounding box: {}\n".format(bbox_splitter.get_area_bbox().__repr__()))
bbox_list = bbox_splitter.get_bbox_list()
info_list = bbox_splitter.get_info_list()
geometry_list = bbox_splitter.get_geometry_list()
geometry_list[0]
def is_image_available(date):
for bbox in bbox_list:
search_iterator = catalog.search(
collection=byoc,
bbox=bbox,
time=(date, date)
)
if len(list(search_iterator)) > 0:
return True
return False
available_slots = [slot for slot in slots if is_image_available(slot)]
comparison_slots = available_slots[:min(5, len(available_slots))]
print(available_slots)
print(f"Total slots: {len(slots)}")
print(f"Available slots: {len(available_slots)}")
print(f"Excluded slots due to empty dates: {len(slots) - len(available_slots)}")
resolution = 3
for slot in available_slots:
for bbox in bbox_list:
bbox = BBox(bbox=bbox, crs=CRS.WGS84)
size = bbox_to_dimensions(bbox, resolution=resolution)
download_function(slot, bbox, size)
for slot in available_slots:
merge_files(slot)
# Delete intermediate files
folders_to_empty = [BASE_PATH / 'merged_virtual', BASE_PATH_SINGLE_IMAGES]
def empty_folders(folders, run=True):
if not run:
print("Skipping empty_folders function.")
return
for folder in folders:
try:
for filename in os.listdir(folder):
file_path = os.path.join(folder, filename)
try:
if os.path.isfile(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
print(f"Error: {e}")
print(f"Emptied folder: {folder}")
except OSError as e:
print(f"Error: {e}")
empty_folders(folders_to_empty, run=empty_folder_question)