ISCE_INSAR/applications/insarApp.py

1209 lines
38 KiB
Python
Raw Normal View History

2019-01-16 19:40:08 +00:00
#!/usr/bin/env python3
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Copyright 2012 California Institute of Technology. ALL RIGHTS RESERVED.
#
2019-01-16 19:40:08 +00:00
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
2019-01-16 19:40:08 +00:00
# http://www.apache.org/licenses/LICENSE-2.0
#
2019-01-16 19:40:08 +00:00
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
2019-01-16 19:40:08 +00:00
# United States Government Sponsorship acknowledged. This software is subject to
# U.S. export control laws and regulations and has been classified as 'EAR99 NLR'
# (No [Export] License Required except when exporting to an embargoed country,
# end user, or in support of a prohibited end use). By downloading this software,
# the user agrees to comply with all applicable U.S. export laws and regulations.
# The user has the responsibility to obtain export licenses, or other export
# authority as may be required before exporting this software to any 'EAR99'
# embargoed foreign country or citizen of those countries.
#
# Authors: Giangi Sacco, Eric Gurrola
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import print_function
import time
import os
import sys
from isce import logging
2019-01-16 19:40:08 +00:00
import isce
import isceobj
import iscesys
from iscesys.Component.Application import Application
from iscesys.Compatibility import Compatibility
from iscesys.Component.Configurable import SELF
import isceobj.InsarProc as InsarProc
from isceobj.Scene.Frame import FrameMixin
logger = logging.getLogger('isce.insar')
SENSOR_NAME = Application.Parameter(
'sensorName',
public_name='sensor name',
default=None,
type=str,
mandatory=True,
doc="Sensor name"
)
OFFSET_METHOD = Application.Parameter(
'offsetMethod',
public_name='slc offset method',
default="offsetprf",
type=str,
mandatory=False,
doc=("SLC offset estimation method name. "+
"Use value=ampcor to run ampcor")
)
OFFSET_SEARCH_WINDOW_SIZE = Application.Parameter(
'offsetSearchWindowSize',
public_name='offset search window size',
default=None,
type=int,
mandatory=False,
doc=("Search window size used in offsetprf "+
"and rgoffset.")
)
PEG_SELECT = Application.Parameter(
'pegSelect',
public_name='peg select',
default='average',
mandatory=False,
doc='Peg selection method. Can be reference, secondary or average'
2019-01-16 19:40:08 +00:00
)
PEG_LAT = Application.Parameter(
'pegLat',
public_name='peg latitude (deg)',
default=None,
type=float,
mandatory=False,
doc='Peg Latitude in degrees'
)
PEG_LON = Application.Parameter(
'pegLon',
public_name='peg longitude (deg)',
default=None,
type=float,
mandatory=False,
doc='Peg Longitude in degrees'
)
PEG_HDG = Application.Parameter(
'pegHdg',
public_name='peg heading (deg)',
default=None,
type=float,
mandatory=False,
doc='Peg Heading in degrees'
)
PEG_RAD = Application.Parameter(
'pegRad',
public_name='peg radius (m)',
default=None,
type=float,
mandatory=False,
doc='Peg Radius of Curvature in meters'
)
FILTER_STRENGTH = Application.Parameter(
'filterStrength',
public_name='filter strength',
default = None,
type=float,
mandatory=False,
doc='Goldstein Werner Filter strength'
)
CORRELATION_METHOD = Application.Parameter(
'correlation_method',
public_name='correlation_method',
default='cchz_wave',
type=str,
mandatory=False,
doc=(
"""Select coherence estimation method:
cchz=cchz_wave
phase_gradient=phase gradient"""
)
)
DOPPLER_METHOD = Application.Parameter(
'dopplerMethod',
public_name='doppler method',
default='useDOPIQ',
type=str, mandatory=False,
doc= "Doppler calculation method.Choices: 'useDOPIQ', 'useCalcDop', 'useDoppler'."
)
USE_DOP = Application.Parameter(
'use_dop',
public_name='use_dop',
default="average",
type=float,
mandatory=False,
doc="Choose whether to use reference, secondary, or average Doppler for processing."
2019-01-16 19:40:08 +00:00
)
UNWRAPPER_NAME = Application.Parameter(
'unwrapper_name',
public_name='unwrapper name',
default='grass',
type=str,
mandatory=False,
doc="Unwrapping method to use. To be used in combination with UNWRAP."
)
# to be replaced by DO_UNWRAP;
UNWRAP = Application.Parameter(
'unwrap',
public_name='unwrap',
default=False,
type=bool,
mandatory=False,
doc="True if unwrapping is desired. To be used in combination with UNWRAPPER_NAME."
)
# not fully supported yet; use UNWRAP instead
DO_UNWRAP = Application.Parameter(
'do_unwrap',
public_name='do unwrap',
default=False,
type=bool,
mandatory=False,
doc="True if unwrapping is desired. To be unsed in combination with UNWRAPPER_NAME."
)
DO_UNWRAP_2STAGE = Application.Parameter(
'do_unwrap_2stage',
public_name='do unwrap 2 stage',
default=False,
type=bool,
mandatory=False,
doc="True if unwrapping is desired. To be unsed in combination with UNWRAPPER_NAME."
)
UNWRAPPER_2STAGE_NAME = Application.Parameter(
'unwrapper_2stage_name',
public_name='unwrapper 2stage name',
default='REDARC0',
type=str,
mandatory=False,
doc="2 Stage Unwrapping method to use. Available: MCF, REDARC0, REDARC1, REDARC2"
)
SOLVER_2STAGE = Application.Parameter(
'solver_2stage',
public_name='SOLVER_2STAGE',
default='pulp',
type=str,
mandatory=False,
doc='Linear Programming Solver for 2Stage; Options: pulp, gurobi, glpk; Used only for Redundant Arcs'
)
DO_OFFSETPRF = Application.Parameter(
'do_offsetprf',
public_name='do offsetprf',
default=True,
type=bool,
mandatory=False,
doc="Set to False if offsetprf is not required."
)
DO_RGOFFSET = Application.Parameter(
'do_rgoffset',
public_name='do rgoffset',
default=True,
type=bool,
mandatory=False,
doc="Set to False if offsetprf is not required."
)
USE_HIGH_RESOLUTION_DEM_ONLY = Application.Parameter(
'useHighResolutionDemOnly',
public_name='useHighResolutionDemOnly',
default=False,
type=int,
mandatory=False,
doc=(
"""If True and a dem is not specified in input, it will only
download the SRTM highest resolution dem if it is available
and fill the missing portion with null values (typically -32767)."""
)
)
DEM_FILENAME = Application.Parameter(
'demFilename',
public_name='demFilename',
default='',
type=str,
mandatory=False,
doc="Filename of the DEM init file"
)
GEO_POSTING = Application.Parameter(
'geoPosting',
public_name='geoPosting',
default=None,
type=float,
mandatory=False,
doc=(
"Output posting for geocoded images in degrees (latitude = longitude)"
)
)
POSTING = Application.Parameter(
'posting',
public_name='posting',
default=15,
type=int,
mandatory=False,
doc="posting for interferogram"
)
RANGE_LOOKS = Application.Parameter(
'rangeLooks',
public_name='range looks',
default=None,
type=int,
mandatory=False,
doc='Number of range looks to use in resamp'
)
AZ_LOOKS = Application.Parameter(
'azLooks',
public_name='azimuth looks',
default=None,
type=int,
mandatory=False,
doc='Number of azimuth looks to use in resamp'
)
PATCH_SIZE = Application.Parameter(
'patchSize',
public_name='azimuth patch size',
default=None,
type=int,
mandatory=False,
doc=(
"Size of overlap/save patch size for formslc"
)
)
GOOD_LINES = Application.Parameter(
'goodLines',
public_name='patch valid pulses',
default=None,
type=int,
mandatory=False,
doc=(
"Size of overlap/save save region for formslc"
)
)
NUM_PATCHES = Application.Parameter(
'numPatches',
public_name='number of patches',
default=None,
type=int,
mandatory=False,
doc=(
"How many patches to process of all available patches"
)
)
GROSS_AZ = Application.Parameter(
'grossAz',
public_name='gross azimuth offset',
default=None,
type=int,
mandatory=False,
doc=(
"Override the value of the gross azimuth offset for offset " +
"estimation prior to interferogram formation"
)
)
GROSS_RG = Application.Parameter(
'grossRg',
public_name='gross range offset',
default=None,
type=int,
mandatory=False,
doc=(
"Override the value of the gross range offset for offset" +
"estimation prior to interferogram formation"
)
)
CULLING_SEQUENCE = Application.Parameter(
'culling_sequence',
public_name='Culling Sequence',
default= (10,5,3),
container=tuple,
type=int,
doc="TBD"
)
CULLING_ERROR_LIMIT = Application.Parameter(
'culling_error_limit',
public_name='Culling error limit',
default=100,
type = int,
mandatory = False,
doc = 'Minimum number of culled offsets to be used for offset field polynomial estimation'
)
GEOCODE_LIST = Application.Parameter(
'geocode_list',
public_name='geocode list',
default = None,
container=list,
type=str,
doc = "List of products to geocode."
)
GEOCODE_BOX = Application.Parameter(
'geocode_bbox',
public_name='geocode bounding box',
default = None,
container=list,
type=float,
doc='Bounding box for geocoding - South, North, West, East in degrees'
)
PICKLE_DUMPER_DIR = Application.Parameter(
'pickleDumpDir',
public_name='pickle dump directory',
default='PICKLE',
type=str,
mandatory=False,
doc=(
"If steps is used, the directory in which to store pickle objects."
)
)
PICKLE_LOAD_DIR = Application.Parameter(
'pickleLoadDir',
public_name='pickle load directory',
default='PICKLE',
type=str,
mandatory=False,
doc=(
"If steps is used, the directory from which to retrieve pickle objects."
)
)
RENDERER = Application.Parameter(
'renderer',
public_name='renderer',
default='pickle',
type=str,
mandatory=False,
doc=(
"Format in which the data is serialized when using steps. Options are xml (default) or pickle."
)
)
#Facility declarations
REFERENCE = Application.Facility(
'reference',
public_name='Reference',
2019-01-16 19:40:08 +00:00
module='isceobj.Sensor',
factory='createSensor',
args=(SENSOR_NAME, 'reference'),
2019-01-16 19:40:08 +00:00
mandatory=True,
doc="Reference raw data component"
2019-01-16 19:40:08 +00:00
)
SECONDARY = Application.Facility(
'secondary',
public_name='Secondary',
2019-01-16 19:40:08 +00:00
module='isceobj.Sensor',
factory='createSensor',
args=(SENSOR_NAME,'secondary'),
2019-01-16 19:40:08 +00:00
mandatory=True,
doc="Secondary raw data component"
2019-01-16 19:40:08 +00:00
)
REFERENCEDOP = Application.Facility(
'referencedop',
public_name='Reference Doppler',
2019-01-16 19:40:08 +00:00
module='isceobj.Doppler',
factory='createDoppler',
args=(DOPPLER_METHOD,),
mandatory=False,
doc="Reference Doppler calculation method"
2019-01-16 19:40:08 +00:00
)
SECONDARYDOP = Application.Facility(
'secondarydop',
public_name='Secondary Doppler',
2019-01-16 19:40:08 +00:00
module='isceobj.Doppler',
factory='createDoppler',
args=(DOPPLER_METHOD,),
mandatory=False,
doc="Reference Doppler calculation method"
2019-01-16 19:40:08 +00:00
)
DEM = Application.Facility(
'dem',
public_name='Dem',
module='isceobj.Image',
factory='createDemImage',
mandatory=False,
doc=(
"Dem Image configurable component. Do not include this in the "+
"input file and an SRTM Dem will be downloaded for you."
)
)
DEM_STITCHER = Application.Facility(
'demStitcher',
public_name='demStitcher',
module='iscesys.DataManager',
factory='createManager',
args=('dem1','iscestitcher',),
mandatory=False,
doc="Object that based on the frame bounding boxes creates a DEM"
)
RUN_ESTIMATE_HEIGHTS = Application.Facility(
'runEstimateHeights',
public_name='Estimate Heights',
module='isceobj.InsarProc',
factory='createEstimateHeights',
args=(SELF(), SENSOR_NAME),
mandatory=False,
doc="mocomp height estimation module"
)
RUN_FORM_SLC = Application.Facility(
'runFormSLC',
public_name='Form SLC',
module='isceobj.InsarProc',
factory='createFormSLC',
args=(SELF(), SENSOR_NAME),
mandatory=False,
doc="SLC formation module"
)
RUN_OFFSETPRF = Application.Facility(
'runOffsetprf',
public_name='slc offsetter',
module='isceobj.InsarProc',
factory='createOffsetprf',
args=(SELF(), OFFSET_METHOD, DO_OFFSETPRF),
mandatory=False,
doc="Offset a pair of SLC images."
)
RUN_RGOFFSET = Application.Facility(
'runRgoffset',
public_name='dem offseter',
module = 'isceobj.InsarProc',
factory= 'createRgoffset',
args=(SELF(), OFFSET_METHOD, DO_RGOFFSET),
mandatory=False,
doc="Dem offset estimator."
)
RUN_UNWRAPPER = Application.Facility(
'runUnwrapper',
public_name='Run unwrapper',
module='isceobj.InsarProc',
factory='createUnwrapper',
args=(SELF(), DO_UNWRAP, UNWRAPPER_NAME, UNWRAP),
mandatory=False,
doc="Unwrapping module"
)
RUN_UNWRAP_2STAGE = Application.Facility(
'runUnwrap2Stage',
public_name='Run unwrapper 2 Stage',
module='isceobj.InsarProc',
factory='createUnwrap2Stage',
args=(SELF(), DO_UNWRAP_2STAGE, UNWRAPPER_NAME),
mandatory=False,
doc="Unwrapping module"
)
_INSAR = Application.Facility(
'_insar',
public_name='insarproc',
module='isceobj.InsarProc',
factory='createInsarProc',
args = ('insarAppContext',isceobj.createCatalog('insarProc')),
mandatory=False,
doc="InsarProc object"
)
## Common interface for all insar applications.
class _InsarBase(Application, FrameMixin):
family = 'insar'
## Define Class parameters in this list
parameter_list = (SENSOR_NAME,
OFFSET_METHOD,
OFFSET_SEARCH_WINDOW_SIZE,
PEG_SELECT,
PEG_LAT,
PEG_LON,
PEG_HDG,
PEG_RAD,
FILTER_STRENGTH,
CORRELATION_METHOD,
DOPPLER_METHOD,
USE_DOP,
UNWRAP,
UNWRAPPER_NAME,
DO_UNWRAP,
DO_OFFSETPRF,
DO_RGOFFSET,
USE_HIGH_RESOLUTION_DEM_ONLY,
DEM_FILENAME,
GEO_POSTING,
POSTING,
RANGE_LOOKS,
AZ_LOOKS,
PATCH_SIZE,
GOOD_LINES,
NUM_PATCHES,
GROSS_AZ,
GROSS_RG,
CULLING_SEQUENCE,
CULLING_ERROR_LIMIT,
GEOCODE_LIST,
GEOCODE_BOX,
PICKLE_DUMPER_DIR,
PICKLE_LOAD_DIR,
RENDERER,
DO_UNWRAP_2STAGE,
UNWRAPPER_2STAGE_NAME,
SOLVER_2STAGE)
facility_list = (REFERENCE,
SECONDARY,
REFERENCEDOP,
SECONDARYDOP,
2019-01-16 19:40:08 +00:00
DEM,
DEM_STITCHER,
RUN_ESTIMATE_HEIGHTS,
RUN_FORM_SLC,
RUN_UNWRAPPER,
RUN_UNWRAP_2STAGE,
RUN_OFFSETPRF,
RUN_RGOFFSET,
_INSAR)
_pickleObj = "_insar"
def __init__(self, family='', name='',cmdline=None):
import isceobj
super().__init__(family=family, name=name,
cmdline=cmdline)
from isceobj.InsarProc import InsarProc
from iscesys.StdOEL.StdOELPy import create_writer
self._stdWriter = create_writer("log", "", True, filename="insar.log")
self._add_methods()
self._insarProcFact = InsarProc
'''
procDoc = isceobj.createCatalog('insarProc')
#self._insar = InsarProc.InsarProc(name='insarApp_conf',
# procDoc=procDoc
# )
self.insar.procDoc._addItem("ISCE_VERSION",
"Release: %s, svn-%s, %s. Current svn-%s" %
(isce.release_version, isce.release_svn_revision,
isce.release_date, isce.svn_revision
),
["insarProc"]
)
'''
return None
def _init(self):
message = (
("ISCE VERSION = %s, RELEASE_SVN_REVISION = %s,"+
"RELEASE_DATE = %s, CURRENT_SVN_REVISION = %s") %
(isce.__version__,
isce.release_svn_revision,
isce.release_date,
isce.svn_revision)
)
logger.info(message)
print(message)
# print("self.sensorName = ", self.sensorName)
# print("self.correlation_method = ", self.correlation_method)
# print("self.use_dop = ", self.use_dop)
# print("self.geoPosting = ", self.geoPosting)
# print("self.posting = ", self.posting)
# print("self.rangeLooks = ", self.rangeLooks)
# print("self.azLooks = ", self.azLooks)
# print("self.offsetMethod = ", self.offsetMethod)
# print("self.grossRg, self.grossAz = ", self.grossRg, self.grossAz )
if ( self.pegLat is not None and
self.pegLon is not None and
self.pegHdg is not None and
self.pegRad is not None ):
from isceobj.Location.Peg import Peg
self.peg = Peg(latitude=self.pegLat,
longitude=self.pegLon,
heading=self.pegHdg,
radiusOfCurvature=self.pegRad)
# print("self.peg = ", self.peg)
else:
self.peg = None
return None
## You need this to use the FrameMixin
@property
def frame(self):
return self.insar.frame
def _configure(self):
self.insar.procDoc._addItem("ISCE_VERSION",
"Release: %s, svn-%s, %s. Current svn-%s" %
(isce.release_version, isce.release_svn_revision,
isce.release_date, isce.svn_revision
),
["insarProc"]
)
#This is a temporary fix to get the user interface back to the dem
#facility interface while changes are being made in the DemImage class
#to include within it the capabilities urrently in extractInfo and
#createDem.
#jng ask Eric No longer needed
if self.demFilename:
import sys
print(
"The demFilename property is no longer supported as an " +
"input parameter."
)
print(
"The original method using a configurable facility for the " +
"Dem is now restored."
)
print(
"The automatic download feature is still supported in the " +
" same way as before:"
)
print(
"If you want automatic download of a Dem, then simply omit "+
"any configuration\ninformation in your input file regarding "+
"the Dem."
)
print()
print(
"Please replace the following information in your input file:"
)
print()
print(
"<property name='demFilename'><value>%s</value></property>" %
self.demFilename
)
print()
print("with the following information and try again:")
print()
print(
"<component name=\'Dem\'><catalog>%s</catalog></component>" %
self.demFilename
)
print()
else:
try:
self.dem.checkInitialization()
#jng ask Eric. self.demFilename no longer needed
# Give self.demFilename a value so that the SRTM Dem will not
# be downloaded
# Temporary fix that will be removed when the download option
# is handled within demImage
self.demFilename = "demFilename"
self.insar.demImage = self.dem
except Exception as err:
pass
#The following print statement is sometimes misleading when
#checkInitialization fails for a reason other than the dem
#not being found. The checkInitialization error should be
#handled more appropriately.
#print(
# "The Dem specified was not properly initialized. An SRTM" +
# " Dem will be downloaded."
# )
#self.dem was not properly initialized
#and self.demFilename is undefined.
#There is a check on self.demFilename
#below to download if necessary
else:
dem_snwe = self.dem.getsnwe()
if self.geocode_bbox:
####Adjust bbox according to dem
if self.geocode_bbox[0] < dem_snwe[0]:
logger.warning('Geocoding southern extent changed to match DEM')
2019-01-16 19:40:08 +00:00
self.geocode_bbox[0] = dem_snwe[0]
if self.geocode_bbox[1] > dem_snwe[1]:
logger.warning('Geocoding northern extent changed to match DEM')
2019-01-16 19:40:08 +00:00
self.geocode_bbox[1] = dem_snwe[1]
if self.geocode_bbox[2] < dem_snwe[2]:
logger.warning('Geocoding western extent changed to match DEM')
2019-01-16 19:40:08 +00:00
self.geocode_bbox[2] = dem_snwe[2]
if self.geocode_bbox[3] > dem_snwe[3]:
logger.warning('Geocoding eastern extent changed to match DEM')
2019-01-16 19:40:08 +00:00
self.geocode_bbox[3] = dem_snwe[3]
#Ensure consistency in geocode_list maintained by insarApp and
#InsarProc. If it is configured in both places, the one in insarApp
#will be used. It is complicated to try to merge the two lists
#because InsarProc permits the user to change the name of the files
#and the linkage between filename and filetype is lost by the time
#geocode_list is fully configured. In order to safely change file
#names and also specify the geocode_list, then insarApp should not
#be given a geocode_list from the user.
if(self.geocode_list is None):
#if not provided by the user use the list from InsarProc
self.geocode_list = self.insar.geocode_list
else:
#if geocode_list defined here, then give it to InsarProc
#for consistency between insarApp and InsarProc and warn the user
#check if the two geocode_lists differ in content
g_count = 0
for g in self.geocode_list:
if g not in self.insar.geocode_list:
g_count += 1
#warn if there are any differences in content
if g_count > 0:
print()
logger.warn((
"Some filenames in insarApp.geocode_list configuration "+
"are different from those in InsarProc. Using names given"+
" to insarApp."))
print("insarApp.geocode_list = {}".format(self.geocode_list))
print(("InsarProc.geocode_list = {}".format(
self.insar.geocode_list)))
self.insar.geocode_list = self.geocode_list
return None
@property
def insar(self):
return self._insar
@insar.setter
def insar(self, value):
self._insar = value
return None
@property
def procDoc(self):
return self.insar.procDoc
@procDoc.setter
def procDoc(self):
raise AttributeError(
"Can not assign to .insar.procDoc-- but you hit all its other stuff"
)
def _finalize(self):
pass
def help(self):
from isceobj.Sensor import SENSORS
print(self.__doc__)
lsensors = list(SENSORS.keys())
lsensors.sort()
print("The currently supported sensors are: ", lsensors)
return None
def help_steps(self):
print(self.__doc__)
print("A description of the individual steps can be found in the README file")
print("and also in the ISCE.pdf document")
return
## Method return True iff it changes the demFilename.
from isceobj.Util.decorators import use_api
@use_api
def verifyDEM(self):
referenceF = self._insar.referenceFrame
secondaryF = self._insar.secondaryFrame
info = self.extractInfo(referenceF, secondaryF)
2019-01-16 19:40:08 +00:00
#if an image has been specified, then no need to create one
if not self.dem.filename:
self.createDem(info)
else:
self.insar.demImage = self.dem
#ensure that the dem vrt file exists by creating (or recreating) it
self.insar.demImage.renderVRT()
#at this point a dem image has been set into self.insar, whether it
#was stitched together or read in input
demImage = self.insar.demImage
#if the demImage is already in wgs84 (because was provided in input) then skip and proceed
if demImage.reference.upper() != 'WGS84':
wgs84demFilename = self.insar.demImage.filename+'.wgs84'
wgs84demxmlFilename = wgs84demFilename+'.xml'
#if the dem reference is EGM96 and the WGS84 corrected
#dem files are not found, then create the WGS84 files
#using the demStitcher's correct method
if( demImage.reference.upper() == 'EGM96' and
not (os.path.isfile(wgs84demFilename) and
os.path.isfile(wgs84demxmlFilename))
):
self.insar.demImage = self.demStitcher.correct(demImage)
#make sure to load the wgs84 if present
elif(os.path.isfile(wgs84demFilename) and
os.path.isfile(wgs84demxmlFilename)):
from isceobj import createDemImage
self.insar.demImage = createDemImage()
self.insar.demImage.load(wgs84demxmlFilename)
if(self.insar.demImage.reference.upper() != 'WGS84'):
print('The dem',wgs84demFilename,'is not wgs84')
raise Exception
#ensure that the wgs84 dem vrt file exists
self.insar.demImage.renderVRT()
#get water mask
self.runCreateWbdMask(info)
return None
def renderProcDoc(self):
self.procDoc.renderXml()
## Run runOffoutliers() repeatedly with arguments from "iterator" keyword
def iterate_runOffoutliers(self, iterator=None):
"""iterate_runOffoutliers(iterator)
runs runOffoutliers multiple times with values (integers) from iterator.
iterator defaults to Insar._default_culling_sequence
"""
if iterator is None: iterator = self.culling_sequence
erriterator = [self.culling_error_limit]*len(iterator)
list(map(self.runOffoutliers, iterator, erriterator))
return None
def set_topoint1(self):
self._insar.topoIntImage = self._insar.resampIntImage
return None
def set_topoint2(self):
self._insar.topoIntImage = self._insar.resampOnlyImage
return None
def startup(self):
self.help()
self._insar.timeStart = time.time()
def endup(self):
self.renderProcDoc()
self._insar.timeEnd = time.time()
logger.info("Total Time: %i seconds" %
(self._insar.timeEnd-self._insar.timeStart))
return None
## Add instance attribute RunWrapper functions, which emulate methods.
def _add_methods(self):
self.runPreprocessor = InsarProc.createPreprocessor(self)
self.extractInfo = InsarProc.createExtractInfo(self)
self.createDem = InsarProc.createCreateDem(self)
self.runCreateWbdMask = InsarProc.createCreateWbdMask(self)
self.runMaskImages = InsarProc.createMaskImages(self)
self.runPulseTiming = InsarProc.createPulseTiming(self)
self.runSetmocomppath = InsarProc.createSetmocomppath(self)
self.runOrbit2sch = InsarProc.createOrbit2sch(self)
self.updatePreprocInfo = InsarProc.createUpdatePreprocInfo(self)
self.runOffoutliers = InsarProc.createOffoutliers(self)
self.prepareResamps = InsarProc.createPrepareResamps(self)
self.runResamp = InsarProc.createResamp(self)
self.runResamp_image = InsarProc.createResamp_image(self)
self.runMocompbaseline = InsarProc.createMocompbaseline(self)
self.runTopo = InsarProc.createTopo(self)
self.runCorrect = InsarProc.createCorrect(self)
self.runShadecpx2rg = InsarProc.createShadecpx2rg(self)
self.runResamp_only = InsarProc.createResamp_only(self)
self.runCoherence = InsarProc.createCoherence(self)
self.runFilter = InsarProc.createFilter(self)
self.runGrass = InsarProc.createGrass(self)
self.runGeocode = InsarProc.createGeocode(self)
return None
def _steps(self):
self.step('startup', func=self.startup,
doc=("Print a helpful message and "+
"set the startTime of processing")
)
# Run a preprocessor for the two sets of frames
self.step('preprocess',
func=self.runPreprocessor,
doc=(
"""Preprocess the reference and secondary sensor data to raw images"""
2019-01-16 19:40:08 +00:00
)
)
# Verify whether the DEM was initialized properly. If not, download
# a DEM
self.step('verifyDEM', func=self.verifyDEM)
# Run pulsetiming for each set of frames
self.step('pulsetiming', func=self.runPulseTiming)
self.step('estimateHeights', func=self.runEstimateHeights)
# Run setmocomppath
self.step('mocompath', func=self.runSetmocomppath, args=(self.peg,))
#init and run orbit2sch
self.step('orbit2sch', func=self.runOrbit2sch)
#update quantities in objPreProc obtained from previous steps
self.step('updatepreprocinfo',
func=self.updatePreprocInfo,
args=(self.use_dop,))
self.step('formslc', func=self.runFormSLC)
self.step('offsetprf', func=self.runOffsetprf)
# Cull offoutliers
self.step('outliers1', func=self.iterate_runOffoutliers)
self.step('prepareresamps',
func=self.prepareResamps,
args=(self.rangeLooks,self.azLooks))
self.step('resamp', func=self.runResamp)
self.step('resamp_image', func=self.runResamp_image)
# Mocompbaseline
self.step('mocompbaseline', func=self.runMocompbaseline)
# Topocorrect
#self.step('settopoint1',
# func=self.insar.delayed_attrcopy_from_to('resampIntImage',
# 'topoIntImage')
# )
self.step('settopoint1', func=self.set_topoint1)
self.step('topo', func=self.runTopo)
self.step('shadecpx2rg', func=self.runShadecpx2rg)
# Compute offsets and cull offoutliers
self.step('rgoffset', func=self.runRgoffset)
self.step('rg_outliers2', func=self.iterate_runOffoutliers)
self.step('resamp_only', func=self.runResamp_only)
#Topocorrect
#self.step('settopoint2',
# func=self.insar.delayed_attrcopy_from_to('resampOnlyImage',
# 'topoIntImage')
# )
self.step('settopoint2', func=self.set_topoint2)
self.step('correct', func=self.runCorrect)
# Coherence ?
self.step('coherence',
func=self.runCoherence,
args=(self.correlation_method,))
# Filter ?
self.step('filter', func=self.runFilter,
args=(self.filterStrength,))
#add water mask to coherence and interferogram
self.step('mask', func=self.runMaskImages)
# Unwrap ?
self.step('unwrap', func=self.runUnwrapper)
# Conditional 2 stage unwrapping
self.step('unwrap2stage', func=self.runUnwrap2Stage,
args=(self.unwrapper_2stage_name, self.solver_2stage))
return None
## Main has the common start to both insarApp and dpmApp.
def main(self):
self.help()
# Run a preprocessor for the two sets of frames
self.runPreprocessor()
#Verify whether user defined a dem component. If not, then download
# SRTM DEM.
self.verifyDEM()
# Run pulsetiming for each set of frames
self.runPulseTiming()
self.runEstimateHeights()
# Run setmocomppath
self.runSetmocomppath(peg=self.peg)
#init and run orbit2sch
self.runOrbit2sch()
#update quantities in objPreProc obtained from previous steps
self.updatePreprocInfo(use_dop=self.use_dop)
self.runFormSLC()
self.runOffsetprf()
# Cull offoutliers
self.iterate_runOffoutliers()
self.prepareResamps(self.rangeLooks, self.azLooks)
self.runResamp()
self.runResamp_image()
# Mocompbaseline
self.runMocompbaseline()
# Topocorrect
self.insar.topoIntImage = self.insar.resampIntImage
self.runTopo()
return None
@property
def resampAmpImage(self):
return self.insar.resampAmpImage
pass
class Insar(_InsarBase):
"""
Insar Application:
Implements InSAR processing flow for a pair of scenes from
sensor raw data to geocoded, flattened interferograms.
"""
family = "insar"
def __init__(self, family='',name='',cmdline=None):
#to allow inheritance with different family name use the locally
#defined only if the subclass (if any) does not specify one
super().__init__(
family=family if family else self.__class__.family, name=name,
cmdline=cmdline)
def Usage(self):
print("Usages: ")
print("insarApp.py <input-file.xml>")
print("insarApp.py --steps")
print("insarApp.py --help")
print("insarApp.py --help --steps")
## extends _InsarBase_steps, but not in the same was as main
def _steps(self):
super()._steps()
# Geocode
self.step('geocode', func=self.runGeocode,
args=(self.geocode_list, self.unwrap, self.geocode_bbox))
# self.step('endup', func=self.endup)
return None
## main() extends _InsarBase.main()
def main(self):
import time
timeStart = time.time()
super().main()
# self.runCorrect()
self.runShadecpx2rg()
self.runRgoffset()
# Cull offoutliers
self.iterate_runOffoutliers()
self.runResamp_only()
self.insar.topoIntImage=self.insar.resampOnlyImage
#self.runTopo()
self.runCorrect()
# Coherence ?
self.runCoherence(method=self.correlation_method)
# Filter ?
self.runFilter(self.filterStrength)
#add water mask to coherence and interferogram
self.runMaskImages()
# Unwrap ?
self.runUnwrapper()
# 2Stage Unwrapping
self.runUnwrap2Stage(self.unwrapper_2stage_name, self.solver_2stage)
# Geocode
self.runGeocode(self.geocode_list, self.unwrap, self.geocode_bbox)
timeEnd = time.time()
logger.info("Total Time: %i seconds" %(timeEnd - timeStart))
self.renderProcDoc()
return None
if __name__ == "__main__":
if not isce.stanford_license:
print("This workflow requires the Stanford licensed code elemnts.")
print("Unable to find the license information in the isce.stanford_license file.")
print("Please either obtain a stanford license and follow the instructions to")
print("install the stanford code elements or else choose a different workflow.")
raise SystemExit(0)
else:
#make an instance of Insar class named 'insarApp'
insar = Insar(name="insarApp")
#configure the insar application
insar.configure()
#invoke the base class run method, which returns status
status = insar.run()
#inform Python of the status of the run to return to the shell
raise SystemExit(status)