import numpy as np
import xarray as xr
import pandas as pd
import holoviews as hv
import hvplot.xarray # noqa
import intake
from mrs.catalog import get_intake_urlWe have seen that cross- and co-polarized signals for Sentinel-1 and ALOS-2 seem to be dependent on the type of vegetation. Let’s have a closer look at this.
E.1 Question 1
We will try to highlight the difference between cross- and co-polarized microwave backscattering for Sentinel-1 and ALOS-2 separately. As already indicated volume scattering leads to depolarization effects, where multiple scattering can cause a change in polarization. Hence, a cross-polarized receiving antenna, such as on-board the Sentinel-1 and ALOS-2 satellites, may receive less energy from smooth bare soils than from vegetated surfaces. And the received energy for a cross-polarized receiving antenna will increase with increasing vegetation density. Hence this property of depolarization with vegetation density can be formulated as the cross-polarised ratio.
\(r_{cross} = \frac{P_{VH}}{P_{VV}} = \frac{\gamma^0_{VH}}{\gamma^0_{VV}} \quad \text{for Sentinel-1}\)
\(r_{cross} = \frac{P_{HV}}{P_{HH}} = \frac{\gamma^0_{HV}}{\gamma^0_{HH}} \quad \text{for ALOS-2}\)
Now you will calculate cross-polarised ratios for Sentinel-1 and ALOS-2.
First load again the same dataset.
Tip: The calculation of the cross-ratio refers to the linear domain and therefore needs a conversion from dB to linear scale. Checkout Notebook 2 again for the conversion.
url = get_intake_url()
cat = intake.open_catalog(url)
fused_ds = cat["fused_array"].read().compute()
fused_dshttps://git.geo.tuwien.ac.at/public_projects/microwave-remote-sensing/-/raw/dev-exs/microwave-remote-sensing.yml
<xarray.Dataset> Size: 307MB
Dimensions: (sensor: 4, time: 5, y: 1528, x: 2508)
Coordinates:
* sensor (sensor) object 32B 's1_VH' 's1_VV' 'alos_HH' 'alos_HV'
* time (time) datetime64[ns] 40B 2022-06-30 2022-07-31 ... 2022-10-31
* y (y) float64 12kB 1.397e+06 1.397e+06 ... 1.382e+06 1.382e+06
* x (x) float64 20kB 4.769e+06 4.769e+06 ... 4.794e+06 4.794e+06
spatial_ref int64 8B 0
Data variables:
gam0 (sensor, time, y, x) float32 307MB -14.52 -14.8 ... -31.16Calculate the cross-polarised ratios separately for each of the satellites with standard mathematical operations on the fused xarray and store the results in two new xarray objects. Make sure to transform the cross-polarised ratio (CR) to linear units for easier interpretation in the following questions.
rcross_da_s1 = ... # YOUR CODE HERE
rcross_da_alos = ... # YOUR CODE HEREAfter you calculate the CR, plot the results with the following code.
LAI_mean = fused_ds.LAI.mean("time")
LAI_image = LAI_mean.hvplot.\
image(rasterize=True, cmap='viridis', clim=(0, 6)).\
opts(title="Mean LAI (Selectable)", frame_height=400, aspect="equal")
id_sat = pd.Index(["sentinel", "alos"], name="sat")
rcross_da = xr.concat([rcross_da_s1, rcross_da_alos], id_sat)
def get_timeseries(x, y):
"""
Callback Function Holoviews
Parameters
----------
x: float
numeric value for x selected on LAI map
y: float
numeric value for y selected on LAI map
"""
lai_value = LAI_mean.sel(x=x, y=y, method="nearest").values
if np.isnan(lai_value):
select = rcross_da.where(LAI_mean.isnull())
label = "Water"
else:
mask = np.isclose(LAI_mean, lai_value, atol=0.05)
select = rcross_da.where(mask)
label = "Mean LAI: " + str(np.round(lai_value, 1))
time_series = select.to_dataset("sat").\
median(["x", "y"], skipna=True).\
hvplot.scatter(ylim=(0, 0.5)).\
opts(title=label, frame_height=400)
return time_series
point_stream = hv.streams.SingleTap(source=LAI_image)
time_series = hv.DynamicMap(get_timeseries, streams=[point_stream])
LAI_image + time_seriesFigure 1: (Left) Map of MEAN LAI around Lake Garda. The pixel values can be seen by hovering your mouse over it. Clicking on the pixel will generate the timeseries for the associated mean LAI on the right hand-side. (Right) Timeseries of CR for Sentinel-1 and ALOS-2.
E.2 Question 2
Analyse the plot that you created above. Based on what you see, select the correct statements.
E.3 Question 3
For this question we will create a boxplot to analyse the sensitivity of CR with to changes in LAI. Sensitivity means how high a response is when we change another variable, like LAI in this case. So an increased sensitivity means a higher response for the same increase in LAI. The boxplot uses boxes to illustrate the distributions of binned LAI values. Box limits indicate the range of the central 50% of the data (a.k.a inter quartile range: IQR), with the median value depicted as a central red line. The whisker limits demarcate 1.5 times the distance of the IQR. Values outside of the whiskers are considered outliers. Outliers have been eliminated in this plot to make the plot more readable.
# labels for LAI bins
ranger = [str(x).zfill(1) for x in range(1, 6)]
# fuse LAI and ALOS-2 and Sentinel-1 CR
LAI_df = fused_ds.LAI.to_dask_dataframe()
LAI_df["LAI"] = LAI_df["LAI"].\
map_partitions(pd.cut, bins=range(6), labels=ranger)
LAI_df["alos"] = rcross_da_alos.to_dask_dataframe()["gam0"]
LAI_df["s1"] = rcross_da_s1.to_dask_dataframe()["gam0"]
# boxplot
ax = LAI_df.compute().plot.box(column=["s1", "alos"], by="LAI",
showfliers=False, figsize=(15, 6))
ax[0].set_xlabel(r"$\text{LAI}$ [$m^2 \cdot m^{-2}$]")
ax[0].set_ylabel(r"$\text{CR}$ [$m^2 \cdot m^{-2}$]")
ax[1].set_xlabel(r"$\text{LAI}$ [$m^2 \cdot m^{-2}$]")
ax[1].set_ylabel(r"$\text{CR}$ [$m^2 \cdot m^{-2}$]")Figure 2: Boxplot for CR of Sentinel-1 and ALOS-2 for binned LAI values
Analyse the boxplot above. Based on what you see in the plot, which satellite is more sensitive to changes in vegetation? Can you also tell to what type of vegetation each satellite is most sensitive to? Explain your reasoning in detail.