earth2studio 0.1.0__py3-none-any.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.
- earth2studio/__init__.py +17 -0
- earth2studio/data/__init__.py +26 -0
- earth2studio/data/arco.py +300 -0
- earth2studio/data/base.py +51 -0
- earth2studio/data/cds.py +385 -0
- earth2studio/data/gfs.py +356 -0
- earth2studio/data/hrrr.py +227 -0
- earth2studio/data/ifs.py +285 -0
- earth2studio/data/rand.py +74 -0
- earth2studio/data/rx.py +298 -0
- earth2studio/data/utils.py +126 -0
- earth2studio/data/xr.py +105 -0
- earth2studio/io/__init__.py +21 -0
- earth2studio/io/base.py +69 -0
- earth2studio/io/kv.py +197 -0
- earth2studio/io/netcdf4.py +238 -0
- earth2studio/io/xarray.py +171 -0
- earth2studio/io/zarr.py +200 -0
- earth2studio/lexicon/__init__.py +21 -0
- earth2studio/lexicon/arco.py +132 -0
- earth2studio/lexicon/base.py +121 -0
- earth2studio/lexicon/cds.py +136 -0
- earth2studio/lexicon/gfs.py +139 -0
- earth2studio/lexicon/hrrr.py +114 -0
- earth2studio/lexicon/ifs.py +116 -0
- earth2studio/models/auto.py +146 -0
- earth2studio/models/batch.py +227 -0
- earth2studio/models/dx/__init__.py +21 -0
- earth2studio/models/dx/base.py +86 -0
- earth2studio/models/dx/climatenet.py +144 -0
- earth2studio/models/dx/corrdiff.py +502 -0
- earth2studio/models/dx/identity.py +68 -0
- earth2studio/models/dx/precipitation_afno.py +159 -0
- earth2studio/models/nn/afno_precip.py +69 -0
- earth2studio/models/nn/climatenet_conv.py +482 -0
- earth2studio/models/px/__init__.py +23 -0
- earth2studio/models/px/base.py +109 -0
- earth2studio/models/px/dlwp.py +371 -0
- earth2studio/models/px/fcn.py +233 -0
- earth2studio/models/px/fengwu.py +406 -0
- earth2studio/models/px/pangu.py +733 -0
- earth2studio/models/px/persistence.py +190 -0
- earth2studio/models/px/sfno.py +299 -0
- earth2studio/models/px/utils.py +30 -0
- earth2studio/perturbation/__init__.py +22 -0
- earth2studio/perturbation/base.py +48 -0
- earth2studio/perturbation/brown.py +85 -0
- earth2studio/perturbation/bv.py +108 -0
- earth2studio/perturbation/gaussian.py +54 -0
- earth2studio/perturbation/spherical.py +242 -0
- earth2studio/perturbation/utils.py +133 -0
- earth2studio/perturbation/zero.py +48 -0
- earth2studio/run.py +243 -0
- earth2studio/statistics/__init__.py +20 -0
- earth2studio/statistics/base.py +72 -0
- earth2studio/statistics/moments.py +275 -0
- earth2studio/statistics/rmse.py +98 -0
- earth2studio/statistics/utils.py +51 -0
- earth2studio/statistics/weights.py +46 -0
- earth2studio/utils/__init__.py +21 -0
- earth2studio/utils/coords.py +308 -0
- earth2studio/utils/time.py +75 -0
- earth2studio/utils/type.py +26 -0
- earth2studio-0.1.0.dist-info/LICENSE +202 -0
- earth2studio-0.1.0.dist-info/METADATA +173 -0
- earth2studio-0.1.0.dist-info/RECORD +68 -0
- earth2studio-0.1.0.dist-info/WHEEL +5 -0
- earth2studio-0.1.0.dist-info/top_level.txt +1 -0
earth2studio/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
|
|
2
|
+
# SPDX-FileCopyrightText: All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
|
|
2
|
+
# SPDX-FileCopyrightText: All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
from .base import DataSource # noqa
|
|
18
|
+
from .arco import ARCO # noq
|
|
19
|
+
from .cds import CDS # noq
|
|
20
|
+
from .gfs import GFS # noq
|
|
21
|
+
from .hrrr import HRRR # noq
|
|
22
|
+
from .ifs import IFS # noq
|
|
23
|
+
from .rand import Random # noqa
|
|
24
|
+
from .rx import LandSeaMask, SurfaceGeoPotential, CosineSolarZenith # noqa
|
|
25
|
+
from .xr import DataArrayFile, DataSetFile # noqa
|
|
26
|
+
from .utils import fetch_data, prep_data_array
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
|
|
2
|
+
# SPDX-FileCopyrightText: All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
import pathlib
|
|
19
|
+
import shutil
|
|
20
|
+
from datetime import datetime, timedelta
|
|
21
|
+
|
|
22
|
+
import fsspec
|
|
23
|
+
import gcsfs
|
|
24
|
+
import numpy as np
|
|
25
|
+
import xarray as xr
|
|
26
|
+
import zarr
|
|
27
|
+
from loguru import logger
|
|
28
|
+
from modulus.distributed.manager import DistributedManager
|
|
29
|
+
from tqdm import tqdm
|
|
30
|
+
|
|
31
|
+
from earth2studio.data.utils import prep_data_inputs
|
|
32
|
+
from earth2studio.lexicon import ARCOLexicon
|
|
33
|
+
from earth2studio.utils.type import TimeArray, VariableArray
|
|
34
|
+
|
|
35
|
+
LOCAL_CACHE = os.path.join(os.path.expanduser("~"), ".cache", "earth2studio")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ARCO:
|
|
39
|
+
"""Analysis-Ready, Cloud Optimized (ARCO) is a data store of ERA5 re-analysis data
|
|
40
|
+
currated by Google. This data is stored in Zarr format and contains 31 surface and
|
|
41
|
+
pressure level variables (for 37 pressure levels) on a 0.25 degree lat lon grid.
|
|
42
|
+
Temporal resolution is 1 hour.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
cache : bool, optional
|
|
47
|
+
Cache data source on local memory, by default True
|
|
48
|
+
verbose : bool, optional
|
|
49
|
+
Print download progress, by default True
|
|
50
|
+
|
|
51
|
+
Warning
|
|
52
|
+
-------
|
|
53
|
+
This is a remote data source and can potentially download a large amount of data
|
|
54
|
+
to your local machine for large requests.
|
|
55
|
+
|
|
56
|
+
Note
|
|
57
|
+
----
|
|
58
|
+
Additional information on the data repository can be referenced here:
|
|
59
|
+
|
|
60
|
+
- https://cloud.google.com/storage/docs/public-datasets/era5
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
ARCO_LAT = np.linspace(90, -90, 721)
|
|
64
|
+
ARCO_LON = np.linspace(0, 359.75, 1440)
|
|
65
|
+
|
|
66
|
+
def __init__(self, cache: bool = True, verbose: bool = True):
|
|
67
|
+
self._cache = cache
|
|
68
|
+
self._verbose = verbose
|
|
69
|
+
|
|
70
|
+
if self._cache:
|
|
71
|
+
gcstore = fsspec.get_mapper(
|
|
72
|
+
"gs://gcp-public-data-arco-era5/ar/full_37-1h-0p25deg-chunk-1.zarr-v3",
|
|
73
|
+
target_protocol="gs",
|
|
74
|
+
cache_storage=self.cache,
|
|
75
|
+
target_options={"anon": True, "default_block_size": 2**20},
|
|
76
|
+
)
|
|
77
|
+
else:
|
|
78
|
+
gcs = gcsfs.GCSFileSystem(cache_timeout=-1)
|
|
79
|
+
gcstore = gcsfs.GCSMap(
|
|
80
|
+
"gs://gcp-public-data-arco-era5/ar/full_37-1h-0p25deg-chunk-1.zarr-v3",
|
|
81
|
+
gcs=gcs,
|
|
82
|
+
)
|
|
83
|
+
self.zarr_group = zarr.open(gcstore, mode="r")
|
|
84
|
+
|
|
85
|
+
def __call__(
|
|
86
|
+
self,
|
|
87
|
+
time: datetime | list[datetime] | TimeArray,
|
|
88
|
+
variable: str | list[str] | VariableArray,
|
|
89
|
+
) -> xr.DataArray:
|
|
90
|
+
"""Function to get data.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
time : datetime | list[datetime] | TimeArray
|
|
95
|
+
Timestamps to return data for (UTC).
|
|
96
|
+
variable : str | list[str] | VariableArray
|
|
97
|
+
String, list of strings or array of strings that refer to variables to
|
|
98
|
+
return. Must be in the ARCO lexicon.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
xr.DataArray
|
|
103
|
+
ERA5 weather data array from ARCO
|
|
104
|
+
"""
|
|
105
|
+
time, variable = prep_data_inputs(time, variable)
|
|
106
|
+
# Create cache dir if doesnt exist
|
|
107
|
+
pathlib.Path(self.cache).mkdir(parents=True, exist_ok=True)
|
|
108
|
+
|
|
109
|
+
# Make sure input time is valid
|
|
110
|
+
self._validate_time(time)
|
|
111
|
+
|
|
112
|
+
# Fetch index file for requested time
|
|
113
|
+
data_arrays = []
|
|
114
|
+
for t0 in time:
|
|
115
|
+
data_array = self.fetch_arco_dataarray(t0, variable)
|
|
116
|
+
data_arrays.append(data_array)
|
|
117
|
+
|
|
118
|
+
# Delete cache if needed
|
|
119
|
+
if not self._cache:
|
|
120
|
+
shutil.rmtree(self.cache)
|
|
121
|
+
|
|
122
|
+
return xr.concat(data_arrays, dim="time")
|
|
123
|
+
|
|
124
|
+
def fetch_arco_dataarray(
|
|
125
|
+
self,
|
|
126
|
+
time: datetime,
|
|
127
|
+
variables: list[str],
|
|
128
|
+
) -> xr.DataArray:
|
|
129
|
+
"""Retrives ARCO data array for given date time by downloading a lat lon array
|
|
130
|
+
from the Zarr store
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
time : datetime
|
|
135
|
+
Date time to fetch
|
|
136
|
+
variables : list[str]
|
|
137
|
+
list of atmosphric variables to fetch. Must be supported in ARCO lexicon
|
|
138
|
+
|
|
139
|
+
Returns
|
|
140
|
+
-------
|
|
141
|
+
xr.DataArray
|
|
142
|
+
ARCO data array for given date time
|
|
143
|
+
"""
|
|
144
|
+
arcoda = xr.DataArray(
|
|
145
|
+
data=np.empty((1, len(variables), len(self.ARCO_LAT), len(self.ARCO_LON))),
|
|
146
|
+
dims=["time", "variable", "lat", "lon"],
|
|
147
|
+
coords={
|
|
148
|
+
"time": [time],
|
|
149
|
+
"variable": variables,
|
|
150
|
+
"lat": self.ARCO_LAT,
|
|
151
|
+
"lon": self.ARCO_LON,
|
|
152
|
+
},
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Load levels coordinate system from Zarr store and check
|
|
156
|
+
level_coords = self.zarr_group["level"][:]
|
|
157
|
+
# Get time index (vanilla zarr doesnt support date indices)
|
|
158
|
+
time_index = self._get_time_index(time)
|
|
159
|
+
|
|
160
|
+
# TODO: Add MP here
|
|
161
|
+
for i, variable in enumerate(
|
|
162
|
+
tqdm(
|
|
163
|
+
variables, desc=f"Fetching ARCO for {time}", disable=(not self._verbose)
|
|
164
|
+
)
|
|
165
|
+
):
|
|
166
|
+
logger.debug(
|
|
167
|
+
f"Fetching ARCO zarr array for variable: {variable} at {time.isoformat()}"
|
|
168
|
+
)
|
|
169
|
+
try:
|
|
170
|
+
arco_name, modifier = ARCOLexicon[variable]
|
|
171
|
+
except KeyError as e:
|
|
172
|
+
logger.error(f"variable id {variable} not found in ARCO lexicon")
|
|
173
|
+
raise e
|
|
174
|
+
|
|
175
|
+
arco_variable, level = arco_name.split("::")
|
|
176
|
+
|
|
177
|
+
# special variables
|
|
178
|
+
if variable == "tp06":
|
|
179
|
+
arcoda[0, i] = modifier(self._fetch_tp06(time))
|
|
180
|
+
continue
|
|
181
|
+
|
|
182
|
+
shape = self.zarr_group[arco_variable].shape
|
|
183
|
+
# Static variables
|
|
184
|
+
if len(shape) == 2:
|
|
185
|
+
arcoda[0, i] = modifier(self.zarr_group[arco_variable][:])
|
|
186
|
+
# Surface variable
|
|
187
|
+
elif len(shape) == 3:
|
|
188
|
+
arcoda[0, i] = modifier(self.zarr_group[arco_variable][time_index])
|
|
189
|
+
# Atmospheric variable
|
|
190
|
+
else:
|
|
191
|
+
level_index = np.where(level_coords == int(level))[0][0]
|
|
192
|
+
arcoda[0, i] = modifier(
|
|
193
|
+
self.zarr_group[arco_variable][time_index, level_index]
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
return arcoda
|
|
197
|
+
|
|
198
|
+
def _fetch_tp06(self, time: datetime) -> np.array:
|
|
199
|
+
"""Handle special tp06 variable"""
|
|
200
|
+
tp06_array = np.zeros((self.ARCO_LAT.shape[0], self.ARCO_LON.shape[0]))
|
|
201
|
+
# Accumulate over past 6 hours
|
|
202
|
+
for i in range(6):
|
|
203
|
+
time_index = self._get_time_index(time - timedelta(hours=i))
|
|
204
|
+
tp06_array += self.zarr_group["total_precipitation"][time_index]
|
|
205
|
+
|
|
206
|
+
return tp06_array
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def cache(self) -> str:
|
|
210
|
+
"""Get the appropriate cache location."""
|
|
211
|
+
cache_location = os.path.join(LOCAL_CACHE, "arco")
|
|
212
|
+
if not self._cache:
|
|
213
|
+
cache_location = os.path.join(
|
|
214
|
+
cache_location, f"tmp_{DistributedManager().rank}"
|
|
215
|
+
)
|
|
216
|
+
return cache_location
|
|
217
|
+
|
|
218
|
+
@classmethod
|
|
219
|
+
def _validate_time(cls, times: list[datetime]) -> None:
|
|
220
|
+
"""Verify if date time is valid for ARCO
|
|
221
|
+
|
|
222
|
+
Parameters
|
|
223
|
+
----------
|
|
224
|
+
times : list[datetime]
|
|
225
|
+
list of date times to fetch data
|
|
226
|
+
"""
|
|
227
|
+
for time in times:
|
|
228
|
+
if not (time - datetime(1900, 1, 1)).total_seconds() % 3600 == 0:
|
|
229
|
+
raise ValueError(
|
|
230
|
+
f"Requested date time {time} needs to be 1 hour interval for ARCO"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
if time < datetime(year=1940, month=1, day=1):
|
|
234
|
+
raise ValueError(
|
|
235
|
+
f"Requested date time {time} needs to be after January 1st, 1940 for ARCO"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
if time >= datetime(year=2023, month=11, day=10):
|
|
239
|
+
raise ValueError(
|
|
240
|
+
f"Requested date time {time} needs to be before November 10th, 2023 for ARCO"
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# if not self.available(time):
|
|
244
|
+
# raise ValueError(f"Requested date time {time} not available in ARCO")
|
|
245
|
+
|
|
246
|
+
@classmethod
|
|
247
|
+
def _get_time_index(cls, time: datetime) -> int:
|
|
248
|
+
"""Small little index converter to go from datetime to integer index.
|
|
249
|
+
We don't need to do with with xarray, but since we are vanilla zaar for speed
|
|
250
|
+
this conversion must be manual.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
time : datetime
|
|
255
|
+
Input date time
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
int
|
|
260
|
+
Time coordinate index of ARCO data
|
|
261
|
+
"""
|
|
262
|
+
start_date = datetime(year=1900, month=1, day=1)
|
|
263
|
+
duration = time - start_date
|
|
264
|
+
return int(divmod(duration.total_seconds(), 3600)[0])
|
|
265
|
+
|
|
266
|
+
@classmethod
|
|
267
|
+
def available(cls, time: datetime | np.datetime64) -> bool:
|
|
268
|
+
"""Checks if given date time is avaliable in the ARCO data source
|
|
269
|
+
|
|
270
|
+
Parameters
|
|
271
|
+
----------
|
|
272
|
+
time : datetime | np.datetime64
|
|
273
|
+
Date time to access
|
|
274
|
+
|
|
275
|
+
Returns
|
|
276
|
+
-------
|
|
277
|
+
bool
|
|
278
|
+
If date time is avaiable
|
|
279
|
+
"""
|
|
280
|
+
if isinstance(time, np.datetime64): # np.datetime64 -> datetime
|
|
281
|
+
_unix = np.datetime64(0, "s")
|
|
282
|
+
_ds = np.timedelta64(1, "s")
|
|
283
|
+
time = datetime.utcfromtimestamp((time - _unix) / _ds)
|
|
284
|
+
|
|
285
|
+
# Offline checks
|
|
286
|
+
try:
|
|
287
|
+
cls._validate_time([time])
|
|
288
|
+
except ValueError:
|
|
289
|
+
return False
|
|
290
|
+
|
|
291
|
+
gcs = gcsfs.GCSFileSystem(cache_timeout=-1)
|
|
292
|
+
gcstore = gcsfs.GCSMap(
|
|
293
|
+
"gs://gcp-public-data-arco-era5/ar/full_37-1h-0p25deg-chunk-1.zarr-v3",
|
|
294
|
+
gcs=gcs,
|
|
295
|
+
)
|
|
296
|
+
zarr_group = zarr.open(gcstore, mode="r")
|
|
297
|
+
# Load time coordinate system from Zarr store and check
|
|
298
|
+
time_index = cls._get_time_index(time)
|
|
299
|
+
max_index = zarr_group["time"][-1]
|
|
300
|
+
return time_index >= 0 and time_index <= max_index
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
|
|
2
|
+
# SPDX-FileCopyrightText: All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
from typing import Protocol, runtime_checkable
|
|
19
|
+
|
|
20
|
+
import xarray as xr
|
|
21
|
+
|
|
22
|
+
from earth2studio.utils.type import TimeArray, VariableArray
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@runtime_checkable
|
|
26
|
+
class DataSource(Protocol):
|
|
27
|
+
"""Data source interface."""
|
|
28
|
+
|
|
29
|
+
def __call__(
|
|
30
|
+
self,
|
|
31
|
+
time: datetime | list[datetime] | TimeArray,
|
|
32
|
+
variable: str | list[str] | VariableArray,
|
|
33
|
+
) -> xr.DataArray:
|
|
34
|
+
"""Function to get data.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
time : datetime | list[datetime] | TimeArray
|
|
39
|
+
Datetime, list of datetimes or array of np.datetime64 to return data for.
|
|
40
|
+
variable : str | list[str] | VariableArray
|
|
41
|
+
String, list of strings or array of strings that refer to variables to
|
|
42
|
+
return.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
xr.DataArray
|
|
47
|
+
An xarray data-array with the dimensions [time, channel, ....]. The coords
|
|
48
|
+
should be provided. Time coordinate should be a datetime array and the
|
|
49
|
+
channel coordinate should be array of strings with Earth2Studio channel ids.
|
|
50
|
+
"""
|
|
51
|
+
pass
|