1798 lines
54 KiB
Python
Executable File
1798 lines
54 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# Copyright 2013 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: Kosal Khun, Marco Lavalle
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
# adapted from applications/insarApp.py
|
|
# Description: This module generates an application running different steps
|
|
# of SAR, InSAR, PolInSAR and TomoSAR processing.
|
|
|
|
|
|
import time
|
|
import datetime
|
|
import os
|
|
import sys
|
|
import math
|
|
from isce import logging
|
|
|
|
import isce
|
|
import isceobj
|
|
import iscesys
|
|
from iscesys.Component.Application import Application
|
|
from iscesys.Component.Configurable import SELF
|
|
from iscesys.Compatibility import Compatibility
|
|
from iscesys.StdOEL.StdOELPy import create_writer
|
|
#from isceobj import IsceProc
|
|
|
|
from isceobj.Scene.Frame import FrameMixin
|
|
import isceobj.IsceProc as IsceProc
|
|
from isceobj.Location.Peg import Peg
|
|
from isceobj import Unwrap
|
|
from isceobj.Sensor import SENSORS
|
|
from contrib.demUtils.Correct_geoid_i2_srtm import Correct_geoid_i2_srtm
|
|
from pprint import pprint
|
|
|
|
POLS = ['hh', 'hv', 'vh', 'vv'] ##accepted polarizations
|
|
|
|
SENSOR_NAME = Application.Parameter(
|
|
'sensorName',
|
|
public_name='sensor name',
|
|
default=None,
|
|
type=str,
|
|
mandatory=True,
|
|
doc="Sensor name"
|
|
)
|
|
|
|
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'
|
|
)
|
|
|
|
DOPPLER_METHOD = Application.Parameter(
|
|
'dopplerMethod',
|
|
public_name='doppler method',
|
|
default='useDOPIQ',
|
|
type=str,
|
|
mandatory=False,
|
|
doc= (
|
|
"Doppler calculation method.Choices: 'useDOPIQ', 'useCalcDop', \n" +
|
|
"'useDoppler'.")
|
|
)
|
|
|
|
USE_DOP = Application.Parameter(
|
|
'use_dop',
|
|
public_name='use_dop',
|
|
default="average",
|
|
type=float,
|
|
mandatory=False,
|
|
doc=(
|
|
"Choose whether to use scene_sid or average Doppler for\n"+
|
|
"processing, where sid is the scene id to use."
|
|
)
|
|
)
|
|
|
|
USE_HIGH_RESOLUTION_DEM_ONLY = Application.Parameter(
|
|
'useHighResolutionDemOnly',
|
|
public_name='useHighResolutionDemOnly',
|
|
default=False,
|
|
type=bool,
|
|
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"
|
|
)
|
|
|
|
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"
|
|
)
|
|
|
|
AZ_SHIFT = Application.Parameter(
|
|
'azShiftPixels',
|
|
public_name='azimuth shift',
|
|
default=None,
|
|
type=int,
|
|
mandatory=False,
|
|
doc='Number of pixels to shift in azimuth'
|
|
)
|
|
|
|
SLC_RGLOOKS = Application.Parameter(
|
|
'slcRgLooks',
|
|
public_name='slc rangelooks',
|
|
default=1,
|
|
type=int,
|
|
mandatory=False,
|
|
doc="Multilooking factor in range direction for SLCs"
|
|
)
|
|
|
|
SLC_AZLOOKS = Application.Parameter(
|
|
'slcAzLooks',
|
|
public_name='slc azimuthlooks',
|
|
default=1,
|
|
type=int,
|
|
mandatory=False,
|
|
doc="Multilooking factor in azimuth direction for SLCs"
|
|
)
|
|
|
|
SLC_FILTERMETHOD = Application.Parameter(
|
|
'slcFilterMethod',
|
|
public_name='slc filtermethod',
|
|
default='Gaussian',
|
|
type=str,
|
|
mandatory=False,
|
|
doc="Filter method for SLCs: Gaussian, Goldstein, adaptative"
|
|
)
|
|
|
|
SLC_FILTERHEIGHT = Application.Parameter(
|
|
'slcFilterHeight',
|
|
public_name='slc filterheight',
|
|
default=1,
|
|
type=int,
|
|
mandatory=False,
|
|
doc="Window height for SLC filtering"
|
|
)
|
|
|
|
SLC_FILTERWIDTH = Application.Parameter(
|
|
'slcFilterWidth',
|
|
public_name='slc filterwidth',
|
|
default=1,
|
|
type=int,
|
|
mandatory=False,
|
|
doc="Window width for SLC filtering"
|
|
)
|
|
|
|
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")
|
|
)
|
|
|
|
COREG_STRATEGY = Application.Parameter(
|
|
'coregStrategy',
|
|
public_name='coregistration strategy',
|
|
default='single reference',
|
|
type=str,
|
|
mandatory=False,
|
|
doc="How to coregister the stack: single reference or cascade"
|
|
)
|
|
|
|
REF_SCENE = Application.Parameter(
|
|
'refScene',
|
|
public_name='reference scene',
|
|
default=None,
|
|
type=str,
|
|
mandatory=False,
|
|
doc="Scene used as reference if coregistration strategy = single reference"
|
|
)
|
|
|
|
REF_POL = Application.Parameter(
|
|
'refPol',
|
|
public_name='reference polarization',
|
|
default='hh',
|
|
type=str,
|
|
mandatory=False,
|
|
doc=("Polarization used as reference if coregistration strategy = "+
|
|
"single reference. Default: HH"
|
|
)
|
|
)
|
|
|
|
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.")
|
|
)
|
|
|
|
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"
|
|
)
|
|
|
|
NUM_FIT_COEFF = Application.Parameter(
|
|
'numFitCoeff',
|
|
public_name='Number of fit coefficients',
|
|
default=6,
|
|
type=int,
|
|
doc="Number of fit coefficients for offoutliers."
|
|
)
|
|
|
|
RESAMP_RGLOOKS = Application.Parameter(
|
|
'resampRgLooks',
|
|
public_name='resamp range looks',
|
|
default=None,
|
|
type=int,
|
|
mandatory=False,
|
|
doc='Number of range looks to use in resamp'
|
|
)
|
|
|
|
RESAMP_AZLOOKS = Application.Parameter(
|
|
'resampAzLooks',
|
|
public_name='resamp azimuth looks',
|
|
default=None,
|
|
type=int,
|
|
mandatory=False,
|
|
doc='Number of azimuth looks to use in resamp'
|
|
)
|
|
|
|
FR_FILTER = Application.Parameter(
|
|
'FR_filter',
|
|
public_name='FR filter',
|
|
default=None,
|
|
type=str,
|
|
mandatory=False,
|
|
doc='Filter method for FR, if spatial filtering is desired'
|
|
)
|
|
|
|
FR_FILTERSIZE_X = Application.Parameter(
|
|
'FR_filtersize_x',
|
|
public_name='FR filtersize X',
|
|
default=None,
|
|
type=int,
|
|
mandatory=False,
|
|
doc='Filter width for FR'
|
|
)
|
|
|
|
FR_FILTERSIZE_Y = Application.Parameter(
|
|
'FR_filtersize_y',
|
|
public_name='FR filtersize Y',
|
|
default=None,
|
|
type=int,
|
|
mandatory=False,
|
|
doc='Filter height for FR'
|
|
)
|
|
|
|
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"""
|
|
)
|
|
)
|
|
|
|
UNWRAPPER_NAME = Application.Parameter(
|
|
'unwrapper_name',
|
|
public_name='unwrapper name',
|
|
default='',
|
|
type=str,
|
|
mandatory=False,
|
|
doc="Unwrapping method to use. To be used in combination with UNWRAP."
|
|
)
|
|
|
|
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"
|
|
)
|
|
|
|
OUTPUT_DIR = Application.Parameter(
|
|
'outputDir',
|
|
public_name='output directory',
|
|
default='.',
|
|
type=str,
|
|
mandatory=False,
|
|
doc="Output directory, where log files and output files will be dumped."
|
|
)
|
|
|
|
SELECTED_SCENES = Application.Parameter(
|
|
'selectedScenes',
|
|
public_name='selectScenes',
|
|
default=[],
|
|
mandatory=False,
|
|
container=list,
|
|
type=str,
|
|
doc="Comma-separated list of scene ids to process. If not given, process all scenes."
|
|
)
|
|
|
|
SELECTED_PAIRS = Application.Parameter(
|
|
'selectedPairs',
|
|
public_name='selectPairs',
|
|
default=[],
|
|
mandatory=False,
|
|
container=list,
|
|
type=str,
|
|
doc=("Comma-separated list of pairs to process. Pairs are in the form sid1-sid2. "+
|
|
"If not given, process all possible pairs."
|
|
)
|
|
)
|
|
|
|
SELECTED_POLS = Application.Parameter(
|
|
'selectedPols',
|
|
public_name='selectPols',
|
|
default=[],
|
|
mandatory=False,
|
|
container=list,
|
|
type=str,
|
|
doc=("Comma-separated list of polarizations to process. "+
|
|
"If not given, process all polarizations."
|
|
)
|
|
)
|
|
|
|
DO_PREPROCESS = Application.Parameter(
|
|
'do_preprocess',
|
|
public_name='do preprocess',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if preprocessor is desired."
|
|
)
|
|
|
|
DO_VERIFY_DEM = Application.Parameter(
|
|
'do_verifyDEM',
|
|
public_name='do verifyDEM',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if verify DEM is desired. If DEM not given, download DEM."
|
|
)
|
|
|
|
DO_PULSETIMING = Application.Parameter(
|
|
'do_pulsetiming',
|
|
public_name='do pulsetiming',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if running pulsetiming is desired."
|
|
)
|
|
|
|
DO_ESTIMATE_HEIGHTS = Application.Parameter(
|
|
'do_estimateheights',
|
|
public_name='do estimateheights',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if estimating heights is desired."
|
|
)
|
|
|
|
DO_SET_MOCOMPPATH = Application.Parameter(
|
|
'do_mocomppath',
|
|
public_name='do mocomppath',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if setting mocomppath is desired."
|
|
)
|
|
|
|
DO_ORBIT2SCH = Application.Parameter(
|
|
'do_orbit2sch',
|
|
public_name='do orbit2sch',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if converting orbit to SCH is desired."
|
|
)
|
|
|
|
DO_UPDATE_PREPROCINFO = Application.Parameter(
|
|
'do_updatepreprocinfo',
|
|
public_name='do updatepreprocinfo',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if updating info is desired."
|
|
)
|
|
|
|
DO_FORM_SLC = Application.Parameter(
|
|
'do_formslc',
|
|
public_name='do formslc',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if form_slc is desired."
|
|
)
|
|
|
|
DO_MULTILOOK_SLC = Application.Parameter(
|
|
'do_multilookslc',
|
|
public_name='do multilookslc',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if slc multilooking is desired."
|
|
)
|
|
|
|
DO_FILTER_SLC = Application.Parameter(
|
|
'do_filterslc',
|
|
public_name='do filterslc',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if slc filtering is desired."
|
|
)
|
|
|
|
DO_GEOCODE_SLC = Application.Parameter(
|
|
'do_geocodeslc',
|
|
public_name='do geocodeslc',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if slc geocoding is desired."
|
|
)
|
|
|
|
DO_OFFSETPRF = Application.Parameter(
|
|
'do_offsetprf',
|
|
public_name='do offsetprf',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if running offsetprf is desired."
|
|
)
|
|
|
|
DO_OUTLIERS1 = Application.Parameter(
|
|
'do_outliers1',
|
|
public_name='do outliers1',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if running outliers is desired."
|
|
)
|
|
|
|
DO_PREPARE_RESAMPS = Application.Parameter(
|
|
'do_prepareresamps',
|
|
public_name='do prepareresamps',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if preparing resamps is desired."
|
|
)
|
|
|
|
DO_RESAMP = Application.Parameter(
|
|
'do_resamp',
|
|
public_name='do resamp',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if outputting of resampled slc is desired."
|
|
)
|
|
|
|
DO_RESAMP_IMAGE = Application.Parameter(
|
|
'do_resamp_image',
|
|
public_name='do resamp image',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if outputting of offset images is desired."
|
|
)
|
|
|
|
DO_POL_CORRECTION = Application.Parameter(
|
|
'do_pol_correction',
|
|
public_name='do polarimetric correction',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc='True if polarimetric correction is desired.'
|
|
)
|
|
|
|
DO_POL_PREPROCESS = Application.Parameter(
|
|
'do_preprocess',
|
|
public_name='do preprocess',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if preprocessor is desired."
|
|
)
|
|
|
|
DO_POL_FR = Application.Parameter(
|
|
'do_pol_fr',
|
|
public_name='do calculate FR',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc='True if calculating Faraday Rotation is desired.'
|
|
)
|
|
|
|
DO_POL_TEC = Application.Parameter(
|
|
'do_pol_tec',
|
|
public_name='do FR to TEC',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc='True if converting FR to TEC is desired.'
|
|
)
|
|
|
|
DO_POL_PHASE = Application.Parameter(
|
|
'do_pol_phase',
|
|
public_name='do TEC to phase',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc='True if converting TEC to phase is desired.'
|
|
)
|
|
|
|
DO_CROSSMUL = Application.Parameter(
|
|
'do_crossmul',
|
|
public_name='do crossmul',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if crossmultiplication is desired."
|
|
)
|
|
|
|
DO_MOCOMP_BASELINE = Application.Parameter(
|
|
'do_mocompbaseline',
|
|
public_name='do mocomp baseline',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if estimating mocomp baseline is desired."
|
|
)
|
|
|
|
DO_SET_TOPOINT1 = Application.Parameter(
|
|
'do_settopoint1',
|
|
public_name='do set topoint1',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if setting toppoint1 is desired."
|
|
)
|
|
|
|
DO_TOPO = Application.Parameter(
|
|
'do_topo',
|
|
public_name='do topo',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if estimating topography is desired."
|
|
)
|
|
|
|
DO_SHADE_CPX2RG = Application.Parameter(
|
|
'do_shadecpx2rg',
|
|
public_name='do shadecpx2rg',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if shadecpx2rg is desired."
|
|
)
|
|
|
|
DO_RG_OFFSET = Application.Parameter(
|
|
'do_rgoffset',
|
|
public_name='do rgoffset',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if rgoffset is desired."
|
|
)
|
|
|
|
DO_RG_OUTLIERS2 = Application.Parameter(
|
|
'do_rg_outliers2',
|
|
public_name='do rg outliers2',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if rg outliers2 is desired."
|
|
)
|
|
|
|
DO_RESAMP_ONLY = Application.Parameter(
|
|
'do_resamp_only',
|
|
public_name='do resamp only',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if resample only is desired."
|
|
)
|
|
|
|
DO_SET_TOPOINT2 = Application.Parameter(
|
|
'do_settopoint2',
|
|
public_name='do set topoint2',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if setting topoint2 is desired."
|
|
)
|
|
|
|
DO_CORRECT = Application.Parameter(
|
|
'do_correct',
|
|
public_name='do correct',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if correcting image is desired."
|
|
)
|
|
|
|
DO_COHERENCE = Application.Parameter(
|
|
'do_coherence',
|
|
public_name='do coherence',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if coherence estimation is desired."
|
|
)
|
|
|
|
DO_FILTER_INF = Application.Parameter(
|
|
'do_filterinf',
|
|
public_name='do filter interferogram',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if interferogram filtering is desired."
|
|
)
|
|
|
|
DO_UNWRAP = Application.Parameter(
|
|
'do_unwrap',
|
|
public_name='do unwrap',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if unwrapping is desired. To be used in combination with UNWRAPPER_NAME."
|
|
)
|
|
|
|
DO_GEOCODE_INF = Application.Parameter(
|
|
'do_geocodeinf',
|
|
public_name='do geocode interferogram',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if interferogram filtering is desired."
|
|
)
|
|
|
|
DO_GEOCODE = Application.Parameter(
|
|
'do_geocode',
|
|
public_name='do geocode',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
doc="True if interferogram filtering is desired."
|
|
)
|
|
|
|
RENDERER = Application.Parameter(
|
|
'renderer',
|
|
public_name='renderer',
|
|
default='pickle',
|
|
type=str,
|
|
mandatory=True,
|
|
doc=(
|
|
"Format in which the data is serialized when using steps. Options are xml (default) or pickle."
|
|
)
|
|
)
|
|
|
|
_ISCE = Application.Facility(
|
|
'_isce',
|
|
public_name='isceproc',
|
|
module='isceobj.IsceProc',
|
|
factory='createIsceProc',
|
|
args = ('isceAppContext', isceobj.createCatalog('isceProc')),
|
|
mandatory=False,
|
|
doc="IsceProc object"
|
|
)
|
|
|
|
STACK = Application.Facility(
|
|
'stack',
|
|
public_name='Stack',
|
|
module='isceobj.Stack',
|
|
factory='createStack',
|
|
mandatory=True,
|
|
doc="Stack component with a list of scenes."
|
|
)
|
|
|
|
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_FORM_SLC = Application.Facility(
|
|
'runFormSLC',
|
|
public_name='Form SLC',
|
|
module='isceobj.IsceProc',
|
|
factory='createFormSLC',
|
|
args=(SELF(), DO_FORM_SLC, SENSOR_NAME),
|
|
mandatory=False,
|
|
doc="SLC formation module"
|
|
)
|
|
|
|
RUN_UPDATE_PREPROC_INFO = Application.Facility(
|
|
'runUpdatePreprocInfo',
|
|
public_name='preproc info updater',
|
|
module='isceobj.IsceProc',
|
|
factory='createUpdatePreprocInfo',
|
|
args=(SELF(), DO_UPDATE_PREPROCINFO, SENSOR_NAME),
|
|
mandatory=False,
|
|
doc="update preproc info module"
|
|
)
|
|
|
|
RUN_OFFSETPRF = Application.Facility(
|
|
'runOffsetprf',
|
|
public_name='slc offsetter',
|
|
module='isceobj.IsceProc',
|
|
factory='createOffsetprf',
|
|
args=(SELF(), DO_OFFSETPRF, OFFSET_METHOD),
|
|
mandatory=False,
|
|
doc="Offset a pair of SLC images."
|
|
)
|
|
|
|
RUN_ESTIMATE_HEIGHTS = Application.Facility(
|
|
'runEstimateHeights',
|
|
public_name='Estimate Heights',
|
|
module='isceobj.IsceProc',
|
|
factory='createEstimateHeights',
|
|
args=(SELF(), DO_ESTIMATE_HEIGHTS, SENSOR_NAME),
|
|
mandatory=False,
|
|
doc="mocomp height estimation module"
|
|
)
|
|
|
|
RUN_SET_MOCOMP_PATH = Application.Facility(
|
|
'runSetmocomppath',
|
|
public_name='set mocomp path',
|
|
module='isceobj.IsceProc',
|
|
factory='createSetmocomppath',
|
|
args=(SELF(), DO_SET_MOCOMPPATH, SENSOR_NAME),
|
|
mandatory=False,
|
|
doc="mocomp set mocomp path module"
|
|
)
|
|
|
|
RUN_RG_OFFSET = Application.Facility(
|
|
'runRgoffset',
|
|
public_name='rg offsetter',
|
|
module='isceobj.IsceProc',
|
|
factory='createRgoffset',
|
|
args=(SELF(), DO_RG_OFFSET, OFFSET_METHOD),
|
|
mandatory=False,
|
|
doc="mocomp dem offsetter module"
|
|
)
|
|
|
|
RUN_UNWRAPPER = Application.Facility(
|
|
'runUnwrapper',
|
|
public_name='Run unwrapper',
|
|
module='isceobj.IsceProc',
|
|
factory='createUnwrapper',
|
|
args=(SELF(), DO_UNWRAP, UNWRAPPER_NAME,),
|
|
mandatory=False,
|
|
doc="Unwrapping module"
|
|
)
|
|
|
|
class IsceApp(Application, FrameMixin):
|
|
"""
|
|
This class represents the application that reads the input xml file and runs the various processing steps accordingly.
|
|
"""
|
|
|
|
family = "isce" #ML 2014-03-25
|
|
|
|
## Define Class parameters in this list
|
|
parameter_list = (SENSOR_NAME,
|
|
PEG_LAT,
|
|
PEG_LON,
|
|
PEG_HDG,
|
|
PEG_RAD,
|
|
DOPPLER_METHOD,
|
|
USE_DOP,
|
|
USE_HIGH_RESOLUTION_DEM_ONLY,
|
|
DEM_FILENAME,
|
|
GEO_POSTING,
|
|
POSTING,
|
|
PATCH_SIZE,
|
|
GOOD_LINES,
|
|
NUM_PATCHES,
|
|
AZ_SHIFT,
|
|
SLC_RGLOOKS,
|
|
SLC_AZLOOKS,
|
|
SLC_FILTERMETHOD,
|
|
SLC_FILTERHEIGHT,
|
|
SLC_FILTERWIDTH,
|
|
OFFSET_METHOD,
|
|
COREG_STRATEGY,
|
|
REF_SCENE,
|
|
REF_POL,
|
|
OFFSET_SEARCH_WINDOW_SIZE,
|
|
GROSS_AZ,
|
|
GROSS_RG,
|
|
CULLING_SEQUENCE,
|
|
NUM_FIT_COEFF,
|
|
RESAMP_RGLOOKS,
|
|
RESAMP_AZLOOKS,
|
|
FR_FILTER,
|
|
FR_FILTERSIZE_X,
|
|
FR_FILTERSIZE_Y,
|
|
CORRELATION_METHOD,
|
|
FILTER_STRENGTH,
|
|
UNWRAPPER_NAME,
|
|
GEOCODE_LIST,
|
|
GEOCODE_BOX,
|
|
PICKLE_DUMPER_DIR,
|
|
PICKLE_LOAD_DIR,
|
|
OUTPUT_DIR,
|
|
SELECTED_SCENES,
|
|
SELECTED_PAIRS,
|
|
SELECTED_POLS,
|
|
DO_PREPROCESS,
|
|
DO_VERIFY_DEM,
|
|
DO_PULSETIMING,
|
|
DO_ESTIMATE_HEIGHTS,
|
|
DO_SET_MOCOMPPATH,
|
|
DO_ORBIT2SCH,
|
|
DO_UPDATE_PREPROCINFO,
|
|
DO_FORM_SLC,
|
|
DO_MULTILOOK_SLC,
|
|
DO_FILTER_SLC,
|
|
DO_GEOCODE_SLC,
|
|
DO_OFFSETPRF,
|
|
DO_OUTLIERS1,
|
|
DO_PREPARE_RESAMPS,
|
|
DO_RESAMP,
|
|
DO_RESAMP_IMAGE,
|
|
DO_POL_CORRECTION,
|
|
DO_POL_FR,
|
|
DO_POL_TEC,
|
|
DO_POL_PHASE,
|
|
DO_CROSSMUL, #2013-11-26
|
|
DO_MOCOMP_BASELINE,
|
|
DO_SET_TOPOINT1,
|
|
DO_TOPO,
|
|
DO_SHADE_CPX2RG,
|
|
DO_RG_OFFSET,
|
|
DO_RG_OUTLIERS2,
|
|
DO_RESAMP_ONLY,
|
|
DO_SET_TOPOINT2,
|
|
DO_CORRECT,
|
|
DO_COHERENCE,
|
|
DO_FILTER_INF,
|
|
DO_UNWRAP,
|
|
DO_GEOCODE_INF,
|
|
DO_GEOCODE,
|
|
RENDERER)
|
|
|
|
facility_list = (STACK,
|
|
DEM,
|
|
DEM_STITCHER,
|
|
RUN_UPDATE_PREPROC_INFO,
|
|
RUN_ESTIMATE_HEIGHTS,
|
|
RUN_SET_MOCOMP_PATH,
|
|
RUN_RG_OFFSET,
|
|
RUN_FORM_SLC,
|
|
RUN_OFFSETPRF,
|
|
RUN_UNWRAPPER,
|
|
_ISCE)
|
|
|
|
_pickleObj = "_isce"
|
|
|
|
def Usage(self):
|
|
print("Usage: isceApp.py <input-file.xml> [options]")
|
|
print("Options:")
|
|
print("None\t\tRun isceApp.py from start to end without pickling")
|
|
print("--help\t\tDisplay configurable parameters and facilities that can be specified in <input-file.xml>")
|
|
print("--help --steps\tDisplay list of available steps according to <input-file.xml>")
|
|
print("--steps\t\tRun isceApp.py from start to end and pickle at each step")
|
|
|
|
|
|
def __init__(self, family='',name='',cmdline=None):
|
|
"""
|
|
Initialize the application: read the xml file and prepare the application.
|
|
"""
|
|
super().__init__(family=family if family else self.__class__.family, name=name,cmdline=cmdline)
|
|
|
|
#store the processing start time
|
|
now = datetime.datetime.now()
|
|
|
|
self._stdWriter = create_writer("log", "", True, filename="isce.log")
|
|
self._add_methods()
|
|
from isceobj.IsceProc import IsceProc
|
|
self._insarProcFact = IsceProc
|
|
self.pairsToCoreg = [] ##pairs to coregister
|
|
self.intromsg = '' ##intro message
|
|
self.peg = None
|
|
|
|
|
|
## You need this to use the FrameMixin
|
|
@property
|
|
def frame(self):
|
|
return self.isce.frame
|
|
|
|
|
|
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)
|
|
)
|
|
self.intromsg = message
|
|
|
|
print(message)
|
|
if ( self.pegLat is not None
|
|
and self.pegLon is not None
|
|
and self.pegHdg is not None
|
|
and self.pegRad is not None ):
|
|
self.peg = Peg(latitude=self.pegLat,
|
|
longitude=self.pegLon,
|
|
heading=self.pegHdg,
|
|
radiusOfCurvature=self.pegRad)
|
|
#for attribute in ["sensorName", "correlation_method", "use_dop", "geoPosting", "posting", "resampRgLooks", "resampAzLooks", "offsetMethod", "peg"]:
|
|
# print("%s = %s" % (attribute, getattr(self, attribute)))
|
|
|
|
def _configure(self):
|
|
|
|
self.isce.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
|
|
),
|
|
["isceProc"]
|
|
)
|
|
#This method includes logger support
|
|
self.verifyOutput()
|
|
#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.
|
|
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()
|
|
self.demFilename = "demFilename"
|
|
self._isce.demImage = self.dem
|
|
except Exception as err:
|
|
pass
|
|
#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')
|
|
self.geocode_bbox[0] = dem_snwe[0]
|
|
|
|
if self.geocode_bbox[1] > dem_snwe[1]:
|
|
logger.warning('Geocoding northern extent changed to match DEM')
|
|
self.geocode_bbox[1] = dem_snwe[1]
|
|
|
|
if self.geocode_bbox[2] < dem_snwe[2]:
|
|
logger.warning('Geocoding western extent changed to match DEM')
|
|
self.geocode_bbox[2] = dem_snwe[2]
|
|
|
|
if self.geocode_bbox[3] > dem_snwe[3]:
|
|
logger.warning('Geocoding eastern extent changed to match DEM')
|
|
self.geocode_bbox[3] = dem_snwe[3]
|
|
|
|
#Ensure consistency in geocode_list maintained by isceApp and
|
|
#IsceProc. If it is configured in both places, the one in isceApp
|
|
#will be used. It is complicated to try to merge the two lists
|
|
#because IsceProc 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 isceApp 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 IsceProc
|
|
self.geocode_list = self._isce.geocode_list
|
|
else:
|
|
#if geocode_list defined here, then give it to IsceProc
|
|
#for consistency between isceApp and IsceProc 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._isce.geocode_list:
|
|
g_count += 1
|
|
#warn if there are any differences in content
|
|
if g_count > 0:
|
|
print()
|
|
logger.warn((
|
|
"Some filenames in isceApp.geocode_list configuration "+
|
|
"are different from those in IsceProc. Using names given"+
|
|
" to isceApp."))
|
|
print("isceApp.geocode_list = {}".format(self.geocode_list))
|
|
print(("IsceProc.geocode_list = {}".format(
|
|
self._isce.geocode_list)))
|
|
|
|
self._isce.geocode_list = self.geocode_list
|
|
|
|
return None
|
|
|
|
|
|
@property
|
|
def isce(self):
|
|
return self._isce
|
|
@isce.setter
|
|
def isce(self, value):
|
|
self._isce = value
|
|
|
|
@property
|
|
def procDoc(self):
|
|
return self._isce.procDoc
|
|
@procDoc.setter
|
|
def procDoc(self):
|
|
raise AttributeError(
|
|
"Can not assign to .isce.procDoc-- but you hit all its other stuff"
|
|
)
|
|
|
|
def _finalize(self):
|
|
pass
|
|
|
|
|
|
def help(self):
|
|
print(self.__doc__)
|
|
lsensors = list(SENSORS.keys())
|
|
lsensors.sort()
|
|
print("The currently supported sensors are: ", lsensors)
|
|
|
|
|
|
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")
|
|
|
|
|
|
def formatAttributes(self):
|
|
self.sensorName = self.sensorName.upper()
|
|
if not self.dopplerMethod.startswith('use'):
|
|
self.dopplerMethod = 'use' + self.dopplerMethod
|
|
self.selectedPols = list(map(str.lower, self.selectedPols))
|
|
|
|
|
|
def prepareStack(self):
|
|
"""
|
|
Populate stack with user data and prepare to run.
|
|
"""
|
|
##Get all scenes as given in xml file
|
|
sceneids = []
|
|
allscenes = []
|
|
scenekeys = []
|
|
for i in range(100):
|
|
try:
|
|
scene = getattr(self.stack, 'scene'+str(i))
|
|
except AttributeError:
|
|
pass
|
|
else:
|
|
if scene:
|
|
sceneids.append(scene['id'])
|
|
allscenes.append(scene)
|
|
scenekeys.extend(scene.keys())
|
|
unique_scenekeys = set(scenekeys)
|
|
sels = []
|
|
for scene in self.selectedScenes:
|
|
pairs = scene.split('-')
|
|
if len(pairs) == 1:
|
|
sid = pairs[0]
|
|
try:
|
|
idx = sceneids.index(sid)
|
|
except ValueError:
|
|
sys.exit("Scene id '%s' is not in list of scenes." % sid)
|
|
else:
|
|
sels.append(sid)
|
|
elif len(pairs) == 2:
|
|
sid1 = pairs[0].strip()
|
|
sid2 = pairs[1].strip()
|
|
try:
|
|
idx1 = sceneids.index(sid1)
|
|
idx2 = sceneids.index(sid2)
|
|
except ValueError as e:
|
|
print(e)
|
|
print(sceneids)
|
|
sys.exit(1)
|
|
else:
|
|
first = min(idx1, idx2)
|
|
last = max(idx1, idx2)
|
|
for i in range(first, last+1):
|
|
sels.append(sceneids[i])
|
|
else:
|
|
sys.exit("Unknow value '%s' in selected scenes." % scene)
|
|
|
|
# make sure that we have unique selected scenes ordered by their scene number
|
|
self.selectedScenes = [ s for s in sceneids if s in sels ]
|
|
if not self.selectedScenes: ##no scenes selected: process all scenes
|
|
self.selectedScenes = sceneids
|
|
for sceneid in self.selectedScenes:
|
|
idx = sceneids.index(sceneid)
|
|
scene = allscenes[idx]
|
|
self.stack.addscene(scene)
|
|
outdir = self.getoutputdir(sceneid)
|
|
if not os.path.exists(outdir):
|
|
os.mkdir(outdir)
|
|
|
|
sels = []
|
|
if not self.selectedPols: ##empty pols
|
|
self.selectedPols = list(POLS) ##select all pols
|
|
for pol in self.selectedPols:
|
|
if pol in POLS:
|
|
if pol in unique_scenekeys: ##the selected pols might not be in the givenkeys
|
|
sels.append(pol)
|
|
else:
|
|
sys.exit("Polarization '%s' is not in accepted list." % pol)
|
|
if not sels:
|
|
sys.exit("Make sure that all scenes have at least one accepted polarization: %s" % ', '.join(POLS))
|
|
|
|
# make sure that we have unique selected pols in the same order as in POLS
|
|
self.selectedPols = [ p for p in POLS if p in sels ]
|
|
|
|
selPairs = []
|
|
for pair in self.selectedPairs:
|
|
try:
|
|
scene1, scene2 = map(str.strip, pair.split('/')) # assume that it's a pair scene1/scene2
|
|
if scene1 in self.selectedScenes and scene2 in self.selectedScenes:
|
|
selPairs.append( (scene1, scene2) )
|
|
except ValueError: # not p1/p2
|
|
try:
|
|
sid1, sid2 = map(str.strip, pair.split('-')) # assume that it's a range first-last
|
|
idx1 = sceneids.index(sid1)
|
|
idx2 = sceneids.index(sid2)
|
|
first = min(idx1, idx2)
|
|
last = max(idx1, idx2)
|
|
for i in range(first, last):
|
|
for j in range(i + 1, last + 1): #KK 2013-12-17
|
|
selPairs.append( (sceneids[i], sceneids[j]) )
|
|
except ValueError: # unknown format
|
|
sys.exit("Unknow format in <selectPairs>: %s" % pair)
|
|
|
|
#keep unique values.
|
|
#pairs like (scene1, scene2) and (scene2, scene1) are considered different here
|
|
#they will be processed as different pairs for now;
|
|
#we might need to check that and remove one of the pairs (to be done)
|
|
self.selectedPairs = list(set(selPairs))
|
|
|
|
if not self.selectedPairs: ##empty value
|
|
self.selectedPairs = []
|
|
nbscenes = len(self.selectedScenes)
|
|
for i in range(nbscenes):
|
|
for j in range(i+1, nbscenes):
|
|
self.selectedPairs.append((self.selectedScenes[i], self.selectedScenes[j]))
|
|
|
|
if self.refPol not in self.selectedPols:
|
|
self.refPol = self.selectedPols[0] # get first selected polarization
|
|
if self.refScene not in self.selectedScenes:
|
|
self.refScene = self.selectedScenes[0] # get first selected scene
|
|
|
|
if self.do_offsetprf or not self.do_offsetprf:
|
|
#list of scenes that compose selected pairs
|
|
scenesInPairs = []
|
|
for pair in self.selectedPairs:
|
|
#add scene1 and scene2 to list
|
|
scenesInPairs.extend(pair)
|
|
#keep unique values
|
|
scenesInPairs = list(set(scenesInPairs))
|
|
#order scenes by their scene number
|
|
orderedScenesInPairs = [ s for s in self.selectedScenes if s in scenesInPairs ]
|
|
|
|
if self.coregStrategy == 'single reference':
|
|
for scene in orderedScenesInPairs:
|
|
self.pairsToCoreg.append( (self.refScene, scene) )
|
|
if (self.refScene, self.refScene) in self.pairsToCoreg:
|
|
self.pairsToCoreg.remove( (self.refScene, self.refScene) )
|
|
elif self.coregStrategy == 'cascade':
|
|
for i in range(len(orderedScenesInPairs)-1):
|
|
self.pairsToCoreg.append((orderedScenesInPairs[i], orderedScenesInPairs[i+1]))
|
|
else:
|
|
sys.exit("Unknown coregistration strategy in runOffsetprf", self.coregStrategy)
|
|
|
|
# creating output directories according to selectedPairs and pairsToCoreg
|
|
#copy pairsToCoreg
|
|
outputPairs = list(self.pairsToCoreg)
|
|
for (p1, p2) in self.selectedPairs:
|
|
#(p2, p1) might be already in pairsToCoreg but we consider them as different pairs
|
|
if (p1, p2) not in self.pairsToCoreg:
|
|
outputPairs.append((p1, p2))
|
|
for (p1, p2) in outputPairs:
|
|
outdir = self.getoutputdir(p1, p2)
|
|
if not os.path.exists(outdir):
|
|
os.mkdir(outdir)
|
|
|
|
self._isce.selectedPols = self.selectedPols
|
|
self._isce.selectedScenes = self.selectedScenes
|
|
self._isce.selectedPairs = self.selectedPairs
|
|
self._isce.coregStrategy = self.coregStrategy
|
|
self._isce.refScene = self.refScene
|
|
self._isce.refPol = self.refPol
|
|
self._isce.pairsToCoreg = self.pairsToCoreg
|
|
self._isce.srcFiles = self.stack.getscenes()
|
|
|
|
def getoutputdir(self, sid1, sid2=''):
|
|
"""
|
|
Return output directory for scene sid1.
|
|
If sid2 is given, return output directory for pair sid1__sid2.
|
|
"""
|
|
if sid2:
|
|
outdir = '%s__%s' % (sid1, sid2)
|
|
else:
|
|
outdir = sid1
|
|
return os.path.join(self.outputDir, outdir)
|
|
|
|
|
|
def verifyOutput(self):
|
|
"""
|
|
Check that output directory exists and instantiate logger.
|
|
"""
|
|
global logger
|
|
if not os.path.isdir(self.outputDir):
|
|
sys.exit("Could not find the output directory: %s" % self.outputDir)
|
|
os.chdir(self.outputDir) ##change working directory to given output directory
|
|
|
|
logger = logging.getLogger('isce.isceProc')
|
|
logger.info(self.intromsg)
|
|
self._isce.dataDirectory = self.outputDir
|
|
self._isce.processingDirectory = self.outputDir
|
|
|
|
|
|
## Method return True iff it changes the demFilename.
|
|
from isceobj.Util.decorators import use_api
|
|
@use_api
|
|
def verifyDEM(self):
|
|
#if an image has been specified, then no need to create one
|
|
if not self.dem.filename:
|
|
#the following lines should be included in the check on demFilename
|
|
frames = self._isce.getAllFromPol(self._isce.refPol, self._isce.frames)
|
|
info = self.extractInfo(frames)
|
|
self.createDem(info)
|
|
else:
|
|
self._isce.demImage = self.dem
|
|
#ensure that the dem vrt file exists by creating (or recreating) it
|
|
self._isce.demImage.renderVRT()
|
|
|
|
#at this point a dem image has been set into self._isce, whether it
|
|
#was sitched together or read in input
|
|
demImage = self._isce.demImage
|
|
#if the demImage is already in wgs84 (because was provided in input) then skip and proceed
|
|
if demImage.reference.upper() != 'WGS84':
|
|
wgs84demFilename = self._isce.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._isce.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._isce.demImage = createDemImage()
|
|
self._isce.demImage.load(wgs84demxmlFilename)
|
|
if(self._isce.demImage.reference.upper() != 'WGS84'):
|
|
print('The dem',wgs84demFilename,'is not wgs84')
|
|
raise Exception
|
|
#ensure that the wgs84 dem vrt file exists
|
|
self._isce.demImage.renderVRT()
|
|
|
|
#get water mask
|
|
#self.runCreateWbdMask(info)
|
|
|
|
return None
|
|
|
|
def renderProcDoc(self):
|
|
self._isce.procDoc.renderXml()
|
|
|
|
|
|
## Run Offoutliers() repeatedly with arguments from "iterator" keyword
|
|
def iterate_runOffoutliers(self, iterator=None):
|
|
"""
|
|
runs runOffoutliers multiple times with values (integers) from iterator.
|
|
iterator defaults to Stack._default_culling_sequence
|
|
"""
|
|
if iterator is None:
|
|
iterator = self.culling_sequence
|
|
map(self.runOffoutliers, iterator)
|
|
|
|
|
|
def set_topoint1(self):
|
|
self._isce.topoIntImages = dict(self._isce.resampIntImages)
|
|
|
|
|
|
def set_topoint2(self):
|
|
self._isce.topoIntImages = dict(self._isce.resampOnlyImages)
|
|
|
|
|
|
def startup(self):
|
|
self.help()
|
|
self.formatAttributes()
|
|
self.prepareStack()
|
|
self.timeStart = time.time()
|
|
|
|
|
|
def endup(self):
|
|
self.renderProcDoc()
|
|
|
|
## Add instance attribute RunWrapper functions, which emulate methods.
|
|
def _add_methods(self):
|
|
self.runPreprocessor = IsceProc.createPreprocessor(self)
|
|
self.extractInfo = IsceProc.createExtractInfo(self)
|
|
self.createDem = IsceProc.createCreateDem(self)
|
|
self.runPulseTiming = IsceProc.createPulseTiming(self)
|
|
self.runOrbit2sch = IsceProc.createOrbit2sch(self)
|
|
self.updatePreprocInfo = IsceProc.createUpdatePreprocInfo(self)
|
|
self.runOffoutliers = IsceProc.createOffoutliers(self)
|
|
self.prepareResamps = IsceProc.createPrepareResamps(self)
|
|
self.runResamp = IsceProc.createResamp(self)
|
|
self.runResamp_image = IsceProc.createResamp_image(self)
|
|
self.runISSI = IsceProc.createISSI(self)
|
|
self.runCrossmul = IsceProc.createCrossmul(self) #2013-11-26
|
|
self.runMocompbaseline = IsceProc.createMocompbaseline(self)
|
|
self.runTopo = IsceProc.createTopo(self)
|
|
self.runCorrect = IsceProc.createCorrect(self)
|
|
self.runShadecpx2rg = IsceProc.createShadecpx2rg(self)
|
|
self.runResamp_only = IsceProc.createResamp_only(self)
|
|
self.runCoherence = IsceProc.createCoherence(self)
|
|
self.runFilter = IsceProc.createFilter(self)
|
|
self.runGrass = IsceProc.createGrass(self)
|
|
self.runGeocode = IsceProc.createGeocode(self)
|
|
|
|
|
|
def _steps(self):
|
|
self.step('startup', func=self.startup,
|
|
doc="Print a helpful message and set the startTime of processing",
|
|
dostep=True)
|
|
|
|
# Run a preprocessor for the sets of frames
|
|
self.step('preprocess', func=self.runPreprocessor,
|
|
doc="Preprocess scenes to raw images", dostep=self.do_preprocess)
|
|
|
|
# Verify whether the DEM was initialized properly. If not, download a DEM
|
|
self.step('verifyDEM', func=self.verifyDEM, dostep=self.do_verifyDEM)
|
|
|
|
# Run pulsetiming for each set of frames
|
|
self.step('pulsetiming', func=self.runPulseTiming, dostep=self.do_pulsetiming)
|
|
|
|
# Estimate heights
|
|
self.step('estimateHeights', func=self.runEstimateHeights, dostep=self.do_estimateheights)
|
|
|
|
# Run setmocomppath
|
|
self.step('mocompath', func=self.runSetmocomppath, args=(self.peg,),
|
|
dostep=self.do_mocomppath)
|
|
|
|
#init and run orbit2sch
|
|
self.step('orbit2sch', func=self.runOrbit2sch, dostep=self.do_orbit2sch)
|
|
|
|
#update quantities in objPreProc obtained from previous steps
|
|
self.step('updatepreprocinfo', func=self.updatePreprocInfo,
|
|
args=(self.use_dop,), dostep=self.do_updatepreprocinfo)
|
|
|
|
#form the single look complex image
|
|
self.step('formslc', func=self.runFormSLC, dostep=self.do_formslc)
|
|
|
|
#Get the list of polarimetric operations to be performed
|
|
polopList = []
|
|
if self.do_pol_correction:
|
|
polopList.append('polcal')
|
|
if self.do_pol_fr:
|
|
polopList.append('fr')
|
|
if self.do_pol_tec:
|
|
polopList.append('tec')
|
|
if self.do_pol_phase:
|
|
polopList.append('phase')
|
|
self.do_pol_correction = True if polopList else False
|
|
|
|
# run polarimetric correction if polopList is not empty
|
|
self.step('pol_correction', func=self.runISSI, args=(polopList,), dostep=self.do_pol_correction)
|
|
|
|
self.step('offsetprf', func=self.runOffsetprf, dostep=self.do_offsetprf)
|
|
|
|
# cull offoutliers
|
|
self.step('outliers1', func=self.iterate_runOffoutliers,
|
|
dostep=self.do_outliers1)
|
|
|
|
# determine rg and az looks
|
|
self.step('prepareresamps', func=self.prepareResamps,
|
|
args=(self.resampRgLooks, self.resampAzLooks),
|
|
dostep=self.do_prepareresamps)
|
|
|
|
# output resampled slc (skip int and amp files)
|
|
self.step('resamp', func=self.runResamp, dostep=self.do_resamp)
|
|
|
|
# output images of offsets
|
|
self.step('resamp_image', func=self.runResamp_image,
|
|
dostep=self.do_resamp_image)
|
|
|
|
# run crossmultiplication (output int and amp)
|
|
self.step('crossmul', func=self.runCrossmul, dostep=self.do_crossmul)
|
|
|
|
# mocompbaseline
|
|
self.step('mocompbaseline', func=self.runMocompbaseline,
|
|
dostep=self.do_mocompbaseline)
|
|
|
|
# assign resampIntImage to topoIntImage
|
|
self.step('settopoint1', func=self.set_topoint1,
|
|
dostep=self.do_settopoint1)
|
|
|
|
self.step('topo', func=self.runTopo, dostep=self.do_topo)
|
|
|
|
self.step('shadecpx2rg', func=self.runShadecpx2rg,
|
|
dostep=self.do_shadecpx2rg)
|
|
|
|
# compute offsets and cull offoutliers
|
|
self.step('rgoffset', func=self.runRgoffset, dostep=True)
|
|
|
|
self.step('rg_outliers2', func=self.iterate_runOffoutliers,
|
|
dostep=self.do_rg_outliers2)
|
|
|
|
self.step('resamp_only', func=self.runResamp_only, dostep=self.do_resamp_only)
|
|
|
|
# assign resampOnlyImage to topoIntImage
|
|
self.step('settopoint2', func=self.set_topoint2, dostep=self.do_settopoint2)
|
|
|
|
self.step('correct', func=self.runCorrect, dostep=self.do_correct)
|
|
|
|
# coherence
|
|
self.step('coherence', func=self.runCoherence,
|
|
args=(self.correlation_method,), dostep=self.do_coherence)
|
|
|
|
# filter
|
|
self.step('filterinf', func=self.runFilter,
|
|
args=(self.filterStrength,), dostep=self.do_filterinf)
|
|
|
|
# unwrap
|
|
self.step('unwrap', func=self.runUnwrapper, dostep=self.do_unwrap)
|
|
|
|
# geocode
|
|
self.step('geocodeinf', func=self.runGeocode,
|
|
args=(self.geocode_list, self.do_unwrap, self.geocode_bbox),
|
|
dostep=self.do_geocode)
|
|
|
|
# self.step('endup', func=self.endup, dostep=True)
|
|
|
|
|
|
def main(self):
|
|
"""
|
|
Run the given processing steps.
|
|
"""
|
|
self.startup()
|
|
|
|
if self.do_preprocess:
|
|
# Run a preprocessor for the sets of frames
|
|
self.runPreprocessor()
|
|
|
|
if self.do_verifyDEM:
|
|
# Verify whether user defined a dem component. If not, then download
|
|
# SRTM DEM.
|
|
self.verifyDEM()
|
|
|
|
if self.do_pulsetiming:
|
|
# Run pulsetiming for each set of frames
|
|
self.runPulseTiming()
|
|
|
|
if self.do_estimateheights:
|
|
self.runEstimateHeights()
|
|
|
|
if self.do_mocomppath:
|
|
# Run setmocomppath
|
|
self.runSetmocomppath(peg=self.peg)
|
|
|
|
if self.do_orbit2sch:
|
|
# init and run orbit2sch
|
|
self.runOrbit2sch()
|
|
|
|
if self.do_updatepreprocinfo:
|
|
# update quantities in objPreProc obtained from previous steps
|
|
self.updatePreprocInfo(use_dop=self.use_dop)
|
|
|
|
if self.do_formslc:
|
|
self.runFormSLC()
|
|
|
|
polopList = []
|
|
if self.do_pol_correction:
|
|
polopList.append('polcal')
|
|
if self.do_pol_fr:
|
|
polopList.append('fr')
|
|
if self.do_pol_tec:
|
|
polopList.append('tec')
|
|
if self.do_pol_phase:
|
|
polopList.append('phase')
|
|
if polopList:
|
|
self.runISSI(polopList)
|
|
|
|
if self.do_offsetprf:
|
|
self.runOffsetprf()
|
|
|
|
if self.do_outliers1:
|
|
# Cull offoutliers
|
|
self.iterate_runOffoutliers()
|
|
|
|
if self.do_prepareresamps:
|
|
self.prepareResamps(self.resampRgLooks, self.resampAzLooks)
|
|
|
|
if self.do_resamp:
|
|
self.runResamp()
|
|
|
|
if self.do_resamp_image:
|
|
self.runResamp_image()
|
|
|
|
if self.do_crossmul: #2013-11-26
|
|
self.runCrossmul()
|
|
|
|
if self.do_mocompbaseline:
|
|
# mocompbaseline
|
|
self.runMocompbaseline()
|
|
|
|
if self.do_settopoint1:
|
|
# assign resampIntImage to topoIntImage
|
|
self.set_topoint1()
|
|
|
|
if self.do_topo:
|
|
# topocorrect
|
|
self.runTopo()
|
|
|
|
if self.do_shadecpx2rg:
|
|
self.runShadecpx2rg()
|
|
|
|
self.runRgoffset()
|
|
|
|
if self.do_rg_outliers2:
|
|
# Cull offoutliers
|
|
self.iterate_runOffoutliers()
|
|
|
|
if self.do_resamp_only:
|
|
self.runResamp_only()
|
|
|
|
if self.do_settopoint2:
|
|
self.set_topoint2()
|
|
|
|
if self.do_correct:
|
|
self.runCorrect()
|
|
|
|
if self.do_coherence:
|
|
# Coherence ?
|
|
self.runCoherence(method=self.correlation_method)
|
|
|
|
if self.do_filterinf:
|
|
# Filter ?
|
|
self.runFilter(self.filterStrength) #KK 2013-12-12 filterStrength as argument
|
|
|
|
if self.do_unwrap:
|
|
# Unwrap ?
|
|
self.runUnwrapper() #KK 2013-12-12 instead of self.verifyUnwrap()
|
|
|
|
if self.do_geocode:
|
|
# Geocode
|
|
self.runGeocode(self.geocode_list, self.do_unwrap, self.geocode_bbox)
|
|
|
|
self.endup()
|
|
|
|
|
|
|
|
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:
|
|
#create the isce object
|
|
isceapp = IsceApp(name='isceApp')
|
|
#configure the isceapp object
|
|
isceapp.configure()
|
|
#invoke the Application base class run method, which returns status
|
|
status = isceapp.run()
|
|
#inform Python of the status of the run to return to the shell
|
|
raise SystemExit(status)
|