Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
L
let-it-snow
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Remote Modules
let-it-snow
Commits
d7904ee9
Commit
d7904ee9
authored
1 year ago
by
Pierre Tysebaert-Plagne
Browse files
Options
Downloads
Patches
Plain Diff
Application du fix décrit dans l'issur 111
parent
9ddb618d
No related branches found
No related tags found
1 merge request
!107
Application du fix décrit dans l'issur 111
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
python/s2snow/hillshade.py
+51
-23
51 additions, 23 deletions
python/s2snow/hillshade.py
with
51 additions
and
23 deletions
python/s2snow/hillshade.py
+
51
−
23
View file @
d7904ee9
import
logging
import
os
import
os
from
osgeo
import
gdal
import
numpy
as
np
import
numpy
as
np
from
lxml
import
etree
from
lxml
import
etree
from
osgeo
import
gdal
,
osr
import
logging
from
s2snow.lis_exception
import
UnknownProductException
from
s2snow.lis_constant
import
AZIMUTH_PATH
,
ZENITH_PATH
from
s2snow.lis_constant
import
AZIMUTH_PATH
,
ZENITH_PATH
from
s2snow.lis_exception
import
UnknownProductException
from
s2snow.otb_wrappers
import
band_math
from
s2snow.otb_wrappers
import
band_math
"""
"""
This scripts compute the hillshade from a DEM and a Sentinel2 Metadata file containing the sun angles.
This scripts compute the hillshade from a DEM and a Sentinel2 Metadata file containing the sun angles.
...
@@ -27,16 +25,48 @@ def get_grid_values_from_xml(xml_path, angle="Zenith"):
...
@@ -27,16 +25,48 @@ def get_grid_values_from_xml(xml_path, angle="Zenith"):
Then, extract the VALUES in <values> v1 v2 v3 </values> <values> v4 v5 v6 </values> format as numpy array
Then, extract the VALUES in <values> v1 v2 v3 </values> <values> v4 v5 v6 </values> format as numpy array
Loop through the arrays to compute the mean.
Loop through the arrays to compute the mean.
'''
'''
tree
=
etree
.
parse
(
xml_path
)
tree
=
etree
.
parse
(
xml_path
)
# get col and row steps (5 km)
node
=
tree
.
xpath
(
f
"
.//Sun_Angles_Grids/
{
angle
}
/COL_STEP
"
)[
0
]
colstep
=
float
(
node
.
text
)
node
=
tree
.
xpath
(
f
"
.//Sun_Angles_Grids/
{
angle
}
/ROW_STEP
"
)[
0
]
# assume it's a north up image
rowstep
=
-
1
*
float
(
node
.
text
)
# get EPSG code
epsg
=
tree
.
find
(
"
.//HORIZONTAL_CS_CODE
"
).
text
# get grid corners coordinates
# warning: in array geometry the lower left corner is the upper left in raster geometry
ulx
=
float
(
tree
.
find
(
"
.//*[@name=
'
upperLeft
'
]/X
"
).
text
)
uly
=
float
(
tree
.
find
(
"
.//*[@name=
'
upperLeft
'
]/Y
"
).
text
)
lrx
=
float
(
tree
.
find
(
"
.//*[@name=
'
lowerRight
'
]/X
"
).
text
)
lry
=
float
(
tree
.
find
(
"
.//*[@name=
'
lowerRight
'
]/Y
"
).
text
)
node
=
tree
.
xpath
(
f
"
.//Sun_Angles_Grids/
{
angle
}
/Values_List
"
)[
0
]
# VALUES
node
=
tree
.
xpath
(
f
"
.//Sun_Angles_Grids/
{
angle
}
/Values_List
"
)[
0
]
# VALUES
arrays_lst
=
[]
arrays_lst
=
[]
for
values
in
node
:
for
values
in
node
:
values_arr
=
[
float
(
k
)
for
k
in
values
.
text
.
split
(
"
"
)]
values_arr
=
[
float
(
k
)
for
k
in
values
.
text
.
split
(
"
"
)]
arrays_lst
.
append
(
values_arr
)
arrays_lst
.
append
(
values_arr
)
return
np
.
array
(
arrays_lst
)
# We assume that the above coordinates correspond to the *centers* of corner pixels
# otherwise the 23x23 grid would have an extra row and column somewhere
ulxMTD
=
ulx
-
colstep
/
2
ulyMTD
=
uly
-
rowstep
/
2
# define the affine transformation coefficients
geoTransform
=
(
ulxMTD
,
colstep
,
0
,
ulyMTD
,
0
,
rowstep
)
# create spatial reference
spatialRef
=
osr
.
SpatialReference
()
spatialRef
.
ImportFromEPSG
(
int
(
epsg
))
return
np
.
array
(
arrays_lst
),
geoTransform
,
spatialRef
def
resample_angles
(
angle_array
,
ref_dem
,
output_angle
):
def
resample_angles
(
angle_array
,
angle_geoTransform
,
angle_spatialRef
,
ref_dem
,
output_angle
):
"""
"""
Resample the small grid of angles to the size of the dem to take into consideration the variation of sun angles given in the metadata files.
Resample the small grid of angles to the size of the dem to take into consideration the variation of sun angles given in the metadata files.
...
@@ -46,13 +76,14 @@ def resample_angles(angle_array, ref_dem, output_angle):
...
@@ -46,13 +76,14 @@ def resample_angles(angle_array, ref_dem, output_angle):
:return Gdal object: the gdal Dataset with the resampled angles
:return Gdal object: the gdal Dataset with the resampled angles
"""
"""
driver
=
gdal
.
GetDriverByName
(
"
GTiff
"
)
driver
=
gdal
.
GetDriverByName
(
"
GTiff
"
)
resampled_angles
=
driver
.
Create
(
output_angle
,
angle_array
.
shape
[
0
],
angle_array
.
shape
[
1
],
1
,
gdal
.
GDT_Float32
)
angles
=
driver
.
Create
(
output_angle
,
angle_array
.
shape
[
0
],
angle_array
.
shape
[
1
],
1
,
gdal
.
GDT_Float32
)
resampled_angles
.
SetGeoTransform
(
ref_dem
.
GetGeoTransform
())
resampled_angles
.
SetProjection
(
ref_dem
.
GetProjection
())
angles
.
SetGeoTransform
(
angle_geoTransform
)
resampled_angles
.
GetRasterBand
(
1
).
WriteArray
(
angle_array
)
angles
.
SetProjection
(
angle_spatialRef
.
ExportToWkt
())
resampled_angles
.
FlushCache
()
angles
.
GetRasterBand
(
1
).
WriteArray
(
angle_array
)
gdal
.
Warp
(
output_angle
,
resampled_angles
,
resampleAlg
=
gdal
.
GRIORA_Cubic
,
width
=
ref_dem
.
RasterXSize
,
height
=
ref_dem
.
RasterYSize
)
angles
.
FlushCache
()
gdal
.
Warp
(
output_angle
,
angles
,
resampleAlg
=
gdal
.
GRIORA_Cubic
,
width
=
ref_dem
.
RasterXSize
,
height
=
ref_dem
.
RasterYSize
)
return
gdal
.
Open
(
output_angle
)
return
gdal
.
Open
(
output_angle
)
...
@@ -141,9 +172,6 @@ def compute_hillshade_mask(output_file, dem_path, hillshade_lim, xml, output_fol
...
@@ -141,9 +172,6 @@ def compute_hillshade_mask(output_file, dem_path, hillshade_lim, xml, output_fol
if
not
os
.
path
.
exists
(
xml
):
if
not
os
.
path
.
exists
(
xml
):
raise
UnknownProductException
(
"
Could not find the Metadata *MTD_ALL.xml file.
"
)
raise
UnknownProductException
(
"
Could not find the Metadata *MTD_ALL.xml file.
"
)
zenith_angles
=
get_grid_values_from_xml
(
xml
,
angle
=
"
Zenith
"
)
azimuth_angles
=
get_grid_values_from_xml
(
xml
,
angle
=
"
Azimuth
"
)
dem
=
gdal
.
Open
(
dem_path
)
dem
=
gdal
.
Open
(
dem_path
)
# len_y cannot be negative
# len_y cannot be negative
...
@@ -154,7 +182,7 @@ def compute_hillshade_mask(output_file, dem_path, hillshade_lim, xml, output_fol
...
@@ -154,7 +182,7 @@ def compute_hillshade_mask(output_file, dem_path, hillshade_lim, xml, output_fol
logging
.
error
(
msg
)
logging
.
error
(
msg
)
raise
UnknownProductException
(
msg
)
raise
UnknownProductException
(
msg
)
dem_array
=
np
.
copy
(
dem
.
ReadAsArray
(
buf_xsize
=
dem
.
RasterXSize
,
buf_ysize
=
dem
.
RasterYSize
,
resample_alg
=
gdal
.
GRA_Lanczos
).
astype
(
dtype
=
np
.
float64
)
)
dem_array
=
dem
.
ReadAsArray
()
# Compute the hill gradient ( https://people.geog.ucsb.edu/~kclarke/G232/terrain/Corripio_2003.pdf )
# Compute the hill gradient ( https://people.geog.ucsb.edu/~kclarke/G232/terrain/Corripio_2003.pdf )
grad
=
gradient
(
dem_array
,
len_x
,
len_y
)
grad
=
gradient
(
dem_array
,
len_x
,
len_y
)
...
@@ -162,10 +190,10 @@ def compute_hillshade_mask(output_file, dem_path, hillshade_lim, xml, output_fol
...
@@ -162,10 +190,10 @@ def compute_hillshade_mask(output_file, dem_path, hillshade_lim, xml, output_fol
# angle covers a tile of side 23*5000m, dem covers a tile of size
# angle covers a tile of side 23*5000m, dem covers a tile of size
# If there are NaN in the xml azimuth and zenith data, the bicubic resizing will create a zone with nan around it
# If there are NaN in the xml azimuth and zenith data, the bicubic resizing will create a zone with nan around it
zenith_angles
=
get_grid_values_from_xml
(
xml
,
angle
=
"
Zenith
"
)
angle_array
,
angle_geoTransform
,
angle_spatialRef
=
get_grid_values_from_xml
(
xml
,
angle
=
"
Zenith
"
)
zenith
=
resample_angles
(
zenith_angles
,
dem
,
os
.
path
.
join
(
output_folder
,
ZENITH_PATH
)).
ReadAsArray
()
zenith
=
resample_angles
(
angle_array
,
angle_geoTransform
,
angle_spatialRef
,
dem
,
os
.
path
.
join
(
output_folder
,
ZENITH_PATH
)).
ReadAsArray
()
a
zimuth_angles
=
get_grid_values_from_xml
(
xml
,
angle
=
"
Azimuth
"
)
a
ngle_array
,
angle_geoTransform
,
angle_spatialRef
=
get_grid_values_from_xml
(
xml
,
angle
=
"
Azimuth
"
)
azimuth
=
resample_angles
(
a
zimuth_angles
,
dem
,
os
.
path
.
join
(
output_folder
,
AZIMUTH_PATH
)).
ReadAsArray
()
azimuth
=
resample_angles
(
a
ngle_array
,
angle_geoTransform
,
angle_spatialRef
,
dem
,
os
.
path
.
join
(
output_folder
,
AZIMUTH_PATH
)).
ReadAsArray
()
sun_vector
=
sun_vector_from_az_zen
(
zenith
,
azimuth
)
sun_vector
=
sun_vector_from_az_zen
(
zenith
,
azimuth
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment