#!/usr/bin/env python3 ######################## #Author: Heresh Fattahi ####################### import os, glob , sys import datetime noMCF = 'False' defoMax = '2' maxNodes = 72 class config(object): """ A class representing the config file """ def __init__(self, outname): self.f= open(outname,'w') self.f.write('[Common]'+'\n') self.f.write('') self.f.write('##########################'+'\n') def configure(self,inps): for k in inps.__dict__.keys(): setattr(self, k, inps.__dict__[k]) self.plot = 'False' self.misreg_az = None self.misreg_rng = None self.multilook_tool = None self.no_data_value = None def Sentinel1_TOPS(self,function): self.f.write('##########################'+'\n') self.f.write(function+'\n') self.f.write('Sentinel1_TOPS : ' + '\n') self.f.write('dirname : ' + self.dirName+'\n') self.f.write('swaths : ' + self.swaths+'\n') if self.orbit_type == 'precise': self.f.write('orbitdir : '+self.orbit_dirname+'\n') else: self.f.write('orbit : '+self.orbit_file+'\n') self.f.write('outdir : ' + self.outDir + '\n') self.f.write('auxdir : ' + self.aux_dirname + '\n') if self.bbox is not None: self.f.write('bbox : ' + self.bbox + '\n') self.f.write('pol : ' + self.polarization + '\n') self.f.write('##########################' + '\n') def computeAverageBaseline(self, function): self.f.write('##########################'+'\n') self.f.write(function + '\n') self.f.write('computeBaseline : '+'\n') self.f.write('reference : ' + self.reference + '\n') self.f.write('secondary : ' + self.secondary + '\n') self.f.write('baseline_file : ' + self.baselineFile + '\n') def computeGridBaseline(self, function): self.f.write('##########################'+'\n') self.f.write(function + '\n') self.f.write('baselineGrid : '+'\n') self.f.write('reference : ' + self.reference + '\n') self.f.write('secondary : ' + self.secondary + '\n') self.f.write('baseline_file : ' + self.baselineFile + '\n') def topo(self,function): self.f.write('##########################'+'\n') self.f.write('#Call topo to produce reference geometry files'+'\n') self.f.write(function + '\n') self.f.write('topo : ' + '\n') self.f.write('reference : ' + self.outDir + '\n') self.f.write('dem : ' + self.dem + '\n') self.f.write('geom_referenceDir : ' + self.geom_referenceDir + '\n') self.f.write('numProcess : ' + str(self.numProcess4topo) + '\n') self.f.write('##########################' + '\n') def geo2rdr(self,function): self.f.write('##########################' + '\n') self.f.write(function + '\n') self.f.write('geo2rdr :' + '\n') self.f.write('secondary : ' + self.secondaryDir + '\n') self.f.write('reference : ' + self.referenceDir + '\n') self.f.write('geom_referenceDir : ' + self.geom_reference + '\n') self.f.write('coregSLCdir : ' + self.coregSecondaryDir + '\n') self.f.write('overlap : ' + self.overlapTrueOrFalse + '\n') if self.useGPU: self.f.write('useGPU : True \n') else: self.f.write('useGPU : False\n') if self.misreg_az is not None: self.f.write('azimuth_misreg : ' + self.misreg_az + '\n') if self.misreg_rng is not None: self.f.write('range_misreg : ' + self.misreg_rng + '\n') def resamp_withCarrier(self,function): self.f.write('##########################' + '\n') self.f.write(function + '\n') self.f.write('resamp_withCarrier : ' + '\n') self.f.write('secondary : ' + self.secondaryDir + '\n') self.f.write('reference : ' + self.referenceDir + '\n') #self.f.write('interferogram_prefix :' + self.interferogram_prefix + '\n') self.f.write('coregdir : ' + self.coregSecondaryDir + '\n') self.f.write('overlap : ' + self.overlapTrueOrFalse + '\n') if self.misreg_az is not None: self.f.write('azimuth_misreg : ' + self.misreg_az + '\n') if self.misreg_rng is not None: self.f.write('range_misreg : ' + self.misreg_rng + '\n') def generateIgram(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('generateIgram : ' + '\n') self.f.write('reference : ' + self.referenceDir + '\n') self.f.write('secondary : ' + self.secondaryDir + '\n') self.f.write('interferogram : ' + self.interferogramDir + '\n') self.f.write('flatten : ' + self.flatten + '\n') self.f.write('interferogram_prefix : ' + self.interferogram_prefix +'\n') self.f.write('overlap : ' + self.overlapTrueOrFalse + '\n') if self.misreg_az is not None: self.f.write('azimuth_misreg : ' + self.misreg_az + '\n') if self.misreg_rng is not None: self.f.write('range_misreg : ' + self.misreg_rng + '\n') self.f.write('###################################' + '\n') def overlap_withDEM(self,function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('overlap_withDEM : '+'\n') self.f.write('interferogram : ' + self.interferogramDir +'\n') self.f.write('reference_dir : ' + self.referenceDir+'\n') self.f.write('secondary_dir : ' + self.secondaryDir+'\n') self.f.write('overlap_dir : ' + self.overlapDir+'\n') def azimuthMisreg(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('estimateAzimuthMisreg : ' + '\n') self.f.write('overlap_dir : ' + self.overlapDir + '\n') self.f.write('out_azimuth : ' + self.misregFile + '\n') self.f.write('coh_threshold : ' + self.esdCoherenceThreshold + '\n') self.f.write('plot : ' + self.plot + '\n') def rangeMisreg(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('estimateRangeMisreg : ' + '\n') self.f.write('reference : ' + self.referenceDir + '\n') self.f.write('secondary : ' + self.secondaryDir + '\n') self.f.write('out_range : ' + self.misregFile + '\n') self.f.write('snr_threshold : ' + self.snrThreshold + '\n') def mergeBurst(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('mergeBursts : ' + '\n') try: self.f.write('stack : ' + self.stack +'\n') except: pass self.f.write('inp_reference : ' + self.reference +'\n') self.f.write('dirname : ' + self.dirName + '\n') self.f.write('name_pattern : ' + self.namePattern + '\n') self.f.write('outfile : ' + self.mergedFile + '\n') self.f.write('method : ' + self.mergeBurstsMethod + '\n') self.f.write('aligned : ' + self.aligned + '\n') self.f.write('valid_only : ' + self.validOnly + '\n') self.f.write('use_virtual_files : ' + self.useVirtualFiles + '\n') self.f.write('multilook : ' + self.multiLook + '\n') self.f.write('range_looks : ' + self.rangeLooks + '\n') self.f.write('azimuth_looks : ' + self.azimuthLooks + '\n') if self.multilook_tool: self.f.write('multilook_tool : ' + self.multilook_tool + '\n') if self.no_data_value is not None: self.f.write('no_data_value : ' + self.no_data_value + '\n') def mergeSwaths(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('mergeSwaths : ' + '\n') self.f.write('input : ' + self.inputDirs + '\n') self.f.write('file : ' + self.fileName + '\n') self.f.write('metadata : ' + self.metadata + '\n') self.f.write('output : ' + self.outDir +'\n') def multiLook(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('looks_withDEM : ' + '\n') self.f.write('input : ' + self.input + '\n') self.f.write('output : ' + self.output + '\n') self.f.write('range : ' + self.rangeLooks + '\n') self.f.write('azimuth : ' + self.azimuthLooks + '\n') def FilterAndCoherence(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('FilterAndCoherence : ' + '\n') self.f.write('input : ' + self.input + '\n') self.f.write('filt : ' + self.filtName + '\n') self.f.write('coh : ' + self.cohName + '\n') self.f.write('strength : ' + self.filtStrength + '\n') self.f.write('slc1 : ' + self.slc1 + '\n') self.f.write('slc2 : ' + self.slc2 + '\n') self.f.write('complex_coh : '+ self.cpxCohName + '\n') self.f.write('range_looks : ' + self.rangeLooks + '\n') self.f.write('azimuth_looks : ' + self.azimuthLooks + '\n') def unwrap(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('unwrap : ' + '\n') self.f.write('ifg : ' + self.ifgName + '\n') self.f.write('unw : ' + self.unwName + '\n') self.f.write('coh : ' + self.cohName + '\n') self.f.write('nomcf : ' + self.noMCF + '\n') self.f.write('reference : ' + self.reference + '\n') self.f.write('defomax : ' + self.defoMax + '\n') self.f.write('rlks : ' + self.rangeLooks + '\n') self.f.write('alks : ' + self.azimuthLooks + '\n') if self.rmFilter: self.f.write('rmfilter : True \n') else: self.f.write('rmfilter : False\n') self.f.write('method : ' + self.unwMethod + '\n') def unwrapSnaphu(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') self.f.write('unwrapSnaphu : ' + '\n') self.f.write('ifg : ' + self.ifgName + '\n') self.f.write('unw : ' + self.unwName + '\n') self.f.write('coh : ' + self.cohName + '\n') self.f.write('nomcf : ' + self.noMCF + '\n') self.f.write('reference : ' + self.reference + '\n') self.f.write('defomax : ' + self.defoMax + '\n') self.f.write('rlks : ' + self.rangeLooks + '\n') self.f.write('alks : ' + self.azimuthLooks + '\n') self.f.write('numProcess : ' + self.numProcess + '\n') def denseOffset(self, function): self.f.write('###################################'+'\n') self.f.write(function + '\n') # CPU or GPU self.f.write('denseOffsets : ' + '\n') #self.f.write('DenseOffsets : ' + '\n') #self.f.write('cuDenseOffsets : ' + '\n') self.f.write('reference : ' + self.reference + '\n') self.f.write('secondary : ' + self.secondary + '\n') self.f.write('outprefix : ' + self.output + '\n') #self.f.write('ww : 256\n') #self.f.write('wh : 128\n') def write_wrapper_config2run_file(self, configName, line_cnt, numProcess = 1): # dispassionate list of commands for single process if numProcess == 1: self.runf.write(self.text_cmd + 'SentinelWrapper.py -c ' + configName + '\n') # aggregate background commands between wait blocks for speed gains elif numProcess > 1: self.runf.write(self.text_cmd + 'SentinelWrapper.py -c ' + configName + ' &\n') if line_cnt == numProcess: self.runf.write('wait\n\n') line_cnt = 0 return line_cnt def finalize(self): self.f.close() class run(object): """ A class representing a run which may contain several functions """ #def __init__(self): def configure(self,inps, runName): for k in inps.__dict__.keys(): setattr(self, k, inps.__dict__[k]) self.runDir = os.path.join(self.work_dir, 'run_files') os.makedirs(self.runDir, exist_ok=True) self.run_outname = os.path.join(self.runDir, runName) print ('writing ', self.run_outname) self.config_path = os.path.join(self.work_dir,'configs') os.makedirs(self.config_path, exist_ok=True) self.runf= open(self.run_outname,'w') def unpackSLC(self, acquisitionDates, safe_dict): swath_path = self.work_dir os.makedirs(self.config_path, exist_ok=True) line_cnt = 0 for slcdate in acquisitionDates: configName = os.path.join(self.config_path,'config_unpack_'+slcdate) configObj = config(configName) configObj.configure(self) configObj.dirName = safe_dict[slcdate].safe_file configObj.orbit_file = safe_dict[slcdate].orbit configObj.orbit_type = safe_dict[slcdate].orbitType configObj.swaths = self.swath_num configObj.outDir = os.path.join(self.work_dir, 'slc/' + slcdate) configObj.geom_referenceDir = os.path.join(self.work_dir, 'geom_slc/' + slcdate) configObj.dem = os.path.join(self.work_dir, configObj.dem) configObj.Sentinel1_TOPS('[Function-1]') configObj.topo('[Function-2]') configObj.finalize() line_cnt += 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt) del configObj def unpackStackReferenceSLC(self, safe_dict): swath_path = self.work_dir os.makedirs(self.config_path, exist_ok=True) configName = os.path.join(self.config_path,'config_reference') configObj = config(configName) configObj.configure(self) configObj.dirName = safe_dict[self.reference_date].safe_file configObj.orbit_file = safe_dict[self.reference_date].orbit configObj.orbit_type = safe_dict[self.reference_date].orbitType configObj.swaths = self.swath_num configObj.outDir = os.path.join(self.work_dir, 'reference') configObj.geom_referenceDir = os.path.join(self.work_dir, 'geom_reference') configObj.dem = os.path.join(self.work_dir, configObj.dem) configObj.Sentinel1_TOPS('[Function-1]') configObj.topo('[Function-2]') configObj.finalize() line_cnt = 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt) del configObj def unpackSecondarysSLC(self, stackReferenceDate, secondaryList, safe_dict): line_cnt = 0 for secondary in secondaryList: configName = os.path.join(self.config_path,'config_secondary_'+secondary) outdir = os.path.join(self.work_dir,'secondarys/'+secondary) configObj = config(configName) configObj.configure(self) configObj.dirName = safe_dict[secondary].safe_file configObj.orbit_file = safe_dict[secondary].orbit configObj.orbit_type = safe_dict[secondary].orbitType configObj.swaths = self.swath_num configObj.outDir = outdir configObj.Sentinel1_TOPS('[Function-1]') configObj.finalize() line_cnt += 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt, self.numProcess) del configObj def averageBaseline(self, stackReferenceDate, secondaryList): line_cnt = 0 for secondary in secondaryList: configName = os.path.join(self.config_path,'config_baseline_'+secondary) configObj = config(configName) configObj.configure(self) configObj.reference = os.path.join(self.work_dir,'reference/') configObj.secondary = os.path.join(self.work_dir,'secondarys/'+secondary) configObj.baselineFile = os.path.join(self.work_dir,'baselines/' + stackReferenceDate +'_' + secondary + '/' + stackReferenceDate +'_'+ secondary + '.txt') configObj.computeAverageBaseline('[Function-1]') configObj.finalize() line_cnt += 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt, self.numProcess) del configObj def gridBaseline(self, stackReferenceDate, secondaryList): line_cnt = 0 for secondary in secondaryList: configName = os.path.join(self.config_path,'config_baselinegrid_'+secondary) configObj = config(configName) configObj.configure(self) configObj.reference = os.path.join(self.work_dir,'reference/') configObj.secondary = os.path.join(self.work_dir,'secondarys/'+secondary) configObj.baselineFile = os.path.join(self.work_dir, 'merged/baselines/' + secondary + '/' + secondary ) configObj.computeGridBaseline('[Function-1]') configObj.finalize() line_cnt += 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt) del configObj # also add the reference in itself to be consistent with the SLC dir configName = os.path.join(self.config_path,'config_baselinegrid_reference') configObj = config(configName) configObj.configure(self) configObj.reference = os.path.join(self.work_dir,'reference/') configObj.secondary = os.path.join(self.work_dir,'reference/') configObj.baselineFile = os.path.join(self.work_dir, 'merged/baselines/' + stackReferenceDate + '/' + stackReferenceDate) configObj.computeGridBaseline('[Function-1]') configObj.finalize() line_cnt = 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt) del configObj def extractOverlaps(self): self.runf.write(self.text_cmd + 'subsetReference.py -m ' + os.path.join(self.work_dir, 'reference') + ' -g ' + os.path.join(self.work_dir, 'geom_reference') + '\n') def geo2rdr_offset(self, secondaryList, fullBurst='False'): line_cnt = 0 for secondary in secondaryList: reference = self.reference_date if fullBurst == 'True': configName = os.path.join(self.config_path, 'config_fullBurst_geo2rdr_' + secondary) else: configName = os.path.join(self.config_path, 'config_overlap_geo2rdr_'+secondary) ########### configObj = config(configName) configObj.configure(self) configObj.secondaryDir = os.path.join(self.work_dir, 'secondarys/'+secondary) configObj.referenceDir = os.path.join(self.work_dir, 'reference') configObj.geom_reference = os.path.join(self.work_dir, 'geom_reference') configObj.coregSecondaryDir = os.path.join(self.work_dir, 'coreg_secondarys/'+secondary) if fullBurst == 'True': configObj.misreg_az = os.path.join(self.work_dir, 'misreg/azimuth/dates/' + secondary + '.txt') configObj.misreg_rng = os.path.join(self.work_dir, 'misreg/range/dates/' + secondary + '.txt') configObj.overlapTrueOrFalse = 'False' else: configObj.overlapTrueOrFalse = 'True' configObj.geo2rdr('[Function-1]') configObj.finalize() line_cnt += 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt, self.numProcess) del configObj def resample_with_carrier(self, secondaryList, fullBurst='False'): line_cnt = 0 for secondary in secondaryList: reference = self.reference_date if fullBurst == 'True': configName = os.path.join(self.config_path, 'config_fullBurst_resample_' + secondary) else: configName = os.path.join(self.config_path, 'config_overlap_resample_' + secondary) ########### configObj = config(configName) configObj.configure(self) configObj.secondaryDir = os.path.join(self.work_dir, 'secondarys/' + secondary) configObj.referenceDir = os.path.join(self.work_dir, 'reference') configObj.coregSecondaryDir = os.path.join(self.work_dir, 'coreg_secondarys/' + secondary) configObj.interferogram_prefix = 'coarse' configObj.referenceDir = os.path.join(self.work_dir, 'reference') if fullBurst == 'True': configObj.misreg_az = os.path.join(self.work_dir, 'misreg/azimuth/dates/' + secondary + '.txt') configObj.misreg_rng = os.path.join(self.work_dir, 'misreg/range/dates/' + secondary + '.txt') configObj.overlapTrueOrFalse = 'False' else: configObj.overlapTrueOrFalse = 'True' configObj.resamp_withCarrier('[Function-1]') configObj.finalize() line_cnt += 1 line_cnt = configObj.write_wrapper_config2run_file(configName, line_cnt, self.numProcess) del configObj def pairs_misregistration(self, dateList, safe_dict): # generating overlap interferograms, estimate azimuth misregistration for each pair: pairs = [] num_overlap_connections = int(self.num_overlap_connections) + 1 for i in range(len(dateList)-1): for j in range(i+1,i+num_overlap_connections): if j= orbit_start_date_time and self.stop_date_time < orbit_stop_date_time: self.orbit = os.path.join(orbitDir,orbit) self.orbitType = 'precise' match = True break if not match: print ("*****************************************") print (self.date) print ("orbit was not found in the "+orbitDir) # It should go and look online print ("downloading precise or restituted orbits ...") restitutedOrbitDir = os.path.join(workDir ,'orbits/' + self.date) orbitFiles = glob.glob(os.path.join(restitutedOrbitDir,'*.EOF')) if len(orbitFiles) > 0: orbitFile = orbitFiles[0] #fields = orbitFile.split('_') fields = os.path.basename(orbitFile).split('_') orbit_start_date_time = datetime.datetime.strptime(fields[6].replace('V',''), datefmt) orbit_stop_date_time = datetime.datetime.strptime(fields[7].replace('.EOF',''), datefmt) if self.start_date_time >= orbit_start_date_time and self.stop_date_time < orbit_stop_date_time: print ("restituted orbit already exists.") self.orbit = orbitFile self.orbitType = 'restituted' #if not os.path.exists(restitutedOrbitDir): else: os.makedirs(restitutedOrbitDir, exist_ok=True) cmd = 'fetchOrbit.py -i ' + self.safe_file + ' -o ' + restitutedOrbitDir print(cmd) os.system(cmd) orbitFile = glob.glob(os.path.join(restitutedOrbitDir,'*.EOF')) self.orbit = orbitFile[0] self.orbitType = 'restituted' # an example for writing job files when using clusters """ def writeJobFile(runFile): jobName = runFile + '.job' dirName = os.path.dirname(runFile) with open(runFile) as ff: nodes = len(ff.readlines()) if nodes >maxNodes: nodes = maxNodes f = open (jobName,'w') f.write('#!/bin/bash '+ '\n') f.write('#PBS -N Parallel_GNU'+ '\n') f.write('#PBS -l nodes=' + str(nodes) + '\n') jobTxt='''#PBS -V #PBS -l walltime=05:00:00 #PBS -q default #PBS -m bae -M hfattahi@gps.caltech.edu echo Working directory is $PBS_O_WORKDIR cd $PBS_O_WORKDIR echo Running on host `hostname` echo Time is `date` ### Define number of processors NPROCS=`wc -l < $PBS_NODEFILE` echo This job has allocated $NPROCS cpus # Tell me which nodes it is run on echo " " echo This jobs runs on the following processors: echo `cat $PBS_NODEFILE` echo " " # # Run the parallel with the nodelist and command file # ''' f.write(jobTxt+ '\n') f.write('parallel --sshloginfile $PBS_NODEFILE -a ' + os.path.basename(runFile) + '\n') f.write('') f.close() """