def forward_model ( mcmc_results, parameter_names, \ observations="sim04_obs_l10_g6_n58.csv", \ meteo_drivers="sim04_met_l10_g6_n58.csv"): from dalec import dalec meteo_data = np.loadtxt( meteo_drivers, delimiter="," ) obs_nee = np.loadtxt ( observations, delimiter="," ) missing_obs = obs_nee[ :, 1] < -9998 nsamples = mcmc_results.shape[1]/2 parameters = mcmc_results[:, :nsamples] sel = np.random.randint ( 0, nsamples-1, size=500 ) #x_init = np.array ( [ 0.513303, 4891.44, 134.927, 82.27539, \ # 74.74379, 12526.28 ] ) i = 0 model_nee = np.zeros ( ( 500, meteo_data.shape[0] ) ) for params in sel: if parameters.shape[0] == 23: retval = dalec ( parameters[17:, params], \ parameters[:17, params], meteo_data, \ -2, 1, 60, 42.2, 2.7) #self.psid, self.rtot, self.lma, self.lat, self.nit ) elif parameters.shape[0] == 24: retval = dalec ( parameters[18:, params], \ parameters[1:18, params], meteo_data, \ -2, 1, 60, 42.2, 2.7) #self.psid, self.rtot, self.lma, self.lat, self.nit ) else: print ">>>>>> Something fishy" model_nee[ i, : ] = retval[ :, -4 ] i = i + 1 #plt.plot ( meteo_data[~missing_obs,0], obs_nee[~missing_obs,1], 'ro' ) #plt.plot return (model_nee, meteo_data[:,0], obs_nee[:,1], missing_obs, meteo_data )
def likelihood_function ( self, theta ): """ This calculates the likelihood function. It first transforms the theta vector into a parameters per grid cell that are then passed on to the model object. """ # Load the parameters into a dictionary indexed by grid_ids parameters = self._transform_variables_lognorm ( theta ) if self.truncate: if np.any ( parameters > self.hi_val ) or \ np.any ( parameters < self.lo_val ): return -np.inf # Parameter have been loaded nto parameter_list for all grid cells # All that needs doing now is to run the model forward for each # grid cell and calculate the likelihood function retval = dalec ( parameters[17:], parameters[:17], self.meteo_data, \ self.psid, self.rtot, self.lma, self.lat, self.nit ) model_nee = retval[ :, -4 ] delta = (self.obs_nee[~self.missing_obs, 1] - \ model_nee[~self.missing_obs] )**2 delta = delta / (self.flux_unc**2 ) delta = delta[::self.obs_thin] p = -0.5*np.sum ( delta ) p -= delta.shape[0]*( np.log ( np.sqrt(2.*np.pi)*self.flux_unc )) self.it += 1 #pdb.set_trace() if self.it%500 == 0: print self.it, np.sum(delta), p self._plot_fit ( model_nee, p ) return p
def likelihood_function ( self, theta ): """ This calculates the likelihood function. It first transforms the theta vector into a parameters per grid cell that are then passed on to the model object. """ # Load the parameters into a dictionary indexed by grid_ids tau = theta[0] #parameters = self._transform_variables_lognorm ( theta[1:] ) parameters = theta[1:] if self.truncate: if np.any ( parameters > self.hi_val ) or \ np.any ( parameters < self.lo_val ): return -np.inf #print tau # Parameter have been loaded nto parameter_list for all grid cells # All that needs doing now is to run the model forward for each # grid cell and calculate the likelihood function retval = dalec ( parameters[17:], parameters[:17], self.meteo_data, \ self.psid, self.rtot, self.lma, self.lat, self.nit ) model_nee = retval[ :, -4 ] first = True p = 0.0 n_obs = self.missing_obs.shape[0] for isample in np.arange ( self.missing_obs.shape[0] ): if not self.missing_obs [ isample ]: if first: # First observation, edge condition, so asymptotic behaviour first = False t_prev = self.meteo_data[ isample, 0 ] p -= np.sum ( np.log ( 2.*np.pi*self.flux_unc )) delta = (self.obs_nee[isample, 1] - \ model_nee[isample] ) p -= 0.5*(delta**2)/self.flux_unc**2 delta_prev = delta # Remember to store t_prev and delta_prev else: # Autoregressive part t_curr = self.meteo_data [isample, 0] # sigma temperated by the temporal correlation sigma_dash = self.flux_unc * np.sqrt ( \ (1. - np.exp (-2.*(t_curr-t_prev)/tau)) ) delta = (self.obs_nee[isample, 1] - \ model_nee[isample] ) arf = delta - np.exp (-(t_curr-t_prev)/tau)*delta_prev arf2 = arf*arf p -= np.log ( np.sqrt(2.*np.pi)*sigma_dash ) p -= 0.5*arf2/(sigma_dash*sigma_dash) t_prev = t_curr delta_prev = delta self.it += 1 if self.it % 500 == 0: self._plot_fit ( model_nee, p, flag="arf" ) return p
def run_model(self, x, i, store=False): """Runs the model forward to ``i+1`` using input state ``x``, assuming parameter vectors stored in the class. The output is returned to the user, but also stored in ``self.previous_state``, if you told the method to store the data. This is an option as one might be using this code within an ensemble. NOTE ---- Not all fluxes are returned! For example, respiration and litter fluxes are ignored. Feel free to add them in. Parameters ----------- x: iter The state, defined as Cf, Cr, Cw, C**t, Csom i: int The time step Returns -------- nee, gpp, Cf, Cr, Cw, C**t, Csom A tuple containing the updated state, as well as the fluxes """ # Extract drivers... doy, temp, tmx, tmn, irad, psid, ca, rtot, nitro = self.drivers[i, :] tmp = 0.5 * (tmx - tmn) # Extract the state components from the input Cf, Cr, Cw, C**t, Csom = x # Run DALEC ( nee, gpp, Ra, Rh1, Rh2, Af, Ar, Aw, Lw, Lr, D, \ Cf, Cr, Cw, C**t, Csom, lai ) = dalec ( doy, \ tmn, tmp, tmx, irad, ca, nitro, \ self.model_params[0], self.model_params[1], \ self.model_params[2:], \ Cf, Cr, Cw, C**t, Csom, psid=psid, rtot=rtot ) # Do we store the output? if store: self.previous_state.append ( [ nee, gpp, Ra, Rh1, Rh2, Af, Ar, Aw, Lw, Lr, D, \ Cf, Cr, Cw, C**t, Csom, lai ] ) return ( nee, gpp, Ra, Rh1, Rh2, Af, Ar, Aw, Lw, Lr, D, \ Cf, Cr, Cw, C**t, Csom )
def likelihood_function ( self, theta ): """ This calculates the likelihood function. It first transforms the theta vector into a parameters per grid cell that are then passed on to the model object. """ # Load the parameters into a dictionary indexed by grid_ids parameters = self._transform_variables_uniform ( theta ) # Parameter have been loaded nto parameter_list for all grid cells # All that needs doing now is to run the model forward for each # grid cell and calculate the likelihood function retval = dalec ( self.x_init, parameters, self.meteo_data ) model_nee = retval[ :, -4 ] delta = (self.obs_nee[~self.missing_obs, 1] - \ model_nee[~self.missing_obs] )**2 p = 0.5*np.sum ( delta[::10] ) / (self.flux_unc**2 ) p -= np.sum ( np.log ( 2.*np.pi*self.flux_unc )) return p