Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions src/poligrain/plot_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from __future__ import annotations

import math

import matplotlib.axes
import matplotlib.patheffects as pe
import matplotlib.pyplot as plt
Expand Down Expand Up @@ -214,3 +216,89 @@ def plot_lines(
vmax=vmax,
cmap=cmap,
)


def calculate_azimuth(
site_0_lon: npt.ArrayLike | float,
site_1_lat: npt.ArrayLike | float,
satellite_lon: npt.ArrayLike | float,
) -> float:
"""Calculate SML azimuth angel.

Calculates the azimuth based on the location of a sensor and the
longitude of a geostationary satellite.

Parameters
----------
site_0_lon : npt.ArrayLike | float
Longitude of sensor.
site_1_lat : npt.ArrayLike | float
Latitude of sensor.
satellite_lon : npt.ArrayLike | float
Longitude of geostationary satellite.

Returns
-------
float

"""
# Convert degrees to radians
dish_lat_rad = math.radians(site_1_lat)
dish_lon_rad = math.radians(site_0_lon)
satellite_lon_rad = math.radians(satellite_lon)

# Calculate the difference in longitude
delta_lon = satellite_lon_rad - dish_lon_rad

# Calculate the azimuth angle
x = math.sin(delta_lon)
y = math.cos(dish_lat_rad) * math.tan(math.radians(0)) - math.sin(
dish_lat_rad
) * math.cos(delta_lon)

azimuth_rad = math.atan2(x, y)

# Convert from radians to degrees and normalize to 0-360
azimuth_deg = math.degrees(azimuth_rad)
return (azimuth_deg + 360) % 360


def calc_sml_line_on_ground(
x: npt.ArrayLike,
y: npt.ArrayLike,
elevation_angel: npt.ArrayLike,
azimuth_angel: npt.ArrayLike,
melting_layer_height: float,
):
"""Calculate the projection of one or many SML on the ground for plotting.

Parameters
----------
x : npt.ArrayLike | float
x coordinate of the location of the SML antenna in projected coordinates
with the unit meters.
y : npt.ArrayLike | float
y coordinate of the location of the SML antenna in projected coordinates
with the unit meters.
elevation_angel: npt.ArrayLike | float
Antenna angel in degrees.
azimuth_angel: npt.ArrayLike | float
Azimuth angel in degrees.
melting_layer_height: float
Height of melting layer above sensor in meter.

Returns
-------
Tuple of the antenna coordinates and the coordinates of the SML beam
projected to the ground based on the melting layer height.

"""
length_on_ground = (
melting_layer_height
* np.sin(np.radians(90))
/ np.sin(np.radians(elevation_angel))
)
endy = y + length_on_ground * np.cos(np.radians(azimuth_angel))
endx = x + length_on_ground * np.sin(np.radians(azimuth_angel))

return (x, y, endx, endy)
14 changes: 14 additions & 0 deletions tests/test_plot_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,17 @@ def test_plot_lines_with_dataarray_raise_wrong_shape():
ds_cmls = xr.open_dataset("tests/test_data/openMRG_CML_180minutes.nc")
with pytest.raises(ValueError, match="has to be 1D"):
plg.plot_map.plot_lines(ds_cmls.rsl.isel(sublink_id=0))


def test_calc_sml_line_on_ground():
x0, y0, x1, y1 = plg.plot_map.calc_sml_line_on_ground(
x=7.576159e05,
y=6.454985e06,
azimuth_angel=159.862,
elevation_angel=36.950,
melting_layer_height=4000,
)

np.testing.assert_almost_equal(
(x0, y0, x1, y1), (757615.9, 6454985.0, 759906.8480931921, 6448737.532106993)
)