geospacelab 0.11.4__py3-none-any.whl → 0.12.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.
- geospacelab/__init__.py +1 -1
- geospacelab/datahub/sources/cdaweb/dmsp/ssusi/downloader.py +103 -0
- geospacelab/datahub/sources/cdaweb/dmsp/ssusi/edr_aur/__init__.py +17 -7
- geospacelab/datahub/sources/cdaweb/dmsp/ssusi/edr_aur/downloader.py +13 -62
- geospacelab/datahub/sources/cdaweb/dmsp/ssusi/sdr_disk/__init__.py +317 -0
- geospacelab/datahub/sources/cdaweb/dmsp/ssusi/sdr_disk/downloader.py +44 -0
- geospacelab/datahub/sources/cdaweb/dmsp/ssusi/sdr_disk/loader.py +198 -0
- geospacelab/datahub/sources/cdaweb/dmsp/ssusi/sdr_disk/variable_config.py +149 -0
- geospacelab/datahub/sources/cdaweb/downloader.py +396 -97
- geospacelab/datahub/sources/cdaweb/downloader_backup.py +93 -0
- geospacelab/datahub/sources/cdaweb/omni/__init__.py +26 -14
- geospacelab/datahub/sources/cdaweb/omni/downloader.py +97 -84
- geospacelab/datahub/sources/esa_eo/swarm/advanced/efi_tct02/__init__.py +1 -1
- geospacelab/datahub/sources/esa_eo/swarm/advanced/efi_tct02/downloader.py +1 -1
- geospacelab/datahub/sources/gfz/hpo/__init__.py +1 -1
- geospacelab/datahub/sources/gfz/hpo/variable_config.py +3 -1
- geospacelab/datahub/sources/madrigal/isr/pfisr/fitted/loader.py +1 -1
- geospacelab/datahub/sources/madrigal/satellites/dmsp/downloader.py +2 -1
- geospacelab/datahub/sources/tud/champ/dns_acc/__init__.py +24 -7
- geospacelab/datahub/sources/tud/champ/dns_acc/downloader.py +29 -36
- geospacelab/datahub/sources/tud/champ/dns_acc/loader.py +28 -2
- geospacelab/datahub/sources/tud/champ/wnd_acc/__init__.py +68 -10
- geospacelab/datahub/sources/tud/champ/wnd_acc/downloader.py +29 -36
- geospacelab/datahub/sources/tud/champ/wnd_acc/loader.py +36 -7
- geospacelab/datahub/sources/tud/champ/wnd_acc/variable_config.py +3 -3
- geospacelab/datahub/sources/tud/downloader.py +288 -113
- geospacelab/datahub/sources/tud/goce/dns_acc/__init__.py +354 -0
- geospacelab/datahub/sources/tud/goce/dns_acc/downloader.py +42 -0
- geospacelab/datahub/sources/tud/goce/dns_acc/loader.py +66 -0
- geospacelab/datahub/sources/tud/goce/dns_acc/variable_config.py +139 -0
- geospacelab/datahub/sources/tud/goce/dns_wnd_acc/__init__.py +3 -3
- geospacelab/datahub/sources/tud/goce/dns_wnd_acc_v01/__init__.py +339 -0
- geospacelab/datahub/sources/tud/goce/dns_wnd_acc_v01/downloader.py +42 -0
- geospacelab/datahub/sources/tud/goce/dns_wnd_acc_v01/loader.py +84 -0
- geospacelab/datahub/sources/tud/goce/dns_wnd_acc_v01/variable_config.py +212 -0
- geospacelab/datahub/sources/tud/goce/wnd_acc/__init__.py +339 -0
- geospacelab/datahub/sources/tud/goce/wnd_acc/downloader.py +42 -0
- geospacelab/datahub/sources/tud/goce/wnd_acc/loader.py +65 -0
- geospacelab/datahub/sources/tud/goce/wnd_acc/variable_config.py +188 -0
- geospacelab/datahub/sources/tud/grace/dns_acc/__init__.py +6 -3
- geospacelab/datahub/sources/tud/grace/dns_acc/downloader.py +29 -37
- geospacelab/datahub/sources/tud/grace/wnd_acc/__init__.py +21 -4
- geospacelab/datahub/sources/tud/grace/wnd_acc/downloader.py +29 -39
- geospacelab/datahub/sources/tud/grace/wnd_acc/loader.py +5 -1
- geospacelab/datahub/sources/tud/grace/wnd_acc/variable_config.py +74 -0
- geospacelab/datahub/sources/tud/grace_fo/dns_acc/__init__.py +6 -3
- geospacelab/datahub/sources/tud/grace_fo/dns_acc/downloader.py +35 -40
- geospacelab/datahub/sources/tud/grace_fo/wnd_acc/__init__.py +20 -4
- geospacelab/datahub/sources/tud/grace_fo/wnd_acc/downloader.py +29 -44
- geospacelab/datahub/sources/tud/grace_fo/wnd_acc/loader.py +4 -0
- geospacelab/datahub/sources/tud/grace_fo/wnd_acc/variable_config.py +73 -0
- geospacelab/datahub/sources/tud/swarm/dns_acc/__init__.py +27 -5
- geospacelab/datahub/sources/tud/swarm/dns_acc/downloader.py +29 -38
- geospacelab/datahub/sources/tud/swarm/dns_pod/__init__.py +24 -5
- geospacelab/datahub/sources/tud/swarm/dns_pod/downloader.py +29 -38
- geospacelab/datahub/sources/tud/swarm/dns_pod/loader.py +3 -0
- geospacelab/datahub/sources/wdc/asysym/downloader.py +2 -2
- geospacelab/visualization/mpl/panels.py +7 -3
- {geospacelab-0.11.4.dist-info → geospacelab-0.12.0.dist-info}/METADATA +1 -1
- {geospacelab-0.11.4.dist-info → geospacelab-0.12.0.dist-info}/RECORD +63 -45
- {geospacelab-0.11.4.dist-info → geospacelab-0.12.0.dist-info}/WHEEL +1 -1
- {geospacelab-0.11.4.dist-info → geospacelab-0.12.0.dist-info}/licenses/LICENSE +0 -0
- {geospacelab-0.11.4.dist-info → geospacelab-0.12.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# Licensed under the BSD 3-Clause License
|
|
2
|
+
# Copyright (C) 2021 GeospaceLab (geospacelab)
|
|
3
|
+
# Author: Lei Cai, Space Physics and Astronomy, University of Oulu
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import datetime
|
|
7
|
+
|
|
8
|
+
import geospacelab.datahub as datahub
|
|
9
|
+
from geospacelab.datahub import DatabaseModel, FacilityModel, InstrumentModel, ProductModel
|
|
10
|
+
from geospacelab.datahub.sources.tud import tud_database
|
|
11
|
+
from geospacelab.datahub.sources.tud.grace import grace_facility
|
|
12
|
+
from geospacelab.config import prf
|
|
13
|
+
import geospacelab.toolbox.utilities.pybasic as basic
|
|
14
|
+
import geospacelab.toolbox.utilities.pylogging as mylog
|
|
15
|
+
import geospacelab.toolbox.utilities.pydatetime as dttool
|
|
16
|
+
from geospacelab.datahub.sources.tud.goce.wnd_acc.loader import Loader as default_Loader
|
|
17
|
+
from geospacelab.datahub.sources.tud.goce.wnd_acc.downloader import (Downloader as default_Downloader)
|
|
18
|
+
import geospacelab.datahub.sources.tud.goce.wnd_acc.variable_config as var_config
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
default_dataset_attrs = {
|
|
22
|
+
'database': tud_database,
|
|
23
|
+
'facility': grace_facility,
|
|
24
|
+
'instrument': 'ACC',
|
|
25
|
+
'product': 'WND-ACC',
|
|
26
|
+
'data_file_ext': 'txt',
|
|
27
|
+
'product_version': 'v02',
|
|
28
|
+
'data_root_dir': prf.datahub_data_root_dir / 'TUD' / 'GOCE',
|
|
29
|
+
'allow_load': True,
|
|
30
|
+
'allow_download': True,
|
|
31
|
+
'force_download': False,
|
|
32
|
+
'data_search_recursive': False,
|
|
33
|
+
'add_AACGM': False,
|
|
34
|
+
'add_APEX': False,
|
|
35
|
+
'label_fields': ['database', 'facility', 'instrument', 'product', 'product_version'],
|
|
36
|
+
'load_mode': 'AUTO',
|
|
37
|
+
'time_clip': True,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
default_variable_names_v01 = []
|
|
41
|
+
default_variable_names_v02 = [
|
|
42
|
+
'SC_DATETIME',
|
|
43
|
+
'SC_GEO_LAT',
|
|
44
|
+
'SC_GEO_LON',
|
|
45
|
+
'SC_GEO_ALT',
|
|
46
|
+
'SC_ARG_LAT',
|
|
47
|
+
'SC_GEO_LST',
|
|
48
|
+
'u_CROSS',
|
|
49
|
+
'UNIT_VECTOR_N',
|
|
50
|
+
'UNIT_VECTOR_E',
|
|
51
|
+
'UNIT_VECTOR_D',
|
|
52
|
+
'u_CROSS_N',
|
|
53
|
+
'u_CROSS_E',
|
|
54
|
+
'u_CROSS_D',
|
|
55
|
+
'FLAG',
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
# default_data_search_recursive = True
|
|
59
|
+
|
|
60
|
+
default_attrs_required = ['sat_id']
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class Dataset(datahub.DatasetSourced):
|
|
64
|
+
def __init__(self, **kwargs):
|
|
65
|
+
kwargs = basic.dict_set_default(kwargs, **default_dataset_attrs)
|
|
66
|
+
|
|
67
|
+
super().__init__(**kwargs)
|
|
68
|
+
|
|
69
|
+
self.database = kwargs.pop('database', 'TUD')
|
|
70
|
+
self.facility = kwargs.pop('facility', 'GOCE')
|
|
71
|
+
self.instrument = kwargs.pop('instrument', 'ACC')
|
|
72
|
+
self.product = kwargs.pop('product', 'WND-ACC')
|
|
73
|
+
self.product_version = kwargs.pop('product_version', 'v02')
|
|
74
|
+
self.local_latest_version = ''
|
|
75
|
+
self.allow_download = kwargs.pop('allow_download', False)
|
|
76
|
+
self.force_download = kwargs.pop('force_download', False)
|
|
77
|
+
self.download_dry_run = kwargs.pop('download_dry_run', False)
|
|
78
|
+
|
|
79
|
+
self.add_AACGM = kwargs.pop('add_AACGM', False)
|
|
80
|
+
self.add_APEX = kwargs.pop('add_APEX', False)
|
|
81
|
+
self._data_root_dir = self.data_root_dir # Record the initial root dir
|
|
82
|
+
|
|
83
|
+
self.sat_id = kwargs.pop('sat_id', '')
|
|
84
|
+
|
|
85
|
+
self.metadata = {}
|
|
86
|
+
|
|
87
|
+
allow_load = kwargs.pop('allow_load', False)
|
|
88
|
+
|
|
89
|
+
# self.config(**kwargs)
|
|
90
|
+
|
|
91
|
+
if self.loader is None:
|
|
92
|
+
self.loader = default_Loader
|
|
93
|
+
|
|
94
|
+
if self.downloader is None:
|
|
95
|
+
self.downloader = default_Downloader
|
|
96
|
+
|
|
97
|
+
self._validate_attrs()
|
|
98
|
+
|
|
99
|
+
if allow_load:
|
|
100
|
+
self.load_data()
|
|
101
|
+
|
|
102
|
+
def _validate_attrs(self):
|
|
103
|
+
for attr_name in default_attrs_required:
|
|
104
|
+
attr = getattr(self, attr_name)
|
|
105
|
+
if not attr:
|
|
106
|
+
mylog.StreamLogger.warning("The parameter {} is required before loading data!".format(attr_name))
|
|
107
|
+
|
|
108
|
+
self.data_root_dir = self.data_root_dir / self.product.upper() / self.product_version
|
|
109
|
+
|
|
110
|
+
def label(self, **kwargs):
|
|
111
|
+
label = super().label()
|
|
112
|
+
return label
|
|
113
|
+
|
|
114
|
+
def load_data(self, **kwargs):
|
|
115
|
+
self.check_data_files(**kwargs)
|
|
116
|
+
if self.product_version == 'v01':
|
|
117
|
+
default_variable_names = default_variable_names_v01
|
|
118
|
+
else:
|
|
119
|
+
default_variable_names = default_variable_names_v02
|
|
120
|
+
self._set_default_variables(
|
|
121
|
+
default_variable_names,
|
|
122
|
+
configured_variables=var_config.configured_variables
|
|
123
|
+
)
|
|
124
|
+
for file_path in self.data_file_paths:
|
|
125
|
+
load_obj = self.loader(file_path, file_type='txt', version=self.product_version)
|
|
126
|
+
|
|
127
|
+
for var_name in self._variables.keys():
|
|
128
|
+
value = load_obj.variables[var_name]
|
|
129
|
+
self._variables[var_name].join(value)
|
|
130
|
+
|
|
131
|
+
# self.select_beams(field_aligned=True)
|
|
132
|
+
if self.time_clip:
|
|
133
|
+
self.time_filter_by_range(var_datetime_name='SC_DATETIME')
|
|
134
|
+
|
|
135
|
+
if self.add_AACGM:
|
|
136
|
+
self.convert_to_AACGM()
|
|
137
|
+
|
|
138
|
+
if self.add_APEX:
|
|
139
|
+
self.convert_to_APEX()
|
|
140
|
+
|
|
141
|
+
self._add_u_CT()
|
|
142
|
+
|
|
143
|
+
def _add_u_CT(self):
|
|
144
|
+
from geospacelab.observatory.orbit.utilities import LEOToolbox
|
|
145
|
+
ds_leo = LEOToolbox(self.dt_fr, self.dt_to)
|
|
146
|
+
ds_leo.clone_variables(self)
|
|
147
|
+
|
|
148
|
+
wind_unit_vector = np.concatenate(
|
|
149
|
+
(
|
|
150
|
+
self['UNIT_VECTOR_N'].value,
|
|
151
|
+
self['UNIT_VECTOR_E'].value,
|
|
152
|
+
self['UNIT_VECTOR_D'].value
|
|
153
|
+
),
|
|
154
|
+
axis=1
|
|
155
|
+
)
|
|
156
|
+
orbit_unit_vector = ds_leo.trajectory_local_unit_vector()
|
|
157
|
+
cp = np.cross(orbit_unit_vector, wind_unit_vector)
|
|
158
|
+
u_CT = -np.sign(cp[:, 2]) * (
|
|
159
|
+
(self['u_CROSS'].value.flatten() * self['UNIT_VECTOR_N'].flatten())**2 +
|
|
160
|
+
(self['u_CROSS'].value.flatten() * self['UNIT_VECTOR_E'].flatten())**2)**0.5
|
|
161
|
+
u_VCT = self['u_CROSS'].value.flatten() * self['UNIT_VECTOR_D'].flatten()
|
|
162
|
+
|
|
163
|
+
var = self['u_CROSS'].clone()
|
|
164
|
+
var.name = 'u_CT'
|
|
165
|
+
var.label = r'$u_{CT}$'
|
|
166
|
+
var.visual.axis[1].lim = [None, None]
|
|
167
|
+
var.value = u_CT[:, np.newaxis]
|
|
168
|
+
self['u_CT'] = var
|
|
169
|
+
|
|
170
|
+
var = self['u_CROSS'].clone()
|
|
171
|
+
var.name = 'u_VCT'
|
|
172
|
+
var.label = r'$u_{VCT}$'
|
|
173
|
+
var.visual.axis[1].lim = [None, None]
|
|
174
|
+
var.value = u_VCT[:, np.newaxis]
|
|
175
|
+
self['u_VCT'] = var
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def add_GEO_LST(self):
|
|
179
|
+
lons = self['SC_GEO_LON'].flatten()
|
|
180
|
+
uts = self['SC_DATETIME'].flatten()
|
|
181
|
+
lsts = [ut + datetime.timedelta(seconds=int(lon/15.*3600)) for ut, lon in zip(uts, lons)]
|
|
182
|
+
lsts = [lst.hour + lst.minute/60. + lst.second/3600. for lst in lsts]
|
|
183
|
+
var = self.add_variable(var_name='SC_GEO_LST')
|
|
184
|
+
var.value = np.array(lsts)[:, np.newaxis]
|
|
185
|
+
var.label = 'LST'
|
|
186
|
+
var.unit = 'h'
|
|
187
|
+
var.depends = self['SC_GEO_LON'].depends
|
|
188
|
+
return var
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def convert_to_APEX(self):
|
|
192
|
+
import geospacelab.cs as gsl_cs
|
|
193
|
+
|
|
194
|
+
coords_in = {
|
|
195
|
+
'lat': self['SC_GEO_LAT'].value.flatten(),
|
|
196
|
+
'lon': self['SC_GEO_LON'].value.flatten(),
|
|
197
|
+
'height': self['SC_GEO_ALT'].value.flatten()
|
|
198
|
+
}
|
|
199
|
+
dts = self['SC_DATETIME'].value.flatten()
|
|
200
|
+
cs_sph = gsl_cs.GEOCSpherical(coords=coords_in, ut=dts)
|
|
201
|
+
cs_apex = cs_sph.to_APEX(append_mlt=True)
|
|
202
|
+
self.add_variable('SC_APEX_LAT')
|
|
203
|
+
self.add_variable('SC_APEX_LON')
|
|
204
|
+
self.add_variable('SC_APEX_MLT')
|
|
205
|
+
self['SC_APEX_LAT'].value = cs_apex['lat'].reshape(self['SC_DATETIME'].value.shape)
|
|
206
|
+
self['SC_APEX_LON'].value = cs_apex['lon'].reshape(self['SC_DATETIME'].value.shape)
|
|
207
|
+
self['SC_APEX_MLT'].value = cs_apex['mlt'].reshape(self['SC_DATETIME'].value.shape)
|
|
208
|
+
|
|
209
|
+
def convert_to_AACGM(self):
|
|
210
|
+
import geospacelab.cs as gsl_cs
|
|
211
|
+
|
|
212
|
+
coords_in = {
|
|
213
|
+
'lat': self['SC_GEO_LAT'].value.flatten(),
|
|
214
|
+
'lon': self['SC_GEO_LON'].value.flatten(),
|
|
215
|
+
'height': self['SC_GEO_ALT'].value.flatten()
|
|
216
|
+
}
|
|
217
|
+
dts = self['SC_DATETIME'].value.flatten()
|
|
218
|
+
cs_sph = gsl_cs.GEOCSpherical(coords=coords_in, ut=dts)
|
|
219
|
+
cs_aacgm = cs_sph.to_AACGM(append_mlt=True)
|
|
220
|
+
self.add_variable('SC_AACGM_LAT')
|
|
221
|
+
self.add_variable('SC_AACGM_LON')
|
|
222
|
+
self.add_variable('SC_AACGM_MLT')
|
|
223
|
+
self['SC_AACGM_LAT'].value = cs_aacgm['lat'].reshape(self['SC_DATETIME'].value.shape)
|
|
224
|
+
self['SC_AACGM_LON'].value = cs_aacgm['lon'].reshape(self['SC_DATETIME'].value.shape)
|
|
225
|
+
self['SC_AACGM_MLT'].value = cs_aacgm['mlt'].reshape(self['SC_DATETIME'].value.shape)
|
|
226
|
+
|
|
227
|
+
def search_data_files(self, **kwargs):
|
|
228
|
+
|
|
229
|
+
dt_fr = self.dt_fr
|
|
230
|
+
dt_to = self.dt_to
|
|
231
|
+
|
|
232
|
+
diff_months = dttool.get_diff_months(dt_fr, dt_to)
|
|
233
|
+
|
|
234
|
+
dt0 = dttool.get_first_day_of_month(self.dt_fr)
|
|
235
|
+
|
|
236
|
+
for i in range(diff_months + 1):
|
|
237
|
+
this_day = dttool.get_next_n_months(dt0, i)
|
|
238
|
+
|
|
239
|
+
initial_file_dir = kwargs.pop(
|
|
240
|
+
'initial_file_dir', self.data_root_dir
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
file_patterns = [
|
|
244
|
+
'GO',
|
|
245
|
+
self.product.upper().replace('-', '_'),
|
|
246
|
+
this_day.strftime('%Y_%m'),
|
|
247
|
+
self.product_version + '.txt'
|
|
248
|
+
]
|
|
249
|
+
# remove empty str
|
|
250
|
+
file_patterns = [pattern for pattern in file_patterns if str(pattern)]
|
|
251
|
+
search_pattern = '*' + '*'.join(file_patterns) + '*'
|
|
252
|
+
|
|
253
|
+
done = super().search_data_files(
|
|
254
|
+
initial_file_dir=initial_file_dir,
|
|
255
|
+
search_pattern=search_pattern,
|
|
256
|
+
allow_multiple_files=False,
|
|
257
|
+
include_extension=False,
|
|
258
|
+
)
|
|
259
|
+
# Validate file paths
|
|
260
|
+
|
|
261
|
+
if (not done and self.allow_download) or self.force_download:
|
|
262
|
+
done = self.download_data()
|
|
263
|
+
if done:
|
|
264
|
+
initial_file_dir = self.data_root_dir
|
|
265
|
+
done = super().search_data_files(
|
|
266
|
+
initial_file_dir=initial_file_dir,
|
|
267
|
+
search_pattern=search_pattern,
|
|
268
|
+
allow_multiple_files=False
|
|
269
|
+
)
|
|
270
|
+
self.data_file_paths = np.unique(self.data_file_paths)
|
|
271
|
+
return done
|
|
272
|
+
|
|
273
|
+
def download_data(self, dt_fr=None, dt_to=None):
|
|
274
|
+
if dt_fr is None:
|
|
275
|
+
dt_fr = self.dt_fr
|
|
276
|
+
if dt_to is None:
|
|
277
|
+
dt_to = self.dt_to
|
|
278
|
+
download_obj = self.downloader(
|
|
279
|
+
dt_fr, dt_to,
|
|
280
|
+
sat_id=self.sat_id,
|
|
281
|
+
product=self.product,
|
|
282
|
+
version=self.product_version,
|
|
283
|
+
force_download=self.force_download,
|
|
284
|
+
dry_run=self.download_dry_run,
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
return any(download_obj.done)
|
|
288
|
+
|
|
289
|
+
@property
|
|
290
|
+
def database(self):
|
|
291
|
+
return self._database
|
|
292
|
+
|
|
293
|
+
@database.setter
|
|
294
|
+
def database(self, value):
|
|
295
|
+
if isinstance(value, str):
|
|
296
|
+
self._database = DatabaseModel(value)
|
|
297
|
+
elif issubclass(value.__class__, DatabaseModel):
|
|
298
|
+
self._database = value
|
|
299
|
+
else:
|
|
300
|
+
raise TypeError
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def product(self):
|
|
304
|
+
return self._product
|
|
305
|
+
|
|
306
|
+
@product.setter
|
|
307
|
+
def product(self, value):
|
|
308
|
+
if isinstance(value, str):
|
|
309
|
+
self._product = ProductModel(value)
|
|
310
|
+
elif issubclass(value.__class__, ProductModel):
|
|
311
|
+
self._product = value
|
|
312
|
+
else:
|
|
313
|
+
raise TypeError
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def facility(self):
|
|
317
|
+
return self._facility
|
|
318
|
+
|
|
319
|
+
@facility.setter
|
|
320
|
+
def facility(self, value):
|
|
321
|
+
if isinstance(value, str):
|
|
322
|
+
self._facility = FacilityModel(value)
|
|
323
|
+
elif issubclass(value.__class__, FacilityModel):
|
|
324
|
+
self._facility = value
|
|
325
|
+
else:
|
|
326
|
+
raise TypeError
|
|
327
|
+
|
|
328
|
+
@property
|
|
329
|
+
def instrument(self):
|
|
330
|
+
return self._instrument
|
|
331
|
+
|
|
332
|
+
@instrument.setter
|
|
333
|
+
def instrument(self, value):
|
|
334
|
+
if isinstance(value, str):
|
|
335
|
+
self._instrument = InstrumentModel(value)
|
|
336
|
+
elif issubclass(value.__class__, InstrumentModel):
|
|
337
|
+
self._instrument = value
|
|
338
|
+
else:
|
|
339
|
+
raise TypeError
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Licensed under the BSD 3-Clause License
|
|
2
|
+
# Copyright (C) 2021 GeospaceLab (geospacelab)
|
|
3
|
+
# Author: Lei Cai, Space Physics and Astronomy, University of Oulu
|
|
4
|
+
|
|
5
|
+
__author__ = "Lei Cai"
|
|
6
|
+
__copyright__ = "Copyright 2021, GeospaceLab"
|
|
7
|
+
__license__ = "BSD-3-Clause License"
|
|
8
|
+
__email__ = "lei.cai@oulu.fi"
|
|
9
|
+
__docformat__ = "reStructureText"
|
|
10
|
+
|
|
11
|
+
import datetime
|
|
12
|
+
from geospacelab.config import prf
|
|
13
|
+
|
|
14
|
+
from geospacelab.datahub.sources.tud.downloader import TUDownloader as DownloaderBase
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Downloader(DownloaderBase):
|
|
18
|
+
|
|
19
|
+
def __init__(self,
|
|
20
|
+
dt_fr, dt_to,
|
|
21
|
+
mission='GOCE',
|
|
22
|
+
sat_id='',
|
|
23
|
+
version='v02',
|
|
24
|
+
product='WND-ACC',
|
|
25
|
+
direct_download=True,
|
|
26
|
+
force_download=False,
|
|
27
|
+
dry_run=False,
|
|
28
|
+
):
|
|
29
|
+
self.mission = mission
|
|
30
|
+
self.version = version
|
|
31
|
+
|
|
32
|
+
super().__init__(
|
|
33
|
+
dt_fr, dt_to,
|
|
34
|
+
mission=mission,
|
|
35
|
+
sat_id=sat_id,
|
|
36
|
+
version=version,
|
|
37
|
+
product=product,
|
|
38
|
+
direct_download=direct_download,
|
|
39
|
+
force_download=force_download,
|
|
40
|
+
dry_run=dry_run
|
|
41
|
+
)
|
|
42
|
+
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Licensed under the BSD 3-Clause License
|
|
2
|
+
# Copyright (C) 2021 GeospaceLab (geospacelab)
|
|
3
|
+
# Author: Lei Cai, Space Physics and Astronomy, University of Oulu
|
|
4
|
+
|
|
5
|
+
__author__ = "Lei Cai"
|
|
6
|
+
__copyright__ = "Copyright 2021, GeospaceLab"
|
|
7
|
+
__license__ = "BSD-3-Clause License"
|
|
8
|
+
__email__ = "lei.cai@oulu.fi"
|
|
9
|
+
__docformat__ = "reStructureText"
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
import numpy as np
|
|
13
|
+
import datetime
|
|
14
|
+
import geospacelab.toolbox.utilities.pydatetime as dttool
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Loader(object):
|
|
18
|
+
|
|
19
|
+
def __init__(self, file_path, file_type='txt', version='v01', direct_load=True):
|
|
20
|
+
self.file_path = file_path
|
|
21
|
+
self.file_type = file_type
|
|
22
|
+
self.version = version
|
|
23
|
+
self.variables = {}
|
|
24
|
+
self.done = False
|
|
25
|
+
if direct_load:
|
|
26
|
+
self.load()
|
|
27
|
+
|
|
28
|
+
def load(self):
|
|
29
|
+
|
|
30
|
+
if self.version == 'v01':
|
|
31
|
+
raise ValueError
|
|
32
|
+
elif 'v02' in self.version:
|
|
33
|
+
self.load_v02()
|
|
34
|
+
else:
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
def load_v02(self):
|
|
38
|
+
with open(self.file_path, 'r') as f:
|
|
39
|
+
text = f.read()
|
|
40
|
+
results = re.findall(
|
|
41
|
+
r"^(\d{4}-\d{2}-\d{2}\s*\d{2}\:\d{2}\:\d{2}\.\d{3})\s*(\w{3})\s*"
|
|
42
|
+
+ r"([\-\d.]+)\s*([\-\d.]+)\s*([\-\d.]+)\s*([\-\d.]+)\s*([\-\d.]+)\s*"
|
|
43
|
+
+ r"([\-\d.]+)\s*([\-\d.]+)\s*([\-\d.]+)\s*([\-\d.]+)\s*([\-\d.]+)",
|
|
44
|
+
text,
|
|
45
|
+
re.M)
|
|
46
|
+
results = list(zip(*results))
|
|
47
|
+
dts = [datetime.datetime.strptime(dtstr + '000', "%Y-%m-%d %H:%M:%S.%f") for dtstr in results[0]]
|
|
48
|
+
if results[1][0] == 'GPS':
|
|
49
|
+
t_gps = [(dt - dttool._GPS_DATETIME_0).total_seconds() for dt in dts]
|
|
50
|
+
dts = dttool.convert_gps_time_to_datetime(t_gps, weeks=None)
|
|
51
|
+
num_rec = len(dts)
|
|
52
|
+
self.variables['SC_DATETIME'] = np.array(dts).reshape(num_rec, 1)
|
|
53
|
+
self.variables['SC_GEO_ALT'] = np.array(results[2]).astype(np.float32).reshape(num_rec, 1) * 1e-3 # in km
|
|
54
|
+
self.variables['SC_GEO_LON'] = np.array(results[3]).astype(np.float32).reshape(num_rec, 1)
|
|
55
|
+
self.variables['SC_GEO_LAT'] = np.array(results[4]).astype(np.float32).reshape(num_rec, 1)
|
|
56
|
+
self.variables['SC_GEO_LST'] = np.array(results[5]).astype(np.float32).reshape(num_rec, 1)
|
|
57
|
+
self.variables['SC_ARG_LAT'] = np.array(results[6]).astype(np.float32).reshape(num_rec, 1)
|
|
58
|
+
self.variables['u_CROSS'] = np.array(results[7]).astype(np.float32).reshape(num_rec, 1)
|
|
59
|
+
self.variables['UNIT_VECTOR_N'] = np.array(results[8]).astype(np.float32).reshape(num_rec, 1)
|
|
60
|
+
self.variables['UNIT_VECTOR_E'] = np.array(results[9]).astype(np.float32).reshape(num_rec, 1)
|
|
61
|
+
self.variables['UNIT_VECTOR_D'] = np.array(results[10]).astype(np.float32).reshape(num_rec, 1)
|
|
62
|
+
self.variables['FLAG'] = np.array(results[6]).astype(np.float32).reshape(num_rec, 1)
|
|
63
|
+
self.variables['u_CROSS_N'] = self.variables['u_CROSS'] * self.variables['UNIT_VECTOR_N']
|
|
64
|
+
self.variables['u_CROSS_E'] = self.variables['u_CROSS'] * self.variables['UNIT_VECTOR_E']
|
|
65
|
+
self.variables['u_CROSS_D'] = self.variables['u_CROSS'] * self.variables['UNIT_VECTOR_D']
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Licensed under the BSD 3-Clause License
|
|
2
|
+
# Copyright (C) 2021 GeospaceLab (geospacelab)
|
|
3
|
+
# Author: Lei Cai, Space Physics and Astronomy, University of Oulu
|
|
4
|
+
|
|
5
|
+
__author__ = "Lei Cai"
|
|
6
|
+
__copyright__ = "Copyright 2021, GeospaceLab"
|
|
7
|
+
__license__ = "BSD-3-Clause License"
|
|
8
|
+
__email__ = "lei.cai@oulu.fi"
|
|
9
|
+
__docformat__ = "reStructureText"
|
|
10
|
+
|
|
11
|
+
from geospacelab.datahub import VariableModel as Var
|
|
12
|
+
import geospacelab.visualization.mpl.colormaps as cm
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
database = 'ESA/EarthOnline'
|
|
17
|
+
|
|
18
|
+
timestamps = {
|
|
19
|
+
'SC_DATETIME': 'SC_DATETIME',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
default_colormap = "gist_ncar"
|
|
24
|
+
|
|
25
|
+
default_plot_config = {
|
|
26
|
+
'line': {
|
|
27
|
+
'linestyle': '-',
|
|
28
|
+
'linewidth': 1.5,
|
|
29
|
+
'marker': '',
|
|
30
|
+
'markersize': 3,
|
|
31
|
+
},
|
|
32
|
+
'pcolormesh': {
|
|
33
|
+
'cmap': default_colormap,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
configured_variables = {}
|
|
38
|
+
visual = 'on'
|
|
39
|
+
|
|
40
|
+
depend_0 = {'UT': 'SC_DATETIME',
|
|
41
|
+
'GEO_LAT': 'SC_GEO_LAT', 'GEO_LON': 'SC_GEO_LON',
|
|
42
|
+
'AACGM_LAT': 'SC_AACGM_LAT', 'AACGM_LON': 'SC_AACGM_LON', 'AACGM_MLT': 'SC_AACGM_MLT'}
|
|
43
|
+
# depend_c = {'SPECTRA': 'EMISSION_SPECTRA'}
|
|
44
|
+
|
|
45
|
+
####################################################################################################################
|
|
46
|
+
var_name = 'u_CROSS'
|
|
47
|
+
var = Var(name=var_name, ndim=1, variable_type='scalar', visual=visual)
|
|
48
|
+
# set variable attrs
|
|
49
|
+
var.fullname = 'Cross neutral wind'
|
|
50
|
+
var.label = r'$u_{cross}$'
|
|
51
|
+
var.unit = 'm/s'
|
|
52
|
+
var.unit_label = r'm/s'
|
|
53
|
+
var.group = r'$u$'
|
|
54
|
+
# var.error = var_name + '_err'
|
|
55
|
+
var.depends = {0: depend_0}
|
|
56
|
+
# set plot attrs
|
|
57
|
+
plot_config = var.visual.plot_config
|
|
58
|
+
plot_config.config(**default_plot_config)
|
|
59
|
+
plot_config.style = '1noE'
|
|
60
|
+
# set axis attrs
|
|
61
|
+
axis = var.visual.axis
|
|
62
|
+
axis[1].data = "@v.value"
|
|
63
|
+
# axis[1].lim = [np.nan, np.nan]
|
|
64
|
+
axis[2].label = '@v.label'
|
|
65
|
+
axis[1].label = '@v.label'
|
|
66
|
+
axis[1].unit = '@v.unit_label'
|
|
67
|
+
|
|
68
|
+
configured_variables[var_name] = var
|
|
69
|
+
|
|
70
|
+
####################################################################################################################
|
|
71
|
+
var_name = 'u_CROSS_E'
|
|
72
|
+
var = Var(name=var_name, ndim=1, variable_type='scalar', visual=visual)
|
|
73
|
+
# set variable attrs
|
|
74
|
+
var.fullname = 'Cross neutral wind (Eastward)'
|
|
75
|
+
var.label = r'$u_{E}$'
|
|
76
|
+
var.unit = 'm/s'
|
|
77
|
+
var.unit_label = r'm/s'
|
|
78
|
+
var.group = r'$u$'
|
|
79
|
+
# var.error = var_name + '_err'
|
|
80
|
+
var.depends = {0: depend_0}
|
|
81
|
+
# set plot attrs
|
|
82
|
+
plot_config = var.visual.plot_config
|
|
83
|
+
plot_config.config(**default_plot_config)
|
|
84
|
+
plot_config.style = '1noE'
|
|
85
|
+
# set axis attrs
|
|
86
|
+
axis = var.visual.axis
|
|
87
|
+
axis[1].data = "@v.value"
|
|
88
|
+
# axis[1].lim = [np.nan, np.nan]
|
|
89
|
+
axis[2].label = '@v.label'
|
|
90
|
+
axis[1].unit = '@v.unit_label'
|
|
91
|
+
|
|
92
|
+
configured_variables[var_name] = var
|
|
93
|
+
|
|
94
|
+
####################################################################################################################
|
|
95
|
+
var_name = 'u_CROSS_N'
|
|
96
|
+
var = Var(name=var_name, ndim=1, variable_type='scalar', visual=visual)
|
|
97
|
+
# set variable attrs
|
|
98
|
+
var.fullname = 'Cross neutral wind (Northward)'
|
|
99
|
+
var.label = r'$u_{N}$'
|
|
100
|
+
var.unit = 'm/s'
|
|
101
|
+
var.unit_label = r'm/s'
|
|
102
|
+
var.group = r'$u$'
|
|
103
|
+
# var.error = var_name + '_err'
|
|
104
|
+
var.depends = {0: depend_0}
|
|
105
|
+
# set plot attrs
|
|
106
|
+
plot_config = var.visual.plot_config
|
|
107
|
+
plot_config.config(**default_plot_config)
|
|
108
|
+
plot_config.style = '1noE'
|
|
109
|
+
# set axis attrs
|
|
110
|
+
axis = var.visual.axis
|
|
111
|
+
axis[1].data = "@v.value"
|
|
112
|
+
# axis[1].lim = [np.nan, np.nan]
|
|
113
|
+
axis[2].label = '@v.label'
|
|
114
|
+
axis[1].unit = '@v.unit_label'
|
|
115
|
+
|
|
116
|
+
configured_variables[var_name] = var
|
|
117
|
+
|
|
118
|
+
####################################################################################################################
|
|
119
|
+
var_name = 'u_CROSS_D'
|
|
120
|
+
var = Var(name=var_name, ndim=1, variable_type='scalar', visual=visual)
|
|
121
|
+
# set variable attrs
|
|
122
|
+
var.fullname = 'Cross neutral wind (Downward)'
|
|
123
|
+
var.label = r'$u_{Down}$'
|
|
124
|
+
var.unit = 'm/s'
|
|
125
|
+
var.unit_label = r'm/s'
|
|
126
|
+
var.group = r'$u$'
|
|
127
|
+
# var.error = var_name + '_err'
|
|
128
|
+
var.depends = {0: depend_0}
|
|
129
|
+
# set plot attrs
|
|
130
|
+
plot_config = var.visual.plot_config
|
|
131
|
+
plot_config.config(**default_plot_config)
|
|
132
|
+
plot_config.style = '1noE'
|
|
133
|
+
# set axis attrs
|
|
134
|
+
axis = var.visual.axis
|
|
135
|
+
axis[1].data = "@v.value"
|
|
136
|
+
# axis[1].lim = [np.nan, np.nan]
|
|
137
|
+
axis[2].label = '@v.label'
|
|
138
|
+
axis[1].unit = '@v.unit_label'
|
|
139
|
+
|
|
140
|
+
configured_variables[var_name] = var
|
|
141
|
+
|
|
142
|
+
####################################################################################################################
|
|
143
|
+
var_name = 'SC_GEO_LAT'
|
|
144
|
+
var = Var(name=var_name, ndim=1, variable_type='scalar', visual=visual)
|
|
145
|
+
# set variable attrs
|
|
146
|
+
var.fullname = 'S/C geographic latitude'
|
|
147
|
+
var.label = r'GLAT'
|
|
148
|
+
var.unit = 'degree'
|
|
149
|
+
var.unit_label = r'$^\circ$'
|
|
150
|
+
var.group = r'GEO'
|
|
151
|
+
# var.error = var_name + '_err'
|
|
152
|
+
var.depends = {0: depend_0}
|
|
153
|
+
# set plot attrs
|
|
154
|
+
plot_config = var.visual.plot_config
|
|
155
|
+
plot_config.config(**default_plot_config)
|
|
156
|
+
plot_config.style = '1noE'
|
|
157
|
+
# set axis attrs
|
|
158
|
+
axis = var.visual.axis
|
|
159
|
+
axis[1].data = "@v.value"
|
|
160
|
+
# axis[1].lim = [-2000, 2000]
|
|
161
|
+
axis[1].label = '@v.label'
|
|
162
|
+
axis[1].unit = '@v.unit_label'
|
|
163
|
+
|
|
164
|
+
configured_variables[var_name] = var
|
|
165
|
+
|
|
166
|
+
####################################################################################################################
|
|
167
|
+
var_name = 'SC_GEO_LON'
|
|
168
|
+
var = Var(name=var_name, ndim=1, variable_type='scalar', visual=visual)
|
|
169
|
+
# set variable attrs
|
|
170
|
+
var.fullname = 'S/C geographic latitude'
|
|
171
|
+
var.label = r'GLON'
|
|
172
|
+
var.unit = 'degree'
|
|
173
|
+
var.unit_label = r'$^\circ$'
|
|
174
|
+
var.group = r'GEO'
|
|
175
|
+
# var.error = var_name + '_err'
|
|
176
|
+
var.depends = {0: depend_0}
|
|
177
|
+
# set plot attrs
|
|
178
|
+
plot_config = var.visual.plot_config
|
|
179
|
+
plot_config.config(**default_plot_config)
|
|
180
|
+
plot_config.style = '1noE'
|
|
181
|
+
# set axis attrs
|
|
182
|
+
axis = var.visual.axis
|
|
183
|
+
axis[1].data = "@v.value"
|
|
184
|
+
# axis[1].lim = [-2000, 2000]
|
|
185
|
+
axis[1].label = '@v.label'
|
|
186
|
+
axis[1].unit = '@v.unit_label'
|
|
187
|
+
|
|
188
|
+
configured_variables[var_name] = var
|
|
@@ -78,6 +78,8 @@ class Dataset(datahub.DatasetSourced):
|
|
|
78
78
|
self.local_latest_version = ''
|
|
79
79
|
self.allow_download = kwargs.pop('allow_download', False)
|
|
80
80
|
self.force_download = kwargs.pop('force_download', False)
|
|
81
|
+
self.download_dry_run = kwargs.pop('download_dry_run', False)
|
|
82
|
+
|
|
81
83
|
self.add_AACGM = kwargs.pop('add_AACGM', False)
|
|
82
84
|
self.add_APEX = kwargs.pop('add_APEX', False)
|
|
83
85
|
self._data_root_dir = self.data_root_dir # Record the initial root dir
|
|
@@ -289,7 +291,7 @@ class Dataset(datahub.DatasetSourced):
|
|
|
289
291
|
search_pattern=search_pattern,
|
|
290
292
|
allow_multiple_files=False
|
|
291
293
|
)
|
|
292
|
-
|
|
294
|
+
self.data_file_paths = np.unique(self.data_file_paths)
|
|
293
295
|
return done
|
|
294
296
|
|
|
295
297
|
def download_data(self, dt_fr=None, dt_to=None):
|
|
@@ -302,10 +304,11 @@ class Dataset(datahub.DatasetSourced):
|
|
|
302
304
|
sat_id=self.sat_id,
|
|
303
305
|
product=self.product,
|
|
304
306
|
version=self.product_version,
|
|
305
|
-
|
|
307
|
+
force_download=self.force_download,
|
|
308
|
+
dry_run=self.download_dry_run
|
|
306
309
|
)
|
|
307
310
|
|
|
308
|
-
return download_obj.done
|
|
311
|
+
return any(download_obj.done)
|
|
309
312
|
|
|
310
313
|
@property
|
|
311
314
|
def database(self):
|