Skip to content

Commit 72673b7

Browse files
authored
Merge pull request #78 from vincelhx/master
angles funcs
2 parents 3d47ea1 + d1fe85d commit 72673b7

10 files changed

Lines changed: 136 additions & 38 deletions

File tree

docs/examples/streaks.ipynb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"metadata": {},
5656
"outputs": [],
5757
"source": [
58+
"xsarsea.windspeed.gmfs.GmfModel.activate_gmfs_impl()\n",
5859
"xsarsea.windspeed.available_models()"
5960
]
6061
},
@@ -138,7 +139,7 @@
138139
"streaks_geo['weight'] = streaks['weight']\n",
139140
"\n",
140141
"# convert directions from image convention to geographic convention\n",
141-
"streaks_geo['streaks_dir'] = xsarsea.dir_sample_to_geo(np.rad2deg(streaks['angle']), streaks_geo['ground_heading']) \n",
142+
"streaks_geo['streaks_dir'] = xsarsea.dir_sample_to_meteo(np.rad2deg(streaks['angle']), streaks_geo['ground_heading']) \n",
142143
"\n",
143144
"streaks_geo = streaks_geo.compute()\n",
144145
"\n",
@@ -228,7 +229,7 @@
228229
"source": [
229230
"#### Convertion between image convention and geographic convention\n",
230231
"\n",
231-
"see [xsarsea.dir_geo_to_sample](../basic_api.rst#xsarsea.dir_geo_to_sample) and [xsarsea.dir_sample_to_geo](../basic_api.rst#xsarsea.dir_sample_to_geo)\n",
232+
"see [xsarsea.dir_meteo_to_sample](../basic_api.rst#xsarsea.dir_meteo_to_sample) and [xsarsea.dir_sample_to_meteo](../basic_api.rst#xsarsea.dir_sample_to_meteo)\n",
232233
"\n"
233234
]
234235
},

docs/examples/windspeed_inversion.ipynb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"> .. warning::\n",
1919
" **Use of ancillary wind**\n",
2020
"\n",
21-
"> We suggest to go from `ancillary_wind = -np.conj(sarwing_ds.owi_ancillary_wind)` to `sarwing_ds.owi_ancillary_wind`` ; then it won't match sarwing results anymore\n",
21+
"> We suggest to go from `ancillary_wind = -np.conj(sarwing_ds.owi_ancillary_wind)` to `ancillary_wind = sarwing_ds.owi_ancillary_wind` ; then it won't match sarwing results anymore\n",
2222
"\n"
2323
]
2424
},
@@ -82,7 +82,7 @@
8282
"\n",
8383
"Ecmwf wind is stored in owi file in *geographical* (deg N/S) convention. `xsarsea.windspeed` need it relative to *sample* (ie antenna), as a complex number.\n",
8484
"\n",
85-
"We use [xsarsea.dir_geo_to_sample](../basic_api.rst#xsarsea.dir_geo_to_sample) to convert `sarwing_ds.owiEcmwfWindDirection` (deg) to radians, relative to sample, using `sarwing_ds.owiHeading`\n"
85+
"We use [xsarsea.dir_meteo_to_sample](../basic_api.rst#xsarsea.dir_meteo_to_sample) to convert `sarwing_ds.owiEcmwfWindDirection` (deg) to radians, relative to sample, using `sarwing_ds.owiHeading`\n"
8686
]
8787
},
8888
{
@@ -92,7 +92,7 @@
9292
"metadata": {},
9393
"outputs": [],
9494
"source": [
95-
"owi_ecmwf_wind = sarwing_ds.owiEcmwfWindSpeed * np.exp(1j* xsarsea.dir_geo_to_sample(sarwing_ds.owiEcmwfWindDirection, sarwing_ds.owiHeading))\n",
95+
"owi_ecmwf_wind = sarwing_ds.owiEcmwfWindSpeed * np.exp(1j* xsarsea.dir_meteo_to_sample(sarwing_ds.owiEcmwfWindDirection, sarwing_ds.owiHeading))\n",
9696
"sarwing_ds = xr.merge([\n",
9797
" sarwing_ds,\n",
9898
" owi_ecmwf_wind.to_dataset(name='owi_ancillary_wind'),\n",
@@ -127,7 +127,7 @@
127127
"vectorfield = hv.VectorField(\n",
128128
" (\n",
129129
" sub_sarwing_ds.sample, sub_sarwing_ds.line,\n",
130-
" xsarsea.dir_geo_to_sample(sub_sarwing_ds.owiEcmwfWindDirection, sub_sarwing_ds.owiHeading),\n",
130+
" xsarsea.dir_meteo_to_sample(sub_sarwing_ds.owiEcmwfWindDirection, sub_sarwing_ds.owiHeading),\n",
131131
" sub_sarwing_ds.owiEcmwfWindSpeed\n",
132132
" )\n",
133133
")\n",
@@ -478,7 +478,7 @@
478478
"vectorfield = hv.VectorField(\n",
479479
" (\n",
480480
" sub_sarwing_ds.sample, sub_sarwing_ds.line,\n",
481-
" xsarsea.dir_geo_to_sample(sarwing_ds[\"winddir_dual\"] ,sub_sarwing_ds.owiHeading),\n",
481+
" xsarsea.dir_meteo_to_sample(sarwing_ds[\"winddir_dual\"] ,sub_sarwing_ds.owiHeading),\n",
482482
" np.abs(wind_dual).isel(line=slice(None, None, 10), sample=slice(None, None, 10))\n",
483483
" )\n",
484484
")\n",
@@ -506,7 +506,7 @@
506506
"vectorfield = hv.VectorField(\n",
507507
" (\n",
508508
" sub_sarwing_ds.sample, sub_sarwing_ds.line,\n",
509-
" xsarsea.dir_geo_to_sample(sub_sarwing_ds.owiWindDirection ,sub_sarwing_ds.owiHeading),\n",
509+
" xsarsea.dir_meteo_to_sample(sub_sarwing_ds.owiWindDirection ,sub_sarwing_ds.owiHeading),\n",
510510
" sub_sarwing_ds.owiWindSpeed\n",
511511
" )\n",
512512
")\n",

docs/examples/windspeed_retrieval_L1.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@
249249
"dataset['sigma0_ocean'] = xr.where(dataset['sigma0'] <= 0, 1e-15, xsar_obj.dataset['sigma0'])\n",
250250
"dataset['ancillary_wind_direction'] = (90. - np.rad2deg(np.arctan2(dataset.model_V10, dataset.model_U10)) + 180) % 360\n",
251251
"dataset['ancillary_wind_speed'] = np.sqrt(dataset['model_U10']**2+dataset['model_V10']**2)\n",
252-
"dataset['ancillary_wind'] = dataset.ancillary_wind_speed * np.exp(1j * xsarsea.dir_geo_to_sample(dataset.ancillary_wind_direction, dataset.ground_heading)) # ref antenna"
252+
"dataset['ancillary_wind'] = dataset.ancillary_wind_speed * np.exp(1j * xsarsea.dir_meteo_to_sample(dataset.ancillary_wind_direction, dataset.ground_heading)) # ref antenna"
253253
]
254254
},
255255
{
@@ -471,7 +471,7 @@
471471
"vectorfield = hv.VectorField(\n",
472472
" (\n",
473473
" sub_ds.sample, sub_ds.line,\n",
474-
" xsarsea.dir_geo_to_sample(sub_ds.winddir_dual,sub_ds.ground_heading),\n",
474+
" xsarsea.dir_meteo_to_sample(sub_ds.winddir_dual,sub_ds.ground_heading),\n",
475475
" sub_ds.windspeed_dual\n",
476476
" )\n",
477477
")\n",
@@ -491,7 +491,7 @@
491491
"vectorfield = hv.VectorField(\n",
492492
" (\n",
493493
" sub_ds.sample, sub_ds.line,\n",
494-
" xsarsea.dir_geo_to_sample(sub_ds.ancillary_wind_direction,sub_ds.ground_heading),\n",
494+
" xsarsea.dir_meteo_to_sample(sub_ds.ancillary_wind_direction,sub_ds.ground_heading),\n",
495495
" sub_ds.ancillary_wind_speed\n",
496496
" )\n",
497497
")\n",

src/xsarsea/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
__all__ = ['sigma0_detrend', 'dir_geo_to_sample', 'dir_sample_to_geo', 'get_test_file']
1+
__all__ = ['sigma0_detrend', 'dir_meteo_to_sample',
2+
'dir_sample_to_meteo', 'dir_meteo_to_oceano', 'dir_oceano_to_meteo', 'dir_to_180', 'dir_to_360', 'get_test_file']
23

34
from .utils import get_test_file
4-
from .xsarsea import dir_geo_to_sample, dir_sample_to_geo, sigma0_detrend, read_sarwing_owi
5+
from .xsarsea import dir_meteo_to_sample, dir_sample_to_meteo, sigma0_detrend, dir_meteo_to_oceano, dir_oceano_to_meteo, dir_to_180, dir_to_360, read_sarwing_owi
56
try:
67
from importlib import metadata
78
except ImportError: # for Python<3.8
89
import importlib_metadata as metadata
910
__version__ = metadata.version('xsarsea')
10-

src/xsarsea/gradients.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
__all__ = ['Gradients', 'Gradients2D',
1313
'circ_smooth', 'PlotGradients', 'circ_hist']
1414

15-
import cv2
15+
try:
16+
import cv2
17+
except:
18+
import cv2
19+
1620
import numpy as np
1721
from scipy import signal, ndimage
1822
import xarray as xr

src/xsarsea/windspeed/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
windspeed module, for retrieving wind speed from sigma0 and models.
33
"""
44
__all__ = ['invert_from_model', 'available_models', 'get_model', 'register_cmod7',
5-
'register_sarwing_luts', 'register_nc_luts', 'nesz_flattening', 'GmfModel']
5+
'register_sarwing_luts', 'register_nc_luts', 'register_luts', 'nesz_flattening', 'GmfModel']
66
from .windspeed import invert_from_model
7-
from .models import available_models, get_model, register_nc_luts
7+
from .models import available_models, get_model, register_nc_luts, register_luts
88
from .sarwing_luts import register_sarwing_luts
99
from .cmod7 import register_cmod7
1010
from .utils import nesz_flattening, get_dsig

src/xsarsea/windspeed/models.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def __call__(self, inc, wspd, phi=None, broadcast=False):
273273
wspd: array-like
274274
windspeed
275275
phi: array-like or None
276-
wind direction, in **gmf convention**
276+
wind direction relative to antenna
277277
broadcast: bool
278278
| If True, input arrays will be broadcasted to the same dimensions, and output will have the same dimension.
279279
| This option is only available for :func:`~xsarsea.windspeed.gmfs.GmfModel`
@@ -397,7 +397,7 @@ def _raw_lut(self, **kwargs):
397397
return lut
398398

399399

400-
def register_nc_luts(topdir, gmf_names=None, **kwargs):
400+
def register_nc_luts(topdir, gmf_names=None):
401401
"""
402402
Register all netcdf luts found under `topdir`.
403403
@@ -518,3 +518,32 @@ def get_model(name):
518518
raise KeyError('model %s not found' % name)
519519

520520
return model
521+
522+
523+
def register_luts(topdir=None, topdir_cmod7=None):
524+
"""
525+
Register gmfModel luts and ncLutModel luts
526+
527+
Parameters
528+
----------
529+
topdir: str
530+
top dir path to nc luts.
531+
532+
topdir_cmod7: str
533+
top dir path to cmod7 luts.
534+
535+
kwargs: dict
536+
kwargs to pass to register_nc_luts
537+
"""
538+
539+
# register gmf luts
540+
import xsarsea.windspeed as windspeed
541+
windspeed.GmfModel.activate_gmfs_impl()
542+
543+
# register nc luts
544+
if topdir != None:
545+
register_nc_luts(topdir)
546+
547+
# register cmod7
548+
if topdir_cmod7 != None:
549+
windspeed.register_cmod7(topdir_cmod7)

src/xsarsea/windspeed/windspeed.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ def invert_from_model(inc, sigma0, sigma0_dual=None, /, ancillary_wind=None, dsi
2323
sigma0 in cross pol for dualpol invertion
2424
ancillary_wind=: xarray.DataArray (numpy.complex28)
2525
ancillary wind
26-
27-
| (for example ecmwf winds), in **model convention**
26+
| (for example ecmwf winds), in **antenna convention**
2827
model=: str or tuple
2928
model to use.
3029
@@ -46,8 +45,7 @@ def invert_from_model(inc, sigma0, sigma0_dual=None, /, ancillary_wind=None, dsi
4645
-------
4746
xarray.DataArray or tuple
4847
If available (copol or dualpol), the returned array is `np.complex64`, with the angle of the returned array is
49-
inverted direction in **gmf convention** (use `-np.conj(result))` to get it in standard convention)
50-
48+
inverted direction in **antenna convention**
5149
See Also
5250
--------
5351
xsarsea.windspeed.available_models
@@ -170,12 +168,6 @@ def __invert_from_model_1d(inc_1d, sigma0_co_db_1d, sigma0_cr_db_1d, dsig_cr_1d,
170168
# this function will be vectorized with 'numba.guvectorize' or 'numpy.frompyfunc'
171169
# set debug=True below to force 'numpy.frompyfunc', so you can debug this code
172170

173-
# gmf and lut doesn't have the same direction convention than xsarsea in the sample direction
174-
# for xsarsea, positive sample means in the sample increasing direction
175-
# for gmf and lut, positive means in the sample decreasing direction
176-
# we switch ancillary wind to the gmf convention
177-
# ancillary_wind_1d = -np.conj(ancillary_wind_1d)
178-
179171
for i in range(len(inc_1d)):
180172
one_inc = inc_1d[i]
181173
one_sigma0_co_db = sigma0_co_db_1d[i]

src/xsarsea/xsarsea.py

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,13 @@ def read_sarwing_owi(owi_file):
8989
return sarwing_ds
9090

9191

92-
def dir_geo_to_sample(geo_dir, ground_heading):
92+
def dir_meteo_to_sample(meteo_dir, ground_heading):
9393
"""
94-
Convert geographical N/S direction to image convention
94+
Convert meteorological N/S direction to image convention
9595
9696
Parameters
9797
----------
98-
geo_dir: geographical direction in degrees north
98+
meteo_dir: meteorological direction in degrees north
9999
ground_heading: azimuth at position, in degrees north
100100
101101
Returns
@@ -104,22 +104,94 @@ def dir_geo_to_sample(geo_dir, ground_heading):
104104
same shape as input. angle in radian, relative to sample, anticlockwise
105105
"""
106106

107-
return np.pi / 2 - np.deg2rad(geo_dir - ground_heading)
107+
return np.pi / 2 - np.deg2rad(meteo_dir - ground_heading)
108108

109109

110-
def dir_sample_to_geo(sample_dir, ground_heading):
110+
def dir_sample_to_meteo(sample_dir, ground_heading):
111111
"""
112-
Convert image direction relative to antenna to geographical direction
112+
Convert image direction relative to antenna to meteorological direction
113113
114114
Parameters
115115
----------
116-
sample_dir: geographical direction in degrees north
116+
sample_dir: angle in degrees, relative to sample, anticlockwise
117117
ground_heading: azimuth at position, in degrees north
118118
119119
Returns
120120
-------
121121
np.float64
122-
same shape as input. angle in degrees, relative to sample, anticlockwise
122+
same shape as input. meteorological direction in degrees north
123123
"""
124124

125125
return 90 - sample_dir + ground_heading
126+
127+
128+
def dir_meteo_to_oceano(meteo_dir):
129+
"""
130+
Convert meteorological direction to oceanographic direction
131+
132+
Parameters
133+
----------
134+
meteo_dir: float
135+
Wind direction in meteorological convention (clockwise, from), ex: 0°=from north, 90°=from east
136+
137+
Returns
138+
-------
139+
float
140+
Wind direction in oceanographic convention (clockwise, to), ex: 0°=to north, 90°=to east
141+
"""
142+
oceano_dir = (meteo_dir + 180) % 360
143+
return oceano_dir
144+
145+
146+
def dir_oceano_to_meteo(oceano_dir):
147+
"""
148+
Convert oceanographic direction to meteorological direction
149+
150+
Parameters
151+
----------
152+
oceano_dir: float
153+
Wind direction in oceanographic convention (clockwise, to), ex: 0°=to north, 90°=to east
154+
155+
Returns
156+
-------
157+
float
158+
Wind direction in meteorological convention (clockwise, from), ex: 0°=from north, 90°=from east
159+
"""
160+
meteo_dir = (oceano_dir - 180) % 360
161+
return meteo_dir
162+
163+
164+
def dir_to_180(angle):
165+
"""
166+
Convert angle to [-180;180]
167+
168+
Parameters
169+
----------
170+
angle: float
171+
angle in degrees
172+
173+
Returns
174+
-------
175+
float
176+
angle in degrees
177+
"""
178+
angle_180 = (angle + 180) % 360 - 180
179+
return angle_180
180+
181+
182+
def dir_to_360(angle):
183+
"""
184+
Convert angle to [0;360]
185+
186+
Parameters
187+
----------
188+
angle: float
189+
angle in degrees
190+
191+
Returns
192+
-------
193+
float
194+
angle in degrees
195+
"""
196+
angle_360 = (angle + 360) % 360
197+
return angle_360

test/test_xsarsea.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def test_inversion():
8484
line=slice(0, 50), sample=slice(0, 60))
8585

8686
owi_ecmwf_wind = sarwing_ds.owiEcmwfWindSpeed * np.exp(
87-
1j * xsarsea.dir_geo_to_sample(sarwing_ds.owiEcmwfWindDirection, sarwing_ds.owiHeading))
87+
1j * xsarsea.dir_meteo_to_sample(sarwing_ds.owiEcmwfWindDirection, sarwing_ds.owiHeading))
8888
sarwing_ds = xr.merge([
8989
sarwing_ds,
9090
owi_ecmwf_wind.to_dataset(name='owi_ancillary_wind'),

0 commit comments

Comments
 (0)