def get_all_z_agl(self): """get all STEM Z cell heights above ground level (from surface to top of domain). """ topo_fname = os.path.join(os.getenv('SARIKA_INPUT'), 'TOPO-124x124.nc') wrfheight_fname = os.path.join(os.getenv('SARIKA_INPUT'), 'wrfheight-124x124-22levs.nc') dom = domain.STEM_Domain(fname_topo=topo_fname) dom.get_STEMZ_height(wrfheight_fname) if self.z_obs_mean is None: self.get_z_lev_mean() n_zlevs = dom.agl.shape[0] z_all_agl = pd.DataFrame({'z_stem': np.arange(n_zlevs) + 1, 'z_agl': dom.agl[:, self.x_stem, self.y_stem]}) self.z_obs_mean = pd.merge(z_all_agl, self.z_obs_mean, how='outer', sort=True) self.z_obs_mean['ocs_interp'] = self.z_obs_mean['analysis_value'] idx_min = self.z_obs_mean.sample_altitude.idxmin() idx_max = self.z_obs_mean.sample_altitude.idxmax() ocs_interp = np.interp( self.z_obs_mean.z_agl, rm_nan(self.z_obs_mean.sample_altitude.values), rm_nan(self.z_obs_mean.analysis_value.values), left=self.z_obs_mean.analysis_value[idx_min], right=self.z_obs_mean.analysis_value[idx_max]) nan_idx = np.where(np.isnan(self.z_obs_mean['analysis_value'])) self.z_obs_mean['ocs_interp'].iloc[nan_idx] = ocs_interp[nan_idx]
def get_z_lev_mean(self): d = domain.STEM_Domain() topo_dir = os.path.join(os.getenv('PROJ'), 'Data', 'STEM_124x124_NA_inputs') self.noaa_site.get_stem_xy(d.get_lon(), d.get_lat()) self.noaa_site.get_stem_z( topo_fname=os.path.join(topo_dir, 'TOPO-124x124.nc'), wrfheight_fname=os.path.join(topo_dir, 'wrfheight-124x124-22levs.nc')) bin_min = 0 # bottom of bottom altitude bin, meters bin_max = 16000 # top of top altitude bin, meters bin_width = 1000 # size of altitude bins, meters bin_edges = np.arange(bin_min, bin_max, bin_width) self.noaa_site.obs['altitude_bin'] = np.digitize( self.noaa_site.obs.sample_altitude, bin_edges) groups = self.noaa_site.obs.groupby('altitude_bin') self.z_obs_mean = groups.mean() self.z_obs_mean = self.z_obs_mean[['x_stem', 'y_stem', 'sample_altitude', 'analysis_value']] # # change the index (which is the z level after the groupby to # # a column) self.z_obs_mean.reset_index(drop=True, inplace=True) # a handful of obs are in adjacent STEM cells, resulting in # non-integral mean x or y cell locations after the mean is # taken. I think that rounding will pick the the "mode" x and # y and convert to an integer in one step self.x_stem = np.int(np.unique(np.round(self.z_obs_mean['x_stem']))[0]) self.y_stem = np.int(np.unique(np.round(self.z_obs_mean['y_stem']))[0]) self.z_obs_mean['x_stem'][:] = self.x_stem self.z_obs_mean['y_stem'][:] = self.y_stem self.z_obs_mean['z_stem'] = domain.get_stem_z_from_altitude( self.z_obs_mean.sample_altitude.values, stem_x=self.z_obs_mean.x_stem.values, stem_y=self.z_obs_mean.y_stem.values) self.z_obs_mean = self.z_obs_mean[['x_stem', 'y_stem', 'z_stem', 'sample_altitude', 'analysis_value']] # after binning some z levels end up with multiple # observations; average them together. self.z_obs_mean = self.z_obs_mean.groupby('z_stem').mean() self.z_obs_mean.reset_index(inplace=True)
def assemble_bar_plot_data(cpickle_fname=os.path.join( os.getenv('HOME'), 'STEM_all_runs.cpickle')): noaa_dir = sau.get_noaa_COS_data_path() noaa_ocs_dd, ocs_daily = sau.get_JA_site_mean_drawdown(noaa_dir) d = domain.STEM_Domain() stem_lon = d.get_lon() stem_lat = d.get_lat() (noaa_ocs_dd['stem_x'], noaa_ocs_dd['stem_y']) = domain.find_nearest_stem_xy( noaa_ocs_dd.sample_longitude, noaa_ocs_dd.sample_latitude, stem_lon, stem_lat) stem_ocs_dd = get_STEM_cos_conc(cpickle_fname) # place model drawdowns into the data frame for k, v in stem_ocs_dd.items(): noaa_ocs_dd[k] = stem_ocs_dd[k][noaa_ocs_dd['stem_x'], noaa_ocs_dd['stem_y']] return (noaa_ocs_dd)
norm=cos_norm, dd_map=map_objs[3, i]) fname = '/tmp/maps_basc.pdf' print("saving {}".format(fname)) fig.savefig(fname) if draw_site_drawdown_timeseries: # FIX THIS: where does dd come from? -TWH plot_site_drawdown_timeseries(dd) if draw_site_locations_map: # draw observation sites map data = noaa_ocs.get_all_NOAA_airborne_data(get_noaa_COS_data_path()) location_map = data.plot_obs_site_locations() n_amer_domain = domain.STEM_Domain() n_amer_domain.get_STEM_perimeter_latlon() location_map.map.plot(n_amer_domain.bnd_lon, n_amer_domain.bnd_lat, latlon=True) location_map.fig.savefig( os.path.join(os.getenv('HOME'), 'plots', 'noaa_obs_sites_STEMdomain.pdf')) plt.close(location_map.fig) if draw_observation_altitude_histograms: # FIX THIS: where does data come from? -TWH draw_observation_altitude_histograms(data) if False:
def top_bounds_QC(top_fname): """plot a map of top boundary file to make sure orientation is correct""" cos = parse_STEM_var('upbound_124x124-climatological_124x124.nc', varname='CO2_TRACER1') m = STEM_mapper.Mapper124x124(cos['data'].squeeze()) m.draw_map(fast_or_pretty='pretty', t_str='Climatological top bounds I/O API', cmap=plt.get_cmap('Blues')) m.map.fig.savefig('./top_bounds_ioapi_map.png') plt.close(m.map.fig) if __name__ == "__main__": # -- # get STEM domain parameteres d = domain.STEM_Domain(Consts().topo_fname) # -- # read NOAA [COS] observations data sites = noaa_ocs.get_all_NOAA_airborne_data(Consts().noaa_dir) sites_list = list(sites.obs.sample_site_code.unique()) # drop WGC because there are no Jul/Aug observations if 'WGC' in sites_list: sites_list.remove('WGC') # drop OIL because of weird-looking column profile from only two # days of data, with three nearby sites (AAO, WBI, HIL) with much # more data and very different column means. if 'OIL' in sites_list: sites_list.remove('OIL') lateral_bounds_sites_list = ['THD', 'PFA', 'ESP', 'TGC', 'NHA', 'SCA', 'CMA']
if __name__ == "__main__": # plot the boundary ring cell number vs. vertical cell number nc = netCDF4.Dataset( os.path.join(os.getcwd(), 'ClimatologicalBounds', 'climatological_COS_bdy_22levs_124x124.nc')) ppb_2_ppt = 1e3 # unit conversion factor cos = nc.variables['CO2_TRACER1'][:].squeeze() * ppb_2_ppt cmap, norm = colormap_nlevs.setup_colormap(vmin=cos.min() - 1, vmax=cos.max() + 1, nlevs=20, cmap=plt.get_cmap('Blues'), extend='neither') d = domain.STEM_Domain() d.get_STEMZ_height(wrfheight_fname=os.path.join( os.getenv('SARIKA_INPUT'), 'wrfheight-124x124-22levs.nc')) agl_perim = np.array( [domain.get_2d_perimeter(d.agl[z, ...]).mean() for z in range(22)]) fontsz = 14 matplotlib.rcParams.update({'font.size': fontsz}) fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(7, 6)) cm = ax.pcolormesh(np.arange(500), agl_perim, cos, cmap=cmap, norm=norm, linewidth=0, rasterized=True)