def nonstationary_spatiotemporal(x,y,amp,scale,diff_degree,t_gam_fun=default_t_gam_fun,h=default_h,symm=None,geometry='aniso_geo_rad',**kwds): """ Spatiotemporal covariance function. Converts x and y to a matrix of covariances. x and y are assumed to have columns (long,lat,t). Parameters are: - t_gam_fun: A function returning a matrix of variogram values. Inputs will be the 't' columns of x and y, as well as kwds. - amp: The MS amplitude of realizations. - scale: Scales distance. - diff_degree: A function that returns local degree of differentiability at x. - h: A function that returns local relative amplitude at x. - inc, ecc: Anisotropy parameters. Needed if geometry=='aniso_geo_rad'. - n_threads: Maximum number of threads available to function. - symm: Flag indicating whether matrix will be symmetric (optional). - geometry: Must be 'aniso_geo_rad' or 'euclidean'. - kwds: Passed to t_gam_fun. References: Stein, 2005. "Space-Time Covariance Functions". Journal of the American Statistical Association 100(469). Pintore and Holmes, 2010, "Spatially adaptive non-stationary covariance functions via spatially adaptive spectra". Journal of the American Statistical Association. Forthcoming. """ # Allocate nx = x.shape[0] ny = y.shape[0] if kwds.has_key('n_threads'): kwds.pop('n_threads') if geometry=='aniso_geo_rad': inc = kwds.pop('inc') ecc = kwds.pop('ecc') else: inc = None ecc = None if geometry not in ['aniso_geo_rad','euclidean']: raise ValueError, 'Geometry %s unknown, must be aniso_geo_rad or euclidean.'%geometry D = np.asmatrix(np.empty((nx,ny),order='F')) GT = np.asmatrix(np.empty((nx,ny),order='F')) # Figure out symmetry and threading if symm is None: symm = (x is y) n_threads = min(get_threadpool_size(), nx*ny / 10000) if n_threads > 1: if not symm: bounds = np.linspace(0,ny,n_threads+1) else: bounds = np.array(np.sqrt(np.linspace(0,ny*ny,n_threads+1)),dtype=int) # Target function for threads def targ(D,GT,x,y,cmin,cmax,symm,inc=inc,ecc=ecc,amp=amp,scale=scale,diff_degree=diff_degree,h=h,geometry=geometry,kwds=kwds): # Spatial distance if geometry=='aniso_geo_rad': aniso_geo_rad(D, x[:,:-1], y[:,:-1], inc, ecc,cmin=cmin,cmax=cmax,symm=symm) else: euclidean(D, x[:,:-1], y[:,:-1], cmin=cmin,cmax=cmax,symm=symm) imul(D,1./scale,cmin=cmin,cmax=cmax,symm=symm) # Temporal variogram ddx, ddy = diff_degree(x), diff_degree(y) origin_val = t_gam_fun(GT, x[:,-1], y[:,-1], ddx, ddy, cmin=cmin,cmax=cmax,symm=False,**kwds) if np.any(GT<0): raise pm.ZeroProbability, 'GT < 0.' # GT = np.add.outer(ddx*.5,ddy*.5) # Local properties hx, hy = h(x), h(y) # Covariance nsst(D,GT,origin_val,hx,hy,cmin=cmin,cmax=cmax,symm=symm) imul(D,amp*amp,cmin=cmin,cmax=cmax,symm=symm) # Serial version if n_threads <= 1: targ(D,GT,x,y,0,-1,symm) # Parallel version else: thread_args = [(D,GT,x,y,bounds[i],bounds[i+1],symm) for i in xrange(n_threads)] map_noreturn(targ, thread_args) if symm: symmetrize(D) return D
def my_st(x,y,amp,scale,inc,ecc,symm=None,**kwds): """ Spatiotemporal covariance function. Converts x and y to a matrix of covariances. x and y are assumed to have columns (long,lat,t). Parameters are: - t_gam_fun: A function returning a matrix of variogram values. Inputs will be the 't' columns of x and y, as well as kwds. - amp: The MS amplitude of realizations. - scale: Scales distance. - inc, ecc: Anisotropy parameters. - n_threads: Maximum number of threads available to function. - symm: Flag indicating whether matrix will be symmetric (optional). - kwds: Passed to t_gam_fun. Output value should never drop below -1. This happens when: -1 > -sf*c+k """ # Allocate nx = x.shape[0] ny = y.shape[0] k=kwds['tlc']/kwds['sd'] c=1./kwds['sd']-k sf=kwds['sf'] tlc=kwds['tlc'] sd=kwds['sd'] if kwds.has_key('n_threads'): kwds.pop('n_threads') # If parameter values are illegal, just return zeros. # This case will be caught by the Potential. if -sd >= 1./(-sf*(1-tlc)+tlc): return np.zeros((nx,ny)) D = np.asmatrix(np.empty((nx,ny),order='F')) GT = np.asmatrix(np.empty((nx,ny),order='F')) # Figure out symmetry and threading if symm is None: symm = (x is y) n_threads = min(get_threadpool_size(), nx*ny / 10000) if n_threads > 1: if not symm: bounds = np.linspace(0,ny,n_threads+1) else: bounds = np.array(np.sqrt(np.linspace(0,ny*ny,n_threads+1)),dtype=int) # Target function for threads def targ(D,GT,x,y,cmin,cmax,symm,inc=inc,ecc=ecc,amp=amp,scale=scale,kwds=kwds): # Spatial distance aniso_geo_rad(D, x[:,:-1], y[:,:-1], inc, ecc,cmin=cmin,cmax=cmax,symm=symm) imul(D,1./scale,cmin=cmin,cmax=cmax,symm=symm) # Temporal variogram origin_val = t_gam_fun(GT, x[:,-1], y[:,-1],cmin=cmin,cmax=cmax,symm=symm,**kwds) # Covariance stein_spatiotemporal(D,GT,origin_val,cmin=cmin,cmax=cmax,symm=symm) imul(D,amp*amp,cmin=cmin,cmax=cmax,symm=symm) # if symm: # symmetrize(D, cmin=cmin, cmax=cmax) # Serial version if n_threads <= 1: targ(D,GT,x,y,0,-1,symm) # Parallel version else: thread_args = [(D,GT,x,y,bounds[i],bounds[i+1],symm) for i in xrange(n_threads)] map_noreturn(targ, thread_args) if symm: symmetrize(D) return D