def trend_surface_model_kriging(obs_data, wrf_data, mu_mod):
    """
    Trend surface model kriging, which assumes spatially uncorrelated errors.
    The kriging results in the matrix K, which contains the kriged observations
    and the matrix V, which contains the kriging variance.
    """
    Nobs = len(obs_data)
    K = np.zeros_like(mu_mod)
    V = np.zeros_like(mu_mod)
    mu_obs = np.zeros((Nobs,))

    for (obs, i) in zip(obs_data, range(Nobs)):
        mu_obs[i] = mu_mod[obs.get_nearest_grid_point()]

    # FIXME: we assume that the measurement variance is the same for all stations
    sigma2 = obs_data[0].get_measurement_variance()

    # In a TSM, the kriging predictor is the same as the estimator
    K[:] = mu_mod

    # precompute the inverse of the dot product
    XtX_1 = 1.0 / np.sum(mu_obs * mu_obs)

    # We compute the kriging variance for each point (covariates should be used but
    # since mu_mod is a scaled version of the covariates, the result is unchanged)
    for pos in np.ndindex(V.shape):
        V[pos] = sigma2 * (1 + mu_mod[pos] * XtX_1 * mu_mod[pos])

    diagnostics().push("skdm_cov_cond", 1.0)

    return K, V
def trend_surface_model_kriging(obs_data, wrf_data, mu_mod):
    """
    Trend surface model kriging, which assumes spatially uncorrelated errors.
    The kriging results in the matrix K, which contains the kriged observations
    and the matrix V, which contains the kriging variance.
    """
    Nobs = len(obs_data)
    K = np.zeros_like(mu_mod)
    V = np.zeros_like(mu_mod)
    mu_obs = np.zeros((Nobs, ))

    for (obs, i) in zip(obs_data, range(Nobs)):
        mu_obs[i] = mu_mod[obs.get_nearest_grid_point()]

    # FIXME: we assume that the measurement variance is the same for all stations
    sigma2 = obs_data[0].get_measurement_variance()

    # In a TSM, the kriging predictor is the same as the estimator
    K[:] = mu_mod

    # precompute the inverse of the dot product
    XtX_1 = 1.0 / np.sum(mu_obs * mu_obs)

    # We compute the kriging variance for each point (covariates should be used but
    # since mu_mod is a scaled version of the covariates, the result is unchanged)
    for pos in np.ndindex(V.shape):
        V[pos] = sigma2 * (1 + mu_mod[pos] * XtX_1 * mu_mod[pos])

    diagnostics().push("skdm_cov_cond", 1.0)

    return K, V
def simple_kriging_data_to_model(obs_data, obs_stds, mu_mod, wrf_data,
                                 mod_stds, t):
    """
    Simple kriging of data points to model points.  The kriging results in
    the matrix K, which contains the kriged observations and the matrix V,
    which contains the kriging variance.
    """
    mlons, mlats = wrf_data.get_lons(), wrf_data.get_lats()
    K = np.zeros_like(mlons)
    V = np.zeros_like(mlons)
    Nobs = len(obs_data)
    obs_vals = np.zeros((Nobs, ))
    station_lonlat = []
    gridndx = []
    mu_obs = np.zeros((Nobs, ))
    measV = np.zeros((Nobs, ))

    # accumulate the indices of the nearest grid points
    ndx = 0
    for obs in obs_data:
        gridndx.append(obs.get_nearest_grid_point())
        obs_vals[ndx] = obs.get_value()
        station_lonlat.append(obs.get_position())
        mu_obs[ndx] = mu_mod[obs.get_nearest_grid_point()]
        measV[ndx] = obs.get_measurement_variance()
        ndx += 1

    # compute observation residuals (using model fit from examine_station_data)
    res_obs = obs_vals - mu_obs

    # construct the covariance matrix and invert it
    C = np.asmatrix(construct_spatial_correlation_matrix2(station_lonlat))
    oS = np.asmatrix(np.diag(obs_stds))
    Sigma = oS.T * C * oS + np.diag(measV)
    SigInv = np.linalg.inv(Sigma)

    diagnostics().push("skdm_cov_cond", np.linalg.cond(Sigma))

    # run the kriging estimator for each model grid point
    K = np.zeros_like(mlats)
    cov = np.zeros_like(mu_obs)
    for p in np.ndindex(K.shape):
        # compute the covariance array anew for each grid point
        for k in range(Nobs):
            lon, lat = station_lonlat[k]
            cc = max(
                0.8565 -
                0.0063 * great_circle_distance(mlons[p], mlats[p], lon, lat),
                0.0)
            cov[k] = mod_stds[p] * cc * obs_stds[k]
        csi = np.dot(cov, SigInv)
        K[p] = mu_mod[p] + np.dot(csi, res_obs)
        V[p] = mod_stds[p]**2 - np.dot(csi, cov)

    return K, V
def simple_kriging_data_to_model(obs_data, obs_stds, mu_mod, wrf_data, mod_stds, t):
    """
    Simple kriging of data points to model points.  The kriging results in
    the matrix K, which contains the kriged observations and the matrix V,
    which contains the kriging variance.
    """
    mlons, mlats = wrf_data.get_lons(), wrf_data.get_lats()
    K = np.zeros_like(mlons)
    V = np.zeros_like(mlons)
    Nobs = len(obs_data)
    obs_vals = np.zeros((Nobs,))
    station_lonlat = []
    gridndx = []
    mu_obs = np.zeros((Nobs,))
    measV = np.zeros((Nobs,))

    # accumulate the indices of the nearest grid points
    ndx = 0
    for obs in obs_data:
        gridndx.append(obs.get_nearest_grid_point())
        obs_vals[ndx] = obs.get_value()
        station_lonlat.append(obs.get_position())
        mu_obs[ndx] = mu_mod[obs.get_nearest_grid_point()]
        measV[ndx] = obs.get_measurement_variance()
        ndx += 1

    # compute observation residuals (using model fit from examine_station_data)
    res_obs = obs_vals - mu_obs

    # construct the covariance matrix and invert it
    C = np.asmatrix(construct_spatial_correlation_matrix2(station_lonlat))
    oS = np.asmatrix(np.diag(obs_stds))
    Sigma = oS.T * C * oS + np.diag(measV)
    SigInv = np.linalg.inv(Sigma)

    diagnostics().push("skdm_cov_cond", np.linalg.cond(Sigma))

    # run the kriging estimator for each model grid point
    K = np.zeros_like(mlats)
    cov = np.zeros_like(mu_obs)
    for p in np.ndindex(K.shape):
        # compute the covariance array anew for each grid point
        for k in range(Nobs):
            lon, lat = station_lonlat[k]
            cc = max(0.8565 - 0.0063 * great_circle_distance(mlons[p], mlats[p], lon, lat), 0.0)
            cov[k] = mod_stds[p] * cc * obs_stds[k]
        csi = np.dot(cov, SigInv)
        K[p] = mu_mod[p] + np.dot(csi, res_obs)
        V[p] = mod_stds[p] ** 2 - np.dot(csi, cov)

    return K, V
 def __init__(self, lock_gamma = None):
     self.lock_gamma = lock_gamma != None
     self.gamma = 1.0 if lock_gamma == None else lock_gamma
     
     # configure diagnostics
     diagnostics().push("mfm_lock_gamma", lock_gamma)
     diagnostics().configure_tag("mfm_res_avg", True, True, True)
     diagnostics().configure_tag("mfm_gamma", True, True, True)
     diagnostics().configure_tag("mfm_mape", True, True, True)
    def __init__(self, lock_gamma=None):
        self.lock_gamma = lock_gamma != None
        self.gamma = 1.0 if lock_gamma == None else lock_gamma

        # configure diagnostics
        diagnostics().push("mfm_lock_gamma", lock_gamma)
        diagnostics().configure_tag("mfm_res_avg", True, True, True)
        diagnostics().configure_tag("mfm_gamma", True, True, True)
        diagnostics().configure_tag("mfm_mape", True, True, True)
    def fit_to_data(self, covar, obs, Sigma = None):
        """
        Fit the covariates to the observations using a general least squares
        approach that works for universal kriging (general covariance)
        and for trend surface modelling (diagonal covariance).

        The covariates must already correspond to observation locations.

        Sigma is the covariance matrix of the errors.
        """

        # gather observation data and corresponding model data     
        # FIXME: doing an inverse here instead of a linear solve as I am lazy
        # and I know that matrix is well conditioned
        XtW = np.dot(covar.T, Sigma) if Sigma is not None else covar.T
        print XtW.shape

        XtWX_1 = np.linalg.inv(np.dot(XtW, covar))
        print XtWX_1.shape
    
        # compute the weighted regression
        print obs.shape
        gamma = np.dot(XtWX_1, np.dot(XtW, obs))

        # push diagnostics out
        diagnostics().push("mfm_res_avg", np.mean(obs - gamma * covar))
        diagnostics().push("mfm_gamma", gamma)
        diagnostics().push("mfm_mape", np.mean(np.abs(obs - gamma * covar)))
        
        # if the gamma is not locked, then store the new best fit
        if not self.lock_gamma:
            self.gamma = gamma
    def fit_to_data(self, covar, obs, Sigma=None):
        """
        Fit the covariates to the observations using a general least squares
        approach that works for universal kriging (general covariance)
        and for trend surface modelling (diagonal covariance).

        The covariates must already correspond to observation locations.

        Sigma is the covariance matrix of the errors.
        """

        # gather observation data and corresponding model data
        # FIXME: doing an inverse here instead of a linear solve as I am lazy
        # and I know that matrix is well conditioned
        XtW = np.dot(covar.T, Sigma) if Sigma is not None else covar.T
        print XtW.shape

        XtWX_1 = np.linalg.inv(np.dot(XtW, covar))
        print XtWX_1.shape

        # compute the weighted regression
        print obs.shape
        gamma = np.dot(XtWX_1, np.dot(XtW, obs))

        # push diagnostics out
        diagnostics().push("mfm_res_avg", np.mean(obs - gamma * covar))
        diagnostics().push("mfm_gamma", gamma)
        diagnostics().push("mfm_mape", np.mean(np.abs(obs - gamma * covar)))

        # if the gamma is not locked, then store the new best fit
        if not self.lock_gamma:
            self.gamma = gamma
def run_module():

    # configure diagnostics
    init_diagnostics("results/kriging_test_diagnostics.txt")
    diagnostics().configure_tag("skdm_obs_res", True, True, True)
    diagnostics().configure_tag("skdm_obs_res_mean", True, True, True)

    wrf_data = WRFModelData(
        '../real_data/witch_creek/realfire03_d04_20071022.nc')

    # read in vars
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    tm = wrf_data.get_times()
    rain = wrf_data['RAINNC']
    Ed, Ew = wrf_data.get_moisture_equilibria()

    # obtain sizes
    Nt = rain.shape[0]
    dom_shape = lat.shape
    locs = np.prod(dom_shape)

    # load station data, match to grid points and build observation records
    # load station data from files
    tz = pytz.timezone('US/Pacific')
    stations = [
        Station(os.path.join(station_data_dir, s), tz, wrf_data)
        for s in station_list
    ]
    obs_data = build_observation_data(stations, 'fuel_moisture', wrf_data)

    # construct initial vector
    mfm = MeanFieldModel()

    # set up parameters
    mod_res_std = np.ones_like(Ed[0, :, :]) * 0.05
    obs_res_std = np.ones((len(stations), )) * 0.1

    # construct a basemap representation of the area
    lat_rng = (np.min(lat), np.max(lat))
    lon_rng = (np.min(lon), np.max(lon))
    m = Basemap(llcrnrlon=lon_rng[0],
                llcrnrlat=lat_rng[0],
                urcrnrlon=lon_rng[1],
                urcrnrlat=lat_rng[1],
                projection='mill')

    plt.figure(figsize=(10, 6))

    # run model
    ndx = 1
    for t in range(1, Nt):
        model_time = wrf_data.get_times()[t]
        E = 0.5 * (Ed[t, :, :] + Ew[t, :, :])

        # if we have an observation somewhere in time, run kriging
        if model_time in obs_data:
            print("Time: %s, step: %d" % (str(model_time), t))

            mfm.fit_to_data(E, obs_data[model_time])
            Efit = mfm.predict_field(E)

            # krige data to observations
            K, V = simple_kriging_data_to_model(obs_data[model_time],
                                                obs_res_std, Efit, wrf_data,
                                                mod_res_std, t)

            plt.clf()
            plt.subplot(2, 2, 1)
            render_spatial_field(m, lon, lat, Efit, 'Equilibrium')
            plt.clim([0.0, 0.2])
            plt.colorbar()

            plt.subplot(2, 2, 2)
            render_spatial_field(m, lon, lat, K, 'Kriging field')
            plt.clim([0.0, 0.2])
            plt.colorbar()

            plt.subplot(2, 2, 3)
            render_spatial_field(m, lon, lat, V, 'Kriging variance')
            plt.clim([0.0, np.max(V)])
            plt.colorbar()

            plt.subplot(2, 2, 4)
            render_spatial_field(m, lon, lat, K - Efit,
                                 'Kriging vs. mean field residuals')
            #            plt.clim([0.0, np.max()])
            plt.colorbar()

            plt.savefig('model_outputs/kriging_test_t%03d.png' % (ndx))
            ndx += 1
    cnt = 0
    random_representations = numpy.zeros((wordmap.len, HYPERPARAMETERS["REPRESENTATION_SIZE"]))

    context_vectors = generate_context_vectors()

    for tokens in trainingsentences():
        for i in range(len(tokens)):
            for j, context in enumerate(HYPERPARAMETERS["CONTEXT_TYPES"]):
                for k in context:
                    tokidx = i + k
                    if tokidx < 0 or tokidx >= len(tokens): continue
                    random_representations[tokens[i]] += context_vectors[j][tokens[tokidx]]
        cnt += 1
        if cnt % 10000 == 0:
            diagnostics.diagnostics(cnt, random_representations)

    logging.info("DONE. Dividing embeddings by their standard deviation...")
    random_representations = random_representations * (1. / numpy.std(random_representations))
    diagnostics.diagnostics(cnt, random_representations)
    diagnostics.visualizedebug(cnt, random_representations, rundir, newkeystr)

    outfile = os.path.join(rundir, "random_representations")
    if newkeystr != "":
        verboseoutfile = os.path.join(rundir, "random_representations%s" % newkeystr)
        logging.info("Writing representations to %s, and creating link %s" % (outfile, verboseoutfile))
        os.system("ln -s random_representations %s " % (verboseoutfile))
    else:
        logging.info("Writing representations to %s, not creating any link because of default settings" % outfile)

    o = open(outfile, "wt")
Esempio n. 11
0
#!/usr/bin/python

from diagnostics import diagnostics, known_compilers, FontError

diagnostics = diagnostics()


class Compiler:
    def __init__(self, infile, outfile, compiler=None):
        self.infile = infile
        self.outfile = outfile
        if compiler:
            if compiler in known_compilers and diagnostics[compiler]:
                self.compile = getattr(self, compiler)
            else:
                raise FontError(compiler, diagnostics)
        else:
            if diagnostics['fontforge']:
                self.compile = self.fontforge
            elif diagnostics['afdko']:
                self.compile = self.afdko
            else:
                raise FontError(diagnostics=diagnostics)

    def fontforge(self):
        import fontforge
        font = fontforge.open(self.infile)
        font.generate(self.outfile, flags=("round"))

    def afdko(self):
        import ufo2fdk
Esempio n. 12
0
def run_module():

    # read in configuration file to execute run
    print("Reading configuration from [%s]" % sys.argv[1])

    with open(sys.argv[1]) as f:
        cfg = eval(f.read())

    # ensure output path exists
    if not os.path.isdir(cfg['output_dir']):
        os.mkdir(cfg['output_dir'])

    # configure diagnostics
    init_diagnostics(
        os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))

    # Trend surface model diagnostics
    diagnostics().configure_tag("kriging_cov_cond", True, True, True)
    diagnostics().configure_tag("s2_eta_hat", True, True, True)
    diagnostics().configure_tag("kriging_rmse", True, True, True)
    diagnostics().configure_tag("kriging_beta", True, True, True)
    diagnostics().configure_tag("kriging_iters", False, True, True)
    diagnostics().configure_tag("kriging_subzero_s2_estimates", False, True,
                                True)
    diagnostics().configure_tag("fm10_kriging_var", True, True, True)

    diagnostics().configure_tag("f0_summary", True, True, True)
    diagnostics().configure_tag("f1_summary", True, True, True)
    diagnostics().configure_tag("f2_summary", True, True, True)
    diagnostics().configure_tag("f3_summary", True, True, True)

    # Assimilation parameters
    diagnostics().configure_tag("K0_summary", True, True, True)
    diagnostics().configure_tag("K1_summary", True, True, True)
    diagnostics().configure_tag("K2_summary", True, True, True)
    diagnostics().configure_tag("K3_summary", True, True, True)
    diagnostics().configure_tag("assim_info", False, False, True)

    # Model forecast, analysis and non-assimilated model: state, covariance, errors
    diagnostics().configure_tag("fm10f_rmse", True, True, True)
    diagnostics().configure_tag("fm10na_rmse", True, True, True)

    # all simulation times and all assimilation times (subset)
    diagnostics().configure_tag("mta", False, True, True)
    diagnostics().configure_tag("mt", False, True, True)

    # observation values and their nearest grid points
    diagnostics().configure_tag("obs_vals", False, True, True)
    diagnostics().configure_tag("obs_ngp", False, True, True)

    # in test mode, we will emit observations at the target station
    # our predictions, the nearest grid point and the test station id
    diagnostics().configure_tag("test_obs", True, True, True)
    diagnostics().configure_tag("test_pred", True, True, True)
    diagnostics().configure_tag("test_ngp", True, True, True)
    diagnostics().configure_tag("test_station_id", True, True, True)

    ### Load and preprocess WRF model data

    # load WRF data
    wrf_data = WRFModelData(cfg['wrf_output'],
                            ['T2', 'Q2', 'PSFC', 'RAINNC', 'RAINC', 'HGT'])
    wrf_data.slice_field('HGT')

    # read in spatial and temporal extent of WRF variables
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    hgt = wrf_data['HGT']
    tm = wrf_data.get_gmt_times()
    Nt = cfg['Nt'] if cfg.has_key('Nt') and cfg['Nt'] is not None else len(tm)
    dom_shape = lat.shape
    print('INFO: domain size is %d x %d grid points.' % dom_shape)
    print('INFO: domain extent is lats (%g to %g) lons (%g to %g).' %
          (np.amin(lat), np.amax(lat), np.amin(lon), np.amax(lon)))

    # if writing is requested, open output file and set up dimensions
    if cfg['write_fields'] not in ['all', 'fmc_gc', 'none']:
        error('FATAL: write_fields must be one of all, fmc_gc or none.')
    if cfg['write_fields'] == 'none':
        cfg['write_fields'] = False
    out_file = None
    ncfmc_gc, ncfm10a, ncfm10aV, ncfm10f, cnfm10fV, ncfm10na = None, None, None, None, None, None
    nctsmV, ncKg = None, None
    if cfg['write_fields']:
        out_file = netCDF4.Dataset(cfg['output_dir'] + '/fields.nc', 'w')
        out_file.createDimension('Time', None)
        out_file.createDimension('fuel_moisture_classes_stag', 5)
        out_file.createDimension('south_north', dom_shape[0])
        out_file.createDimension('west_east', dom_shape[1])
        ncfmc_gc = out_file.createVariable(
            'FMC_GC', 'f4',
            ('Time', 'fuel_moisture_classes_stag', 'south_north', 'west_east'))
        if cfg['write_fields'] == 'all':
            ncfm10a = out_file.createVariable(
                'fm10a', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10aV = out_file.createVariable(
                'fm10a_var', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10na = out_file.createVariable(
                'fm10na', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10f = out_file.createVariable(
                'fm10f', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10fV = out_file.createVariable(
                'fm10f_var', 'f4', ('Time', 'south_north', 'west_east'))
            nctsmV = out_file.createVariable(
                'tsm_var', 'f4', ('Time', 'south_north', 'west_east'))
            ncKg = out_file.createVariable(
                'kalman_gain', 'f4', ('Time', 'south_north', 'west_east'))
            print('INFO: opened fields.nc for writing ALL output fields.')
        else:
            print('INFO: opened field.nc for writing FMC_GC only.')

    test_mode = (cfg['run_mode'] == 'test')
    tgt_station = None
    if cfg['run_mode'] == 'test':
        print('INFO: running in TEST mode! Will perform leave-one-out tesing.')
        tgt_station_id = cfg['target_station_id']
        diagnostics().push('test_station_id', tgt_station_id)
    elif cfg['run_mode'] == 'production':
        print(
            'INFO: running in PRODUCTION mode! Using all observation stations.'
        )
    else:
        error('FATAL: invalid run mode! Must be "test" or "production".')

    # determine simulation times
    tm_start = parse_datetime(
        cfg['start_time']) if cfg['start_time'] is not None else tm[0]
    tm_end = parse_datetime(
        cfg['end_time']) if cfg['end_time'] is not None else tm[-1]

    # if the required start time or end time are outside the simulation domain, exit with an error
    if tm_start < tm[0] or tm_end > tm[-1]:
        print('FATAL: invalid time range, required [%s-%s], availble [%s-%s]' %
              (str(tm_start), str(tm_end), str(tm[0]), str(tm[-1])))
        sys.exit(2)

    print('INFO: time limits are %s to %s\nINFO: simulation is from %s to %s' %
          (str(tm_start), str(tm_end), str(tm[0]), str(tm[-1])))

    # retrieve dynamic covariates and remove mean at each time point for T2 and PSFC
    T2 = wrf_data['T2']
    #T2 -= np.mean(np.mean(T2,axis=0),axis=0)[np.newaxis,np.newaxis,:]

    PSFC = wrf_data['PSFC']
    #PSFC -= np.mean(np.mean(PSFC,axis=0),axis=0)[np.newaxis,np.newaxis,:]

    # numerical fix - if it rains at an intensity of less than 0.001 per hour, set rain to zero
    # also, use log(rain + 1) to prevent wild trend surface model predictions when stations see little rain
    # but elsewhere there is too much rain
    # without this, numerical errors in trend surface model may pop up
    rain = wrf_data['RAIN']
    #rain[rain < 0.01] = 0.0
    rain = np.log(rain + 1.0)

    # moisture equilibria are now computed from averaged Q,P,T at beginning and end of period
    Ed, Ew = wrf_data.get_moisture_equilibria()

    ### Load observation data from the stations

    # compute the diagonal distance between grid points
    grid_dist_km = great_circle_distance(lon[0, 0], lat[0, 0], lon[1, 1],
                                         lat[1, 1])
    print('INFO: diagonal distance in grid is %g' % grid_dist_km)

    # load station data from files
    with open(cfg['station_list_file'], 'r') as f:
        si_list = f.read().split('\n')

    si_list = filter(lambda x: len(x) > 0 and x[0] != '#',
                     map(string.strip, si_list))

    # for each station id, load the station
    stations = []
    for code in si_list:
        mws = MesoWestStation(code)
        mws.load_station_info(
            os.path.join(cfg["station_info_dir"], "%s.info" % code))
        mws.register_to_grid(wrf_data)
        if mws.get_dist_to_grid() < grid_dist_km / 2.0:
            print(
                'Station %s: lat %g lon %g nearest grid pt %s lat %g lon %g dist_to_grid %g'
                % (code, mws.lat, mws.lon, str(mws.grid_pt), lat[mws.grid_pt],
                   lon[mws.grid_pt], mws.dist_grid_pt))
            mws.load_station_data(
                os.path.join(cfg["station_data_dir"], "%s.obs" % code))
            if test_mode and mws.get_id() == tgt_station_id:
                tgt_station = mws
                print(
                    'INFO: in test mode, targeting station %s (removed from data pool).'
                    % tgt_station_id)
                diagnostics().push("test_ngp", mws.get_nearest_grid_point())
            else:
                stations.append(mws)

    print('Loaded %d stations (discarded %d stations, too far from grid).' %
          (len(stations), len(si_list) - len(stations)))

    if test_mode and tgt_station is None:
        error(
            'FATAL: in test mode, a station was removed that was not among accepted stations.'
        )

    # build the observation data
    obs_data_fm10 = build_observation_data(stations, 'FM')

    # build target data if in test mode
    tgt_obs_fm10 = None
    test_ngp = None
    if test_mode:
        test_ngp = tgt_station.get_nearest_grid_point()
        tgt_obs_fm10 = build_observation_data([tgt_station], 'FM')

    ### Initialize model and visualization

    # construct initial conditions from timestep 0
    E = 0.5 * (Ed[0, :, :] + Ew[0, :, :])

    # set up parameters
    Nk = 4  # we simulate 4 types of fuel
    Q = np.diag(cfg['Q'])
    P0 = np.diag(cfg['P0'])
    Tk = np.array([1.0, 10.0, 100.0, 1000.0]) * 3600
    dt = (tm[1] - tm[0]).seconds
    print("INFO: Computed timestep from WRF is is %g seconds." % dt)
    mresV = np.zeros_like(E)
    mid = np.zeros_like(E)
    Kg = np.zeros((dom_shape[0], dom_shape[1], len(Tk) + 2))

    # preprocess all static covariates
    cov_ids = cfg['covariates']
    Xd3 = len(cov_ids) + 1
    X = np.zeros((dom_shape[0], dom_shape[1], Xd3))
    Xr = np.zeros((dom_shape[0], dom_shape[1], Xd3))
    static_covar_map = {
        "lon": lon - np.mean(lon),
        "lat": lat - np.mean(lat),
        "elevation": hgt - np.mean(hgt),
        "constant": np.ones(dom_shape)
    }
    dynamic_covar_map = {"temperature": T2, "pressure": PSFC, "rain": rain}

    for i in range(1, Xd3):
        cov_id = cov_ids[i - 1]
        if cov_id in static_covar_map:
            print('INFO: found static covariate %s' % cov_id)
            Xr[:, :, i] = static_covar_map[cov_id]
        elif cov_id in dynamic_covar_map:
            print('INFO: found dynamic covariate %s' % cov_id)
        else:
            print('FATAL: unknown covariate %s encountered' % cov_id)
            sys.exit(2)

    print("INFO: there are %d covariates (including model state)" % Xd3)

    # retrieve assimilation time window
    assim_time_win = cfg['assimilation_time_window']

    print('GMM init: equilibrium (%g,%g,%g) and at 86,205 %g' %
          (np.amin(E), np.mean(E), np.amax(E), E[86, 205]))

    models = GridMoistureModel(
        E[:, :, np.newaxis][:, :, np.zeros((4, ), dtype=np.int)], Tk, P0)
    models_na = GridMoistureModel(
        E[:, :, np.newaxis][:, :, np.zeros((4, ), dtype=np.int)], Tk, P0)

    ###  Run model for each WRF timestep and assimilate data when available
    t_start, t_end = 1, len(tm) - 1
    while tm_start > tm[t_start]:
        t_start += 1
    while tm_end < tm[t_end]:
        t_end -= 1

    # the first FMC_GC value gets filled out with equilibria
    if cfg['write_fields']:
        for i in range(Nk):
            ncfmc_gc[0, i, :, :] = E

    print('INFO: running simulation from %s (%d) to %s (%d).' %
          (str(tm[t_start]), t_start, str(tm[t_end]), t_end))
    for t in range(t_start, t_end + 1):
        model_time = tm[t]
        print("INFO: time: %s, step: %d" % (str(model_time), t))

        diagnostics().push("mt", model_time)

        models_na.advance_model(Ed[t - 1, :, :], Ew[t - 1, :, :],
                                rain[t - 1, :, :], dt, Q)
        models.advance_model(Ed[t - 1, :, :], Ew[t - 1, :, :],
                             rain[t - 1, :, :], dt, Q)

        # extract fuel moisture contents [make a fresh copy every iteration!]
        f = models.get_state().copy()
        f_na = models_na.get_state().copy()

        # push 10-hr fuel state & variance of forecast
        if cfg['write_fields'] == 'all':
            ncfm10f[t, :, :] = models.get_state()[:, :, 1]
            ncfm10fV[t, :, :] = models.P[:, :, 1, 1]
            ncfm10na[t, :, :] = models_na.get_state()[:, :, 1]

        # examine the assimilated fields (if assimilation is activated)
        for i in range(4):
            diagnostics().push("f%d_summary" % i, (t, np.amin(
                f[:, :, i]), np.mean(f[:, :, i]), np.amax(f[:, :, i])))
            if np.any(f[:, :, i] < 0.0):
                print(
                    "WARN: in field %d there were %d negative moisture values !"
                    % (i, np.count_nonzero(f[:, :, i] < 0.0)))
                ind = np.unravel_index(np.argmin(f[:, :, i]), f.shape[:2])
                print(models.P[ind[0], ind[1], :, :])
                print("Full model state at position %d,%d:" % (ind[0], ind[1]))
                print(models.m_ext[ind[0], ind[1], :])
            if np.any(f[:, :, i] > 2.5):
                print(
                    "WARN: in field %d there were %d moisture values above 2.5!"
                    % (i, np.count_nonzero(f[:, :, i] > 2.5)))
                ind = np.unravel_index(np.argmax(f[:, :, i]), f.shape[:2])
                print(models.P[ind[0], ind[1], :, :])
                print("Full model state at position %d,%d:" % (ind[0], ind[1]))
                print(models.m_ext[ind[0], ind[1], :])

        if cfg['assimilate']:

            # run Kriging on each observed fuel type
            Kfs, Vfs, fns = [], [], []
            for obs_data, fuel_ndx in [(obs_data_fm10, 1)]:

                # run the kriging subsystem and the Kalman update only if have valid observations
                valid_times = [
                    z for z in obs_data.keys()
                    if abs(total_seconds(z - model_time)) < assim_time_win /
                    2.0
                ]
                print(
                    'INFO: there are %d valid times at model time %s for fuel index %d'
                    % (len(valid_times), str(model_time), fuel_ndx))
                if len(valid_times) > 0:

                    # add model time as time when assimilation occurred
                    diagnostics().push("mta", model_time)

                    # retrieve observations for current time
                    obs_valid_now = []
                    for z in valid_times:
                        obs_valid_now.extend(obs_data[z])

                    print(
                        'INFO: model time %s, assimilating %d observations.' %
                        (str(model_time), len(obs_valid_now)))

                    # construct covariates for this time instant
                    X[:, :, 0] = f[:, :, fuel_ndx]
                    for i in range(1, Xd3):
                        cov_id = cov_ids[i - 1]
                        if cov_id in static_covar_map:
                            X[:, :, i] = Xr[:, :, i]
                        elif cov_id in dynamic_covar_map:
                            F = dynamic_covar_map[cov_id]
                            X[:, :, i] = F[t, :, :]
                        else:
                            error('FATAL: found unknown covariate %s' % cov_id)

                    # find differences (residuals) between observed measurements and nearest grid points
                    obs_vals = [o.get_value() for o in obs_valid_now]
                    obs_ngp = [
                        o.get_nearest_grid_point() for o in obs_valid_now
                    ]
                    diagnostics().push("obs_vals", obs_vals)
                    diagnostics().push("obs_ngp", obs_ngp)

                    mod_vals = np.array(
                        [f[i, j, fuel_ndx] for i, j in obs_ngp])
                    mod_na_vals = np.array(
                        [f_na[i, j, fuel_ndx] for i, j in obs_ngp])
                    diagnostics().push("fm10f_rmse",
                                       np.mean((obs_vals - mod_vals)**2)**0.5)
                    diagnostics().push(
                        "fm10na_rmse",
                        np.mean((obs_vals - mod_na_vals)**2)**0.5)

                    # krige observations to grid points
                    Kf_fn, Vf_fn = fit_tsm(obs_valid_now, X)
                    if np.count_nonzero(Kf_fn > 2.5) > 0:
                        rain_t = dynamic_covar_map['rain'][t, :, :]
                        print(
                            'WARN: in TSM found %d values over 2.5, %d of those had rain, clamped to 2.5'
                            % (np.count_nonzero(Kf_fn > 2.5),
                               np.count_nonzero(
                                   np.logical_and(Kf_fn > 2.5, rain_t > 0.0))))
                        Kf_fn[Kf_fn > 2.5] = 2.5
                    if np.count_nonzero(Kf_fn < 0.0) > 0:
                        print(
                            'WARN: in TSM found %d values under 0.0, clamped to 0.0'
                            % np.count_nonzero(Kf_fn < 0.0))
                        Kf_fn[Kf_fn < 0.0] = 0.0

                    krig_vals = np.array([Kf_fn[ngp] for ngp in obs_ngp])
                    diagnostics().push("assim_info",
                                       (t, fuel_ndx, obs_vals, krig_vals,
                                        mod_vals, mod_na_vals))
                    diagnostics().push("fm10_kriging_var", (t, np.mean(Vf_fn)))

                    if cfg['write_fields'] == 'all':
                        nctsmV[t, :, :] = Vf_fn

                    # append to storage for kriged fields in this time instant
                    Kfs.append(Kf_fn)
                    Vfs.append(Vf_fn)
                    fns.append(fuel_ndx)

            # if there were any observations, run the kalman update step
            if len(fns) > 0:
                NobsClasses = len(fns)

                O = np.zeros((dom_shape[0], dom_shape[1], NobsClasses))
                V = np.zeros(
                    (dom_shape[0], dom_shape[1], NobsClasses, NobsClasses))

                for i in range(NobsClasses):
                    O[:, :, i] = Kfs[i]
                    V[:, :, i, i] = Vfs[i]

                # execute the Kalman update
                if len(fns) == 1:
                    models.kalman_update_single2(O, V, fns[0], Kg)
                else:
                    models.kalman_update(O, V, fns, Kg)

                # push new diagnostic outputs
                if cfg['write_fields'] == 'all':
                    ncKg[t, :, :] = Kg[:, :, 1]

                for i in range(4):
                    diagnostics().push(
                        "K%d_summary" % i,
                        (t, np.amin(Kg[:, :, i]), np.mean(
                            Kg[:, :, i]), np.amax(Kg[:, :, i])))
                    if np.any(models.get_state()[:, :, i] < 0.0):
                        print(
                            "WARN: in field %d there were %d negative moisture values !"
                            % (i,
                               np.count_nonzero(
                                   models.get_state()[:, :, i] < 0.0)))
                        ind = np.unravel_index(
                            np.argmin(models.get_state()[:, :, i]),
                            models.get_state().shape[:2])
                        print(models.P[ind[0], ind[1], :, :])
                        print(
                            "TSM input at given position: value %g variance %g"
                            % (O[ind[0], ind[1]], V[ind[0], ind[1]]))
                        print("Model state at given position:")
                        print(models.m_ext[ind[0], ind[1], :])

            # store post-assimilation (or forecast depending on whether observations were available) FM-10 state and variance
            if cfg['write_fields'] == 'all':
                ncfm10a[t, :, :] = models.get_state()[:, :, 1]
                ncfm10aV[t, :, :] = models.P[:, :, 1, 1]

            # we don't care if we assimilated or not, we always check our error on target station if in test mode
            if test_mode:
                valid_times = [
                    z for z in tgt_obs_fm10.keys()
                    if abs(total_seconds(z - model_time)) < assim_time_win /
                    2.0
                ]
                tgt_i, tgt_j = test_ngp
                diagnostics().push("test_pred", f[tgt_i, tgt_j, 1])
                if len(valid_times) > 0:
                    # this is our target observation [FIXME: this disregards multiple observations if multiple happen to be valid]
                    tgt_obs = tgt_obs_fm10[valid_times[0]][0]
                    obs = tgt_obs.get_value()
                    diagnostics().push("test_obs", obs)
                else:
                    diagnostics().push("test_obs", np.nan)

            # store data in wrf_file variable FMC_G
            if cfg['write_fields']:
                ncfmc_gc[t, :Nk, :, :] = np.transpose(
                    models.get_state()[:, :, :Nk], axes=[2, 0, 1])

        # store the diagnostics in a binary file when done
    diagnostics().dump_store(os.path.join(cfg['output_dir'],
                                          'diagnostics.bin'))

    # close the netCDF file (relevant if we did write into FMC_GC)
    if out_file is not None:
        out_file.close()
def universal_kriging_data_to_model(obs_data, obs_stds, m, wrf_data, mod_stds, t):
    """
    Universal kriging of data points to model points.  The kriging results in
    the matrix K, which contains the kriged observations and the matrix V,
    which contains the kriging variance.
    """
    mlons, mlats = wrf_data.get_lons(), wrf_data.get_lats()
    K = np.zeros_like(mlons)
    V = np.zeros_like(mlons)
    Nobs = len(obs_data)
    obs_vals = np.zeros((Nobs,))
    station_lonlat = []
    gridndx = []
    mu_obs = np.zeros((Nobs,))
    m_pred = np.zeros((Nobs,))
    measV = np.zeros((Nobs,))

    # accumulate the indices of the nearest grid points
    ndx = 0
    for obs in obs_data:
        gridndx.append(obs.get_nearest_grid_point())
        obs_vals[ndx] = obs.get_value()
        station_lonlat.append(obs.get_position())
        measV[ndx] = obs.get_measurement_variance()
        m_pred[ndx] = m[obs.get_nearest_grid_point()]
        ndx += 1

    # convert lists to column vectors
    m_pred = np.asmatrix(m_pred).T
    obs_vals = np.asmatrix(obs_vals).T

    # construct the covariance matrix and invert it
    C = np.asmatrix(construct_spatial_correlation_matrix2(station_lonlat))
    oS = np.asmatrix(np.diag(obs_stds))
    Sigma = oS.T * C * oS + np.diag(measV)
    SigInv = np.linalg.inv(Sigma)

    # estimate the fixed part of the model
    gamma = np.linalg.inv(m_pred.T * SigInv * m_pred) * m_pred.T * SigInv * obs_vals
    gamma = gamma[0, 0]
    mu_mod = m * gamma

    ndx = 0
    for obs in obs_data:
        mu_obs[ndx] = mu_mod[obs.get_nearest_grid_point()]
        ndx += 1

    # compute observation residuals (using model fit from examine_station_data)
    # and the mean absolute deviation
    res_obs = np.asmatrix(obs_vals - mu_obs).T
    mape = np.mean(np.abs(res_obs))

    diagnostics().push("skdm_cov_cond", np.linalg.cond(Sigma))

    # precompute some matrices
    xs = obs_vals.T * SigInv
    xsx_1 = 1.0 / (xs * obs_vals)

    # run the kriging estimator for each model grid point
    K = np.zeros_like(mlats)
    cov = np.asmatrix(np.zeros_like(mu_obs)).T
    for p in np.ndindex(K.shape):

        # compute the covariance array anew for each grid point
        for k in range(Nobs):
            lon, lat = station_lonlat[k]
            cc = max(0.8565 - 0.0063 * great_circle_distance(mlons[p], mlats[p], lon, lat), 0.0)
            cov[k, 0] = mod_stds[p] * cc * obs_stds[k]

        csi = SigInv * (cov - obs_vals * xsx_1 * (xs * cov - mu_mod[p]))
        K[p] = csi.T * obs_vals
        tmp = mu_mod[p] - cov.T * SigInv * obs_vals
        V[p] = mod_stds[p] ** 2 - cov.T * SigInv * cov + tmp * xsx_1 * tmp

    return K, V, gamma, mape
Esempio n. 14
0
        logging.info("CONTINUING FROM TRAINING STATE")
    except IOError:
        print >> sys.stderr, ("...FAILURE reading training state for %s %s" % (newkeystr, rundir))
        print >> sys.stderr, ("INITIALIZING")

        m = model.Model()
        cnt = 0
        epoch = 1
        get_train_minibatch = examples.TrainingMinibatchStream()
        logging.basicConfig(filename=logfile, filemode="w", level=logging.DEBUG)
        logging.info("INITIALIZING TRAINING STATE")

    logging.info(myyaml.dump(common.dump.vars_seq([hyperparameters, miscglobals])))

    #validate(0)
    diagnostics.diagnostics(cnt, m)
#    diagnostics.visualizedebug(cnt, m, rundir)
    while 1:
        logging.info("STARTING EPOCH #%d" % epoch)
        for ebatch in get_train_minibatch:
            cnt += len(ebatch)
        #    print [wordmap.str(id) for id in e]

            noise_sequences, weights = corrupt.corrupt_examples(m, ebatch)
            m.train(ebatch, noise_sequences, weights)

            #validate(cnt)
            if cnt % (int(1000./HYPERPARAMETERS["MINIBATCH SIZE"])*HYPERPARAMETERS["MINIBATCH SIZE"]) == 0:
                logging.info("Finished training step %d (epoch %d)" % (cnt, epoch))
#                print ("Finished training step %d (epoch %d)" % (cnt, epoch))
            if cnt % (int(100000./HYPERPARAMETERS["MINIBATCH SIZE"])*HYPERPARAMETERS["MINIBATCH SIZE"]) == 0:
Esempio n. 15
0
        logging.info("CONTINUING FROM TRAINING STATE")
    except IOError:
        print >> sys.stderr, ("...FAILURE reading training state for %s %s" % (newkeystr, rundir))
        print >> sys.stderr, ("INITIALIZING")

        m = model.Model()
        cnt = 0
        epoch = 1
        get_train_minibatch = examples.TrainingMinibatchStream()
        logging.basicConfig(filename=logfile, filemode="w", level=logging.DEBUG)
        logging.info("INITIALIZING TRAINING STATE")

    logging.info(myyaml.dump(common.dump.vars_seq([hyperparameters, miscglobals])))

    #validate(0)
    diagnostics.diagnostics(cnt, m)
#    diagnostics.visualizedebug(cnt, m, rundir)
    while 1:
        logging.info("STARTING EPOCH #%d" % epoch)
        for ebatch in get_train_minibatch:
            cnt += len(ebatch)
        #    print [wordmap.str(id) for id in e]
            m.train(ebatch)

            #validate(cnt)
            if cnt % (int(1000./HYPERPARAMETERS["MINIBATCH SIZE"])*HYPERPARAMETERS["MINIBATCH SIZE"]) == 0:
                logging.info("Finished training step %d (epoch %d)" % (cnt, epoch))
#                print ("Finished training step %d (epoch %d)" % (cnt, epoch))
            if cnt % (int(100000./HYPERPARAMETERS["MINIBATCH SIZE"])*HYPERPARAMETERS["MINIBATCH SIZE"]) == 0:
                diagnostics.diagnostics(cnt, m)
                if os.path.exists(os.path.join(rundir, "BAD")):
Esempio n. 16
0
def cell_classifier(image_file, cnn=None, save_diag=False, out_dir=''):

    vis_diag = False

    # OPEN THE image to be processed
    try:
        im = io.imread(image_file)  # read uint8 image
    except Exception:
        logging.info(image_file + ' does not exist')
        return []
    if im.ndim != 3:
        logging.info('not color image')
        return []
    """
    DIAGNOSTICS
    """
    diag = diagnostics.diagnostics(im, image_file, vis_diag=False)
    """
    CREATE OUTPUT AND DIAG DIRS
    """

    output_dir = diag.param.getOutDir(dir_name=os.path.join('output', out_dir))
    diag_dir = diag.param.getOutDir(dir_name=os.path.join('diag', out_dir))
    """
    RESIZE
    """
    hsv_resize, scale = imtools.imRescaleMaxDim(diag.hsv_corrected,
                                                diag.param.middle_size,
                                                interpolation=0)
    im_resize, scale = imtools.imRescaleMaxDim(diag.im_corrected,
                                               diag.param.middle_size,
                                               interpolation=0)
    """
    WBC nucleus masks
    """
    sat_tsh = max(diag.sat_q95, diag.param.wbc_min_sat)
    mask_nuc = detections.wbc_nucleus_mask(hsv_resize,
                                           diag.param,
                                           sat_tsh=sat_tsh,
                                           scale=scale,
                                           vis_diag=vis_diag,
                                           fig='')
    """
    CREATE WBC REGIONS
    """
    prop_wbc = detections.wbc_regions(mask_nuc, diag.param, scale=scale)
    """
    CELL FOREGORUND MASK
    """
    mask_cell = detections.cell_mask(hsv_resize,
                                     diag.param,
                                     scale=scale,
                                     mask=mask_nuc,
                                     init_centers=diag.cent_init,
                                     vis_diag=vis_diag,
                                     fig='cell_mask')
    """
    CELL MARKERS AnD REGIONS
    """
    markers_rbc, prop_rbc = detections.cell_markers_from_mask(
        mask_cell,
        diag.param,
        scale=scale,
        vis_diag=vis_diag,
        fig='cell_markers')
    """
    COUNTING
    """
    diag.measures['n_WBC'] = len(prop_wbc)
    diag.measures['n_RBC'] = len(prop_rbc)
    """
    PARAMETERS for WBC NORMALIZATION 
    """
    if mask_nuc.sum() > 0:
        pixs = im_resize[mask_nuc, ]
        diag.measures['nucleus_median_rgb'] = np.median(pixs, axis=0)
    """
    CHECK ERRORS
    """
    diag.checks()
    if len(diag.error_list) > 0:
        logging.info(image_file + ' is of wrong quality')
        diag.writeDiagnostics(diag_dir)
        return []
    """
    CREATE shapes
    """
    shapelist_WBC = []
    for p in prop_wbc:
        # centroid is in row,col
        pts = [(
            p.centroid[1] / scale +
            0.8 * p.major_axis_length * np.cos(theta * 2 * np.pi / 20) / scale,
            p.centroid[0] / scale +
            0.8 * p.major_axis_length * np.sin(theta * 2 * np.pi / 20) / scale)
               for theta in range(20)]
        #pts=[(p.centroid[1]/scale,p.centroid[0]/scale)]
        one_shape = ('None', 'circle', pts, 'None', 'None')

        # WBC classification
        # check if shape is fully contained in the image canvas
        #         if min((im.shape[1],im.shape[0])-np.max(one_shape[2],axis=0))<0\
        #                or min(np.min(one_shape[2],axis=0))<0:
        #            continue


        im_cropped,o,r=imtools.crop_shape(diag.im_corrected,one_shape,\
                                           diag.param.rgb_norm,diag.measures['nucleus_median_rgb'],\
                                           scale=1,adjust=True)
        if im_cropped is not None and cnn is not None:
            # do the actual classification
            if r[0] > 1.5 * diag.param.rbcR:
                wbc_label, pct = cnn.classify(im_cropped)
            else:
                wbc_label = ['un']
            # redefiniton of wbc type
            one_shape = (wbc_label[0], 'circle', pts, 'None', 'None')

        shapelist_WBC.append(one_shape)

    shapelist_RBC = []
    for p in prop_rbc:
        pts = [(p.centroid[1] / scale, p.centroid[0] / scale)]
        is_in_wbc = False
        for shape in shapelist_WBC:
            bb = Path(shape[2])
            intersect = bb.contains_points(pts)
            if intersect.sum() > 0:
                is_in_wbc = True
        if not is_in_wbc:
            one_shape = ('RBC', 'circle', pts, 'None', 'None')
            shapelist_RBC.append(one_shape)
    shapelist = shapelist_WBC
    shapelist.extend(shapelist_RBC)
    """
    REMOVE ANNOTATIONS CLOSE TO BORDER
    """
    shapelist = annotations.remove_border_annotations(shapelist, im.shape,
                                                      diag.param.border)

    head, tail = os.path.split(image_file)
    xml_file = os.path.join(output_dir, tail.replace('.bmp', ''))
    tmp = annotations.AnnotationWriter(head, xml_file,
                                       (im.shape[0], im.shape[1]))
    tmp.addShapes(shapelist)
    tmp.save()
    """
    CREATE and SAVE DIAGNOSTICS IMAGES
    """
    if save_diag:
        im_rbc = imtools.overlayImage(im_resize,
                                      markers_rbc, (1, 0, 0),
                                      1,
                                      vis_diag=vis_diag,
                                      fig='sat')
        im_detect = imtools.overlayImage(im_rbc,
                                         mask_nuc, (0, 0, 1),
                                         0.5,
                                         vis_diag=vis_diag,
                                         fig='nuc')

        #        border=np.zeros(im_resize.shape[0:2]).astype('uint8')
        #        border[0:diag.param.middle_border,:]=1
        #        border[-diag.param.middle_border-1:-1,:]=1
        #        border[:,0:diag.param.middle_border]=1
        #        border[:,-diag.param.middle_border-1:-1]=1
        #        im_detect=imtools.overlayImage(im_nuc,border>0,\
        #                (1,1,0),0.2,vis_diag=vis_diag,fig='detections')
        #        im_detect,scale=imtools.imRescaleMaxDim(im_detect,diag.param.middle_size,interpolation = 1)
        #
        diag.saveDiagImage(im_detect, 'detections', savedir=diag_dir)

        diag.writeDiagnostics(diag_dir)

    return shapelist
def run_module():
    
    # read in configuration file to execute run
    print("Reading configuration from [%s]" % sys.argv[1])
    
    with open(sys.argv[1]) as f:
        cfg = eval(f.read())
    
    # ensure output path exists
    if not os.path.isdir(cfg['output_dir']): 
        os.mkdir(cfg['output_dir'])
        
    # configure diagnostics        
    init_diagnostics(os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))
    diagnostics().configure_tag("skdm_obs_res", False, True, True)
    diagnostics().configure_tag("skdm_cov_cond", False, True, True)

    diagnostics().configure_tag("assim_mV", False, False, True)
    diagnostics().configure_tag("assim_K0", False, False, True)
    diagnostics().configure_tag("assim_K1", False, False, True)
    diagnostics().configure_tag("assim_data", False, False, True)
    diagnostics().configure_tag("assim_mresV", False, False, True)

    diagnostics().configure_tag("kriging_variance", False, False, True)
    diagnostics().configure_tag("kriging_obs_res_var", False, False, True)

    print("INFO: input file is [%s]." % cfg['input_file'])
    wrf_data = WRFModelData(cfg['input_file'], tz_name = 'US/Pacific')
    
    # read in vars
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    tm = wrf_data.get_local_times()
    rain = wrf_data['RAIN']
    Ed, Ew = wrf_data.get_moisture_equilibria()
    
    # find maximum moisture overall to set up visualization
#    maxE = max(np.max(Ed), np.max(Ew)) * 1.2
    maxE = 0.3
    
    # obtain sizes
    Nt = rain.shape[0]
    dom_shape = lat.shape
    
    # load station data from files
    tz = pytz.timezone('US/Pacific')
    stations = [StationAdam() for s in station_list]
    for (s,sname) in zip(stations, station_list):
        s.load_station_data(os.path.join(station_data_dir, sname), tz)
        s.register_to_grid(wrf_data)
        s.set_measurement_variance('fm10', 0.05)
    
    # build the observation data structure indexed by time
    obs_data_fm10 = build_observation_data(stations, 'fm10', wrf_data, tm)
    
    # construct initial conditions
    E = 0.5 * (Ed[1,:,:] + Ew[1,:,:])
    
    # set up parameters
    Q = np.eye(9) * 0.001
    P0 = np.eye(9) * 0.01
    dt = 10.0 * 60
    K = np.zeros_like(E)
    V = np.zeros_like(E)
    mV = np.zeros_like(E)
    predicted_field = np.zeros_like(E)
    mresV = np.zeros_like(E)
    Kf_fn = np.zeros_like(E)
    Vf_fn = np.zeros_like(E)
    mid = np.zeros_like(E)
    Kg = np.zeros((dom_shape[0], dom_shape[1], 9))
    cV12 = np.zeros_like(E)
    
    # initialize the mean field model (default fit is 1.0 of equilibrium before new information comes in)
    mfm = MeanFieldModel(cfg['lock_gamma'])

    # construct model grid using standard fuel parameters
    Tk = np.array([1.0, 10.0, 100.0]) * 3600
    models = np.zeros(dom_shape, dtype = np.object)
    models_na = np.zeros_like(models)
    for pos in np.ndindex(dom_shape): 
        models[pos] = CellMoistureModel((lat[pos], lon[pos]), 3, E[pos], Tk, P0 = P0)
        models_na[pos] = CellMoistureModel((lat[pos], lon[pos]), 3, E[pos], Tk, P0 = P0)

    m = None

    plt.figure(figsize = (12, 8))
    
    # run model
    for t in range(1, Nt):
        model_time = tm[t]
        print("Time: %s, step: %d" % (str(model_time), t))

        # pre-compute equilibrium moisture to save a lot of time
        E = 0.5 * (Ed[t,:,:] + Ew[t,:,:])
        
        # run the model update
        for pos in np.ndindex(dom_shape):
            i, j = pos
            models[pos].advance_model(Ed[t, i, j], Ew[t, i, j], rain[t, i, j], dt, Q)
            models_na[pos].advance_model(Ed[t, i, j], Ew[t, i, j], rain[t, i, j], dt, Q)
            
        # prepare visualization data        
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        f_na = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]
            f_na[p[0], p[1], :] = models_na[p].get_state()[:3]
            mV[pos] = models[p].get_state_covar()[1,1]
            cV12[pos] = models[p].get_state_covar()[0,1]
            mid[p] = models[p].get_model_ids()[1]
            

        # run Kriging on each observed fuel type
        Kf = []
        Vf = []
        fn = []
        for obs_data, fuel_ndx in [ (obs_data_fm10, 1) ]:

            if model_time in obs_data:

                # fit the current estimation of the moisture field to the data 
                base_field = f[:,:,fuel_ndx]
                mfm.fit_to_data(base_field, obs_data[model_time])
                
                # find differences (residuals) between observed measurements and nearest grid points
                # use this to update observation residual standard deviation 
                obs_vals = np.array([o.get_value() for o in obs_data[model_time]])
                mod_vals = np.array([f[:,:,fuel_ndx][o.get_nearest_grid_point()] for o in obs_data[model_time]])
                mod_na_vals = np.array([f_na[:,:,fuel_ndx][o.get_nearest_grid_point()] for o in obs_data[model_time]])
                obs_re.update_with(obs_vals - mod_vals)
                diagnostics().push("kriging_obs_res_var", (t, np.mean(obs_re.get_variance())))
            
                # retrieve the variance of the model field
                mresV = mod_re.get_variance()

                # krige data to observations
                if cfg['kriging_strategy'] == 'uk':
                    Kf_fn, Vf_fn, gamma, mape = universal_kriging_data_to_model(obs_data[model_time],
                                                                          obs_re.get_variance() ** 0.5,
                                                                          base_field,
                                                                          wrf_data,
                                                                          mresV ** 0.5, t)
                    # replace the stored gamma with the uk computed gamma
                    diagnostics().pull("mfm_gamma")[-1] = gamma
                    diagnostics().pull("mfm_mape")[-1] = mape
                    print("uk: replaced mfm_gamma %g, mfm_mape %g" % (gamma, mape))

                    # update the residuals estimator with the current
                    mod_re.update_with(gamma * f[:,:,fuel_ndx] - Kf_fn)

                elif cfg['kriging_strategy'] == 'tsm':
                    # predict the moisture field using observed fuel type
                    predicted_field = mfm.predict_field(base_field)

                    # run the tsm kriging estimator
                    Kf_fn, Vf_fn = trend_surface_model_kriging(obs_data[model_time], wrf_data, predicted_field)

                    # update the model residual estimator and get current best estimate of variance
                    mod_re.update_with(f[:,:,fuel_ndx] - predicted_field)

                else:
                    raise ValueError('Invalid kriging strategy [%s] in configuration.' % cfg['kriiging_strategy'])

                krig_vals = np.array([Kf_fn[o.get_nearest_grid_point()] for o in obs_data[model_time]])                
                diagnostics().push("assim_data", (t, fuel_ndx, obs_vals, krig_vals, mod_vals, mod_na_vals))
                plot_model_snapshot(cfg, tm, t, fuel_ndx, obs_vals, krig_vals, mod_vals, mod_na_vals)

                # append to storage for kriged fields in this time instant
                Kf.append(Kf_fn)
                Vf.append(Vf_fn)
                fn.append(fuel_ndx)

        # if there were any observations, run the kalman update step
        if len(fn) > 0:
            Nobs = len(fn)
            # run the kalman update in each model independently
            # gather the standard deviations of the moisture fuel after the Kalman update
            for pos in np.ndindex(dom_shape):
                O = np.zeros((Nobs,))
                V = np.zeros((Nobs, Nobs))
                
                # construct observations for this position
                for i in range(Nobs):
                    O[i] = Kf[i][pos]
                    V[i,i] = Vf[i][pos]
                
                # execute the Kalman update
                Kij = models[pos].kalman_update(O, V, fn)
                Kg[pos[0], pos[1], :] = Kij[:, 0]


        # prepare visualization data        
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]
            
        plt.clf()
        plt.subplot(3,3,1)
        render_spatial_field_fast(m, lon, lat, f[:,:,0], '1-hr fuel')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,2)
        render_spatial_field_fast(m, lon, lat, f[:,:,1], '10-hr fuel')
        plt.clim([0.0, maxE])        
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,3)
        render_spatial_field_fast(m, lon, lat, f_na[:,:,1], '10hr fuel - no assim')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,4)
        render_spatial_field_fast(m, lon, lat, Kg[:,:,0], 'Kalman gain, fm1')  
        plt.clim([0.0, 3.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,5)
        render_spatial_field_fast(m, lon, lat, Kg[:,:,1], 'Kalman gain, fm10')       
        plt.clim([0.0, 1.0])        
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,6)
	render_spatial_field_fast(m, lon, lat, Kf_fn, 'Kriging field')
	plt.clim([0.0, maxE])
        plt.axis('off')
	plt.colorbar()
        plt.subplot(3,3,7)
        render_spatial_field_fast(m, lon, lat, mid, 'Model ids')
        plt.clim([0.0, 5.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,8)
        render_spatial_field_fast(m, lon, lat, Vf_fn, 'Kriging var')
        plt.clim([0.0, np.max(Vf_fn)])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,9)
        render_spatial_field_fast(m, lon, lat, mresV, 'fm10 model var')
        plt.clim([0.0, np.max(mresV)])
        plt.axis('off')
        plt.colorbar()
        
        plt.savefig(os.path.join(cfg['output_dir'], 'moisture_model_t%03d.png' % t))

        # push new diagnostic outputs
        diagnostics().push("assim_K0", (t, np.mean(Kg[:,:,0])))
        diagnostics().push("assim_K1", (t, np.mean(Kg[:,:,1])))
        diagnostics().push("assim_mV", (t, np.mean(mV)))
        diagnostics().push("assim_mresV", (t, np.mean(mresV)))
        diagnostics().push("kriging_variance", (t, np.mean(Vf_fn)))

        
    # store the gamma coefficients
    with open(os.path.join(cfg['output_dir'], 'gamma.txt'), 'w') as f:
        f.write(str(diagnostics().pull('mfm_gamma')))
        
    # make a plot of gammas
    plt.figure()
    plt.plot(diagnostics().pull('mfm_gamma'))
    plt.title('Mean field model - gamma')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_gamma.png'))

    plt.figure()
    plt.plot(diagnostics().pull('skdm_cov_cond'))
    plt.title('Condition number of covariance matrix')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_sigma_cond.png'))

    # make 
    # make a plot for each substation
    plt.figure()
    D = diagnostics().pull("assim_data")
    for i in range(len(stations)):
        plt.clf()
        # get data for the i-th station
        t_i = [ o[0] for o in D]
        obs_i = [ o[2][i] for o in D]
        krig_i = [ o[3][i] for o in D]
        mod_i = [ o[4][i] for o in D]
        mod_na_i = [ o[5][i] for o in D]
        mx = max(max(obs_i), max(mod_i), max(krig_i), max(mod_i))
        plt.plot(t_i, obs_i, 'ro')
        plt.plot(t_i, krig_i, 'bo-')
        plt.plot(t_i, mod_i, 'kx-', linewidth = 1.5)
        plt.plot(t_i, mod_na_i, 'mx-')
        plt.ylim([0.0, 1.1 * mx])
        plt.legend(['Obs.', 'Kriged', 'Model', 'NoAssim'])
        plt.title('Station observations fit to model and kriging field')
        plt.savefig(os.path.join(cfg['output_dir'], 'station%02d.png' % (i+1)))
    
    
    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K1")],
             [d[1] for d in diagnostics().pull("assim_K1")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_10hr.png'))
    
    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K0")],
             [d[1] for d in diagnostics().pull("assim_K0")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_1hr.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_mV")],
             [d[1] for d in diagnostics().pull("assim_mV")], 'ro-')
    plt.title('Average model variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_fm10_model_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_mresV")],
             [d[1] for d in diagnostics().pull("assim_mresV")], 'ro-')
    plt.title('Average fm10 residual variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_fm10_model_residual_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("kriging_variance")],
             [d[1] for d in diagnostics().pull("kriging_variance")], 'ro-')
    plt.title('Kriging field variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kriging_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("kriging_obs_res_var")],
             [d[1] for d in diagnostics().pull("kriging_obs_res_var")], 'ro-')
    plt.title('Observation residual variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_observation_residual_variance.png'))
    
    plt.figure()
    plt.plot(diagnostics().pull("mfm_mape"), 'ro-', linewidth = 2)
    plt.title('Mean absolute prediction error of station data')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_station_mape.png'))

    diagnostics().dump_store(os.path.join(cfg['output_dir'], 'diagnostics.bin'))
    
    # as a last step encode all the frames as video
    os.system("cd %s; avconv -qscale 1 -r 20 -b 9600 -i moisture_model_t%%03d.png video.mp4" % cfg['output_dir'])
Esempio n. 18
0
image_list_indir = imtools.imagelist_in_depth(image_dir, level=1)
print('processing ' + str(len(image_list_indir)) + ' images')

i_detected = -1
samples = []
for i, image_file in enumerate(image_list_indir):
    print(str(i) + ' : ' + image_file)
    """
    READ IMAGE
    """
    # READ THE IMAGE
    im = io.imread(image_file)  # read uint8 image
    """ 
    CREATE AND SAVE DIAGNOSTICS
    """
    diag = diagnostics.diagnostics(im, image_file, vis_diag=False)

    wbc_types = diag.param.wbc_types
    wbc_basic_types = diag.param.wbc_basic_types
    """
    CREATE HSV
    """
    hsv_resize, scale = imtools.imRescaleMaxDim(diag.hsv_corrected,
                                                diag.param.middle_size,
                                                interpolation=0)
    im_resize, scale = imtools.imRescaleMaxDim(diag.im_corrected,
                                               diag.param.middle_size,
                                               interpolation=0)
    """
    WBC nucleus masks
    """
def universal_kriging_data_to_model(obs_data, obs_stds, m, wrf_data, mod_stds,
                                    t):
    """
    Universal kriging of data points to model points.  The kriging results in
    the matrix K, which contains the kriged observations and the matrix V,
    which contains the kriging variance.
    """
    mlons, mlats = wrf_data.get_lons(), wrf_data.get_lats()
    K = np.zeros_like(mlons)
    V = np.zeros_like(mlons)
    Nobs = len(obs_data)
    obs_vals = np.zeros((Nobs, ))
    station_lonlat = []
    gridndx = []
    mu_obs = np.zeros((Nobs, ))
    m_pred = np.zeros((Nobs, ))
    measV = np.zeros((Nobs, ))

    # accumulate the indices of the nearest grid points
    ndx = 0
    for obs in obs_data:
        gridndx.append(obs.get_nearest_grid_point())
        obs_vals[ndx] = obs.get_value()
        station_lonlat.append(obs.get_position())
        measV[ndx] = obs.get_measurement_variance()
        m_pred[ndx] = m[obs.get_nearest_grid_point()]
        ndx += 1

    # convert lists to column vectors
    m_pred = np.asmatrix(m_pred).T
    obs_vals = np.asmatrix(obs_vals).T

    # construct the covariance matrix and invert it
    C = np.asmatrix(construct_spatial_correlation_matrix2(station_lonlat))
    oS = np.asmatrix(np.diag(obs_stds))
    Sigma = oS.T * C * oS + np.diag(measV)
    SigInv = np.linalg.inv(Sigma)

    # estimate the fixed part of the model
    gamma = np.linalg.inv(
        m_pred.T * SigInv * m_pred) * m_pred.T * SigInv * obs_vals
    gamma = gamma[0, 0]
    mu_mod = m * gamma

    ndx = 0
    for obs in obs_data:
        mu_obs[ndx] = mu_mod[obs.get_nearest_grid_point()]
        ndx += 1

    # compute observation residuals (using model fit from examine_station_data)
    # and the mean absolute deviation
    res_obs = np.asmatrix(obs_vals - mu_obs).T
    mape = np.mean(np.abs(res_obs))

    diagnostics().push("skdm_cov_cond", np.linalg.cond(Sigma))

    # precompute some matrices
    xs = obs_vals.T * SigInv
    xsx_1 = 1.0 / (xs * obs_vals)

    # run the kriging estimator for each model grid point
    K = np.zeros_like(mlats)
    cov = np.asmatrix(np.zeros_like(mu_obs)).T
    for p in np.ndindex(K.shape):

        # compute the covariance array anew for each grid point
        for k in range(Nobs):
            lon, lat = station_lonlat[k]
            cc = max(
                0.8565 -
                0.0063 * great_circle_distance(mlons[p], mlats[p], lon, lat),
                0.0)
            cov[k, 0] = mod_stds[p] * cc * obs_stds[k]

        csi = SigInv * (cov - obs_vals * xsx_1 * (xs * cov - mu_mod[p]))
        K[p] = csi.T * obs_vals
        tmp = (mu_mod[p] - cov.T * SigInv * obs_vals)
        V[p] = mod_stds[p]**2 - cov.T * SigInv * cov + tmp * xsx_1 * tmp

    return K, V, gamma, mape
Esempio n. 20
0
def run_module():
  # read in configuration file to execute run
  print("Reading configuration from [%s]" % sys.argv[1])

  with open(sys.argv[1]) as f:
      cfg = eval(f.read())

  # init diagnostics
  init_diagnostics(os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))
  diagnostics().configure_tag("s2_eta_hat", True, True, True)
  diagnostics().configure_tag("kriging_rmse", True, True, True)
  diagnostics().configure_tag("kriging_beta", True, True, True)
  diagnostics().configure_tag("kriging_iters", False, True, True)
  diagnostics().configure_tag("kriging_subzero_s2_estimates", False, True, True)

  # load the wrfinput file
  wrfin = WRFModelData(cfg['wrf_input'], ['T2', 'Q2', 'PSFC', 'HGT', 'FMC_GC', 'FMEP'])
  lat, lon = wrfin.get_lats(), wrfin.get_lons()
  ts_now = wrfin['GMT'][0]
  dom_shape = lat.shape
  print('INFO: domain size is %d x %d grid points, wrfinput timestamp %s' % (dom_shape[0], dom_shape[1], str(ts_now)))
  print('INFO: domain extent is lats (%g to %g) lons (%g to %g).' % (np.amin(lat),np.amax(lat),np.amin(lon),np.amax(lon)))

  # compute the diagonal distance between grid points
  grid_dist_km = great_circle_distance(lon[0,0], lat[0,0], lon[1,1], lat[1,1])
  print('INFO: diagonal distance in grid is %g' % grid_dist_km)
 
  # load observations but discard those too far away from the grid nodes
  obss = load_raws_observations(cfg['observations'], lat, lon, grid_dist_km)
  fm10 = build_observation_data(obss)
  print('INFO: %d different time instances found in observations' % len(fm10))

  # if a previous cycle is available (i.e. the wrfoutput is a valid file)
  if os.path.exists(cfg['wrf_output_prev']) and check_overlap(cfg['wrf_output_prev'],ts_now):

    # load the model as a wrfout with all default variables
    wrfout = WRFModelData(cfg['wrf_output_prev'])
    outts = wrfout['GMT']
    print("INFO: previous forecast [%s - %s] exists, running DA till %s" % (str(outts[0]),str(outts[-1]),str(ts_now)))

    # run from the start until now (retrieve fuel moisture, extended parameters, covariance matrix)
    model =  run_data_assimilation(wrfout, fm10, ts_now, cfg)
    # store this for the current time instance (fm, ep in the wrfinput, P next to it)
    d = netCDF4.Dataset(cfg['wrf_input'], 'r+')
    d.variables['FMC_GC'] = fm
    d.variables['FMEP'] = ep
    d.close()

    # store the covariance matrix alongside the wrfinput file
    dir = os.path.dirname(wrfin)
    store_covariance_matrix(P, os.path.join(dir, 'P.nc'))

  else:

    print("INFO: no previous forecast found, running DA from equilibrium at %s" % (str(ts_now)))
    # initialize from weather equilibrium and perform one DA step
    model = init_from_equilibrium(wrfin, fm10, ts_now, cfg)

    # store result in wrfinput dataset
    d = netCDF4.Dataset(cfg['wrf_input'], 'r+')
    fmcep = model.get_state()
    d.variables['FMC_GC'][0,:3,:,:] = fmcep[:,:,:3].transpose((2,0,1))
    d.variables['FMEP'][0,:,:,:] = fmcep[:,:,3:5].transpose((2,0,1))
    d.close()
    store_covariance_matrix(model.get_state_covar(), os.path.join(os.path.dirname(cfg['wrf_input']), 'P.nc'))

  return 0
Esempio n. 21
0
                # Make sure all examples have the same source language
                assert e.l1 == source_language

            # The following is code for training on bilingual examples.
            # TODO: Monolingual examples?

            correct_sequences, noise_sequences, weights = ebatch_to_sequences(ebatch)
            translation_model[source_language].train(correct_sequences, noise_sequences, weights)

            #validate(translation_model, cnt)
            if int(cnt/1000) > int(lastcnt/1000):
                logging.info("Finished training step %d (epoch %d)" % (cnt, epoch))
#                print ("Finished training step %d (epoch %d)" % (cnt, epoch))
            if int(cnt/10000) > int(lastcnt/10000):
                for l1 in translation_model:
                    diagnostics.diagnostics(cnt, translation_model[l1])
                if os.path.exists(os.path.join(rundir, "BAD")):
                    logging.info("Detected file: %s\nSTOPPING" % os.path.join(rundir, "BAD"))
                    sys.stderr.write("Detected file: %s\nSTOPPING\n" % os.path.join(rundir, "BAD"))
                    sys.exit(0)
            if int(cnt/HYPERPARAMETERS["VALIDATE_EVERY"]) > int(lastcnt/HYPERPARAMETERS["VALIDATE_EVERY"]):
                validate(translation_model, cnt)
                pass
#                for l1 in translation_model:
#                    diagnostics.visualizedebug(cnt, translation_model[l1], rundir, newkeystr)

        validate(translation_model, cnt)
#        get_train_minibatch = w2w.examples.get_training_minibatch_online()
        get_train_minibatch = w2w.examples.get_training_minibatch_cached()
        epoch += 1
Esempio n. 22
0
def fit_tsm(obs_data, X):
    """
    Trend surface model kriging, which assumes spatially uncorrelated errors.
    The kriging results in the matrix K, which contains the kriged observations
    and the matrix V, which contains the kriging variance.
    """
    Nobs = len(obs_data)

    # we ensure we have at most Nobs covariates
    Nallcov = min(X.shape[2], Nobs)

    # the matrix of covariates
    Xobs = np.zeros((Nobs, Nallcov))

    # outputs
    K = np.zeros(X[:,:,0].shape)
    V = np.zeros_like(K)

    # the vector of target observations
    y = np.zeros((Nobs,1))

    # the vector of observation variances
    obs_var = np.zeros((Nobs,))

    # fill out matrix/vector structures
    for (obs,i) in zip(obs_data, range(Nobs)):
        p = obs.get_nearest_grid_point()
        y[i,0] = obs.get_value()
        Xobs[i,:] = X[p[0], p[1], :Nallcov]
        obs_var[i] = obs.get_variance()

    # remove covariates that contain only zeros
    norms = np.sum(Xobs**2, axis = 0) ** 0.5
    nz_covs = np.nonzero(norms)[0]
    Ncov = len(nz_covs)
    X = X[:,:,nz_covs]
    Xobs = Xobs[:,nz_covs]
    norms = norms[nz_covs]

    # normalize all covariates
    for i in range(1, Ncov):
        scalar = norms[0] / norms[i]
        Xobs[:,i] *= scalar
        X[:,:,i] *= scalar

    Xobs = np.asmatrix(Xobs)

    # initialize the iterative algorithm
    s2_eta_hat_old = 10.0
    s2_eta_hat = 0.0
    iters = 0
    subzeros = 0
    res2 = None
    XtSX = None
    equal_variance_flag = np.all(obs_var == obs_var[0])

    if equal_variance_flag:
      # use a much faster algorithm that requires no iterations
      Q, R = np.linalg.qr(Xobs)
      beta = np.linalg.solve(R, np.asmatrix(Q).T * y)
      res2 = np.asarray(y - Xobs * beta)[:,0]**2
      gamma2 = obs_var[0]
      if Nobs > Ncov:
        s2_eta_hat = max(1.0 / (Nobs - Ncov) * np.sum(res2) - gamma2, 0.0)
      else:
        s2_eta_hat = 0.0
      XtSX = 1.0 / (s2_eta_hat + gamma2) * (Xobs.T* Xobs)
      iters = -1
      subzeros = 0

    else:

      # while the relative change is more than 0.1%
      while abs( (s2_eta_hat_old - s2_eta_hat) / max(s2_eta_hat_old, 1e-8)) > 1e-3:
          #print('TSM: iter %d s_eta_hat_old %g s2_eta_hat %g' % (iters, s2_eta_hat_old, s2_eta_hat))
          s2_eta_hat_old = s2_eta_hat

          # recompute covariance matrix
          Sigma_diag = obs_var + s2_eta_hat
          Sigma = np.diag(Sigma_diag)
          Sigma_1 = np.diag(1.0 / Sigma_diag)
          XtSX = Xobs.T * Sigma_1 * Xobs
          #print('TSM: XtSX = %s' % str(XtSX))

          # QR solution method of the least squares problem
          Sigma_1_2 = np.asmatrix(np.diag(Sigma_diag ** -0.5))
          yt = Sigma_1_2 * y
          Q, R = np.linalg.qr(Sigma_1_2 * Xobs)
          beta = np.linalg.solve(R, np.asmatrix(Q).T * yt)
          res2 = np.asarray(y - Xobs * beta)[:,0]**2
  #        print('TSM: beta %s res2 %s' % (str(beta), str(res2)))

          # compute new estimate of variance of microscale variability
          s2_array = res2 - obs_var
          for i in range(len(s2_array)):
              s2_array[i] += np.dot(Xobs[i,:], np.linalg.solve(XtSX, Xobs[i,:].T))

  #        print('TSM: s2_array %s' % str(s2_array))
          s2_eta_hat = numerical_solve_bisect(res2, obs_var, Ncov)
          if s2_eta_hat < 0.0:
  #          print("TSM: s2_eta_hat estimate below zero")
            s2_eta_hat = 0.0

  #        print('TSM: s2_eta_hat %g' % s2_eta_hat)

          subzeros = np.count_nonzero(s2_array < 0.0)
          iters += 1

    # map computed betas to original (possibly extended) betas which include unused variables
    beta_ext = np.asmatrix(np.zeros((Nallcov,1)))
    beta_ext[nz_covs] = beta
    diagnostics().push("s2_eta_hat", s2_eta_hat)
    diagnostics().push("kriging_beta", beta_ext)
    diagnostics().push("kriging_iters", iters)
    diagnostics().push("kriging_rmse", np.mean(res2)**0.5)
    diagnostics().push("kriging_subzero_s2_estimates", subzeros)
#    diagnostics().push("kriging_cov_cond", np.linalg.cond(XtSX))

    for i in range(X.shape[0]):
        for j in range(X.shape[1]):
            x_ij = X[i,j,:]
            K[i,j] = np.dot(x_ij, beta)
            V[i,j] = s2_eta_hat + np.dot(x_ij, np.linalg.solve(XtSX, x_ij))
            if V[i,j] < 0.0:
              print("ERROR: negative kriging variance!")

    return K, V
Esempio n. 23
0
    random_representations = numpy.zeros(
        (wordmap.len, HYPERPARAMETERS["REPRESENTATION_SIZE"]))

    context_vectors = generate_context_vectors()

    for tokens in trainingsentences():
        for i in range(len(tokens)):
            for j, context in enumerate(HYPERPARAMETERS["CONTEXT_TYPES"]):
                for k in context:
                    tokidx = i + k
                    if tokidx < 0 or tokidx >= len(tokens): continue
                    random_representations[tokens[i]] += context_vectors[j][
                        tokens[tokidx]]
        cnt += 1
        if cnt % 10000 == 0:
            diagnostics.diagnostics(cnt, random_representations)

    logging.info("DONE. Dividing embeddings by their standard deviation...")
    random_representations = random_representations * (
        1. / numpy.std(random_representations))
    diagnostics.diagnostics(cnt, random_representations)
    diagnostics.visualizedebug(cnt, random_representations, rundir, newkeystr)

    outfile = os.path.join(rundir, "random_representations")
    if newkeystr != "":
        verboseoutfile = os.path.join(rundir,
                                      "random_representations%s" % newkeystr)
        logging.info("Writing representations to %s, and creating link %s" %
                     (outfile, verboseoutfile))
        os.system("ln -s random_representations %s " % (verboseoutfile))
    else:
def run_module():
    
    # read in configuration file to execute run
    print("Reading configuration from [%s]" % sys.argv[1])
    
    with open(sys.argv[1]) as f:
        cfg = eval(f.read())
    
    # ensure output path exists
    if not os.path.isdir(cfg['output_dir']): 
        os.mkdir(cfg['output_dir'])

    # configure diagnostics        
    init_diagnostics(os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))

    # Error covariance matrix condition number in kriging
    diagnostics().configure_tag("skdm_cov_cond", False, True, True)

    # Assimilation parameters
    diagnostics().configure_tag("assim_K0", False, True, True)
    diagnostics().configure_tag("assim_K1", True, True, True)
    diagnostics().configure_tag("assim_data", False, False, True)

    diagnostics().configure_tag("obs_residual_var", True, True, True)

    diagnostics().configure_tag("fm10_model_residual_var", True, True, True)
    diagnostics().configure_tag("fm10_model_var", False, True, True)
    diagnostics().configure_tag("fm10_kriging_var", False, True, True)

    ### Load and preprocess WRF model data

    # load WRF data
    wrf_data = WRFModelData(cfg['input_file'], tz_name = 'US/Mountain')
    
    # read in spatial and temporal extent of WRF variables
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    tm = wrf_data.get_gmt_times()
    Nt = cfg['Nt'] if cfg['Nt'] is not None else len(tm)
    dom_shape = lat.shape

    # retrieve the rain variable
    rain = wrf_data['RAIN']

    # moisture equilibria are now computed from averaged Q,P,T at beginning and end of period
    Ed, Ew = wrf_data.get_moisture_equilibria()

    ### Load observation data from the stations

    # load station data from files
    with open(os.path.join(cfg['station_data_dir'], cfg['station_list_file']), 'r') as f:
        si_list = f.read().split('\n')

    si_list = filter(lambda x: len(x) > 0, map(string.strip, si_list))

    # for each station id, load the station
    stations = []
    for sinfo in si_list:
        code = sinfo.split(',')[0]
        mws = MesoWestStation(sinfo, wrf_data)
        for suffix in [ '_1', '_2', '_3', '_4', '_5', '_6', '_7' ]:
            mws.load_station_data(os.path.join(cfg['station_data_dir'], '%s%s.xls' % (code, suffix)))
        stations.append(mws)

    print('Loaded %d stations.' % len(stations))
    
    # check stations for nans
    stations = filter(MesoWestStation.data_ok, stations)
    print('Have %d stations with complete data.' % len(stations))

    # set the measurement variance of the stations
    for s in stations:
        s.set_measurement_variance('fm10', cfg['fm10_meas_var'])

    # build the observation data
    obs_data_fm10 = build_observation_data(stations, 'fm10', wrf_data, tm)

    ### Initialize model and visualization

    # find maximum moisture overall to set up visualization
    maxE = 0.5
    
    # construct initial conditions from timestep 1 (because Ed/Ew at zero are zero)
    E = 0.5 * (Ed[1,:,:] + Ew[1,:,:])
    
    # set up parameters
    Q = np.eye(9) * cfg['Q']
    P0 = np.eye(9) * cfg['P0']
    dt = (tm[1] - tm[0]).seconds
    print("INFO: Computed timestep from WRF is is %g seconds." % dt)
    K = np.zeros_like(E)
    V = np.zeros_like(E)
    mV = np.zeros_like(E)
    predicted_field = np.zeros_like(E)
    mresV = np.zeros_like(E)
    Kf_fn = np.zeros_like(E)
    Vf_fn = np.zeros_like(E)
    mid = np.zeros_like(E)
    Kg = np.zeros((dom_shape[0], dom_shape[1], 9))
    cV12 = np.zeros_like(E)
    
    # moisture state and observation residual variance estimators
    mod_re = OnlineVarianceEstimator(np.zeros_like(E), np.ones_like(E) * 0.05, 1)
    obs_re = OnlineVarianceEstimator(np.zeros((len(stations),)), np.ones(len(stations),) * 0.05, 1)
    
    # initialize the mean field model (default fit is 1.0 of equilibrium before new information comes in)
    mfm = MeanFieldModel(cfg['lock_gamma'])

    # construct model grid using standard fuel parameters
    Tk = np.array([1.0, 10.0, 100.0]) * 3600
    models = np.zeros(dom_shape, dtype = np.object)
    models_na = np.zeros_like(models)
    for p in np.ndindex(dom_shape): 
        models[p] = CellMoistureModel((lat[p], lon[p]), 3, E[p], Tk, P0 = P0)
        models_na[p] = CellMoistureModel((lat[p], lon[p]), 3, E[p], Tk, P0 = P0)

    m = None
    plt.figure(figsize = (12, 8))
    
    ###  Run model for each WRF timestep and assimilate data when available
    for t in range(1, Nt):
        model_time = tm[t]
        print("INFO: time: %s, step: %d" % (str(model_time), t))

        # run the model update
        for p in np.ndindex(dom_shape):
            i, j = p
            models[p].advance_model(Ed[t-1, i, j], Ew[t-1, i, j], rain[t-1, i, j], dt, Q)
            models_na[p].advance_model(Ed[t-1, i, j], Ew[t-1, i, j], rain[t-1, i, j], dt, Q)
            
        # prepare visualization data
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        f_na = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]
            f_na[p[0], p[1], :] = models_na[p].get_state()[:3]
            P = models[p].get_state_covar()
            cV12[p] = P[0,1]
            mV[p] = P[1,1]
            mid[p] = models[p].get_model_ids()[1]

        diagnostics().push("fm10_model_var", (t, np.mean(mV)))

        # run Kriging on each observed fuel type
        Kf = []
        Vf = []
        fn = []
        for obs_data, fuel_ndx in [ (obs_data_fm10, 1) ]:

            # run the kriging subsystem and the Kalman update only if we have observations
            if model_time in obs_data:

                # retrieve observations for current time
                obs_t = obs_data[model_time]


                # fit the current estimation of the moisture field to the data 
                base_field = f[:,:,fuel_ndx]
                mfm.fit_to_data(base_field, obs_data[model_time])
                
                # find differences (residuals) between observed measurements and nearest grid points
                # use this to update observation residual standard deviation 
                obs_vals = np.array([o.get_value() for o in obs_data[model_time]])
                mod_vals = np.array([base_field[o.get_nearest_grid_point()] for o in obs_data[model_time]])
                mod_na_vals = np.array([f_na[:,:,fuel_ndx][o.get_nearest_grid_point()] for o in obs_data[model_time]])
                obs_re.update_with(obs_vals - mod_vals)
                diagnostics().push("obs_residual_var", (t, np.mean(obs_re.get_variance())))
            
                # predict the moisture field using observed fuel type
                predicted_field = mfm.predict_field(base_field)

                # update the model residual estimator and get current best estimate of variance
                mod_re.update_with(f[:,:,fuel_ndx] - predicted_field)
                mresV = mod_re.get_variance()
                diagnostics().push("fm10_model_residual_var", (t, np.mean(mresV)))

                # krige observations to grid points
                Kf_fn, Vf_fn = trend_surface_model_kriging(obs_data[model_time], wrf_data, predicted_field)

                krig_vals = np.array([Kf_fn[o.get_nearest_grid_point()] for o in obs_data[model_time]])                
                diagnostics().push("assim_data", (t, fuel_ndx, obs_vals, krig_vals, mod_vals, mod_na_vals))
                plot_model_snapshot(cfg, tm, t, fuel_ndx, obs_vals, krig_vals, mod_vals, mod_na_vals)

                diagnostics().push("fm10_kriging_var", (t, np.mean(Vf_fn)))

                # append to storage for kriged fields in this time instant
                Kf.append(Kf_fn)
                Vf.append(Vf_fn)
                fn.append(fuel_ndx)


        # if there were any observations, run the kalman update step
        if len(fn) > 0:
            Nobs = len(fn)
            # run the kalman update in each model independently
            # gather the standard deviations of the moisture fuel after the Kalman update
            for p in np.ndindex(dom_shape):
                O = np.zeros((Nobs,))
                V = np.zeros((Nobs, Nobs))
                
                # construct observations for this position
                for i in range(Nobs):
                    O[i] = Kf[i][p]
                    V[i,i] = Vf[i][p]
                
                # execute the Kalman update
                Kp = models[p].kalman_update(O, V, fn)
                Kg[p[0], p[1], :] = Kp[:, 0]

            # push new diagnostic outputs
            diagnostics().push("assim_K0", (t, np.mean(Kg[:,:,0])))
            diagnostics().push("assim_K1", (t, np.mean(Kg[:,:,1])))

        # prepare visualization data        
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]
            
        plt.clf()
        plt.subplot(3,3,1)
        render_spatial_field_fast(m, lon, lat, f[:,:,0], '1-hr fuel')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,2)
        render_spatial_field_fast(m, lon, lat, f[:,:,1], '10-hr fuel')
        plt.clim([0.0, maxE])        
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,3)
        render_spatial_field_fast(m, lon, lat, f_na[:,:,1], '10hr fuel - no assim')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,4)
        render_spatial_field_fast(m, lon, lat, Kg[:,:,0], 'Kalman gain for 1-hr fuel')  
        plt.clim([0.0, 3.0])        
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,5)
        render_spatial_field_fast(m, lon, lat, Kg[:,:,1], 'Kalman gain for 10-hr fuel')       
        plt.clim([0.0, 1.0])        
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,6)
	render_spatial_field_fast(m, lon, lat, Kf_fn, 'Kriging field')
	plt.clim([0.0, maxE])
        plt.axis('off')
	plt.colorbar()
        plt.subplot(3,3,7)
        render_spatial_field_fast(m, lon, lat, mid, 'Model ids')
        plt.clim([0.0, 5.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,8)
        render_spatial_field_fast(m, lon, lat, Vf_fn, 'Kriging variance')
        plt.clim([0.0, np.max(Vf_fn)])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3,3,9)
        render_spatial_field_fast(m, lon, lat, mresV, 'Model res. variance')
        plt.clim([0.0, np.max(mresV)])
        plt.axis('off')
        plt.colorbar()
        
        plt.savefig(os.path.join(cfg['output_dir'], 'moisture_model_t%03d.png' % t))


    # store the diagnostics in a binary file
    diagnostics().dump_store(os.path.join(cfg['output_dir'], 'diagnostics.bin'))
    
    # make a plot of gammas
    plt.figure()
    plt.plot(diagnostics().pull('mfm_gamma'), 'bo-')
    plt.title('Mean field model - gamma')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_gamma.png'))

    plt.figure()
    plt.plot(diagnostics().pull('skdm_cov_cond'))
    plt.title('Condition number of covariance matrix')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_sigma_cond.png'))

    # make a plot for each substation
    plt.figure()
    D = diagnostics().pull("assim_data")
    for i in range(len(stations)):
        plt.clf()
        # get data for the i-th station
        t_i = [ o[0] for o in D]
        obs_i = [ o[2][i] for o in D]
        krig_i = [ o[3][i] for o in D]
        mod_i = [ o[4][i] for o in D]
        mod_na_i = [ o[5][i] for o in D]
        mx = max(max(obs_i), max(mod_i), max(krig_i), max(mod_i))
        plt.plot(t_i, obs_i, 'ro')
        plt.plot(t_i, krig_i, 'bo-')
        plt.plot(t_i, mod_i, 'kx-', linewidth = 1.5)
        plt.plot(t_i, mod_na_i, 'mx-')
        plt.ylim([0.0, 1.1 * mx])
        plt.legend(['Obs.', 'Kriged', 'Model', 'NoAssim'])
        plt.title('Station observations fit to model and kriging field')
        plt.savefig(os.path.join(cfg['output_dir'], 'station%02d.png' % (i+1)))
        
    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K1")],
             [d[1] for d in diagnostics().pull("assim_K1")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_10hr.png'))
    
    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K0")],
             [d[1] for d in diagnostics().pull("assim_K0")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_1hr.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("fm10_model_var")],
             [d[1] for d in diagnostics().pull("fm10_model_var")], 'ro-')
    plt.title('Average fm10 model variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_fm10_model_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("fm10_model_residual_var")],
             [d[1] for d in diagnostics().pull("fm10_model_residual_var")], 'ro-')
    plt.title('Average fm10 model residual variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_fm10_model_residual_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("fm10_kriging_var")],
             [d[1] for d in diagnostics().pull("fm10_kriging_var")], 'ro-')
    plt.title('Kriging field variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kriging_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("obs_residual_var")],
             [d[1] for d in diagnostics().pull("obs_residual_var")], 'ro-')
    plt.title('Observation residual variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_observation_residual_variance.png'))
    
    plt.figure()
    plt.plot(diagnostics().pull("mfm_mape"), 'ro-', linewidth = 2)
    plt.title('Mean absolute prediction error of station data')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_station_mape.png'))
Esempio n. 25
0
def micro_step(it_diag, dt, size_z, size_x, th_ar, qv_ar, rhof_ar, rhoh_ar,
               uf_ar, uh_ar, wf_ar, wh_ar, xf_ar, zf_ar, xh_ar, zh_ar,
               tend_th_ar, tend_qv_ar):
    try:
        # global should be used for all variables defined in "if first_timestep"
        global prtcls, dx, dz, timestep, last_diag

        # superdroplets: initialisation (done only once)
        if timestep == 0:

            # first, removing the no-longer-needed pointer file
            os.unlink(ptrfname)

            arrx = ptr2np(xf_ar, size_x, 1)
            arrz = ptr2np(zf_ar, 1, size_z)

            # checking if grids are equal
            np.testing.assert_almost_equal((arrx[1:] - arrx[:-1]).max(),
                                           (arrx[1:] - arrx[:-1]).min(),
                                           decimal=7)
            np.testing.assert_almost_equal((arrz[1:] - arrz[:-1]).max(),
                                           (arrz[1:] - arrz[:-1]).min(),
                                           decimal=7)
            dx = arrx[1] - arrx[0]
            dz = arrz[1] - arrz[0]

            opts_init = libcl.lgrngn.opts_init_t()
            opts_init.dt = dt
            opts_init.nx, opts_init.nz = size_x - 2, size_z
            opts_init.dx, opts_init.dz = dx, dz
            opts_init.z0 = dz  # skipping the first sub-terrain level
            opts_init.x1, opts_init.z1 = dx * opts_init.nx, dz * opts_init.nz
            opts_init.sd_conc_mean = params["sd_conc"]
            opts_init.dry_distros = {params["kappa"]: lognormal}
            opts_init.sstp_cond, opts_init.sstp_coal = params[
                "sstp_cond"], params["sstp_coal"]

            try:
                print("Trying with CUDA backend..."),
                prtcls = libcl.lgrngn.factory(libcl.lgrngn.backend_t.CUDA,
                                              opts_init)
                print(" OK!")
            except:
                print(" KO!")
                try:
                    print("Trying with OpenMP backend..."),
                    prtcls = libcl.lgrngn.factory(
                        libcl.lgrngn.backend_t.OpenMP, opts_init)
                    print(" OK!")
                except:
                    print(" KO!")
                    print("Trying with serial backend..."),
                    prtcls = libcl.lgrngn.factory(
                        libcl.lgrngn.backend_t.serial, opts_init)
                    print(" OK!")

            # allocating arrays for those variables that are not ready to use
            # (i.e. either different size or value conversion needed)
            for name in ("thetad", "qv"):
                arrays[name] = np.empty((opts_init.nx, opts_init.nz))
            arrays["rhod"] = np.empty((opts_init.nz, ))
            arrays["Cx"] = np.empty((opts_init.nx + 1, opts_init.nz))
            arrays["Cz"] = np.empty((opts_init.nx, opts_init.nz + 1))

        # defining qv and thetad (in every timestep)
        arrays["qv"][:, :] = ptr2np(qv_ar, size_x, size_z)[1:-1, :]
        arrays["thetad"][:, :] = th_kid2dry(
            ptr2np(th_ar, size_x, size_z)[1:-1, :], arrays["qv"][:, :])

        # finalising initialisation
        if timestep == 0:
            arrays["rhod"][:] = rho_kid2dry(
                ptr2np(rhof_ar, 1, size_z)[:], arrays["qv"][0, :])

            arrays["Cx"][:, :] = ptr2np(uh_ar, size_x,
                                        size_z)[:-1, :] * dt / dx
            assert (arrays["Cx"][0, :] == arrays["Cx"][-1, :]).all()

            arrays["Cz"][:, 0] = 0  # no particles there anyhow
            arrays["Cz"][:,
                         1:] = ptr2np(wh_ar, size_x, size_z)[1:-1, :] * dt / dz

            prtcls.init(arrays["thetad"], arrays["qv"], arrays["rhod"],
                        arrays["Cx"], arrays["Cz"])
            dg.diagnostics(prtcls, arrays, 1, size_x, size_z,
                           timestep == 0)  # writing down state at t=0

        # spinup period logic
        opts.sedi = opts.coal = timestep >= params["spinup"]

        # superdroplets: all what have to be done within a timestep

        prtcls.step_sync(opts, arrays["thetad"], arrays["qv"], arrays["rhod"])

        prtcls.step_async(opts)

        # calculating tendency for theta (first converting back to non-dry theta
        ptr2np(tend_th_ar, size_x, size_z)[1:-1, :] = -(
            ptr2np(th_ar, size_x, size_z)[1:-1, :] -  # old
            th_dry2kid(arrays["thetad"], arrays["qv"])  # new
        ) / dt  #TODO: check if dt needed

        # calculating tendency for qv
        ptr2np(tend_qv_ar, size_x, size_z)[1:-1, :] = -(
            ptr2np(qv_ar, size_x, size_z)[1:-1, :] -  # old                
            arrays["qv"]  # new 
        ) / dt  #TODO: check if dt needed

        # diagnostics
        if last_diag < it_diag:
            dg.diagnostics(prtcls, arrays, it_diag, size_x, size_z,
                           timestep == 0)
            last_diag = it_diag

        timestep += 1
    except:
        traceback.print_exc()
        return False
    else:
        return True
def run_module():

    # configure diagnostics        
    init_diagnostics("results/kriging_test_diagnostics.txt")
    diagnostics().configure_tag("skdm_obs_res", True, True, True)
    diagnostics().configure_tag("skdm_obs_res_mean", True, True, True)
        
    wrf_data = WRFModelData('../real_data/witch_creek/realfire03_d04_20071022.nc')
    
    # read in vars
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    tm = wrf_data.get_times()
    rain = wrf_data['RAINNC']
    Ed, Ew = wrf_data.get_moisture_equilibria()
    
    # obtain sizes
    Nt = rain.shape[0]
    dom_shape = lat.shape
    locs = np.prod(dom_shape)
    
    # load station data, match to grid points and build observation records
    # load station data from files
    tz = pytz.timezone('US/Pacific')
    stations = [Station(os.path.join(station_data_dir, s), tz, wrf_data) for s in station_list]
    obs_data = build_observation_data(stations, 'fuel_moisture', wrf_data) 
    
    # construct initial vector
    mfm = MeanFieldModel()
    
    # set up parameters
    mod_res_std = np.ones_like(Ed[0,:,:]) * 0.05
    obs_res_std = np.ones((len(stations),)) * 0.1
    
    # construct a basemap representation of the area
    lat_rng = (np.min(lat), np.max(lat))
    lon_rng = (np.min(lon), np.max(lon))
    m = Basemap(llcrnrlon=lon_rng[0],llcrnrlat=lat_rng[0],
                urcrnrlon=lon_rng[1],urcrnrlat=lat_rng[1],
                projection = 'mill')

    plt.figure(figsize = (10, 6))
    
    # run model
    ndx = 1
    for t in range(1, Nt):
        model_time = wrf_data.get_times()[t]
        E = 0.5 * (Ed[t,:,:] + Ew[t,:,:])

        # if we have an observation somewhere in time, run kriging
        if model_time in obs_data:
            print("Time: %s, step: %d" % (str(model_time), t))
            
            mfm.fit_to_data(E, obs_data[model_time])
            Efit = mfm.predict_field(E)

            # krige data to observations
            K, V = simple_kriging_data_to_model(obs_data[model_time], obs_res_std, Efit, wrf_data, mod_res_std, t)
                
            plt.clf()
            plt.subplot(2,2,1)
            render_spatial_field(m, lon, lat, Efit, 'Equilibrium')
            plt.clim([0.0, 0.2])
            plt.colorbar()

            plt.subplot(2,2,2)
            render_spatial_field(m, lon, lat, K, 'Kriging field')
            plt.clim([0.0, 0.2])
            plt.colorbar()

            plt.subplot(2,2,3)
            render_spatial_field(m, lon, lat, V, 'Kriging variance')
            plt.clim([0.0, np.max(V)])
            plt.colorbar()
            
            plt.subplot(2,2,4)
            render_spatial_field(m, lon, lat, K - Efit, 'Kriging vs. mean field residuals')
#            plt.clim([0.0, np.max()])
            plt.colorbar()
            
            plt.savefig('model_outputs/kriging_test_t%03d.png' % (ndx))
            ndx += 1 
def run_module():

    # read in configuration file to execute run
    print("Reading configuration from [%s]" % sys.argv[1])

    with open(sys.argv[1]) as f:
        cfg = eval(f.read())

    # ensure output path exists
    if not os.path.isdir(cfg['output_dir']):
        os.mkdir(cfg['output_dir'])

    # configure diagnostics
    init_diagnostics(
        os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))

    # Error covariance matrix condition number in kriging
    diagnostics().configure_tag("skdm_cov_cond", False, True, True)

    # Assimilation parameters
    diagnostics().configure_tag("assim_K0", False, True, True)
    diagnostics().configure_tag("assim_K1", True, True, True)
    diagnostics().configure_tag("assim_data", False, False, True)

    diagnostics().configure_tag("fm10_model_var", False, True, True)
    diagnostics().configure_tag("fm10_kriging_var", False, True, True)

    ### Load and preprocess WRF model data

    # load WRF data
    wrf_data = WRFModelData(cfg['input_file'], tz_name='US/Mountain')

    # read in spatial and temporal extent of WRF variables
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    tm = wrf_data.get_gmt_times()
    Nt = cfg['Nt'] if cfg.has_key('Nt') and cfg['Nt'] is not None else len(tm)
    dom_shape = lat.shape

    # retrieve the rain variable
    rain = wrf_data['RAIN']

    # moisture equilibria are now computed from averaged Q,P,T at beginning and end of period
    Ed, Ew = wrf_data.get_moisture_equilibria()

    ### Load observation data from the stations

    # load station data from files
    with open(os.path.join(cfg['station_data_dir'], cfg['station_list_file']),
              'r') as f:
        si_list = f.read().split('\n')

    si_list = filter(lambda x: len(x) > 0 and x[0] != '#',
                     map(string.strip, si_list))

    # for each station id, load the station
    stations = []
    for code in si_list:
        mws = MesoWestStation(code)
        mws.load_station_info(
            os.path.join(cfg["station_data_dir"], "%s.info" % code))
        mws.register_to_grid(wrf_data)
        mws.load_station_data(
            os.path.join(cfg["station_data_dir"], "%s.obs" % code))
        stations.append(mws)

    print('Loaded %d stations.' % len(stations))

    # check stations for nans
    stations = filter(MesoWestStation.data_ok, stations)
    print('Have %d stations with complete data.' % len(stations))

    # build the observation data
    #    obs_data_fm10 = build_observation_data(stations, 'FM')
    obs_data_fm10 = {}

    ### Initialize model and visualization

    # find maximum moisture overall to set up visualization
    maxE = 0.5

    # construct initial conditions from timestep 1 (because Ed/Ew at zero are zero)
    E = 0.5 * (Ed[1, :, :] + Ew[1, :, :])

    # set up parameters
    Q = np.eye(9) * cfg['Q']
    P0 = np.eye(9) * cfg['P0']
    dt = (tm[1] - tm[0]).seconds
    print("INFO: Computed timestep from WRF is is %g seconds." % dt)
    K = np.zeros_like(E)
    V = np.zeros_like(E)
    mV = np.zeros_like(E)
    predicted_field = np.zeros_like(E)
    mresV = np.zeros_like(E)
    Kf_fn = np.zeros_like(E)
    Vf_fn = np.zeros_like(E)
    mid = np.zeros_like(E)
    Kg = np.zeros((dom_shape[0], dom_shape[1], 9))
    cV12 = np.zeros_like(E)

    # initialize the mean field model (default fit is 1.0 of equilibrium before new information comes in)
    mfm = MeanFieldModel(cfg['lock_gamma'])

    # construct model grid using standard fuel parameters
    Tk = np.array([1.0, 10.0, 100.0]) * 3600
    models = np.zeros(dom_shape, dtype=np.object)
    models_na = np.zeros_like(models)
    for p in np.ndindex(dom_shape):
        models[p] = CellMoistureModel((lat[p], lon[p]), 3, E[p], Tk, P0=P0)
        models_na[p] = CellMoistureModel((lat[p], lon[p]), 3, E[p], Tk, P0=P0)

    m = None
    plt.figure(figsize=(12, 8))

    ###  Run model for each WRF timestep and assimilate data when available
    for t in range(1, Nt):
        model_time = tm[t]
        print("INFO: time: %s, step: %d" % (str(model_time), t))

        # run the model update
        for p in np.ndindex(dom_shape):
            i, j = p
            models[p].advance_model(Ed[t - 1, i, j], Ew[t - 1, i, j],
                                    rain[t - 1, i, j], dt, Q)
            models_na[p].advance_model(Ed[t - 1, i, j], Ew[t - 1, i, j],
                                       rain[t - 1, i, j], dt, Q)

        # prepare visualization data
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        f_na = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]
            f_na[p[0], p[1], :] = models_na[p].get_state()[:3]
            P = models[p].get_state_covar()
            cV12[p] = P[0, 1]
            mV[p] = P[1, 1]
            mid[p] = models[p].get_model_ids()[1]

        diagnostics().push("fm10_model_var", (t, np.mean(mV)))

        # run Kriging on each observed fuel type
        Kf = []
        Vf = []
        fn = []
        for obs_data, fuel_ndx in [(obs_data_fm10, 1)]:

            # run the kriging subsystem and the Kalman update only if we have observations
            if model_time in obs_data:

                # retrieve observations for current time
                obs_t = obs_data[model_time]

                # fit the current estimation of the moisture field to the data
                base_field = f[:, :, fuel_ndx]
                mfm.fit_to_data(base_field, obs_data[model_time])

                # find differences (residuals) between observed measurements and nearest grid points
                # use this to update observation residual standard deviation
                obs_vals = np.array(
                    [o.get_value() for o in obs_data[model_time]])
                mod_vals = np.array([
                    base_field[o.get_nearest_grid_point()]
                    for o in obs_data[model_time]
                ])
                mod_na_vals = np.array([
                    f_na[:, :, fuel_ndx][o.get_nearest_grid_point()]
                    for o in obs_data[model_time]
                ])

                # predict the moisture field using observed fuel type
                predicted_field = mfm.predict_field(base_field)

                # krige observations to grid points
                Kf_fn, Vf_fn = trend_surface_model_kriging(
                    obs_data[model_time], wrf_data, predicted_field)

                krig_vals = np.array([
                    Kf_fn[o.get_nearest_grid_point()]
                    for o in obs_data[model_time]
                ])
                diagnostics().push(
                    "assim_data",
                    (t, fuel_ndx, obs_vals, krig_vals, mod_vals, mod_na_vals))
                plot_model_snapshot(cfg, tm, t, fuel_ndx, obs_vals, krig_vals,
                                    mod_vals, mod_na_vals)

                diagnostics().push("fm10_kriging_var", (t, np.mean(Vf_fn)))

                # append to storage for kriged fields in this time instant
                Kf.append(Kf_fn)
                Vf.append(Vf_fn)
                fn.append(fuel_ndx)

        # if there were any observations, run the kalman update step
        if len(fn) > 0:
            Nobs = len(fn)
            # run the kalman update in each model independently
            # gather the standard deviations of the moisture fuel after the Kalman update
            for p in np.ndindex(dom_shape):
                O = np.zeros((Nobs, ))
                V = np.zeros((Nobs, Nobs))

                # construct observations for this position
                for i in range(Nobs):
                    O[i] = Kf[i][p]
                    V[i, i] = Vf[i][p]

                # execute the Kalman update
                Kp = models[p].kalman_update(O, V, fn)
                Kg[p[0], p[1], :] = Kp[:, 0]

            # push new diagnostic outputs
            diagnostics().push("assim_K0", (t, np.mean(Kg[:, :, 0])))
            diagnostics().push("assim_K1", (t, np.mean(Kg[:, :, 1])))

        # prepare visualization data
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]

        plt.clf()
        plt.subplot(3, 3, 1)
        render_spatial_field_fast(m, lon, lat, f[:, :, 0], '1-hr fuel')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 2)
        render_spatial_field_fast(m, lon, lat, f[:, :, 1], '10-hr fuel')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 3)
        render_spatial_field_fast(m, lon, lat, f_na[:, :, 1],
                                  '10hr fuel - no assim')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 4)
        render_spatial_field_fast(m, lon, lat, Kg[:, :, 0],
                                  'Kalman gain for 1-hr fuel')
        plt.clim([0.0, 3.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 5)
        render_spatial_field_fast(m, lon, lat, Kg[:, :, 1],
                                  'Kalman gain for 10-hr fuel')
        plt.clim([0.0, 1.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 6)
        render_spatial_field_fast(m, lon, lat, Kf_fn, 'Kriging field')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 7)
        render_spatial_field_fast(m, lon, lat, mid, 'Model ids')
        plt.clim([0.0, 5.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 8)
        render_spatial_field_fast(m, lon, lat, Vf_fn, 'Kriging variance')
        plt.clim([0.0, np.max(Vf_fn)])
        plt.axis('off')
        plt.colorbar()
        #        plt.subplot(3,3,9)
        #        render_spatial_field_fast(m, lon, lat, mresV, 'Model variance')
        #        plt.clim([0.0, np.max(mresV)])
        #       plt.axis('off')
        #        plt.colorbar()

        plt.savefig(
            os.path.join(cfg['output_dir'], 'moisture_model_t%03d.png' % t))

    # store the diagnostics in a binary file
    diagnostics().dump_store(os.path.join(cfg['output_dir'],
                                          'diagnostics.bin'))

    # make a plot of gammas
    plt.figure()
    plt.plot(diagnostics().pull('mfm_gamma'), 'bo-')
    plt.title('Mean field model - gamma')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_gamma.png'))

    plt.figure()
    plt.plot(diagnostics().pull('skdm_cov_cond'))
    plt.title('Condition number of covariance matrix')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_sigma_cond.png'))

    # make a plot for each substation
    plt.figure()
    D = diagnostics().pull("assim_data")
    for i in range(len(stations)):
        plt.clf()
        # get data for the i-th station
        t_i = [o[0] for o in D]
        obs_i = [o[2][i] for o in D]
        krig_i = [o[3][i] for o in D]
        mod_i = [o[4][i] for o in D]
        mod_na_i = [o[5][i] for o in D]
        mx = max(max(obs_i), max(mod_i), max(krig_i), max(mod_i))
        plt.plot(t_i, obs_i, 'ro')
        plt.plot(t_i, krig_i, 'bo-')
        plt.plot(t_i, mod_i, 'kx-', linewidth=1.5)
        plt.plot(t_i, mod_na_i, 'mx-')
        plt.ylim([0.0, 1.1 * mx])
        plt.legend(['Obs.', 'Kriged', 'Model', 'NoAssim'])
        plt.title('Station observations fit to model and kriging field')
        plt.savefig(
            os.path.join(cfg['output_dir'], 'station%02d.png' % (i + 1)))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K1")],
             [d[1] for d in diagnostics().pull("assim_K1")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_10hr.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K0")],
             [d[1] for d in diagnostics().pull("assim_K0")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_1hr.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("fm10_model_var")],
             [d[1] for d in diagnostics().pull("fm10_model_var")], 'ro-')
    plt.title('Average fm10 model variance')
    plt.savefig(os.path.join(cfg['output_dir'],
                             'plot_fm10_model_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("fm10_model_residual_var")],
             [d[1] for d in diagnostics().pull("fm10_model_residual_var")],
             'ro-')
    plt.title('Average fm10 model residual variance')
    plt.savefig(
        os.path.join(cfg['output_dir'],
                     'plot_fm10_model_residual_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("fm10_kriging_var")],
             [d[1] for d in diagnostics().pull("fm10_kriging_var")], 'ro-')
    plt.title('Kriging field variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kriging_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("obs_residual_var")],
             [d[1] for d in diagnostics().pull("obs_residual_var")], 'ro-')
    plt.title('Observation residual variance')
    plt.savefig(
        os.path.join(cfg['output_dir'],
                     'plot_observation_residual_variance.png'))

    plt.figure()
    plt.plot(diagnostics().pull("mfm_mape"), 'ro-', linewidth=2)
    plt.title('Mean absolute prediction error of station data')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_station_mape.png'))
def run_module():

    # read in configuration file to execute run
    print("Reading configuration from [%s]" % sys.argv[1])

    with open(sys.argv[1]) as f:
        cfg = eval(f.read())

    # ensure output path exists
    if not os.path.isdir(cfg['output_dir']):
        os.mkdir(cfg['output_dir'])

    # configure diagnostics
    init_diagnostics(
        os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))
    diagnostics().configure_tag("skdm_obs_res", False, True, True)
    diagnostics().configure_tag("skdm_cov_cond", False, True, True)

    diagnostics().configure_tag("assim_mV", False, False, True)
    diagnostics().configure_tag("assim_K0", False, False, True)
    diagnostics().configure_tag("assim_K1", False, False, True)
    diagnostics().configure_tag("assim_data", False, False, True)
    diagnostics().configure_tag("assim_mresV", False, False, True)

    diagnostics().configure_tag("kriging_variance", False, False, True)
    diagnostics().configure_tag("kriging_obs_res_var", False, False, True)

    print("INFO: input file is [%s]." % cfg['input_file'])
    wrf_data = WRFModelData(cfg['input_file'], tz_name='US/Pacific')

    # read in vars
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    tm = wrf_data.get_local_times()
    rain = wrf_data['RAIN']
    Ed, Ew = wrf_data.get_moisture_equilibria()

    # find maximum moisture overall to set up visualization
    #    maxE = max(np.max(Ed), np.max(Ew)) * 1.2
    maxE = 0.3

    # obtain sizes
    Nt = rain.shape[0]
    dom_shape = lat.shape

    # load station data from files
    tz = pytz.timezone('US/Pacific')
    stations = [StationAdam() for s in station_list]
    for (s, sname) in zip(stations, station_list):
        s.load_station_data(os.path.join(station_data_dir, sname), tz)
        s.register_to_grid(wrf_data)
        s.set_measurement_variance('fm10', 0.05)

    # build the observation data structure indexed by time
    obs_data_fm10 = build_observation_data(stations, 'fm10', wrf_data, tm)

    # construct initial conditions
    E = 0.5 * (Ed[1, :, :] + Ew[1, :, :])

    # set up parameters
    Q = np.eye(9) * 0.001
    P0 = np.eye(9) * 0.01
    dt = 10.0 * 60
    K = np.zeros_like(E)
    V = np.zeros_like(E)
    mV = np.zeros_like(E)
    predicted_field = np.zeros_like(E)
    mresV = np.zeros_like(E)
    Kf_fn = np.zeros_like(E)
    Vf_fn = np.zeros_like(E)
    mid = np.zeros_like(E)
    Kg = np.zeros((dom_shape[0], dom_shape[1], 9))
    cV12 = np.zeros_like(E)

    # initialize the mean field model (default fit is 1.0 of equilibrium before new information comes in)
    mfm = MeanFieldModel(cfg['lock_gamma'])

    # construct model grid using standard fuel parameters
    Tk = np.array([1.0, 10.0, 100.0]) * 3600
    models = np.zeros(dom_shape, dtype=np.object)
    models_na = np.zeros_like(models)
    for pos in np.ndindex(dom_shape):
        models[pos] = CellMoistureModel((lat[pos], lon[pos]),
                                        3,
                                        E[pos],
                                        Tk,
                                        P0=P0)
        models_na[pos] = CellMoistureModel((lat[pos], lon[pos]),
                                           3,
                                           E[pos],
                                           Tk,
                                           P0=P0)

    m = None

    plt.figure(figsize=(12, 8))

    # run model
    for t in range(1, Nt):
        model_time = tm[t]
        print("Time: %s, step: %d" % (str(model_time), t))

        # pre-compute equilibrium moisture to save a lot of time
        E = 0.5 * (Ed[t, :, :] + Ew[t, :, :])

        # run the model update
        for pos in np.ndindex(dom_shape):
            i, j = pos
            models[pos].advance_model(Ed[t, i, j], Ew[t, i, j], rain[t, i, j],
                                      dt, Q)
            models_na[pos].advance_model(Ed[t, i, j], Ew[t, i, j],
                                         rain[t, i, j], dt, Q)

        # prepare visualization data
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        f_na = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]
            f_na[p[0], p[1], :] = models_na[p].get_state()[:3]
            mV[pos] = models[p].get_state_covar()[1, 1]
            cV12[pos] = models[p].get_state_covar()[0, 1]
            mid[p] = models[p].get_model_ids()[1]

        # run Kriging on each observed fuel type
        Kf = []
        Vf = []
        fn = []
        for obs_data, fuel_ndx in [(obs_data_fm10, 1)]:

            if model_time in obs_data:

                # fit the current estimation of the moisture field to the data
                base_field = f[:, :, fuel_ndx]
                mfm.fit_to_data(base_field, obs_data[model_time])

                # find differences (residuals) between observed measurements and nearest grid points
                # use this to update observation residual standard deviation
                obs_vals = np.array(
                    [o.get_value() for o in obs_data[model_time]])
                mod_vals = np.array([
                    f[:, :, fuel_ndx][o.get_nearest_grid_point()]
                    for o in obs_data[model_time]
                ])
                mod_na_vals = np.array([
                    f_na[:, :, fuel_ndx][o.get_nearest_grid_point()]
                    for o in obs_data[model_time]
                ])
                obs_re.update_with(obs_vals - mod_vals)
                diagnostics().push("kriging_obs_res_var",
                                   (t, np.mean(obs_re.get_variance())))

                # retrieve the variance of the model field
                mresV = mod_re.get_variance()

                # krige data to observations
                if cfg['kriging_strategy'] == 'uk':
                    Kf_fn, Vf_fn, gamma, mape = universal_kriging_data_to_model(
                        obs_data[model_time],
                        obs_re.get_variance()**0.5, base_field, wrf_data,
                        mresV**0.5, t)
                    # replace the stored gamma with the uk computed gamma
                    diagnostics().pull("mfm_gamma")[-1] = gamma
                    diagnostics().pull("mfm_mape")[-1] = mape
                    print("uk: replaced mfm_gamma %g, mfm_mape %g" %
                          (gamma, mape))

                    # update the residuals estimator with the current
                    mod_re.update_with(gamma * f[:, :, fuel_ndx] - Kf_fn)

                elif cfg['kriging_strategy'] == 'tsm':
                    # predict the moisture field using observed fuel type
                    predicted_field = mfm.predict_field(base_field)

                    # run the tsm kriging estimator
                    Kf_fn, Vf_fn = trend_surface_model_kriging(
                        obs_data[model_time], wrf_data, predicted_field)

                    # update the model residual estimator and get current best estimate of variance
                    mod_re.update_with(f[:, :, fuel_ndx] - predicted_field)

                else:
                    raise ValueError(
                        'Invalid kriging strategy [%s] in configuration.' %
                        cfg['kriiging_strategy'])

                krig_vals = np.array([
                    Kf_fn[o.get_nearest_grid_point()]
                    for o in obs_data[model_time]
                ])
                diagnostics().push(
                    "assim_data",
                    (t, fuel_ndx, obs_vals, krig_vals, mod_vals, mod_na_vals))
                plot_model_snapshot(cfg, tm, t, fuel_ndx, obs_vals, krig_vals,
                                    mod_vals, mod_na_vals)

                # append to storage for kriged fields in this time instant
                Kf.append(Kf_fn)
                Vf.append(Vf_fn)
                fn.append(fuel_ndx)

        # if there were any observations, run the kalman update step
        if len(fn) > 0:
            Nobs = len(fn)
            # run the kalman update in each model independently
            # gather the standard deviations of the moisture fuel after the Kalman update
            for pos in np.ndindex(dom_shape):
                O = np.zeros((Nobs, ))
                V = np.zeros((Nobs, Nobs))

                # construct observations for this position
                for i in range(Nobs):
                    O[i] = Kf[i][pos]
                    V[i, i] = Vf[i][pos]

                # execute the Kalman update
                Kij = models[pos].kalman_update(O, V, fn)
                Kg[pos[0], pos[1], :] = Kij[:, 0]

        # prepare visualization data
        f = np.zeros((dom_shape[0], dom_shape[1], 3))
        for p in np.ndindex(dom_shape):
            f[p[0], p[1], :] = models[p].get_state()[:3]

        plt.clf()
        plt.subplot(3, 3, 1)
        render_spatial_field_fast(m, lon, lat, f[:, :, 0], '1-hr fuel')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 2)
        render_spatial_field_fast(m, lon, lat, f[:, :, 1], '10-hr fuel')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 3)
        render_spatial_field_fast(m, lon, lat, f_na[:, :, 1],
                                  '10hr fuel - no assim')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 4)
        render_spatial_field_fast(m, lon, lat, Kg[:, :, 0], 'Kalman gain, fm1')
        plt.clim([0.0, 3.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 5)
        render_spatial_field_fast(m, lon, lat, Kg[:, :, 1],
                                  'Kalman gain, fm10')
        plt.clim([0.0, 1.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 6)
        render_spatial_field_fast(m, lon, lat, Kf_fn, 'Kriging field')
        plt.clim([0.0, maxE])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 7)
        render_spatial_field_fast(m, lon, lat, mid, 'Model ids')
        plt.clim([0.0, 5.0])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 8)
        render_spatial_field_fast(m, lon, lat, Vf_fn, 'Kriging var')
        plt.clim([0.0, np.max(Vf_fn)])
        plt.axis('off')
        plt.colorbar()
        plt.subplot(3, 3, 9)
        render_spatial_field_fast(m, lon, lat, mresV, 'fm10 model var')
        plt.clim([0.0, np.max(mresV)])
        plt.axis('off')
        plt.colorbar()

        plt.savefig(
            os.path.join(cfg['output_dir'], 'moisture_model_t%03d.png' % t))

        # push new diagnostic outputs
        diagnostics().push("assim_K0", (t, np.mean(Kg[:, :, 0])))
        diagnostics().push("assim_K1", (t, np.mean(Kg[:, :, 1])))
        diagnostics().push("assim_mV", (t, np.mean(mV)))
        diagnostics().push("assim_mresV", (t, np.mean(mresV)))
        diagnostics().push("kriging_variance", (t, np.mean(Vf_fn)))

    # store the gamma coefficients
    with open(os.path.join(cfg['output_dir'], 'gamma.txt'), 'w') as f:
        f.write(str(diagnostics().pull('mfm_gamma')))

    # make a plot of gammas
    plt.figure()
    plt.plot(diagnostics().pull('mfm_gamma'))
    plt.title('Mean field model - gamma')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_gamma.png'))

    plt.figure()
    plt.plot(diagnostics().pull('skdm_cov_cond'))
    plt.title('Condition number of covariance matrix')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_sigma_cond.png'))

    # make
    # make a plot for each substation
    plt.figure()
    D = diagnostics().pull("assim_data")
    for i in range(len(stations)):
        plt.clf()
        # get data for the i-th station
        t_i = [o[0] for o in D]
        obs_i = [o[2][i] for o in D]
        krig_i = [o[3][i] for o in D]
        mod_i = [o[4][i] for o in D]
        mod_na_i = [o[5][i] for o in D]
        mx = max(max(obs_i), max(mod_i), max(krig_i), max(mod_i))
        plt.plot(t_i, obs_i, 'ro')
        plt.plot(t_i, krig_i, 'bo-')
        plt.plot(t_i, mod_i, 'kx-', linewidth=1.5)
        plt.plot(t_i, mod_na_i, 'mx-')
        plt.ylim([0.0, 1.1 * mx])
        plt.legend(['Obs.', 'Kriged', 'Model', 'NoAssim'])
        plt.title('Station observations fit to model and kriging field')
        plt.savefig(
            os.path.join(cfg['output_dir'], 'station%02d.png' % (i + 1)))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K1")],
             [d[1] for d in diagnostics().pull("assim_K1")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_10hr.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_K0")],
             [d[1] for d in diagnostics().pull("assim_K0")], 'ro-')
    plt.title('Average Kalman gain')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kalman_gain_1hr.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_mV")],
             [d[1] for d in diagnostics().pull("assim_mV")], 'ro-')
    plt.title('Average model variance')
    plt.savefig(os.path.join(cfg['output_dir'],
                             'plot_fm10_model_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("assim_mresV")],
             [d[1] for d in diagnostics().pull("assim_mresV")], 'ro-')
    plt.title('Average fm10 residual variance')
    plt.savefig(
        os.path.join(cfg['output_dir'],
                     'plot_fm10_model_residual_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("kriging_variance")],
             [d[1] for d in diagnostics().pull("kriging_variance")], 'ro-')
    plt.title('Kriging field variance')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_kriging_variance.png'))

    plt.figure()
    plt.plot([d[0] for d in diagnostics().pull("kriging_obs_res_var")],
             [d[1] for d in diagnostics().pull("kriging_obs_res_var")], 'ro-')
    plt.title('Observation residual variance')
    plt.savefig(
        os.path.join(cfg['output_dir'],
                     'plot_observation_residual_variance.png'))

    plt.figure()
    plt.plot(diagnostics().pull("mfm_mape"), 'ro-', linewidth=2)
    plt.title('Mean absolute prediction error of station data')
    plt.savefig(os.path.join(cfg['output_dir'], 'plot_station_mape.png'))

    diagnostics().dump_store(os.path.join(cfg['output_dir'],
                                          'diagnostics.bin'))

    # as a last step encode all the frames as video
    os.system(
        "cd %s; avconv -qscale 1 -r 20 -b 9600 -i moisture_model_t%%03d.png video.mp4"
        % cfg['output_dir'])
Esempio n. 29
0
def run_module():

    # read in configuration file to execute run
    print("Reading configuration from [%s]" % sys.argv[1])

    with open(sys.argv[1]) as f:
        cfg = eval(f.read())

    # ensure output path exists
    if not os.path.isdir(cfg['output_dir']):
        os.mkdir(cfg['output_dir'])

    # configure diagnostics
    init_diagnostics(os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))

    # Trend surface model diagnostics
    diagnostics().configure_tag("kriging_cov_cond", True, True, True)
    diagnostics().configure_tag("s2_eta_hat", True, True, True)
    diagnostics().configure_tag("kriging_rmse", True, True, True)
    diagnostics().configure_tag("kriging_beta", True, True, True)
    diagnostics().configure_tag("kriging_iters", False, True, True)
    diagnostics().configure_tag("kriging_subzero_s2_estimates", False, True, True)
    diagnostics().configure_tag("fm10_kriging_var", True, True, True)

    diagnostics().configure_tag("f0_summary", True, True, True)
    diagnostics().configure_tag("f1_summary", True, True, True)
    diagnostics().configure_tag("f2_summary", True, True, True)
    diagnostics().configure_tag("f3_summary", True, True, True)

    # Assimilation parameters
    diagnostics().configure_tag("K0_summary", True, True, True)
    diagnostics().configure_tag("K1_summary", True, True, True)
    diagnostics().configure_tag("K2_summary", True, True, True)
    diagnostics().configure_tag("K3_summary", True, True, True)
    diagnostics().configure_tag("assim_info", False, False, True)

    # Model forecast, analysis and non-assimilated model: state, covariance, errors
    diagnostics().configure_tag("fm10f_rmse", True, True, True)
    diagnostics().configure_tag("fm10na_rmse", True, True, True)
    
    # all simulation times and all assimilation times (subset)
    diagnostics().configure_tag("mta", False, True, True)
    diagnostics().configure_tag("mt", False, True, True)

    # observation values and their nearest grid points
    diagnostics().configure_tag("obs_vals", False, True, True)
    diagnostics().configure_tag("obs_ngp", False, True, True)

    # in test mode, we will emit observations at the target station
    # our predictions, the nearest grid point and the test station id
    diagnostics().configure_tag("test_obs", True, True, True)
    diagnostics().configure_tag("test_pred", True, True, True)
    diagnostics().configure_tag("test_ngp", True, True, True)
    diagnostics().configure_tag("test_station_id", True, True, True)

    ### Load and preprocess WRF model data

    # load WRF data
    wrf_data = WRFModelData(cfg['wrf_output'],  ['T2', 'Q2', 'PSFC', 'RAINNC', 'RAINC', 'HGT'])
    wrf_data.slice_field('HGT')

    # read in spatial and temporal extent of WRF variables
    lat, lon = wrf_data.get_lats(), wrf_data.get_lons()
    hgt = wrf_data['HGT']
    tm = wrf_data.get_gmt_times()
    Nt = cfg['Nt'] if cfg.has_key('Nt') and cfg['Nt'] is not None else len(tm)
    dom_shape = lat.shape
    print('INFO: domain size is %d x %d grid points.' % dom_shape)
    print('INFO: domain extent is lats (%g to %g) lons (%g to %g).' % (np.amin(lat),np.amax(lat),np.amin(lon),np.amax(lon)))

    # if writing is requested, open output file and set up dimensions 
    if cfg['write_fields'] not in [ 'all', 'fmc_gc', 'none']:
        error('FATAL: write_fields must be one of all, fmc_gc or none.')
    if cfg['write_fields'] == 'none':
      cfg['write_fields'] = False
    out_file = None
    ncfmc_gc, ncfm10a, ncfm10aV, ncfm10f, cnfm10fV, ncfm10na = None, None, None, None, None, None
    nctsmV, ncKg = None, None
    if cfg['write_fields']:
        out_file = netCDF4.Dataset(cfg['output_dir'] + '/fields.nc', 'w')
        out_file.createDimension('Time', None)
        out_file.createDimension('fuel_moisture_classes_stag', 5)
        out_file.createDimension('south_north', dom_shape[0])
        out_file.createDimension('west_east', dom_shape[1])
        ncfmc_gc = out_file.createVariable('FMC_GC', 'f4', ('Time', 'fuel_moisture_classes_stag', 'south_north', 'west_east'))
        if cfg['write_fields'] == 'all':
            ncfm10a = out_file.createVariable('fm10a', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10aV = out_file.createVariable('fm10a_var', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10na = out_file.createVariable('fm10na', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10f = out_file.createVariable('fm10f', 'f4', ('Time', 'south_north', 'west_east'))
            ncfm10fV = out_file.createVariable('fm10f_var', 'f4', ('Time', 'south_north', 'west_east'))
            nctsmV = out_file.createVariable('tsm_var', 'f4', ('Time', 'south_north', 'west_east'))
            ncKg = out_file.createVariable('kalman_gain', 'f4', ('Time', 'south_north', 'west_east'))
            print('INFO: opened fields.nc for writing ALL output fields.')
        else:
            print('INFO: opened field.nc for writing FMC_GC only.')

    test_mode = (cfg['run_mode'] == 'test')
    tgt_station = None
    if cfg['run_mode'] == 'test':
      print('INFO: running in TEST mode! Will perform leave-one-out tesing.')
      tgt_station_id = cfg['target_station_id']
      diagnostics().push('test_station_id', tgt_station_id)
    elif cfg['run_mode'] == 'production':
      print('INFO: running in PRODUCTION mode! Using all observation stations.')
    else:
      error('FATAL: invalid run mode! Must be "test" or "production".')

    # determine simulation times
    tm_start = parse_datetime(cfg['start_time']) if cfg['start_time'] is not None else tm[0]
    tm_end = parse_datetime(cfg['end_time']) if cfg['end_time'] is not None else tm[-1]

    # if the required start time or end time are outside the simulation domain, exit with an error
    if tm_start < tm[0] or tm_end > tm[-1]:
        print('FATAL: invalid time range, required [%s-%s], availble [%s-%s]' %
              (str(tm_start), str(tm_end), str(tm[0]), str(tm[-1])))
        sys.exit(2)

    print('INFO: time limits are %s to %s\nINFO: simulation is from %s to %s' %
          (str(tm_start), str(tm_end), str(tm[0]), str(tm[-1])))

    # retrieve dynamic covariates and remove mean at each time point for T2 and PSFC
    T2 = wrf_data['T2']
    #T2 -= np.mean(np.mean(T2,axis=0),axis=0)[np.newaxis,np.newaxis,:]

    PSFC = wrf_data['PSFC']
    #PSFC -= np.mean(np.mean(PSFC,axis=0),axis=0)[np.newaxis,np.newaxis,:]

    # numerical fix - if it rains at an intensity of less than 0.001 per hour, set rain to zero
    # also, use log(rain + 1) to prevent wild trend surface model predictions when stations see little rain
    # but elsewhere there is too much rain
    # without this, numerical errors in trend surface model may pop up
    rain = wrf_data['RAIN']
    #rain[rain < 0.01] = 0.0
    rain = np.log(rain + 1.0)

    # moisture equilibria are now computed from averaged Q,P,T at beginning and end of period
    Ed, Ew = wrf_data.get_moisture_equilibria()

    ### Load observation data from the stations

    # compute the diagonal distance between grid points
    grid_dist_km = great_circle_distance(lon[0,0], lat[0,0], lon[1,1], lat[1,1])
    print('INFO: diagonal distance in grid is %g' % grid_dist_km)

    # load station data from files
    with open(cfg['station_list_file'], 'r') as f:
        si_list = f.read().split('\n')

    si_list = filter(lambda x: len(x) > 0 and x[0] != '#', map(string.strip, si_list))

    # for each station id, load the station
    stations = []
    for code in si_list:
        mws = MesoWestStation(code)
        mws.load_station_info(os.path.join(cfg["station_info_dir"], "%s.info" % code))
        mws.register_to_grid(wrf_data)
        if mws.get_dist_to_grid() < grid_dist_km / 2.0:
            print('Station %s: lat %g lon %g nearest grid pt %s lat %g lon %g dist_to_grid %g' %
               (code, mws.lat, mws.lon, str(mws.grid_pt), lat[mws.grid_pt], lon[mws.grid_pt], mws.dist_grid_pt))
            mws.load_station_data(os.path.join(cfg["station_data_dir"], "%s.obs" % code))
            if test_mode and mws.get_id() == tgt_station_id:
                tgt_station = mws
                print('INFO: in test mode, targeting station %s (removed from data pool).' % tgt_station_id)
                diagnostics().push("test_ngp", mws.get_nearest_grid_point())
            else:
                stations.append(mws)

    print('Loaded %d stations (discarded %d stations, too far from grid).' % (len(stations), len(si_list) - len(stations)))

    if test_mode and tgt_station is None:
      error('FATAL: in test mode, a station was removed that was not among accepted stations.')

    # build the observation data
    obs_data_fm10 = build_observation_data(stations, 'FM')

    # build target data if in test mode
    tgt_obs_fm10 = None
    test_ngp = None
    if test_mode:
      test_ngp = tgt_station.get_nearest_grid_point()
      tgt_obs_fm10 = build_observation_data([tgt_station], 'FM')

    ### Initialize model and visualization

    # construct initial conditions from timestep 0
    E = 0.5 * (Ed[0,:,:] + Ew[0,:,:])

    # set up parameters
    Nk = 4  # we simulate 4 types of fuel
    Q = np.diag(cfg['Q'])
    P0 = np.diag(cfg['P0'])
    Tk = np.array([1.0, 10.0, 100.0, 1000.0]) * 3600
    dt = (tm[1] - tm[0]).seconds
    print("INFO: Computed timestep from WRF is is %g seconds." % dt)
    mresV = np.zeros_like(E)
    mid = np.zeros_like(E)
    Kg = np.zeros((dom_shape[0], dom_shape[1], len(Tk)+2))

    # preprocess all static covariates
    cov_ids = cfg['covariates']
    Xd3 = len(cov_ids) + 1
    X = np.zeros((dom_shape[0], dom_shape[1], Xd3))
    Xr = np.zeros((dom_shape[0], dom_shape[1], Xd3))
    static_covar_map = { "lon" : lon - np.mean(lon), "lat" : lat - np.mean(lat), "elevation" : hgt - np.mean(hgt), "constant" : np.ones(dom_shape) }
    dynamic_covar_map = { "temperature" : T2, "pressure" : PSFC, "rain" : rain }

    for i in range(1, Xd3):
        cov_id = cov_ids[i-1]
        if cov_id in static_covar_map:
          print('INFO: found static covariate %s' % cov_id)
          Xr[:, :, i] = static_covar_map[cov_id]
        elif cov_id in dynamic_covar_map:
          print('INFO: found dynamic covariate %s' % cov_id)
        else:
          print('FATAL: unknown covariate %s encountered' % cov_id)
          sys.exit(2)

    print("INFO: there are %d covariates (including model state)" % Xd3)

    # retrieve assimilation time window
    assim_time_win = cfg['assimilation_time_window']

    print('GMM init: equilibrium (%g,%g,%g) and at 86,205 %g' % (np.amin(E),np.mean(E),np.amax(E),E[86,205]))

    models = GridMoistureModel(E[:,:,np.newaxis][:,:,np.zeros((4,),dtype=np.int)], Tk, P0)
    models_na = GridMoistureModel(E[:,:,np.newaxis][:,:,np.zeros((4,),dtype=np.int)], Tk, P0)

    ###  Run model for each WRF timestep and assimilate data when available
    t_start, t_end = 1, len(tm)-1
    while tm_start > tm[t_start]:
        t_start+=1
    while tm_end < tm[t_end]:
        t_end-=1

    # the first FMC_GC value gets filled out with equilibria
    if cfg['write_fields']:
        for i in range(Nk):
            ncfmc_gc[0, i, :, :] = E

    print('INFO: running simulation from %s (%d) to %s (%d).' % (str(tm[t_start]), t_start, str(tm[t_end]), t_end))
    for t in range(t_start, t_end+1):
        model_time = tm[t]
        print("INFO: time: %s, step: %d" % (str(model_time), t))

        diagnostics().push("mt", model_time)

        models_na.advance_model(Ed[t-1,:,:], Ew[t-1,:,:], rain[t-1,:,:], dt, Q)
        models.advance_model(Ed[t-1,:,:], Ew[t-1,:,:], rain[t-1,:,:], dt, Q)

        # extract fuel moisture contents [make a fresh copy every iteration!]
        f = models.get_state().copy()
        f_na = models_na.get_state().copy()

        # push 10-hr fuel state & variance of forecast
        if cfg['write_fields'] == 'all':
            ncfm10f[t,:,:] = models.get_state()[:,:,1]
            ncfm10fV[t,:,:] = models.P[:,:,1,1]
            ncfm10na[t,:,:] = models_na.get_state()[:,:,1]


        # examine the assimilated fields (if assimilation is activated)
        for i in range(4):
            diagnostics().push("f%d_summary" % i, (t, np.amin(f[:,:,i]), np.mean(f[:,:,i]), np.amax(f[:,:,i])))
            if np.any(f[:,:,i] < 0.0):
                print("WARN: in field %d there were %d negative moisture values !" % (i, np.count_nonzero(f[:,:,i] < 0.0)))
                ind = np.unravel_index(np.argmin(f[:,:,i]), f.shape[:2])
                print(models.P[ind[0],ind[1],:,:])
                print("Full model state at position %d,%d:" % (ind[0],ind[1]))
                print(models.m_ext[ind[0],ind[1],:])
            if np.any(f[:,:,i] > 2.5):
                print("WARN: in field %d there were %d moisture values above 2.5!" % (i, np.count_nonzero(f[:,:,i] > 2.5)))
                ind = np.unravel_index(np.argmax(f[:,:,i]), f.shape[:2])
                print(models.P[ind[0],ind[1],:,:])
                print("Full model state at position %d,%d:" % (ind[0],ind[1]))
                print(models.m_ext[ind[0],ind[1],:])

        if cfg['assimilate']:

            # run Kriging on each observed fuel type
            Kfs, Vfs, fns = [], [], []
            for obs_data, fuel_ndx in [ (obs_data_fm10, 1) ]:

                # run the kriging subsystem and the Kalman update only if have valid observations
                valid_times = [z for z in obs_data.keys() if abs(total_seconds(z - model_time)) < assim_time_win/2.0]
                print('INFO: there are %d valid times at model time %s for fuel index %d' % (len(valid_times), str(model_time), fuel_ndx))
                if len(valid_times) > 0:

                    # add model time as time when assimilation occurred
                    diagnostics().push("mta", model_time)

                    # retrieve observations for current time
                    obs_valid_now = []
                    for z in valid_times:
                        obs_valid_now.extend(obs_data[z])

                    print('INFO: model time %s, assimilating %d observations.' % (str(model_time), len(obs_valid_now)))

                    # construct covariates for this time instant
                    X[:,:,0] = f[:,:,fuel_ndx]
                    for i in range(1, Xd3):
                      cov_id = cov_ids[i-1]
                      if cov_id in static_covar_map:
                        X[:, :, i] = Xr[:, :, i]
                      elif cov_id in dynamic_covar_map:
                        F = dynamic_covar_map[cov_id]
                        X[:, :, i] = F[t, :, :]
                      else:
                        error('FATAL: found unknown covariate %s' % cov_id)

                    # find differences (residuals) between observed measurements and nearest grid points
                    obs_vals = [o.get_value() for o in obs_valid_now]
                    obs_ngp  = [o.get_nearest_grid_point() for o in obs_valid_now]
                    diagnostics().push("obs_vals", obs_vals)
                    diagnostics().push("obs_ngp", obs_ngp)

                    mod_vals    = np.array([f[i,j,fuel_ndx] for i,j in obs_ngp])
                    mod_na_vals = np.array([f_na[i,j,fuel_ndx] for i,j  in obs_ngp])
                    diagnostics().push("fm10f_rmse", np.mean((obs_vals - mod_vals)**2)**0.5)
                    diagnostics().push("fm10na_rmse", np.mean((obs_vals - mod_na_vals)**2)**0.5)

                    # krige observations to grid points
                    Kf_fn, Vf_fn = fit_tsm(obs_valid_now, X)
                    if np.count_nonzero(Kf_fn > 2.5) > 0:
                        rain_t = dynamic_covar_map['rain'][t,:,:]
                        print('WARN: in TSM found %d values over 2.5, %d of those had rain, clamped to 2.5' %
                                (np.count_nonzero(Kf_fn > 2.5),
                                 np.count_nonzero(np.logical_and(Kf_fn > 2.5, rain_t > 0.0))))
                        Kf_fn[Kf_fn > 2.5] = 2.5
                    if np.count_nonzero(Kf_fn < 0.0) > 0:
                        print('WARN: in TSM found %d values under 0.0, clamped to 0.0' % np.count_nonzero(Kf_fn < 0.0))
                        Kf_fn[Kf_fn < 0.0] = 0.0

                    krig_vals = np.array([Kf_fn[ngp] for ngp in obs_ngp])
                    diagnostics().push("assim_info", (t, fuel_ndx, obs_vals, krig_vals, mod_vals, mod_na_vals))
                    diagnostics().push("fm10_kriging_var", (t, np.mean(Vf_fn)))

                    if cfg['write_fields'] == 'all':
                        nctsmV[t,:,:] = Vf_fn

                    # append to storage for kriged fields in this time instant
                    Kfs.append(Kf_fn)
                    Vfs.append(Vf_fn)
                    fns.append(fuel_ndx)


            # if there were any observations, run the kalman update step
            if len(fns) > 0:
                NobsClasses = len(fns)

                O = np.zeros((dom_shape[0], dom_shape[1], NobsClasses))
                V = np.zeros((dom_shape[0], dom_shape[1], NobsClasses, NobsClasses))

                for i in range(NobsClasses):
                    O[:,:,i] = Kfs[i]
                    V[:,:,i,i] = Vfs[i]

                # execute the Kalman update
                if len(fns) == 1:
                    models.kalman_update_single2(O, V, fns[0], Kg)
                else:
                    models.kalman_update(O, V, fns, Kg)

                # push new diagnostic outputs
                if cfg['write_fields'] == 'all':
                    ncKg[t,:,:] = Kg[:,:,1]

                for i in range(4):
                    diagnostics().push("K%d_summary" % i, (t, np.amin(Kg[:,:,i]), np.mean(Kg[:,:,i]), np.amax(Kg[:,:,i])))
                    if np.any(models.get_state()[:,:,i] < 0.0):
                        print("WARN: in field %d there were %d negative moisture values !" % (i, np.count_nonzero(models.get_state()[:,:,i] < 0.0)))
                        ind = np.unravel_index(np.argmin(models.get_state()[:,:,i]), models.get_state().shape[:2])
                        print(models.P[ind[0],ind[1],:,:])
                        print("TSM input at given position: value %g variance %g" % (O[ind[0],ind[1]], V[ind[0],ind[1]]))
                        print("Model state at given position:")
                        print(models.m_ext[ind[0],ind[1],:])

            # store post-assimilation (or forecast depending on whether observations were available) FM-10 state and variance
            if cfg['write_fields'] == 'all':
                ncfm10a[t,:,:] = models.get_state()[:,:,1]
                ncfm10aV[t,:,:] = models.P[:,:,1,1]

            # we don't care if we assimilated or not, we always check our error on target station if in test mode
            if test_mode:
                valid_times = [z for z in tgt_obs_fm10.keys() if abs(total_seconds(z - model_time)) < assim_time_win/2.0]
                tgt_i, tgt_j = test_ngp
                diagnostics().push("test_pred", f[tgt_i, tgt_j,1])
                if len(valid_times) > 0:
                  # this is our target observation [FIXME: this disregards multiple observations if multiple happen to be valid]
                  tgt_obs = tgt_obs_fm10[valid_times[0]][0]
                  obs = tgt_obs.get_value()
                  diagnostics().push("test_obs", obs)
                else:
                  diagnostics().push("test_obs", np.nan)


            # store data in wrf_file variable FMC_G
            if cfg['write_fields']:
                ncfmc_gc[t,:Nk,:,:] = np.transpose(models.get_state()[:,:,:Nk],axes=[2,0,1])

        # store the diagnostics in a binary file when done
    diagnostics().dump_store(os.path.join(cfg['output_dir'], 'diagnostics.bin'))

    # close the netCDF file (relevant if we did write into FMC_GC)
    if out_file is not None:
        out_file.close()
Esempio n. 30
0
#!/usr/bin/python

from os import mkdir
from os.path import splitext, dirname, sep, join, exists, basename
from codecs import open
from diagnostics import diagnostics, known_compilers, FontError

diagnostics = diagnostics()

class Compiler:
    def __init__(self,infiles,webfonts=False,afdko=False):
        # we strip trailing slashes from ufo names,
        # otherwise we get confused later on when
        # generating filenames:
        self.infiles = [i.strip(sep) for i in infiles]
        self.webfonts = webfonts
        self.css = ''

        if afdko:
            if diagnostics['afdko']:
                self.compile = self.afdko
            else:
                raise FontError("afdko", diagnostics)
        else:
            if diagnostics['fontforge']:
                self.compile = self.fontforge
            else:
                raise FontError("fontforge", diagnostics)

    def fontforge(self):
        import fontforge
Esempio n. 31
0
def run_module():
    # read in configuration file to execute run
    print("Reading configuration from [%s]" % sys.argv[1])

    with open(sys.argv[1]) as f:
        cfg = eval(f.read())

    # init diagnostics
    init_diagnostics(
        os.path.join(cfg['output_dir'], 'moisture_model_v1_diagnostics.txt'))
    diagnostics().configure_tag("s2_eta_hat", True, True, True)
    diagnostics().configure_tag("kriging_rmse", True, True, True)
    diagnostics().configure_tag("kriging_beta", True, True, True)
    diagnostics().configure_tag("kriging_iters", False, True, True)
    diagnostics().configure_tag("kriging_subzero_s2_estimates", False, True,
                                True)

    # load the wrfinput file
    wrfin = WRFModelData(cfg['wrf_input'],
                         ['T2', 'Q2', 'PSFC', 'HGT', 'FMC_GC', 'FMEP'])
    lat, lon = wrfin.get_lats(), wrfin.get_lons()
    ts_now = wrfin['GMT'][0]
    dom_shape = lat.shape
    print('INFO: domain size is %d x %d grid points, wrfinput timestamp %s' %
          (dom_shape[0], dom_shape[1], str(ts_now)))
    print('INFO: domain extent is lats (%g to %g) lons (%g to %g).' %
          (np.amin(lat), np.amax(lat), np.amin(lon), np.amax(lon)))

    # compute the diagonal distance between grid points
    grid_dist_km = great_circle_distance(lon[0, 0], lat[0, 0], lon[1, 1],
                                         lat[1, 1])
    print('INFO: diagonal distance in grid is %g' % grid_dist_km)

    # load observations but discard those too far away from the grid nodes
    obss = load_raws_observations(cfg['observations'], lat, lon, grid_dist_km)
    fm10 = build_observation_data(obss)
    print('INFO: %d different time instances found in observations' %
          len(fm10))

    # if a previous cycle is available (i.e. the wrfoutput is a valid file)
    if os.path.exists(cfg['wrf_output_prev']) and check_overlap(
            cfg['wrf_output_prev'], ts_now):

        # load the model as a wrfout with all default variables
        wrfout = WRFModelData(cfg['wrf_output_prev'])
        outts = wrfout['GMT']
        print("INFO: previous forecast [%s - %s] exists, running DA till %s" %
              (str(outts[0]), str(outts[-1]), str(ts_now)))

        # run from the start until now (retrieve fuel moisture, extended parameters, covariance matrix)
        model = run_data_assimilation(wrfout, fm10, ts_now, cfg)
        # store this for the current time instance (fm, ep in the wrfinput, P next to it)
        d = netCDF4.Dataset(cfg['wrf_input'], 'r+')
        d.variables['FMC_GC'] = fm
        d.variables['FMEP'] = ep
        d.close()

        # store the covariance matrix alongside the wrfinput file
        dir = os.path.dirname(wrfin)
        store_covariance_matrix(P, os.path.join(dir, 'P.nc'))

    else:

        print(
            "INFO: no previous forecast found, running DA from equilibrium at %s"
            % (str(ts_now)))
        # initialize from weather equilibrium and perform one DA step
        model = init_from_equilibrium(wrfin, fm10, ts_now, cfg)

        # store result in wrfinput dataset
        d = netCDF4.Dataset(cfg['wrf_input'], 'r+')
        fmcep = model.get_state()
        d.variables['FMC_GC'][0, :3, :, :] = fmcep[:, :, :3].transpose(
            (2, 0, 1))
        d.variables['FMEP'][0, :, :, :] = fmcep[:, :, 3:5].transpose((2, 0, 1))
        d.close()
        store_covariance_matrix(
            model.get_state_covar(),
            os.path.join(os.path.dirname(cfg['wrf_input']), 'P.nc'))

    return 0
Esempio n. 32
0
def fit_tsm(obs_data, X):
    """
    Trend surface model kriging, which assumes spatially uncorrelated errors.
    The kriging results in the matrix K, which contains the kriged observations
    and the matrix V, which contains the kriging variance.
    """
    Nobs = len(obs_data)

    # we ensure we have at most Nobs covariates
    Nallcov = min(X.shape[2], Nobs)

    # the matrix of covariates
    Xobs = np.zeros((Nobs, Nallcov))

    # outputs
    K = np.zeros(X[:, :, 0].shape)
    V = np.zeros_like(K)

    # the vector of target observations
    y = np.zeros((Nobs, 1))

    # the vector of observation variances
    obs_var = np.zeros((Nobs, ))

    # fill out matrix/vector structures
    for (obs, i) in zip(obs_data, range(Nobs)):
        p = obs.get_nearest_grid_point()
        y[i, 0] = obs.get_value()
        Xobs[i, :] = X[p[0], p[1], :Nallcov]
        obs_var[i] = obs.get_variance()

    # remove covariates that contain only zeros
    norms = np.sum(Xobs**2, axis=0)**0.5
    nz_covs = np.nonzero(norms)[0]
    Ncov = len(nz_covs)
    X = X[:, :, nz_covs]
    Xobs = Xobs[:, nz_covs]
    norms = norms[nz_covs]

    # normalize all covariates
    for i in range(1, Ncov):
        scalar = norms[0] / norms[i]
        Xobs[:, i] *= scalar
        X[:, :, i] *= scalar

    Xobs = np.asmatrix(Xobs)

    # initialize the iterative algorithm
    s2_eta_hat_old = 10.0
    s2_eta_hat = 0.0
    iters = 0
    subzeros = 0
    res2 = None
    XtSX = None
    equal_variance_flag = np.all(obs_var == obs_var[0])

    if equal_variance_flag:
        # use a much faster algorithm that requires no iterations
        Q, R = np.linalg.qr(Xobs)
        beta = np.linalg.solve(R, np.asmatrix(Q).T * y)
        res2 = np.asarray(y - Xobs * beta)[:, 0]**2
        gamma2 = obs_var[0]
        if Nobs > Ncov:
            s2_eta_hat = max(1.0 / (Nobs - Ncov) * np.sum(res2) - gamma2, 0.0)
        else:
            s2_eta_hat = 0.0
        XtSX = 1.0 / (s2_eta_hat + gamma2) * (Xobs.T * Xobs)
        iters = -1
        subzeros = 0

    else:

        # while the relative change is more than 0.1%
        while abs(
            (s2_eta_hat_old - s2_eta_hat) / max(s2_eta_hat_old, 1e-8)) > 1e-3:
            #print('TSM: iter %d s_eta_hat_old %g s2_eta_hat %g' % (iters, s2_eta_hat_old, s2_eta_hat))
            s2_eta_hat_old = s2_eta_hat

            # recompute covariance matrix
            Sigma_diag = obs_var + s2_eta_hat
            Sigma = np.diag(Sigma_diag)
            Sigma_1 = np.diag(1.0 / Sigma_diag)
            XtSX = Xobs.T * Sigma_1 * Xobs
            #print('TSM: XtSX = %s' % str(XtSX))

            # QR solution method of the least squares problem
            Sigma_1_2 = np.asmatrix(np.diag(Sigma_diag**-0.5))
            yt = Sigma_1_2 * y
            Q, R = np.linalg.qr(Sigma_1_2 * Xobs)
            beta = np.linalg.solve(R, np.asmatrix(Q).T * yt)
            res2 = np.asarray(y - Xobs * beta)[:, 0]**2
            #        print('TSM: beta %s res2 %s' % (str(beta), str(res2)))

            # compute new estimate of variance of microscale variability
            s2_array = res2 - obs_var
            for i in range(len(s2_array)):
                s2_array[i] += np.dot(Xobs[i, :],
                                      np.linalg.solve(XtSX, Xobs[i, :].T))

#        print('TSM: s2_array %s' % str(s2_array))
            s2_eta_hat = numerical_solve_bisect(res2, obs_var, Ncov)
            if s2_eta_hat < 0.0:
                #          print("TSM: s2_eta_hat estimate below zero")
                s2_eta_hat = 0.0

#        print('TSM: s2_eta_hat %g' % s2_eta_hat)

            subzeros = np.count_nonzero(s2_array < 0.0)
            iters += 1

    # map computed betas to original (possibly extended) betas which include unused variables
    beta_ext = np.asmatrix(np.zeros((Nallcov, 1)))
    beta_ext[nz_covs] = beta
    diagnostics().push("s2_eta_hat", s2_eta_hat)
    diagnostics().push("kriging_beta", beta_ext)
    diagnostics().push("kriging_iters", iters)
    diagnostics().push("kriging_rmse", np.mean(res2)**0.5)
    diagnostics().push("kriging_subzero_s2_estimates", subzeros)
    #    diagnostics().push("kriging_cov_cond", np.linalg.cond(XtSX))

    for i in range(X.shape[0]):
        for j in range(X.shape[1]):
            x_ij = X[i, j, :]
            K[i, j] = np.dot(x_ij, beta)
            V[i, j] = s2_eta_hat + np.dot(x_ij, np.linalg.solve(XtSX, x_ij))
            if V[i, j] < 0.0:
                print("ERROR: negative kriging variance!")

    return K, V
Esempio n. 33
0
def micro_step(it_diag, dt, size_z, size_x, th_ar, qv_ar, rhof_ar, rhoh_ar,
               exner_ar, uf_ar, uh_ar, wf_ar, wh_ar, xf_ar, zf_ar, xh_ar,
               zh_ar, tend_th_ar, tend_qv_ar, rh_ar):
    try:
        # global should be used for all variables defined in "if first_timestep"
        global prtcls, dx, dz, timestep, last_diag
        #pdb.set_trace()
        # superdroplets: initialisation (done only once)
        if timestep == 0:
            # first, removing the no-longer-needed pointer file
            os.unlink(ptrfname)

            arrx = ptr2np(xf_ar, size_x, 1)
            arrz = ptr2np(zf_ar, 1, size_z)

            # checking if grids are equal
            np.testing.assert_almost_equal((arrx[1:] - arrx[:-1]).max(),
                                           (arrx[1:] - arrx[:-1]).min(),
                                           decimal=7)
            np.testing.assert_almost_equal((arrz[1:] - arrz[:-1]).max(),
                                           (arrz[1:] - arrz[:-1]).min(),
                                           decimal=7)
            dx = arrx[1] - arrx[0]
            dz = arrz[1] - arrz[0]

            opts_init = libcl.lgrngn.opts_init_t()
            opts_init.dt = dt
            opts_init.nx, opts_init.nz = size_x - 2, size_z
            opts_init.dx, opts_init.dz = dx, dz
            opts_init.z0 = dz  # skipping the first sub-terrain level
            opts_init.x1, opts_init.z1 = dx * opts_init.nx, dz * opts_init.nz
            opts_init.sd_conc = int(params["sd_conc"])
            opts_init.dry_distros = {params["kappa"]: lognormal}
            opts_init.sstp_cond, opts_init.sstp_coal = params[
                "sstp_cond"], params["sstp_coal"]
            opts_init.terminal_velocity = libcl.lgrngn.vt_t.beard77fast
            opts_init.kernel = libcl.lgrngn.kernel_t.hall_davis_no_waals
            opts_init.adve_scheme = libcl.lgrngn.as_t.pred_corr
            opts_init.exact_sstp_cond = 0
            opts_init.n_sd_max = opts_init.nx * opts_init.nz * opts_init.sd_conc

            try:
                print(("Trying with multi_CUDA backend..."), end=' ')
                prtcls = libcl.lgrngn.factory(
                    libcl.lgrngn.backend_t.multi_CUDA, opts_init)
                print(" OK!")
            except:
                print(" KO!")
                try:
                    print(("Trying with CUDA backend..."), end=' ')
                    prtcls = libcl.lgrngn.factory(libcl.lgrngn.backend_t.CUDA,
                                                  opts_init)
                    print(" OK!")
                except:
                    print(" KO!")
                    try:
                        print(("Trying with OpenMP backend..."), end=' ')
                        prtcls = libcl.lgrngn.factory(
                            libcl.lgrngn.backend_t.OpenMP, opts_init)
                        print(" OK!")
                    except:
                        print(" KO!")
                        print(("Trying with serial backend..."), end=' ')
                        prtcls = libcl.lgrngn.factory(
                            libcl.lgrngn.backend_t.serial, opts_init)
                        print(" OK!")

            # allocating arrays for those variables that are not ready to use
            # (i.e. either different size or value conversion needed)
            for name in ("thetad", "qv", "p_d", "T_kid", "rhod_kid"):
                arrays[name] = np.empty((opts_init.nx, opts_init.nz))
            arrays["rhod"] = np.empty((opts_init.nz, ))
            arrays["Cx"] = np.empty((opts_init.nx + 1, opts_init.nz))
            arrays["Cz"] = np.empty((opts_init.nx, opts_init.nz + 1))
            arrays["RH_lib_ante_cond"] = np.empty((opts_init.nx, opts_init.nz))
            arrays["T_lib_ante_cond"] = np.empty((opts_init.nx, opts_init.nz))
            arrays["RH_kid"] = np.empty((opts_init.nx, opts_init.nz))

        # defining qv and thetad (in every timestep)
        arrays["qv"][:, :] = ptr2np(qv_ar, size_x, size_z)[1:-1, :]
        arrays["thetad"][:, :] = th_kid2dry(
            ptr2np(th_ar, size_x, size_z)[1:-1, :], arrays["qv"][:, :])
        arrays["p_d"][:, :] = (ptr2np(exner_ar, size_x, size_z)[1:-1, :])**(
            c_pd / R_d) * p_1000 * eps / (eps + arrays["qv"])
        arrays["T_kid"][:, :] = ptr2np(exner_ar, size_x,
                                       size_z)[1:-1, :] * ptr2np(
                                           th_ar, size_x, size_z)[1:-1, :]
        arrays["rhod_kid"] = arrays["p_d"] / arrays["T_kid"] / R_d
        arrays["RH_kid"][:, :] = ptr2np(rh_ar, size_x, size_z)[1:-1, :]

        #pdb.set_trace()

        # finalising initialisation
        if timestep == 0:
            arrays["rhod"][:] = rho_kid2dry(
                ptr2np(rhof_ar, 1, size_z)[:], arrays["qv"][0, :])

        arrays["Cx"][:, :] = ptr2np(uh_ar, size_x, size_z)[:-1, :] * dt / dx
        assert (arrays["Cx"][0, :] == arrays["Cx"][-1, :]).all()

        # putting meaningful values to the sub-terain level (to avoid segfault from library)
        arrays["Cz"][:, 0] = 0.
        arrays["qv"][:, 0] = 0.
        arrays["thetad"][:, 0] = 300.
        arrays["rhod"][0] = 1.

        arrays["Cz"][:, 1:] = ptr2np(wh_ar, size_x, size_z)[1:-1, :] * dt / dz

        if timestep == 0:
            prtcls.init(arrays["thetad"],
                        arrays["qv"],
                        arrays["rhod"],
                        Cx=arrays["Cx"],
                        Cz=arrays["Cz"])
            dg.diagnostics(prtcls, arrays, 1, size_x, size_z,
                           timestep == 0)  # writing down state at t=0

        # spinup period logic
        opts.sedi = opts.coal = timestep >= params["spinup_rain"]
        if timestep >= params["spinup_smax"]: opts.RH_max = 44

        # saving RH for the output file
        prtcls.diag_all()
        prtcls.diag_RH()
        arrays["RH_lib_ante_cond"] = np.frombuffer(prtcls.outbuf()).reshape(
            size_x - 2, size_z) * 100
        for i in range(0, prtcls.opts_init.nx):
            for j in range(0, prtcls.opts_init.nz):
                arrays["T_lib_ante_cond"][i, j] = libcl.common.T(
                    arrays["thetad"][i, j], arrays["rhod"][j])

        # superdroplets: all what have to be done within a timestep
        prtcls.step_sync(opts,
                         arrays["thetad"],
                         arrays["qv"],
                         Cx=arrays["Cx"],
                         Cz=arrays["Cz"],
                         RH=arrays["RH_kid"],
                         T=arrays["T_kid"])

        prtcls.step_async(opts)

        # calculating tendency for theta (first converting back to non-dry theta
        ptr2np(tend_th_ar, size_x, size_z)[1:-1, :] = -(
            ptr2np(th_ar, size_x, size_z)[1:-1, :] -  # old
            th_dry2kid(arrays["thetad"], arrays["qv"])  # new
        ) / dt  #TODO: check if dt needed

        # calculating tendency for qv
        ptr2np(tend_qv_ar, size_x, size_z)[1:-1, :] = -(
            ptr2np(qv_ar, size_x, size_z)[1:-1, :] -  # old                
            arrays["qv"]  # new 
        ) / dt  #TODO: check if dt needed

        # diagnostics
        if last_diag < it_diag:
            dg.diagnostics(prtcls, arrays, it_diag, size_x, size_z,
                           timestep == 0)
            last_diag = it_diag

        timestep += 1
    except:
        traceback.print_exc()
        return False
    else:
        return True