Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
Brings in changes to the aircraft matching code and a Python utility
to help identify missing wrf output files
  • Loading branch information
Josh Laughner committed May 18, 2018
2 parents 0ac528a + 4ae15b2 commit ff7f103
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 21 deletions.
147 changes: 127 additions & 20 deletions ChemComparison/match_wrf2campaigns.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
end

methods(Static = true)
function Match = discover_md(prof_mode, wrf_dirs)
function Match = discover_md(prof_mode, wrf_dirs, varargin)
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});

campaign_name = 'discover_md';
if ~exist('prof_mode', 'var')
if ~exist('prof_mode', 'var') || isempty(prof_mode)
prof_mode = 'daily';
end
if ~exist('wrf_dirs', 'var')
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2011/07'};
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2011/07'};
end

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

Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);

Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
end

function Match = discover_ca(prof_mode, wrf_dirs)
function Match = discover_ca(prof_mode, wrf_dirs, varargin)
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});

campaign_name = 'discover_ca';
if ~exist('prof_mode', 'var')
if ~exist('prof_mode', 'var') || isempty(prof_mode)
prof_mode = 'daily';
end
if ~exist('wrf_dirs', 'var')
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2013/01', '/Volumes/share-wrf1/Outputs/us/2013/02'};
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/01', '/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/02'};
end

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

Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);

Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
end

function Match = discover_tx(prof_mode, wrf_dirs)
function Match = discover_tx(prof_mode, wrf_dirs, varargin)
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});

campaign_name = 'discover_tx';
if ~exist('prof_mode', 'var')
if ~exist('prof_mode', 'var') || isempty(prof_mode)
prof_mode = 'daily';
end
if ~exist('wrf_dirs', 'var')
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2013/09'};
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/09'};
end

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

Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);

Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
end

function Match = discover_co(prof_mode, wrf_dirs)
function Match = discover_co(prof_mode, wrf_dirs, varargin)
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});

campaign_name = 'discover_co';
if ~exist('prof_mode', 'var')
if ~exist('prof_mode', 'var') || isempty(prof_mode)
prof_mode = 'daily';
end
if ~exist('wrf_dirs', 'var')
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2014/07','/Volumes/share-wrf1/Outputs/us/2014/08'};
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2014/07','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2014/08'};
end

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

Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);

Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
end

function Match = dc3(prof_mode, wrf_dirs)
function Match = dc3(prof_mode, wrf_dirs, varargin)
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});

campaign_name = 'dc3';
if ~exist('wrf_dirs', 'var')
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
%wrf_dirs = '/Volumes/share2/USERS/LaughnerJ/WRF/DC3/lnox_off-fixed_BCs';
wrf_dirs = {'/Volumes/share-wrf1/Outputs/us/2012/05','/Volumes/share-wrf1/Outputs/us/2012/06'};
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2012/05','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2012/06'};
end
if ~exist('prof_mode', 'var')
if ~exist('prof_mode', 'var') || isempty(prof_mode)
prof_mode = 'daily';
end

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

Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);

Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
end

function Match = soas(prof_mode, wrf_dirs, varargin)
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});

campaign_name = 'soas';
if ~exist('prof_mode', 'var') || isempty(prof_mode)
prof_mode = 'daily';
end
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
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'};
end

Out = campaign_wide_ops(campaign_name, {'NO2_ppbv', 'LONGITUDE', 'LATITUDE', 'StaticPrs'}, 'cat', 'datefmt','datenum');

Raw.campaign = campaign_name;
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
Raw.no2 = Out.data.NO2_ppbv * 1e-9 * 1e6;
Raw.lon = Out.data.LONGITUDE;
Raw.lat = Out.data.LATITUDE;
Raw.pres = Out.data.StaticPrs;

Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);

Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
end

function Match = seac4rs(prof_mode, wrf_dirs, varargin)
[utc_range, lst_range] = match_wrf2campaigns.parse_common_args(varargin{:});

campaign_name = 'seac4rs';
if ~exist('prof_mode', 'var') || isempty(prof_mode)
prof_mode = 'daily';
end
if ~exist('wrf_dirs', 'var') || isempty(wrf_dirs)
wrf_dirs = {'/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/08','/Volumes/share-wrf1/BEHR-WRF/Outputs/us/2013/09'};
end

Out = campaign_wide_ops(campaign_name, {'NO2_TDLIF', 'LONGITUDE', 'LATITUDE', 'PRESSURE'}, 'cat', 'datefmt','datenum');

Raw.campaign = campaign_name;
Raw.dvec = match_wrf2campaigns.convert_aircraft_times(Out);
Raw.no2 = Out.data.NO2_TDLIF * 1e-12 * 1e6;
Raw.lon = Out.data.LONGITUDE;
Raw.lat = Out.data.LATITUDE;
Raw.pres = Out.data.PRESSURE;

Raw = match_wrf2campaigns.restrict_by_time(Raw, Out.utcs, utc_range, lst_range);

Match = match_wrf2aircraft(Raw, wrf_dirs, prof_mode);
end
end
Expand All @@ -129,6 +199,43 @@
function dvec = convert_aircraft_times(Out)
dvec = Out.dates + Out.utcs ./ (60*60*24);
end

function varargout = parse_common_args(varargin)
p = inputParser;
p.addParameter('utc_range', []);
p.addParameter('lst_range', []);

p.parse(varargin{:});
pout = p.Results;

varargout{1} = pout.utc_range;
varargout{2} = pout.lst_range;
end

function Raw = restrict_by_time(Raw, utcs, utc_range, lst_range)
xx_in_range = true(size(utcs));
if ~isempty(utc_range)
xx_in_range = xx_in_range & match_wrf2campaigns.time_range_logical(utcs, utc_range);
end
if ~isempty(lst_range)
xx_in_range = xx_in_range & match_wrf2campaigns.time_range_logical(utc2local_sec(utcs, round(Raw.lon/15)), lst_range);
end

fns = fieldnames(Raw);
for f = 1:numel(fns)
if isnumeric(Raw.(fns{f}))
Raw.(fns{f}) = Raw.(fns{f})(xx_in_range);
end
end
end

function xx = time_range_logical(sec_after_midnight, time_range)
% Assume the range is given in hours after midnight. Convert to
% seconds.
range_start = time_range(1) * 60^2;
range_end = time_range(2) * 60^2;
xx = sec_after_midnight >= range_start & sec_after_midnight <= range_end;
end
end

end
Expand Down
2 changes: 1 addition & 1 deletion convert_wrf_temperature.m
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@
T = T+300;

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

72 changes: 72 additions & 0 deletions missing_wrfout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from __future__ import print_function

import argparse
import datetime as dt
import os
import sys


def shell_error(msg, exit_code=1):
print(msg, file=sys.stderr)
exit(exit_code)


def parse_wrf_date(datestr):
return dt.datetime.strptime(datestr, '%Y-%m-%d_%H:%M:%S')


def parse_timestep(stepstr):
vals = [int(x) for x in stepstr.split(':')]
while len(vals) < 0:
vals.append(0)

return dt.timedelta(hours=vals[0], minutes=vals[1], seconds=vals[2])


def iter_date(start, end, step):
curr_date = start
while curr_date <= end:
yield curr_date
curr_date += step


def parse_args():
parser = argparse.ArgumentParser(description='List missing WRF output files',
epilog='This program will exit with code 0 if all files were found and code 1 if '
'any files were missing. Other errors will be indicated by higher exit codes.')
parser.add_argument('start_date', type=parse_wrf_date, help='First expected date in yyyy-mm-dd_HH:MM:SS format')
parser.add_argument('end_date', type=parse_wrf_date, help='Last expected date in yyyy-mm-dd_HH:MM:SS format')
parser.add_argument('-t', '--time-step', type=parse_timestep, default=dt.timedelta(hours=1),
help='Increment between files in HH, HH:MM, or HH:MM:SS format. Default is %(default)s')
parser.add_argument('-d', '--dir', default='.', help='Directory to search. Default is the current directory.')
parser.add_argument('-n', '--domain', default=1, type=int, help='Domain number to check')
parser.add_argument('-f', '--filename', default='wrfout_d{domain:02}_%Y-%m-%d_%H:%M:%S',
help='The format of the WRF output filenames. For each file, it is first formatted with the '
'.format(domain=d) call (to insert the domain number) then passed through '
'datetime.strftime to insert the date. Default is %(default)s.')

args = parser.parse_args()

if not os.path.isdir(args.dir):
shell_error('Argument for "--dir" is not a valid directory', exit_code=2)

return args


def main():
args = parse_args()
files_missing = False
for date in iter_date(args.start_date, args.end_date, args.time_step):
wrf_fname = os.path.join(args.dir, date.strftime(args.filename.format(domain=args.domain)))
if not os.path.isfile(wrf_fname):
files_missing = True
print(wrf_fname, 'MISSING')

if files_missing:
exit(1)
else:
exit(0)


if __name__ == '__main__':
main()

0 comments on commit ff7f103

Please sign in to comment.