Skip to content

Commit 9cb2bd2

Browse files
Merge pull request #1350 from spedas/t_1346
Add support for METOP data sets archived at NCEI
2 parents 1e1d266 + ed677f1 commit 9cb2bd2

4 files changed

Lines changed: 72 additions & 17 deletions

File tree

pyspedas/projects/poes/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"local_data_dir": "poes_data/",
55
"remote_data_dir": "https://spdf.gsfc.nasa.gov/pub/data/noaa/",
66
"ncei_remote_data_dir": "https://www.ncei.noaa.gov/data/poes-metop-space-environment-monitor/access/l2/v01r00/cdf/",
7+
"ncei_l1b_remote_data_dir": "https://www.ncei.noaa.gov/data/poes-metop-space-environment-monitor/access/l1b/v01r00/"
78
}
89

910
# override local data directory with environment variables

pyspedas/projects/poes/load.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from pyspedas.utilities.download import download
33
from pyspedas.tplot_tools import time_clip as tclip
44
from pyspedas.tplot_tools import cdf_to_tplot
5+
from pyspedas.tplot_tools import netcdf_to_tplot
6+
import re
57

68
from .config import CONFIG
79

@@ -15,6 +17,7 @@ def load(
1517
suffix="",
1618
get_support_data=False,
1719
ncei_server=False,
20+
ncei_l1b_server=False,
1821
varformat=None,
1922
varnames=[],
2023
downloadonly=False,
@@ -91,6 +94,14 @@ def load(
9194
remote_path = CONFIG["ncei_remote_data_dir"]
9295
num = prb[-2:]
9396
pathformat = "%Y/" + prb + "/poes_n" + num + "_%Y%m%d.cdf"
97+
elif ncei_l1b_server:
98+
remote_path = CONFIG["ncei_l1b_remote_data_dir"]
99+
num = re.search("[0-9]+",prb)[0]
100+
prb_name=prb.split(num)[0]
101+
prb_l = prb[0:1]
102+
103+
prb_name_num_formatted=prb_name + num.zfill(2)
104+
pathformat = "%Y/" + prb_name_num_formatted + "/poes_" + prb_l + num.zfill(2) + "_%Y%m%d_proc.nc"
94105
else:
95106
remote_path = CONFIG["remote_data_dir"]
96107
if instrument == "sem":
@@ -120,15 +131,22 @@ def load(
120131
if downloadonly:
121132
return out_files
122133

123-
tvars = cdf_to_tplot(
124-
out_files,
125-
prefix=prefix,
126-
suffix=suffix,
127-
get_support_data=get_support_data,
128-
varformat=varformat,
129-
varnames=varnames,
130-
notplot=notplot,
131-
)
134+
if ncei_l1b_server:
135+
tvars = netcdf_to_tplot(
136+
out_files,
137+
prefix=prefix,
138+
suffix=suffix,
139+
)
140+
else:
141+
tvars = cdf_to_tplot(
142+
out_files,
143+
prefix=prefix,
144+
suffix=suffix,
145+
get_support_data=get_support_data,
146+
varformat=varformat,
147+
varnames=varnames,
148+
notplot=notplot,
149+
)
132150

133151
if notplot:
134152
return tvars

pyspedas/projects/poes/tests/test_poes.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ def test_ncei_server(self):
4040
vars = load(trange=['1999-01-03', '1999-01-04'], probe=['noaa15'], ncei_server=True, time_clip=True)
4141
self.assertTrue('geogLL' in vars)
4242

43+
def test_ncei_l1b_server(self):
44+
vars = load(trange=['2026-04-05', '2026-04-06'], probe=['metop03'], ncei_l1b_server=True, time_clip=True)
45+
self.assertTrue('ted_ele_tel30_hi_eflux' in vars)
46+
47+
def test_ncei_l1b_server_metop_varient(self):
48+
vars = load(trange=['2026-04-05', '2026-04-06'], probe=['metop3'], ncei_l1b_server=True, time_clip=True)
49+
self.assertTrue('ted_ele_tel30_hi_eflux' in vars)
4350

4451
if __name__ == '__main__':
4552
unittest.main()

pyspedas/tplot_tools/importers/netcdf_to_tplot.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@ def change_time_to_unix_time(time_var):
2323
# ICON uses nonstandard units strings
2424
if units == "ms":
2525
units = "milliseconds since 1970-01-01 00:00:00"
26-
dates = num2date(time_var[:], units=units)
26+
# Check if the long_name attribute has stored the epoch description (POES/METOP):
27+
elif hasattr(time_var, "long_name"):
28+
if time_var.long_name == "milliseconds since 1970":
29+
units = "milliseconds since 1970-01-01 00:00:00"
30+
31+
time_data=time_var[:]
32+
if hasattr(time_data,"data"):
33+
time_data=time_var[:].data
34+
dates = num2date(time_data, units=units)
2735
unix_times = list()
2836
for date in dates:
2937
unix_time = calendar.timegm(date.timetuple()) + date.microsecond/1e6
@@ -130,17 +138,27 @@ def netcdf_to_tplot(
130138
# If multiple matching keys are found, the one that appears latest in the above list
131139
# will take precedence
132140
var_fill_value = atts_dict[key]
141+
142+
if hasattr(reg_var[:],"get_fill_value"):
143+
var_fill_value=reg_var[:].get_fill_value()
133144

134145
# If var_fill_value is None, or already NaN, there's nothing to do here.
135146
# Integer arrays can't be NaN-filled, so if var_fill_value is any kind of integer, skip those too.
136147
# Some missions have strings defined as fill values. (ICON)
137148
if var_fill_value is not None and not isinstance(var_fill_value, np.integer) and not isinstance(var_fill_value, str) and not np.isnan(var_fill_value):
138149
# We want to force missing values to be nan so that plots don't look strange
139-
var_mask = np.ma.masked_where(
140-
reg_var == np.float32(var_fill_value), reg_var
141-
)
142-
var_filled = np.ma.filled(var_mask, np.nan)
143-
masked_vars[var] = var_filled
150+
if hasattr(reg_var[:],"data"):
151+
var_mask = np.ma.masked_where(
152+
reg_var[:].data == np.float32(var_fill_value), reg_var[:].data
153+
)
154+
var_filled = np.ma.filled(var_mask, np.nan)
155+
masked_vars[var] = var_filled
156+
else:
157+
var_mask = np.ma.masked_where(
158+
reg_var == np.float32(var_fill_value), reg_var
159+
)
160+
var_filled = np.ma.filled(var_mask, np.nan)
161+
masked_vars[var] = var_filled
144162
else:
145163
var_filled = reg_var
146164
masked_vars[var] = var_filled
@@ -168,8 +186,19 @@ def netcdf_to_tplot(
168186
# If this_time does not exist, we can't save this as tplot variable.
169187
continue
170188
elif this_time == var:
171-
# If this_time has the same name as the current variable, do not save it.
172-
continue
189+
# The time the variable depends on may not have been set.
190+
# Check if time is a variable:
191+
if 'time' in vars_and_atts.keys():
192+
# If it is, check if the sizes match:
193+
if vfile[var].size == vfile['time'].size:
194+
# If they do, we can infer that the time variable is the one we want here.
195+
this_time = "time"
196+
else:
197+
# If not, it probably depends on something else / nothing.
198+
continue
199+
else:
200+
# If this_time has the same name as the current variable, do not save it.
201+
continue
173202

174203
# Find the time values (as unix times).
175204
if this_time in times_dict:

0 commit comments

Comments
 (0)