def get_temporal_coherence_mask(inps, template): """Generate mask from temporal coherence""" configKeys = ['pysar.networkInversion.minTempCoh'] inps.maskFile = 'maskTempCoh.h5' inps.minTempCoh = template['pysar.networkInversion.minTempCoh'] maskCmd = 'generate_mask.py {} -m {} -o {} --shadow {}'.format( inps.tempCohFile, inps.minTempCoh, inps.maskFile, inps.geomFile) print(maskCmd) # update mode checking # run if 1) output file exists; 2) newer than input file and 3) all config keys are the same run = False if ut.run_or_skip(out_file=inps.maskFile, in_file=inps.tempCohFile, print_msg=False) == 'run': run = True else: print( ' 1) output file: {} already exists and newer than input file: {}' .format(inps.maskFile, inps.tempCohFile)) meta_dict = readfile.read_attribute(inps.maskFile) if any( str(template[i]) != meta_dict.get(i, 'False') for i in configKeys): run = True print( ' 2) NOT all key configration parameters are the same --> run.\n\t{}' .format(configKeys)) else: print(' 2) all key configuration parameters are the same:\n\t{}'. format(configKeys)) # result print('run this step:', run) if run: status = subprocess.Popen(maskCmd, shell=True).wait() if status is not 0: raise Exception( 'Error while generating mask file from temporal coherence.') # update configKeys meta_dict = {} for key in configKeys: meta_dict[key] = template[key] ut.add_attribute(inps.maskFile, meta_dict) # check number of pixels selected in mask file for following analysis min_num_pixel = float(template['pysar.networkInversion.minNumPixel']) msk = readfile.read(inps.maskFile)[0] num_pixel = np.sum(msk != 0.) print('number of pixels selected: {}'.format(num_pixel)) if num_pixel < min_num_pixel: msg = "Not enought coherent pixels selected (minimum of {}). ".format( int(min_num_pixel)) msg += "Try the following:\n" msg += "1) Check the reference pixel and make sure it's not in areas with unwrapping errors\n" msg += "2) Check the network and make sure it's fully connected without subsets" raise RuntimeError(msg) del msk return
def run_geocode(inps): """geocode all input files""" start_time = time.time() # Prepare geometry for geocoding res_obj = resample(lookupFile=inps.lookupFile, dataFile=inps.file[0], SNWE=inps.SNWE, laloStep=inps.laloStep, processor=inps.processor) res_obj.open() if not inps.nprocs: inps.nprocs = multiprocessing.cpu_count() # resample input files one by one for infile in inps.file: print('-' * 50+'\nresampling file: {}'.format(infile)) atr = readfile.read_attribute(infile, datasetName=inps.dset) outfile = auto_output_filename(infile, inps) if inps.updateMode and ut.run_or_skip(outfile, in_file=[infile, inps.lookupFile]) == 'skip': print('update mode is ON, skip geocoding.') continue # read source data and resample dsNames = readfile.get_dataset_list(infile, datasetName=inps.dset) maxDigit = max([len(i) for i in dsNames]) dsResDict = dict() for dsName in dsNames: print('reading {d:<{w}} from {f} ...'.format(d=dsName, w=maxDigit, f=os.path.basename(infile))) data = readfile.read(infile, datasetName=dsName, print_msg=False)[0] if atr['FILE_TYPE'] == 'timeseries' and len(data.shape) == 2: data = np.reshape(data, (1, data.shape[0], data.shape[1])) res_data = res_obj.run_resample(src_data=data, interp_method=inps.interpMethod, fill_value=inps.fillValue, nprocs=inps.nprocs, print_msg=True) dsResDict[dsName] = res_data # update metadata if inps.radar2geo: atr = metadata_radar2geo(atr, res_obj) else: atr = metadata_geo2radar(atr, res_obj) #if len(dsNames) == 1 and dsName not in ['timeseries']: # atr['FILE_TYPE'] = dsNames[0] # infile = None writefile.write(dsResDict, out_file=outfile, metadata=atr, ref_file=infile) m, s = divmod(time.time()-start_time, 60) print('time used: {:02.0f} mins {:02.1f} secs.\n'.format(m, s)) return outfile
def run_load_data(self, step_name): """Load InSAR stacks into HDF5 files in ./INPUTS folder. It 1) copy auxiliary files into work directory (for Unvi of Miami only) 2) load all interferograms stack files into PYSAR/INPUTS directory. 3) check loading result 4) add custom metadata (optional, for HDF-EOS5 format only) """ # 1) copy aux files (optional) self._copy_aux_file() # 2) loading data scp_args = '--template {}'.format(self.templateFile) if self.customTemplateFile: scp_args += ' {}'.format(self.customTemplateFile) if self.projectName: scp_args += ' --project {}'.format(self.projectName) # run print("load_data.py", scp_args) pysar.load_data.main(scp_args.split()) os.chdir(self.workDir) # 3) check loading result load_complete, stack_file, geom_file = ut.check_loaded_dataset(self.workDir, print_msg=True)[0:3] # 3.1) output waterMask.h5 water_mask_file = 'waterMask.h5' if 'waterMask' in readfile.get_dataset_list(geom_file): print('generate {} from {} for conveniency'.format(water_mask_file, geom_file)) if ut.run_or_skip(out_file=water_mask_file, in_file=geom_file) == 'run': water_mask, atr = readfile.read(geom_file, datasetName='waterMask') atr['FILE_TYPE'] = 'waterMask' writefile.write(water_mask, out_file=water_mask_file, metadata=atr) # 4) add custom metadata (optional) if self.customTemplateFile: print('updating {}, {} metadata based on custom template file: {}'.format( os.path.basename(stack_file), os.path.basename(geom_file), os.path.basename(self.customTemplateFile))) # use ut.add_attribute() instead of add_attribute.py because of # better control of special metadata, such as SUBSET_X/YMIN ut.add_attribute(stack_file, self.customTemplate) ut.add_attribute(geom_file, self.customTemplate) # 5) if not load_complete, plot and raise exception if not load_complete: # plot result if error occured self.plot_result(print_aux=False, plot=plot) # go back to original directory print('Go back to directory:', self.cwd) os.chdir(self.cwd) # raise error msg = 'step {}: NOT all required dataset found, exit.'.format(step_name) raise RuntimeError(msg) return
def analyze_rms(date_list, rms_list, inps): # reference date ref_idx = np.argmin(rms_list) print('-' * 50 + '\ndate with min RMS: {} - {:.4f}'.format( date_list[ref_idx], rms_list[ref_idx])) ref_date_file = 'reference_date.txt' if ut.run_or_skip( out_file=ref_date_file, in_file=[inps.timeseries_file, inps.mask_file, inps.template_file], check_readable=False) == 'run': with open(ref_date_file, 'w') as f: f.write(date_list[ref_idx] + '\n') print('save date to file: ' + ref_date_file) # exclude date(s) - outliers try: rms_threshold = ut.median_abs_deviation_threshold(rms_list, center=0., cutoff=inps.cutoff) except: # equivalent calculation using numpy assuming Gaussian distribution rms_threshold = np.median(rms_list) / .6745 * inps.cutoff ex_idx = [rms_list.index(i) for i in rms_list if i > rms_threshold] print(('-' * 50 + '\ndate(s) with RMS > {} * median RMS' ' ({:.4f})'.format(inps.cutoff, rms_threshold))) ex_date_file = 'exclude_date.txt' if ex_idx: # print for i in ex_idx: print('{} - {:.4f}'.format(date_list[i], rms_list[i])) # save to text file with open(ex_date_file, 'w') as f: for i in ex_idx: f.write(date_list[i] + '\n') print('save date(s) to file: ' + ex_date_file) else: print('None.') if os.path.isfile(ex_date_file): rmCmd = 'rm {}'.format(ex_date_file) print(rmCmd) os.system(rmCmd) # plot bar figure and save fig_file = os.path.splitext(inps.rms_file)[0] + '.pdf' fig, ax = plt.subplots(figsize=inps.fig_size) print('create figure in size:', inps.fig_size) ax = plot_rms_bar(ax, date_list, np.array(rms_list) * 1000., cutoff=inps.cutoff) fig.savefig(fig_file, bbox_inches='tight', transparent=True) print('save figure to file: ' + fig_file) return inps
def generate_temporal_coherence_mask(self): """Generate reliable pixel mask from temporal coherence""" geom_file = ut.check_loaded_dataset(self.workDir, print_msg=False)[2] tcoh_file = 'temporalCoherence.h5' mask_file = 'maskTempCoh.h5' tcoh_min = self.template['pysar.networkInversion.minTempCoh'] scp_args = '{} -m {} -o {} --shadow {}'.format(tcoh_file, tcoh_min, mask_file, geom_file) print('generate_mask.py', scp_args) # update mode: run only if: # 1) output file exists and newer than input file, AND # 2) all config keys are the same config_keys = ['pysar.networkInversion.minTempCoh'] print('update mode: ON') flag = 'skip' if ut.run_or_skip(out_file=mask_file, in_file=tcoh_file, print_msg=False) == 'run': flag = 'run' else: print('1) output file: {} already exists and newer than input file: {}'.format(mask_file, tcoh_file)) atr = readfile.read_attribute(mask_file) if any(str(self.template[i]) != atr.get(i, 'False') for i in config_keys): flag = 'run' print('2) NOT all key configration parameters are the same: {}'.format(config_keys)) else: print('2) all key configuration parameters are the same: {}'.format(config_keys)) print('run or skip: {}'.format(flag)) if flag == 'run': pysar.generate_mask.main(scp_args.split()) # update configKeys atr = {} for key in config_keys: atr[key] = self.template[key] ut.add_attribute(mask_file, atr) # check number of pixels selected in mask file for following analysis num_pixel = np.sum(readfile.read(mask_file)[0] != 0.) print('number of reliable pixels: {}'.format(num_pixel)) min_num_pixel = float(self.template['pysar.networkInversion.minNumPixel']) if num_pixel < min_num_pixel: msg = "Not enough reliable pixels (minimum of {}). ".format(int(min_num_pixel)) msg += "Try the following:\n" msg += "1) Check the reference pixel and make sure it's not in areas with unwrapping errors\n" msg += "2) Check the network and make sure it's fully connected without subsets" raise RuntimeError(msg) return
def create_custom_template(custom_template_file, work_dir): """ Creates or restores custom template file. """ if custom_template_file: # Copy custom template file to work directory if utils.run_or_skip(os.path.basename(custom_template_file), custom_template_file, check_readable=False) == 'run': shutil.copy2(custom_template_file, work_dir) # Read custom template logger.log( loglevel.INFO, 'read custom template file: {}'.format(custom_template_file)) return readfile.read_template(custom_template_file) else: return dict()
def run_save2hdfeos5(self, step_name): """Save displacement time-series and its aux data in geo coordinate into HDF-EOS5 format""" if self.template['pysar.save.hdfEos5'] is True: # input ts_file = self.get_timeseries_filename( self.template)[step_name]['input'] # Add attributes from custom template to timeseries file if self.customTemplate is not None: ut.add_attribute(ts_file, self.customTemplate) tcoh_file = 'temporalCoherence.h5' mask_file = 'geo_maskTempCoh.h5' geom_file = ut.check_loaded_dataset(self.workDir, print_msg=False)[2] if 'GEOCODE' in ts_file: tcoh_file = './GEOCODE/geo_temporalCoherence.h5' mask_file = './GEOCODE/geo_maskTempCoh.h5' geom_file = './GEOCODE/geo_{}'.format( os.path.basename(geom_file)) # cmd print('--------------------------------------------') scp_args = '{f} -c {c} -m {m} -g {g} -t {t}'.format( f=ts_file, c=tcoh_file, m=mask_file, g=geom_file, t=self.templateFile) print('save_hdfeos5.py', scp_args) # output (check existing file) atr = readfile.read_attribute(ts_file) SAT = sensor.get_unavco_mission_name(atr) try: hdfeos5_file = get_file_list('{}_*.he5'.format(SAT))[0] except: hdfeos5_file = None if ut.run_or_skip( out_file=hdfeos5_file, in_file=[ts_file, tcoh_file, mask_file, geom_file]) == 'run': pysar.save_hdfeos5.main(scp_args.split()) else: print('save time-series to HDF-EOS5 format is OFF.') return
def extract_isce_metadata(meta_file, geom_dir=None, rsc_file=None, update_mode=True): """Extract metadata from ISCE stack products Parameters: meta_file : str, path of metadata file, master/IW1.xml or masterShelve/data.dat geom_dir : str, path of geometry directory. rsc_file : str, output file name of ROIPAC format rsc file Returns: metadata : dict """ if not rsc_file: rsc_file = os.path.join(os.path.dirname(meta_file), 'data.rsc') # check existing rsc_file if update_mode and ut.run_or_skip(rsc_file, in_file=meta_file, check_readable=False) == 'skip': return readfile.read_roipac_rsc(rsc_file) # 1. extract metadata from XML / shelve file fbase = os.path.basename(meta_file) if fbase.startswith("IW"): print('extract metadata from ISCE/topsStack xml file:', meta_file) metadata = extract_tops_metadata(meta_file) elif fbase.startswith("data"): print('extract metadata from ISCE/stripmapStack shelve file:', meta_file) metadata = extract_stripmap_metadata(meta_file) elif fbase.endswith(".xml"): metadata = extract_stripmap_metadata(meta_file) else: raise ValueError("unrecognized ISCE metadata file: {}".format(meta_file)) # 2. extract metadata from geometry file if geom_dir: metadata = extract_geometry_metadata(geom_dir, metadata) # 3. common metadata metadata['PROCESSOR'] = 'isce' metadata['ANTENNA_SIDE'] = '-1' # convert all value to string format for key, value in metadata.items(): metadata[key] = str(value) # write to .rsc file metadata = readfile.standardize_metadata(metadata) if rsc_file: print('writing ', rsc_file) writefile.write_roipac_rsc(metadata, rsc_file) return metadata
def copy_aux_file(inps): # for Univ of Miami fileList = ['PROCESS/unavco_attributes.txt', 'PROCESS/bl_list.txt', 'SLC/summary*slc.jpg'] try: projectDir = os.path.join(os.getenv('SCRATCHDIR'), inps.projectName) fileList = ut.get_file_list([os.path.join(projectDir, i) for i in fileList], abspath=True) for file in fileList: if ut.run_or_skip(out_file=os.path.basename(file), in_file=file, check_readable=False) == 'run': shutil.copy2(file, inps.workDir) print('copy {} to work directory'.format(os.path.basename(file))) except: pass return inps
def run_local_oscillator_drift_correction(self, step_name): """Correct local oscillator drift (LOD). Automatically applied for Envisat data. Automatically skipped for all the other data. """ geom_file = ut.check_loaded_dataset(self.workDir, print_msg=False)[2] fnames = self.get_timeseries_filename(self.template)[step_name] in_file = fnames['input'] out_file = fnames['output'] if in_file != out_file: scp_args = '{} {} -o {}'.format(in_file, geom_file, out_file) print('local_oscilator_drift.py', scp_args) if ut.run_or_skip(out_file=out_file, in_file=in_file) == 'run': pysar.local_oscilator_drift.main(scp_args.split()) else: atr = readfile.read_attribute(in_file) sat = atr.get('PLATFORM', None) print('No local oscillator drift correction is needed for {}.'.format(sat)) return
def run_geocode(self, step_name): """geocode data files in radar coordinates into ./GEOCODE folder.""" if self.template['pysar.geocode']: ts_file = self.get_timeseries_filename( self.template)[step_name]['input'] atr = readfile.read_attribute(ts_file) if 'Y_FIRST' not in atr.keys(): # 1. geocode out_dir = os.path.join(self.workDir, 'GEOCODE') if not os.path.isdir(out_dir): os.makedirs(out_dir) print('create directory:', out_dir) geom_file, lookup_file = ut.check_loaded_dataset( self.workDir, print_msg=False)[2:4] in_files = [ geom_file, 'temporalCoherence.h5', ts_file, 'velocity.h5' ] scp_args = '-l {l} -t {t} --outdir {o} --update '.format( l=lookup_file, t=self.templateFile, o=out_dir) for in_file in in_files: scp_args += ' {}'.format(in_file) print('geocode.py', scp_args) pysar.geocode.main(scp_args.split()) # 2. generate reliable pixel mask in geo coordinate geom_file = os.path.join( out_dir, 'geo_{}'.format(os.path.basename(geom_file))) tcoh_file = os.path.join(out_dir, 'geo_temporalCoherence.h5') mask_file = os.path.join(out_dir, 'geo_maskTempCoh.h5') tcoh_min = self.template['pysar.networkInversion.minTempCoh'] scp_args = '{} -m {} -o {} --shadow {}'.format( tcoh_file, tcoh_min, mask_file, geom_file) print('generate_mask.py', scp_args) if ut.run_or_skip(out_file=mask_file, in_file=tcoh_file) == 'run': pysar.generate_mask.main(scp_args.split()) else: print('geocoding is OFF') return
def main(iargs=None): inps = cmd_line_parse(iargs) baselineDict = {} if inps.baselineDir: baselineDict = baseline_timeseries(inps.baselineDir) metadata = {} if inps.xmlFile: rscFile = os.path.join(os.path.dirname(inps.xmlFile), 'data.rsc') if ut.run_or_skip(rscFile, in_file=inps.xmlFile, check_readable=False) == 'run': metadata = extract_isce_metadata(inps.xmlFile, rscFile) else: metadata = readfile.read_roipac_rsc(rscFile) if inps.geometryDir: metadata = prepare_geometry(inps.geometryDir, metadata) if inps.ifgramDir and inps.ifgramFiles: for namePattern in inps.ifgramFiles: prepare_stack(inps.ifgramDir, namePattern, metadata, baselineDict) print('Done.') return
def run_save2google_earth(self, step_name): """Save velocity file in geo coordinates into Google Earth raster image.""" if self.template['pysar.save.kmz'] is True: print( 'creating Google Earth KMZ file for geocoded velocity file: ...' ) # input vel_file = 'velocity.h5' atr = readfile.read_attribute(vel_file) if 'Y_FIRST' not in atr.keys(): vel_file = os.path.join(self.workDir, 'GEOCODE/geo_velocity.h5') # output kmz_file = '{}.kmz'.format(os.path.splitext(vel_file)[0]) scp_args = '{} -o {}'.format(vel_file, kmz_file) print('save_kmz.py', scp_args) # update mode try: fbase = os.path.basename(kmz_file) kmz_file = [ i for i in [ fbase, './GEOCODE/{}'.format(fbase), './PIC/{}'.format( fbase) ] if os.path.isfile(i) ][0] except: kmz_file = None if ut.run_or_skip(out_file=kmz_file, in_file=vel_file, check_readable=False) == 'run': pysar.save_kmz.main(scp_args.split()) else: print('save velocity to Google Earth format is OFF.') return
def get_delay_timeseries(inps, atr): """Calculate delay time-series and write it to HDF5 file. Parameters: inps : namespace, all input parameters atr : dict, metadata to be saved in trop_file Returns: trop_file : str, file name of ECMWF.h5 """ def get_dataset_size(fname): atr = readfile.read_attribute(fname) return (atr['LENGTH'], atr['WIDTH']) if (ut.run_or_skip(out_file=inps.trop_file, in_file=inps.grib_file_list, print_msg=False) == 'skip' and get_dataset_size(inps.trop_file) == get_dataset_size( inps.geom_file)): print( '{} file exists and is newer than all GRIB files, skip updating.'. format(inps.trop_file)) else: if any(i is None for i in [inps.geom_file, inps.ref_yx]): print( 'No DEM / incidenceAngle / ref_yx found, skip calculating tropospheric delays.' ) if not os.path.isfile(inps.trop_file): inps.trop_file = None return # calculate phase delay length, width = int(atr['LENGTH']), int(atr['WIDTH']) num_date = len(inps.grib_file_list) date_list = [ str(re.findall('\d{8}', i)[0]) for i in inps.grib_file_list ] trop_data = np.zeros((num_date, length, width), np.float32) print( 'calcualting delay for each date using PyAPS (Jolivet et al., 2011; 2014) ...' ) print('number of grib files used: {}'.format(num_date)) prog_bar = ptime.progressBar(maxValue=num_date) for i in range(num_date): grib_file = inps.grib_file_list[i] trop_data[i] = get_delay(grib_file, inps) prog_bar.update(i + 1, suffix=os.path.basename(grib_file)) prog_bar.close() # Convert relative phase delay on reference date try: inps.ref_date = atr['REF_DATE'] except: inps.ref_date = date_list[0] print('convert to relative phase delay with reference date: ' + inps.ref_date) inps.ref_idx = date_list.index(inps.ref_date) trop_data -= np.tile(trop_data[inps.ref_idx, :, :], (num_date, 1, 1)) # Write tropospheric delay to HDF5 atr['REF_Y'] = inps.ref_yx[0] atr['REF_X'] = inps.ref_yx[1] ts_obj = timeseries(inps.trop_file) ts_obj.write2hdf5(data=trop_data, dates=date_list, metadata=atr, refFile=inps.timeseries_file) # Delete temporary DEM file in ROI_PAC format if inps.geom_file: temp_files = [ fname for fname in [inps.dem_file, inps.inc_angle_file, inps.lat_file, inps.lon_file] if (fname is not None and 'pyaps' in fname) ] if temp_files: print('delete temporary geometry files') rmCmd = 'rm ' for fname in temp_files: rmCmd += ' {f} {f}.rsc '.format(f=fname) print(rmCmd) os.system(rmCmd) return
def main(iargs=None): start_time = time.time() inps = cmd_line_parse(iargs) if inps.version: raise SystemExit(version.version_description) ######################################### # Initiation ######################################### print(version.logo) # Project Name inps.projectName = None if inps.customTemplateFile: inps.customTemplateFile = os.path.abspath(inps.customTemplateFile) inps.projectName = os.path.splitext(os.path.basename(inps.customTemplateFile))[0] print('Project name:', inps.projectName) # Work directory if not inps.workDir: if autoPath and 'SCRATCHDIR' in os.environ and inps.projectName: inps.workDir = os.path.join(os.getenv('SCRATCHDIR'), inps.projectName, 'PYSAR') else: inps.workDir = os.getcwd() inps.workDir = os.path.abspath(inps.workDir) if not os.path.isdir(inps.workDir): os.makedirs(inps.workDir) os.chdir(inps.workDir) print("Go to work directory:", inps.workDir) copy_aux_file(inps) inps, template, customTemplate = read_template(inps) ######################################### # Loading Data ######################################### print('\n********** Load Data **********') loadCmd = 'load_data.py --template {}'.format(inps.templateFile) if inps.customTemplateFile: loadCmd += ' {}'.format(inps.customTemplateFile) if inps.projectName: loadCmd += ' --project {}'.format(inps.projectName) print(loadCmd) status = subprocess.Popen(loadCmd, shell=True).wait() os.chdir(inps.workDir) print('-'*50) inps, atr = ut.check_loaded_dataset(inps.workDir, inps) # Add template options into HDF5 file metadata if inps.customTemplateFile: #metaCmd = 'add_attribute.py {} {}'.format(inps.stackFile, inps.customTemplateFile) #print(metaCmd) #status = subprocess.Popen(metaCmd, shell=True).wait() # better control of special metadata, such as SUBSET_X/YMIN print('updating {} metadata based on custom template file: {}'.format( os.path.basename(inps.stackFile), inps.customTemplateFile)) ut.add_attribute(inps.stackFile, customTemplate) if inps.load_dataset: raise SystemExit('Exit as planned after loading/checking the dataset.') if inps.reset: print('Reset dataset attributtes for a fresh re-run.\n'+'-'*50) # Reset reference pixel refPointCmd = 'reference_point.py {} --reset'.format(inps.stackFile) print(refPointCmd) status = subprocess.Popen(refPointCmd, shell=True).wait() # Reset network modification networkCmd = 'modify_network.py {} --reset'.format(inps.stackFile) print(networkCmd) status = subprocess.Popen(networkCmd, shell=True).wait() ######################################### # Generating Aux files ######################################### print('\n********** Generate Auxiliary Files **********') inps.waterMaskFile = 'waterMask.h5' if not os.path.isfile(inps.waterMaskFile): inps.waterMaskFile = None # Initial mask (pixels with valid unwrapPhase or connectComponent in ALL interferograms) inps.maskFile = 'mask.h5' maskCmd = 'generate_mask.py {} --nonzero -o {} --update'.format(inps.stackFile, inps.maskFile) print(maskCmd) status = subprocess.Popen(maskCmd, shell=True).wait() # Average phase velocity - Stacking inps.avgPhaseVelFile = 'avgPhaseVelocity.h5' avgCmd = 'temporal_average.py {i} --dataset unwrapPhase -o {o} --update'.format(i=inps.stackFile, o=inps.avgPhaseVelFile) print(avgCmd) status = subprocess.Popen(avgCmd, shell=True).wait() # Average spatial coherence inps.avgSpatialCohFile = 'avgSpatialCoherence.h5' avgCmd = 'temporal_average.py {i} --dataset coherence -o {o} --update'.format(i=inps.stackFile, o=inps.avgSpatialCohFile) print(avgCmd) status = subprocess.Popen(avgCmd, shell=True).wait() # mask based on average spatial coherence inps.maskSpatialCohFile = 'maskSpatialCoh.h5' if ut.run_or_skip(out_file=inps.maskSpatialCohFile, in_file=inps.avgSpatialCohFile) == 'run': maskCmd = 'generate_mask.py {i} -m 0.7 -o {o}'.format(i=inps.avgSpatialCohFile, o=inps.maskSpatialCohFile) if inps.waterMaskFile: maskCmd += ' --base {}'.format(inps.waterMaskFile) print(maskCmd) status = subprocess.Popen(maskCmd, shell=True).wait() ######################################### # Referencing Interferograms in Space ######################################### print('\n********** Select Reference Point **********') refPointCmd = 'reference_point.py {} -t {} -c {}'.format(inps.stackFile, inps.templateFile, inps.avgSpatialCohFile) print(refPointCmd) status = subprocess.Popen(refPointCmd, shell=True).wait() if status is not 0: raise Exception('Error while finding reference pixel in space.\n') ############################################ # Unwrapping Error Correction (Optional) # based on the consistency of triplets # of interferograms ############################################ correct_unwrap_error(inps, template) ######################################### # Network Modification (Optional) ######################################### print('\n********** Modify Network **********') networkCmd = 'modify_network.py {} -t {}'.format(inps.stackFile, inps.templateFile) print(networkCmd) status = subprocess.Popen(networkCmd, shell=True).wait() if status is not 0: raise Exception('Error while modifying the network of interferograms.\n') # Plot network colored in spatial coherence print('--------------------------------------------------') plotCmd = 'plot_network.py {} --template {} --nodisplay'.format(inps.stackFile, inps.templateFile) print(plotCmd) inps.cohSpatialAvgFile = '{}_coherence_spatialAverage.txt'.format( os.path.splitext(os.path.basename(inps.stackFile))[0]) try: outFile = [i for i in ['Network.pdf', 'PIC/Network.pdf'] if os.path.isfile(i)][0] except: outFile = None if ut.run_or_skip(out_file=outFile, in_file=[inps.stackFile, inps.cohSpatialAvgFile, inps.templateFile], check_readable=False) == 'run': status = subprocess.Popen(plotCmd, shell=True).wait() if inps.modify_network: raise SystemExit('Exit as planned after network modification.') ######################################### # Inversion of Interferograms ######################################## print('\n********** Invert Network of Interferograms into Time-series **********') invCmd = 'ifgram_inversion.py {} --template {} --update '.format(inps.stackFile, inps.templateFile) if inps.fast: invCmd += ' --fast' if inps.waterMaskFile: invCmd += ' -m {}'.format(inps.waterMaskFile) print(invCmd) inps.timeseriesFile = 'timeseries.h5' inps.tempCohFile = 'temporalCoherence.h5' inps.timeseriesFiles = ['timeseries.h5'] #all ts files status = subprocess.Popen(invCmd, shell=True).wait() if status is not 0: raise Exception('Error while inverting network interferograms into timeseries') print('\n--------------------------------------------') print('Update Mask based on Temporal Coherence ...') get_temporal_coherence_mask(inps, template) if inps.invert_network: raise SystemExit('Exit as planned after network inversion.') ############################################## # LOD (Local Oscillator Drift) Correction # for Envisat data in radar coord only ############################################## if atr['PLATFORM'].lower().startswith('env'): print('\n********** Local Oscillator Drift Correction for Envisat **********') outName = os.path.splitext(inps.timeseriesFile)[0]+'_LODcor.h5' lodCmd = 'local_oscilator_drift.py {} {} -o {}'.format(inps.timeseriesFile, inps.geomFile, outName) print(lodCmd) if ut.run_or_skip(out_file=outName, in_file=[inps.timeseriesFile, inps.geomFile]) == 'run': status = subprocess.Popen(lodCmd, shell=True).wait() if status is not 0: raise Exception('Error while correcting Local Oscillator Drift.\n') inps.timeseriesFile = outName inps.timeseriesFiles.append(outName) ############################################## # Tropospheric Delay Correction (Optional) ############################################## print('\n********** Tropospheric Delay Correction **********') correct_tropospheric_delay(inps, template) ############################################## # Phase Ramp Correction (Optional) ############################################## print('\n********** Remove Phase Ramp **********') inps.derampMaskFile = template['pysar.deramp.maskFile'] inps.derampMethod = template['pysar.deramp'] if inps.derampMethod: print('Phase Ramp Removal method: {}'.format(inps.derampMethod)) ramp_list = ['linear', 'quadratic', 'linear_range', 'quadratic_range', 'linear_azimuth', 'quadratic_azimuth'] if inps.derampMethod in ramp_list: outName = '{}_ramp.h5'.format(os.path.splitext(inps.timeseriesFile)[0]) derampCmd = 'remove_ramp.py {} -s {} -m {} -o {}'.format(inps.timeseriesFile, inps.derampMethod, inps.derampMaskFile, outName) print(derampCmd) if ut.run_or_skip(out_file=outName, in_file=inps.timeseriesFile) == 'run': status = subprocess.Popen(derampCmd, shell=True).wait() if status is not 0: raise Exception('Error while removing phase ramp for time-series.\n') inps.timeseriesFile = outName inps.timeseriesFiles.append(outName) else: msg = 'un-recognized phase ramp method: {}'.format(inps.derampMethod) msg += '\navailable ramp types:\n{}'.format(ramp_list) raise ValueError(msg) else: print('No phase ramp removal.') ############################################## # Topographic (DEM) Residuals Correction (Optional) ############################################## print('\n********** Topographic Residual (DEM error) Correction **********') outName = os.path.splitext(inps.timeseriesFile)[0]+'_demErr.h5' topoCmd = 'dem_error.py {i} -t {t} -o {o} --update '.format(i=inps.timeseriesFile, t=inps.templateFile, o=outName) if not inps.fast: topoCmd += ' -g {}'.format(inps.geomFile) print(topoCmd) inps.timeseriesResFile = None if template['pysar.topographicResidual']: status = subprocess.Popen(topoCmd, shell=True).wait() if status is not 0: raise Exception('Error while correcting topographic phase residual.\n') inps.timeseriesFile = outName inps.timeseriesResFile = 'timeseriesResidual.h5' inps.timeseriesFiles.append(outName) else: print('No correction for topographic residuals.') # Timeseries Residual Standard Deviation print('\n********** Timeseries Residual Root Mean Square **********') if inps.timeseriesResFile: rmsCmd = 'timeseries_rms.py {} -t {}'.format(inps.timeseriesResFile, inps.templateFile) print(rmsCmd) status = subprocess.Popen(rmsCmd, shell=True).wait() if status is not 0: raise Exception('Error while calculating RMS of time series phase residual.\n') else: print('No timeseries residual file found! Skip residual RMS analysis.') # Reference in Time print('\n********** Select Reference Date **********') if template['pysar.reference.date']: refCmd = 'reference_date.py -t {} '.format(inps.templateFile) for fname in inps.timeseriesFiles: refCmd += ' {}'.format(fname) print(refCmd) status = subprocess.Popen(refCmd, shell=True).wait() if status is not 0: raise Exception('Error while changing reference date.\n') else: print('No reference change in time.') ############################################# # Velocity and rmse maps ############################################# print('\n********** Estimate Velocity **********') inps.velFile = 'velocity.h5' velCmd = 'timeseries2velocity.py {} -t {} -o {} --update'.format(inps.timeseriesFile, inps.templateFile, inps.velFile) print(velCmd) status = subprocess.Popen(velCmd, shell=True).wait() if status is not 0: raise Exception('Error while estimating linear velocity from time-series.\n') # Velocity from Tropospheric delay if inps.tropFile: suffix = os.path.splitext(os.path.basename(inps.tropFile))[0].title() inps.tropVelFile = '{}{}.h5'.format(os.path.splitext(inps.velFile)[0], suffix) velCmd = 'timeseries2velocity.py {} -t {} -o {} --update'.format(inps.tropFile, inps.templateFile, inps.tropVelFile) print(velCmd) status = subprocess.Popen(velCmd, shell=True).wait() ############################################ # Post-processing # Geocodeing --> Masking --> KMZ & HDF-EOS5 ############################################ print('\n********** Post-processing **********') if template['pysar.save.hdfEos5'] is True and template['pysar.geocode'] is False: print('Turn ON pysar.geocode to be able to save to HDF-EOS5 format.') template['pysar.geocode'] = True # Geocoding if not inps.geocoded: if template['pysar.geocode'] is True: print('\n--------------------------------------------') geo_dir = os.path.abspath('./GEOCODE') if not os.path.isdir(geo_dir): os.makedirs(geo_dir) print('create directory: {}'.format(geo_dir)) geoCmd = ('geocode.py {v} {c} {t} {g} -l {l} -t {e}' ' --outdir {d} --update').format(v=inps.velFile, c=inps.tempCohFile, t=inps.timeseriesFile, g=inps.geomFile, l=inps.lookupFile, e=inps.templateFile, d=geo_dir) print(geoCmd) status = subprocess.Popen(geoCmd, shell=True).wait() if status is not 0: raise Exception('Error while geocoding.\n') else: inps.velFile = os.path.join(geo_dir, 'geo_'+os.path.basename(inps.velFile)) inps.tempCohFile = os.path.join(geo_dir, 'geo_'+os.path.basename(inps.tempCohFile)) inps.timeseriesFile = os.path.join(geo_dir, 'geo_'+os.path.basename(inps.timeseriesFile)) inps.geomFile = os.path.join(geo_dir, 'geo_'+os.path.basename(inps.geomFile)) inps.geocoded = True # generate mask based on geocoded temporal coherence print('\n--------------------------------------------') outName = os.path.join(geo_dir, 'geo_maskTempCoh.h5') genCmd = 'generate_mask.py {} -m {} -o {}'.format(inps.tempCohFile, inps.minTempCoh, outName) print(genCmd) if ut.run_or_skip(out_file=outName, in_file=inps.tempCohFile) == 'run': status = subprocess.Popen(genCmd, shell=True).wait() inps.maskFile = outName # mask velocity file if inps.velFile and inps.maskFile: outName = '{}_masked.h5'.format(os.path.splitext(inps.velFile)[0]) maskCmd = 'mask.py {} -m {} -o {}'.format(inps.velFile, inps.maskFile, outName) print(maskCmd) if ut.run_or_skip(out_file=outName, in_file=[inps.velFile, inps.maskFile]) == 'run': status = subprocess.Popen(maskCmd, shell=True).wait() try: inps.velFile = glob.glob(outName)[0] except: inps.velFile = None # Save to Google Earth KML file if inps.geocoded and inps.velFile and template['pysar.save.kml'] is True: print('\n--------------------------------------------') print('creating Google Earth KMZ file for geocoded velocity file: ...') outName = '{}.kmz'.format(os.path.splitext(os.path.basename(inps.velFile))[0]) kmlCmd = 'save_kml.py {} -o {}'.format(inps.velFile, outName) print(kmlCmd) try: outFile = [i for i in [outName, 'PIC/{}'.format(outName)] if os.path.isfile(i)][0] except: outFile = None if ut.run_or_skip(out_file=outFile, in_file=inps.velFile, check_readable=False) == 'run': status = subprocess.Popen(kmlCmd, shell=True).wait() if status is not 0: raise Exception('Error while generating Google Earth KMZ file.') ############################################# # Save Timeseries to HDF-EOS5 format ############################################# if template['pysar.save.hdfEos5'] is True: print('\n********** Save Time-series in HDF-EOS5 Format **********') save_hdfeos5(inps, customTemplate) ############################################# # Plot Figures ############################################# if template['pysar.plot']: plot_pysarApp(inps) ############################################# # Timing # ############################################# m, s = divmod(time.time()-start_time, 60) print('\n###############################################') print('End of PySAR Routine Processing Workflow!') print('###############################################\n') print('time used: {:02.0f} mins {:02.1f} secs'.format(m, s))
def correct_tropospheric_delay(inps, template): """Correct tropospheric delay with options from template""" inps.tropPolyOrder = template['pysar.troposphericDelay.polyOrder'] inps.tropModel = template['pysar.troposphericDelay.weatherModel'] inps.tropMethod = template['pysar.troposphericDelay.method'] # check existing tropospheric delay file try: fileList = [os.path.join(inps.workDir, 'INPUTS/{}.h5'.format(inps.tropModel))] inps.tropFile = ut.get_file_list(fileList)[0] except: inps.tropFile = None # run if inps.tropMethod: fbase = os.path.splitext(inps.timeseriesFile)[0] # Phase/Elevation Ratio (Doin et al., 2009) if inps.tropMethod == 'height_correlation': outName = '{}_tropHgt.h5'.format(fbase) print('tropospheric delay correction with height-correlation approach') tropCmd = ('tropcor_phase_elevation.py {t} -g {d} -p {p}' ' -m {m} -o {o}').format(t=inps.timeseriesFile, d=inps.geomFile, p=inps.tropPolyOrder, m=inps.maskFile, o=outName) print(tropCmd) if ut.run_or_skip(out_file=outName, in_file=inps.timeseriesFile) == 'run': status = subprocess.Popen(tropCmd, shell=True).wait() if status is not 0: raise Exception('Error while correcting tropospheric delay.\n') inps.timeseriesFile = outName inps.timeseriesFiles.append(outName) # Weather Re-analysis Data (Jolivet et al., 2011;2014) elif inps.tropMethod == 'pyaps': inps.weatherDir = template['pysar.troposphericDelay.weatherDir'] outName = '{}_{}.h5'.format(fbase, inps.tropModel) print(('Atmospheric correction using Weather Re-analysis dataset' ' (PyAPS, Jolivet et al., 2011)')) print('Weather Re-analysis dataset:', inps.tropModel) tropCmd = ('tropcor_pyaps.py -f {t} --model {m} -g {g}' ' -w {w}').format(t=inps.timeseriesFile, m=inps.tropModel, g=inps.geomFile, w=inps.weatherDir) print(tropCmd) if ut.run_or_skip(out_file=outName, in_file=inps.timeseriesFile) == 'run': if inps.tropFile: tropCmd = 'diff.py {} {} -o {} --force'.format(inps.timeseriesFile, inps.tropFile, outName) print('--------------------------------------------') print('Use existed tropospheric delay file: {}'.format(inps.tropFile)) print(tropCmd) status = subprocess.Popen(tropCmd, shell=True).wait() if status is not 0: print('\nError while correcting tropospheric delay, try the following:') print('1) Check the installation of PyAPS') print(' http://earthdef.caltech.edu/projects/pyaps/wiki/Main') print(' Try in command line: python -c "import pyaps"') print('2) Use other tropospheric correction method, height-correlation, for example') print('3) or turn off the option by setting pysar.troposphericDelay.method = no.\n') raise RuntimeError() inps.timeseriesFile = outName inps.timeseriesFiles.append(outName) else: print('Un-recognized atmospheric delay correction method: {}'.format(inps.tropMethod)) # Grab tropospheric delay file try: fileList = [os.path.join(inps.workDir, 'INPUTS/{}.h5'.format(inps.tropModel))] inps.tropFile = ut.get_file_list(fileList)[0] except: inps.tropFile = None return
def read_template(inps): print('\n********** Read Template File **********') # default template inps.templateFile = os.path.join(inps.workDir, 'pysarApp_template.txt') if not os.path.isfile(inps.templateFile): print('generate default template file:', inps.templateFile) shutil.copy2(inps.autoTemplateFile, inps.workDir) else: check_obsolete_default_template(inps) # custom template customTemplate = None if inps.customTemplateFile: # Copy custom template file to work directory inputs_dir = os.path.join(inps.workDir, 'INPUTS') if ut.run_or_skip(out_file=os.path.join(inputs_dir, os.path.basename(inps.customTemplateFile)), in_file=inps.customTemplateFile, check_readable=False) == 'run': if not os.path.isdir(inputs_dir): os.makedirs(inputs_dir) print('create directory:', inputs_dir) shutil.copy2(inps.customTemplateFile, inputs_dir) print('copy {} to INPUTS directory'.format(os.path.basename(inps.customTemplateFile))) # Read custom template print('read custom template file:', inps.customTemplateFile) customTemplate = readfile.read_template(inps.customTemplateFile) # correct some loose type errors standardValues = {'def':'auto', 'default':'auto', 'y':'yes', 'on':'yes', 'true':'yes', 'n':'no', 'off':'no', 'false':'no' } for key, value in customTemplate.items(): if value in standardValues.keys(): customTemplate[key] = standardValues[value] for key in ['pysar.deramp', 'pysar.troposphericDelay.method']: if key in customTemplate.keys(): customTemplate[key] = customTemplate[key].lower().replace('-', '_') if 'processor' in customTemplate.keys(): customTemplate['pysar.load.processor'] = customTemplate['processor'] for key in ['SUBSET_XMIN', 'SUBSET_YMIN']: if key in customTemplate.keys(): customTemplate.pop(key) # Update default template with custom input template print('update default template based on input custom template') inps.templateFile = ut.update_template_file(inps.templateFile, customTemplate) if inps.generate_template: raise SystemExit('Exit as planned after template file generation.') print('read default template file:', inps.templateFile) template = readfile.read_template(inps.templateFile) template = ut.check_template_auto_value(template) # Get existing files name: unavco_attributes.txt try: inps.unavcoMetadataFile = ut.get_file_list('unavco_attribute*txt', abspath=True)[0] except: inps.unavcoMetadataFile = None print('No UNAVCO attributes file found.') return inps, template, customTemplate
def get_delay_timeseries(inps, atr): """Calculate delay time-series and write it to HDF5 file. Parameters: inps : namespace, all input parameters atr : dict, metadata to be saved in trop_file Returns: trop_file : str, file name of ECMWF.h5 """ def get_dataset_size(fname): atr = readfile.read_attribute(fname) return (atr['LENGTH'], atr['WIDTH']) # check 1 - existing tropo delay file if (ut.run_or_skip(out_file=inps.trop_file, in_file=inps.grib_file_list, print_msg=False) == 'skip' and get_dataset_size(inps.trop_file) == get_dataset_size( inps.geom_file)): print( '{} file exists and is newer than all GRIB files, skip updating.'. format(inps.trop_file)) return # check 2 - geometry file if any(i is None for i in [inps.geom_file, inps.ref_yx]): print( 'No DEM / incidenceAngle / ref_yx found, skip calculating tropospheric delays.' ) if not os.path.isfile(inps.trop_file): inps.trop_file = None return # prepare geometry data geom_obj = geometry(inps.geom_file) geom_obj.open() inps.dem = geom_obj.read(datasetName='height') inps.inc = geom_obj.read(datasetName='incidenceAngle') if 'latitude' in geom_obj.datasetNames: inps.lat = geom_obj.read(datasetName='latitude') inps.lon = geom_obj.read(datasetName='longitude') else: inps.lat, inps.lon = get_lat_lon(geom_obj.metadata) # calculate phase delay length, width = int(atr['LENGTH']), int(atr['WIDTH']) num_date = len(inps.grib_file_list) date_list = [str(re.findall('\d{8}', i)[0]) for i in inps.grib_file_list] trop_data = np.zeros((num_date, length, width), np.float32) print( 'calcualting delay for each date using PyAPS (Jolivet et al., 2011; 2014) ...' ) print('number of grib files used: {}'.format(num_date)) if verbose: prog_bar = ptime.progressBar(maxValue=num_date) for i in range(num_date): grib_file = inps.grib_file_list[i] trop_data[i] = get_delay(grib_file, inps) if verbose: prog_bar.update(i + 1, suffix=os.path.basename(grib_file)) if verbose: prog_bar.close() # Convert relative phase delay on reference date inps.ref_date = atr.get('REF_DATE', date_list[0]) print('convert to relative phase delay with reference date: ' + inps.ref_date) inps.ref_idx = date_list.index(inps.ref_date) trop_data -= np.tile(trop_data[inps.ref_idx, :, :], (num_date, 1, 1)) # Write tropospheric delay to HDF5 atr['REF_Y'] = inps.ref_yx[0] atr['REF_X'] = inps.ref_yx[1] ts_obj = timeseries(inps.trop_file) ts_obj.write2hdf5(data=trop_data, dates=date_list, metadata=atr, refFile=inps.timeseries_file) return
def run_tropospheric_delay_correction(self, step_name): """Correct tropospheric delays.""" geom_file = ut.check_loaded_dataset(self.workDir, print_msg=False)[2] mask_file = 'maskTempCoh.h5' fnames = self.get_timeseries_filename(self.template)[step_name] in_file = fnames['input'] out_file = fnames['output'] if in_file != out_file: poly_order = self.template['pysar.troposphericDelay.polyOrder'] tropo_model = self.template['pysar.troposphericDelay.weatherModel'] weather_dir = self.template['pysar.troposphericDelay.weatherDir'] method = self.template['pysar.troposphericDelay.method'] def get_dataset_size(fname): atr = readfile.read_attribute(fname) return (atr['LENGTH'], atr['WIDTH']) # Phase/Elevation Ratio (Doin et al., 2009) if method == 'height_correlation': tropo_look = self.template['pysar.troposphericDelay.looks'] tropo_min_cor = self.template[ 'pysar.troposphericDelay.minCorrelation'] scp_args = '{f} -g {g} -p {p} -m {m} -o {o} -l {l} -t {t}'.format( f=in_file, g=geom_file, p=poly_order, m=mask_file, o=out_file, l=tropo_look, t=tropo_min_cor) print( 'tropospheric delay correction with height-correlation approach' ) print('tropo_phase_elevation.py', scp_args) if ut.run_or_skip(out_file=out_file, in_file=in_file) == 'run': pysar.tropo_phase_elevation.main(scp_args.split()) # Weather Re-analysis Data (Jolivet et al., 2011;2014) elif method == 'pyaps': scp_args = '-f {f} --model {m} -g {g} -w {w}'.format( f=in_file, m=tropo_model, g=geom_file, w=weather_dir) print( 'Atmospheric correction using Weather Re-analysis dataset (PyAPS, Jolivet et al., 2011)' ) print('Weather Re-analysis dataset:', tropo_model) print('tropo_pyaps.py ', scp_args) tropo_file = './INPUTS/{}.h5'.format(tropo_model) if ut.run_or_skip(out_file=out_file, in_file=[in_file, tropo_file]) == 'run': if os.path.isfile(tropo_file) and get_dataset_size( tropo_file) == get_dataset_size(in_file): scp_args = '{f} {t} -o {o} --force'.format( f=in_file, t=tropo_file, o=out_file) print('--------------------------------------------') print('Use existed tropospheric delay file: {}'.format( tropo_file)) print('diff.py', scp_args) pysar.diff.main(scp_args.split()) else: from pysar import tropo_pyaps tropo_pyaps.main(scp_args.split()) else: print('No tropospheric delay correction.') return
def _read_template(self): # read custom template, to: # 1) update default template # 2) add metadata to ifgramStack file and HDF-EOS5 file self.customTemplate = None if self.customTemplateFile: cfile = self.customTemplateFile # Copy custom template file to INPUTS directory for backup inputs_dir = os.path.join(self.workDir, 'INPUTS') if not os.path.isdir(inputs_dir): os.makedirs(inputs_dir) print('create directory:', inputs_dir) if ut.run_or_skip(out_file=os.path.join(inputs_dir, os.path.basename(cfile)), in_file=cfile, check_readable=False) == 'run': shutil.copy2(cfile, inputs_dir) print('copy {} to INPUTS directory for backup.'.format( os.path.basename(cfile))) # Read custom template print('read custom template file:', cfile) cdict = readfile.read_template(cfile) # correct some loose type errors standardValues = { 'def': 'auto', 'default': 'auto', 'y': 'yes', 'on': 'yes', 'true': 'yes', 'n': 'no', 'off': 'no', 'false': 'no' } for key, value in cdict.items(): if value in standardValues.keys(): cdict[key] = standardValues[value] for key in ['pysar.deramp', 'pysar.troposphericDelay.method']: if key in cdict.keys(): cdict[key] = cdict[key].lower().replace('-', '_') if 'processor' in cdict.keys(): cdict['pysar.load.processor'] = cdict['processor'] # these metadata are used in load_data.py only, not needed afterwards # (in order to manually add extra offset when the lookup table is shifted) # (seen in ROI_PAC product sometimes) for key in ['SUBSET_XMIN', 'SUBSET_YMIN']: if key in cdict.keys(): cdict.pop(key) self.customTemplate = dict(cdict) # Update default template file based on custom template print('update default template based on input custom template') self.templateFile = ut.update_template_file( self.templateFile, self.customTemplate) print('read default template file:', self.templateFile) self.template = readfile.read_template(self.templateFile) self.template = ut.check_template_auto_value(self.template) # correct some loose setup conflicts if self.template['pysar.geocode'] is False: for key in ['pysar.save.hdfEos5', 'pysar.save.kmz']: if self.template[key] is True: self.template['pysar.geocode'] = True print('Turn ON pysar.geocode in order to run {}.'.format( key)) break return