def _validate_input(self): if self.vnir.gt != self.swir.gt: raise ValueError((self.vnir.gt, self.swir.gt), 'VNIR and SWIR geoinformation should be equal.') if not prj_equal(self.vnir.prj, self.swir.prj): raise ValueError((self.vnir.prj, self.swir.prj), 'VNIR and SWIR projection should be equal.') if self.vnir.bands != len(self.wvls.vnir): raise ValueError("The number of VNIR bands must be equal to the number of elements in 'vnir_wvls': " "%d != %d" % (self.vnir.bands, len(self.wvls.vnir))) if self.swir.bands != len(self.wvls.swir): raise ValueError("The number of SWIR bands must be equal to the number of elements in 'swir_wvls': " "%d != %d" % (self.swir.bands, len(self.wvls.swir)))
def compute_geolayer(self) -> (np.ndarray, np.ndarray): """Compute pixel-wise lon/lat arrays based on RPC coefficients, corner coordinates and image dimensions. :return: (2D longitude array, 2D latitude array) """ # transform corner coordinates of EnMAP image to UTM grid_utm_epsg = get_UTMEPSG_from_LonLat( *get_center_coord(self.enmapIm_cornerCoords)) cornerCoordsUTM = np.array([ transform_any_prj(4326, grid_utm_epsg, lon, lat) for lon, lat in self.enmapIm_cornerCoords ]) xmin, xmax = cornerCoordsUTM[:, 0].min(), cornerCoordsUTM[:, 0].max() ymin, ymax = cornerCoordsUTM[:, 1].min(), cornerCoordsUTM[:, 1].max() # get UTM bounding box and move it to the EnMAP grid xmin, ymin, xmax, ymax = \ move_extent_to_coord_grid((xmin, ymin, xmax, ymax), enmap_coordinate_grid_utm['x'], enmap_coordinate_grid_utm['y']) # set up a regular grid of UTM points with a specific mesh width meshwidth = 300 # 10 EnMAP pixels y_grid_utm, x_grid_utm = np.meshgrid(np.arange(ymax, ymin - meshwidth, -meshwidth), np.arange(xmin, xmax + meshwidth, meshwidth), indexing='ij') if not isinstance(self.elevation, (int, float)): # transform UTM grid to DEM projection x_grid_demPrj, y_grid_demPrj = \ (x_grid_utm, y_grid_utm) if prj_equal(grid_utm_epsg, self.elevation.epsg) else \ transform_coordArray(CRS(grid_utm_epsg).to_wkt(), CRS(self.elevation.epsg).to_wkt(), x_grid_utm, y_grid_utm) # retrieve corresponding heights from DEM # -> resample DEM to EnMAP grid? xy_pairs_demPrj = np.vstack( [x_grid_demPrj.flatten(), y_grid_demPrj.flatten()]).T heights = self.elevation.read_pointData(xy_pairs_demPrj).flatten() else: heights = np.full_like(x_grid_utm.flatten(), self.elevation) # transform UTM points to lon/lat lon_grid, lat_grid = \ transform_coordArray(CRS(grid_utm_epsg).to_wkt(), CRS(4326).to_wkt(), x_grid_utm, y_grid_utm) lons = lon_grid.flatten() lats = lat_grid.flatten() # compute floating point EnMAP image coordinates for the selected UTM points rows, cols = self.transform_LonLatHeight_to_RowCol(lon=lons, lat=lats, height=heights) # interpolate lon/lats to get lon/lat coordinates integer image coordinates of EnMAP image rows_im, cols_im = self.enmapIm_dims_sensorgeo out_rows_grid, out_cols_grid = np.meshgrid(range(rows_im), range(cols_im), indexing='ij') out_xy_pairs = np.vstack( [out_cols_grid.flatten(), out_rows_grid.flatten()]).T in_xy_pairs = np.array((cols, rows)).T # Compute the triangulation (that takes time and can be computed for all values to be interpolated at once), # then run the interpolation triangulation = Delaunay(in_xy_pairs) lons_interp = LinearNDInterpolator( triangulation, lons)(out_xy_pairs).reshape(*out_rows_grid.shape) lats_interp = LinearNDInterpolator( triangulation, lats)(out_xy_pairs).reshape(*out_rows_grid.shape) # lons_interp / lats_interp may contain NaN values in case xmin, ymin, xmax, ymax has been set too small # to account for RPC transformation errors # => fix that by extrapolation at NaN value positions # FIXME: can this be avoided by modified xmin/ymin/xmy/ymax coords? lons_interp = self._fill_nans_at_corners( lons_interp, along_axis=0) # extrapolate in left/right direction lats_interp = self._fill_nans_at_corners(lats_interp, along_axis=1) # return a geolayer in the exact dimensions like the EnMAP detector array return lons_interp, lats_interp
def warping_needed(self): """Return True if image warping is needed in consideration of the input parameters of DESHIFTER.""" assert self.out_grid, 'Output grid must be calculated before.' equal_prj = prj_equal(self.ref_prj, self.shift_prj) return \ False if (equal_prj and not self.GCPList and is_coord_grid_equal(self.updated_gt, *self.out_grid)) else True