Skip to content

Commit ff7f103

Browse files
author
Josh Laughner
committed
Merge branch 'develop'
Brings in changes to the aircraft matching code and a Python utility to help identify missing wrf output files
2 parents 0ac528a + 4ae15b2 commit ff7f103

File tree

3 files changed

+200
-21
lines changed

3 files changed

+200
-21
lines changed

ChemComparison/match_wrf2campaigns.m

Lines changed: 127 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
end
88

99
methods(Static = true)
10-
function Match = discover_md(prof_mode, wrf_dirs)
10+
function Match = discover_md(prof_mode, wrf_dirs, varargin)
11+
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});
12+
1113
campaign_name = 'discover_md';
12-
if ~exist('prof_mode', 'var')
14+
if ~exist('prof_mode', 'var') || isempty(prof_mode)
1315
prof_mode = 'daily';
1416
end
15-
if ~exist('wrf_dirs', 'var')
16-
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2011/07'};
17+
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
18+
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2011/07'};
1719
end
1820

1921
Out = campaign_wide_ops(campaign_name, {'NO2_LIF', 'LONGITUDE', 'LATITUDE', 'PRESSURE'}, 'cat', 'datefmt','datenum');
@@ -24,16 +26,20 @@
2426
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
2527
Raw.campaign = campaign_name;
2628

29+
Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);
30+
2731
Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
2832
end
2933

30-
function Match = discover_ca(prof_mode, wrf_dirs)
34+
function Match = discover_ca(prof_mode, wrf_dirs, varargin)
35+
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});
36+
3137
campaign_name = 'discover_ca';
32-
if ~exist('prof_mode', 'var')
38+
if ~exist('prof_mode', 'var') || isempty(prof_mode)
3339
prof_mode = 'daily';
3440
end
35-
if ~exist('wrf_dirs', 'var')
36-
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2013/01', '/Volumes/share-wrf1/Outputs/us/2013/02'};
41+
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
42+
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/01', '/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/02'};
3743
end
3844

3945
Out = campaign_wide_ops(campaign_name, {'NO2_MixingRatio_LIF', 'LONGITUDE', 'LATITUDE', 'PRESSURE'}, 'cat', 'datefmt','datenum');
@@ -44,16 +50,20 @@
4450
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
4551
Raw.campaign = campaign_name;
4652

53+
Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);
54+
4755
Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
4856
end
4957

50-
function Match = discover_tx(prof_mode, wrf_dirs)
58+
function Match = discover_tx(prof_mode, wrf_dirs, varargin)
59+
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});
60+
5161
campaign_name = 'discover_tx';
52-
if ~exist('prof_mode', 'var')
62+
if ~exist('prof_mode', 'var') || isempty(prof_mode)
5363
prof_mode = 'daily';
5464
end
55-
if ~exist('wrf_dirs', 'var')
56-
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2013/09'};
65+
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
66+
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/09'};
5767
end
5868

5969
Out = campaign_wide_ops(campaign_name, {'NO2_MixingRatio_LIF', 'LONGITUDE', 'LATITUDE', 'PRESSURE'}, 'cat', 'datefmt','datenum');
@@ -64,16 +74,20 @@
6474
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
6575
Raw.campaign = campaign_name;
6676

77+
Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);
78+
6779
Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
6880
end
6981

70-
function Match = discover_co(prof_mode, wrf_dirs)
82+
function Match = discover_co(prof_mode, wrf_dirs, varargin)
83+
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});
84+
7185
campaign_name = 'discover_co';
72-
if ~exist('prof_mode', 'var')
86+
if ~exist('prof_mode', 'var') || isempty(prof_mode)
7387
prof_mode = 'daily';
7488
end
75-
if ~exist('wrf_dirs', 'var')
76-
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2014/07','/Volumes/share-wrf1/Outputs/us/2014/08'};
89+
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
90+
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2014/07','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2014/08'};
7791
end
7892

7993
Out = campaign_wide_ops(campaign_name, {'NO2_LIF', 'LONGITUDE', 'LATITUDE', 'PRESSURE'}, 'cat', 'datefmt','datenum');
@@ -84,16 +98,20 @@
8498
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
8599
Raw.campaign = campaign_name;
86100

101+
Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);
102+
87103
Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
88104
end
89105

90-
function Match = dc3(prof_mode, wrf_dirs)
106+
function Match = dc3(prof_mode, wrf_dirs, varargin)
107+
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});
108+
91109
campaign_name = 'dc3';
92-
if ~exist('wrf_dirs', 'var')
110+
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
93111
%wrf_dirs = '/Volumes/share2/USERS/LaughnerJ/WRF/DC3/lnox_off-fixed_BCs';
94-
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2012/05','/Volumes/share-wrf1/Outputs/us/2012/06'};
112+
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2012/05','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2012/06'};
95113
end
96-
if ~exist('prof_mode', 'var')
114+
if ~exist('prof_mode', 'var') || isempty(prof_mode)
97115
prof_mode = 'daily';
98116
end
99117

@@ -121,6 +139,58 @@
121139
% 2) The units for this mixing ratio are g/kg, in WRF it is kg/kg.
122140
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
123141

142+
Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);
143+
144+
Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
145+
end
146+
147+
function Match = soas(prof_mode, wrf_dirs, varargin)
148+
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});
149+
150+
campaign_name = 'soas';
151+
if ~exist('prof_mode', 'var') || isempty(prof_mode)
152+
prof_mode = 'daily';
153+
end
154+
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
155+
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/05','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/05','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/07'};
156+
end
157+
158+
Out = campaign_wide_ops(campaign_name, {'NO2_ppbv', 'LONGITUDE', 'LATITUDE', 'StaticPrs'}, 'cat', 'datefmt','datenum');
159+
160+
Raw.campaign = campaign_name;
161+
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
162+
Raw.no2 = Out.data.NO2_ppbv * 1e-9 * 1e6;
163+
Raw.lon = Out.data.LONGITUDE;
164+
Raw.lat = Out.data.LATITUDE;
165+
Raw.pres = Out.data.StaticPrs;
166+
167+
Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);
168+
169+
Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
170+
end
171+
172+
function Match = seac4rs(prof_mode, wrf_dirs, varargin)
173+
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});
174+
175+
campaign_name = 'seac4rs';
176+
if ~exist('prof_mode', 'var') || isempty(prof_mode)
177+
prof_mode = 'daily';
178+
end
179+
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
180+
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/08','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/09'};
181+
end
182+
183+
Out = campaign_wide_ops(campaign_name, {'NO2_TDLIF', 'LONGITUDE', 'LATITUDE', 'PRESSURE'}, 'cat', 'datefmt','datenum');
184+
185+
Raw.campaign = campaign_name;
186+
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
187+
Raw.no2 = Out.data.NO2_TDLIF * 1e-12 * 1e6;
188+
Raw.lon = Out.data.LONGITUDE;
189+
Raw.lat = Out.data.LATITUDE;
190+
Raw.pres = Out.data.PRESSURE;
191+
192+
Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);
193+
124194
Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
125195
end
126196
end
@@ -129,6 +199,43 @@
129199
function dvec = convert_aircraft_times(Out)
130200
dvec = Out.dates + Out.utcs ./ (60*60*24);
131201
end
202+
203+
function varargout = parse_common_args(varargin)
204+
p = inputParser;
205+
p.addParameter('utc_range', []);
206+
p.addParameter('lst_range', []);
207+
208+
p.parse(varargin{:});
209+
pout = p.Results;
210+
211+
varargout{1} = pout.utc_range;
212+
varargout{2} = pout.lst_range;
213+
end
214+
215+
function Raw = restrict_by_time(Raw, utcs, utc_range, lst_range)
216+
xx_in_range = true(size(utcs));
217+
if ~isempty(utc_range)
218+
xx_in_range = xx_in_range & match_wrf2campaigns.time_range_logical(utcs, utc_range);
219+
end
220+
if ~isempty(lst_range)
221+
xx_in_range = xx_in_range & match_wrf2campaigns.time_range_logical(utc2local_sec(utcs, round(Raw.lon/15)), lst_range);
222+
end
223+
224+
fns = fieldnames(Raw);
225+
for f = 1:numel(fns)
226+
if isnumeric(Raw.(fns{f}))
227+
Raw.(fns{f}) = Raw.(fns{f})(xx_in_range);
228+
end
229+
end
230+
end
231+
232+
function xx = time_range_logical(sec_after_midnight, time_range)
233+
% Assume the range is given in hours after midnight. Convert to
234+
% seconds.
235+
range_start = time_range(1) * 60^2;
236+
range_end = time_range(2) * 60^2;
237+
xx = sec_after_midnight >= range_start & sec_after_midnight <= range_end;
238+
end
132239
end
133240

134241
end

convert_wrf_temperature.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,6 @@
8080
T = T+300;
8181

8282
% Now convert from potential temperature to absolute temperature
83-
T = T .* ((P+PB) ./ 1e5) .^ 0.2865;
83+
T = T .* ((P+PB) ./ 1e5) .^ 0.2864;
8484
end
8585

missing_wrfout.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from __future__ import print_function
2+
3+
import argparse
4+
import datetime as dt
5+
import os
6+
import sys
7+
8+
9+
def shell_error(msg, exit_code=1):
10+
print(msg, file=sys.stderr)
11+
exit(exit_code)
12+
13+
14+
def parse_wrf_date(datestr):
15+
return dt.datetime.strptime(datestr, '%Y-%m-%d_%H:%M:%S')
16+
17+
18+
def parse_timestep(stepstr):
19+
vals = [int(x) for x in stepstr.split(':')]
20+
while len(vals) < 0:
21+
vals.append(0)
22+
23+
return dt.timedelta(hours=vals[0], minutes=vals[1], seconds=vals[2])
24+
25+
26+
def iter_date(start, end, step):
27+
curr_date = start
28+
while curr_date <= end:
29+
yield curr_date
30+
curr_date += step
31+
32+
33+
def parse_args():
34+
parser = argparse.ArgumentParser(description='List missing WRF output files',
35+
epilog='This program will exit with code 0 if all files were found and code 1 if '
36+
'any files were missing. Other errors will be indicated by higher exit codes.')
37+
parser.add_argument('start_date', type=parse_wrf_date, help='First expected date in yyyy-mm-dd_HH:MM:SS format')
38+
parser.add_argument('end_date', type=parse_wrf_date, help='Last expected date in yyyy-mm-dd_HH:MM:SS format')
39+
parser.add_argument('-t', '--time-step', type=parse_timestep, default=dt.timedelta(hours=1),
40+
help='Increment between files in HH, HH:MM, or HH:MM:SS format. Default is %(default)s')
41+
parser.add_argument('-d', '--dir', default='.', help='Directory to search. Default is the current directory.')
42+
parser.add_argument('-n', '--domain', default=1, type=int, help='Domain number to check')
43+
parser.add_argument('-f', '--filename', default='wrfout_d{domain:02}_%Y-%m-%d_%H:%M:%S',
44+
help='The format of the WRF output filenames. For each file, it is first formatted with the '
45+
'.format(domain=d) call (to insert the domain number) then passed through '
46+
'datetime.strftime to insert the date. Default is %(default)s.')
47+
48+
args = parser.parse_args()
49+
50+
if not os.path.isdir(args.dir):
51+
shell_error('Argument for "--dir" is not a valid directory', exit_code=2)
52+
53+
return args
54+
55+
56+
def main():
57+
args = parse_args()
58+
files_missing = False
59+
for date in iter_date(args.start_date, args.end_date, args.time_step):
60+
wrf_fname = os.path.join(args.dir, date.strftime(args.filename.format(domain=args.domain)))
61+
if not os.path.isfile(wrf_fname):
62+
files_missing = True
63+
print(wrf_fname, 'MISSING')
64+
65+
if files_missing:
66+
exit(1)
67+
else:
68+
exit(0)
69+
70+
71+
if __name__ == '__main__':
72+
main()

0 commit comments

Comments
 (0)