def get_interpolation_weights(self, source_lons = None, source_lats = None, dest_lons = None, dest_lats = None, nneighbours = 4 ): """ get the interpolation array M (nx*ny, nneighbors) and negibor indices G: DEST_FIELD = M * SOURCE_FIELD.flatten()[G] """ source_lons_1d, source_lats_1d = source_lons.flatten(), source_lats.flatten() [x,y,z] = lat_lon.lon_lat_to_cartesian_normalized(source_lons_1d, source_lats_1d) kdtree = KDTree(zip(x, y, z)) [xi, yi, zi] = lat_lon.lon_lat_to_cartesian_normalized(dest_lons.flatten(), dest_lats.flatten()) [distances, indices] = kdtree.query( zip( xi, yi, zi ) , k = nneighbours ) if len(distances.shape) == 2: weights = 1.0 / distances ** 2 norm = weights.sum(axis = 1) norm = np.array( [norm] * nneighbours ).transpose() weights /= norm else: weights = np.ones(distances.shape) return weights, indices
def __init__(self, data_path = 'data/era_interim/evap1980-2010.nc', varName = 'e', start_date = None, end_date = None): self.start_date = start_date self.end_date = end_date self._data_path = data_path self.monthly_normals = [] self.longitudes = None self.latitudes = None self.reference_date = None self.varName = varName self.quebec_mask = None # 1 for the points in Quebec 0 for the points outside ds = nc.Dataset(data_path) self.varValues = ds.variables[varName][:].transpose((0,2,1)) self.timeValues = ds.variables["time"][:] self.timeUnits = ds.variables["time"].units self.missing_value = ds.variables[varName].missing_value self.varUnits = ds.variables[varName].units self.longitudes = ds.variables["longitude"][:] self.latitudes = ds.variables["latitude"][:] self.ecmwf_data_step = timedelta(hours = int(self.timeValues[1] - self.timeValues[0])) ds.close() lon_0 = self.longitudes[0] + self.longitudes[-1] lon_0 /= 2.0 llcrnrlon = self.longitudes.min() llcrnrlat = self.latitudes.min() urcrnrlon = self.longitudes.max() urcrnrlat = self.latitudes.max() self.basemap = Basemap(#projection="cyl", #lat_0=45, lon_0 = -40, llcrnrlon=llcrnrlon, llcrnrlat=llcrnrlat, urcrnrlon=urcrnrlon, urcrnrlat=urcrnrlat ) [lats2d, lons2d] = np.meshgrid(self.latitudes, self.longitudes) print "lon range: ", lons2d.min(), lons2d.max() print "lat range: ", lats2d.min(), lats2d.max() print "lower left crnr (lon, lat): ", lons2d[0,0], lats2d[0,0] print "upper right crnr (lon, lat): ", lons2d[-1,-1], lats2d[-1,-1] [x, y, z] = lat_lon.lon_lat_to_cartesian_normalized(lons2d.flatten(), lats2d.flatten()) grid_points = np.array([x, y, z]).transpose() self.kd_tree = KDTree(grid_points) pass
def get_data_interpolated_to_points(self, dest_lons = None, dest_lats = None, source_lons = None, source_lats = None, data = None): """ Designed to interpolate all data to the AMNO domain """ if None not in [source_lons, source_lats]: lons1d = source_lons.flatten() lats1d = source_lats.flatten() points = lat_lon.lon_lat_to_cartesian_normalized(lons1d, lats1d) points = np.array(points).transpose() point_tree = KDTree(points) else: point_tree = self.kd_tree assert source_lons.shape == source_lats.shape == data.shape [xi, yi, zi] = lat_lon.lon_lat_to_cartesian_normalized(dest_lons.flatten(), dest_lats.flatten()) pointsi = np.array([xi, yi, zi]).transpose() data1d = data.flatten() #distances dimensions = (n_points, n_neigbours) [distances, indices] = point_tree.query(pointsi, k = 4) weights = 1.0 / distances ** 2 norm = [np.sum(weights, axis = 1)] * weights.shape[1] norm = np.array(norm).transpose() weights /= norm result = [] for i in xrange(pointsi.shape[0]): w = weights[i, :] d = data1d[indices[i, :]] result.append(np.sum(w * d)) return np.array(result).reshape( dest_lons.shape )