def test_point(): # Subset of tests/cxx/isce3/geometry/geometry/geometry.cpp fn = os.path.join(iscetest.data, "envisat.h5") slc = SLC(hdf5file=fn) orbit = slc.getOrbit() subband = "A" doplut = slc.getDopplerCentroid(frequency=subband) grid = slc.getRadarGrid(frequency=subband) # First row of input_data.txt dt = isce3.core.DateTime("2003-02-26T17:55:22.976222") r = 826988.6900674499 h = 1777. dem = isce3.geometry.DEMInterpolator(h) t = (dt - orbit.reference_epoch).total_seconds() dop = doplut.eval(t, r) wvl = grid.wavelength # native doppler, expect first row of output_data.txt llh = isce3.geometry.rdr2geo(t, r, orbit, grid.lookside, dop, wvl, dem) assert np.isclose(np.degrees(llh[0]), -115.44101120961082) assert np.isclose(np.degrees(llh[1]), 35.28794014757191) assert np.isclose(llh[2], 1777.) # zero doppler, expect first row of output_data_zerodop.txt llh = isce3.geometry.rdr2geo(t, r, orbit, grid.lookside, 0.0, dem=dem) assert np.isclose(np.degrees(llh[0]), -115.43883834023249) assert np.isclose(np.degrees(llh[1]), 35.29610867314526) assert np.isclose(llh[2], 1776.9999999993)
def main(opts): #instantiate slc object from NISAR SLC class slc = SLC(hdf5file=opts.product) # extract orbit orbit = slc.getOrbit() # extract the radar grid parameters radarGrid = slc.getRadarGrid() # construct ellipsoid which is by default WGS84 ellipsoid = isce3.core.ellipsoid() # Create geo2rdr instance geo2rdrObj = isce3.geometry.geo2rdr(radarGrid=radarGrid, orbit=orbit, ellipsoid=ellipsoid) # Read topo multiband raster topoRaster = isce3.io.raster( filename=os.path.join(opts.topodir, 'topo.vrt')) # Init output directory if not os.path.isdir(opts.outdir): os.mkdir(opts.outdir) # Run geo2rdr geo2rdrObj.geo2rdr(topoRaster, outputDir=opts.outdir, azshift=opts.azoff, rgshift=opts.rgoff)
def main(opts): #instantiate slc object from NISAR SLC class slc = SLC(hdf5file=opts.product) # extract orbit orbit = slc.getOrbit() # extract the radar grid parameters radarGrid = slc.getRadarGrid() # construct ellipsoid which is by default WGS84 ellipsoid = isce3.core.ellipsoid() rdr2geo = isce3.geometry.rdr2geo(radarGrid=radarGrid, orbit=orbit, ellipsoid=ellipsoid, computeMask=opts.mask) # Read DEM raster demRaster = isce3.io.raster(filename=opts.dem) # Init output directory if not os.path.isdir(opts.outdir): os.mkdir(opts.outdir) # Run rdr2geo rdr2geo.topo(demRaster, outputDir=opts.outdir) return 0
def main(opts): """ crossmul """ # prepare input rasters masterSlc = SLC(hdf5file=opts.master) masterSlcDataset = masterSlc.getSlcDataset(opts.frequency, opts.polarization) masterSlcRaster = Raster('', h5=masterSlcDataset) slaveSlc = SLC(hdf5file=opts.slave) slaveSlcDataset = slaveSlc.getSlcDataset(opts.frequency, opts.polarization) slaveSlcRaster = Raster('', h5=slaveSlcDataset) # prepare mulitlooked interferogram dimensions masterGrid = masterSlc.getRadarGrid(opts.frequency) length = int(masterGrid.length / opts.alks) width = int(masterGrid.width / opts.rlks) # init output directory(s) initDir(opts.intPathAndPrefix) initDir(opts.cohPathAndPrefix) # prepare output rasters driver = gdal.GetDriverByName('ISCE') igramDataset = driver.Create(opts.intPathAndPrefix, width, length, 1, gdal.GDT_CFloat32) igramRaster = Raster('', dataset=igramDataset) cohDataset = driver.Create(opts.cohPathAndPrefix, width, length, 1, gdal.GDT_Float32) cohRaster = Raster('', dataset=cohDataset) # prepare optional rasters if opts.rgoff: rgOffRaster = Raster(opts.rgoff) else: rgOffRaster = None if opts.azband: dopMaster = masterSlc.getDopplerCentroid() dopSlave = slaveSlc.getDopplerCentroid() prf = dopMaster.getRadarGrid(opts.frequency).prf azimuthBandwidth = opts.azband else: dopMaster = dopSlave = None prf = azimuthBandwidth = 0.0 crossmul = Crossmul() crossmul.crossmul(masterSlcRaster, slaveSlcRaster, igramRaster, cohRaster, rngOffset=rgOffRaster, refDoppler=dopMaster, secDoppler=dopSlave, rangeLooks=opts.rlks, azimuthLooks=opts.alks, prf=prf, azimuthBandwidth=azimuthBandwidth)
def main(opts): """ resample SLC """ # prep SLC dataset input productSlc = SLC(hdf5file=opts.product) # get grids needed for resamp object instantiation productGrid = productSlc.getRadarGrid(opts.frequency) # instantiate resamp object based on user input if 'cuda' not in dir(isce3) and opts.gpu: warnings.warn('CUDA resamp not available. Switching to CPU resamp') opts.gpu = False if opts.gpu: resamp = isce3.cuda.image.resampSlc( radarGrid=productGrid, doppler=productSlc.getDopplerCentroid(), wavelength=productGrid.wavelength) else: resamp = isce3.image.resampSlc(radarGrid=productGrid, doppler=productSlc.getDopplerCentroid(), wavelength=productGrid.wavelength) # set number of lines per tile if arg > 0 if opts.linesPerTile: resamp.linesPerTile = opts.linesPerTile # Prepare input rasters inSlcDataset = productSlc.getSlcDataset(opts.frequency, opts.polarization) inSlcRaster = isce3.io.raster(filename='', h5=inSlcDataset) azOffsetRaster = isce3.io.raster( filename=os.path.join(opts.offsetdir, 'azimuth.off')) rgOffsetRaster = isce3.io.raster( filename=os.path.join(opts.offsetdir, 'range.off')) # Init output directory if opts.outFilePath: path, _ = os.path.split(opts.outFilePath) os.makedirs(path, exist_ok=True) # Prepare output raster driver = gdal.GetDriverByName('ISCE') outds = driver.Create(opts.outFilePath, rgOffsetRaster.width, rgOffsetRaster.length, 1, gdal.GDT_CFloat32) outSlcRaster = isce3.io.raster(filename='', dataset=outds) # Run resamp resamp.resamp(inSlc=inSlcRaster, outSlc=outSlcRaster, rgoffRaster=rgOffsetRaster, azoffRaster=azOffsetRaster)
def common_crossmul_obj(): ''' instantiate and return common crossmul object for both run tests ''' # make SLC object and extract parameters slc_obj = SLC(hdf5file=os.path.join(iscetest.data, 'envisat.h5')) dopp = isce.core.avg_lut2d_to_lut1d(slc_obj.getDopplerCentroid()) prf = slc_obj.getRadarGrid().prf crossmul = isce.signal.Crossmul() crossmul.set_dopplers(dopp, dopp) crossmul.set_az_filter(prf, 2000.0, 0.25) return crossmul
def get_geo_polygon(ref_slc, min_height=-500., max_height=9000., pts_per_edge=5): """Create polygon (EPSG:4326) using RSLC radar grid and orbits Parameters: ----------- ref_slc: str Path to RSLC product to stage the DEM for min_height: float Global minimum height (in m) for DEM interpolator max_height: float Global maximum height (in m) for DEM interpolator pts_per_edge: float Number of points per edge for min/max bounding box computation Returns: ------- poly: shapely.Geometry.Polygon Bounding polygon corresponding to RSLC perimeter on the ground """ from isce3.core import LUT2d from isce3.geometry import DEMInterpolator, get_geo_perimeter_wkt from nisar.products.readers import SLC # Prepare SLC dataset input productSlc = SLC(hdf5file=ref_slc) # Extract orbits, radar grid, and doppler for frequency A orbit = productSlc.getOrbit() radar_grid = productSlc.getRadarGrid(frequency='A') doppler = LUT2d() # Get min and max global height DEM interpolators dem_min = DEMInterpolator(height=min_height) dem_max = DEMInterpolator(height=max_height) # Get min and max bounding boxes box_min = get_geo_perimeter_wkt(radar_grid, orbit, doppler, dem_min, pts_per_edge) box_max = get_geo_perimeter_wkt(radar_grid, orbit, doppler, dem_max, pts_per_edge) # Determine minimum and maximum polygons poly_min = shapely.wkt.loads(box_min) poly_max = shapely.wkt.loads(box_max) # Get polygon from intersection of poly_min and poly_max poly = poly_min | poly_max return poly
def determine_perimeter(opts): """ Determine perimeter for DEM staging """ from nisar.products.readers import SLC from isce3.geometry import deminterpolator from isce3.geometry import getGeoPerimeter from isce3.core import projection if opts.bbox is not None: print('Determine perimeter from bounding box') lat = opts.bbox[0:2] lon = opts.bbox[2:4] ring = LinearRing([(lon[0], lat[0]), (lon[0], lat[1]), (lon[1], lat[1]), (lon[1], lat[0])]) else: print('Determine perimeter from SLC radar grid') # Prepare SLC dataset input productSlc = SLC(hdf5file=opts.product) # Extract orbits and radar Grid parameters orbit = productSlc.getOrbit() radarGrid = productSlc.getRadarGrid() # Minimum and Maximum global heights dem_min = deminterpolator(height=-500.) dem_max = deminterpolator(height=9000.) # Get Minimum and Maximum bounding boxes epsg = projection(epsg=4326) box_min = getGeoPerimeter(radarGrid, orbit, epsg, dem=dem_min, pointsPerEdge=5) box_max = getGeoPerimeter(radarGrid, orbit, epsg, dem=dem_max, pointsPerEdge=5) dummy = json.loads(box_min)['coordinates'] + \ json.loads(box_max)['coordinates'] ring = LinearRing(dummy) return ring
def main(opts): #instantiate slc object from NISAR SLC class slc = SLC(hdf5file=opts.product) # extract orbit orbit = slc.getOrbit() # extract the radar grid parameters radarGrid = slc.getRadarGrid() # construct ellipsoid which is by default WGS84 ellipsoid = isce3.core.ellipsoid() # get doppler centroid doppler = slc.getDopplerCentroid() # instantiate geo2rdr object based on user input if 'cuda' not in dir(isce3) and opts.gpu: warnings.warn('CUDA geo2rdr not available. Switching to CPU geo2rdr') opts.gpu = False if opts.gpu: geo2rdrObj = isce3.cuda.geometry.geo2rdr(radarGrid=radarGrid, orbit=orbit, ellipsoid=ellipsoid, doppler=doppler, threshold=1e-9) else: geo2rdrObj = isce3.geometry.geo2rdr(radarGrid=radarGrid, orbit=orbit, ellipsoid=ellipsoid, doppler=doppler, threshold=1e-9) # Read topo multiband raster topoRaster = isce3.io.raster(filename=opts.topopath) # Init output directory os.makedirs(opts.outdir, exist_ok=True) # Run geo2rdr geo2rdrObj.geo2rdr(topoRaster, outputDir=opts.outdir, azshift=opts.azoff, rgshift=opts.rgoff)
def main(opts): #instantiate slc object from NISAR SLC class slc = SLC(hdf5file=opts.product) # extract orbit orbit = slc.getOrbit() # extract the radar grid parameters radarGrid = slc.getRadarGrid() # construct ellipsoid which is by default WGS84 ellipsoid = isce3.core.ellipsoid() # get doppler centroid doppler = slc.getDopplerCentroid() # instantiate rdr2geo object based on user input if 'cuda' not in dir(isce3) and opts.gpu: warnings.warn('CUDA rdr2geo not available. Switching to CPU rdr2geo') opts.gpu = False if opts.gpu: rdr2geo = isce3.cuda.geometry.rdr2geo(radarGrid=radarGrid, orbit=orbit, ellipsoid=ellipsoid, computeMask=opts.mask, doppler=doppler) else: rdr2geo = isce3.geometry.rdr2geo(radarGrid=radarGrid, orbit=orbit, ellipsoid=ellipsoid, computeMask=opts.mask, doppler=doppler) # Read DEM raster demRaster = isce3.io.raster(filename=opts.dem) # Init output directory os.makedirs(opts.outdir, exist_ok=True) # Run rdr2geo rdr2geo.topo(demRaster, outputDir=opts.outdir) return 0
def main(opts): """ resample SLC """ # prep SLC dataset input productSlc = SLC(hdf5file=opts.product) # get grids needed for resamp object instantiation productGrid = productSlc.getRadarGrid(opts.frequency) # instantiate resamp object resamp = ResampSlc(productGrid, productSlc.getDopplerCentroid(), productGrid.wavelength) # set number of lines per tile if arg > 0 if opts.linesPerTile: resamp.linesPerTile = opts.linesPerTile # Prepare input rasters inSlcDataset = productSlc.getSlcDataset(opts.frequency, opts.polarization) inSlcRaster = Raster('', h5=inSlcDataset) azOffsetRaster = Raster( filename=os.path.join(opts.offsetdir, 'azimuth.off')) rgOffsetRaster = Raster(filename=os.path.join(opts.offsetdir, 'range.off')) # Init output directory if opts.outPathAndFile: path, file = os.path.split(opts.outPathAndFile) if not os.path.isdir(path): os.makedirs(path) # Prepare output raster driver = gdal.GetDriverByName('ISCE') slcPathAndName = opts.outPathAndFile outds = driver.Create(os.path.join(slcPathAndName), rgOffsetRaster.width, rgOffsetRaster.length, 1, gdal.GDT_CFloat32) outSlcRaster = Raster('', dataset=outds) # Run resamp resamp.resamp(inSlc=inSlcRaster, outSlc=outSlcRaster, rgoffRaster=rgOffsetRaster, azoffRaster=azOffsetRaster)
def run(cfg): ''' run GCOV ''' # pull parameters from cfg input_hdf5 = cfg['input_file_group']['input_file_path'] output_hdf5 = cfg['product_path_group']['sas_output_file'] freq_pols = cfg['processing']['input_subset']['list_of_frequencies'] flag_fullcovariance = cfg['processing']['input_subset']['fullcovariance'] flag_symmetrize_cross_pol_channels = \ cfg['processing']['input_subset']['symmetrize_cross_pol_channels'] scratch_path = cfg['product_path_group']['scratch_path'] radar_grid_cubes_geogrid = cfg['processing']['radar_grid_cubes']['geogrid'] radar_grid_cubes_heights = cfg['processing']['radar_grid_cubes']['heights'] # DEM parameters dem_file = cfg['dynamic_ancillary_file_group']['dem_file'] dem_margin = cfg['processing']['dem_margin'] dem_interp_method_enum = cfg['processing']['dem_interpolation_method_enum'] # unpack geocode run parameters geocode_dict = cfg['processing']['geocode'] geocode_algorithm = geocode_dict['algorithm_type'] output_mode = geocode_dict['output_mode'] flag_apply_rtc = geocode_dict['apply_rtc'] memory_mode = geocode_dict['memory_mode'] geogrid_upsampling = geocode_dict['geogrid_upsampling'] abs_cal_factor = geocode_dict['abs_rad_cal'] clip_max = geocode_dict['clip_max'] clip_min = geocode_dict['clip_min'] geogrids = geocode_dict['geogrids'] flag_upsample_radar_grid = geocode_dict['upsample_radargrid'] flag_save_nlooks = geocode_dict['save_nlooks'] flag_save_rtc = geocode_dict['save_rtc'] flag_save_dem = geocode_dict['save_dem'] # unpack RTC run parameters rtc_dict = cfg['processing']['rtc'] output_terrain_radiometry = rtc_dict['output_type'] rtc_algorithm = rtc_dict['algorithm_type'] input_terrain_radiometry = rtc_dict['input_terrain_radiometry'] rtc_min_value_db = rtc_dict['rtc_min_value_db'] rtc_upsampling = rtc_dict['dem_upsampling'] # unpack geo2rdr parameters geo2rdr_dict = cfg['processing']['geo2rdr'] threshold = geo2rdr_dict['threshold'] maxiter = geo2rdr_dict['maxiter'] if (flag_apply_rtc and output_terrain_radiometry == isce3.geometry.RtcOutputTerrainRadiometry.SIGMA_NAUGHT): output_radiometry_str = "radar backscatter sigma0" elif (flag_apply_rtc and output_terrain_radiometry == isce3.geometry.RtcOutputTerrainRadiometry.GAMMA_NAUGHT): output_radiometry_str = 'radar backscatter gamma0' elif input_terrain_radiometry == isce3.geometry.RtcInputTerrainRadiometry.BETA_NAUGHT: output_radiometry_str = 'radar backscatter beta0' else: output_radiometry_str = 'radar backscatter sigma0' # unpack pre-processing preprocess = cfg['processing']['pre_process'] rg_look = preprocess['range_looks'] az_look = preprocess['azimuth_looks'] radar_grid_nlooks = rg_look * az_look # init parameters shared between frequencyA and frequencyB sub-bands slc = SLC(hdf5file=input_hdf5) dem_raster = isce3.io.Raster(dem_file) zero_doppler = isce3.core.LUT2d() epsg = dem_raster.get_epsg() proj = isce3.core.make_projection(epsg) ellipsoid = proj.ellipsoid exponent = 2 info_channel = journal.info("gcov.run") error_channel = journal.error("gcov.run") info_channel.log("starting geocode COV") t_all = time.time() for frequency in freq_pols.keys(): t_freq = time.time() # unpack frequency dependent parameters radar_grid = slc.getRadarGrid(frequency) if radar_grid_nlooks > 1: radar_grid = radar_grid.multilook(az_look, rg_look) geogrid = geogrids[frequency] input_pol_list = freq_pols[frequency] # do no processing if no polarizations specified for current frequency if not input_pol_list: continue # set dict of input rasters input_raster_dict = {} # `input_pol_list` is the input list of polarizations that may include # HV and VH. `pol_list` is the actual list of polarizations to be # geocoded. It may include HV but it will not include VH if the # polarimetric symmetrization is performed pol_list = input_pol_list for pol in pol_list: temp_ref = \ f'HDF5:"{input_hdf5}":/{slc.slcPath(frequency, pol)}' temp_raster = isce3.io.Raster(temp_ref) input_raster_dict[pol] = temp_raster # symmetrize cross-polarimetric channels (if applicable) if (flag_symmetrize_cross_pol_channels and 'HV' in input_pol_list and 'VH' in input_pol_list): # create output raster symmetrized_hv_temp = tempfile.NamedTemporaryFile(dir=scratch_path, suffix='.tif') # get cross-polarimetric channels from input_raster_dict hv_raster_obj = input_raster_dict['HV'] vh_raster_obj = input_raster_dict['VH'] # create output symmetrized HV object symmetrized_hv_obj = isce3.io.Raster(symmetrized_hv_temp.name, hv_raster_obj.width, hv_raster_obj.length, hv_raster_obj.num_bands, hv_raster_obj.datatype(), 'GTiff') # call symmetrization function isce3.polsar.symmetrize_cross_pol_channels(hv_raster_obj, vh_raster_obj, symmetrized_hv_obj) # ensure changes are flushed to disk by closing & re-opening the # raster. del symmetrized_hv_obj symmetrized_hv_obj = isce3.io.Raster(symmetrized_hv_temp.name) # Since HV and VH were symmetrized into HV, remove VH from # `pol_list` and `from input_raster_dict`. pol_list.remove('VH') input_raster_dict.pop('VH') # Update `input_raster_dict` with the new `symmetrized_hv_obj` input_raster_dict['HV'] = symmetrized_hv_obj # construct input rasters input_raster_list = [] for pol in pol_list: input_raster_list.append(input_raster_dict[pol]) # set paths temporary files input_temp = tempfile.NamedTemporaryFile(dir=scratch_path, suffix='.vrt') input_raster_obj = isce3.io.Raster(input_temp.name, raster_list=input_raster_list) # init Geocode object depending on raster type if input_raster_obj.datatype() == gdal.GDT_Float32: geo = isce3.geocode.GeocodeFloat32() elif input_raster_obj.datatype() == gdal.GDT_Float64: geo = isce3.geocode.GeocodeFloat64() elif input_raster_obj.datatype() == gdal.GDT_CFloat32: geo = isce3.geocode.GeocodeCFloat32() elif input_raster_obj.datatype() == gdal.GDT_CFloat64: geo = isce3.geocode.GeocodeCFloat64() else: err_str = 'Unsupported raster type for geocoding' error_channel.log(err_str) raise NotImplementedError(err_str) orbit = slc.getOrbit() # init geocode members geo.orbit = orbit geo.ellipsoid = ellipsoid geo.doppler = zero_doppler geo.threshold_geo2rdr = threshold geo.numiter_geo2rdr = maxiter geo.dem_block_margin = dem_margin # set data interpolator based on the geocode algorithm if output_mode == isce3.geocode.GeocodeOutputMode.INTERP: geo.data_interpolator = geocode_algorithm geo.geogrid(geogrid.start_x, geogrid.start_y, geogrid.spacing_x, geogrid.spacing_y, geogrid.width, geogrid.length, geogrid.epsg) # create output raster temp_output = tempfile.NamedTemporaryFile(dir=scratch_path, suffix='.tif') output_raster_obj = isce3.io.Raster(temp_output.name, geogrid.width, geogrid.length, input_raster_obj.num_bands, gdal.GDT_Float32, 'GTiff') nbands_off_diag_terms = 0 out_off_diag_terms_obj = None if flag_fullcovariance: nbands = input_raster_obj.num_bands nbands_off_diag_terms = (nbands**2 - nbands) // 2 if nbands_off_diag_terms > 0: temp_off_diag = tempfile.NamedTemporaryFile(dir=scratch_path, suffix='.tif') out_off_diag_terms_obj = isce3.io.Raster( temp_off_diag.name, geogrid.width, geogrid.length, nbands_off_diag_terms, gdal.GDT_CFloat32, 'GTiff') if flag_save_nlooks: temp_nlooks = tempfile.NamedTemporaryFile(dir=scratch_path, suffix='.tif') out_geo_nlooks_obj = isce3.io.Raster(temp_nlooks.name, geogrid.width, geogrid.length, 1, gdal.GDT_Float32, "GTiff") else: temp_nlooks = None out_geo_nlooks_obj = None if flag_save_rtc: temp_rtc = tempfile.NamedTemporaryFile(dir=scratch_path, suffix='.tif') out_geo_rtc_obj = isce3.io.Raster(temp_rtc.name, geogrid.width, geogrid.length, 1, gdal.GDT_Float32, "GTiff") else: temp_rtc = None out_geo_rtc_obj = None if flag_save_dem: temp_interpolated_dem = tempfile.NamedTemporaryFile( dir=scratch_path, suffix='.tif') if (output_mode == isce3.geocode.GeocodeOutputMode.AREA_PROJECTION ): interpolated_dem_width = geogrid.width + 1 interpolated_dem_length = geogrid.length + 1 else: interpolated_dem_width = geogrid.width interpolated_dem_length = geogrid.length out_geo_dem_obj = isce3.io.Raster(temp_interpolated_dem.name, interpolated_dem_width, interpolated_dem_length, 1, gdal.GDT_Float32, "GTiff") else: temp_interpolated_dem = None out_geo_dem_obj = None # geocode rasters geo.geocode(radar_grid=radar_grid, input_raster=input_raster_obj, output_raster=output_raster_obj, dem_raster=dem_raster, output_mode=output_mode, geogrid_upsampling=geogrid_upsampling, flag_apply_rtc=flag_apply_rtc, input_terrain_radiometry=input_terrain_radiometry, output_terrain_radiometry=output_terrain_radiometry, exponent=exponent, rtc_min_value_db=rtc_min_value_db, rtc_upsampling=rtc_upsampling, rtc_algorithm=rtc_algorithm, abs_cal_factor=abs_cal_factor, flag_upsample_radar_grid=flag_upsample_radar_grid, clip_min=clip_min, clip_max=clip_max, radargrid_nlooks=radar_grid_nlooks, out_off_diag_terms=out_off_diag_terms_obj, out_geo_nlooks=out_geo_nlooks_obj, out_geo_rtc=out_geo_rtc_obj, out_geo_dem=out_geo_dem_obj, input_rtc=None, output_rtc=None, dem_interp_method=dem_interp_method_enum, memory_mode=memory_mode) del output_raster_obj if flag_save_nlooks: del out_geo_nlooks_obj if flag_save_rtc: del out_geo_rtc_obj if flag_save_dem: del out_geo_dem_obj if flag_fullcovariance: # out_off_diag_terms_obj.close_dataset() del out_off_diag_terms_obj with h5py.File(output_hdf5, 'a') as hdf5_obj: hdf5_obj.attrs['Conventions'] = np.string_("CF-1.8") root_ds = f'/science/LSAR/GCOV/grids/frequency{frequency}' h5_ds = os.path.join(root_ds, 'listOfPolarizations') if h5_ds in hdf5_obj: del hdf5_obj[h5_ds] pol_list_s2 = np.array(pol_list, dtype='S2') dset = hdf5_obj.create_dataset(h5_ds, data=pol_list_s2) dset.attrs['description'] = np.string_( 'List of processed polarization layers with frequency ' + frequency) h5_ds = os.path.join(root_ds, 'radiometricTerrainCorrectionFlag') if h5_ds in hdf5_obj: del hdf5_obj[h5_ds] dset = hdf5_obj.create_dataset(h5_ds, data=bool(flag_apply_rtc)) # save GCOV diagonal elements xds = hdf5_obj[os.path.join(root_ds, 'xCoordinates')] yds = hdf5_obj[os.path.join(root_ds, 'yCoordinates')] cov_elements_list = [p.upper() + p.upper() for p in pol_list] # save GCOV imagery _save_hdf5_dataset(temp_output.name, hdf5_obj, root_ds, yds, xds, cov_elements_list, long_name=output_radiometry_str, units='', valid_min=clip_min, valid_max=clip_max) # save listOfCovarianceTerms freq_group = hdf5_obj[root_ds] if not flag_fullcovariance: _save_list_cov_terms(cov_elements_list, freq_group) # save nlooks if flag_save_nlooks: _save_hdf5_dataset(temp_nlooks.name, hdf5_obj, root_ds, yds, xds, 'numberOfLooks', long_name='number of looks', units='', valid_min=0) # save rtc if flag_save_rtc: _save_hdf5_dataset(temp_rtc.name, hdf5_obj, root_ds, yds, xds, 'areaNormalizationFactor', long_name='RTC area factor', units='', valid_min=0) # save interpolated DEM if flag_save_dem: ''' The DEM is interpolated over the geogrid pixels vertices rather than the pixels centers. ''' if (output_mode == isce3.geocode.GeocodeOutputMode.AREA_PROJECTION): dem_geogrid = isce3.product.GeoGridParameters( start_x=geogrid.start_x - geogrid.spacing_x / 2, start_y=geogrid.start_y - geogrid.spacing_y / 2, spacing_x=geogrid.spacing_x, spacing_y=geogrid.spacing_y, width=int(geogrid.width) + 1, length=int(geogrid.length) + 1, epsg=geogrid.epsg) yds_dem, xds_dem = \ set_get_geo_info(hdf5_obj, root_ds, dem_geogrid) else: yds_dem = yds xds_dem = xds _save_hdf5_dataset(temp_interpolated_dem.name, hdf5_obj, root_ds, yds_dem, xds_dem, 'interpolatedDem', long_name='Interpolated DEM', units='') # save GCOV off-diagonal elements if flag_fullcovariance: off_diag_terms_list = [] for b1, p1 in enumerate(pol_list): for b2, p2 in enumerate(pol_list): if (b2 <= b1): continue off_diag_terms_list.append(p1.upper() + p2.upper()) _save_list_cov_terms(cov_elements_list + off_diag_terms_list, freq_group) _save_hdf5_dataset(temp_off_diag.name, hdf5_obj, root_ds, yds, xds, off_diag_terms_list, long_name=output_radiometry_str, units='', valid_min=clip_min, valid_max=clip_max) t_freq_elapsed = time.time() - t_freq info_channel.log( f'frequency {frequency} ran in {t_freq_elapsed:.3f} seconds') if frequency.upper() == 'B': continue cube_geogrid = isce3.product.GeoGridParameters( start_x=radar_grid_cubes_geogrid.start_x, start_y=radar_grid_cubes_geogrid.start_y, spacing_x=radar_grid_cubes_geogrid.spacing_x, spacing_y=radar_grid_cubes_geogrid.spacing_y, width=int(radar_grid_cubes_geogrid.width), length=int(radar_grid_cubes_geogrid.length), epsg=radar_grid_cubes_geogrid.epsg) cube_group_name = '/science/LSAR/GCOV/metadata/radarGrid' native_doppler = slc.getDopplerCentroid() ''' The native-Doppler LUT bounds error is turned off to computer cubes values outside radar-grid boundaries ''' native_doppler.bounds_error = False add_radar_grid_cubes_to_hdf5(hdf5_obj, cube_group_name, cube_geogrid, radar_grid_cubes_heights, radar_grid, orbit, native_doppler, zero_doppler, threshold, maxiter) t_all_elapsed = time.time() - t_all info_channel.log( f"successfully ran geocode COV in {t_all_elapsed:.3f} seconds")
def run(cfg, resample_type): ''' run resample_slc ''' input_hdf5 = cfg['input_file_group']['secondary_file_path'] scratch_path = pathlib.Path(cfg['product_path_group']['scratch_path']) freq_pols = cfg['processing']['input_subset']['list_of_frequencies'] # According to the type of resampling, choose proper resample cfg resamp_args = cfg['processing'][f'{resample_type}_resample'] # Get SLC parameters slc = SLC(hdf5file=input_hdf5) info_channel = journal.info('resample_slc.run') info_channel.log('starting resampling SLC') # Check if use GPU or CPU resampling use_gpu = isce3.core.gpu_check.use_gpu(cfg['worker']['gpu_enabled'], cfg['worker']['gpu_id']) if use_gpu: # Set current CUDA device device = isce3.cuda.core.Device(cfg['worker']['gpu_id']) isce3.cuda.core.set_device(device) t_all = time.time() for freq in freq_pols.keys(): # Get frequency specific parameters radar_grid = slc.getRadarGrid(frequency=freq) native_doppler = slc.getDopplerCentroid(frequency=freq) # Open offsets offsets_dir = pathlib.Path(resamp_args['offsets_dir']) # Create separate directories for coarse and fine resample # Open corresponding range/azimuth offsets resample_slc_scratch_path = scratch_path / \ f'{resample_type}_resample_slc' / f'freq{freq}' if resample_type == 'coarse': offsets_path = offsets_dir / 'geo2rdr' / f'freq{freq}' rg_off = isce3.io.Raster(str(offsets_path / 'range.off')) az_off = isce3.io.Raster(str(offsets_path / 'azimuth.off')) else: # We checked the existence of HH/VV offsets in resample_slc_runconfig.py # Select the first offsets available between HH and VV freq_offsets_path = offsets_dir / 'rubbersheet_offsets' / f'freq{freq}' if os.path.isdir(str(freq_offsets_path / 'HH')): offsets_path = freq_offsets_path / 'HH' else: offsets_path = freq_offsets_path / 'VV' rg_off = isce3.io.Raster(str(offsets_path / 'range.off.vrt')) az_off = isce3.io.Raster(str(offsets_path / 'azimuth.off.vrt')) # Create resample slc directory resample_slc_scratch_path.mkdir(parents=True, exist_ok=True) # Initialize CPU or GPU resample object accordingly if use_gpu: Resamp = isce3.cuda.image.ResampSlc else: Resamp = isce3.image.ResampSlc resamp_obj = Resamp(radar_grid, native_doppler) # If lines per tile is > 0, assign it to resamp_obj if resamp_args['lines_per_tile']: resamp_obj.lines_per_tile = resamp_args['lines_per_tile'] # Get polarization list for which resample SLCs pol_list = freq_pols[freq] for pol in pol_list: # Create directory for each polarization out_dir = resample_slc_scratch_path / pol out_dir.mkdir(parents=True, exist_ok=True) out_path = out_dir / 'coregistered_secondary.slc' # Extract and create raster of SLC to resample h5_ds = f'/{slc.SwathPath}/frequency{freq}/{pol}' raster_path = f'HDF5:{input_hdf5}:{h5_ds}' raster = isce3.io.Raster(raster_path) # Create output raster resamp_slc = isce3.io.Raster(str(out_path), rg_off.width, rg_off.length, rg_off.num_bands, gdal.GDT_CFloat32, 'ENVI') resamp_obj.resamp(raster, resamp_slc, rg_off, az_off) t_all_elapsed = time.time() - t_all info_channel.log( f"successfully ran resample in {t_all_elapsed:.3f} seconds")
def main(opts): """ crossmul """ # prepare input rasters referenceSlc = SLC(hdf5file=opts.reference) referenceSlcDataset = referenceSlc.getSlcDataset(opts.frequency, opts.polarization) referenceSlcRaster = isce3.io.raster(filename='', h5=referenceSlcDataset) secondarySlc = SLC(hdf5file=opts.secondary) if opts.secondaryRaster: secondarySlcRaster = isce3.io.raster(filename=opts.secondaryRaster) else: secondarySlcDataset = secondarySlc.getSlcDataset( opts.frequency, opts.polarization) secondarySlcRaster = isce3.io.raster(filename='', h5=secondarySlcDataset) # prepare mulitlooked interferogram dimensions referenceGrid = referenceSlc.getRadarGrid(opts.frequency) length = int(referenceGrid.length / opts.alks) width = int(referenceGrid.width / opts.rlks) # init output directory(s) getDir = lambda filepath: os.path.split(filepath)[0] os.makedirs(getDir(opts.intFilePath), exist_ok=True) os.makedirs(getDir(opts.cohFilePath), exist_ok=True) # prepare output rasters driver = gdal.GetDriverByName('ISCE') igramDataset = driver.Create(opts.intFilePath, width, length, 1, gdal.GDT_CFloat32) igramRaster = isce3.io.raster(filename='', dataset=igramDataset) # coherence only generated when multilooked enabled if (opts.alks > 1 or opts.rlks > 1): cohDataset = driver.Create(opts.cohFilePath, width, length, 1, gdal.GDT_Float32) cohRaster = isce3.io.raster(filename='', dataset=cohDataset) else: cohRaster = None # prepare optional rasters if opts.rgoff: rgOffRaster = isce3.io.raster(filename=opts.rgoff) else: rgOffRaster = None if opts.azband: dopReference = referenceSlc.getDopplerCentroid() dopSecondary = secondarySlc.getDopplerCentroid() prf = referenceSlc.getSwathMetadata( opts.frequency).nominalAcquisitionPRF azimuthBandwidth = opts.azband else: dopReference = dopSecondary = None prf = azimuthBandwidth = 0.0 # instantiate crossmul object based on user input if 'cuda' not in dir(isce3) and opts.gpu: warnings.warn('CUDA crossmul not available. Switching to CPU crossmul') opts.gpu = False if opts.gpu: crossmul = isce3.cuda.signal.crossmul() else: crossmul = isce3.signal.crossmul() crossmul.crossmul(referenceSlcRaster, secondarySlcRaster, igramRaster, cohRaster, rngOffset=rgOffRaster, refDoppler=dopReference, secDoppler=dopSecondary, rangeLooks=opts.rlks, azimuthLooks=opts.alks, prf=prf, azimuthBandwidth=azimuthBandwidth)
def run(cfg): ''' run geocodeSlc according to parameters in cfg dict ''' # pull parameters from cfg input_hdf5 = cfg['input_file_group']['input_file_path'] output_hdf5 = cfg['product_path_group']['sas_output_file'] freq_pols = cfg['processing']['input_subset']['list_of_frequencies'] geogrids = cfg['processing']['geocode']['geogrids'] radar_grid_cubes_geogrid = cfg['processing']['radar_grid_cubes']['geogrid'] radar_grid_cubes_heights = cfg['processing']['radar_grid_cubes']['heights'] dem_file = cfg['dynamic_ancillary_file_group']['dem_file'] threshold_geo2rdr = cfg['processing']['geo2rdr']['threshold'] iteration_geo2rdr = cfg['processing']['geo2rdr']['maxiter'] lines_per_block = cfg['processing']['blocksize']['y'] dem_block_margin = cfg['processing']['dem_margin'] flatten = cfg['processing']['flatten'] # init parameters shared by frequency A and B slc = SLC(hdf5file=input_hdf5) orbit = slc.getOrbit() dem_raster = isce3.io.Raster(dem_file) epsg = dem_raster.get_epsg() proj = isce3.core.make_projection(epsg) ellipsoid = proj.ellipsoid # Doppler of the image grid (Zero for NISAR) image_grid_doppler = isce3.core.LUT2d() info_channel = journal.info("gslc.run") info_channel.log("starting geocode SLC") t_all = time.time() with h5py.File(output_hdf5, 'a') as dst_h5: for freq in freq_pols.keys(): frequency = f"frequency{freq}" pol_list = freq_pols[freq] radar_grid = slc.getRadarGrid(freq) geo_grid = geogrids[freq] # get doppler centroid native_doppler = slc.getDopplerCentroid(frequency=freq) for polarization in pol_list: t_pol = time.time() output_dir = os.path.dirname(os.path.abspath(output_hdf5)) os.makedirs(output_dir, exist_ok=True) raster_ref = f'HDF5:{input_hdf5}:/{slc.slcPath(freq, polarization)}' slc_raster = isce3.io.Raster(raster_ref) # access the HDF5 dataset for a given frequency and polarization dataset_path = f'/science/LSAR/GSLC/grids/{frequency}/{polarization}' gslc_dataset = dst_h5[dataset_path] # Construct the output ratster directly from HDF5 dataset gslc_raster = isce3.io.Raster( f"IH5:::ID={gslc_dataset.id.id}".encode("utf-8"), update=True) # run geocodeSlc isce3.geocode.geocode_slc(gslc_raster, slc_raster, dem_raster, radar_grid, geo_grid, orbit, native_doppler, image_grid_doppler, ellipsoid, threshold_geo2rdr, iteration_geo2rdr, lines_per_block, dem_block_margin, flatten) # the rasters need to be deleted del gslc_raster del slc_raster # output_raster_ref = f'HDF5:{output_hdf5}:/{dataset_path}' gslc_raster = isce3.io.Raster( f"IH5:::ID={gslc_dataset.id.id}".encode("utf-8")) compute_stats_complex_data(gslc_raster, gslc_dataset) t_pol_elapsed = time.time() - t_pol info_channel.log( f'polarization {polarization} ran in {t_pol_elapsed:.3f} seconds' ) if freq.upper() == 'B': continue cube_geogrid = isce3.product.GeoGridParameters( start_x=radar_grid_cubes_geogrid.start_x, start_y=radar_grid_cubes_geogrid.start_y, spacing_x=radar_grid_cubes_geogrid.spacing_x, spacing_y=radar_grid_cubes_geogrid.spacing_y, width=int(radar_grid_cubes_geogrid.width), length=int(radar_grid_cubes_geogrid.length), epsg=radar_grid_cubes_geogrid.epsg) cube_group_name = '/science/LSAR/GSLC/metadata/radarGrid' native_doppler.bounds_error = False ''' The native-Doppler LUT bounds error is turned off to computer cubes values outside radar-grid boundaries ''' add_radar_grid_cubes_to_hdf5(dst_h5, cube_group_name, cube_geogrid, radar_grid_cubes_heights, radar_grid, orbit, native_doppler, image_grid_doppler, threshold_geo2rdr, iteration_geo2rdr) t_all_elapsed = time.time() - t_all info_channel.log( f"successfully ran geocode SLC in {t_all_elapsed:.3f} seconds")
def run(cfg): ''' run rdr2geo ''' # pull parameters from cfg input_hdf5 = cfg['input_file_group']['input_file_path'] dem_file = cfg['dynamic_ancillary_file_group']['dem_file'] scratch_path = pathlib.Path(cfg['product_path_group']['scratch_path']) freq_pols = cfg['processing']['input_subset']['list_of_frequencies'] threshold = cfg['processing']['rdr2geo']['threshold'] numiter = cfg['processing']['rdr2geo']['numiter'] extraiter = cfg['processing']['rdr2geo']['extraiter'] lines_per_block = cfg['processing']['rdr2geo']['lines_per_block'] # get params from SLC slc = SLC(hdf5file=input_hdf5) orbit = slc.getOrbit() # set defaults shared by both frequencies dem_raster = isce3.io.Raster(dem_file) epsg = dem_raster.get_epsg() proj = isce3.core.make_projection(epsg) ellipsoid = proj.ellipsoid # NISAR RSLC products are always zero doppler grid_doppler = isce3.core.LUT2d() info_channel = journal.info("rdr2geo.run") info_channel.log("starting rdr2geo") # check if gpu ok to use use_gpu = isce3.core.gpu_check.use_gpu(cfg['worker']['gpu_enabled'], cfg['worker']['gpu_id']) if use_gpu: # Set the current CUDA device. device = isce3.cuda.core.Device(cfg['worker']['gpu_id']) isce3.cuda.core.set_device(device) t_all = time.time() for freq in freq_pols.keys(): # get frequency specific parameters radargrid = slc.getRadarGrid(freq) # create seperate directory within scratch dir for rdr2geo run rdr2geo_scratch_path = scratch_path / 'rdr2geo' / f'freq{freq}' rdr2geo_scratch_path.mkdir(parents=True, exist_ok=True) # init CPU or CUDA object accordingly if use_gpu: Rdr2Geo = isce3.cuda.geometry.Rdr2Geo else: Rdr2Geo = isce3.geometry.Rdr2Geo rdr2geo_obj = Rdr2Geo(radargrid, orbit, ellipsoid, grid_doppler, threshold=threshold, numiter=numiter, extraiter=extraiter, lines_per_block=lines_per_block) # dict of layer names keys to tuples of their output name and GDAL types layers = { 'x': ('x', gdal.GDT_Float64), 'y': ('y', gdal.GDT_Float64), 'z': ('z', gdal.GDT_Float64), 'incidence': ('incidence', gdal.GDT_Float32), 'heading': ('heading', gdal.GDT_Float32), 'local_incidence': ('localIncidence', gdal.GDT_Float32), 'local_psi': ('localPsi', gdal.GDT_Float32), 'simulated_amplitude': ('simamp', gdal.GDT_Float32), 'layover_shadow': ('layoverShadowMask', gdal.GDT_Byte) } # get rdr2geo config dict from processing dict for brevity rdr2geo_cfg = cfg['processing']['rdr2geo'] # list comprehend rasters to be written from layers dict raster_list = [ get_raster_obj(f'{str(rdr2geo_scratch_path)}/{fname}.rdr', radargrid, rdr2geo_cfg[f'write_{key_name}'], dtype) for key_name, (fname, dtype) in layers.items() ] # extract individual elements from dict as args for topo x_raster, y_raster, height_raster, incidence_raster,\ heading_raster, local_incidence_raster, local_psi_raster,\ simulated_amplitude_raster, shadow_raster = raster_list # run topo rdr2geo_obj.topo(dem_raster, x_raster, y_raster, height_raster, incidence_raster, heading_raster, local_incidence_raster, local_psi_raster, simulated_amplitude_raster, shadow_raster) # remove undesired/None rasters from raster list raster_list = [raster for raster in raster_list if raster is not None] # save non-None rasters to vrt output_vrt = isce3.io.Raster(f'{str(rdr2geo_scratch_path)}/topo.vrt', raster_list) output_vrt.set_epsg(rdr2geo_obj.epsg_out) t_all_elapsed = time.time() - t_all info_channel.log( f"successfully ran rdr2geo in {t_all_elapsed:.3f} seconds")
def run(cfg: dict, output_hdf5: str = None, resample_type='coarse'): ''' run crossmul ''' # pull parameters from cfg ref_hdf5 = cfg['input_file_group']['input_file_path'] sec_hdf5 = cfg['input_file_group']['secondary_file_path'] freq_pols = cfg['processing']['input_subset']['list_of_frequencies'] flatten = cfg['processing']['crossmul']['flatten'] if flatten is not None: flatten_path = cfg['processing']['crossmul']['flatten'] if output_hdf5 is None: output_hdf5 = cfg['product_path_group']['sas_output_file'] # init parameters shared by frequency A and B ref_slc = SLC(hdf5file=ref_hdf5) sec_slc = SLC(hdf5file=sec_hdf5) error_channel = journal.error('crossmul.run') info_channel = journal.info("crossmul.run") info_channel.log("starting crossmultipy") # check if gpu ok to use use_gpu = isce3.core.gpu_check.use_gpu(cfg['worker']['gpu_enabled'], cfg['worker']['gpu_id']) if use_gpu: # Set the current CUDA device. device = isce3.cuda.core.Device(cfg['worker']['gpu_id']) isce3.cuda.core.set_device(device) crossmul = isce3.cuda.signal.Crossmul() else: crossmul = isce3.signal.Crossmul() crossmul.range_looks = cfg['processing']['crossmul']['range_looks'] crossmul.az_looks = cfg['processing']['crossmul']['azimuth_looks'] crossmul.oversample = cfg['processing']['crossmul']['oversample'] crossmul.rows_per_block = cfg['processing']['crossmul']['rows_per_block'] # check if user provided path to raster(s) is a file or directory coregistered_slc_path = pathlib.Path( cfg['processing']['crossmul']['coregistered_slc_path']) coregistered_is_file = coregistered_slc_path.is_file() if not coregistered_is_file and not coregistered_slc_path.is_dir(): err_str = f"{coregistered_slc_path} is invalid; needs to be a file or directory." error_channel.log(err_str) raise ValueError(err_str) t_all = time.time() with h5py.File(output_hdf5, 'a', libver='latest', swmr=True) as dst_h5: for freq, pol_list in freq_pols.items(): # get 2d doppler, discard azimuth dependency, and set crossmul dopplers ref_dopp = isce3.core.avg_lut2d_to_lut1d( ref_slc.getDopplerCentroid(frequency=freq)) sec_dopp = isce3.core.avg_lut2d_to_lut1d( sec_slc.getDopplerCentroid(frequency=freq)) crossmul.set_dopplers(ref_dopp, sec_dopp) freq_group_path = f'/science/LSAR/RIFG/swaths/frequency{freq}' if flatten is not None: # set frequency dependent range offset raster flatten_raster = isce3.io.Raster( f'{flatten_path}/geo2rdr/freq{freq}/range.off') # prepare range filter parameters rdr_grid = ref_slc.getRadarGrid(freq) rg_pxl_spacing = rdr_grid.range_pixel_spacing wavelength = rdr_grid.wavelength rg_sample_freq = isce3.core.speed_of_light / 2.0 / rg_pxl_spacing rg_bandwidth = ref_slc.getSwathMetadata( freq).processed_range_bandwidth # set crossmul range filter crossmul.set_rg_filter(rg_sample_freq, rg_bandwidth, rg_pxl_spacing, wavelength) for pol in pol_list: pol_group_path = f'{freq_group_path}/interferogram/{pol}' # prepare reference input raster ref_raster_str = f'HDF5:{ref_hdf5}:/{ref_slc.slcPath(freq, pol)}' ref_slc_raster = isce3.io.Raster(ref_raster_str) # prepare secondary input raster if coregistered_is_file: raster_str = f'HDF5:{sec_hdf5}:/{sec_slc.slcPath(freq, pol)}' else: raster_str = str( coregistered_slc_path / f'{resample_type}_resample_slc/' f'freq{freq}/{pol}/coregistered_secondary.slc') sec_slc_raster = isce3.io.Raster(raster_str) # access the HDF5 dataset for a given frequency and polarization dataset_path = f'{pol_group_path}/wrappedInterferogram' igram_dataset = dst_h5[dataset_path] # Construct the output ratster directly from HDF5 dataset igram_raster = isce3.io.Raster( f"IH5:::ID={igram_dataset.id.id}".encode("utf-8"), update=True) # call crossmul with coherence if multilooked if crossmul.range_looks > 1 or crossmul.az_looks > 1: # access the HDF5 dataset for a given frequency and polarization dataset_path = f'{pol_group_path}/coherenceMagnitude' coherence_dataset = dst_h5[dataset_path] # Construct the output ratster directly from HDF5 dataset coherence_raster = isce3.io.Raster( f"IH5:::ID={coherence_dataset.id.id}".encode("utf-8"), update=True) if flatten is not None: crossmul.crossmul(ref_slc_raster, sec_slc_raster, flatten_raster, igram_raster, coherence_raster) else: crossmul.crossmul(ref_slc_raster, sec_slc_raster, igram_raster, coherence_raster) # Allocate raster statistics for coherence compute_stats_real_data(coherence_raster, coherence_dataset) del coherence_raster else: # no coherence without multilook crossmul.crossmul(ref_slc_raster, sec_slc_raster, igram_raster) del igram_raster # Allocate stats for rubbersheet offsets stats_offsets(dst_h5, freq, pol) t_all_elapsed = time.time() - t_all info_channel.log( f"successfully ran crossmul in {t_all_elapsed:.3f} seconds")
def cpu_run(cfg, runw_hdf5, output_hdf5): """ Geocode RUNW products on CPU Parameters ---------- cfg : dict Dictionary containing run configuration runw_hdf5 : str Path input RUNW HDF5 output_hdf5 : str Path to output GUNW HDF5 """ # pull parameters from cfg ref_hdf5 = cfg["input_file_group"]["input_file_path"] freq_pols = cfg["processing"]["input_subset"]["list_of_frequencies"] geogrids = cfg["processing"]["geocode"]["geogrids"] dem_file = cfg["dynamic_ancillary_file_group"]["dem_file"] threshold_geo2rdr = cfg["processing"]["geo2rdr"]["threshold"] iteration_geo2rdr = cfg["processing"]["geo2rdr"]["maxiter"] lines_per_block = cfg["processing"]["geocode"]["lines_per_block"] dem_block_margin = cfg["processing"]["dem_margin"] az_looks = cfg["processing"]["crossmul"]["azimuth_looks"] rg_looks = cfg["processing"]["crossmul"]["range_looks"] interp_method = cfg["processing"]["geocode"]["interp_method"] gunw_datasets = cfg["processing"]["geocode"]["datasets"] scratch_path = pathlib.Path(cfg['product_path_group']['scratch_path']) offset_cfg = cfg["processing"]["dense_offsets"] slc = SLC(hdf5file=ref_hdf5) info_channel = journal.info("geocode.run") info_channel.log("starting geocode") # NISAR products are always zero doppler grid_zero_doppler = isce3.core.LUT2d() # set defaults shared by both frequencies dem_raster = isce3.io.Raster(dem_file) epsg = dem_raster.get_epsg() proj = isce3.core.make_projection(epsg) ellipsoid = proj.ellipsoid # init geocode object geo = isce3.geocode.GeocodeFloat32() # init geocode members orbit = slc.getOrbit() geo.orbit = orbit geo.ellipsoid = ellipsoid geo.doppler = grid_zero_doppler geo.threshold_geo2rdr = threshold_geo2rdr geo.numiter_geo2rdr = iteration_geo2rdr geo.dem_block_margin = dem_block_margin geo.lines_per_block = lines_per_block geo.data_interpolator = interp_method t_all = time.time() with h5py.File(output_hdf5, "a") as dst_h5: for freq, pol_list in freq_pols.items(): radar_grid_slc = slc.getRadarGrid(freq) if az_looks > 1 or rg_looks > 1: radar_grid_mlook = radar_grid_slc.multilook(az_looks, rg_looks) geo_grid = geogrids[freq] geo.geogrid( geo_grid.start_x, geo_grid.start_y, geo_grid.spacing_x, geo_grid.spacing_y, geo_grid.width, geo_grid.length, geo_grid.epsg, ) # Assign correct radar grid if az_looks > 1 or rg_looks > 1: radar_grid = radar_grid_mlook else: radar_grid = radar_grid_slc desired = ['coherence_magnitude', 'unwrapped_phase'] geo.data_interpolator = interp_method cpu_geocode_rasters(geo, gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, radar_grid, dem_raster) desired = ["connected_components"] geo.data_interpolator = 'NEAREST' cpu_geocode_rasters(geo, gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, radar_grid, dem_raster) desired = ['along_track_offset', 'slant_range_offset'] geo.data_interpolator = interp_method radar_grid_offset = get_offset_radar_grid(offset_cfg, radar_grid_slc) cpu_geocode_rasters(geo, gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, radar_grid_offset, dem_raster) desired = ["layover_shadow_mask"] geo.data_interpolator = 'NEAREST' cpu_geocode_rasters(geo, gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, radar_grid_slc, dem_raster, scratch_path, compute_stats=False) # spec for NISAR GUNW does not require freq B so skip radar cube if freq.upper() == 'B': continue add_radar_grid_cube(cfg, freq, radar_grid, orbit, dst_h5) t_all_elapsed = time.time() - t_all info_channel.log(f"Successfully ran geocode in {t_all_elapsed:.3f} seconds")
def create(cfg, frequency_group=None, frequency=None, geocode_dict=None, default_spacing_x=None, default_spacing_y=None): ''' - frequency_group is the name of the sub-group that holds the fields x_posting and y_posting, which is usually the frequency groups "A" or "B". If these fields are direct member of the output_posting group, e.g for radar_grid_cubes, the frequency_group should be left as None. - frequency is the frequency name, if not provided, it will be the same as the frequency_group. - geocode_dict overwrites the default geocode_dict from processing.geocode - default_spacing_x is default pixel spacing in the X-direction - default_spacing_y is default pixel spacing in the Y-direction For production we only fix epsgcode and snap value and will rely on the rslc product metadta to compute the bounding box of the geocoded products there is a place holder in SLC product for compute Bounding box when that method is populated we should be able to simply say bbox = self.slc_obj.computeBoundingBox(epsg=state.epsg) for now let's rely on the run config input ''' error_channel = journal.error('geogrid.create') # unpack and init if geocode_dict is None: geocode_dict = cfg['processing']['geocode'] input_hdf5 = cfg['input_file_group']['input_file_path'] dem_file = cfg['dynamic_ancillary_file_group']['dem_file'] slc = SLC(hdf5file=input_hdf5) # unpack and check cfg dict values. default values set to trigger inside fix(...) epsg = geocode_dict['output_epsg'] start_x = geocode_dict['top_left']['x_abs'] start_y = geocode_dict['top_left']['y_abs'] if frequency is None: frequency = frequency_group if frequency_group is None: spacing_x = geocode_dict['output_posting']['x_posting'] spacing_y = geocode_dict['output_posting']['y_posting'] else: spacing_x = geocode_dict['output_posting'][frequency_group][ 'x_posting'] spacing_y = geocode_dict['output_posting'][frequency_group][ 'y_posting'] end_x = geocode_dict['bottom_right']['x_abs'] end_y = geocode_dict['bottom_right']['y_abs'] assert epsg is not None assert 1024 <= epsg <= 32767 if spacing_y is not None: # spacing_y from runconfig should be positive valued assert spacing_y > 0.0 spacing_y = -1.0 * spacing_y # copy X spacing from default X spacing (if applicable) if spacing_x is None and default_spacing_x is not None: spacing_x = default_spacing_x # copy Y spacing from default Y spacing (if applicable) if spacing_y is None and default_spacing_y is not None: spacing_y = default_spacing_y if spacing_x is None or spacing_y is None: dem_raster = isce3.io.Raster(dem_file) # Set pixel spacing using the input DEM (same EPSG) if epsg == dem_raster.get_epsg(): # copy X spacing from DEM if spacing_x is None: spacing_x = dem_raster.dx # DEM X spacing should be positive if spacing_x <= 0: err_str = f'Expected positive pixel spacing in the X/longitude direction' err_str += f' for DEM {dem_file}. Actual value: {spacing_x}.' error_channel.log(err_str) raise ValueError(err_str) # copy Y spacing from DEM if spacing_y is None: spacing_y = dem_raster.dy # DEM Y spacing should be negative if spacing_y >= 0: err_str = f'Expected negative pixel spacing in the Y/latitude direction' err_str += f' for DEM {dem_file}. Actual value: {spacing_y}.' error_channel.log(err_str) raise ValueError(err_str) else: epsg_spatial_ref = osr.SpatialReference() epsg_spatial_ref.ImportFromEPSG(epsg) # Set pixel spacing in degrees (lat/lon) if epsg_spatial_ref.IsGeographic(): if spacing_x is None: spacing_x = 0.00017966305682390427 if spacing_y is None: spacing_y = -0.00017966305682390427 # Set pixel spacing in meters else: if spacing_x is None: spacing_x = 20 if spacing_y is None: spacing_y = -20 if spacing_x == 0.0 or spacing_y == 0.0: err_str = 'spacing_x or spacing_y cannot be 0.0' error_channel.log(err_str) raise ValueError(err_str) # init geogrid if None in [start_x, start_y, epsg, end_x, end_y]: # extract other geogrid params from radar grid and orbit constructed bounding box geogrid = isce3.product.bbox_to_geogrid(slc.getRadarGrid(frequency), slc.getOrbit(), isce3.core.LUT2d(), spacing_x, spacing_y, epsg) # restore runconfig start_x (if provided) if start_x is not None: end_x_from_function = geogrid.start_x + geogrid.spacing_x * geogrid.width geogrid.start_x = start_x geogrid.width = int( np.ceil((end_x_from_function - start_x) / geogrid.spacing_x)) # restore runconfig end_x (if provided) if end_x is not None: geogrid.width = int( np.ceil((end_x - geogrid.start_x) / geogrid.spacing_x)) # restore runconfig start_y (if provided) if start_y is not None: end_y_from_function = geogrid.start_y + geogrid.spacing_y * geogrid.length geogrid.start_y = start_y geogrid.length = int( np.ceil((end_y_from_function - start_y) / geogrid.spacing_y)) # restore runconfig end_y (if provided) if end_y is not None: geogrid.length = int( np.ceil((end_y - geogrid.start_y) / geogrid.spacing_y)) else: width = _grid_size(end_x, start_x, spacing_x) length = _grid_size(end_y, start_y, -1.0 * spacing_y) # build from probably good user values geogrid = isce3.product.GeoGridParameters(start_x, start_y, spacing_x, spacing_y, width, length, epsg) # recheck x+y end points before snap and length+width calculation end_pt = lambda start, sz, spacing: start + spacing * sz if end_x is None: end_x = end_pt(geogrid.start_x, geogrid.spacing_x, geogrid.width) if end_y is None: end_y = end_pt(geogrid.start_y, geogrid.spacing_y, geogrid.length) # snap all the things x_snap = geocode_dict['x_snap'] y_snap = geocode_dict['y_snap'] if x_snap is not None or y_snap is not None: # check snap values before proceeding if x_snap <= 0 or y_snap <= 0: err_str = 'Snap values must be > 0.' error_channel.log(err_str) raise ValueError(err_str) if x_snap % spacing_x != 0.0 or y_snap % spacing_y != 0: err_str = 'Snap values must be exact multiples of spacings. i.e. snap % spacing == 0.0' error_channel.log(err_str) raise ValueError(err_str) snap_coord = lambda val, snap, round_func: round_func( float(val) / snap) * snap geogrid.start_x = snap_coord(geogrid.start_x, x_snap, np.floor) geogrid.start_y = snap_coord(geogrid.start_y, y_snap, np.ceil) end_x = snap_coord(end_x, x_snap, np.ceil) end_y = snap_coord(end_y, y_snap, np.floor) geogrid.length = _grid_size(end_y, geogrid.start_y, geogrid.spacing_y) geogrid.width = _grid_size(end_x, geogrid.start_x, geogrid.spacing_x) return geogrid
def main(opts): """ Runs isce::geocode::GeocodeCov for any GDAL raster with an associated HDF5 product. For example, to geocode a multilooked interferogram, provide the HDF5 product for the reference scene which defined the full-resolution radar geometry. """ # Common driver for all output files driver = gdal.GetDriverByName('ISCE') # Open input raster input_raster = Raster(opts.raster) # Open its associated product slc = SLC(hdf5file=opts.h5) # Make ellipsoid ellps = isce3.core.ellipsoid() # Get radar grid radar_grid = slc.getRadarGrid() if (opts.alks > 1 or opts.rlks > 1): radar_grid = radar_grid.multilook(opts.alks, opts.rlks) # Get orbit orbit = slc.getOrbit() # Make reference epochs consistent orbit.referenceEpoch = radar_grid.referenceEpoch # Make a zero-Doppler LUT doppler = isce3.core.lut2d() # Compute DEM bounds for radar grid proj_win = isce3.geometry.geometry.getBoundsOnGround( orbit, ellps, doppler, radar_grid, 0, 0, radar_grid.width, radar_grid.length, margin=np.radians(0.01)) # GDAL expects degrees proj_win = np.degrees(proj_win) # Extract virtual DEM covering radar bounds ds = gdal.Open(opts.dem, gdal.GA_ReadOnly) crop_dem_ds = gdal.Translate('/vsimem/dem.crop', ds, format='ISCE', projWin=proj_win) ds = None # Instantiate Geocode object geo = Geocode(orbit=orbit, ellipsoid=ellps, inputRaster=input_raster) # Set radar grid # geo.radarGrid(doppler, # radar_grid.referenceEpoch, # radar_grid.sensingStart, # 1.0/radar_grid.prf, # radar_grid.length, # radar_grid.startingRange, # radar_grid.rangePixelSpacing, # radar_grid.wavelength, # radar_grid.width, # radar_grid.lookSide) # Get DEM geotransform from DEM raster lon0, dlon, _, lat0, _, dlat = crop_dem_ds.GetGeoTransform() ny_geo = crop_dem_ds.RasterYSize nx_geo = crop_dem_ds.RasterXSize crop_dem_ds = None print('Cropped DEM shape: (%d, %d)' % (ny_geo, nx_geo)) # Open DEM raster as an ISCE raster dem_raster = Raster('/vsimem/dem.crop') # Set geographic grid geo.geoGrid(lon0, lat0, dlon, dlat, nx_geo, ny_geo, dem_raster.EPSG) # Create output raster if opts.outname == '': opts.outname = opts.raster + '.geo' odset = driver.Create(opts.outname, nx_geo, ny_geo, 1, input_raster.getDatatype(band=1)) output_raster = Raster('', dataset=odset) # Run geocoding geo.geocode(radar_grid, input_raster, output_raster, dem_raster) # Clean up crop_dem_ds = None odset = None gdal.Unlink('/vsimem/dem.crop')
def gpu_run(cfg, runw_hdf5, output_hdf5): """ Geocode RUNW products on GPU Parameters ---------- cfg : dict Dictionary containing run configuration runw_hdf5 : str Path input RUNW HDF5 output_hdf5 : str Path to output GUNW HDF5 """ t_all = time.time() # Extract parameters from cfg dictionary dem_block_margin = cfg["processing"]["dem_margin"] ref_hdf5 = cfg["input_file_group"]["input_file_path"] dem_file = cfg["dynamic_ancillary_file_group"]["dem_file"] freq_pols = cfg["processing"]["input_subset"]["list_of_frequencies"] geogrids = cfg["processing"]["geocode"]["geogrids"] lines_per_block = cfg["processing"]["geocode"]["lines_per_block"] interp_method = cfg["processing"]["geocode"]["interp_method"] gunw_datasets = cfg["processing"]["geocode"]["datasets"] az_looks = cfg["processing"]["crossmul"]["azimuth_looks"] rg_looks = cfg["processing"]["crossmul"]["range_looks"] offset_cfg = cfg["processing"]["dense_offsets"] scratch_path = pathlib.Path(cfg['product_path_group']['scratch_path']) if interp_method == 'BILINEAR': interp_method = isce3.core.DataInterpMethod.BILINEAR if interp_method == 'BICUBIC': interp_method = isce3.core.DataInterpMethod.BICUBIC if interp_method == 'NEAREST': interp_method = isce3.core.DataInterpMethod.NEAREST if interp_method == 'BIQUINTIC': interp_method = isce3.core.DataInterpMethod.BIQUINTIC info_channel = journal.info("geocode.run") info_channel.log("starting geocode") # Init frequency independent objects slc = SLC(hdf5file=ref_hdf5) grid_zero_doppler = isce3.core.LUT2d() dem_raster = isce3.io.Raster(dem_file) with h5py.File(output_hdf5, "a", libver='latest', swmr=True) as dst_h5: get_ds_names = lambda ds_dict, desired: [ x for x, y in ds_dict.items() if y and x in desired] # Per frequency, init required geocode objects for freq, pol_list in freq_pols.items(): geogrid = geogrids[freq] # Create frequency based radar grid radar_grid = slc.getRadarGrid(freq) if az_looks > 1 or rg_looks > 1: # Multilook radar grid if needed radar_grid = radar_grid.multilook(az_looks, rg_looks) desired = ['coherence_magnitude', 'unwrapped_phase'] # Create radar grid geometry used by most datasets rdr_geometry = isce3.container.RadarGeometry(radar_grid, slc.getOrbit(), grid_zero_doppler) # Create geocode object other than offset and shadow layover datasets geocode_obj = isce3.cuda.geocode.Geocode(geogrid, rdr_geometry, dem_raster, dem_block_margin, lines_per_block, interp_method, invalid_value=np.nan) gpu_geocode_rasters(gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, geocode_obj) desired = ["connected_components"] ''' connected_components raster has type unsigned char and an invalid value of NaN becomes 0 which conflicts with 0 being used to indicate an unmasked value/pixel. 255 is chosen as it is the most distant value from components assigned in ascending order [0, 1, ...) ''' geocode_conn_comp_obj = isce3.cuda.geocode.Geocode(geogrid, rdr_geometry, dem_raster, dem_block_margin, lines_per_block, isce3.core.DataInterpMethod.NEAREST, invalid_value=255) gpu_geocode_rasters(gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, geocode_conn_comp_obj) desired = ['along_track_offset', 'slant_range_offset'] # If needed create geocode object for offset datasets # Create offset unique radar grid radar_grid = get_offset_radar_grid(offset_cfg, slc.getRadarGrid(freq)) # Create radar grid geometry required by offset datasets rdr_geometry = isce3.container.RadarGeometry(radar_grid, slc.getOrbit(), grid_zero_doppler) geocode_offset_obj = isce3.cuda.geocode.Geocode(geogrid, rdr_geometry, dem_raster, dem_block_margin, lines_per_block, interp_method, invalid_value=np.nan) gpu_geocode_rasters(gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, geocode_offset_obj) desired = ["layover_shadow_mask"] # If needed create geocode object for shadow layover dataset # Create radar grid geometry required by layover shadow rdr_geometry = isce3.container.RadarGeometry(slc.getRadarGrid(freq), slc.getOrbit(), grid_zero_doppler) ''' layover shadow raster has type char and an invalid value of NaN becomes 0 which conflicts with 0 being used to indicate an unmasked value/pixel. 127 is chosen as it is the most distant value from the allowed set of [0, 1, 2, 3]. ''' geocode_shadow_obj = isce3.cuda.geocode.Geocode(geogrid, rdr_geometry, dem_raster, dem_block_margin, lines_per_block, isce3.core.DataInterpMethod.NEAREST, invalid_value=127) gpu_geocode_rasters(gunw_datasets, desired, freq, pol_list, runw_hdf5, dst_h5, geocode_shadow_obj, scratch_path, compute_stats=False) # spec for NISAR GUNW does not require freq B so skip radar cube if freq.upper() == 'B': continue add_radar_grid_cube(cfg, freq, radar_grid, slc.getOrbit(), dst_h5) t_all_elapsed = time.time() - t_all info_channel.log(f"Successfully ran geocode in {t_all_elapsed:.3f} seconds")
def run(cfg): ''' run geo2rdr ''' # Pull parameters from cfg dict sec_hdf5 = cfg['input_file_group']['secondary_file_path'] dem_file = cfg['dynamic_ancillary_file_group']['dem_file'] scratch_path = pathlib.Path(cfg['product_path_group']['scratch_path']) freq_pols = cfg['processing']['input_subset']['list_of_frequencies'] threshold = cfg['processing']['geo2rdr']['threshold'] numiter = cfg['processing']['geo2rdr']['maxiter'] lines_per_block = cfg['processing']['geo2rdr']['lines_per_block'] # Get parameters from SLC slc = SLC(hdf5file=sec_hdf5) orbit = slc.getOrbit() # Set ellipsoid based on DEM epsg dem_raster = isce3.io.Raster(dem_file) epsg = dem_raster.get_epsg() proj = isce3.core.make_projection(epsg) ellipsoid = proj.ellipsoid # NISAR RSLC products are always zero doppler doppler_grid = isce3.core.LUT2d() info_channel = journal.info('geo2rdr.run') info_channel.log("starting geo2rdr") # check if gpu use if required use_gpu = isce3.core.gpu_check.use_gpu(cfg['worker']['gpu_enabled'], cfg['worker']['gpu_id']) if use_gpu: # set CUDA device device = isce3.cuda.core.Device(cfg['worker']['gpu_id']) isce3.cuda.core.set_device(device) t_all = time.time() for freq in freq_pols.keys(): # Get parameters specific for that frequency radar_grid = slc.getRadarGrid(frequency=freq) # Create geo2rdr directory geo2rdr_scratch_path = scratch_path / 'geo2rdr' / f'freq{freq}' geo2rdr_scratch_path.mkdir(parents=True, exist_ok=True) # Initialize CPU or GPU geo2rdr object accordingly if use_gpu: Geo2Rdr = isce3.cuda.geometry.Geo2Rdr else: Geo2Rdr = isce3.geometry.Geo2Rdr geo2rdr_obj = Geo2Rdr(radar_grid, orbit, ellipsoid, doppler_grid, threshold, numiter, lines_per_block) # Opem Topo Raster topo_path = pathlib.Path(cfg['processing']['geo2rdr']['topo_path']) rdr2geo_topo_path = topo_path / 'rdr2geo' / f'freq{freq}' / 'topo.vrt' topo_raster = isce3.io.Raster(str(rdr2geo_topo_path)) # Run geo2rdr geo2rdr_obj.geo2rdr(topo_raster, str(geo2rdr_scratch_path)) t_all_elapsed = time.time() - t_all info_channel.log( f"Successfully ran geo2rdr in {t_all_elapsed:.3f} seconds")
def test_rtc(): # Open HDF5 file and create radar grid parameter print('iscetest.data:', iscetest.data) h5_path = os.path.join(iscetest.data, 'envisat.h5') slc_obj = SLC(hdf5file=h5_path) frequency = 'A' radar_grid_sl = slc_obj.getRadarGrid(frequency) # Open DEM raster dem_file = os.path.join(iscetest.data, 'srtm_cropped.tif') dem_obj = isce3.io.Raster(dem_file) # Crop original radar grid parameter radar_grid_cropped = \ radar_grid_sl.offset_and_resize(30, 135, 128, 128) # Multi-look original radar grid parameter nlooks_az = 5 nlooks_rg = 5 radar_grid_ml = \ radar_grid_sl.multilook(nlooks_az, nlooks_rg) # Create orbit and Doppler LUT orbit = slc_obj.getOrbit() doppler = slc_obj.getDopplerCentroid() doppler.bounds_error = False # doppler = isce3.core.LUT2d() # set input parameters input_terrain_radiometry = isce3.geometry.RtcInputTerrainRadiometry.BETA_NAUGHT output_terrain_radiometry = isce3.geometry.RtcOutputTerrainRadiometry.GAMMA_NAUGHT rtc_area_mode = isce3.geometry.RtcAreaMode.AREA_FACTOR for radar_grid_str in radar_grid_str_list: # Open DEM raster if (radar_grid_str == 'cropped'): radar_grid = radar_grid_cropped else: radar_grid = radar_grid_ml for rtc_algorithm in rtc_algorithm_list: geogrid_upsampling = 1 # test removed because it requires high geogrid upsampling (too # slow) if (rtc_algorithm == isce3.geometry.RtcAlgorithm.RTC_BILINEAR_DISTRIBUTION and radar_grid_str == 'cropped'): continue elif (rtc_algorithm == isce3.geometry.RtcAlgorithm.RTC_BILINEAR_DISTRIBUTION): filename = './rtc_bilinear_distribution_' + radar_grid_str + '.bin' else: filename = './rtc_area_proj_' + radar_grid_str + '.bin' print('generating file:', filename) # Create output raster out_raster = isce3.io.Raster(filename, radar_grid.width, radar_grid.length, 1, gdal.GDT_Float32, 'ENVI') # Call RTC isce3.geometry.compute_rtc(radar_grid, orbit, doppler, dem_obj, out_raster, input_terrain_radiometry, output_terrain_radiometry, rtc_area_mode, rtc_algorithm, geogrid_upsampling) del out_raster # check results for radar_grid_str in radar_grid_str_list: for rtc_algorithm in rtc_algorithm_list: # test removed because it requires high geogrid upsampling (too # slow) if (rtc_algorithm == isce3.geometry.RtcAlgorithm.RTC_BILINEAR_DISTRIBUTION and radar_grid_str == 'cropped'): continue elif (rtc_algorithm == isce3.geometry.RtcAlgorithm.RTC_BILINEAR_DISTRIBUTION): max_rmse = 0.7 filename = './rtc_bilinear_distribution_' + radar_grid_str + '.bin' else: max_rmse = 0.1 filename = './rtc_area_proj_' + radar_grid_str + '.bin' print('evaluating file:', os.path.abspath(filename)) # Open computed integrated-area raster test_gdal_dataset = gdal.Open(filename) # Open reference raster ref_filename = os.path.join(iscetest.data, 'rtc/rtc_' + radar_grid_str + '.bin') ref_gdal_dataset = gdal.Open(ref_filename) print('reference file:', ref_filename) assert ( test_gdal_dataset.RasterXSize == ref_gdal_dataset.RasterXSize) assert ( test_gdal_dataset.RasterYSize == ref_gdal_dataset.RasterYSize) square_sum = 0.0 # sum of square difference n_nan = 0 # number of NaN pixels n_npos = 0 # number of non-positive pixels # read test and ref arrays test_array = test_gdal_dataset.GetRasterBand(1).ReadAsArray() ref_array = ref_gdal_dataset.GetRasterBand(1).ReadAsArray() n_valid = 0 # iterates over rows (i) and columns (j) for i in range(ref_gdal_dataset.RasterYSize): for j in range(ref_gdal_dataset.RasterXSize): # if nan, increment n_nan if (np.isnan(test_array[i, j]) or np.isnan(ref_array[i, j])): n_nan = n_nan + 1 continue # if n_npos, incremennt n_npos if (ref_array[i, j] <= 0 or test_array[i, j] <= 0): n_npos = n_npos + 1 continue # otherwise, increment n_valid n_valid = n_valid + 1 square_sum += (test_array[i, j] - ref_array[i, j])**2 print(' ----------------') print(' # total:', n_valid + n_nan + n_npos) print(' ----------------') print(' # valid:', n_valid) print(' # NaNs:', n_nan) print(' # non-positive:', n_npos) print(' ----------------') assert (n_valid != 0) # Compute average over entire image rmse = np.sqrt(square_sum / n_valid) print(' RMSE =', rmse) print(' ----------------') # Enforce bound on average pixel-error assert (rmse < max_rmse) # Enforce bound on number of ignored pixels assert (n_nan < 1e-4 * ref_gdal_dataset.RasterXSize * ref_gdal_dataset.RasterYSize) assert (n_npos < 1e-4 * ref_gdal_dataset.RasterXSize * ref_gdal_dataset.RasterYSize)