pycontrails 0.51.2__cp311-cp311-win_amd64.whl → 0.52.0__cp311-cp311-win_amd64.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.
Potentially problematic release.
This version of pycontrails might be problematic. Click here for more details.
- pycontrails/__init__.py +1 -1
- pycontrails/_version.py +2 -2
- pycontrails/core/__init__.py +1 -1
- pycontrails/core/cache.py +1 -1
- pycontrails/core/flight.py +32 -28
- pycontrails/core/rgi_cython.cp311-win_amd64.pyd +0 -0
- pycontrails/datalib/__init__.py +4 -1
- pycontrails/datalib/_leo_utils/search.py +250 -0
- pycontrails/datalib/_leo_utils/static/bq_roi_query.sql +6 -0
- pycontrails/datalib/_leo_utils/vis.py +60 -0
- pycontrails/{core/datalib.py → datalib/_met_utils/metsource.py} +1 -1
- pycontrails/datalib/ecmwf/arco_era5.py +8 -7
- pycontrails/datalib/ecmwf/common.py +3 -2
- pycontrails/datalib/ecmwf/era5.py +12 -11
- pycontrails/datalib/ecmwf/era5_model_level.py +12 -11
- pycontrails/datalib/ecmwf/hres.py +14 -13
- pycontrails/datalib/ecmwf/hres_model_level.py +15 -14
- pycontrails/datalib/ecmwf/ifs.py +14 -13
- pycontrails/datalib/gfs/gfs.py +15 -14
- pycontrails/datalib/goes.py +2 -2
- pycontrails/datalib/landsat.py +567 -0
- pycontrails/datalib/sentinel.py +512 -0
- pycontrails/models/apcemm/__init__.py +8 -0
- pycontrails/models/apcemm/apcemm.py +983 -0
- pycontrails/models/apcemm/inputs.py +226 -0
- pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +183 -0
- pycontrails/models/apcemm/utils.py +437 -0
- pycontrails/models/cocipgrid/cocip_grid.py +7 -6
- pycontrails/models/dry_advection.py +14 -5
- {pycontrails-0.51.2.dist-info → pycontrails-0.52.0.dist-info}/METADATA +19 -11
- {pycontrails-0.51.2.dist-info → pycontrails-0.52.0.dist-info}/RECORD +36 -27
- pycontrails/datalib/spire/__init__.py +0 -19
- /pycontrails/datalib/{spire/spire.py → spire.py} +0 -0
- {pycontrails-0.51.2.dist-info → pycontrails-0.52.0.dist-info}/LICENSE +0 -0
- {pycontrails-0.51.2.dist-info → pycontrails-0.52.0.dist-info}/NOTICE +0 -0
- {pycontrails-0.51.2.dist-info → pycontrails-0.52.0.dist-info}/WHEEL +0 -0
- {pycontrails-0.51.2.dist-info → pycontrails-0.52.0.dist-info}/top_level.txt +0 -0
|
@@ -40,8 +40,9 @@ import pandas as pd
|
|
|
40
40
|
import xarray as xr
|
|
41
41
|
|
|
42
42
|
import pycontrails
|
|
43
|
-
from pycontrails.core import cache
|
|
43
|
+
from pycontrails.core import cache
|
|
44
44
|
from pycontrails.core.met import MetDataset, MetVariable
|
|
45
|
+
from pycontrails.datalib._met_utils import metsource
|
|
45
46
|
from pycontrails.datalib.ecmwf.common import ECMWFAPI, CDSCredentialsNotFound
|
|
46
47
|
from pycontrails.datalib.ecmwf.model_levels import pressure_levels_at_model_levels
|
|
47
48
|
from pycontrails.datalib.ecmwf.variables import MODEL_LEVEL_VARIABLES
|
|
@@ -73,7 +74,7 @@ class ERA5ModelLevel(ECMWFAPI):
|
|
|
73
74
|
|
|
74
75
|
Parameters
|
|
75
76
|
----------
|
|
76
|
-
time :
|
|
77
|
+
time : metsource.TimeInput | None
|
|
77
78
|
The time range for data retrieval, either a single datetime or (start, end) datetime range.
|
|
78
79
|
Input must be datetime-like or tuple of datetime-like
|
|
79
80
|
(:py:class:`datetime.datetime`, :class:`pandas.Timestamp`, :class:`numpy.datetime64`)
|
|
@@ -82,9 +83,9 @@ class ERA5ModelLevel(ECMWFAPI):
|
|
|
82
83
|
for the nominal reanalysis and no larger than 1 day for ensemble members.
|
|
83
84
|
This ensures that exactly one request is submitted per file on tape accessed.
|
|
84
85
|
If None, ``paths`` must be defined and all time coordinates will be loaded from files.
|
|
85
|
-
variables :
|
|
86
|
+
variables : metsource.VariableInput
|
|
86
87
|
Variable name (i.e. "t", "air_temperature", ["air_temperature, specific_humidity"])
|
|
87
|
-
pressure_levels :
|
|
88
|
+
pressure_levels : metsource.PressureLevelInput, optional
|
|
88
89
|
Pressure levels for data, in hPa (mbar).
|
|
89
90
|
To download surface-level parameters, use :class:`pycontrails.datalib.ecmwf.ERA5`.
|
|
90
91
|
Defaults to pressure levels that match model levels at a nominal surface pressure.
|
|
@@ -123,9 +124,9 @@ class ERA5ModelLevel(ECMWFAPI):
|
|
|
123
124
|
|
|
124
125
|
def __init__(
|
|
125
126
|
self,
|
|
126
|
-
time:
|
|
127
|
-
variables:
|
|
128
|
-
pressure_levels:
|
|
127
|
+
time: metsource.TimeInput,
|
|
128
|
+
variables: metsource.VariableInput,
|
|
129
|
+
pressure_levels: metsource.PressureLevelInput | None = None,
|
|
129
130
|
timestep_freq: str | None = None,
|
|
130
131
|
product_type: str = "reanalysis",
|
|
131
132
|
grid: float | None = None,
|
|
@@ -186,18 +187,18 @@ class ERA5ModelLevel(ECMWFAPI):
|
|
|
186
187
|
datasource_timestep_freq = "1h" if product_type == "reanalysis" else "3h"
|
|
187
188
|
if timestep_freq is None:
|
|
188
189
|
timestep_freq = datasource_timestep_freq
|
|
189
|
-
if not
|
|
190
|
+
if not metsource.validate_timestep_freq(timestep_freq, datasource_timestep_freq):
|
|
190
191
|
msg = (
|
|
191
192
|
f"Product {self.product_type} has timestep frequency of {datasource_timestep_freq} "
|
|
192
193
|
f"and cannot support requested timestep frequency of {timestep_freq}."
|
|
193
194
|
)
|
|
194
195
|
raise ValueError(msg)
|
|
195
196
|
|
|
196
|
-
self.timesteps =
|
|
197
|
+
self.timesteps = metsource.parse_timesteps(time, freq=timestep_freq)
|
|
197
198
|
if pressure_levels is None:
|
|
198
199
|
pressure_levels = pressure_levels_at_model_levels(20_000.0, 50_000.0)
|
|
199
|
-
self.pressure_levels =
|
|
200
|
-
self.variables =
|
|
200
|
+
self.pressure_levels = metsource.parse_pressure_levels(pressure_levels)
|
|
201
|
+
self.variables = metsource.parse_variables(variables, self.pressure_level_variables)
|
|
201
202
|
|
|
202
203
|
def __repr__(self) -> str:
|
|
203
204
|
base = super().__repr__()
|
|
@@ -17,8 +17,9 @@ import xarray as xr
|
|
|
17
17
|
from overrides import overrides
|
|
18
18
|
|
|
19
19
|
import pycontrails
|
|
20
|
-
from pycontrails.core import cache
|
|
20
|
+
from pycontrails.core import cache
|
|
21
21
|
from pycontrails.core.met import MetDataset, MetVariable
|
|
22
|
+
from pycontrails.datalib._met_utils import metsource
|
|
22
23
|
from pycontrails.datalib.ecmwf.common import ECMWFAPI
|
|
23
24
|
from pycontrails.datalib.ecmwf.variables import PRESSURE_LEVEL_VARIABLES, SURFACE_VARIABLES
|
|
24
25
|
from pycontrails.utils import dependencies, iteration, temp
|
|
@@ -120,7 +121,7 @@ class HRES(ECMWFAPI):
|
|
|
120
121
|
|
|
121
122
|
Parameters
|
|
122
123
|
----------
|
|
123
|
-
time :
|
|
124
|
+
time : metsource.TimeInput | None
|
|
124
125
|
The time range for data retrieval, either a single datetime or (start, end) datetime range.
|
|
125
126
|
Input must be a datetime-like or tuple of datetime-like
|
|
126
127
|
(datetime, :class:`pandas.Timestamp`, :class:`numpy.datetime64`)
|
|
@@ -129,10 +130,10 @@ class HRES(ECMWFAPI):
|
|
|
129
130
|
be assumed to be the nearest synoptic hour: 00, 06, 12, 18.
|
|
130
131
|
All subsequent times will be downloaded for relative to :attr:`forecast_time`.
|
|
131
132
|
If None, ``paths`` must be defined and all time coordinates will be loaded from files.
|
|
132
|
-
variables :
|
|
133
|
+
variables : metsource.VariableInput
|
|
133
134
|
Variable name (i.e. "air_temperature", ["air_temperature, relative_humidity"])
|
|
134
135
|
See :attr:`pressure_level_variables` for the list of available variables.
|
|
135
|
-
pressure_levels :
|
|
136
|
+
pressure_levels : metsource.PressureLevelInput, optional
|
|
136
137
|
Pressure levels for data, in hPa (mbar)
|
|
137
138
|
Set to -1 for to download surface level parameters.
|
|
138
139
|
Defaults to -1.
|
|
@@ -241,9 +242,9 @@ class HRES(ECMWFAPI):
|
|
|
241
242
|
|
|
242
243
|
def __init__(
|
|
243
244
|
self,
|
|
244
|
-
time:
|
|
245
|
-
variables:
|
|
246
|
-
pressure_levels:
|
|
245
|
+
time: metsource.TimeInput | None,
|
|
246
|
+
variables: metsource.VariableInput,
|
|
247
|
+
pressure_levels: metsource.PressureLevelInput = -1,
|
|
247
248
|
paths: str | list[str] | pathlib.Path | list[pathlib.Path] | None = None,
|
|
248
249
|
cachepath: str | list[str] | pathlib.Path | list[pathlib.Path] | None = None,
|
|
249
250
|
grid: float = 0.25,
|
|
@@ -277,13 +278,13 @@ class HRES(ECMWFAPI):
|
|
|
277
278
|
if time is None and paths is None:
|
|
278
279
|
raise ValueError("Time input is required when paths is None")
|
|
279
280
|
|
|
280
|
-
self.timesteps =
|
|
281
|
-
self.pressure_levels =
|
|
281
|
+
self.timesteps = metsource.parse_timesteps(time, freq="1h")
|
|
282
|
+
self.pressure_levels = metsource.parse_pressure_levels(
|
|
282
283
|
pressure_levels, self.supported_pressure_levels
|
|
283
284
|
)
|
|
284
|
-
self.variables =
|
|
285
|
+
self.variables = metsource.parse_variables(variables, self.supported_variables)
|
|
285
286
|
|
|
286
|
-
self.grid =
|
|
287
|
+
self.grid = metsource.parse_grid(grid, [0.1, 0.25, 0.5, 1]) # lat/lon degree resolution
|
|
287
288
|
|
|
288
289
|
# "enfo" = ensemble forecast
|
|
289
290
|
# "oper" = atmospheric model/HRES
|
|
@@ -309,12 +310,12 @@ class HRES(ECMWFAPI):
|
|
|
309
310
|
if forecast_time_pd.hour % 6:
|
|
310
311
|
raise ValueError("Forecast hour must be on one of 00, 06, 12, 18")
|
|
311
312
|
|
|
312
|
-
self.forecast_time =
|
|
313
|
+
self.forecast_time = metsource.round_hour(forecast_time_pd.to_pydatetime(), 6)
|
|
313
314
|
|
|
314
315
|
# if no specific forecast is requested, set the forecast time using timesteps
|
|
315
316
|
elif self.timesteps:
|
|
316
317
|
# round first element to the nearest 6 hour time (00, 06, 12, 18 UTC) for forecast_time
|
|
317
|
-
self.forecast_time =
|
|
318
|
+
self.forecast_time = metsource.round_hour(self.timesteps[0], 6)
|
|
318
319
|
|
|
319
320
|
# when no forecast_time or time input, forecast_time is defined in _open_and_cache
|
|
320
321
|
|
|
@@ -28,8 +28,9 @@ import xarray as xr
|
|
|
28
28
|
from overrides import overrides
|
|
29
29
|
|
|
30
30
|
import pycontrails
|
|
31
|
-
from pycontrails.core import cache
|
|
31
|
+
from pycontrails.core import cache
|
|
32
32
|
from pycontrails.core.met import MetDataset, MetVariable
|
|
33
|
+
from pycontrails.datalib._met_utils import metsource
|
|
33
34
|
from pycontrails.datalib.ecmwf.common import ECMWFAPI
|
|
34
35
|
from pycontrails.datalib.ecmwf.model_levels import pressure_levels_at_model_levels
|
|
35
36
|
from pycontrails.datalib.ecmwf.variables import MODEL_LEVEL_VARIABLES
|
|
@@ -70,7 +71,7 @@ class HRESModelLevel(ECMWFAPI):
|
|
|
70
71
|
|
|
71
72
|
Parameters
|
|
72
73
|
----------
|
|
73
|
-
time :
|
|
74
|
+
time : metsource.TimeInput
|
|
74
75
|
The time range for data retrieval, either a single datetime or (start, end) datetime range.
|
|
75
76
|
Input must be datetime-like or tuple of datetime-like
|
|
76
77
|
(:py:class:`datetime.datetime`, :class:`pandas.Timestamp`, :class:`numpy.datetime64`)
|
|
@@ -80,9 +81,9 @@ class HRESModelLevel(ECMWFAPI):
|
|
|
80
81
|
If ``forecast_time`` is unspecified, the forecast time will
|
|
81
82
|
be assumed to be the nearest synoptic hour available in the operational archive (00 or 12).
|
|
82
83
|
All subsequent times will be downloaded for relative to :attr:`forecast_time`.
|
|
83
|
-
variables :
|
|
84
|
+
variables : metsource.VariableInput
|
|
84
85
|
Variable name (i.e. "t", "air_temperature", ["air_temperature, specific_humidity"])
|
|
85
|
-
pressure_levels :
|
|
86
|
+
pressure_levels : metsource.PressureLevelInput, optional
|
|
86
87
|
Pressure levels for data, in hPa (mbar).
|
|
87
88
|
To download surface-level parameters, use :class:`pycontrails.datalib.ecmwf.HRES`.
|
|
88
89
|
Defaults to pressure levels that match model levels at a nominal surface pressure.
|
|
@@ -119,9 +120,9 @@ class HRESModelLevel(ECMWFAPI):
|
|
|
119
120
|
|
|
120
121
|
def __init__(
|
|
121
122
|
self,
|
|
122
|
-
time:
|
|
123
|
-
variables:
|
|
124
|
-
pressure_levels:
|
|
123
|
+
time: metsource.TimeInput,
|
|
124
|
+
variables: metsource.VariableInput,
|
|
125
|
+
pressure_levels: metsource.PressureLevelInput | None = None,
|
|
125
126
|
timestep_freq: str | None = None,
|
|
126
127
|
grid: float | None = None,
|
|
127
128
|
forecast_time: DatetimeLike | None = None,
|
|
@@ -165,15 +166,15 @@ class HRESModelLevel(ECMWFAPI):
|
|
|
165
166
|
raise ValueError(msg)
|
|
166
167
|
self.levels = levels
|
|
167
168
|
|
|
168
|
-
forecast_hours =
|
|
169
|
+
forecast_hours = metsource.parse_timesteps(time, freq="1h")
|
|
169
170
|
if forecast_time is None:
|
|
170
|
-
self.forecast_time =
|
|
171
|
+
self.forecast_time = metsource.round_hour(forecast_hours[0], 12)
|
|
171
172
|
else:
|
|
172
173
|
forecast_time_pd = pd.to_datetime(forecast_time)
|
|
173
174
|
if (hour := forecast_time_pd.hour) % 12:
|
|
174
175
|
msg = f"Forecast hour must be one of 00 or 12 but is {hour:02d}."
|
|
175
176
|
raise ValueError(msg)
|
|
176
|
-
self.forecast_time =
|
|
177
|
+
self.forecast_time = metsource.round_hour(forecast_time_pd.to_pydatetime(), 12)
|
|
177
178
|
|
|
178
179
|
last_step = (forecast_hours[-1] - self.forecast_time) / timedelta(hours=1)
|
|
179
180
|
if last_step > LAST_STEP_6H:
|
|
@@ -188,7 +189,7 @@ class HRESModelLevel(ECMWFAPI):
|
|
|
188
189
|
)
|
|
189
190
|
if timestep_freq is None:
|
|
190
191
|
timestep_freq = datasource_timestep_freq
|
|
191
|
-
if not
|
|
192
|
+
if not metsource.validate_timestep_freq(timestep_freq, datasource_timestep_freq):
|
|
192
193
|
msg = (
|
|
193
194
|
f"Forecast out to step {last_step} "
|
|
194
195
|
f"has timestep frequency of {datasource_timestep_freq} "
|
|
@@ -196,15 +197,15 @@ class HRESModelLevel(ECMWFAPI):
|
|
|
196
197
|
)
|
|
197
198
|
raise ValueError(msg)
|
|
198
199
|
|
|
199
|
-
self.timesteps =
|
|
200
|
+
self.timesteps = metsource.parse_timesteps(time, freq=timestep_freq)
|
|
200
201
|
if self.step_offset < 0:
|
|
201
202
|
msg = f"Selected forecast time {self.forecast_time} is after first timestep."
|
|
202
203
|
raise ValueError(msg)
|
|
203
204
|
|
|
204
205
|
if pressure_levels is None:
|
|
205
206
|
pressure_levels = pressure_levels_at_model_levels(20_000.0, 50_000.0)
|
|
206
|
-
self.pressure_levels =
|
|
207
|
-
self.variables =
|
|
207
|
+
self.pressure_levels = metsource.parse_pressure_levels(pressure_levels)
|
|
208
|
+
self.variables = metsource.parse_variables(variables, self.pressure_level_variables)
|
|
208
209
|
|
|
209
210
|
def __repr__(self) -> str:
|
|
210
211
|
base = super().__repr__()
|
pycontrails/datalib/ecmwf/ifs.py
CHANGED
|
@@ -15,13 +15,14 @@ import pandas as pd
|
|
|
15
15
|
import xarray as xr
|
|
16
16
|
from overrides import overrides
|
|
17
17
|
|
|
18
|
-
from pycontrails.core import
|
|
18
|
+
from pycontrails.core import met
|
|
19
|
+
from pycontrails.datalib._met_utils import metsource
|
|
19
20
|
from pycontrails.datalib.ecmwf.variables import ECMWF_VARIABLES
|
|
20
21
|
from pycontrails.physics import constants
|
|
21
22
|
from pycontrails.utils.types import DatetimeLike
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
class IFS(
|
|
25
|
+
class IFS(metsource.MetDataSource):
|
|
25
26
|
"""
|
|
26
27
|
ECMWF Integrated Forecasting System (IFS) data source.
|
|
27
28
|
|
|
@@ -31,16 +32,16 @@ class IFS(datalib.MetDataSource):
|
|
|
31
32
|
|
|
32
33
|
Parameters
|
|
33
34
|
----------
|
|
34
|
-
time :
|
|
35
|
+
time : metsource.TimeInput | None
|
|
35
36
|
The time range for data retrieval, either a single datetime or (start, end) datetime range.
|
|
36
37
|
Input must be a single datetime-like or tuple of datetime-like
|
|
37
38
|
(datetime, :class:`pandas.Timestamp`, :class:`numpy.datetime64`)
|
|
38
39
|
specifying the (start, end) of the date range, inclusive.
|
|
39
40
|
If None, all time coordinates will be loaded.
|
|
40
|
-
variables :
|
|
41
|
+
variables : metsource.VariableInput
|
|
41
42
|
Variable name (i.e. "air_temperature", ["air_temperature, relative_humidity"])
|
|
42
43
|
See :attr:`pressure_level_variables` for the list of available variables.
|
|
43
|
-
pressure_levels :
|
|
44
|
+
pressure_levels : metsource.PressureLevelInput, optional
|
|
44
45
|
Pressure level bounds for data (min, max), in hPa (mbar)
|
|
45
46
|
Set to -1 for to download surface level parameters.
|
|
46
47
|
Defaults to -1.
|
|
@@ -69,9 +70,9 @@ class IFS(datalib.MetDataSource):
|
|
|
69
70
|
|
|
70
71
|
def __init__(
|
|
71
72
|
self,
|
|
72
|
-
time:
|
|
73
|
-
variables:
|
|
74
|
-
pressure_levels:
|
|
73
|
+
time: metsource.TimeInput | None,
|
|
74
|
+
variables: metsource.VariableInput,
|
|
75
|
+
pressure_levels: metsource.PressureLevelInput = -1,
|
|
75
76
|
paths: str | list[str] | pathlib.Path | list[pathlib.Path] | None = None,
|
|
76
77
|
grid: float | None = None,
|
|
77
78
|
forecast_path: str | pathlib.Path | None = None,
|
|
@@ -89,9 +90,9 @@ class IFS(datalib.MetDataSource):
|
|
|
89
90
|
self.forecast_date = pd.to_datetime(forecast_date).to_pydatetime()
|
|
90
91
|
|
|
91
92
|
# parse inputs
|
|
92
|
-
self.timesteps =
|
|
93
|
-
self.pressure_levels =
|
|
94
|
-
self.variables =
|
|
93
|
+
self.timesteps = metsource.parse_timesteps(time, freq="3h")
|
|
94
|
+
self.pressure_levels = metsource.parse_pressure_levels(pressure_levels, None)
|
|
95
|
+
self.variables = metsource.parse_variables(variables, self.supported_variables)
|
|
95
96
|
|
|
96
97
|
def __repr__(self) -> str:
|
|
97
98
|
base = super().__repr__()
|
|
@@ -221,8 +222,8 @@ class IFS(datalib.MetDataSource):
|
|
|
221
222
|
LOG.debug(f"Loading IFS forecast date {date_str}")
|
|
222
223
|
|
|
223
224
|
# load each dataset
|
|
224
|
-
xr_kwargs.setdefault("chunks",
|
|
225
|
-
xr_kwargs.setdefault("engine",
|
|
225
|
+
xr_kwargs.setdefault("chunks", metsource.DEFAULT_CHUNKS)
|
|
226
|
+
xr_kwargs.setdefault("engine", metsource.NETCDF_ENGINE)
|
|
226
227
|
ds_full = xr.open_dataset(path_full, **xr_kwargs)
|
|
227
228
|
ds_fl = xr.open_dataset(path_fl, **xr_kwargs)
|
|
228
229
|
ds_surface = xr.open_dataset(path_surface, **xr_kwargs)
|
pycontrails/datalib/gfs/gfs.py
CHANGED
|
@@ -22,7 +22,8 @@ import xarray as xr
|
|
|
22
22
|
from overrides import overrides
|
|
23
23
|
|
|
24
24
|
import pycontrails
|
|
25
|
-
from pycontrails.core import cache,
|
|
25
|
+
from pycontrails.core import cache, met
|
|
26
|
+
from pycontrails.datalib._met_utils import metsource
|
|
26
27
|
from pycontrails.datalib.gfs.variables import (
|
|
27
28
|
PRESSURE_LEVEL_VARIABLES,
|
|
28
29
|
SURFACE_VARIABLES,
|
|
@@ -43,12 +44,12 @@ logger = logging.getLogger(__name__)
|
|
|
43
44
|
GFS_FORECAST_BUCKET = "noaa-gfs-bdp-pds"
|
|
44
45
|
|
|
45
46
|
|
|
46
|
-
class GFSForecast(
|
|
47
|
+
class GFSForecast(metsource.MetDataSource):
|
|
47
48
|
"""GFS Forecast data access.
|
|
48
49
|
|
|
49
50
|
Parameters
|
|
50
51
|
----------
|
|
51
|
-
time : `
|
|
52
|
+
time : `metsource.TimeInput`
|
|
52
53
|
The time range for data retrieval, either a single datetime or (start, end) datetime range.
|
|
53
54
|
Input must be a single datetime-like or tuple of datetime-like (datetime,
|
|
54
55
|
:class:`pandas.Timestamp`, :class:`numpy.datetime64`)
|
|
@@ -56,10 +57,10 @@ class GFSForecast(datalib.MetDataSource):
|
|
|
56
57
|
All times will be downloaded for a single forecast model run nearest to the start time
|
|
57
58
|
(see :attr:`forecast_time`)
|
|
58
59
|
If None, ``paths`` must be defined and all time coordinates will be loaded from files.
|
|
59
|
-
variables : `
|
|
60
|
+
variables : `metsource.VariableInput`
|
|
60
61
|
Variable name (i.e. "temperature", ["temperature, relative_humidity"])
|
|
61
62
|
See :attr:`pressure_level_variables` for the list of available variables.
|
|
62
|
-
pressure_levels : `
|
|
63
|
+
pressure_levels : `metsource.PressureLevelInput`, optional
|
|
63
64
|
Pressure levels for data, in hPa (mbar)
|
|
64
65
|
Set to [-1] for to download surface level parameters.
|
|
65
66
|
Defaults to [-1].
|
|
@@ -132,9 +133,9 @@ class GFSForecast(datalib.MetDataSource):
|
|
|
132
133
|
|
|
133
134
|
def __init__(
|
|
134
135
|
self,
|
|
135
|
-
time:
|
|
136
|
-
variables:
|
|
137
|
-
pressure_levels:
|
|
136
|
+
time: metsource.TimeInput | None,
|
|
137
|
+
variables: metsource.VariableInput,
|
|
138
|
+
pressure_levels: metsource.PressureLevelInput = -1,
|
|
138
139
|
paths: str | list[str] | pathlib.Path | list[pathlib.Path] | None = None,
|
|
139
140
|
grid: float = 0.25,
|
|
140
141
|
forecast_time: DatetimeLike | None = None,
|
|
@@ -175,13 +176,13 @@ class GFSForecast(datalib.MetDataSource):
|
|
|
175
176
|
# 3 hourly for 0.5 and 1 degree grid
|
|
176
177
|
# https://www.nco.ncep.noaa.gov/pmb/products/gfs/
|
|
177
178
|
freq = "1h" if grid == 0.25 else "3h"
|
|
178
|
-
self.timesteps =
|
|
179
|
+
self.timesteps = metsource.parse_timesteps(time, freq=freq)
|
|
179
180
|
|
|
180
|
-
self.pressure_levels =
|
|
181
|
+
self.pressure_levels = metsource.parse_pressure_levels(
|
|
181
182
|
pressure_levels, self.supported_pressure_levels
|
|
182
183
|
)
|
|
183
|
-
self.variables =
|
|
184
|
-
self.grid =
|
|
184
|
+
self.variables = metsource.parse_variables(variables, self.supported_variables)
|
|
185
|
+
self.grid = metsource.parse_grid(grid, (0.25, 0.5, 1))
|
|
185
186
|
|
|
186
187
|
# note GFS allows unsigned requests (no credentials)
|
|
187
188
|
# https://stackoverflow.com/questions/34865927/can-i-use-boto3-anonymously/34866092#34866092
|
|
@@ -195,12 +196,12 @@ class GFSForecast(datalib.MetDataSource):
|
|
|
195
196
|
if forecast_time_pd.hour % 6:
|
|
196
197
|
raise ValueError("Forecast hour must be on one of 00, 06, 12, 18")
|
|
197
198
|
|
|
198
|
-
self.forecast_time =
|
|
199
|
+
self.forecast_time = metsource.round_hour(forecast_time_pd.to_pydatetime(), 6)
|
|
199
200
|
|
|
200
201
|
# if no specific forecast is requested, set the forecast time using timesteps
|
|
201
202
|
else:
|
|
202
203
|
# round first element to the nearest 6 hour time (00, 06, 12, 18 UTC) for forecast_time
|
|
203
|
-
self.forecast_time =
|
|
204
|
+
self.forecast_time = metsource.round_hour(self.timesteps[0], 6)
|
|
204
205
|
|
|
205
206
|
def __repr__(self) -> str:
|
|
206
207
|
base = super().__repr__()
|
pycontrails/datalib/goes.py
CHANGED
|
@@ -35,7 +35,7 @@ except ModuleNotFoundError as exc:
|
|
|
35
35
|
name="goes module",
|
|
36
36
|
package_name="cartopy",
|
|
37
37
|
module_not_found_error=exc,
|
|
38
|
-
pycontrails_optional_package="
|
|
38
|
+
pycontrails_optional_package="sat",
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
try:
|
|
@@ -45,7 +45,7 @@ except ModuleNotFoundError as exc:
|
|
|
45
45
|
name="goes module",
|
|
46
46
|
package_name="gcsfs",
|
|
47
47
|
module_not_found_error=exc,
|
|
48
|
-
pycontrails_optional_package="
|
|
48
|
+
pycontrails_optional_package="sat",
|
|
49
49
|
)
|
|
50
50
|
|
|
51
51
|
|