440 lines
12 KiB
Python
Executable File
440 lines
12 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# Copyright 2010 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.
|
|
#
|
|
# Author: Walter Szeliga
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
from iscesys.Component.Component import Component
|
|
from . import snaphu
|
|
|
|
ALTITUDE = Component.Parameter(
|
|
'altitude',
|
|
public_name='ALTITUDE',
|
|
default=None,
|
|
type=float,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Altitude'
|
|
)
|
|
|
|
|
|
AZIMUTH_LOOKS = Component.Parameter(
|
|
'azimuthLooks',
|
|
public_name='AZIMUTH_LOOKS',
|
|
default=1,
|
|
type=int,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Number of looks in the azimuth direction'
|
|
)
|
|
|
|
|
|
CORR_FILE = Component.Parameter(
|
|
'corrfile',
|
|
public_name='CORR_FILE',
|
|
default=None,
|
|
type=str,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Correlation file name'
|
|
)
|
|
|
|
|
|
CORR_LOOKS = Component.Parameter(
|
|
'corrLooks',
|
|
public_name='CORR_LOOKS',
|
|
default=None,
|
|
type=int,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Correlation looks'
|
|
)
|
|
|
|
|
|
COR_FILE_FORMAT = Component.Parameter(
|
|
'corFileFormat',
|
|
public_name='COR_FILE_FORMAT',
|
|
default='ALT_LINE_DATA',
|
|
type=str,
|
|
mandatory=False,
|
|
intent='input',
|
|
doc='Correlation file format'
|
|
)
|
|
|
|
|
|
COSTMODE = Component.Parameter(
|
|
'costMode',
|
|
public_name='COSTMODE',
|
|
default='DEFO',
|
|
type=str,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Cost function mode. Options are "TOPO","DEFO","SMOOTH".'
|
|
)
|
|
|
|
|
|
DEFORMATION_MAX_CYCLES = Component.Parameter(
|
|
'defoMaxCycles',
|
|
public_name='DEFORMATION_MAX_CYCLES',
|
|
default=1.2,
|
|
type=float,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Deformation max cycles'
|
|
)
|
|
|
|
|
|
DUMP_CONNECTED_COMPONENTS = Component.Parameter(
|
|
'dumpConnectedComponents',
|
|
public_name='DUMP_CONNECTED_COMPONENTS',
|
|
default=True,
|
|
type=bool,
|
|
mandatory=False,
|
|
intent='input',
|
|
doc='Dump the connected component to a file with extension .conncomp'
|
|
)
|
|
|
|
|
|
EARTHRADIUS = Component.Parameter(
|
|
'earthRadius',
|
|
public_name='EARTHRADIUS',
|
|
default=0,
|
|
type=float,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Earth radius'
|
|
)
|
|
|
|
|
|
INIT_METHOD = Component.Parameter(
|
|
'initMethod',
|
|
public_name='INIT_METHOD',
|
|
default='MST',
|
|
type=str,
|
|
mandatory=False,
|
|
intent='input',
|
|
doc='Init method. Options are "MST" or "MCF"'
|
|
)
|
|
|
|
|
|
INIT_ONLY = Component.Parameter(
|
|
'initOnly',
|
|
public_name='INIT_ONLY',
|
|
default=False,
|
|
type=bool,
|
|
mandatory=False,
|
|
intent='input',
|
|
doc='Is this is set along with the DUMP_CONNECTED_COMPONENTS flag, then only the' +\
|
|
'connected components are computed and dumped into a file with extension .conncomp'
|
|
)
|
|
|
|
|
|
INPUT = Component.Parameter(
|
|
'input',
|
|
public_name='INPUT',
|
|
default=None,
|
|
type=str,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Input file name'
|
|
)
|
|
|
|
|
|
INT_FILE_FORMAT = Component.Parameter(
|
|
'intFileFormat',
|
|
public_name='INT_FILE_FORMAT',
|
|
default='COMPLEX_DATA',
|
|
type=str,
|
|
mandatory=False,
|
|
intent='input',
|
|
doc='Interferogram file format'
|
|
)
|
|
|
|
|
|
MAX_COMPONENTS = Component.Parameter(
|
|
'maxComponents',
|
|
public_name='MAX_COMPONENTS',
|
|
default=32,
|
|
type=int,
|
|
mandatory=False,
|
|
intent='input',
|
|
doc='Max number of components'
|
|
)
|
|
|
|
|
|
OUTPUT = Component.Parameter(
|
|
'output',
|
|
public_name='OUTPUT',
|
|
default=None,
|
|
type=str,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Output file name'
|
|
)
|
|
|
|
|
|
RANGE_LOOKS = Component.Parameter(
|
|
'rangeLooks',
|
|
public_name='RANGE_LOOKS',
|
|
default=1,
|
|
type=int,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Number of looks in the range direction'
|
|
)
|
|
|
|
|
|
UNW_FILE_FORMAT = Component.Parameter(
|
|
'unwFileFormat',
|
|
public_name='UNW_FILE_FORMAT',
|
|
default='ALT_LINE_DATA',
|
|
type=str,
|
|
mandatory=False,
|
|
intent='input',
|
|
doc='Unwrap file format'
|
|
)
|
|
|
|
|
|
WAVELENGTH = Component.Parameter(
|
|
'wavelength',
|
|
public_name='WAVELENGTH',
|
|
default=None,
|
|
type=float,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Wave length'
|
|
)
|
|
|
|
|
|
WIDTH = Component.Parameter(
|
|
'width',
|
|
public_name='WIDTH',
|
|
default=None,
|
|
type=int,
|
|
mandatory=True,
|
|
intent='input',
|
|
doc='Image width'
|
|
)
|
|
|
|
class Snaphu(Component):
|
|
|
|
parameter_list = (
|
|
ALTITUDE,
|
|
INPUT,
|
|
DUMP_CONNECTED_COMPONENTS,
|
|
WIDTH,
|
|
EARTHRADIUS,
|
|
INIT_ONLY,
|
|
CORR_LOOKS,
|
|
COR_FILE_FORMAT,
|
|
CORR_FILE,
|
|
WAVELENGTH,
|
|
MAX_COMPONENTS,
|
|
RANGE_LOOKS,
|
|
DEFORMATION_MAX_CYCLES,
|
|
UNW_FILE_FORMAT,
|
|
OUTPUT,
|
|
AZIMUTH_LOOKS,
|
|
INIT_METHOD,
|
|
COSTMODE,
|
|
INT_FILE_FORMAT
|
|
)
|
|
|
|
"""The Snaphu cost unwrapper"""
|
|
|
|
fileFormats = { 'COMPLEX_DATA' : 1,
|
|
'FLOAT_DATA' : 2,
|
|
'ALT_LINE_DATA' : 3,
|
|
'ALT_SAMPLE_DATA' : 4}
|
|
|
|
logging_name = "contrib.Snaphu.Snaphu"
|
|
|
|
|
|
family = 'snaphu'
|
|
|
|
def __init__(self,family='',name=''):
|
|
super(Snaphu, self).__init__(family if family else self.__class__.family, name=name)
|
|
self.minConnectedComponentFrac = 0.01
|
|
self.connectedComponentCostThreshold = 300
|
|
self.magnitude = None
|
|
|
|
|
|
def setCorrfile(self, corrfile):
|
|
"""Set the correlation filename for unwrapping"""
|
|
self.corrfile = corrfile
|
|
|
|
def setDefoMaxCycles(self, ncycles):
|
|
"""Set the maximum phase discontinuity expected."""
|
|
self.defoMaxCycles = ncycles
|
|
|
|
def setCorrLooks(self, looks):
|
|
"""Set the number of looks used for computing correlation"""
|
|
self.corrLooks = looks
|
|
|
|
def setInput(self,input):
|
|
"""Set the input filename for unwrapping"""
|
|
self.input = input
|
|
|
|
def setOutput(self,output):
|
|
"""Set the output filename for unwrapping"""
|
|
self.output = output
|
|
|
|
def setWidth(self,width):
|
|
"""Set the image width"""
|
|
self.width = width
|
|
|
|
def setWavelength(self,wavelength):
|
|
"""Set the radar wavelength"""
|
|
self.wavelength = wavelength
|
|
|
|
def setRangeLooks(self, looks):
|
|
self.rangeLooks = looks
|
|
|
|
def setAzimuthLooks(self, looks):
|
|
self.azimuthLooks = looks
|
|
|
|
def setIntFileFormat(self, instr):
|
|
self.intFileFormat = str(instr)
|
|
|
|
def setCorFileFormat(self, instr):
|
|
self.corFileFormat = str(instr)
|
|
|
|
def setUnwFileFormat(self, instr):
|
|
self.unwFileFormat = str(instr)
|
|
|
|
def setCostMode(self,costMode):
|
|
#moved the selection into prepare otherwise using configurable to
|
|
#init would not work
|
|
self.costMode = costMode
|
|
|
|
def setInitOnly(self, logic):
|
|
self.initOnly = logic
|
|
|
|
def dumpConnectedComponents(self, logic):
|
|
self.dumpConnectedComponents = logic
|
|
|
|
def setAltitude(self,altitude):
|
|
"""Set the satellite altitude"""
|
|
self.altitude = altitude
|
|
|
|
def setEarthRadius(self,earthRadius):
|
|
"""Set the local Earth radius"""
|
|
self.earthRadius = earthRadius
|
|
|
|
def setInitMethod(self, method):
|
|
"""Set the initialization method."""
|
|
#moved the selection into prepare otherwise using configurable to
|
|
#init would not work
|
|
self.initMethod = method
|
|
|
|
|
|
def setMaxComponents(self, num):
|
|
"""Set the maximum number of connected components."""
|
|
self.maxComponents = num
|
|
|
|
def prepare(self):
|
|
"""Perform some initialization of defaults"""
|
|
|
|
snaphu.setDefaults_Py()
|
|
snaphu.setInitOnly_Py(int(self.initOnly))
|
|
snaphu.setInput_Py(self.input)
|
|
snaphu.setOutput_Py(self.output)
|
|
if self.magnitude is not None:
|
|
snaphu.setMagnitude_Py(self.magnitude)
|
|
snaphu.setWavelength_Py(self.wavelength)
|
|
|
|
if not self.costMode in ['TOPO','DEFO','SMOOTH']:
|
|
self.logger.error('Invalid cost mode %s' % (self.costMode))
|
|
#must be one of the 3 above
|
|
snaphu.setCostMode_Py(1 if self.costMode == 'TOPO' else
|
|
(2 if self.costMode == 'DEFO' else 3))
|
|
snaphu.setAltitude_Py(self.altitude)
|
|
snaphu.setEarthRadius_Py(self.earthRadius)
|
|
if self.corrfile is not None:
|
|
snaphu.setCorrfile_Py(self.corrfile)
|
|
|
|
if self.corrLooks is not None:
|
|
snaphu.setCorrLooks_Py(self.corrLooks)
|
|
|
|
if self.defoMaxCycles is not None:
|
|
snaphu.setDefoMaxCycles_Py(self.defoMaxCycles)
|
|
|
|
if not self.initMethod in ['MST','MCF']:
|
|
self.logger.error('Invalid init method %s' % (self.initMethod))
|
|
snaphu.setInitMethod_Py(1 if self.initMethod == 'MST' else 2)
|
|
|
|
snaphu.setMaxComponents_Py(self.maxComponents)
|
|
snaphu.setRangeLooks_Py(int(self.rangeLooks))
|
|
snaphu.setAzimuthLooks_Py(int(self.azimuthLooks))
|
|
snaphu.setMinConnectedComponentFraction_Py(int(self.minConnectedComponentFrac))
|
|
snaphu.setConnectedComponentThreshold_Py(int(self.connectedComponentCostThreshold))
|
|
snaphu.setIntFileFormat_Py( int(self.fileFormats[self.intFileFormat]))
|
|
snaphu.setCorFileFormat_Py( int(self.fileFormats[self.corFileFormat]))
|
|
snaphu.setUnwFileFormat_Py( int(self.fileFormats[self.unwFileFormat]))
|
|
|
|
|
|
def unwrap(self):
|
|
"""Unwrap the interferogram"""
|
|
|
|
###Connected components can be dumped out in non-initonly mode
|
|
if not self.initOnly and self.dumpConnectedComponents:
|
|
snaphu.setConnectedComponents_Py(self.output+'.conncomp')
|
|
# snaphu.setRegrowComponents_Py(int(True))
|
|
|
|
snaphu.snaphu_Py(self.width)
|
|
self._unwrappingCompleted = True
|
|
|
|
##Second pass if initOnly mode was used.
|
|
if self.initOnly and self.dumpConnectedComponents:
|
|
self.growConnectedComponentsOnly()
|
|
|
|
def growConnectedComponentsOnly(self,infile=None,outfile=None):
|
|
'''
|
|
Grows the connected components using an unwrapped file.
|
|
'''
|
|
print('Growing connected components on second pass')
|
|
if infile is None:
|
|
inputFile = self.output
|
|
else:
|
|
inputFile = infile
|
|
|
|
if outfile is None:
|
|
outputFile = inputFile + '.conncomp'
|
|
else:
|
|
outputFile = outfile
|
|
|
|
self.prepare()
|
|
snaphu.setInitOnly_Py(int(False))
|
|
snaphu.setInput_Py(inputFile)
|
|
snaphu.setConnectedComponents_Py(outputFile)
|
|
snaphu.setRegrowComponents_Py(int(True))
|
|
snaphu.setUnwrappedInput_Py(int(True))
|
|
snaphu.snaphu_Py(self.width)
|
|
|