pyVPRM 3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyVPRM/VPRM.py +1118 -0
- pyVPRM/__init__.py +1 -0
- pyVPRM/lib/__init__.py +0 -0
- pyVPRM/lib/downmodis.py +1012 -0
- pyVPRM/lib/fancy_plot.py +75 -0
- pyVPRM/lib/flux_tower_class.py +444 -0
- pyVPRM/lib/fluxnet_info/fluxnet_sites.pkl +0 -0
- pyVPRM/lib/fluxnet_info/site_infos.txt +218 -0
- pyVPRM/lib/functions.py +471 -0
- pyVPRM/meteorologies/__init__.py +0 -0
- pyVPRM/meteorologies/era5_class_dkrz.py +279 -0
- pyVPRM/meteorologies/era5_class_draft.py +60 -0
- pyVPRM/meteorologies/era5_monthly_xr.py +149 -0
- pyVPRM/meteorologies/met_base_class.py +67 -0
- pyVPRM/meteorologies/met_local_measurement.py +56 -0
- pyVPRM/sat_managers/__init__.py +0 -0
- pyVPRM/sat_managers/base_manager.py +430 -0
- pyVPRM/sat_managers/city.py +21 -0
- pyVPRM/sat_managers/copernicus.py +29 -0
- pyVPRM/sat_managers/esa_world_cover.py +21 -0
- pyVPRM/sat_managers/mapbiomas.py +35 -0
- pyVPRM/sat_managers/modis.py +266 -0
- pyVPRM/sat_managers/proba_v.py +86 -0
- pyVPRM/sat_managers/sentinel2.py +192 -0
- pyVPRM/sat_managers/synmap.py +21 -0
- pyVPRM/sat_managers/viirs.py +232 -0
- pyVPRM/sat_managers/viirs09ga.py +173 -0
- pyVPRM/vprm_configs/__init__.py +0 -0
- pyVPRM/vprm_configs/copernicus_land_cover.yaml +94 -0
- pyVPRM/vprm_configs/esa_world_cover.yaml +71 -0
- pyVPRM/vprm_configs/synmap.yaml +106 -0
- pyVPRM/vprm_models/__init__.py +1 -0
- pyVPRM/vprm_models/model_params/__init__.py +0 -0
- pyVPRM/vprm_models/vprm_base.py +691 -0
- pyVPRM/vprm_models/vprm_base_no_xeric.py +585 -0
- pyVPRM/vprm_models/vprm_modified.py +530 -0
- pyVPRM/vprm_models/vprm_nn.py +130 -0
- pyVPRM-3.0.dist-info/LICENSE +21 -0
- pyVPRM-3.0.dist-info/METADATA +40 -0
- pyVPRM-3.0.dist-info/RECORD +42 -0
- pyVPRM-3.0.dist-info/WHEEL +5 -0
- pyVPRM-3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
from shapely.geometry import Point, Polygon, box
|
|
6
|
+
import rioxarray as rxr
|
|
7
|
+
import zipfile
|
|
8
|
+
import glob
|
|
9
|
+
from pyproj import Transformer
|
|
10
|
+
import geopandas as gpd
|
|
11
|
+
from pyVPRM.lib import downmodis
|
|
12
|
+
import math
|
|
13
|
+
from pyproj import Proj
|
|
14
|
+
from affine import Affine
|
|
15
|
+
from rioxarray.rioxarray import affine_to_coords
|
|
16
|
+
import requests
|
|
17
|
+
from requests.auth import HTTPDigestAuth
|
|
18
|
+
from rioxarray import merge
|
|
19
|
+
import yaml
|
|
20
|
+
import warnings
|
|
21
|
+
|
|
22
|
+
warnings.filterwarnings("ignore")
|
|
23
|
+
from matplotlib.colors import LinearSegmentedColormap
|
|
24
|
+
from lxml import etree
|
|
25
|
+
from datetime import datetime
|
|
26
|
+
from rasterio.warp import calculate_default_transform
|
|
27
|
+
import h5py
|
|
28
|
+
from dateutil import parser
|
|
29
|
+
import xarray as xr
|
|
30
|
+
from datetime import datetime, timedelta, date
|
|
31
|
+
import numpy as np
|
|
32
|
+
from loguru import logger
|
|
33
|
+
|
|
34
|
+
def geodesic_point_buffer(lat, lon, km):
|
|
35
|
+
buf = Point(0, 0).buffer(km * 1000) # distance in metres
|
|
36
|
+
t = Transformer.from_crs(
|
|
37
|
+
"+proj=aeqd +lat_0={lat} +lon_0={lon} +x_0=0 +y_0=0".format(lat=lat, lon=lon),
|
|
38
|
+
"+proj=longlat +datum=WGS84",
|
|
39
|
+
)
|
|
40
|
+
ret = [t.transform(i[0], i[1]) for i in buf.exterior.coords[:]]
|
|
41
|
+
return ret
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def make_cmap(vmin, vmax, nbins, cmap_name="Reds"):
|
|
45
|
+
if isinstance(cmap_name, list):
|
|
46
|
+
cmap = LinearSegmentedColormap.from_list("some_name", cmap_name, N=nbins)
|
|
47
|
+
else:
|
|
48
|
+
cmap = mpl.cm.get_cmap(cmap_name) # define the colormap
|
|
49
|
+
# extract all colors from the .jet map
|
|
50
|
+
cmaplist = [cmap(i) for i in range(cmap.N)]
|
|
51
|
+
|
|
52
|
+
# create the new map
|
|
53
|
+
cmap = mpl.colors.LinearSegmentedColormap.from_list(
|
|
54
|
+
"Custom cmap", cmaplist, cmap.N
|
|
55
|
+
)
|
|
56
|
+
# cmap.set_under('blue') #'#d4ebf2')
|
|
57
|
+
|
|
58
|
+
# define the bins and normalize
|
|
59
|
+
bounds = np.linspace(vmin, vmax, nbins)
|
|
60
|
+
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
|
|
61
|
+
return cmap, norm
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class satellite_data_manager:
|
|
65
|
+
# Base class for all satellite images
|
|
66
|
+
|
|
67
|
+
def __init__(self, datapath=None, sat_image_path=None, sat_img=None):
|
|
68
|
+
self.bands = None
|
|
69
|
+
self.outpath = datapath
|
|
70
|
+
self.sat_image_path = sat_image_path
|
|
71
|
+
self.sat_img = sat_img
|
|
72
|
+
if isinstance(self.sat_img, str):
|
|
73
|
+
self.sat_img = xr.open_dataset(self.sat_img)
|
|
74
|
+
self.bands = list(self.sat_img.keys())
|
|
75
|
+
self.t = None
|
|
76
|
+
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
def value_at_lonlat(
|
|
80
|
+
self, lon, lat, as_array=True, key=None, isel={}, interp_method="nearest"
|
|
81
|
+
):
|
|
82
|
+
"""
|
|
83
|
+
Get the value at a specific latitude (lat) and longitude (lon)
|
|
84
|
+
|
|
85
|
+
Parameters:
|
|
86
|
+
lon(float or list of floats) : longitude
|
|
87
|
+
lat(float or list of floats) : latitude
|
|
88
|
+
as_array (bool): If true, return numpy array
|
|
89
|
+
key (str): Only get values for a specific key. All keys if None
|
|
90
|
+
interp_method (str): which method to use for interpolating. 'linear' by default.
|
|
91
|
+
For nearest neighbour set to 'nearest'.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
None
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
if self.t is None:
|
|
98
|
+
self.t = Transformer.from_crs(
|
|
99
|
+
"+proj=longlat +datum=WGS84", self.sat_img.rio.crs
|
|
100
|
+
)
|
|
101
|
+
x_a, y_a = self.t.transform(lon, lat)
|
|
102
|
+
# ret = self.sat_img.sel(x=x_a, y=y_a, method="nearest")
|
|
103
|
+
if key is not None:
|
|
104
|
+
if isinstance(x_a, list):
|
|
105
|
+
ret = (
|
|
106
|
+
self.sat_img[key]
|
|
107
|
+
.isel(isel)
|
|
108
|
+
.interp(x=("z", x_a), y=("z", y_a), method=interp_method)
|
|
109
|
+
)
|
|
110
|
+
else:
|
|
111
|
+
ret = (
|
|
112
|
+
self.sat_img[key]
|
|
113
|
+
.isel(isel)
|
|
114
|
+
.interp(x=x_a, y=y_a, method=interp_method)
|
|
115
|
+
)
|
|
116
|
+
else:
|
|
117
|
+
if isinstance(x_a, list) | isinstance(x_a, np.ndarray):
|
|
118
|
+
ret = self.sat_img.isel(isel).interp(
|
|
119
|
+
x=("z", x_a), y=("z", y_a), method=interp_method
|
|
120
|
+
)
|
|
121
|
+
else:
|
|
122
|
+
ret = self.sat_img.isel(isel).interp(x=x_a, y=y_a, method=interp_method)
|
|
123
|
+
if as_array:
|
|
124
|
+
return ret.to_array().values
|
|
125
|
+
else:
|
|
126
|
+
return ret
|
|
127
|
+
|
|
128
|
+
def drop_bands(self, band_names=None):
|
|
129
|
+
if band_names is not None:
|
|
130
|
+
self.sat_img = self.sat_img.drop(band_names)
|
|
131
|
+
else:
|
|
132
|
+
if self.bands is None:
|
|
133
|
+
self.set_band_names()
|
|
134
|
+
self.sat_img = self.sat_img.drop(self.bands)
|
|
135
|
+
|
|
136
|
+
def reduce_along_lon_lat(
|
|
137
|
+
self, lon, lat, interp_method="nearest", new_dim_name="z", inplace=True
|
|
138
|
+
):
|
|
139
|
+
if self.t is None:
|
|
140
|
+
self.t = Transformer.from_crs(
|
|
141
|
+
"+proj=longlat +datum=WGS84", self.sat_img.rio.crs
|
|
142
|
+
)
|
|
143
|
+
x_a, y_a = self.t.transform(lon, lat)
|
|
144
|
+
ret = self.sat_img.interp(
|
|
145
|
+
x=(new_dim_name, x_a), y=(new_dim_name, y_a), method=interp_method
|
|
146
|
+
)
|
|
147
|
+
if inplace:
|
|
148
|
+
self.sat_img = ret
|
|
149
|
+
return
|
|
150
|
+
else:
|
|
151
|
+
return ret
|
|
152
|
+
|
|
153
|
+
def load(self, proj=None, **kwargs):
|
|
154
|
+
# loading using the individual loading functions
|
|
155
|
+
# of the derived classes
|
|
156
|
+
|
|
157
|
+
self.individual_loading(**kwargs)
|
|
158
|
+
if proj is not None:
|
|
159
|
+
self.reproject(proj=proj)
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
def get_band_names(self):
|
|
163
|
+
return self.keys
|
|
164
|
+
|
|
165
|
+
def reproject(self, proj, **kwargs):
|
|
166
|
+
# reproject using a pre-defined projection or by passing a
|
|
167
|
+
# projection string
|
|
168
|
+
|
|
169
|
+
if proj == "WGS84":
|
|
170
|
+
self.sat_img = self.sat_img.rio.reproject(
|
|
171
|
+
"+proj=longlat +datum=WGS84", **kwargs
|
|
172
|
+
) #
|
|
173
|
+
elif proj == "CRS":
|
|
174
|
+
self.sat_img = self.sat_img.rio.reproject(
|
|
175
|
+
self.sat_img.rio.estimate_utm_crs(), **kwargs
|
|
176
|
+
)
|
|
177
|
+
else:
|
|
178
|
+
self.sat_img = self.sat_img.rio.reproject(proj, **kwargs)
|
|
179
|
+
try:
|
|
180
|
+
self.proj_dict = self.sat_img.rio.crs.to_dict()
|
|
181
|
+
except Exception as e:
|
|
182
|
+
self.proj_dict = {}
|
|
183
|
+
logger.info(e)
|
|
184
|
+
self.t = Transformer.from_crs(
|
|
185
|
+
"+proj=longlat +datum=WGS84", self.sat_img.rio.crs
|
|
186
|
+
)
|
|
187
|
+
return
|
|
188
|
+
|
|
189
|
+
def transform_to_grid(self, sat_manager_inst):
|
|
190
|
+
|
|
191
|
+
import xesmf as xe
|
|
192
|
+
|
|
193
|
+
src_x = self.sat_img.coords["x"].values
|
|
194
|
+
src_y = self.sat_img.coords["y"].values
|
|
195
|
+
X, Y = np.meshgrid(src_x, src_y)
|
|
196
|
+
t = Transformer.from_crs(self.sat_img.rio.crs, "+proj=longlat +datum=WGS84")
|
|
197
|
+
x_long, y_lat = t.transform(X, Y)
|
|
198
|
+
src_grid = xr.Dataset(
|
|
199
|
+
{
|
|
200
|
+
"lon": (["y", "x"], x_long, {"units": "degrees_east"}),
|
|
201
|
+
"lat": (["y", "x"], y_lat, {"units": "degrees_north"}),
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
src_grid = src_grid.set_coords(["lon", "lat"])
|
|
205
|
+
|
|
206
|
+
src_x = sat_manager_inst.sat_img.coords["x"].values
|
|
207
|
+
src_y = sat_manager_inst.sat_img.coords["y"].values
|
|
208
|
+
X, Y = np.meshgrid(src_x, src_y)
|
|
209
|
+
t = Transformer.from_crs(
|
|
210
|
+
sat_manager_inst.sat_img.rio.crs, "+proj=longlat +datum=WGS84"
|
|
211
|
+
)
|
|
212
|
+
x_long, y_lat = t.transform(X, Y)
|
|
213
|
+
dest_grid = xr.Dataset(
|
|
214
|
+
{
|
|
215
|
+
"lon": (["y", "x"], x_long, {"units": "degrees_east"}),
|
|
216
|
+
"lat": (["y", "x"], y_lat, {"units": "degrees_north"}),
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
dest_grid = dest_grid.set_coords(["lon", "lat"])
|
|
220
|
+
|
|
221
|
+
regridder = xe.Regridder(src_grid, dest_grid, "bilinear")
|
|
222
|
+
self.sat_img = regridder(self.sat_img)
|
|
223
|
+
self.sat_img = self.sat_img.assign_coords(
|
|
224
|
+
{
|
|
225
|
+
"x": sat_manager_inst.sat_img.coords["x"].values,
|
|
226
|
+
"y": sat_manager_inst.sat_img.coords["y"].values,
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
self.sat_img.rio.set_crs(sat_manager_inst.sat_img.rio.crs)
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
def plot_bands(self, cmaps="Reds", titles=None, save=None):
|
|
233
|
+
# plot the bands of the satellite image
|
|
234
|
+
pass
|
|
235
|
+
|
|
236
|
+
def plot_rgb(self, which_bands=[2, 1, 0], str_clip=2, figsize=0.9, save=None):
|
|
237
|
+
# plot an rgb image with the bands given in which_bands
|
|
238
|
+
pass
|
|
239
|
+
|
|
240
|
+
def plot_ndvi(
|
|
241
|
+
self, band1, band2, figsize=0.9, save=None, n_colors=9, vmin=None, vmax=1.0
|
|
242
|
+
):
|
|
243
|
+
# plot the normalized difference vegetation index
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
def add_tile(self, new_tiles, reproject=False):
|
|
247
|
+
# merge tiles together using the projection of the current satellite image
|
|
248
|
+
|
|
249
|
+
if not isinstance(new_tiles, list):
|
|
250
|
+
new_tiles = [new_tiles]
|
|
251
|
+
if not np.all([isinstance(i, satellite_data_manager) for i in new_tiles]):
|
|
252
|
+
logger.info("Can only merge with another instance of a satellite_data_manger")
|
|
253
|
+
if reproject:
|
|
254
|
+
logger.info("Do reprojections")
|
|
255
|
+
to_merge = [
|
|
256
|
+
i.sat_img.rio.reproject(self.sat_img.rio.crs) for i in new_tiles
|
|
257
|
+
]
|
|
258
|
+
else:
|
|
259
|
+
to_merge = [i.sat_img for i in new_tiles]
|
|
260
|
+
to_merge.append(self.sat_img)
|
|
261
|
+
logger.info("Merge")
|
|
262
|
+
self.sat_img = merge.merge_datasets(to_merge)
|
|
263
|
+
return
|
|
264
|
+
|
|
265
|
+
def crop_box(self, box, from_disk=False):
|
|
266
|
+
if not box.crs == self.sat_img.rio.crs:
|
|
267
|
+
# If the crs is not equal reproject the data
|
|
268
|
+
box = box.to_crs(self.sat_img.rio.crs)
|
|
269
|
+
self.sat_img = self.sat_img.rio.clip(
|
|
270
|
+
box, all_touched=True, from_disk=from_disk
|
|
271
|
+
).squeeze()
|
|
272
|
+
|
|
273
|
+
def crop(self, lonlat, radius, from_disk=False):
|
|
274
|
+
# crop the satellite images in place using a given radius around a given
|
|
275
|
+
# longitude and latitude
|
|
276
|
+
|
|
277
|
+
circle_poly = gpd.GeoSeries(
|
|
278
|
+
Polygon(geodesic_point_buffer(lonlat[1], lonlat[0], radius)), crs="WGS 84"
|
|
279
|
+
)
|
|
280
|
+
if not circle_poly.crs == self.sat_img.rio.crs:
|
|
281
|
+
# If the crs is not equal reproject the data
|
|
282
|
+
circle_poly = circle_poly.to_crs(self.sat_img.rio.crs)
|
|
283
|
+
|
|
284
|
+
crop_bound_box = [box(*circle_poly.total_bounds)]
|
|
285
|
+
|
|
286
|
+
self.sat_img = self.sat_img.rio.clip(
|
|
287
|
+
[box(*circle_poly.total_bounds)], all_touched=True, from_disk=from_disk
|
|
288
|
+
).squeeze()
|
|
289
|
+
return
|
|
290
|
+
|
|
291
|
+
def crop_to_polygon(self, polygon, from_disk=False):
|
|
292
|
+
if not polygon.crs == self.sat_img.rio.crs:
|
|
293
|
+
polygon = polygon.to_crs(self.sat_img.rio.crs)
|
|
294
|
+
|
|
295
|
+
self.sat_img = self.sat_img.rio.clip(
|
|
296
|
+
polygon.geometry, all_touched=True, from_disk=from_disk
|
|
297
|
+
).squeeze()
|
|
298
|
+
return
|
|
299
|
+
|
|
300
|
+
def crop_to_number_of_pixels(self, lonlat, num_pixels, key, reproject=False):
|
|
301
|
+
# crop the satellite images in place to a certain number of pixels around
|
|
302
|
+
# the given longitude and latitude
|
|
303
|
+
|
|
304
|
+
if (self.sat_img.rio.crs != self.sat_img.rio.estimate_utm_crs()) & reproject:
|
|
305
|
+
self.sat_img = self.sat_img.rio.reproject(
|
|
306
|
+
self_sat.img.rio.estimate_utm_crs()
|
|
307
|
+
)
|
|
308
|
+
t = Transformer.from_crs("+proj=longlat +datum=WGS84", self.sat_img.rio.crs)
|
|
309
|
+
x_a, y_a = t.transform(lonlat[0], lonlat[1])
|
|
310
|
+
x_ind = np.argmin(np.abs(self.sat_img.x.values - x_a))
|
|
311
|
+
y_ind = np.argmin(np.abs(self.sat_img.y.values - y_a))
|
|
312
|
+
shift = int(np.floor(num_pixels / 2.0))
|
|
313
|
+
return self.sat_img[key].values[
|
|
314
|
+
y_ind - shift : y_ind + shift + 1, x_ind - shift : x_ind + shift + 1
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
def individual_loading(self):
|
|
318
|
+
return
|
|
319
|
+
|
|
320
|
+
def save(self, save_path):
|
|
321
|
+
# save satellite image to save_path
|
|
322
|
+
|
|
323
|
+
self.sat_img.to_netcdf(save_path)
|
|
324
|
+
return
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class earthdata(satellite_data_manager):
|
|
328
|
+
# Classes for everything that can be downloaded from the NASA
|
|
329
|
+
# earthdata server, especially MODIS and VIIRS
|
|
330
|
+
|
|
331
|
+
def __init__(self, datapath=None, sat_image_path=None, sat_img=None):
|
|
332
|
+
super().__init__(datapath, sat_image_path, sat_img)
|
|
333
|
+
return
|
|
334
|
+
|
|
335
|
+
def _init_downloader(
|
|
336
|
+
self,
|
|
337
|
+
dest,
|
|
338
|
+
date,
|
|
339
|
+
delta,
|
|
340
|
+
username,
|
|
341
|
+
lonlat=None,
|
|
342
|
+
pwd=None,
|
|
343
|
+
token=None,
|
|
344
|
+
jpg=False,
|
|
345
|
+
enddate=None,
|
|
346
|
+
hv=None,
|
|
347
|
+
):
|
|
348
|
+
# Downloader with interface to the Earthdata server
|
|
349
|
+
|
|
350
|
+
if hv is not None:
|
|
351
|
+
h = hv[0]
|
|
352
|
+
v = hv[1]
|
|
353
|
+
else:
|
|
354
|
+
h, v = self.lat_lon_to_modis(lonlat[1], lonlat[0])
|
|
355
|
+
day = "{}-{:02d}-{:02d}".format(date.year, date.month, date.day)
|
|
356
|
+
tiles = "h{:02d}v{:02d}".format(h, v)
|
|
357
|
+
|
|
358
|
+
downloader = downmodis.downModis(
|
|
359
|
+
destinationFolder=dest,
|
|
360
|
+
tiles=tiles,
|
|
361
|
+
today=day,
|
|
362
|
+
product=self.product,
|
|
363
|
+
path=self.path,
|
|
364
|
+
delta=delta,
|
|
365
|
+
user=username,
|
|
366
|
+
enddate=enddate,
|
|
367
|
+
password=pwd,
|
|
368
|
+
token=token,
|
|
369
|
+
jpg=jpg,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
return downloader
|
|
373
|
+
|
|
374
|
+
def download(
|
|
375
|
+
self,
|
|
376
|
+
date,
|
|
377
|
+
savepath,
|
|
378
|
+
username,
|
|
379
|
+
lonlat=None,
|
|
380
|
+
pwd=None,
|
|
381
|
+
token=None,
|
|
382
|
+
delta=1,
|
|
383
|
+
jpg=False,
|
|
384
|
+
enddate=None,
|
|
385
|
+
hv=None,
|
|
386
|
+
rmv_downloads=False,
|
|
387
|
+
):
|
|
388
|
+
|
|
389
|
+
modisDown = self._init_downloader(
|
|
390
|
+
savepath, date, delta, username, lonlat, pwd, token, jpg, enddate, hv
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
# try:
|
|
394
|
+
modisDown.connect()
|
|
395
|
+
ds = modisDown.getListDays()
|
|
396
|
+
for d in ds:
|
|
397
|
+
fs = modisDown.getFilesList(d)
|
|
398
|
+
cde = modisDown.checkDataExist(fs)
|
|
399
|
+
logger.info("Download {}: {}".format(d, cde))
|
|
400
|
+
for c in cde:
|
|
401
|
+
os.system(
|
|
402
|
+
"wget --user {} --password {} --directory-prefix {} {} ".format(
|
|
403
|
+
modisDown.user,
|
|
404
|
+
modisDown.password,
|
|
405
|
+
modisDown.writeFilePath,
|
|
406
|
+
os.path.join(modisDown.url, modisDown.path, d, c),
|
|
407
|
+
)
|
|
408
|
+
)
|
|
409
|
+
time.sleep(5)
|
|
410
|
+
# modisDown.dayDownload(d, cde)
|
|
411
|
+
return
|
|
412
|
+
|
|
413
|
+
def _to_standard_format(self):
|
|
414
|
+
return
|
|
415
|
+
|
|
416
|
+
def lat_lon_to_modis(self, lat, lon):
|
|
417
|
+
CELLS = 2400
|
|
418
|
+
VERTICAL_TILES = 18
|
|
419
|
+
HORIZONTAL_TILES = 36
|
|
420
|
+
EARTH_RADIUS = 6371007.181
|
|
421
|
+
EARTH_WIDTH = 2 * math.pi * EARTH_RADIUS
|
|
422
|
+
|
|
423
|
+
TILE_WIDTH = EARTH_WIDTH / HORIZONTAL_TILES
|
|
424
|
+
TILE_HEIGHT = TILE_WIDTH
|
|
425
|
+
CELL_SIZE = TILE_WIDTH / CELLS
|
|
426
|
+
MODIS_GRID = Proj(f"+proj=sinu +R={EARTH_RADIUS} +nadgrids=@null +wktext")
|
|
427
|
+
x, y = MODIS_GRID(lon, lat)
|
|
428
|
+
h = (EARTH_WIDTH * 0.5 + x) / TILE_WIDTH
|
|
429
|
+
v = -(EARTH_WIDTH * 0.25 + y - (VERTICAL_TILES - 0) * TILE_HEIGHT) / TILE_HEIGHT
|
|
430
|
+
return int(h), int(v)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pyVPRM.sat_managers.base_manager import satellite_data_manager
|
|
2
|
+
import rioxarray as rxr
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class city_land_cover_map(satellite_data_manager):
|
|
7
|
+
|
|
8
|
+
def __init__(self, sat_image_path):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.load_kwargs = {}
|
|
11
|
+
self.sat_image_path = sat_image_path
|
|
12
|
+
self.resolution = 10.0
|
|
13
|
+
|
|
14
|
+
def get_resolution(self):
|
|
15
|
+
return self.resolution
|
|
16
|
+
|
|
17
|
+
def individual_loading(self):
|
|
18
|
+
self.sat_img = rxr.open_rasterio(
|
|
19
|
+
self.sat_image_path, band_as_variable=True
|
|
20
|
+
).squeeze()
|
|
21
|
+
self.keys = np.array(list(self.sat_img.data_vars))
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from pyVPRM.sat_managers.base_manager import satellite_data_manager
|
|
2
|
+
import rioxarray as rxr
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class copernicus_land_cover_map(satellite_data_manager):
|
|
7
|
+
# Class to load the copernicus land cover map
|
|
8
|
+
# To get the data, download for example from
|
|
9
|
+
# here: https://lcviewer.vito.be/download
|
|
10
|
+
|
|
11
|
+
def __init__(self, sat_image_path):
|
|
12
|
+
super().__init__()
|
|
13
|
+
self.load_kwargs = {}
|
|
14
|
+
self.sat_image_path = sat_image_path
|
|
15
|
+
self.resolution = 92.2256325412261
|
|
16
|
+
|
|
17
|
+
def get_resolution(self):
|
|
18
|
+
return self.resolution
|
|
19
|
+
|
|
20
|
+
def individual_loading(self):
|
|
21
|
+
try:
|
|
22
|
+
self.sat_img = rxr.open_rasterio(
|
|
23
|
+
self.sat_image_path, masked=True, band_as_variable=True, cache=False
|
|
24
|
+
).squeeze()
|
|
25
|
+
except:
|
|
26
|
+
self.sat_img = rxr.open_rasterio(
|
|
27
|
+
self.sat_image_path, masked=True, cache=False
|
|
28
|
+
).squeeze()
|
|
29
|
+
self.keys = np.array(list(self.sat_img.data_vars))
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pyVPRM.sat_managers.base_manager import satellite_data_manager
|
|
2
|
+
import rioxarray as rxr
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class esa_world_cover(satellite_data_manager):
|
|
7
|
+
|
|
8
|
+
def __init__(self, sat_image_path):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.load_kwargs = {}
|
|
11
|
+
self.sat_image_path = sat_image_path
|
|
12
|
+
self.resolution = 10.0
|
|
13
|
+
|
|
14
|
+
def get_resolution(self):
|
|
15
|
+
return self.resolution
|
|
16
|
+
|
|
17
|
+
def individual_loading(self):
|
|
18
|
+
self.sat_img = rxr.open_rasterio(
|
|
19
|
+
self.sat_image_path, band_as_variable=True
|
|
20
|
+
).squeeze()
|
|
21
|
+
self.keys = np.array(list(self.sat_img.data_vars))
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from pyVPRM.sat_managers.base_manager import satellite_data_manager
|
|
2
|
+
import rioxarray as rxr
|
|
3
|
+
import numpy as np
|
|
4
|
+
import xarray as xr
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class mapbiomas(satellite_data_manager):
|
|
8
|
+
# Class to load the copernicus land cover map
|
|
9
|
+
# To get the data, download for example from
|
|
10
|
+
# here: https://lcviewer.vito.be/download
|
|
11
|
+
|
|
12
|
+
def __init__(self, sat_image_path):
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.load_kwargs = {}
|
|
15
|
+
self.sat_image_path = sat_image_path
|
|
16
|
+
self.resolution = 30
|
|
17
|
+
|
|
18
|
+
def get_resolution(self):
|
|
19
|
+
return self.resolution
|
|
20
|
+
|
|
21
|
+
def individual_loading(self):
|
|
22
|
+
self.sat_img = xr.open_dataset(self.sat_image_path)
|
|
23
|
+
self.sat_img = self.sat_img.rio.write_crs("WGS84")
|
|
24
|
+
self.sat_img = self.sat_img.rename({"band_data": "band_1"})
|
|
25
|
+
self.sat_img["band_1"] = xr.where(
|
|
26
|
+
np.isnan(self.sat_img["band_1"]), 8, self.sat_img["band_1"]
|
|
27
|
+
)
|
|
28
|
+
# try:
|
|
29
|
+
# self.sat_img = rxr.open_rasterio(self.sat_image_path,
|
|
30
|
+
# masked=True, band_as_variable=True,
|
|
31
|
+
# cache=False).squeeze()
|
|
32
|
+
# except:
|
|
33
|
+
# self.sat_img = rxr.open_rasterio(self.sat_image_path,
|
|
34
|
+
# masked=True, cache=False).squeeze()
|
|
35
|
+
self.keys = np.array(list(self.sat_img.data_vars))
|