def _grd_subset_georegion(infile, outfile, logfile, georegion): '''A wrapper around SNAP's subset routine This function takes an OST imported frame and subsets it according to the coordinates given in the region Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to georegion (str): a WKT style formatted POLYGON that bounds the subset region ''' # get Snap's gpt file gpt_file = h.gpt_path() # extract window from scene command = '{} Subset -x -q {} -Ssource=\'{}\' -t \'{}\' \ -PcopyMetadata=true -Pgeoregion=\'{}\''.format( gpt_file, 2 * os.cpu_count(), infile, outfile, georegion) # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: print(' INFO: Succesfully subsetted product') else: print(' ERROR: Subsetting exited with an error. \ See {} for Snap Error output'.format(logfile)) sys.exit(107)
def _grd_speckle_filter(infile, outfile, logfile, speckle_dict): '''A wrapper around SNAP's Lee-Sigma Speckle Filter This function takes OST imported Sentinel-1 product and applies a standardised version of the Lee-Sigma Speckle Filter with SNAP's defaut values. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to ''' # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() print(' INFO: Applying speckle filtering.') # contrcut command string command = ('{} Speckle-Filter -x -q {}' ' -PestimateENL={}' ' -PanSize={}' ' -PdampingFactor={}' ' -Penl={}' ' -Pfilter={}' ' -PfilterSizeX={}' ' -PfilterSizeY={}' ' -PnumLooksStr={}' ' -PsigmaStr={}' ' -PtargetWindowSizeStr={}' ' -PwindowSize={}' '-t \'{}\' \'{}\''.format( gpt_file, 2 * os.cpu_count(), speckle_dict['estimate ENL'], speckle_dict['pan size'], speckle_dict['damping'], speckle_dict['ENL'], speckle_dict['filter'], speckle_dict['filter x size'], speckle_dict['filter y size'], speckle_dict['num of looks'], speckle_dict['sigma'], speckle_dict['target window size'], speckle_dict['window size'], outfile, infile) ) # run command and get return code return_code = h.run_command(command, logfile) # hadle errors and logs if return_code == 0: print(' INFO: Succesfully applied speckle filtering.') else: print(' ERROR: Speckle Filtering exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def _slice_assembly(filelist, outfile, logfile, polar='VV,VH,HH,HV'): '''A wrapper of SNAP's slice assembly routine This function assembles consecutive frames acquired at the same date. Can be either GRD or SLC products Args: filelist (str): a string of a space separated list of OST imported Sentinel-1 product slices to be assembled outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to ''' print(' INFO: Assembling consecutive frames:') # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() # construct command command = '{} SliceAssembly -x -q {} -PselectedPolarisations={} \ -t \'{}\' {}'.format(gpt_file, 2 * os.cpu_count(), polar, outfile, filelist) # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: print(' INFO: Succesfully assembled products') else: print(' ERROR: Slice Assembly exited with an error. \ See {} for Snap Error output'.format(logfile)) sys.exit(101)
def _grd_speckle_filter(infile, outfile, logfile): '''A wrapper around SNAP's Lee-Sigma Speckle Filter This function takes OST imported Sentinel-1 product and applies a standardised version of the Lee-Sigma Speckle Filter with SNAP's defaut values. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to ''' # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() print(' INFO: Applying the Lee-Sigma Speckle Filter') # contrcut command string command = '{} Speckle-Filter -x -q {} -PestimateENL=true \ -t \'{}\' \'{}\''.format(gpt_file, 2 * os.cpu_count(), outfile, infile) # run command and get return code return_code = h.run_command(command, logfile) # hadle errors and logs if return_code == 0: print(' INFO: Succesfully imported product') else: print(' ERROR: Speckle Filtering exited with an error. \ See {} for Snap Error output'.format(logfile)) sys.exit(111)
def _grd_to_db(infile, outfile, logfile): '''A wrapper around SNAP's linear to db routine This function takes an OST calibrated Sentinel-1 product and converts it to dB. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to ''' # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() print(' INFO: Converting the image to dB-scale.') # construct command string command = '{} LinearToFromdB -x -q {} -t \'{}\' {}'.format( gpt_file, 2 * os.cpu_count(), outfile, infile) # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: print(' INFO: Succesfully converted product to dB-scale.') else: print(' ERROR: Linear to dB conversion exited with an error. \ See {} for Snap Error output'.format(logfile)) sys.exit(113)
def _grd_ls_mask(infile, outfile, logfile, resolution, dem_dict): '''A wrapper around SNAP's Layover/Shadow mask routine This function takes OST imported Sentinel-1 product and calculates the Layover/Shadow mask. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to resolution (int): the resolution of the output product in meters dem (str): A Snap compliant string for the dem to use. Possible choices are: 'SRTM 1sec HGT' (default) 'SRTM 3sec' 'ASTER 1sec GDEM' 'ACE30' ''' # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() # get path to ost package rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] print(' INFO: Creating the Layover/Shadow mask') # get path to workflow xml graph = opj(rootpath, 'graphs', 'S1_GRD2ARD', '3_LSmap.xml') # construct command string # command = '{} {} -x -q {} -Pinput=\'{}\' -Presol={} -Pdem=\'{}\' \ # -Poutput=\'{}\''.format(gpt_file, graph, 2 * os.cpu_count(), # infile, resolution, dem, outfile) command = ('{} {} -x -q {} -Pinput=\'{}\' -Presol={} ' ' -Pdem=\'{}\'' ' -Pdem_file=\'{}\'' ' -Pdem_nodata=\'{}\'' ' -Pdem_resampling=\'{}\'' ' -Pimage_resampling=\'{}\'' ' -Poutput=\'{}\''.format( gpt_file, graph, 2 * os.cpu_count(), infile, resolution, dem_dict['dem name'], dem_dict['dem file'], dem_dict['dem nodata'], dem_dict['dem resampling'], dem_dict['image resampling'], outfile)) # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: print(' INFO: Succesfully create a Layover/Shadow mask') else: print(' ERROR: Layover/Shadow mask creation exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def _coreg2(master, slave, outfile, logfile, dem_dict, ncores=os.cpu_count()): '''A wrapper around SNAP's back-geocoding co-registration routine This function takes a list of 2 OST imported Sentinel-1 SLC products and co-registers them properly. This routine is sufficient for coherence estimation, but not for InSAR, since the ESD refinement is not applied. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to dem (str): A Snap compliant string for the dem to use. Possible choices are: 'SRTM 1sec HGT' (default) 'SRTM 3sec' 'ASTER 1sec GDEM' 'ACE30' ncores(int): the number of cpu cores to allocate to the gpt job - defaults to cpu count ''' # get gpt file gpt_file = h.gpt_path() # get path to graph rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Coreg.xml') # make dem file snap readable in case of no external dem if not dem_dict['dem file']: dem_dict['dem file'] = " " print(' INFO: Co-registering {} and {}'.format(master, slave)) command = ('{} {} -x -q {} ' ' -Pmaster={}' ' -Pslave={}' ' -Pdem=\'{}\'' ' -Pdem_file=\'{}\'' ' -Pdem_nodata=\'{}\'' ' -Pdem_resampling=\'{}\'' ' -Poutput={} '.format(gpt_file, graph, ncores, master, slave, dem_dict['dem name'], dem_dict['dem file'], dem_dict['dem nodata'], dem_dict['dem resampling'], outfile)) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully coregistered product.') else: print(' ERROR: Co-registration exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def ls_mask(infile, outfile, logfile, config_dict): """Wrapper function of a Snap graph for Layover/Shadow mask creation :param infile: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters ard = config_dict['processing']['single_ARD'] dem_dict = ard['dem'] cpus = config_dict['snap_cpu_parallelism'] # auto projections of snap if 42001 <= dem_dict['out_projection'] <= 97002: projection = f"AUTO:{dem_dict['out_projection']}" # epsg codes else: projection = f"EPSG:{dem_dict['out_projection']}" logger.debug('Creating the Layover/Shadow mask') # get path to workflow xml graph = OST_ROOT.joinpath('graphs/S1_GRD2ARD/3_LSmap.xml') command = ( f'{GPT_FILE} {graph} -x -q {2 * cpus} ' f'-Pinput=\'{str(infile)}\' ' f'-Presol={ard["resolution"]} ' f'-Pdem=\'{dem_dict["dem_name"]}\' ' f'-Pdem_file=\'{dem_dict["dem_file"]}\' ' f'-Pdem_nodata=\'{dem_dict["dem_nodata"]}\' ' f'-Pdem_resampling=\'{dem_dict["dem_resampling"]}\' ' f'-Pimage_resampling=\'{dem_dict["image_resampling"]}\' ' f'-Pegm_correction=\'{str(dem_dict["egm_correction"]).lower()}\' ' f'-Pprojection=\'{projection}\' ' f'-Poutput=\'{str(outfile)}\'') # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: logger.debug('Succesfully created a Layover/Shadow mask') else: raise GPTRuntimeError( f'Layover/Shadow mask creation exited with error {return_code}. ' f'See {logfile} for Snap\'s error message.') # do check routine return_code = h.check_out_dimap(outfile, test_stats=False) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}')
def _grd_terrain_correction_deg(infile, outfile, logfile, resolution, dem='SRTM 1Sec HGT'): '''A wrapper around SNAP's Terrain Correction routine This function takes an OST calibrated Sentinel-1 product and does the geocodification. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to resolution (int): the resolution of the output product in meters dem (str): A Snap compliant string for the dem to use. Possible choices are: 'SRTM 1sec HGT' (default) 'SRTM 3sec' 'ASTER 1sec GDEM' 'ACE30' ''' # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() # get path to ost package rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] print(' INFO: Geocoding the calibrated product') # calculate the multi-look factor # multilook_factor = int(int(resolution) / 10) multilook_factor = 1 graph = opj(rootpath, 'graphs', 'S1_GRD2ARD', '3_ML_TC_deg.xml') # construct command string command = '{} {} -x -q {} -Pinput=\'{}\' -Presol={} -Pml={} -Pdem=\'{}\' \ -Poutput=\'{}\''.format(gpt_file, graph, 2 * os.cpu_count(), infile, resolution, multilook_factor, dem, outfile) # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: print(' INFO: Succesfully imported product') else: print(' ERROR: Terain Correction exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def create_stack( file_list, out_stack, logfile, config_dict, polarisation=None, pattern=None, ): """ :param file_list: :param out_stack: :param logfile: :param config_dict: :param polarisation: :param pattern: :return: """ # get relevant config parameters cpus = config_dict['snap_cpu_parallelism'] logger.debug('Creating multi-temporal stack.') if pattern: graph = OST_ROOT.joinpath('graphs/S1_TS/1_BS_Stacking_HAalpha.xml') command = (f'{GPT_FILE} {graph} -x -q {2*cpus} ' f'-Pfilelist={file_list} ' f'-PbandPattern=\'{pattern}.*\' ' f'-Poutput={out_stack}') else: graph = OST_ROOT.joinpath('graphs/S1_TS/1_BS_Stacking.xml') command = (f'{GPT_FILE} {graph} -x -q {2*cpus} ' f'-Pfilelist={file_list} ' f'-Ppol={polarisation} ' f'-Poutput={out_stack}') return_code = h.run_command(command, logfile) if return_code == 0: logger.debug('Successfully created multi-temporal stack') else: raise GPTRuntimeError( f'Multi-temporal stack creation exited with error {return_code}. ' f'See {logfile} for Snap\'s error message.') # do check routine return_msg = h.check_out_dimap(out_stack) if return_msg == 0: logger.debug('Product passed validity check.') else: raise NotValidFileError( f'Product did not pass file check: {return_msg}')
def _grd_frame_import_subset(infile, outfile, georegion, logfile, polarisation='VV,VH,HH,HV'): '''A wrapper of SNAP import of a subset of single Sentinel-1 GRD product This function takes an original Sentinel-1 scene (either zip or SAFE format), updates the orbit information (does not fail if not available), removes the thermal noise, subsets it to the given georegion and stores it as a SNAP compatible EAM-Dimap format. Args: infile: string or os.path object for an original Sentinel-1 GRD product in zip or SAFE format outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to polarisation (str): a string consisiting of the polarisation (comma separated) e.g. 'VV,VH', default value: 'VV,VH,HH,HV' georegion (str): a WKT style formatted POLYGON that bounds the subset region ''' print(' INFO: Importing {} by applying precise orbit file and' ' removing thermal noise, as well as subsetting.'.format( os.path.basename(infile))) # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() # get path to ost package rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] graph = opj(rootpath, 'graphs', 'S1_GRD2ARD', '1_AO_TNR_SUB.xml') # construct command command = '{} {} -x -q {} -Pinput=\'{}\' -Pregion=\'{}\' -Ppolarisation={} \ -Poutput=\'{}\''.format(gpt_file, graph, 2 * os.cpu_count(), infile, georegion, polarisation, outfile) # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: print(' INFO: Succesfully imported product') else: print(' ERROR: Frame import exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def slice_assembly(filelist, outfile, logfile, config_dict): """Wrapper function around SNAP's slice assembly routine :param filelist: a string of a space separated list of OST imported Sentinel-1 GRD product frames to be assembled :type filelist: str :param outfile: :param logfile: :param config_dict: :return: """ '''A wrapper of SNAP's slice assembly routine This function assembles consecutive frames acquired at the same date. Can be either GRD or SLC products Args: filelist (str): a string of a space separated list of OST imported Sentinel-1 product slices to be assembled outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to ''' # get relevant config parameters ard = config_dict['processing']['single_ARD'] polars = ard['polarisation'].replace(' ', '') cpus = config_dict['snap_cpu_parallelism'] logger.debug('Assembling consecutive frames:') # construct command command = (f'{GPT_FILE} SliceAssembly -x -q {2*cpus} ' f'-PselectedPolarisations={polars} ' f'-t \'{str(outfile)}\' {filelist}') # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: logger.debug('Succesfully assembled products') else: raise GPTRuntimeError( f'ERROR: Slice Assembly exited with error {return_code}. ' f'See {logfile} for Snap Error output') # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}')
def coreg(master, slave, outfile, logfile, config_dict): """A wrapper around SNAP's back-geocoding co-registration routine This function takes 2 OST imported Sentinel-1 SLC products (master and slave) and co-registers them properly. This routine is sufficient for coherence estimation, but not for InSAR, since the ESD refinement is not applied. :param master: :param slave: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters cpus = config_dict['snap_cpu_parallelism'] dem_dict = config_dict['processing']['single_ARD']['dem'] logger.debug(f'Co-registering {master} and {slave}') # construct command command = ( f'{GPT_FILE} Back-Geocoding -x -q {2*cpus} ' f'-PdemName=\'{dem_dict["dem_name"]}\' ' #f'-PdemName=\'SRTM 3Sec\' ' f'-PdemResamplingMethod=\'{dem_dict["dem_resampling"]}\' ' f'-PexternalDEMFile=\'{dem_dict["dem_file"]}\' ' f'-PexternalDEMNoDataValue=\'{dem_dict["dem_nodata"]}\' ' f'-PmaskOutAreaWithoutElevation=false ' f'-PresamplingType=BILINEAR_INTERPOLATION ' f'-t \'{str(outfile)}\'' f' "{master}" "{slave}"' ) logger.debug(f'Executing command: {command}') return_code = h.run_command(command, logfile) if return_code == 0: logger.debug('Succesfully coregistered product.') else: raise GPTRuntimeError( f'Co-registration exited with an error {return_code}. ' f'See {logfile} for Snap error output.' ) # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}' )
def _import(infile, out_prefix, logfile, swath, burst, polar='VV,VH,HH,HV', ncores=os.cpu_count()): '''A wrapper of SNAP import of a single Sentinel-1 SLC burst This function takes an original Sentinel-1 scene (either zip or SAFE format), updates the orbit information (does not fail if not available), and extracts a single burst based on the given input parameters. Args: infile: string or os.path object for an original Sentinel-1 GRD product in zip or SAFE format out_prefix: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to swath (str): the corresponding IW subswath of the burst burst (str): the burst number as in the Sentinel-1 annotation file polar (str): a string consisiting of the polarisation (comma separated) e.g. 'VV,VH', default value: 'VV,VH,HH,HV' ncores(int): the number of cpu cores to allocate to the gpt job - defaults to cpu count ''' # get gpt file gpt_file = h.gpt_path() # get path to graph rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_BurstSplit_AO.xml') print(' INFO: Importing Burst {} from Swath {}' ' from scene {}'.format(burst, swath, os.path.basename(infile))) command = '{} {} -x -q {} -Pinput={} -Ppolar={} -Pswath={}\ -Pburst={} -Poutput={}' \ .format(gpt_file, graph, ncores, infile, polar, swath, burst, out_prefix) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully imported product') else: print(' ERROR: Frame import exited with an error. \ See {} for Snap Error output'.format(logfile)) # sys.exit(119) return return_code
def coreg2(master, slave, outfile, logfile, config_dict): """A wrapper around SNAP's back-geocoding co-registration routine This function takes 2 OST imported Sentinel-1 SLC products (master and slave) and co-registers them properly. This routine is sufficient for coherence estimation, but not for InSAR, since the ESD refinement is not applied. :param master: :param slave: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters cpus = config_dict['snap_cpu_parallelism'] dem_dict = config_dict['processing']['single_ARD']['dem'] # get path to graph graph = OST_ROOT.joinpath('graphs/S1_SLC2ARD/S1_SLC_Coreg.xml') logger.debug(f'Co-registering {master} and {slave}') command = ( f"{GPT_FILE} {graph} -x -q {2*cpus} " f" -Pmaster={master} " f" -Pslave={slave} " f" -Pdem_name=\'{dem_dict['dem_name']}\' " f" -Pdem_file=\'{dem_dict['dem_file']}\' " f" -Pdem_nodata=\'{dem_dict['dem_nodata']}\' " f" -Pdem_resampling=\'{dem_dict['dem_resampling']}\' " f" -Poutput={str(outfile)}" ) return_code = h.run_command(command, logfile) if return_code == 0: logger.debug('Successfully co-registered product.') else: raise GPTRuntimeError( f'Co-registration exited with an error {return_code}. ' f'See {logfile} for Snap\'s error message.' ) # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}' )
def speckle_filter(infile, outfile, logfile, config_dict): """Wrapper function around SNAP's Speckle Filter function This function takes OST imported Sentinel-1 product and applies the Speckle Filter as defind within the config dictionary. :param infile: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters cpus = config_dict['snap_cpu_parallelism'] speckle_dict = config_dict['processing']['single_ARD']['speckle_filter'] logger.debug('Applying speckle filtering.') # construct command string command = ( f"{GPT_FILE} Speckle-Filter -x -q {2*cpus} " f"-PestimateENL=\'{speckle_dict['estimate_ENL']}\' " f"-PanSize=\'{speckle_dict['pan_size']}\' " f"-PdampingFactor=\'{speckle_dict['damping']}\' " f"-Penl=\'{speckle_dict['ENL']}\' " f"-Pfilter=\'{speckle_dict['filter']}\' " f"-PfilterSizeX=\'{speckle_dict['filter_x_size']}\' " f"-PfilterSizeY=\'{speckle_dict['filter_y_size']}\' " f"-PnumLooksStr=\'{speckle_dict['num_of_looks']}\' " f"-PsigmaStr=\'{speckle_dict['sigma']}\' " f"-PtargetWindowSizeStr=\"{speckle_dict['target_window_size']}\" " f"-PwindowSize=\"{speckle_dict['window_size']}\" " f"-t \'{str(outfile)}\' \'{str(infile)}\' ") # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: logger.debug('Successfully applied speckle filtering.') else: raise GPTRuntimeError( f'Speckle filtering exited with error {return_code}. ' f'See {logfile} for Snap\'s error message.') # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}')
def calibration(infile, outfile, logfile, config_dict): """ :param infile: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters product_type = config_dict['processing']['single_ARD']['product_type'] cpus = config_dict['snap_cpu_parallelism'] # transform calibration parameter to snap readable sigma0, beta0, gamma0 = 'false', 'false', 'false' if product_type == 'GTC-sigma0': sigma0 = 'true' elif product_type == 'GTC-gamma0': gamma0 = 'true' elif product_type == 'RTC-gamma0': beta0 = 'true' else: raise TypeError('Wrong product type selected.') logger.debug(f'Calibrating the product to {product_type}.') # construct command string command = (f'{GPT_FILE} Calibration -x -q {2*cpus} ' f' -PoutputBetaBand=\'{beta0}\' ' f' -PoutputGammaBand=\'{gamma0}\' ' f' -PoutputSigmaBand=\'{sigma0}\' ' f' -t \'{str(outfile)}\' \'{str(infile)}\'') # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: logger.debug(f'Calibration to {product_type} successful.') else: raise GPTRuntimeError(f'Calibration exited with error {return_code}. ' f'See {logfile} for Snap\'s error message.') # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}')
def _terrain_correction(infile, outfile, logfile, resolution, dem_dict): '''A wrapper around SNAP's Terrain Correction routine This function takes an OST calibrated Sentinel-1 product and does the geocodification. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to resolution (int): the resolution of the output product in meters dem (str): A Snap compliant string for the dem to use. Possible choices are: 'SRTM 1sec HGT' (default) 'SRTM 3sec' 'ASTER 1sec GDEM' 'ACE30' ''' # get gpt file gpt_file = h.gpt_path() print(" INFO: Geocoding input scene") command = ('{} Terrain-Correction -x -q {}' ' -PdemName=\'{}\'' ' -PexternalDEMFile=\'{}\'' ' -PexternalDEMNoDataValue=\'{}\'' ' -PdemResamplingMethod=\'{}\'' ' -PimgResamplingMethod=\'{}\'' ' -PnodataValueAtSea=\'false\'' ' -PpixelSpacingInMeter=\'{}\'' ' -t {} {}'.format(gpt_file, 2 * os.cpu_count(), dem_dict['dem name'], dem_dict['dem file'], dem_dict['dem nodata'], dem_dict['dem resampling'], dem_dict['image resampling'], resolution, outfile, infile)) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully orthorectified product.') else: print(' ERROR: Geocoding exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def _terrain_correction_deg(infile, outfile, logfile, resolution=0.001, dem='SRTM 1sec HGT'): '''A wrapper around SNAP's Terrain Correction routine This function takes an OST calibrated Sentinel-1 product and does the geocodification. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to resolution (int): the resolution of the output product in degree dem (str): A Snap compliant string for the dem to use. Possible choices are: 'SRTM 1sec HGT' (default) 'SRTM 3sec' 'ASTER 1sec GDEM' 'ACE30' ''' # get gpt file gpt_file = h.gpt_path() print(" INFO: Geocoding input scene") command = '{} Terrain-Correction -x -q {} \ -PdemResamplingMethod=\'BILINEAR_INTERPOLATION\' \ -PimgResamplingMethod=\'BILINEAR_INTERPOLATION\' \ -PnodataValueAtSea=\'false\' \ -PpixelSpacingInDegree=\'{}\' \ -PdemName=\'{}\' \ -t {} {}' \ .format(gpt_file, 2 * os.cpu_count(), resolution, dem, outfile, infile) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully imported product') else: print(' ERROR: Geocoding exited with an error. \ See {} for Snap Error output'.format(logfile)) # sys.exit(122) return return_code
def coherence(infile, outfile, logfile, config_dict): """A wrapper around SNAP's coherence routine This function takes a co-registered stack of 2 Sentinel-1 SLC products and calculates the coherence. :param infile: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters ard = config_dict['processing']['single_ARD'] polars = ard['coherence_bands'].replace(' ', '') cpus = config_dict['snap_cpu_parallelism'] # get path to graph graph = OST_ROOT.joinpath('graphs/S1_SLC2ARD/S1_SLC_Coh_Deb.xml') logger.debug('Coherence estimation') command = ( f"{GPT_FILE} {graph} -x -q {2 * cpus} " f"-Pazimuth_window={ard['coherence_azimuth']} " f"-Prange_window={ard['coherence_range']} " f'-Ppolar=\'{polars}\' ' f'-Pinput="{str(infile)}" ' f'-Poutput="{str(outfile)}"' ) logger.debug(f'Executing command: {command}') return_code = h.run_command(command, logfile) if return_code == 0: logger.debug('Succesfully created coherence product.') else: raise GPTRuntimeError( f'Coherence exited with an error {return_code}. ' f'See {logfile} for Snap\'s error message.' ) # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}' )
def mt_speckle_filter(in_stack, out_stack, logfile, speckle_dict, ncores=os.cpu_count()): ''' ''' # get gpt file gpt_file = h.gpt_path() # # get path to graph # rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] # graph = opj(rootpath, 'graphs', 'S1_TS', '2_MT_Speckle.xml') # # command = '{} {} -x -q {} -Pinput={} \ # -Poutput={}'.format(gpt_file, graph, 2 * os.cpu_count(), # in_stack, out_stack) print(' INFO: Applying multi-temporal speckle filtering.') # contrcut command string command = ('{} Multi-Temporal-Speckle-Filter -x -q {}' ' -PestimateENL={}' ' -PanSize={}' ' -PdampingFactor={}' ' -Penl={}' ' -Pfilter=\'{}\'' ' -PfilterSizeX={}' ' -PfilterSizeY={}' ' -PnumLooksStr={}' ' -PsigmaStr={}' ' -PtargetWindowSizeStr={}' ' -PwindowSize={}' ' -t \'{}\' \'{}\''.format( gpt_file, ncores, speckle_dict['estimate ENL'], speckle_dict['pan size'], speckle_dict['damping'], speckle_dict['ENL'], speckle_dict['filter'], speckle_dict['filter x size'], speckle_dict['filter y size'], speckle_dict['num of looks'], speckle_dict['sigma'], speckle_dict['target window size'], speckle_dict['window size'], out_stack, in_stack)) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Successfully applied multi-temporal speckle filtering') else: print(' ERROR: Multi-temporal speckle filtering exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def mt_speckle_filter(in_stack, out_stack, logfile, config_dict): """ :param in_stack: :param out_stack: :param logfile: :param config_dict: :return: """ # get relevant config parameters cpus = config_dict['snap_cpu_parallelism'] speckle_dict = ( config_dict['processing']['time-series_ARD']['mt_speckle_filter']) # debug message logger.debug('Applying multi-temporal speckle filtering.') # construct command string command = ( f"{GPT_FILE} Multi-Temporal-Speckle-Filter -x -q {2*cpus} " f"-PestimateENL=\'{speckle_dict['estimate_ENL']}\' " f"-PanSize=\'{speckle_dict['pan_size']}\' " f"-PdampingFactor=\'{speckle_dict['damping']}\' " f"-Penl=\'{speckle_dict['ENL']}\' " f"-Pfilter=\'{speckle_dict['filter']}\' " f"-PfilterSizeX=\'{speckle_dict['filter_x_size']}\' " f"-PfilterSizeY=\'{speckle_dict['filter_y_size']}\' " f"-PnumLooksStr=\'{speckle_dict['num_of_looks']}\' " f"-PsigmaStr=\'{speckle_dict['sigma']}\' " f"-PtargetWindowSizeStr=\"{speckle_dict['target_window_size']}\" " f"-PwindowSize=\"{speckle_dict['window_size']}\" " f"-t \'{out_stack}\' \'{in_stack}\' ") return_code = h.run_command(command, logfile) if return_code == 0: logger.debug('Successfully applied multi-temporal speckle filtering') else: raise GPTRuntimeError( f'Multi-temporal Spackle Filter exited with error {return_code}. ' f'See {logfile} for Snap\'s error message.') # do check routine return_code = h.check_out_dimap(out_stack) if return_code == 0: return str(out_stack.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}')
def grd_subset_georegion(infile, outfile, logfile, config_dict): """Wrapper function around SNAP's subset routine This function takes an OST imported/slice assembled frame and subsets it according to the coordinates given in the region :param infile: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters cpus = config_dict['snap_cpu_parallelism'] try: aoi = config_dict['aoi'] except KeyError: aoi = '' logger.debug('Subsetting imported imagery.') # extract window from scene command = (f'{GPT_FILE} Subset -x -q {2*cpus} ' f'-PcopyMetadata=true ' f'-PgeoRegion=\'{aoi}\' ' f'-Ssource=\'{str(infile)}\' ' f'-t \'{str(outfile)}\'') # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: logger.debug('Succesfully subsetted product.') else: raise GPTRuntimeError(f'Subsetting exited with error {return_code}. ' f'See {logfile} for Snap\'s error message.') # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}')
def _grd_frame_import(infile, outfile, logfile, polar='VV,VH,HH,HV'): '''A wrapper of SNAP import of a single Sentinel-1 GRD product This function takes an original Sentinel-1 scene (either zip or SAFE format), updates the orbit information (does not fail if not available), removes the thermal noise and stores it as a SNAP compatible BEAM-Dimap format. Args: infile: string or os.path object for an original Sentinel-1 GRD product in zip or SAFE format outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to polar (str): a string consisiting of the polarisation (comma separated) e.g. 'VV,VH', default value: 'VV,VH,HH,HV' ''' print(' INFO: Importing {} by applying precise orbit file and' ' removing thermal noise'.format(os.path.basename(infile))) # get path to SNAP's command line executable gpt gpt_file = h.gpt_path() # get path to ost package root_path = imp.find_module('ost')[1] graph = opj(root_path, 'graphs', 'S1_GRD2ARD', '1_AO_TNR.xml') # construct command command = '{} {} -x -q {} -Pinput=\'{}\' -Ppolar={} \ -Poutput=\'{}\''.format(gpt_file, graph, os.cpu_count(), infile, polar, outfile) # run command return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: print(' INFO: Succesfully imported product') else: print(' ERROR: Frame import exited with an error. \ See {} for Snap Error output'.format(logfile)) sys.exit(102)
def _ls_mask(infile, outfile, logfile, resolution, dem='SRTM 1sec HGT'): '''A wrapper around SNAP's Layover/Shadow mask routine This function takes OST imported Sentinel-1 product and calculates the Layover/Shadow mask. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to resolution (int): the resolution of the output product in meters dem (str): A Snap compliant string for the dem to use. Possible choices are: 'SRTM 1sec HGT' (default) 'SRTM 3sec' 'ASTER 1sec GDEM' 'ACE30' ''' # get gpt file gpt_file = h.gpt_path() # get path to graph rootpath = imp.find_module('ost')[1] graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_LS_TC.xml') print(" INFO: Compute Layover/Shadow mask") command = '{} {} -x -q {} -Pinput={} -Presol={} -Poutput={} -Pdem=\'{}\'' \ .format(gpt_file, graph, 2 * os.cpu_count(), infile, resolution, outfile, dem) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully created Layover/Shadow mask') else: print(' ERROR: Layover/Shadow mask creation exited with an error. \ See {} for Snap Error output'.format(logfile)) # sys.exit(121) return return_code
def _coreg2(master, slave, outfile, logfile, dem='SRTM 1sec HGT'): '''A wrapper around SNAP's back-geocoding co-registration routine This function takes a list of 2 OST imported Sentinel-1 SLC products and co-registers them properly. This routine is sufficient for coherence estimation, but not for InSAR, since the ESD refinement is not applied. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to dem (str): A Snap compliant string for the dem to use. Possible choices are: 'SRTM 1sec HGT' (default) 'SRTM 3sec' 'ASTER 1sec GDEM' 'ACE30' ''' # get gpt file gpt_file = h.gpt_path() # get path to graph rootpath = imp.find_module('ost')[1] graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Coreg.xml') print(' INFO: Co-registering {} and {}'.format(master, slave)) command = '{} {} -x -q {} -Pmaster={} -Pslave={} -Poutput={} -Pdem=\'{}\''\ .format(gpt_file, graph, 2 * os.cpu_count(), master, slave, outfile, dem) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully coregistered product') else: print(' ERROR: Co-registration exited with an error. \ See {} for Snap Error output'.format(logfile)) # sys.exit(112) return return_code
def _ha_alpha(infile, outfile, logfile, pol_speckle_filter=False): '''A wrapper of SNAP H-A-alpha polarimetric decomposition This function takes an OST imported Sentinel-1 scene/burst and calulates the polarimetric decomposition parameters for the H-A-alpha decomposition. Args: infile: string or os.path object for an original Sentinel-1 GRD product in zip or SAFE format out_prefix: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to pol_speckle_filter (bool): wether or not to apply the polarimetric speckle filter ''' # get gpt file gpt_file = h.gpt_path() # get path to graph rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] if pol_speckle_filter: graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Deb_Spk_Halpha.xml') else: graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Deb_Halpha.xml') print(" INFO: Calculating the H-alpha dual polarisation") command = '{} {} -x -q {} -Pinput={} -Poutput={}' \ .format(gpt_file, graph, 2 * os.cpu_count(), infile, outfile) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully created H/Alpha product') else: print(' ERROR: H/Alpha exited with an error. \ See {} for Snap Error output'.format(logfile)) # sys.exit(121) return return_code
def _terrain_flattening(infile, outfile, logfile, dem_dict): '''A wrapper around SNAP's terrain flattening This function takes OST calibrated Sentinel-1 SLC product and applies the terrain flattening to correct for radiometric distortions along slopes Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to ''' # get gpt file gpt_file = h.gpt_path() print(' INFO: Correcting for the illumination along slopes' ' (Terrain Flattening).') command = ('{} Terrain-Flattening -x -q {} ' ' -PadditionalOverlap=0.15' ' -PoversamplingMultiple=1.5' ' -PdemName=\'{}\'' ' -PexternalDEMFile=\'{}\'' ' -PexternalDEMNoDataValue=\'{}\'' ' -PdemResamplingMethod=\'{}\'' ' -t {} {}'.format(gpt_file, 2 * os.cpu_count(), dem_dict['dem name'], dem_dict['dem file'], dem_dict['dem nodata'], dem_dict['dem resampling'], outfile, infile)) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully applied the terrain flattening.') else: print(' ERROR: Terrain Flattening exited with an error.' ' See {} for Snap Error output'.format(logfile)) return return_code
def _coherence(infile, outfile, logfile, polar='VV,VH,HH,HV', ncores=os.cpu_count()): '''A wrapper around SNAP's coherence routine This function takes a co-registered stack of 2 Sentinel-1 SLC products and calculates the coherence. Args: infile: string or os.path object for an OST imported frame in BEAM-Dimap format (i.e. *.dim) outfile: string or os.path object for the output file written in BEAM-Dimap format logfile: string or os.path object for the file where SNAP'S STDOUT/STDERR is written to ncores(int): the number of cpu cores to allocate to the gpt job - defaults to cpu count ''' # get gpt file gpt_file = h.gpt_path() # get path to graph rootpath = importlib.util.find_spec('ost').submodule_search_locations[0] graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Coh_Deb.xml') print(' INFO: Coherence estimation') command = '{} {} -x -q {} -Pinput={} -Ppolar=\'{}\' -Poutput={}' \ .format(gpt_file, graph, ncores, infile, polar, outfile) return_code = h.run_command(command, logfile) if return_code == 0: print(' INFO: Succesfully created coherence product.') else: print(' ERROR: Coherence exited with an error. \ See {} for Snap Error output'.format(logfile)) return return_code
def terrain_flattening(infile, outfile, logfile, config_dict): """Wrapper function to Snap's Terrain Flattening routine :param infile: :param outfile: :param logfile: :param config_dict: :return: """ # get relevant config parameters cpus = config_dict['snap_cpu_parallelism'] dem_dict = config_dict['processing']['single_ARD']['dem'] logger.debug('Applying terrain flattening to calibrated product.') command = (f"{GPT_FILE} Terrain-Flattening -x -q {2*cpus} " f"-PdemName=\'{dem_dict['dem_name']}\' " f"-PdemResamplingMethod=\'{dem_dict['dem_resampling']}\' " f"-PexternalDEMFile=\'{dem_dict['dem_file']}\' " f"-PexternalDEMNoDataValue={dem_dict['dem_nodata']} " f"-t \'{str(outfile)}\' \'{str(infile)}\'") # run command and get return code return_code = h.run_command(command, logfile) # handle errors and logs if return_code == 0: logger.debug('Succesfully terrain flattened product') else: raise GPTRuntimeError( f'Terrain Flattening exited with error {return_code}. ' f'See {logfile} for Snap\'s error message.') # do check routine return_code = h.check_out_dimap(outfile) if return_code == 0: return str(outfile.with_suffix('.dim')) else: raise NotValidFileError( f'Product did not pass file check: {return_code}')