Coverage for wrainfo/reader.py: 94%
119 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-18 12:40 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-18 12:40 +0000
1"""Reader module."""
3# WRaINfo, Is a software to process FURUNO weather radar data.
4#
5# Copyright (c) 2022, FernLab (GFZ Potsdam, fernlab@gfz-potsdam.de)
6#
7# This software was developed within the context of the RaINfo ("Potential use of
8# high resolution weather data in agriculture") project of FernLab funded by
9# the Impulse and Networking Fund of the Helmholtz Association.
10#
11# Licensed under the Apache License, Version 2.0 (the "License");
12# you may not use this file except in compliance with the License.
13#
14# You may obtain a copy of the License at
15# http://www.apache.org/licenses/LICENSE-2.0
16#
17# Unless required by applicable law or agreed to in writing, software
18# distributed under the License is distributed on an "AS IS" BASIS,
19# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20# See the License for the specific language governing permissions and
21# limitations under the License.
23# imports
24# -------
26import datetime as dt
27import os
28import glob
29import re
30import xarray as xr
31import numpy as np
32import pickle
33import json
34from pathlib import Path
37# read configuration file
38# -----------------------
40def read_config_file(path=".../example_settings_path_dependencies_wr_furuno.json", selection=None):
41 """Read wr_furuno config file in json format.
43 Parameter
44 ---------
45 path : str
46 Path to config file.
47 selection : str
48 select setting parameter
50 Return
51 ------
52 : dict
53 configured directories in the configuration file.
54 """
55 path = path.replace("~", str(Path.home()))
57 if not Path(path).is_file():
58 raise Exception("wrainfo.reader.read_config_file(): Config file'", path, "' not found.")
60 file = open(path)
61 conf = json.load(file)
62 file.close()
64 if selection is not None:
65 if selection in conf.keys():
66 return conf[selection]
67 else:
68 raise Exception("wrainfo.reader.read_config_file(): Setting parameter'",
69 selection,
70 "' not in settings file '",
71 path,
72 "'.")
73 else:
74 return conf
77# Functions to read the Furuno data
78# ----------------------------------
80def get_furuno_path(path, start_time=dt.datetime.today()):
81 """Create path of Furuno radar data files.
83 Parameters
84 ----------
85 path : str
86 Path to configuration file
87 start_time : datetime.datetime
88 datetime object to select correct folder
90 Returns
91 -------
92 radar_path : str
93 Path to radar data
94 """
95 raw_path = read_config_file(path=path, selection="raw_data_directory")
96 subfolder_struct_raw_path = read_config_file(path=path, selection="subfolder_structure_raw_data")
98 radar_path = os.path.join(raw_path, subfolder_struct_raw_path)
99 return radar_path.format(start_time.year, start_time.month, start_time.day)
102def get_file_date_regex(filename):
103 """Get regex from filename."""
104 # regex for ""%Y-%m-%d--%H:%M:%S"
105 reg0 = r"\d{4}.\d{2}.\d{2}..\d{2}.\d{2}.\d{2}"
106 # regex for "%Y%m%d%H%M%S"
107 reg1 = r"\d{14}"
108 # regex for 20220216_085000
109 reg2 = r"\d{4}\d{2}\d{2}.\d{2}\d{2}\d{2}"
110 for reg in [reg0, reg1, reg2]:
111 match = re.search(reg, os.path.basename(filename))
112 if match is not None:
113 return reg
114 return None
117def get_datetime_from_filename(filename, regex):
118 """Get datetime from filename."""
119 fmt = "%Y%m%d%H%M%S"
120 match = re.search(regex, os.path.basename(filename))
121 match = "".join(re.findall(r"[0-9]+", match.group()))
122 return dt.datetime.strptime(match, fmt)
125def load_error_flist(path):
126 """Load error file list.
128 Parameter
129 ---------
130 path : str
131 Path to configuration file
133 Returns
134 ------
135 : list
136 list of error files.
137 """
138 path_error_flist = read_config_file(path=path, selection="error_flist_directory")
140 with open(path_error_flist, 'rb') as fp:
141 error_files = pickle.load(fp)
143 return error_files
146def create_filelist(starttime, endtime, path, pattern="_000.scnx.gz"):
147 """Create filelist from path_glob and filename dates.
149 Parameters
150 ----------
151 starttime : dt.datetime
152 start time
153 endtime : dt.datetime
154 end time
155 path : str
156 Path to configuration file
157 pattern : str
158 extension of the scnx/netcdf file
159 (scnx file: elevation angle 0.5° = "_000.scnx.gz")
160 (netcdf file: = ".nc" , elevation angle is included in the filename)
162 Returns
163 -------
164 : list
165 list of files
166 """
167 flist = []
168 flist_scnx = []
169 flist_h5 = []
170 flist_nc = []
171 datetime_list = []
172 date = starttime
174 error_flist = load_error_flist(path=path)
176 while date <= endtime:
178 raw_path = get_furuno_path(path=path, start_time=date)
180 file_names = sorted(glob.glob(os.path.join(raw_path, "*")))
182 # fixed empty list of file_names
183 if len(file_names) > 0:
184 regex = get_file_date_regex(file_names[0])
186 for fname in file_names:
187 time = get_datetime_from_filename(fname, regex)
188 if time >= date:
189 if time < endtime:
190 if fname.endswith(pattern):
191 if fname not in error_flist:
192 flist_scnx.append(fname)
193 if fname.endswith(".h5"):
194 if fname not in error_flist:
195 flist_h5.append(fname)
196 if fname.endswith(".nc"):
197 if fname not in error_flist:
198 flist_nc.append(fname)
200 if len(flist_nc) > 0:
201 for file in flist_nc:
202 flist.append(file)
204 if len(flist_scnx) == 0:
205 if len(flist_h5) > 0:
206 for file in flist_h5:
207 flist.append(file)
209 if len(flist_scnx) > 0:
210 for file in flist_scnx:
211 filetime_scnx = get_datetime_from_filename(file, regex)
212 datetime_list.append(filetime_scnx)
213 flist.append(file)
214 if len(flist_h5) > 0:
215 for file in flist_h5:
216 filetime_h5 = get_datetime_from_filename(file, regex)
217 if filetime_h5 not in datetime_list:
218 flist.append(file)
220 date = date + dt.timedelta(1)
222 flist = sorted(set(flist))
224 return flist
227# read single file of Furuno data
228# (important for create the clutter map)
229# ---------------------------------------
231def read_single_file(file, grp="dataset1"):
232 """Read a single file, reindexes and returns a dataset object.
234 Parameters
235 ----------
236 file : str
237 path to file as string
238 grp : str
239 hdf5 group (elevation angle)
241 Returns
242 -------
243 : xarray Dataset
244 xarray Dataset with variables.
245 """
246 extension = os.path.splitext(file)[1]
248 if extension == ".gz":
249 # the elevation angle the elevation angle is already selected in the flist!
250 tmp = xr.open_mfdataset((file,), engine="furuno", group=1,
251 concat_dim="time", combine="nested",
252 backend_kwargs=dict(reindex_angle=1.0))
254 else:
255 tmp = xr.open_mfdataset((file,), engine="odim", group=grp,
256 concat_dim="time", combine="nested",
257 backend_kwargs=dict(reindex_angle=1.0))
259 # TODO add case sensitive decision on these parameters
260 re_index_parameters = np.arange(0.25, 360, 0.5)
262 ri = tmp.reindex(azimuth=re_index_parameters, method="nearest")
263 return ri
266# read processed cluttermap from Furuno
267# -------------------------------------
269def get_cmap(starttime,
270 endtime,
271 path,
272 elev="0.5",
273 timestr="%Y%m%d"):
274 """Read processed cluttermap from Furuno.
276 Parameters
277 ---------
278 starttime : datetime.datetime
279 datetime - object to select correct files for list
280 endtime : datetime.datetime
281 datetime - object to select correct files for list
282 path : str
283 Path to configuration file
284 elev : str
285 selected elevation angle of cmap
287 Returns
288 -------
289 : xarray.Dataset
290 clutter map as xarray.Dataset.
291 """
292 # read settings from configuration file
293 clutter_dir = read_config_file(path=path, selection="monthly_clutter_directory")
294 subfolderstruct = read_config_file(path=path, selection="subfolder_structure_clutter_directory")
296 # create file structure
297 file_struct = os.path.join(f"{clutter_dir}", f"{subfolderstruct}", "*")
299 path = file_struct.format(year=starttime.year)
301 # list all cmaps in the folder
302 cmaps = sorted(glob.glob(path))
304 selected_map = None
305 last_date = dt.datetime(1900, 1, 1)
307 for cmap in cmaps:
308 # choose the stop time from filename
309 filetime_end = dt.datetime.strptime((os.path.basename(cmap)[19:27]), timestr)
310 elev_cmap = os.path.basename(cmap)[33:36]
312 if filetime_end > (endtime - dt.timedelta(45)):
313 if filetime_end > last_date:
314 if elev_cmap == elev: # noqa E712
315 selected_map = cmap
316 last_date = filetime_end
318 if selected_map is None:
319 print("wrainfo.reader.get_cmap(): No cmap found for these dates.")
321 # read cmap
322 cmap = xr.open_dataset(selected_map, engine="h5netcdf")
324 return cmap