471 lines
14 KiB
Python
Executable File
471 lines
14 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# Copyright 2012 California Institute of Technology. ALL RIGHTS RESERVED.
|
|
#
|
|
# 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
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# 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.
|
|
#
|
|
# 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
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
import time
|
|
import sys
|
|
from isce import logging
|
|
|
|
import isce
|
|
import isceobj
|
|
import iscesys
|
|
from iscesys.Component.Application import Application
|
|
from iscesys.Compatibility import Compatibility
|
|
from iscesys.Component.Configurable import SELF
|
|
from isceobj import RtcProc
|
|
from isceobj.Util.decorators import use_api
|
|
|
|
logger = logging.getLogger('isce.grdsar')
|
|
|
|
|
|
SENSOR_NAME = Application.Parameter(
|
|
'sensorName',
|
|
public_name='sensor name',
|
|
default='SENTINEL1',
|
|
type=str,
|
|
mandatory=True,
|
|
doc="Sensor name"
|
|
)
|
|
|
|
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 Digital Elevation Model (DEM)"
|
|
)
|
|
|
|
WATER_FILENAME = Application.Parameter(
|
|
'waterFilename',
|
|
public_name='waterFilename',
|
|
default='',
|
|
type=str,
|
|
mandatory=False,
|
|
doc='Filename with SWBD data')
|
|
|
|
APPLY_WATER_MASK = Application.Parameter(
|
|
'applyWaterMask',
|
|
public_name='apply water mask',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc = 'Flag to apply water mask to images')
|
|
|
|
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'
|
|
)
|
|
|
|
EPSG = Application.Parameter(
|
|
'epsg',
|
|
public_name='epsg id',
|
|
default = '',
|
|
type=str,
|
|
doc='epsg code for roi'
|
|
)
|
|
|
|
GSPACING = Application.Parameter('gspacing',
|
|
public_name='geocode spacing',
|
|
default = 100.0,
|
|
type = float,
|
|
doc = 'Desired grid spacing of geocoded product in meters, in the specified UTM grid.'
|
|
)
|
|
|
|
INTMETHOD = Application.Parameter('intmethod',
|
|
public_name='geocode interpolation method',
|
|
default = 'bilinear',
|
|
type = str,
|
|
doc = 'Desired grid spacing of geocoded product in meters, in the specified UTM grid.'
|
|
)
|
|
|
|
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='xml',
|
|
type=str,
|
|
mandatory=True,
|
|
doc=(
|
|
"Format in which the data is serialized when using steps. Options are xml (default) or pickle."
|
|
))
|
|
|
|
NUMBER_AZIMUTH_LOOKS = Application.Parameter('numberAzimuthLooks',
|
|
public_name='azimuth looks',
|
|
default=None,
|
|
type=int,
|
|
mandatory=False,
|
|
doc='')
|
|
|
|
|
|
NUMBER_RANGE_LOOKS = Application.Parameter('numberRangeLooks',
|
|
public_name='range looks',
|
|
default=None,
|
|
type=int,
|
|
mandatory=False,
|
|
doc=''
|
|
)
|
|
|
|
POSTING = Application.Parameter('posting',
|
|
public_name='posting',
|
|
default = 10.0,
|
|
type = float,
|
|
mandatory = False,
|
|
doc = 'Posting of data. This can be any integer multiple of the product resolution. Used to determine looks')
|
|
|
|
POLARIZATIONS = Application.Parameter('polarizations',
|
|
public_name='polarizations',
|
|
default = [],
|
|
type = str,
|
|
container = list,
|
|
doc = 'Polarizations to process')
|
|
|
|
GEOCODE_LIST = Application.Parameter(
|
|
'geocode_list',
|
|
public_name='geocode list',
|
|
default = None,
|
|
container=list,
|
|
type=str,
|
|
doc = "List of products to geocode."
|
|
)
|
|
|
|
APPLY_THERMAL_NOISE_CORRECTION = Application.Parameter(
|
|
'apply_thermal_noise_correction',
|
|
public_name='apply thermal noise correction',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc = 'Flag to apply thermal noise correction. Currently only available for Sentinel-1.')
|
|
|
|
|
|
#Facility declarations
|
|
REFERENCE = Application.Facility(
|
|
'reference',
|
|
public_name='Reference',
|
|
module='isceobj.Sensor.GRD',
|
|
factory='createSensor',
|
|
args=(SENSOR_NAME, 'reference'),
|
|
mandatory=True,
|
|
doc="GRD data component"
|
|
)
|
|
|
|
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"
|
|
)
|
|
|
|
|
|
_GRD = Application.Facility(
|
|
'_grd',
|
|
public_name='rtcproc',
|
|
module='isceobj.RtcProc',
|
|
factory='createRtcProc',
|
|
args = ('rtcAppContext',isceobj.createCatalog('rtcProc')),
|
|
mandatory=False,
|
|
doc="RtcProc object"
|
|
)
|
|
|
|
|
|
class GRDSAR(Application):
|
|
|
|
family = 'grdsar'
|
|
## Define Class parameters in this list
|
|
parameter_list = (SENSOR_NAME,
|
|
USE_HIGH_RESOLUTION_DEM_ONLY,
|
|
DEM_FILENAME,
|
|
NUMBER_AZIMUTH_LOOKS,
|
|
NUMBER_RANGE_LOOKS,
|
|
POSTING,
|
|
GEOCODE_BOX,
|
|
EPSG,
|
|
GSPACING,
|
|
INTMETHOD,
|
|
PICKLE_DUMPER_DIR,
|
|
PICKLE_LOAD_DIR,
|
|
RENDERER,
|
|
POLARIZATIONS,
|
|
GEOCODE_LIST,
|
|
APPLY_THERMAL_NOISE_CORRECTION)
|
|
|
|
facility_list = (REFERENCE,
|
|
DEM_STITCHER,
|
|
_GRD)
|
|
|
|
_pickleObj = "_grd"
|
|
|
|
def __init__(self, family='', name='',cmdline=None):
|
|
import isceobj
|
|
from isceobj.RtcProc import RtcProc
|
|
from iscesys.StdOEL.StdOELPy import create_writer
|
|
|
|
super().__init__(
|
|
family=family if family else self.__class__.family, name=name,
|
|
cmdline=cmdline)
|
|
|
|
self._stdWriter = create_writer("log", "", True, filename="grdsar.log")
|
|
self._add_methods()
|
|
self._insarProcFact = RtcProc
|
|
return None
|
|
|
|
|
|
|
|
def Usage(self):
|
|
print("Usages: ")
|
|
print("rtcApp.py <input-file.xml>")
|
|
print("rtcApp.py --steps")
|
|
print("rtcApp.py --help")
|
|
print("rtcApp.py --help --steps")
|
|
|
|
|
|
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)
|
|
return None
|
|
|
|
def _configure(self):
|
|
|
|
self.grd.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
|
|
),
|
|
["rtcProc"]
|
|
)
|
|
|
|
if(self.geocode_list is None):
|
|
self.geocode_list = self.grd.geocode_list
|
|
else:
|
|
g_count = 0
|
|
for g in self.geocode_list:
|
|
if g not in self.grd.geocode_list:
|
|
g_count += 1
|
|
#warn if there are any differences in content
|
|
if g_count > 0:
|
|
print()
|
|
logger.warn((
|
|
"Some filenames in rtcApp.geocode_list configuration "+
|
|
"are different from those in rtcProc. Using names given"+
|
|
" to grdApp."))
|
|
print("grdApp.geocode_list = {}".format(self.geocode_list))
|
|
print(("grdProc.geocode_list = {}".format(
|
|
self.grd.geocode_list)))
|
|
|
|
self.grd.geocode_list = self.geocode_list
|
|
|
|
return None
|
|
|
|
@property
|
|
def grd(self):
|
|
return self._grd
|
|
|
|
@grd.setter
|
|
def grd(self, value):
|
|
self._grd = value
|
|
return None
|
|
|
|
@property
|
|
def procDoc(self):
|
|
return self.grd.procDoc
|
|
|
|
@procDoc.setter
|
|
def procDoc(self):
|
|
raise AttributeError(
|
|
"Can not assign to .grd.procDoc-- but you hit all its other stuff"
|
|
)
|
|
|
|
def _finalize(self):
|
|
pass
|
|
|
|
def help(self):
|
|
from isceobj.Sensor.GRD 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
|
|
|
|
|
|
def renderProcDoc(self):
|
|
self.procDoc.renderXml()
|
|
|
|
def startup(self):
|
|
self.help()
|
|
self._grd.timeStart = time.time()
|
|
|
|
def endup(self):
|
|
self.renderProcDoc()
|
|
self._grd.timeEnd = time.time()
|
|
logger.info("Total Time: %i seconds" %
|
|
(self._grd.timeEnd-self._grd.timeStart))
|
|
return None
|
|
|
|
|
|
## Add instance attribute RunWrapper functions, which emulate methods.
|
|
def _add_methods(self):
|
|
self.runPreprocessor = RtcProc.createPreprocessor(self)
|
|
self.verifyDEM = RtcProc.createVerifyDEM(self)
|
|
self.multilook = RtcProc.createLooks(self)
|
|
self.runTopo = RtcProc.createTopo(self)
|
|
self.runNormalize = RtcProc.createNormalize(self)
|
|
self.runGeocode = RtcProc.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=(
|
|
"""Unpack the input data"""
|
|
)
|
|
)
|
|
|
|
# Verify whether the DEM was initialized properly. If not, download
|
|
# a DEM
|
|
self.step('verifyDEM', func=self.verifyDEM)
|
|
|
|
#Multilook product as needed
|
|
self.step('multilook', func=self.multilook)
|
|
|
|
##Run topo for each bursts
|
|
self.step('topo', func=self.runTopo)
|
|
|
|
##Run normalize to get gamma0
|
|
self.step('normalize', func=self.runNormalize)
|
|
|
|
# Geocode
|
|
self.step('geocode', func=self.runGeocode)
|
|
|
|
return None
|
|
|
|
@use_api
|
|
def main(self):
|
|
self.help()
|
|
|
|
timeStart= time.time()
|
|
|
|
# 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()
|
|
|
|
#Multilook as needed
|
|
self.multilook()
|
|
|
|
##Run topo for each burst
|
|
self.runTopo()
|
|
|
|
##Run normalize to get gamma0
|
|
self.runNormalize()
|
|
|
|
# Geocode
|
|
self.runGeocode()
|
|
|
|
timeEnd = time.time()
|
|
logger.info("Total Time: %i seconds" %(timeEnd - timeStart))
|
|
|
|
self.renderProcDoc()
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
grdsar = GRDSAR(name="rtcApp")
|
|
grdsar.configure()
|
|
grdsar.run()
|