def test_basic1(self): from pyresample.ewa import ll2cr from pyresample.geometry import SwathDefinition, AreaDefinition from pyresample.utils import proj4_str_to_dict lon_arr = create_test_longitude(-95.0, -75.0, (50, 100), dtype=np.float64) lat_arr = create_test_latitude(18.0, 40.0, (50, 100), dtype=np.float64) swath_def = SwathDefinition(lon_arr, lat_arr) grid_info = static_lcc.copy() cw = grid_info["cell_width"] ch = grid_info["cell_height"] ox = grid_info["origin_x"] oy = grid_info["origin_y"] w = grid_info["width"] h = grid_info["height"] half_w = abs(cw / 2.) half_h = abs(ch / 2.) extents = [ ox - half_w, oy - h * abs(ch) - half_h, ox + w * abs(cw) + half_w, oy + half_h ] area = AreaDefinition('test_area', 'test_area', 'test_area', proj4_str_to_dict(grid_info['proj4_definition']), w, h, extents) points_in_grid, lon_res, lat_res, = ll2cr(swath_def, area, fill=np.nan, copy=False) self.assertEqual(points_in_grid, lon_arr.size, "all points should be contained in a dynamic grid") self.assertIs(lon_arr, lon_res) self.assertIs(lat_arr, lat_res) self.assertEqual(points_in_grid, lon_arr.size, "all these test points should fall in this grid")
def _call_ll2cr(lons, lats, target_geo_def): """Wrap ll2cr() for handling dask delayed calls better.""" new_src = SwathDefinition(lons, lats) swath_points_in_grid, cols, rows = ll2cr(new_src, target_geo_def) if swath_points_in_grid == 0: return (lons.shape, np.nan, lons.dtype), (lats.shape, np.nan, lats.dtype) return np.stack([cols, rows], axis=0)
def calc_ewa_params(in_area, out_area): """Calculate projection parameters for EWA interpolation""" swath_points_in_grid, cols, rows = ll2cr(in_area, out_area) del swath_points_in_grid cache = {} # cache['ewa_swath_points_in_grid'] = \ # swath_points_in_grid cache['ewa_cols'] = cols cache['ewa_rows'] = rows return cache
def _call_ll2cr(lons, lats, target_geo_def, computing_meta=False): """Wrap ll2cr() for handling dask delayed calls better.""" if computing_meta: # produce a representative meta array in the best case # avoids errors when we return our "empty" tuples below return np.zeros((2, *lons.shape), dtype=lons.dtype) new_src = SwathDefinition(lons, lats) swath_points_in_grid, cols, rows = ll2cr(new_src, target_geo_def) if swath_points_in_grid == 0: return (lons.shape, np.nan, lons.dtype), (lats.shape, np.nan, lats.dtype) return np.stack([cols, rows], axis=0)
def _call_ll2cr(self, lons, lats, target_geo_def, swath_usage=0): """Wrapper around ll2cr for handling dask delayed calls better.""" new_src = SwathDefinition(lons, lats) swath_points_in_grid, cols, rows = ll2cr(new_src, target_geo_def) # FIXME: How do we check swath usage/coverage if we only do this # per-block # # Determine if enough of the input swath was used # grid_name = getattr(self.target_geo_def, "name", "N/A") # fraction_in = swath_points_in_grid / float(lons.size) # swath_used = fraction_in > swath_usage # if not swath_used: # LOG.info("Data does not fit in grid %s because it only %f%% of " # "the swath is used" % # (grid_name, fraction_in * 100)) # raise RuntimeError("Data does not fit in grid %s" % (grid_name,)) # else: # LOG.debug("Data fits in grid %s and uses %f%% of the swath", # grid_name, fraction_in * 100) return np.stack([cols, rows], axis=0)
def __init__(self, in_area, out_area, in_latlons=None, mode=None, radius=10000, nprocs=1): if (mode is not None and mode not in ["quick", "nearest", "ewa", "bilinear"]): raise ValueError("Projector mode must be one of 'nearest', " "'quick', 'ewa', 'bilinear'") self.area_file = get_area_file() self.in_area = None self.out_area = None self._cache = None self._filename = None self.mode = "quick" self.radius = radius self.conf = ConfigParser.ConfigParser() self.conf.read(os.path.join(CONFIG_PATH, "mpop.cfg")) # TODO: # - Rework so that in_area and out_area can be lonlats. # - Add a recompute flag ? # Setting up the input area try: self.in_area = get_area_def(in_area) in_id = in_area except (utils.AreaNotFound, AttributeError): try: in_id = in_area.area_id self.in_area = in_area except AttributeError: try: # TODO: Note that latlons are in order (lons, lats) self.in_area = geometry.SwathDefinition(lons=in_latlons[0], lats=in_latlons[1]) in_id = in_area except TypeError: raise utils.AreaNotFound("Input area " + str(in_area) + " must be defined in " + self.area_file + ", be an area object" " or longitudes/latitudes must be " "provided.") # Setting up the output area try: self.out_area = get_area_def(out_area) out_id = out_area except (utils.AreaNotFound, AttributeError): try: out_id = out_area.area_id self.out_area = out_area except AttributeError: raise utils.AreaNotFound("Output area " + str(out_area) + " must be defined in " + self.area_file + " or " "be an area object.") # if self.in_area == self.out_area: # return # choosing the right mode if necessary if mode is None: try: dicts = in_area.proj_dict, out_area.proj_dict del dicts self.mode = "quick" except AttributeError: self.mode = "nearest" else: self.mode = mode filename = (in_id + "2" + out_id + "_" + str(_get_area_hash(self.in_area)) + "to" + str(_get_area_hash(self.out_area)) + "_" + self.mode + ".npz") projections_directory = "/var/tmp" try: projections_directory = self.conf.get("projector", "projections_directory") except ConfigParser.NoSectionError: pass self._filename = os.path.join(projections_directory, filename) try: self._cache = {} self._file_cache = np.load(self._filename) except: logger.info("Computing projection from %s to %s...", in_id, out_id) if self.mode == "nearest": valid_index, valid_output_index, index_array, distance_array = \ kd_tree.get_neighbour_info(self.in_area, self.out_area, self.radius, neighbours=1, nprocs=nprocs) del distance_array self._cache = {} self._cache['valid_index'] = valid_index self._cache['valid_output_index'] = valid_output_index self._cache['index_array'] = index_array elif self.mode == "quick": ridx, cidx = \ utils.generate_quick_linesample_arrays(self.in_area, self.out_area) self._cache = {} self._cache['row_idx'] = ridx self._cache['col_idx'] = cidx elif self.mode == "ewa": from pyresample.ewa import ll2cr swath_points_in_grid, cols, rows = ll2cr(self.in_area, self.out_area) self._cache = {} # self._cache['ewa_swath_points_in_grid'] = \ # swath_points_in_grid self._cache['ewa_cols'] = cols self._cache['ewa_rows'] = rows elif self.mode == "bilinear": bilinear_t, bilinear_s, input_idxs, idx_arr = \ get_bil_info(self.in_area, self.out_area, self.radius, neighbours=32, nprocs=nprocs, masked=False) self._cache = {} self._cache['bilinear_s'] = bilinear_s self._cache['bilinear_t'] = bilinear_t self._cache['input_idxs'] = input_idxs self._cache['idx_arr'] = idx_arr
def precompute(self, mask=None, # nprocs=1, cache_dir=False, **kwargs): """Generate row and column arrays and store it for later use. Note: The `mask` keyword should be provided if geolocation may be valid where data points are invalid. This defaults to the `mask` attribute of the `data` numpy masked array passed to the `resample` method. """ del kwargs source_geo_def = self.source_geo_def ewa_hash = self.get_hash(source_geo_def=source_geo_def) filename = self._create_cache_filename(cache_dir, ewa_hash) self._read_params_from_cache(cache_dir, ewa_hash, filename) if self.cache is not None: LOG.debug("Loaded ll2cr parameters") return self.cache else: LOG.debug("Computing ll2cr parameters") lons, lats = source_geo_def.get_lonlats() grid_name = getattr(self.target_geo_def, "name", "N/A") # SatPy/PyResample don't support dynamic grids out of the box yet is_static = True if is_static: # we are remapping to a static unchanging grid/area with all of # its parameters specified # inplace operation so lon_arr and lat_arr are written to swath_points_in_grid, cols, rows = ll2cr(source_geo_def, self.target_geo_def) else: raise NotImplementedError( "Dynamic ll2cr is not supported by satpy yet") # Determine if enough of the input swath was used fraction_in = swath_points_in_grid / float(lons.size) swath_used = fraction_in > self.swath_usage if not swath_used: LOG.info("Data does not fit in grid %s because it only %f%% of " "the swath is used" % (grid_name, fraction_in * 100)) raise RuntimeError("Data does not fit in grid %s" % (grid_name,)) else: LOG.debug("Data fits in grid %s and uses %f%% of the swath", grid_name, fraction_in * 100) # Can't save masked arrays to npz, so remove the mask if hasattr(rows, 'mask'): rows = rows.data cols = cols.data # it's important here not to modify the existing cache dictionary. self.cache = { "source_geo_def": source_geo_def, "rows": rows, "cols": cols, } self._update_caches(ewa_hash, cache_dir, filename) return self.cache
def precompute(self, mask=None, # nprocs=1, cache_dir=False, **kwargs): """Generate row and column arrays and store it for later use. Note: The `mask` keyword should be provided if geolocation may be valid where data points are invalid. This defaults to the `mask` attribute of the `data` numpy masked array passed to the `resample` method. """ del kwargs source_geo_def = self.source_geo_def kd_hash = self.get_hash(source_geo_def=source_geo_def) if isinstance(cache_dir, (str, six.text_type)): filename = os.path.join(cache_dir, hashlib.sha1(kd_hash).hexdigest() + ".npz") else: filename = os.path.join('.', hashlib.sha1(kd_hash.encode("utf-8")).hexdigest() + ".npz") try: self.cache = self.caches[kd_hash] # trick to keep most used caches away from deletion del self.caches[kd_hash] self.caches[kd_hash] = self.cache if cache_dir: self.dump(filename) return self.cache except KeyError: if os.path.exists(filename): LOG.debug("Loading kd-tree parameters") self.cache = dict(np.load(filename)) self.caches[kd_hash] = self.cache while len(self.caches) > CACHE_SIZE: self.caches.popitem(False) if cache_dir: self.dump(filename) return self.cache else: LOG.debug("Computing ll2cr parameters") lons, lats = source_geo_def.get_lonlats() fill_in = np.nan grid_name = getattr(self.target_geo_def, "name", "N/A") p = self.target_geo_def.proj4_string cw = self.target_geo_def.pixel_size_x ch = -abs(self.target_geo_def.pixel_size_y) w = self.target_geo_def.x_size h = self.target_geo_def.y_size ox = self.target_geo_def.area_extent[0] oy = self.target_geo_def.area_extent[3] is_static = True # SatPy/PyResample don't support dynamic grids out of the box yet if is_static: # we are remapping to a static unchanging grid/area with all of # its parameters specified # inplace operation so lon_arr and lat_arr are written to swath_points_in_grid = ll2cr(source_geo_def, self.target_geo_def) else: raise NotImplementedError("Dynamic ll2cr is not supported by satpy yet") swath_points_in_grid = ll2cr(source_geo_def, self.target_geo_def) swath_points_in_grid, lon_orig, lat_orig, origin_x, origin_y, width, height = results # edit the grid information because now we know what it is # FIXME: This should be less magical to the user, maybe a separate step for this operation self.target_geo_def.origin_x = origin_x self.target_geo_def.origin_y = origin_y self.target_geo_def.width = width self.target_geo_def.height = height # Determine if enough of the input swath was used fraction_in = swath_points_in_grid / float(lon_arr.size) swath_used = fraction_in > self.swath_usage if not swath_used: LOG.info("Data does not fit in grid %s because it only %f%% of the swath is used" % (grid_name, fraction_in * 100)) raise RuntimeError("Data does not fit in grid %s" % (grid_name,)) else: LOG.debug("Data fits in grid %s and uses %f%% of the swath", grid_name, fraction_in * 100) # it's important here not to modify the existing cache dictionary. self.cache = { "source_geo_def": source_geo_def, "rows": lat_arr, "cols": lon_arr, } self.caches[kd_hash] = self.cache while len(self.caches) > CACHE_SIZE: self.caches.popitem(False) if cache_dir: # XXX: Look in to doing memmap-able files instead `arr.tofile(filename)` self.dump(filename) return self.cache