def get_WRF_Tsoil_VWC(fname_wrf):
    """obtain WRF soil T and soil moisture.  soil T is masked below 10 C
    because Mary's soil flux model fitting data went no lower..
    """

    vwc = sp.parse_STEM_var(nc_fname=fname_wrf, varname='SMOIS')
    Tsoil = sp.parse_STEM_var(nc_fname=fname_wrf, varname='TSOIL')

    ten_C = 273.15 + 10  # 10 C expressed in Kelvins
    Tsoil['data'] = ma.masked_less(Tsoil['data'], ten_C)

    return (vwc, Tsoil)
def get_WRF_Tsoil_VWC(fname_wrf):
    """obtain WRF soil T and soil moisture.  soil T is masked below 10 C
    because Mary's soil flux model fitting data went no lower..
    """

    vwc = sp.parse_STEM_var(nc_fname=fname_wrf, varname='SMOIS')
    Tsoil = sp.parse_STEM_var(nc_fname=fname_wrf, varname='TSOIL')

    ten_C = 273.15 + 10  # 10 C expressed in Kelvins
    Tsoil['data'] = ma.masked_less(Tsoil['data'], ten_C)

    return(vwc, Tsoil)
def draw_map(t_str,
             ax,
             data,
             vmin,
             vmax,
             cmap=plt.get_cmap('Blues'),
             norm=plt.normalize,
             maskoceans_switch=True):

    map = NAMapFigure(t_str=t_str,
                      cb_axis=None,
                      map_axis=ax,
                      fast_or_pretty='pretty',
                      lat_0=49,
                      lon_0=-97,
                      mapwidth=5.8e6,
                      mapheight=5.2e6)

    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.getenv('SARIKA_INPUT'), 'TOPO-124x124.nc'))

    if maskoceans_switch:
        data = maskoceans(lon, lat, data, inlands=False, resolution='f')

    cm = map.map.contourf(lon, lat,
                          data,
                          cmap=cmap,
                          latlon=True,
                          norm=norm,
                          vmin=vmin,
                          vmax=vmax)
    return(map, cm)
def calc_ratio(fsoil_mary, fsoil_kettle):
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    fsoil_mary = maskoceans(lon, lat, fsoil_mary)
    fsoil_kettle = maskoceans(lon, lat, fsoil_kettle)
    ratio = ma.masked_invalid(fsoil_kettle) / ma.masked_invalid(fsoil_mary)
    return(ratio)
def calc_ratio(fsoil_mary, fsoil_kettle):
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    fsoil_mary = maskoceans(lon, lat, fsoil_mary)
    fsoil_kettle = maskoceans(lon, lat, fsoil_kettle)
    ratio = ma.masked_invalid(fsoil_kettle) / ma.masked_invalid(fsoil_mary)
    return (ratio)
Example #6
0
def get_anthro_fCOS(run_key):
    """parse July-August 2008 anthropogenic COS surface flux
    """
    Jul1 = datetime(2008, 7, 1)
    Aug31 = datetime(2008, 8, 31, 23, 59, 59)
    flux = sp.parse_STEM_var(nc_fname=ndp.get_runs()[run_key].fcos_path,
                             varname='Coal_COS',
                             t0=Jul1,
                             t1=Aug31)
    fcos_mean = flux['data'].mean(axis=0).squeeze()
    return fcos_mean
def get_hybrid_fsoil(fname_hybrid_fsoil):
    fsoil_JA = sp.parse_STEM_var(fname_hybrid_fsoil,
                                 t0=datetime(2008, 7, 1),
                                 t1=datetime(2008, 8, 31, 23, 59, 59),
                                 varname='fsoil')
    s_per_tstamp = 6 * 60 * 60  # six hours expressed as seconds
    mol_per_pmol = 1e-12
    n_months = 2
    fsoil_itgd = np.sum(fsoil_JA['data'] * mol_per_pmol * s_per_tstamp,
                        axis=0) / n_months
    return (fsoil_itgd.squeeze())
def get_anthro_fCOS(run_key):
    """parse July-August 2008 anthropogenic COS surface flux
    """
    Jul1 = datetime(2008, 7, 1)
    Aug31 = datetime(2008, 8, 31, 23, 59, 59)
    flux = sp.parse_STEM_var(nc_fname=ndp.get_runs()[run_key].fcos_path,
                             varname='Coal_COS',
                             t0=Jul1,
                             t1=Aug31)
    fcos_mean = flux['data'].mean(axis=0).squeeze()
    return fcos_mean
def get_hybrid_fsoil(fname_hybrid_fsoil):
    fsoil_JA = sp.parse_STEM_var(fname_hybrid_fsoil,
                                 t0=datetime(2008, 7, 1),
                                 t1=datetime(2008, 8, 31,
                                             23, 59, 59),
                                 varname='fsoil')
    s_per_tstamp = 6 * 60 * 60  # six hours expressed as seconds
    mol_per_pmol = 1e-12
    n_months = 2
    fsoil_itgd = np.sum(fsoil_JA['data'] * mol_per_pmol * s_per_tstamp,
                        axis=0) / n_months
    return(fsoil_itgd.squeeze())
def get_kettle_soil(fname_kettle_fcos):
    s_per_tstamp = 60 * 60 * 24  # one day expressed as seconds
    n_months = 2  # July and Aug
    fsoil_k = sp.parse_STEM_var(fname_kettle_fcos,
                                t0=datetime(2008, 7, 1),
                                t1=datetime(2008, 8, 31, 23, 59, 59),
                                varname='cos')

    fsoil_k['data'] = ma.masked_invalid(fsoil_k['data'])
    # convert mol m-2 s-1 to mol m-2 mon-1
    fsoil_k_itgd = np.sum(fsoil_k['data'] * s_per_tstamp, axis=0)
    fsoil_k_itgd = (fsoil_k_itgd / n_months).squeeze()
    return(fsoil_k_itgd)
Example #11
0
    def get_STEM_perimeter_latlon(self):
        """Given a STEM topo file in self.fname_topo with latitude and
        longitude coordinates of the STEM grid, populates self.bnd_lon
        and self.bnd_lat with 1-D numpy arrays containing the
        coordinates of the perimiter grid cells.
        """

        self.STEM_lon, self.STEM_lat, self.topo = (
            sp.parse_STEM_coordinates(self.fname_topo))
        self.bnd_lon = get_2d_perimeter(self.STEM_lon)
        self.bnd_lat = get_2d_perimeter(self.STEM_lat)

        return(self)
def get_kettle_soil(fname_kettle_fcos):
    s_per_tstamp = 60 * 60 * 24  # one day expressed as seconds
    n_months = 2  # July and Aug
    fsoil_k = sp.parse_STEM_var(fname_kettle_fcos,
                                t0=datetime(2008, 7, 1),
                                t1=datetime(2008, 8, 31, 23, 59, 59),
                                varname='cos')

    fsoil_k['data'] = ma.masked_invalid(fsoil_k['data'])
    # convert mol m-2 s-1 to mol m-2 mon-1
    fsoil_k_itgd = np.sum(fsoil_k['data'] * s_per_tstamp, axis=0)
    fsoil_k_itgd = (fsoil_k_itgd / n_months).squeeze()
    return (fsoil_k_itgd)
def draw_ratio(map, ratio):
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    ratio = maskoceans(lon, lat, ratio)
    ratio_norm = midpt_norm.MidpointNormalize(midpoint=1.0)
    cm = map.map.pcolor(lon, lat, ratio,
                        vmin=-7,  # np.percentile(ratio, 1),
                        vmax=9,  # np.percentile(ratio, 99),
                        cmap=plt.get_cmap('PuOr'),
                        norm=ratio_norm,
                        latlon=True)
    cb = plt.colorbar(cm, ax=map.ax_map, extend='both',
                      ticks=np.arange(-7, 9, 2))
    cb.solids.set_edgecolor("face")
def draw_LRU_map():
    nc = netCDF4.Dataset(os.environ['LRU_FILE'])
    LRU = nc.variables['LRU'][...].squeeze()
    nc.close()
    stem_lon, stem_lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.getenv('SARIKA_INPUT'), 'TOPO-124x124.nc'))
    fcos_norm = midpt_norm.MidpointNormalize(midpoint=1.61)
    lru_map = na_map.NAMapFigure(cb_axis=True, t_str='LRU from C4 veg pct')
    cm = lru_map.map.pcolor(stem_lon, stem_lat, LRU,
                            cmap=plt.get_cmap('PuOr'),
                            latlon=True,
                            norm=fcos_norm)
    ticks = np.concatenate([np.linspace(1.12, 1.84, 5), np.array([1.61])])
    cbar = lru_map.fig.colorbar(cm, cax=lru_map.ax_cmap, ticks=ticks)
    cbar.ax.set_title('LRU')
    lru_map.fig.savefig('LRU_from_c4pct.pdf')
def draw_LRU_map():
    nc = netCDF4.Dataset(os.environ['LRU_FILE'])
    LRU = nc.variables['LRU'][...].squeeze()
    nc.close()
    stem_lon, stem_lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.getenv('SARIKA_INPUT'), 'TOPO-124x124.nc'))
    fcos_norm = midpt_norm.MidpointNormalize(midpoint=1.61)
    lru_map = na_map.NAMapFigure(cb_axis=True, t_str='LRU from C4 veg pct')
    cm = lru_map.map.pcolor(stem_lon,
                            stem_lat,
                            LRU,
                            cmap=plt.get_cmap('PuOr'),
                            latlon=True,
                            norm=fcos_norm)
    ticks = np.concatenate([np.linspace(1.12, 1.84, 5), np.array([1.61])])
    cbar = lru_map.fig.colorbar(cm, cax=lru_map.ax_cmap, ticks=ticks)
    cbar.ax.set_title('LRU')
    lru_map.fig.savefig('LRU_from_c4pct.pdf')
def fCOS_from_C4pct_diagnostics():

    draw_LRU_map()

    runs = edp.get_C3C4runs()
    for k in runs.keys():
        fcos = sp.parse_STEM_var(nc_fname=runs[k].fcos_path,
                                 t0=datetime.datetime(2008, 7, 1),
                                 t1=datetime.datetime(2008, 8, 31, 23, 59, 59),
                                 varname='cos')
        print('{}: min: {:0.2e}    max: {:0.2e}    mean: {:0.2e}'.format(
            k, fcos['data'].min(), fcos['data'].max(), fcos['data'].mean()))
        fig, ax = plt.subplots()
        cm = ax.pcolor(fcos['data'].squeeze().mean(axis=0),
                       cmap=plt.get_cmap('Blues'))
        plt.colorbar(cm)
        plt.title(k)
        fig.savefig('/tmp/fcos_{}.png'.format(k))
def draw_crop_pct(fname_crop_pct, map_obj, mask = None):
    nc = netCDF4.Dataset(fname_crop_pct)
    pct = nc.variables['crop_pct'][...].squeeze()
    nc.close()

    if mask is not None:
        pct = ma.masked_where(mask, pct)

    # pct = sp.parse_STEM_var(fname_crop_pct, varname='crop_pct')
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    cm = map_obj.map.pcolormesh(lon, lat, pct,
                                cmap=plt.get_cmap('Blues'),
                                vmin=0.0,
                                vmax=1.0,
                                latlon=True)
    cb = plt.colorbar(cm, ax=map_obj.ax_map)
    cb.solids.set_edgecolor("face")
def draw_ratio(map, ratio):
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    ratio = maskoceans(lon, lat, ratio)
    ratio_norm = midpt_norm.MidpointNormalize(midpoint=1.0)
    cm = map.map.pcolor(
        lon,
        lat,
        ratio,
        vmin=-7,  # np.percentile(ratio, 1),
        vmax=9,  # np.percentile(ratio, 99),
        cmap=plt.get_cmap('PuOr'),
        norm=ratio_norm,
        latlon=True)
    cb = plt.colorbar(cm,
                      ax=map.ax_map,
                      extend='both',
                      ticks=np.arange(-7, 9, 2))
    cb.solids.set_edgecolor("face")
def preprocess_NOAA_airborne_data_for_JA_spatial_analysis(noaa_dir):
    """
    (1) parses all NOAA COS observation files from noaa_dir
    (2) assigns each observation to a STEM x, y, and z cell
    (3) removes all observations with a [COS] value of -999
    (4) removes all observations that are not in July or August
    (5) removes all observations west of 140 deg W longitude (this
        roughly correspondes to the western boundary of the 124x124
        STEM domain)

    INPUTS
    noaa_dir: full path to a directory containing NOAA COS observation files

    OUTPUTS
    a noaa_ocs object

    SEE ALSO
    stem_pytools.noaa_ocs
    """

    data = noaa_ocs.get_all_NOAA_airborne_data(noaa_dir)

    stem_input_dir = os.getenv('SARIKA_INPUT')
    topo_file = os.path.join(stem_input_dir, 'TOPO-124x124.nc')
    wrf_height_file = os.path.join(stem_input_dir,
                                   'wrfheight-124x124-22levs.nc')
    stem_lon, stem_lat, topo = STEM_parsers.parse_STEM_coordinates(topo_file)
    data.get_stem_xy(stem_lon, stem_lat)
    data.get_stem_z(topo_fname=topo_file,
                    wrfheight_fname=wrf_height_file)

    # some observations list longitude of -999: remove those
    keep_idx = data.obs['sample_longitude'].values > -998
    # keep observations from July and August only
    keep_idx = keep_idx & np.in1d(data.obs['sample_month'].values, [7, 8])
    # remove observations in Alaska - this is outside of the STEM
    # domain.  I can do this crudely by cutting it off at 140 deg W
    # longitude.
    keep_idx = keep_idx & (data.obs.sample_longitude > -140)
    data.obs = data.obs.loc[keep_idx]

    return(data)
def draw_crop_pct(fname_crop_pct, map_obj, mask=None):
    nc = netCDF4.Dataset(fname_crop_pct)
    pct = nc.variables['crop_pct'][...].squeeze()
    nc.close()

    if mask is not None:
        pct = ma.masked_where(mask, pct)

    # pct = sp.parse_STEM_var(fname_crop_pct, varname='crop_pct')
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    cm = map_obj.map.pcolormesh(lon,
                                lat,
                                pct,
                                cmap=plt.get_cmap('Blues'),
                                vmin=0.0,
                                vmax=1.0,
                                latlon=True)
    cb = plt.colorbar(cm, ax=map_obj.ax_map)
    cb.solids.set_edgecolor("face")
def draw_fsoil(map, fsoil, vmin, vmax):
    pmol_per_mol = 1e12
    fsoil = fsoil * pmol_per_mol
    vmin = vmin * pmol_per_mol
    vmax = vmax * pmol_per_mol
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    fsoil = maskoceans(lon, lat, fsoil)
    norm = midpt_norm.MidpointNormalize(midpoint=0.0)
    cm = map.map.pcolor(lon, lat, fsoil,
                        vmin=vmin,  # np.nanmin(fsoil),
                        vmax=vmax,  # np.nanmax(fsoil),
                        norm=norm,
                        cmap=plt.get_cmap('RdGy_r'),
                        latlon=True)
    cb = plt.colorbar(cm, ax=map.ax_map, extend='both',
                      format=FuncFormatter(scinot_format.scinot_format))
    cb.solids.set_edgecolor("face")
    cb.ax.set_title('pmol COS m$^{-2}$ mon$^{-1}$',
                    fontdict={'fontsize': 8})
Example #22
0
def preprocess_NOAA_airborne_data_for_JA_spatial_analysis(noaa_dir):
    """
    (1) parses all NOAA COS observation files from noaa_dir
    (2) assigns each observation to a STEM x, y, and z cell
    (3) removes all observations with a [COS] value of -999
    (4) removes all observations that are not in July or August
    (5) removes all observations west of 140 deg W longitude (this
        roughly correspondes to the western boundary of the 124x124
        STEM domain)

    INPUTS
    noaa_dir: full path to a directory containing NOAA COS observation files

    OUTPUTS
    a noaa_ocs object

    SEE ALSO
    stem_pytools.noaa_ocs
    """

    data = noaa_ocs.get_all_NOAA_airborne_data(noaa_dir)

    stem_input_dir = os.getenv('SARIKA_INPUT')
    topo_file = os.path.join(stem_input_dir, 'TOPO-124x124.nc')
    wrf_height_file = os.path.join(stem_input_dir,
                                   'wrfheight-124x124-22levs.nc')
    stem_lon, stem_lat, topo = STEM_parsers.parse_STEM_coordinates(topo_file)
    data.get_stem_xy(stem_lon, stem_lat)
    data.get_stem_z(topo_fname=topo_file, wrfheight_fname=wrf_height_file)

    # some observations list longitude of -999: remove those
    keep_idx = data.obs['sample_longitude'].values > -998
    # keep observations from July and August only
    keep_idx = keep_idx & np.in1d(data.obs['sample_month'].values, [7, 8])
    # remove observations in Alaska - this is outside of the STEM
    # domain.  I can do this crudely by cutting it off at 140 deg W
    # longitude.
    keep_idx = keep_idx & (data.obs.sample_longitude > -140)
    data.obs = data.obs.loc[keep_idx]

    return (data)
def fCOS_from_C4pct_diagnostics():

    draw_LRU_map()

    runs = edp.get_C3C4runs()
    for k in runs.keys():
        fcos = sp.parse_STEM_var(nc_fname=runs[k].fcos_path,
                                 t0=datetime.datetime(2008, 7, 1),
                                 t1=datetime.datetime(2008, 8, 31, 23, 59, 59),
                                 varname='cos')
        print('{}: min: {:0.2e}    max: {:0.2e}    mean: {:0.2e}'.format(
            k,
            fcos['data'].min(),
            fcos['data'].max(),
            fcos['data'].mean()))
        fig, ax = plt.subplots()
        cm = ax.pcolor(fcos['data'].squeeze().mean(axis=0),
                       cmap=plt.get_cmap('Blues'))
        plt.colorbar(cm)
        plt.title(k)
        fig.savefig('/tmp/fcos_{}.png'.format(k))
    def parse(self, t0, t1, verbose=False):
        """parse the concentrations in the object's AQOUT file(s) for the
        period beginning with t0 and ending with t1.  The
        concentration are placed in a list of numpy ndarray objects;
        that list is placed in the calling object's 'data' field.  The
        corresponding timestamps are also placed in a list.  That list
        is then placed in the calling object's 't' field.

        Assumes that the timestep of all AQOUT files is one hour.
        Results are undefined if this requirement is not met.

        INPUTS
        t0, t1: datetime.datetime objects specifying the starting and
            ending timestamps to combine

        """

        one_hour = 10000  # Models-3 I/O API format for 1 hour
                          # (integer, HHMMSS)

        for p in self.aqout_paths:
            nc = netCDF4.Dataset(p)
            tstep = nc.TSTEP
            nc.close()
            if tstep != one_hour:
                raise ValueError('timestep of {} is not one hour!'
                                 '(it is {})'.format(os.path.basename(p),
                                                     tstep))
            if verbose:
                sys.stdout.write('parsing {}\n'.format(os.path.basename(p)))
                sys.stdout.flush()
            this_cos = sp.parse_STEM_var(p,
                                         varname='CO2_TRACER1',
                                         t0=t0,
                                         t1=t1)
            self.data.append(this_cos['data'])
            this_t = pd.DatetimeIndex(this_cos['t'], freq='1H')
            self.t.append(this_t)
def draw_fsoil(map, fsoil, vmin, vmax):
    pmol_per_mol = 1e12
    fsoil = fsoil * pmol_per_mol
    vmin = vmin * pmol_per_mol
    vmax = vmax * pmol_per_mol
    lon, lat, topo = sp.parse_STEM_coordinates(
        os.path.join(os.environ['SARIKA_INPUT'], 'TOPO-124x124.nc'))
    fsoil = maskoceans(lon, lat, fsoil)
    norm = midpt_norm.MidpointNormalize(midpoint=0.0)
    cm = map.map.pcolor(
        lon,
        lat,
        fsoil,
        vmin=vmin,  # np.nanmin(fsoil),
        vmax=vmax,  # np.nanmax(fsoil),
        norm=norm,
        cmap=plt.get_cmap('RdGy_r'),
        latlon=True)
    cb = plt.colorbar(cm,
                      ax=map.ax_map,
                      extend='both',
                      format=FuncFormatter(scinot_format.scinot_format))
    cb.solids.set_edgecolor("face")
    cb.ax.set_title('pmol COS m$^{-2}$ mon$^{-1}$', fontdict={'fontsize': 8})
Example #26
0
    ax.plot(this_dd)
    ax.set_xlabel('hours since 1 July 2008 00:00')
    ax.set_ylabel('surface [COS] drawdown, ppt')
    ax.text(
        1200, 0.9 * this_dd.max(), 'mean (10 Jul - 31 Aug): {:0.1f}'.format(
            this_dd[240:].squeeze().mean()))
    ax.text(
        1200, 0.8 * this_dd.max(), 'median (10 Jul - 31 Aug): {:0.1f}'.format(
            np.median(this_dd[240:].squeeze())))
    ax.set_title(sitename)
    fig.savefig('/global/homes/t/twhilton/plots/{}_dd.pdf'.format(sitename))


cos_clim = sp.parse_STEM_var(
    nc_fname=
    '/project/projectdirs/m2319/STEM_Runs/STEM_NAmerica_Climatological_Bounds/output/AQOUT.climatological_bnd.nc',
    t0=datetime(2008, 7, 1),
    t1=datetime(2008, 8, 31, 23, 59, 59),
    varname='CO2_TRACER1')

nha_x = 33
nha_y = 70

cma_x = 29
cma_y = 60

sca_x = 23
sca_y = 44

molecules_m3_to_ppt = 1e12
cos_sca = cos_clim['data'][:, :, sca_x, sca_y] * molecules_m3_to_ppt
def get_JulAug_total_flux(which_flux='GPP', models=None):
    """
    calculate total July and August flux for 124 by 124 STEM domain
    for either (1) gross primary productivity or (2) COS plant flux.
    Fluxes are calculated for one or more model runs according to the
    models input parameter.

    INPUT PARAMETERS:
    flux: string; {GPP} | fCOS
    models: tuple of strings; model runs for which to calculate
        fluxes.  All elements must be members of
        stem_pytools.ecampbell300_data_paths.get_runs().  If
        unspecified fluxes are calculated for all models listed by
        get_runs().

    RETURN VALUE:
    A dict of 124 by 124 arrays containing fluxes.  Dict keys are the
    model runs specified by models input parameter.  Units are
    petagrams C m-2 for GPP; picomoles m-2 for fCOS.
    """
    Jul1 = datetime(2008, 7, 1)
    Aug31 = datetime(2008, 8, 31, 23, 59, 59)

    runs = ndp.get_runs()

    if models is None:
        models = runs.keys()
    # models.sort()

    flux_mean = {}
    flux_total = {}
    for k in models:

        C_mol_per_g = (1.0 / 12.0107)
        umol_per_mol = 1e6
        g_per_kg = 1e3
        C_umol_per_kg = g_per_kg * C_mol_per_g * umol_per_mol
        Pg_per_kg = 1e-12
        t0 = Jul1
        t1 = Aug31

        if 'canibis' in k:
            # Can-IBIS timestep is monthly; calculate seconds per month
            s_per_tstep = 60 * 60 * 24 * (365 / 12)
        elif 'SiB' in k:
            # SiB timestep is hourly; calculate seconds per hour
            s_per_tstep = 60 * 60
        elif 'casa' in k:
            # CASA-GFED3 timestep is hourly; calculate seconds per 3 hours
            s_per_tstep = 3 * 60 * 60
        elif k == 'Fsoil_Kettle':
            # kettle soil fluxes are daily
            s_per_tstep = 60 * 60 * 24
        elif k == 'Fsoil_Hybrid5Feb':
            # Whelan soil fluxes are 6-hourly
            s_per_tstep = 60 * 60 * 6
        else:
            raise ValueError('don''t have timestep for {}'.format(k))

        if which_flux is 'GPP':
            gross_flux_varname = sp.get_CO2grossflux_varname(runs[k].gpp_path)
            print 'reading ', runs[k].gpp_path
            flux = sp.parse_STEM_var(nc_fname=runs[k].gpp_path,
                                     varname=gross_flux_varname,
                                     t0=t0,
                                     t1=t1)
            gpp_mean = flux['data'].mean(axis=0).squeeze()
            print 'mean GPP before units convert {} min: {}, max {}'.format(
                k, gpp_mean.min(), gpp_mean.max())

            if 'SiB' in k:
                # SiB units are mol m-2 s-1; convert mol to umol now
                flux['data'] = flux['data'] * umol_per_mol
            else:
                # convert GPP from Kg C m-2 s-1 to umol m-2 s-1
                flux['data'] = flux['data'] * C_umol_per_kg
            gpp_mean = flux['data'].mean(axis=0).squeeze()
            print 'mean GPP after units convert {} min: {}, max {}'.format(
                k, gpp_mean.min(), gpp_mean.max())

        elif which_flux is 'fCOS':
            gross_flux_varname = 'cos'
            print 'reading ', runs[k].fcos_path
            flux = sp.parse_STEM_var(nc_fname=runs[k].fcos_path,
                                     varname=gross_flux_varname,
                                     t0=t0,
                                     t1=t1)
            # convert fCOS from mol m-2 s-1 to pmol m-2 s-1
            pmol_per_mol = 1e12
            flux['data'] = flux['data'] * pmol_per_mol
            print('model: {}; mean fCOS: {}\n'.format(k,
                                                      np.mean(flux['data'])))

        flux_mean[k] = flux['data'].squeeze().mean(axis=0)
        # flux_mean[k] = ma.masked_less(flux_mean[k], -1e20)
        # calculate total flux in Pg C month-1
        m2_per_cell = 6e4 * 6e4  # STEM cells are 60 km per side
        months_in_analysis = 2

        flux_total[k] = (flux['data'].squeeze().sum(axis=0) *
                         s_per_tstep *
                         m2_per_cell *
                         (1.0 / C_umol_per_kg) *
                         Pg_per_kg *
                         (1.0 / months_in_analysis))

        if flux_mean[k].sum() < 0:
            flux_mean[k] = flux_mean[k] * -1.0
    return (flux_mean, flux_total)
    this_dd = dd[..., x, y].squeeze()
    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(15, 8))
    ax.plot(this_dd)
    ax.set_xlabel('hours since 1 July 2008 00:00')
    ax.set_ylabel('surface [COS] drawdown, ppt')
    ax.text(1200, 0.9 * this_dd.max(),
            'mean (10 Jul - 31 Aug): {:0.1f}'.format(
                this_dd[240:].squeeze().mean()))
    ax.text(1200, 0.8 * this_dd.max(),
            'median (10 Jul - 31 Aug): {:0.1f}'.format(
                np.median(this_dd[240:].squeeze())))
    ax.set_title(sitename)
    fig.savefig('/global/homes/t/twhilton/plots/{}_dd.pdf'.format(sitename))

cos_clim = sp.parse_STEM_var(nc_fname='/project/projectdirs/m2319/STEM_Runs/STEM_NAmerica_Climatological_Bounds/output/AQOUT.climatological_bnd.nc',
                             t0=datetime(2008, 7, 1),
                             t1=datetime(2008, 8, 31, 23, 59, 59),
                             varname='CO2_TRACER1')

nha_x = 33
nha_y = 70

cma_x = 29
cma_y = 60

sca_x = 23
sca_y = 44

molecules_m3_to_ppt = 1e12
cos_sca = cos_clim['data'][:, :, sca_x, sca_y] * molecules_m3_to_ppt

cmap, norm = colormap_nlevs.setup_colormap(vmin=cos_sca.min() - 1,
import os.path
import os
from datetime import datetime
from stem_pytools import STEM_parsers as sp
from stem_pytools.noaa_ocs import get_STEMZ_height
from timutils import midpt_norm
import brewer2mpl

bd_fname = os.path.join(os.getenv('SARIKA_INPUT'),
                        'bdv-124x124-cos-pctm_2008_2009.nc')
topo_fname = os.path.join(os.getenv('SARIKA_INPUT'), 'TOPO-124x124.nc')
wrf_fname = os.path.join(os.getenv('SARIKA_INPUT'),
                         'wrfheight-124x124-22levs.nc')

bd = sp.parse_STEM_var(bd_fname,
                       varname='CO2_TRACER1',
                       t0=datetime(2008, 7, 1),
                       t1=datetime(2008, 9, 1))

w_bnd_tavg = np.mean(bd['data'][:, :, -125:-1], axis=0) * 1000

stemlon, stemlat, topo = sp.parse_STEM_coordinates(topo_fname)
agl, asl = get_STEMZ_height(topo_fname, wrf_fname)

cos_norm = midpt_norm.MidpointNormalize(midpoint=450)
cos_cmap = brewer2mpl.get_map('PuOr', 'diverging', 8).mpl_colormap

fig, ax = plt.subplots()
lat = stemlat[:, -1]
ax.set_xlim([lat.min(), lat.max()])
cm = ax.pcolormesh(lat,
                   agl[:, :, -1],
def assemble_data(model_runs=None, pickle_fname=None):
    """calculate and save to a cPickle file:
    (1) daily mid-day [COS] mean
    (2) daily mid-day [COS] standard deviation
    (3) timestamps associated with (1) and (2)

    the data are placed in a dict and saved to a user-specified
    cpickle file.

    INPUT PARAMETERS
    model_runs: dict of STEMRun objects.  If unspecified the default
        is the output of stem_pytools.NERSC_data_paths.get_runs()
    pickle_fname: full path of the cpickle file to create.  If
        unspecified the default is
        /home/thilton/Data/STEM/aq_out_data.cpickle

    OUTPUT PARAMETERS:
    all_data: dict containing (1), (2), and (3) above.

    """

    warnings.warn('assemble_data is deprecated and will be removed in'
                  ' the future.  Please use '
                  'aqout_postprocess.aqout_container instead')

    if model_runs is None:
        model_runs = ndp.get_runs()

    t = []
    cos_mean = []
    cos_std = []

    for k, run in model_runs.items():
        t0 = datetime.now()
        print 'processing {}'.format(k)
        this_cos = sp.parse_STEM_var(run.aqout_path,
                                     varname='CO2_TRACER1',
                                     t0=datetime(2008, 7, 8),
                                     t1=datetime(2008, 8, 31, 23, 59, 59))
        t_data = pd.DatetimeIndex(this_cos['t'], freq='1H')

        this_t, this_mean = daily_window_stats(t_data,
                                               this_cos['data'],
                                               is_midday,
                                               np.mean)
        this_t, this_std = daily_window_stats(t_data,
                                              this_cos['data'],
                                              is_midday,
                                              np.std)
        t.append(this_t)
        cos_mean.append(this_mean)
        cos_std.append(this_std)
        print 'finished {}, time: {}'.format(k, str(datetime.now() - t0))

    t_dict = {key: value for key, value in zip(model_runs.keys(), t)}
    cos_mean_dict = {key: value for key, value in zip(model_runs.keys(),
                                                      cos_mean)}
    cos_std_dict = {key: value for key, value in zip(model_runs.keys(),
                                                     cos_std)}
    all_data_dict = {'t': t_dict,
                     'cos_mean': cos_mean_dict,
                     'cos_std': cos_std_dict}
    outfile = open(pickle_fname, 'wb')
    cPickle.dump(all_data_dict, outfile, protocol=2)
    outfile.close()

    return(all_data_dict)

if __name__ == "__main__":

    ffmpeg_present = check_for_ffmpeg()
    if ffmpeg_present is False:
        sys.exit("ffmpeg not found. Exiting now.")

    hours_in_day = 24
    data_dir = os.path.join('/project', 'projectdirs', 'm2319', 'STEM_Runs',
                            'STEM_NAmerica_Climatological_Bounds', 'output')
    outfile = 'climatological_bounds_TEST.mp4'

    cos = sp.parse_STEM_var(nc_fname=os.path.join(
        data_dir, 'AQOUT.climatological_bnd.nc'),
                            t0=datetime(2008, 7, 1),
                            t1=datetime(2008, 8, 31, 23, 59, 59),
                            varname='CO2_TRACER1')
    dd = calc_STEM_COS_drawdown(cos['data'])
    m, fig, ax, cbar_ax, map_data = map_init(dd)

    im_ani = animation.FuncAnimation(
        fig,
        func=map_update,
        frames=len(cos['t']),
        interval=100,
        # blit=True,  # only update parts that changed
        fargs=[m, fig, ax, cbar_ax, cos['t'], dd, map_data])

    im_ani.save(outfile, metadata={'artist': 'STEM'}, bitrate=100000)
    plt.close(fig)