def test_regularization(self):
     x = np.linspace(0, 10, 4)
     model_true = np.array([2.5, 5.0])
     data = f(model_true, x)
     model_pred = modest.nonlin_lstsq(f, data, 2, regularization=(0, 0.0), system_args=(x,))
     self.assertTrue(np.linalg.norm(model_pred - model_true) < tol)
     model_pred = modest.nonlin_lstsq(f, data, 2, regularization=(0, 1e8), system_args=(x,))
     self.assertTrue(np.linalg.norm(model_pred) < tol)
     model_pred = modest.nonlin_lstsq(f, data, 2, regularization=(1, 1e8), system_args=(x,))
     self.assertTrue((model_pred[0] - model_pred[1]) < tol)
    def test_solver_nnls(self):
        x = np.linspace(0, 10, 4)
        # the bounds should not impede the results here
        model_true = np.array([0.1, 5.0])
        data = f_nonlin(model_true, x)
        model_pred = modest.nonlin_lstsq(f_nonlin, data, 2, system_args=(x,), solver=modest.nnls)
        self.assertTrue(np.linalg.norm(model_pred - model_true) < tol)
        self.assertTrue(all(model_pred >= 0.0))

        # the bounds should influence the results here
        model_true = np.array([-2.5, 5.0])
        data = f_nonlin(model_true, x)
        model_pred = modest.nonlin_lstsq(f_nonlin, data, 2, system_args=(x,), solver=modest.nnls)
        self.assertTrue(all(model_pred >= 0.0))
Exemple #3
0
 def test_nonnegativity(self):
   soln0 = modest.nonlin_lstsq(system,
                               data,
                               model_prior,
                               data_covariance=data_cov,
                               prior_covariance=model_prior_cov,
                               system_args=(time,),
                               solver=modest.nnls)
   kf1 = modest.KalmanFilter(model_prior,
                             model_prior_cov,
                             system_kf,
                             solver=modest.nonlin_lstsq_update,
                             solver_kwargs={'solver':modest.nnls})
   kf1.filter(data_kf,data_cov_kf,time)
   soln1 = kf1.get_posterior()[0]
   self.assertTrue(np.all(np.isclose(soln0,soln1)))
Exemple #4
0
  def test_bayes_least_squares(self):
    soln1,cov1 = modest.nonlin_lstsq(system,
                                data,
                                model_prior,
                                data_covariance=data_cov,
                                prior_covariance=model_prior_cov,
                                system_args=(time,),
                                output=['solution','solution_covariance'])
    
    kf = modest.KalmanFilter(model_prior,
                             model_prior_cov,
                             system_kf)

    kf.filter(data_kf,data_cov_kf,time)
    soln2,cov2 = kf.get_posterior()
    kf.close()
    self.assertTrue(np.all(np.isclose(soln1,soln2)))
    self.assertTrue(np.all(np.isclose(cov1,cov2)))
Exemple #5
0
  def test_smoothing_no_core(self):
    pred1 = modest.nonlin_lstsq(system,
                                data,
                                model_prior,
                                data_covariance=data_cov,
                                prior_covariance=model_prior_cov,
                                system_args=(time,),
                                output=['predicted'])

    kf = modest.KalmanFilter(model_prior,
                             model_prior_cov,
                             system_kf,
                             core=False)
 
    kf.filter(data_kf,data_cov_kf,time,smooth=True)
    pred2 = np.array([system_kf(kf.history['smooth'][i,:],t) for i,t in enumerate(time)])
    kf.close()
    self.assertTrue(np.all(np.isclose(pred1[:,None],pred2)))
Exemple #6
0
def ECEF_to_geodetic(x,y,z,ref='WGS84'):
  '''finds the geodetic coordinates from cartesian coordinates

  This is done by solving a nonlinear inverse problem using 
  'geodetic_to_cartesian' as the forward problem. This is not the
  most efficient algorithm.

  change to ecef to geodetic

  Parameters
  ----------
    x,y,z: (scalars) coordinates in meters

    ref: (optional) reference ellipoid. Either 'NAD27','GRS80', or 
      'WGS84'

  Returns
  -------
    lon,lat,h: longitude (degrees), latitude (degrees) and height 
      above the reference ellipsoid (meters)

  The coordinate system is as defined by the WGS84, where the z axis
  is pointing in the direction of the IERS Reference pole; the x axis
  is the intersection between the equatorial plane and the IERS
  Reference Meridian; and the y axis completes a right-handed
  coordinate coordinate system
  '''
  lon,lat,h =  modest.nonlin_lstsq(
                 _system,
                 np.array([x,y,z]),
                 np.zeros(3),
                 system_args=(ref,),
                 rtol=1e-10,
                 atol=1e-10,
                 maxitr=100,
                 LM_damping=True,
                 LM_param=1.0)

  #print(lon,lat)
  lon,lat = bound_lon_lat(lon,lat)
  return lon,lat,h
Exemple #7
0
def ECEF_to_geodetic(x, y, z, ref='WGS84'):
    '''finds the geodetic coordinates from cartesian coordinates

  This is done by solving a nonlinear inverse problem using 
  'geodetic_to_cartesian' as the forward problem. This is not the
  most efficient algorithm.

  change to ecef to geodetic

  Parameters
  ----------
    x,y,z: (scalars) coordinates in meters

    ref: (optional) reference ellipoid. Either 'NAD27','GRS80', or 
      'WGS84'

  Returns
  -------
    lon,lat,h: longitude (degrees), latitude (degrees) and height 
      above the reference ellipsoid (meters)

  The coordinate system is as defined by the WGS84, where the z axis
  is pointing in the direction of the IERS Reference pole; the x axis
  is the intersection between the equatorial plane and the IERS
  Reference Meridian; and the y axis completes a right-handed
  coordinate coordinate system
  '''
    lon, lat, h = modest.nonlin_lstsq(_system,
                                      np.array([x, y, z]),
                                      np.zeros(3),
                                      system_args=(ref, ),
                                      rtol=1e-10,
                                      atol=1e-10,
                                      maxitr=100,
                                      LM_damping=True,
                                      LM_param=1.0)

    #print(lon,lat)
    lon, lat = bound_lon_lat(lon, lat)
    return lon, lat, h
Exemple #8
0
  def test_masked_arrays(self):
    data_indices = [1,2,3,5,6,7,8,10,12]
    mask = np.ones((len(data),1),dtype=bool)
    mask[data_indices,:] = False
    soln1,cov1 = modest.nonlin_lstsq(system,
                                data,
                                model_prior,
                                data_covariance=data_cov,
                                prior_covariance=model_prior_cov,
                                data_indices=data_indices, 
                                system_args=(time,),
                                output=['solution','solution_covariance'])

    kf = modest.KalmanFilter(model_prior,
                             model_prior_cov,
                             system_kf)

    kf.filter(data_kf,data_cov_kf,time,mask=mask)
    soln2,cov2 = kf.get_posterior()
    kf.close()
    self.assertTrue(np.all(np.isclose(soln1,soln2)))
    self.assertTrue(np.all(np.isclose(cov1,cov2)))
Exemple #9
0
 def test_reg_bayes_least_squares(self):
   soln0 = modest.nonlin_lstsq(system,
                               data,
                               model_prior,
                               data_covariance=data_cov,
                               prior_covariance=model_prior_cov,
                               system_args=(time,),
                               regularization=reg_mat)
   kf1 = modest.KalmanFilter(model_prior,
                            model_prior_cov,
                            system_reg_kf,
                            obs_args=(0.25819889*reg_mat,))
   kf2 = modest.KalmanFilter(model_prior,
                             model_prior_cov,
                             system_kf,
                             solver=modest.nonlin_lstsq_update,
                             solver_kwargs={'regularization':0.25819889*reg_mat})
   kf1.filter(data_reg_kf,data_reg_cov_kf,time)
   soln1 = kf1.get_posterior()[0]
   kf2.filter(data_kf,data_cov_kf,time)
   soln2 = kf2.get_posterior()[0]
   kf1.close()
   kf2.close()
   self.assertTrue(np.all(np.isclose(soln0,soln1,soln2)))
Exemple #10
0
def main(data,gf,param,outfile):
  '''
  Nt: number of time steps
  Nx: number of positions
  Dx: spatial dimensions of coordinates and displacements 
  Ns: number of slip basis functions per slip direction
  Ds: number of slip directions
  Nv: number of fluidity basis functions
  total: number of state parameters (Ns*Ds + Nv + 2*Nx*Dx)

  Parameters
  ----------
    data: \ mask : (Nt,Nx) boolean array
          \ mean : (Nt,Nx,Dx) array
          \ covariance : (Nt,Nx,Dx,Dx) array
          \ metadata \ position : (Nx,Dx) array
                       time : (Nt,) array

    prior: \ mean : (total,) array
           \ covariance : (total,total) array

    gf: \ elastic : (Ns,Ds,Nx,Dx) array
        \ viscoelastic : (Ns,Ds,Dv,Nx,Dx) array
        \ metadata \ position : (Nx,Dx) array

    reg: \ regularization : (*,total) array

    params: user parameter dictionary

  Returns
  -------
    out: \ slip_integral \ mean : (Nt,Ns,Ds) array
                         \ uncertainty :(Nt,Ns,Ds) array
         \ slip \ mean : (Nt,Ns,Ds) array
                \ uncertainty : (Nt,Ns,Ds) array
         \ slip_derivative \ mean : (Nt,Ns,Ds) array
                           \ uncertainty : (Nt,Ns,Ds) array
         \ fluidity \ mean : (Nv,) array
                    \ uncertainty : (Nv,) array
         \ secular_velocity \ mean : (Nx,Dx) array
                            \ uncertainty : (Nx,Dx) array
         \ baseline_displacement \ mean : (Nx,Dx) array
                                 \ uncertainty : (Nx,Dx) array

  '''
  F = gf['slip'][...]
  G = gf['fluidity'][...]
  coseismic_times = np.array(param['coseismic_times'])
  afterslip_start_times = param['afterslip_start_times']
  afterslip_end_times = param['afterslip_end_times']
  afterslip_times = zip(afterslip_start_times,afterslip_end_times) 
  afterslip_times = np.array(afterslip_times)
  time = data['time'][:]

  slip_scale = 1.0 # meter
  relax_scale = 1.0 # year
  time_scale = np.std(time)
  time_shift = np.mean(time) # years
  disp_scale = 1.0 # meter
  # shift is different for each time series
  disp_shift = np.mean(data['mean'],0)

  # scale greens functions
  # F is originally in meters disp per meter slip
  F /= disp_scale/slip_scale
  # G is originally in meters/year disp per meter slip*fluidity 
  G /= (disp_scale/time_scale)/(slip_scale/relax_scale) 
  
  time -= time_shift
  time /= time_scale

  coseismic_times -= time_shift
  coseismic_times /= time_scale
  afterslip_times -= time_shift
  afterslip_times /= time_scale

  param['initial_slip_variance'] /= slip_scale**2
  param['fluidity_variance'] *= relax_scale**2
  param['secular_velocity_variance'] /= (disp_scale/time_scale)**2
  param['baseline_displacement_variance'] /= disp_scale**2

  # define slip functions and slip jacobian here
  slip_func,slip_jac = steps_and_ramps(coseismic_times,
                                       afterslip_times)

  Nst = len(coseismic_times) + len(afterslip_start_times)
  Ns,Ds,Nv,Nx,Dx = np.shape(G)
  Nt = len(time)
  
  # check for consistency between input
  assert data['mean'].shape == (Nt,Nx,Dx)
  assert data['variance'].shape == (Nt,Nx,Dx)
  assert F.shape == (Ns,Ds,Nx,Dx)
  assert G.shape == (Ns,Ds,Nv,Nx,Dx)
  p = state_parser(Nst,Ns,Ds,Nv,Nx,Dx)

  if param['solver'] == 'bvls':
    solver = modest.bvls
    upper_bound = 1e6*np.ones(p['total'])
    lower_bound = -1e6*np.ones(p['total'])

    # all inferred fluidities will be positive
    lower_bound[p['fluidity']] = 0

    # all inferred left lateral slip will be positive
    left_lateral_indices = np.array(p['slip'][:,:,0],copy=True)
    thrust_indices = np.array(p['slip'][:,:,1],copy=True)
    upper_bound[left_lateral_indices] = 0.0
    solver_args = (lower_bound,upper_bound)
    solver_kwargs = {}

  if param['solver'] == 'lstsq':
    solver = modest.lstsq
    solver_args = ()
    solver_kwargs = {}

  elif param['solver'] == 'lsmr':
    solver = modest.lsmr
    solver_args = ()
    solver_kwargs = {}

  elif param['solver'] == 'lgmres':
    solver = modest.lgmres
    solver_args = ()
    solver_kwargs = {'tol':1e-8,'maxiter':1000}

  elif param['solver'] == 'dgs':
    solver = modest.dgs
    solver_args = ()
    solver_kwargs = {}

  #fprior = prior.create_formatted_prior(param,p,slip_model='parameterized')
  Xprior,Cprior = prior.create_prior(param,p,slip_model='parameterized')   
  reg_matrix = reg.create_regularization(param,p,slip_model='parameterized')
  reg_rows = len(reg_matrix)  

  setup_output_file(outfile,p,
                    data['name'][...],
                    data['position'][...],
                    data['time'][...])
  
  Xprior,Cprior = modest.nonlin_lstsq(
                      regularization,
                      np.zeros(reg_rows),
                      Xprior, 
                      data_covariance=np.eye(reg_rows),
                      prior_covariance=Cprior,
                      system_args=(reg_matrix,),
                      jacobian=regularization_jacobian,
                      jacobian_args=(reg_matrix,),
                      maxitr=param['maxitr'],
                      solver=solver, 
                      solver_args=solver_args,
                      solver_kwargs=solver_kwargs,
                      LM_damping=True,
                      output=['solution','solution_covariance'])

  time_indices = range(Nt)
  block_time_indices = modest.misc.divide_list(time_indices,param['time_blocks'])
  for i in block_time_indices:
    outfile['data/mean'][i,...] = data['mean'][i,...]
    outfile['data/mask'][i,...] = data['mask'][i,...]
    outfile['data/covariance'][i,...] = data['variance'][i,...]
    di = data['mean'][i,...]
    di -= disp_shift
    di /= disp_scale

    di_mask = np.array(data['mask'][i,:],dtype=bool)
    # expand to three dimensions
    di_mask = np.repeat(di_mask[...,None],3,-1)
    di = di[~di_mask]
    Cdi = data['variance'][i,...]
    Cdi /= disp_scale**2
    Cdi = Cdi[~di_mask]

    Xprior,Cprior = modest.nonlin_lstsq(
                      observation,
                      di,
                      Xprior, 
                      data_covariance=Cdi,
                      prior_covariance=Cprior,
                      system_args=(time[i],F,G,p,slip_func,di_mask),
                      jacobian=observation_jacobian,
                      jacobian_args=(time[i],F,G,p,slip_func,slip_jac,di_mask),
                      solver=solver, 
                      solver_args=solver_args,
                      solver_kwargs=solver_kwargs,
                      maxitr=param['maxitr'],
                      LM_damping=True,
                      LM_param=1.0,
                      rtol=1e-2,
                      atol=1e-2,
                      output=['solution','solution_covariance'])

  post_mean_scaled,post_cov_scaled = Xprior,Cprior

  post_mean = np.copy(post_mean_scaled)
  post_mean[p['baseline_displacement']] *= disp_scale
  post_mean[p['baseline_displacement']] += disp_shift
  post_mean[p['secular_velocity']] *= (disp_scale/time_scale)  
  post_mean[p['slip']] *= slip_scale
  post_mean[p['fluidity']] /= relax_scale

  for i in range(Nt):
    outfile['state/all'][i,:] = post_mean
    outfile['state/baseline_displacement'][i,...] = post_mean[p['baseline_displacement']]   
    outfile['state/secular_velocity'][i,...] = post_mean[p['secular_velocity']]   
    outfile['state/slip'][i,...] = slip_func(post_mean[p['slip']],time[i])   
    outfile['state/slip_derivative'][i,...] = slip_func(post_mean[p['slip']],time[i],diff=1)
    outfile['state/fluidity'][i,...] = post_mean[p['fluidity']]   

  # compute predicted data
  logger.info('computing predicted data')
  error = 0.0
  count = 0
  for i in range(Nt):
    predicted = observation_t(post_mean_scaled,
                              time[i],
                              F,G,p,slip_func)
    # change back to meters
    predicted *= disp_scale    
    predicted += disp_shift
    residual = outfile['data/mean'][i,...] - predicted
    covariance = outfile['data/covariance'][i,...]
    data_mask = np.array(outfile['data/mask'][i,...],dtype=bool)
    error += L2(residual,covariance,data_mask) 
    count += np.sum(~data_mask)

    outfile['predicted/mean'][i,...] = predicted

    mask = np.zeros(p['total'])
    mask[p['secular_velocity']] = 1.0
    mask[p['baseline_displacement']] = 1.0
    mask_post_mean = post_mean_scaled*mask
    tectonic = observation_t(mask_post_mean,
                             time[i],
                             F,G,p,
                             slip_func)
    tectonic *= disp_scale
    tectonic += disp_shift
    outfile['tectonic/mean'][i,...] = tectonic

    mask = np.zeros(p['total'])
    mask[p['slip']] = 1.0
    mask_post_mean = post_mean_scaled*mask
    elastic = observation_t(mask_post_mean,
                            time[i],
                            F,G,p,
                            slip_func)

    elastic *= disp_scale
    outfile['elastic/mean'][i,...] = elastic 

    visc = (outfile['predicted/mean'][i,...] - 
            outfile['tectonic/mean'][i,...] - 
            outfile['elastic/mean'][i,...])
    outfile['viscous/mean'][i,...] = visc

  logger.info('total RMSE: %s' % np.sqrt(error/count))

  return 
# true mode we are trying to recover
model_true = np.random.random(2)
model_true[0] *= 0.6 
model_true[0] += 1.2 
model_true[1] *= 0.3
model_true[1] += 0.1
 
# create synthetic data
N = 100
time = np.linspace(0.0,5.0,100)
data = system(model_true,time) + np.random.normal(0.0,0.1,N)
data_variance = 0.1*np.ones(N)

soln,soln_cov,pred = modest.nonlin_lstsq(system,data,M,
                                         data_covariance=data_variance,
                                         system_args=(time,),
                                         solver=modest.bvls,
                                         solver_args=(lb,ub), 
                                         output=['solution','solution_covariance','predicted'])
# plot misfit surface
trialsx = np.linspace(1.0,2.0,200)
trialsy = np.linspace(0.001,0.5,200)
trialsx,trialsy = np.meshgrid(trialsx,trialsy)
trialsx = trialsx.flatten()
trialsy = trialsy.flatten()
trials = np.array([trialsx,trialsy]).T
misfit = np.array([np.sum((system(m,time) - data)**2/data_variance) for m in trials])
model_best = trials[np.argmin(misfit)]


# model space plot
fig,ax = plt.subplots()
 def test_solver_lstsq(self):
     x = np.linspace(0, 10, 4)
     model_true = np.array([2.5, 5.0])
     data = f_nonlin(model_true, x)
     model_pred = modest.nonlin_lstsq(f_nonlin, data, 2, system_args=(x,), solver=modest.lstsq)
     self.assertTrue(np.linalg.norm(model_pred - model_true) < tol)
 def test_linear_with_jacobian(self):
     x = np.linspace(0, 10, 4)
     model_true = np.array([2.5, 5.0])
     data = f(model_true, x)
     model_pred = modest.nonlin_lstsq(f, data, np.zeros(2), jacobian=jac, jacobian_args=(x,), system_args=(x,))
     self.assertTrue(np.linalg.norm(model_pred - model_true) < tol)
 def test_linear_no_init_guess(self):
     x = np.linspace(0, 10, 4)
     model_true = np.array([2.5, 5.0])
     data = f(model_true, x)
     model_pred = modest.nonlin_lstsq(f, data, 2, system_args=(x,))
     self.assertTrue(np.linalg.norm(model_pred - model_true) < tol)
Exemple #15
0
def logexp_filter(u,var,t,start,jumps,trials=10,diff=0,detrend=False,reg=1e-10):
  ''' 
  Assumes that the underlying signal can be described by
  
    u(t) = a + b*t + 
           c*H(t-t_eq) + 
           d*H(t-t_eq)*(t-t_eq) +  
           e_i*log(1 + t/tau_i)
  
  and that the observation contains seasonal signals and jumps at 
  indicated times. So the observation equation is
  
    uobs(t) = a + b*t + 
              c*H(t-t_eq) + 
              d_i*log(1 + t/tau_i) + 
              f*sin(2*pi*t) + g*sin(4*pi*t) 
              h*cos(2*pi*t) + m*cos(4*pi*t) 
              n_i*H(t-t_i)

  This function estimates a,b,c,d_i,tau_i,e,f,g,h, and m_i with 
  a nonlinear least squares algorithm.  We put a positivity constraint
  on tau and we also restrict c and d_i to have the same sign
  '''
  # remove jumps that are not within the observation time interval
  jumps = np.array([j for j in jumps if (j>t[0]) & (j<t[-1])])

  J = len(jumps)
  # total number of model parameters 
  M = 11 + J 

  def system(m,diff=0):
    if diff == 0:
      out = np.zeros(len(t)) 
      out += m[0]  
      out += m[1]*t
      out += m[2]*_H(t-start)
      out += m[3]*_pslog((t-start)/m[4])
      out += m[5]*_psexp((t-start)/m[6])
      out += m[7]*np.sin(2*np.pi*t)  
      out += m[8]*np.sin(4*np.pi*t)  
      out += m[9]*np.cos(2*np.pi*t)  
      out += m[10]*np.cos(4*np.pi*t)  
      for j,val in enumerate(jumps):
        out += m[11+j]*_H(t-val)  

    # derivative w.r.t. t
    elif diff == 1:
      out = np.zeros(len(t)) 
      out += m[1]
      out += _H(t-start)*(m[3]/((t-start) + m[4]))
      out += _H(t-start)*(m[5]*np.exp(-(t-start)/m[6])/m[6])
      out += m[7]*np.cos(2*np.pi*t)*2*np.pi
      out += m[8]*np.cos(4*np.pi*t)*4*np.pi
      out += -m[9]*np.sin(2*np.pi*t)*2*np.pi  
      out += -m[10]*np.sin(4*np.pi*t)*4*np.pi

    return out
  
  if detrend:  
    idx1 = np.array([0,1,7,8,9,10])
    idx2 = np.arange(11,M,dtype=int)
    nuisance_indices = np.concatenate((idx1,idx2))
    signal_indices = np.array([2,3,4,5,6])

  else:
    idx1 = np.array([7,8,9,10])
    idx2 = np.arange(11,M,dtype=int)
    nuisance_indices = np.concatenate((idx1,idx2))
    signal_indices = np.array([0,1,2,3,4,5,6])

  jacobian = modest.make_jacobian(system)

  best_err = np.inf
  for i in range(trials):
    # set lower and upper bounds for model parameters
    minit = np.ones(M)
    lb = -1e10*np.ones(M)
    ub = 1e10*np.ones(M)
    # do not allow timescales less that 0.001
    minit[4] = 10**np.random.normal(0.0,0.5)
    minit[6] = 10**np.random.normal(0.0,0.5)
    lb[4] = 1e-3        
    lb[6] = 1e-3        

    err1,m1,mcov1,pred1 = modest.nonlin_lstsq(
                            system,u,minit,
                            solver=modest.bvls,solver_args=(lb,ub),
                            data_covariance=var,
                            LM_damping=True, 
                            regularization=(0,reg),
                            output=['misfit','solution','solution_covariance','predicted'])
    if err1 < best_err:
      best_err = err1
      m = m1
      mcov = mcov1
      pred = pred1

  # find the jacobian matrix for the final model estimate
  jac = jacobian(m,diff=diff)  

  # find the estimated signal by evaluating the system with 0.0 for
  # the nuisance parameters
  m[nuisance_indices] = 0.0
  signal_pred = system(m,diff=diff)

  # slice the model covariance matrix and jacobian so that it only
  # contains columns for the parameters of interest
  jac = jac[:,signal_indices]
  mcov = mcov[np.ix_(signal_indices,signal_indices)]

  # use error propagation to find the uncertainty on the predicted
  # signal
  signal_cov = jac.dot(mcov).dot(jac.T)
  # for some reason, diag returns a read-only array
  signal_var = np.copy(np.diag(signal_cov))

  return signal_pred,signal_var