diff --git a/applications/SConscript b/applications/SConscript index 5f38f64..18326c2 100644 --- a/applications/SConscript +++ b/applications/SConscript @@ -78,9 +78,8 @@ listFiles = ['mdx.py', 'wbd.py', 'downsampleDEM.py', 'gdal2isce_xml.py', - 'alos2App.py', - 'alos2burstApp.py', - 'scansarApp.py', + 'alos2App.py', + 'alos2burstApp.py', 'wbd_with_correction.py'] # 'isce2he5.py'] diff --git a/applications/fixImageXml.py b/applications/fixImageXml.py index afe859c..b65aca0 100755 --- a/applications/fixImageXml.py +++ b/applications/fixImageXml.py @@ -18,7 +18,7 @@ def cmdLineParse(): help = 'Input image for which the XML file needs to be fixed.') fname = parser.add_mutually_exclusive_group(required=True) - fname.add_argument('-f', '--full', action='store_false', + fname.add_argument('-f', '--full', action='store_true', help = 'Replace filename with full path including dir in which file is located') fname.add_argument('-b', '--base', action='store_true', help = 'Replace filename with basename to use in current directory') diff --git a/applications/scansarApp.py b/applications/scansarApp.py deleted file mode 100755 index a5338ce..0000000 --- a/applications/scansarApp.py +++ /dev/null @@ -1,881 +0,0 @@ -#!/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 ScansarProc - -logger = logging.getLogger('isce.insar') - - -SENSOR_NAME = Application.Parameter( - 'sensorName', - public_name='sensor name', - default='ALOS2', - type=str, - mandatory=True, - doc="Sensor name" - ) -FULL_APERTURE_PRODUCT = Application.Parameter( - 'isFullApertureProduct', - public_name='is full aperture product', - default=False, - type=bool, - mandatory=True, - doc= "To indicate full aperture or burst-by-burst") - -BURST_OVERLAP_THRESHOLD = Application.Parameter( - 'burstOverlapThreshold', - public_name='burst overlap threshold', - default=85.0, - type=float, - mandatory=True, - doc='Minimum burst overlap needed to stop triggering common azimuth spectra filtering') - -UNWRAPPER_NAME = Application.Parameter( - 'unwrapper_name', - public_name='unwrapper name', - default='icu', - type=str, - mandatory=False, - doc="Unwrapping method to use. To be used in combination with UNWRAP." -) - - -# 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' -) - -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)" - ) -GEOCODE_DEM_FILENAME = Application.Parameter( - 'geocodeDemFilename', - public_name='geocode demfilename', - default='', - type=str, - mandatory=False, - doc='Filename of the DEM for geocoding') - - -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='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=7, - type=int, - mandatory=False, - doc='') - - -NUMBER_RANGE_LOOKS = Application.Parameter('numberRangeLooks', - public_name='range looks', - default=19, - type=int, - mandatory=False, - doc='' -) - -FILTER_STRENGTH = Application.Parameter('filterStrength', - public_name='filter strength', - default=0.5, - type=float, - mandatory=False, - doc='') - -OFFSET_SNR_THRESHOLD = Application.Parameter('offsetSNRThreshold', - public_name = 'offset SNR threshold', - default=8.0, - type=float, - mandatory = False, - doc = 'Offset SNR threshold') - -####New parameters for multi-swath -USE_VIRTUAL_FILES = Application.Parameter('useVirtualFiles', - public_name = 'use virtual files', - default=True, - type=bool, - mandatory=False, - doc = 'Use virtual files when possible to save space') - -SWATHS = Application.Parameter('swaths', - public_name = 'swaths', - default = [], - type=int, - container=list, - mandatory=False, - doc = 'Swaths to process') - -DO_INSAR = Application.Parameter('doInSAR', - public_name = 'do interferogram', - default = True, - type = bool, - doc = 'Perform interferometry. Set to false to skip insar steps.') - -GEOCODE_LIST = Application.Parameter( - 'geocode_list', - public_name='geocode list', - default = None, - container=list, - type=str, - doc = "List of products to geocode." - ) - - -WINDOW_SIZE_WIDTH = Application.Parameter( - 'winwidth', - public_name='Ampcor window width', - default=64, - type=int, - mandatory=False, - doc='Ampcor main window size width. Used in runDenseOffsets.' - ) - -WINDOW_SIZE_HEIGHT = Application.Parameter( - 'winhgt', - public_name='Ampcor window height', - default=64, - type=int, - mandatory=False, - doc='Ampcor main window size height. Used in runDenseOffsets.') - - -SEARCH_WINDOW_WIDTH = Application.Parameter( - 'srcwidth', - public_name='Ampcor search window width', - default=20, - type=int, - mandatory=False, - doc='Ampcor search window size width. Used in runDenseOffsets.' - ) - -SEARCH_WINDOW_HEIGHT = Application.Parameter( - 'srchgt', - public_name='Ampcor search window height', - default=20, - type=int, - mandatory=False, - doc='Ampcor search window size height. Used in runDenseOffsets.' - ) - -SKIP_SAMPLE_ACROSS = Application.Parameter( - 'skipwidth', - public_name='Ampcor skip width', - default=32, - type=int, - mandatory=False, - doc='Ampcor skip across width. Used in runDenseOffsets.' - ) - -SKIP_SAMPLE_DOWN = Application.Parameter( - 'skiphgt', - public_name='Ampcor skip height', - default=32, - type=int, - mandatory=False, - doc='Ampcor skip down height. Used in runDenseOffsets.' - ) - -OFFSET_MARGIN = Application.Parameter( - 'margin', - public_name='Ampcor margin', - default=50, - type=int, - mandatory=False, - doc='Ampcor margin offset. Used in runDenseOffsets.' - ) - -OVERSAMPLING_FACTOR = Application.Parameter( - 'oversample', - public_name='Ampcor oversampling factor', - default=32, - type=int, - mandatory=False, - doc='Ampcor oversampling factor. Used in runDenseOffsets.' - ) - -ACROSS_GROSS_OFFSET = Application.Parameter( - 'rgshift', - public_name='Range shift', - default=0, - type=int, - mandatory=False, - doc='Ampcor gross offset across. Used in runDenseOffsets.' - ) - -DOWN_GROSS_OFFSET = Application.Parameter( - 'azshift', - public_name='Azimuth shift', - default=0, - type=int, - mandatory=False, - doc='Ampcor gross offset down. Used in runDenseOffsets.' - ) - -DENSE_OFFSET_SNR_THRESHOLD = Application.Parameter( - 'dense_offset_snr_thresh', - public_name='SNR Threshold factor', - default=None, - type=float, - mandatory=False, - doc='SNR Threshold factor used in filtering offset field objects.') - -FILTER_NULL = Application.Parameter( - 'filt_null', - public_name='Filter NULL factor', - default=-10000., - type=float, - mandatory=False, - doc='NULL factor to use in filtering offset fields to avoid numpy type issues.' - ) - -FILTER_WIN_SIZE = Application.Parameter( - 'filt_size', - public_name='Filter window size', - default=5, - type=int, - mandatory=False, - doc='Window size for median_filter.' - ) - -OFFSET_GEOCODE_LIST = Application.Parameter( - 'off_geocode_list', - public_name='offset geocode list', - default=None, - container=list, - type=str, - mandatory=False, - doc='List of offset-specific files to geocode.' - ) - -USE_GPU = Application.Parameter( - 'useGPU', - public_name='use GPU', - default=False, - type=bool, - mandatory=False, - doc='Allow App to use GPU when available') - -#Facility declarations -MASTER = Application.Facility( - 'master', - public_name='Master', - module='isceobj.Sensor.ScanSAR', - factory='createSensor', - args=(SENSOR_NAME, 'master'), - mandatory=True, - doc="Master raw data component" - ) - -SLAVE = Application.Facility( - 'slave', - public_name='Slave', - module='isceobj.Sensor.ScanSAR', - factory='createSensor', - args=(SENSOR_NAME,'slave'), - mandatory=True, - doc="Slave raw 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" -) - - -RUN_UNWRAPPER = Application.Facility( - 'runUnwrapper', - public_name='Run unwrapper', - module='isceobj.ScansarProc', - factory='createUnwrapper', - args=(SELF(), DO_UNWRAP, UNWRAPPER_NAME), - mandatory=False, - doc="Unwrapping module" -) - -RUN_UNWRAP_2STAGE = Application.Facility( - 'runUnwrap2Stage', - public_name='Run unwrapper 2 Stage', - module='isceobj.ScansarProc', - factory='createUnwrap2Stage', - args=(SELF(), DO_UNWRAP_2STAGE, UNWRAPPER_NAME), - mandatory=False, - doc="Unwrapping module" -) - -_INSAR = Application.Facility( - '_insar', - public_name='scansarproc', - module='isceobj.ScansarProc', - factory='createScansarProc', - args = ('scansarAppContext',isceobj.createCatalog('scansarProc')), - mandatory=False, - doc="ScansarProc object" -) - - -## Common interface for all insar applications. -class ScansarInSAR(Application): - - family = 'scansarinsar' - ## Define Class parameters in this list - parameter_list = (SENSOR_NAME, - UNWRAPPER_NAME, - DEM_FILENAME, - GEOCODE_DEM_FILENAME, - BURST_OVERLAP_THRESHOLD, - NUMBER_AZIMUTH_LOOKS, - NUMBER_RANGE_LOOKS, - FILTER_STRENGTH, - OFFSET_SNR_THRESHOLD, - DO_INSAR, - DO_UNWRAP, - USE_HIGH_RESOLUTION_DEM_ONLY, - GEOCODE_BOX, - PICKLE_DUMPER_DIR, - PICKLE_LOAD_DIR, - RENDERER, - DO_UNWRAP_2STAGE, - UNWRAPPER_2STAGE_NAME, - SOLVER_2STAGE, - GEOCODE_LIST, - USE_VIRTUAL_FILES, - SWATHS, - WINDOW_SIZE_HEIGHT, - WINDOW_SIZE_WIDTH, - SEARCH_WINDOW_HEIGHT, - SEARCH_WINDOW_WIDTH, - SKIP_SAMPLE_ACROSS, - SKIP_SAMPLE_DOWN, - OFFSET_MARGIN, - OVERSAMPLING_FACTOR, - ACROSS_GROSS_OFFSET, - DOWN_GROSS_OFFSET, - DENSE_OFFSET_SNR_THRESHOLD, - FILTER_NULL, - FILTER_WIN_SIZE, - OFFSET_GEOCODE_LIST, - USE_GPU) - - facility_list = (MASTER, - SLAVE, - DEM_STITCHER, - RUN_UNWRAPPER, - RUN_UNWRAP_2STAGE, - _INSAR) - - _pickleObj = "_insar" - - def __init__(self, family='', name='',cmdline=None): - import isceobj - from isceobj.ScansarProc import ScansarProc - 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="scansarinsar.log") - self._add_methods() - self._insarProcFact = ScansarProc - return None - - - - def Usage(self): - print("Usages: ") - print("scansarApp.py ") - print("scansarApp.py --steps") - print("scansarApp.py --help") - print("scansarApp.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.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"] - ) - - #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 - - - if (self.off_geocode_list is None): - self.off_geocode_list = self.insar.off_geocode_list - else: - g_count = 0 - for g in self.off_geocode_list: - if g not in self.insar.off_geocode_list: - g_count += 1 - - if g_count > 0: - self.insar.off_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.ScanSAR 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._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 = ScansarProc.createPreprocessor(self) - self.runCommonRangeSpectra = ScansarProc.createCommonRangeSpectra(self) - self.runEqualizeSlcs = ScansarProc.createEqualizeSlcs(self) - self.runEstimateBurstSync = ScansarProc.createEstimateBurstSync(self) -# self.runComputeBaseline = ScansarProc.createComputeBaseline(self) -# self.verifyDEM = ScansarProc.createVerifyDEM(self) -# self.verifyGeocodeDEM = ScansarProc.createVerifyGeocodeDEM(self) -# self.runTopo = ScansarProc.createTopo(self) -# self.runSubsetOverlaps = ScansarProc.createSubsetOverlaps(self) -# self.runCoarseOffsets = ScansarProc.createCoarseOffsets(self) -# self.runCoarseResamp = ScansarProc.createCoarseResamp(self) -# self.runOverlapIfg = ScansarProc.createOverlapIfg(self) -# self.runPrepESD = ScansarProc.createPrepESD(self) -# self.runESD = ScansarProc.createESD(self) -# self.runRangeCoreg = ScansarProc.createRangeCoreg(self) -# self.runFineOffsets = ScansarProc.createFineOffsets(self) -# self.runFineResamp = ScansarProc.createFineResamp(self) -# self.runBurstIfg = ScansarProc.createBurstIfg(self) -# self.runMergeBursts = ScansarProc.createMergeBursts(self) -# self.runFilter = ScansarProc.createFilter(self) -# self.runGeocode = ScansarProc.createGeocode(self) -# self.runDenseOffsets = ScansarProc.createDenseOffsets(self) -# self.runOffsetFilter = ScansarProc.createOffsetFilter(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 master and slave sensor data to raw images""" - ) - ) - - # Run common range spectra filtering - self.step('commonrangespectra', - func=self.runCommonRangeSpectra, - doc=("""Filter images to common range spectra""")) - - - #Run image equalization to make pixels same size - self.step('equalizeslcs', - func=self.runEqualizeSlcs, - doc=("""Make pixel sizes the same""")) - - #Run estimation of burst sync - self.step('estimateburstsync', - func=self.runEstimateBurstSync, - doc=("""Estimate amount of burst sync""")) - - # Compute baselines and estimate common bursts - #self.step('computeBaselines', - # func=self.runComputeBaseline, - # doc=( - # """Compute baseline and number of common bursts""" - # ) - # ) - - # Verify whether the DEM was initialized properly. If not, download - # a DEM - #self.step('verifyDEM', func=self.verifyDEM) - - ##Run topo for each bursts - #self.step('topo', func=self.runTopo) - - ##Run subset overlaps - #self.step('subsetoverlaps', func=self.runSubsetOverlaps) - - ##Run coarse offsets - #self.step('coarseoffsets', func=self.runCoarseOffsets) - - ####Run coarse resamp - #self.step('coarseresamp', func=self.runCoarseResamp) - - ####Run overlap ifgs - #self.step('overlapifg', func=self.runOverlapIfg) - - ###Run prepare ESD inputs - #self.step('prepesd', func=self.runPrepESD) - - ###Run ESD - #self.step('esd', func=self.runESD) - - ###Run range coregistration - #self.step('rangecoreg', func=self.runRangeCoreg) - - ###Estimate fine offsets - #self.step('fineoffsets', func=self.runFineOffsets) - - ###Resample slave bursts - #self.step('fineresamp', func=self.runFineResamp) - - ####Create burst interferograms - #self.step('burstifg', func=self.runBurstIfg) - - ###Merge burst products into a single file - #self.step('mergebursts', func=self.runMergeBursts) - - ###Filter the interferogram - #self.step('filter', func=self.runFilter) - - - # 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)) - - - # Geocode - #self.step('geocode', func=self.runGeocode, - # args=(self.geocode_list, self.do_unwrap, self.geocode_bbox)) - - # Dense offsets - #self.step('denseoffsets', func=self.runDenseOffsets) - - #Filter offsets - #self.step('filteroffsets', func=self.runOffsetFilter) - - #Geocode offsets - #self.step('geocodeoffsets', func=self.runGeocode, - # args=(self.off_geocode_list, False, self.geocode_bbox, True)) - -# self.step('endup', func=self.endup) - return None - - ## Main has the common start to both insarApp and dpmApp. - def main(self): - self.help() - - timeStart= time.time() - - # Run a preprocessor for the two sets of frames - self.runPreprocessor() - - #Filter to common range spectra - self.runCommonRangeSpectra() - - #Make pixels the same size - self.runEqualizeSlcs() - - #Estimate amount of burst sync - self.runEstimateBurstSync() - - #Compute baselines and common bursts - #self.runComputeBaseline() - - - #Verify whether user defined a dem component. If not, then download - # SRTM DEM. - #self.verifyDEM() - - ##Run topo for each burst - #self.runTopo() - - ##Run subset overlaps - #self.runSubsetOverlaps() - - ##Run coarse offsets - #self.runCoarseOffsets() - - ##Run coarse resamp - #self.runCoarseResamp() - - ##Run ifg - #self.runOverlapIfg() - - ##Prepare for ESD - #self.runPrepESD() - - #Run ESD - #self.runESD() - - ###Estimate range misregistration - #self.runRangeCoreg() - - ###Estimate fine offsets - #self.runFineOffsets() - - ###Resample slave bursts - #self.runFineResamp() - - ###Create burst interferograms - #self.runBurstIfg() - - ####Merge bursts into single files - #self.runMergeBursts() - - ###Filter the interferogram - #self.runFilter() - - #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.do_unwrap, self.geocode_bbox) - - - #Dense offsets - #self.runDenseOffsets() - - #Filter offsets - #self.runOffsetFilter() - - - #Geocode offsets - #self.runGeocode(self.off_geocode_list, False, self.geocode_bbox, True) - - timeEnd = time.time() - logger.info("Total Time: %i seconds" %(timeEnd - timeStart)) - - self.renderProcDoc() - - return None - - - - -if __name__ == "__main__": - import sys - insar = ScansarInSAR(name="scansarApp") - insar.configure() - insar.run() diff --git a/components/isceobj/SConscript b/components/isceobj/SConscript index bb13b8e..e37117f 100644 --- a/components/isceobj/SConscript +++ b/components/isceobj/SConscript @@ -70,6 +70,5 @@ SConscript('Registry/SConscript') SConscript('StripmapProc/SConscript') SConscript('TopsProc/SConscript') SConscript('RtcProc/SConscript') -SConscript('ScansarProc/SConscript') SConscript('Alos2Proc/SConscript') SConscript('Alos2burstProc/SConscript') diff --git a/components/isceobj/ScansarProc/Factories.py b/components/isceobj/ScansarProc/Factories.py deleted file mode 100644 index 5a9f1e4..0000000 --- a/components/isceobj/ScansarProc/Factories.py +++ /dev/null @@ -1,104 +0,0 @@ -# -# Author: Piyush Agram -# Copyright 2016 -# - -# Path to the _RunWrapper factories -_PATH = "isceobj.ScansarProc." - -## A factory to make _RunWrapper factories -def _factory(name, other_name=None): - """create_run_wrapper = _factory(name) - name is the module and class function name - """ - other_name = other_name or name - module = __import__( - _PATH+name, fromlist=[""] - ) - cls = getattr(module, other_name) - def creater(other, *args, **kwargs): - """_RunWrapper for object calling %s""" - return _RunWrapper(other, cls) - return creater - -## Put in "_" to prevernt import on "from Factorties import *" -class _RunWrapper(object): - """_RunWrapper(other, func)(*args, **kwargs) - - executes: - - func(other, *args, **kwargs) - - (like a method) - """ - def __init__(self, other, func): - self.method = func - self.other = other - return None - - def __call__(self, *args, **kwargs): - return self.method(self.other, *args, **kwargs) - - pass - -def createUnwrapper(other, do_unwrap = None, unwrapperName = None, - unwrap = None): - if not do_unwrap and not unwrap: - #if not defined create an empty method that does nothing - def runUnwrap(self): - return None - elif unwrapperName.lower() == 'snaphu': - from .runUnwrapSnaphu import runUnwrap - elif unwrapperName.lower() == 'snaphu_mcf': - from .runUnwrapSnaphu import runUnwrapMcf as runUnwrap - elif unwrapperName.lower() == 'icu': - from .runUnwrapIcu import runUnwrap - elif unwrapperName.lower() == 'grass': - from .runUnwrapGrass import runUnwrap - return _RunWrapper(other, runUnwrap) - -def createUnwrap2Stage(other, do_unwrap_2stage = None, unwrapperName = None): - if (not do_unwrap_2stage) or (unwrapperName.lower() == 'icu') or (unwrapperName.lower() == 'grass'): - #if not defined create an empty method that does nothing - def runUnwrap2Stage(*arg, **kwargs): - return None - else: - try: - import pulp - from .runUnwrap2Stage import runUnwrap2Stage - except ImportError: - raise Exception('Please install PuLP Linear Programming API to run 2stage unwrap') - return _RunWrapper(other, runUnwrap2Stage) - - -createPreprocessor = _factory("runPreprocessor") -createCommonRangeSpectra = _factory("runCommonRangeSpectra") -createEqualizeSlcs = _factory("runEqualizeSlcs") -createEstimateBurstSync = _factory("runEstimateBurstSync") -#createComputeBaseline = _factory("runComputeBaseline") -#createVerifyDEM = _factory("runVerifyDEM") -#createVerifyGeocodeDEM = _factory("runVerifyGeocodeDEM") -#createTopo = _factory("runTopo") -#createSubsetOverlaps = _factory("runSubsetOverlaps") -#createCoarseOffsets = _factory("runCoarseOffsets") -#createCoarseResamp = _factory("runCoarseResamp") -#createOverlapIfg = _factory("runOverlapIfg") -#createPrepESD = _factory("runPrepESD") -#createESD = _factory("runESD") -#createRangeCoreg = _factory("runRangeCoreg") -#createFineOffsets = _factory("runFineOffsets") -#createFineResamp = _factory("runFineResamp") -#createBurstIfg = _factory("runBurstIfg") -#createMergeBursts = _factory("runMergeBursts") -#createFilter = _factory("runFilter") -#createGeocode = _factory("runGeocode") - -#createMaskImages = _factory("runMaskImages") -#createCreateWbdMask = _factory("runCreateWbdMask") - -###topsOffsetApp factories -#createMergeSLCs = _factory("runMergeSLCs") -#createDenseOffsets = _factory("runDenseOffsets") -#createOffsetFilter = _factory("runOffsetFilter") -#createOffsetGeocode = _factory("runOffsetGeocode") -#createCropOffsetGeo = _factory("runCropOffsetGeo") diff --git a/components/isceobj/ScansarProc/SConscript b/components/isceobj/ScansarProc/SConscript deleted file mode 100644 index 49c970e..0000000 --- a/components/isceobj/ScansarProc/SConscript +++ /dev/null @@ -1,48 +0,0 @@ -#! /usr/bin/env python - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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. -# -# Author: Eric Gurrola -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - - -#!/usr/bin/env python -import os - -Import('envisceobj') -package = envisceobj['PACKAGE'] -project = 'ScansarProc' - -install = os.path.join(envisceobj['PRJ_SCONS_INSTALL'],package,project) - -listFiles = ['__init__.py', 'Factories.py', 'ScansarProc.py', 'runPreprocessor.py', - 'runCommonRangeSpectra.py', 'runEqualizeSlcs.py', - 'runEstimateBurstSync.py'] -#, 'runComputeBaseline.py', 'runVerifyDEM.py', 'runTopo.py', 'runSubsetOverlaps.py', 'runCoarseOffsets.py', 'runCoarseResamp.py', 'runOverlapIfg.py', 'runPrepESD.py', 'runESD.py', 'runRangeCoreg.py', 'runFineOffsets.py', 'runFineResamp.py', 'runBurstIfg.py', 'runMergeBursts.py', 'runFilter.py', 'runUnwrapGrass.py', 'runUnwrapIcu.py', 'runUnwrapSnaphu.py', 'runGeocode.py', 'runMergeSLCs.py', 'runDenseOffsets.py', 'runOffsetFilter.py', 'runOffsetGeocode.py', 'runCropOffsetGeo.py', 'runUnwrap2Stage.py', 'VRTManager.py', 'runVerifyGeocodeDEM.py'] -envisceobj.Install(install,listFiles) -envisceobj.Alias('install',install) diff --git a/components/isceobj/ScansarProc/ScansarProc.py b/components/isceobj/ScansarProc/ScansarProc.py deleted file mode 100644 index 2de1890..0000000 --- a/components/isceobj/ScansarProc/ScansarProc.py +++ /dev/null @@ -1,567 +0,0 @@ -# -# Author: Piyush Agram -# Copyright 2018 -# - -import os -import logging -import logging.config -from iscesys.Component.Component import Component -from iscesys.DateTimeUtil.DateTimeUtil import DateTimeUtil as DTU -from iscesys.Compatibility import Compatibility - - -MASTER_SLC_PRODUCT = Component.Parameter('masterSlcProduct', - public_name='master slc product', - default='master', - type=str, - mandatory=False, - doc='Directory name of the master SLC product') - - -SLAVE_SLC_PRODUCT = Component.Parameter('slaveSlcProduct', - public_name='slave slc product', - default='slave', - type=str, - mandatory=False, - doc='Directory name of the slave SLC product') - -NUMBER_COMMON_BURSTS = Component.Parameter('numberOfCommonBursts', - public_name = 'number of common bursts', - default = None, - type = int, - container=list, - mandatory = False, - doc = 'Number of common bursts between slave and master') - - -DEM_FILENAME = Component.Parameter('demFilename', - public_name='dem image name', - default = None, - type = str, - mandatory = False, - doc = 'Name of the dem file') - -GEOMETRY_DIRNAME = Component.Parameter('geometryDirname', - public_name='geometry directory name', - default='geom_master', - type=str, - mandatory=False, - doc = 'Geometry directory') - -COMMON_RANGE_SPECTRA_SLC_DIRECTORY = Component.Parameter('commonRangeSpectraSlcDirectory', - public_name='equalized slc directory name', - default='commonrangespectra_slc', - type=str, - mandatory=False, - doc='directory with common range spectral slcs') - -RANGE_SPECTRA_OVERLAP_THRESHOLD = Component.Parameter('rangeSpectraOverlapThreshold', - public_name='range spectra overlap threshold', - default=3.0e6, - type=float, - mandatory=False, - doc='Minimum range spectra overlap needed') - -EQUALIZED_SLC_DIRECTORY = Component.Parameter('equalizedSlcDirectory', - public_name='equalized slc directory', - default='equalized_slc', - type=str, - mandatory=False, - doc='Directory with equalized slcs') - -BURST_SYNC_DIRECTORY = Component.Parameter('burstSyncDirectory', - public_name='bursy sync directory', - default='burst_sync', - type=str, - mandatory=False, - doc='Directory with burst sync information') - -COARSE_OFFSETS_DIRECTORY = Component.Parameter('coarseOffsetsDirname', - public_name = 'coarse offsets directory name', - default = 'coarse_offsets', - type = str, - mandatory = False, - doc = 'coarse offsets directory name') - -COARSE_COREG_DIRECTORY = Component.Parameter('coarseCoregDirname', - public_name = 'coarse coreg directory name', - default = 'coarse_coreg', - type = str, - mandatory = False, - doc = 'coarse coregistered slc directory name') - -COARSE_IFG_DIRECTORY = Component.Parameter('coarseIfgDirname', - public_name = 'coarse interferogram directory name', - default = 'coarse_interferogram', - type = str, - mandatory = False, - doc = 'Coarse interferogram directory') - - -FINE_OFFSETS_DIRECTORY = Component.Parameter('fineOffsetsDirname', - public_name = 'fine offsets directory name', - default = 'fine_offsets', - type = str, - mandatory = False, - doc = 'fine offsets directory name') - -FINE_COREG_DIRECTORY = Component.Parameter('fineCoregDirname', - public_name = 'fine coreg directory name', - default = 'fine_coreg', - type = str, - mandatory = False, - doc = 'fine coregistered slc directory name') - -FINE_IFG_DIRECTORY = Component.Parameter('fineIfgDirname', - public_name = 'fine interferogram directory name', - default = 'fine_interferogram', - type = str, - mandatory = False, - doc = 'Fine interferogram directory') - -MERGED_DIRECTORY = Component.Parameter('mergedDirname', - public_name = 'merged products directory name', - default = 'merged', - type = str, - mandatory = False, - doc = 'Merged product directory') - -OVERLAPS_SUBDIRECTORY = Component.Parameter('overlapsSubDirname', - public_name = 'overlaps subdirectory name', - default = 'overlaps', - type = str, - mandatory = False, - doc = 'Overlap region processing directory') - -NUMBER_OF_SWATHS = Component.Parameter('numberOfSwaths', - public_name = 'number of swaths', - default=0, - type=int, - mandatory = False, - doc = 'Number of swaths') - -MERGED_IFG_NAME = Component.Parameter( - 'mergedIfgname', - public_name='merged interferogram name', - default='topophase.flat', - type=str, - mandatory=False, - doc='Filename of the merged interferogram.' -) - - -MERGED_LOS_NAME = Component.Parameter( - 'mergedLosName', - public_name = 'merged los name', - default = 'los.rdr', - type = str, - mandatory = False, - doc = 'Merged los file name') - - -COHERENCE_FILENAME = Component.Parameter('coherenceFilename', - public_name='coherence name', - default='phsig.cor', - type=str, - mandatory=False, - doc='Coherence file name') - -CORRELATION_FILENAME = Component.Parameter('correlationFilename', - public_name='correlation name', - default='topophase.cor', - type=str, - mandatory=False, - doc='Correlation file name') - -FILTERED_INT_FILENAME = Component.Parameter('filtFilename', - public_name = 'filtered interferogram name', - default = 'filt_topophase.flat', - type = str, - mandatory = False, - doc = 'Filtered interferogram filename') - - -UNWRAPPED_INT_FILENAME = Component.Parameter('unwrappedIntFilename', - public_name='unwrapped interferogram filename', - default='filt_topophase.unw', - type=str, - mandatory=False, - doc='') - -UNWRAPPED_2STAGE_FILENAME = Component.Parameter('unwrapped2StageFilename', - public_name='unwrapped 2Stage filename', - default='filt_topophase_2stage.unw', - type=str, - mandatory=False, - doc='Output File name of 2Stage unwrapper') - -CONNECTED_COMPONENTS_FILENAME = Component.Parameter( - 'connectedComponentsFilename', - public_name='connected component filename', - default=None, - type=str, - mandatory=False, - doc='' -) - -DEM_CROP_FILENAME = Component.Parameter('demCropFilename', - public_name='dem crop file name', - default='dem.crop', - type=str, - mandatory=False, - doc='') - - -GEOCODE_LIST = Component.Parameter('geocode_list', - public_name='geocode list', - default=[COHERENCE_FILENAME, - CORRELATION_FILENAME, - UNWRAPPED_INT_FILENAME, - MERGED_LOS_NAME, - MERGED_IFG_NAME, - FILTERED_INT_FILENAME, - UNWRAPPED_2STAGE_FILENAME, - ], - container=list, - type=str, - mandatory=False, - doc='List of files to geocode' -) - -UNMASKED_PREFIX = Component.Parameter('unmaskedPrefix', - public_name='unmasked filename prefix', - default='unmasked', - type=str, - mandatory=False, - doc='Prefix prepended to the image filenames that have not been water masked') - - -####Adding things from topsOffsetApp for integration -OFFSET_TOP = Component.Parameter( - 'offset_top', - public_name='Top offset location', - default=None, - type=int, - mandatory=False, - doc='Ampcor-calculated top offset location. Overridden by workflow.' - ) - -OFFSET_LEFT = Component.Parameter( - 'offset_left', - public_name='Left offset location', - default=None, - type=int, - mandatory=False, - doc='Ampcor-calculated left offset location. Overridden by workflow.' - ) - -OFFSET_WIDTH = Component.Parameter( - 'offset_width', - public_name='Offset image nCols', - default=None, - type=int, - mandatory=False, - doc='Number of columns in the final offset field (calculated in DenseAmpcor).' - ) - -OFFSET_LENGTH = Component.Parameter( - 'offset_length', - public_name='Offset image nRows', - default=None, - type=int, - mandatory=False, - doc='Number of rows in the final offset field (calculated in DenseAmpcor).' - ) - -OFFSET_OUTPUT_FILE = Component.Parameter( - 'offsetfile', - public_name='Offset filename', - default='dense_offsets.bil', - type=str, - mandatory=False, - doc='Filename for gross dense offsets BIL. Used in runDenseOffsets.' - ) - -OFFSET_SNR_FILE = Component.Parameter( - 'snrfile', - public_name='Offset SNR filename', - default='dense_offsets_snr.bil', - type=str, - mandatory=False, - doc='Filename for gross dense offsets SNR. Used in runDenseOffsets.') - -FILT_OFFSET_OUTPUT_FILE = Component.Parameter( - 'filt_offsetfile', - public_name='Filtered offset filename', - default='filt_dense_offsets.bil', - type=str, - mandatory=False, - doc='Filename for filtered dense offsets BIL.' - ) - -OFFSET_GEOCODE_LIST = Component.Parameter('off_geocode_list', - public_name='offset geocode list', - default = [OFFSET_OUTPUT_FILE, - OFFSET_SNR_FILE, - FILT_OFFSET_OUTPUT_FILE], - container = list, - type=str, - mandatory=False, - doc = 'List of files on offset grid to geocode') - - - -class ScansarProc(Component): - """ - This class holds the properties, along with methods (setters and getters) - to modify and return their values. - """ - - parameter_list = (MASTER_SLC_PRODUCT, - SLAVE_SLC_PRODUCT, - DEM_FILENAME, - GEOMETRY_DIRNAME, - COMMON_RANGE_SPECTRA_SLC_DIRECTORY, - RANGE_SPECTRA_OVERLAP_THRESHOLD, - EQUALIZED_SLC_DIRECTORY, - BURST_SYNC_DIRECTORY, - COARSE_OFFSETS_DIRECTORY, - COARSE_COREG_DIRECTORY, - COARSE_IFG_DIRECTORY, - FINE_OFFSETS_DIRECTORY, - FINE_COREG_DIRECTORY, - FINE_IFG_DIRECTORY, - OVERLAPS_SUBDIRECTORY, - MERGED_DIRECTORY, - MERGED_IFG_NAME, - MERGED_LOS_NAME, - COHERENCE_FILENAME, - FILTERED_INT_FILENAME, - UNWRAPPED_INT_FILENAME, - UNWRAPPED_2STAGE_FILENAME, - CONNECTED_COMPONENTS_FILENAME, - DEM_CROP_FILENAME, - GEOCODE_LIST, - UNMASKED_PREFIX, - CORRELATION_FILENAME, - OFFSET_TOP, - OFFSET_LEFT, - OFFSET_LENGTH, - OFFSET_WIDTH, - OFFSET_OUTPUT_FILE, - OFFSET_SNR_FILE, - FILT_OFFSET_OUTPUT_FILE, - OFFSET_GEOCODE_LIST) - - facility_list = () - - - family='scansarcontext' - - def __init__(self, name='', procDoc=None): - #self.updatePrivate() - - super().__init__(family=self.__class__.family, name=name) - self.procDoc = procDoc - return None - - def _init(self): - """ - Method called after Parameters are configured. - Determine whether some Parameters still have unresolved - Parameters as their default values and resolve them. - """ - - #Determine whether the geocode_list still contains Parameters - #and give those elements the proper value. This will happen - #whenever the user doesn't provide as input a geocode_list for - #this component. - - mergedir = self.mergedDirname - for i, x in enumerate(self.geocode_list): - if isinstance(x, Component.Parameter): - y = getattr(self, getattr(x, 'attrname')) - self.geocode_list[i] = os.path.join(mergedir, y) - - - for i,x in enumerate(self.off_geocode_list): - if isinstance(x, Component.Parameter): - y = getattr(self, getattr(x, 'attrname')) - self.off_geocode_list[i] = os.path.join(mergedir, y) - - return - - - def loadProduct(self, xmlname): - ''' - Load the product using Product Manager. - ''' - - from iscesys.Component.ProductManager import ProductManager as PM - - pm = PM() - pm.configure() - - obj = pm.loadProduct(xmlname) - - return obj - - - def saveProduct(self, obj, xmlname): - ''' - Save the product to an XML file using Product Manager. - ''' - - from iscesys.Component.ProductManager import ProductManager as PM - - pm = PM() - pm.configure() - - pm.dumpProduct(obj, xmlname) - - return None - - - def getMergedOrbit(self, products): - from isceobj.Orbit.Orbit import Orbit - - ###Create merged orbit - orb = Orbit() - orb.configure() - - burst = product[0] - #Add first burst orbit to begin with - for sv in burst.orbit: - orb.addStateVector(sv) - - - for pp in product: - ##Add all state vectors - for sv in pp.orbit: - if (sv.time< orb.minTime) or (sv.time > orb.maxTime): - orb.addStateVector(sv) - - pp.orbit = orb - - return orb - - - - def getInputSwathList(self, inlist): - ''' - To be used to get list of swaths that user wants us to process. - ''' - if len(inlist) == 0: - return [x+1 for x in range(self.numberOfSwaths)] - else: - return inlist - - def getValidSwathList(self, inlist): - ''' - Used to get list of swaths left after applying all filters - e.g, region of interest. - ''' - - import glob - - inswaths = glob.glob( os.path.join(self.masterSlcProduct, 's*.xml')) - - swaths = [] - for x in inswaths: - swaths.append( int(os.path.splitext(os.path.basename(x))[0][-1])) - - return sorted(swaths) - - def hasGPU(self): - ''' - Determine if GPU modules are available. - ''' - - flag = False - try: - from zerodop.GPUtopozero.GPUtopozero import PyTopozero - from zerodop.GPUgeo2rdr.GPUgeo2rdr import PyGeo2rdr - flag = True - except: - pass - - return flag - - def getOverlapFrequency(self, centerfreq1, bandwidth1, - centerfreq2, bandwidth2): - startfreq1 = centerfreq1 - bandwidth1 / 2.0 - endingfreq1 = centerfreq1 + bandwidth1 / 2.0 - - startfreq2 = centerfreq2 - bandwidth2 / 2.0 - endingfreq2 = centerfreq2 + bandwidth2 / 2.0 - - overlapfreq = [] - if startfreq2 <= startfreq1 <= endingfreq2: - overlapfreq.append(startfreq1) - - if startfreq2 <= endingfreq1 <= endingfreq2: - overlapfreq.append(endingfreq1) - - if startfreq1 < startfreq2 < endingfreq1: - overlapfreq.append(startfreq2) - - if startfreq1 < endingfreq2 < endingfreq1: - overlapfreq.append(endingfreq2) - - if len(overlapfreq) != 2: - #no overlap bandwidth - return None - else: - startfreq = min(overlapfreq) - endingfreq = max(overlapfreq) - return [startfreq, endingfreq] - - @property - def commonRangeSpectraMasterSlcProduct(self): - infile = self.masterSlcProduct - if infile[-1] == os.path.sep: - infile = infile[:-1] - - base = os.path.sep.join( infile.split(os.path.sep)[-2:]) - return os.path.join( self.commonRangeSpectraSlcDirectory, base) - - @property - def commonRangeSpectraSlaveSlcProduct(self): - infile = self.slaveSlcProduct - if infile[-1] == os.path.sep: - infile = infile[:-1] - - base = os.path.sep.join( infile.split(os.path.sep)[-2:]) - return os.path.join( self.commonRangeSpectraSlcDirectory, base) - - @property - def equalizedMasterSlcProduct(self): - infile = self.masterSlcProduct - if infile[-1] == os.path.sep: - infile = infile[:-1] - - base = os.path.sep.join(infile.split(os.path.sep)[-2:]) - return os.path.join( self.equalizedSlcDirectory, base) - - @property - def equalizedSlaveSlcProduct(self): - infile = self.slaveSlcProduct - if infile[-1] == os.path.sep: - infile = infile[:-1] - - base = os.path.sep.join(infile.split(os.path.sep)[-2:]) - return os.path.join( self.equalizedSlcDirectory, base) - - def writeBurstSyncFile(self, outfile, rgoff, azoff, - nb, nc, - unsynLines, synLines): - - with open(outfile, 'w') as fid: - fid.write('image pair range offset: {0}\n'.format(rgoff)) - fid.write('image pair azimuth offset: {0}\n'.format(azoff)) - fid.write('number of lines in a burst: {0}\n'.format(nb)) - fid.write('number of lines in a burst cycle: {0}\n'.format(nc)) - fid.write('number of unsynchronized lines in a burst: {0}\n'.format(unsynLines)) - fid.write('burst synchronization: {0}%'.format((synLines/nb)*100.0)) - - diff --git a/components/isceobj/ScansarProc/__init__.py b/components/isceobj/ScansarProc/__init__.py deleted file mode 100644 index ddc9601..0000000 --- a/components/isceobj/ScansarProc/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -# Author: Piyush Agram -# Copyright 2016 -# - -from .ScansarProc import * -from .Factories import * - -def getFactoriesInfo(): - return {'ScansarProc': - {'args': - { - 'procDoc':{'value':None,'type':'Catalog','optional':True} - }, - 'factory':'createScansarProc' - } - - } - -def createScansarProc(name=None, procDoc= None): - from .ScansarProc import ScansarProc - return ScansarProc(name = name,procDoc = procDoc) diff --git a/components/isceobj/ScansarProc/runCommonRangeSpectra.py b/components/isceobj/ScansarProc/runCommonRangeSpectra.py deleted file mode 100644 index 50a0e53..0000000 --- a/components/isceobj/ScansarProc/runCommonRangeSpectra.py +++ /dev/null @@ -1,120 +0,0 @@ -# -# Author: Piyush Agram -# Copyright 2016 -# - -import logging -import isceobj -import os -from isceobj.Constants import SPEED_OF_LIGHT -import numpy as np - -logger = logging.getLogger('isce.scansarinsar.runCommonRangeSpectra') - - -def createVirtualCopy(infile, outfile): - ''' - Create a virtual copy as is. - ''' - from osgeo import gdal - import shutil - - ds = gdal.Open(infile + '.vrt', gdal.GA_ReadOnly) - width = ds.RasterXSize - lgth = ds.RasterYSize - - ds = None - - - img = isceobj.createSlcImage() - img.setWidth(width) - img.setLength(lgth) - img.setAccessMode('READ') - img.setFilename(outfile) - img.renderHdr() - - ##Copy VRT as is - shutil.copyfile( infile + '.vrt', outfile + '.vrt') - - - -def runCommonRangeSpectra(self): - '''Align central frequencies and pixel sizes. - ''' - - swathList = self._insar.getValidSwathList(self.swaths) - catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) - - print('Common swaths: ', swathList) - - for ind, swath in enumerate(swathList): - - ##Load master swath - master = self._insar.loadProduct( os.path.join(self._insar.masterSlcProduct, - 's{0}.xml'.format(swath))) - - ##Load slave swath - slave = self._insar.loadProduct( os.path.join(self._insar.slaveSlcProduct, - 's{0}.xml'.format(swath))) - - - ##Check for overlap frequency - centerfreq1 = SPEED_OF_LIGHT / master.radarWavelegth - bandwidth1 = np.abs( master.instrument.pulseLength * master.instrument.chirpSlope) - - centerfreq2 = SPEED_OF_LIGHT / slave.radarWavelegth - bandwidth2 = np.abs( slave.instrument.pulseLength * slave.instrument.chirpSlope) - - overlapfreq = self._insar.getOverlapFrequency(centerfreq1, bandwidth1, - centerfreq2, bandwidth2) - - if (overlapfreq is None): - print('No range bandwidth overlap found for swath {0}'.format(swath)) - raise Exception('No range spectra overlap') - - overlapbw = overlapfreq[1] - overlapfreq[0] - - print('Range spectra overlap for swath {0} : {1}'.format(swath, overlapbw)) - if overlapbw < self._insar.rangeSpectraOverlapThreshold: - raise Exception('Not enough range spectra overlap for swath {0}'.format(swath)) - - - centerfreq = 0.5 * (centerfreq1 + centerfreq2) - - - ###Check if master needs range filtering - if (np.abs(centerfreq1 - centerfreq) < 1.0) and ((bandwidth1 - 1.0) < overlapbw): - print('No need to range filter master slc for swath {0}'.format(swath)) - infile = master.image.filename - outfile = os.path.join(self._insar.commonRangeSpectraSlcDirectory, - os.path.sep.join(infile.split(os.path.sep)[-4:])) - os.makedirs( os.path.dirname(outfile)) - createVirtualCopy(infile, outfile) - ##Generate product - master.image.filename = outfile - self._insar.saveProduct(master, os.path.dirname(outfile) + '.xml') - - - else: - raise NotImplementedError('This feature will be available after porting rg_filter') - - - ###Check if slave needs range filtering - if (np.abs(centerfreq2 - centerfreq) < 1.0) and ((bandwidth2 - 1.0) < overlapbw): - print('No need to range filter slave slc for swath {0}'.format(swath)) - - infile = slave.image.filename - outfile = os.path.join(self._insar.commonRangeSpectraSlcDirectory, - os.path.sep.join(infile.split(os.path.sep)[-4:])) - os.makedirs( os.path.dirname(outfile)) - createVirtualCopy(infile, outfile) - ##Generate product - slave.image.filename = outfile - self._insar.saveProduct(slave, os.path.dirname(outfile) + '.xml') - - else: - raise NotImplementedError('This feature will be available after porting rg_filter') - - - catalog.printToLog(logger, "runCommonRangeSpectra") - self._insar.procDoc.addAllFromCatalog(catalog) diff --git a/components/isceobj/ScansarProc/runEqualizeSlcs.py b/components/isceobj/ScansarProc/runEqualizeSlcs.py deleted file mode 100644 index c9f02b2..0000000 --- a/components/isceobj/ScansarProc/runEqualizeSlcs.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Author: Piyush Agram -# Copyright 2016 -# - -import logging -import isceobj -import os -import numpy as np - -logger = logging.getLogger('isce.scansarinsar.runCommonRangeSpectra') - - -def createVirtualCopy(infile, outfile): - ''' - Create a virtual copy as is. - ''' - from osgeo import gdal - import shutil - - ds = gdal.Open(infile + '.vrt', gdal.GA_ReadOnly) - width = ds.RasterXSize - lgth = ds.RasterYSize - - ds = None - - - img = isceobj.createSlcImage() - img.setWidth(width) - img.setLength(lgth) - img.setAccessMode('READ') - img.setFilename(outfile) - img.renderHdr() - - ##Copy VRT as is - shutil.copyfile( infile + '.vrt', outfile + '.vrt') - - - -def runEqualizeSlcs(self): - '''Align central frequencies and pixel sizes. - ''' - - swathList = self._insar.getValidSwathList(self.swaths) - catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) - - print('Common swaths: ', swathList) - - for ind, swath in enumerate(swathList): - - ##Load master swath - master = self._insar.loadProduct( os.path.join(self._insar.commonRangeSpectraMasterSlcProduct, - 's{0}.xml'.format(swath))) - - ##Load slave swath - slave = self._insar.loadProduct( os.path.join(self._insar.commonRangeSpectraSlaveSlcProduct, - 's{0}.xml'.format(swath))) - - - ###Check if master needs range filtering - if (np.abs(master.instrument.rangeSamplingRate - slave.instrument.rangeSamplingRate) < 1.0) and ((master.PRF - slave.PRF) < 1.0): - print('No need to equalize pixesl for swath {0}'.format(swath)) - - - ####Copy master as is - infile = master.image.filename - outfile = os.path.join(self._insar.equalizedMasterSlcProduct, - 's{0}/swath.slc'.format(swath)) - os.makedirs( os.path.dirname(outfile)) - createVirtualCopy(infile, outfile) - ##Generate product - master.image.filename = outfile - self._insar.saveProduct(master, os.path.dirname(outfile) + '.xml') - - - ###Copy slave as is - infile = slave.image.filename - outfile = os.path.join(self._insar.equalizedSlaveSlcProduct, - 's{0}/swath.slc'.format(swath)) - os.makedirs( os.path.dirname(outfile)) - createVirtualCopy(infile, outfile) - ##Generate product - slave.image.filename = outfile - self._insar.saveProduct(slave, os.path.dirname(outfile) + '.xml') - - else: - raise NotImplementedError("We haven't implemented this yet. Maybe we can get around this. To be explored ...") - - - catalog.printToLog(logger, "runEqualizeSlcs") - self._insar.procDoc.addAllFromCatalog(catalog) diff --git a/components/isceobj/ScansarProc/runEstimateBurstSync.py b/components/isceobj/ScansarProc/runEstimateBurstSync.py deleted file mode 100644 index cd7581b..0000000 --- a/components/isceobj/ScansarProc/runEstimateBurstSync.py +++ /dev/null @@ -1,123 +0,0 @@ -# -# Author: Piyush Agram -# Copyright 2016 -# - -import logging -import isceobj -import os -import numpy as np -import datetime - -logger = logging.getLogger('isce.scansarinsar.runEstimateBurstSync') - - -def runEstimateBurstSync(self): - '''Estimate burst sync between acquisitions. - ''' - - swathList = self._insar.getValidSwathList(self.swaths) - catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) - - print('Common swaths: ', swathList) - - if not os.path.isdir(self._insar.burstSyncDirectory): - os.makedirs(self._insar.burstSyncDirectory) - - for ind, swath in enumerate(swathList): - - ##Load master swath - master = self._insar.loadProduct( os.path.join(self._insar.equalizedMasterSlcProduct, - 's{0}.xml'.format(swath))) - - ##Load slave swath - slave = self._insar.loadProduct( os.path.join(self._insar.equalizedSlaveSlcProduct, - 's{0}.xml'.format(swath))) - - ##Replacing Cunren's original high fidelity implementation with simpler more efficient one - ##To estimate burst sync, we dont really need the DEM. Hardly changes with topography - ##Topo impacts range offset but hardly affects azimuth offsets. Hence using a single estimate - ##At mid range and start of middle burst of the master. - ##In the original implementation - topo and geo2rdr were performed to the mid 100 lines of - ##master image. Eventually, offset estimates were averaged to a single number. - ##Our single estimate gets us to that number in a simpler manner. - - ###Get mid range for middle burst of master - midRange = master.startingRange + 0.5 * master.numberOfSamples * master.instrument.rangePixelSize - midLine = master.burstStartLines[len(master.burstStartLines)//2] - - tmaster = master.sensingStart + datetime.timedelta(seconds = midLine / master.PRF) - llh = master.orbit.rdr2geo(tmaster, midRange) - - slvaz, slvrng = slave.orbit.geo2rdr(llh) - - - ###Translate to offsets - rgoff = ((slvrng - slave.startingRange) / slave.instrument.rangePixelSize) - 0.5 * master.numberOfSamples - azoff = ((slvaz - slave.sensingStart).total_seconds() * slave.PRF) - midLine - - - ##Jumping back to Cunren's original code - scburstStartLine = master.burstStartLines[0] + azoff - nb = slave.nbraw - nc = slave.ncraw - - #Slave burst start times corresponding to master burst start times implies 100% synchronization - scburstStartLines = scburstStartLine + np.arange(-100000, 100000)*nc - dscburstStartLines = -(slave.burstStartLines[0] - scburstStartLines) - - unsynLines = dscburstStartLines[ np.argmin( np.abs(dscburstStartLines))] - - if np.abs(unsynLines) >= nb: - synLines = 0 - if unsynLines > 0: - unsynLines = nb - else: - unsynLines = -nb - else: - synLines = nb - np.abs(unsynLines) - - - ##Copy of illustration from Cunren's code - ############################################################# ############################### - #illustration of the sign of the number of unsynchronized lin es (unsynLines) - #The convention is the same as ampcor offset, that is, - # slaveLineNumber = masterLineNumber + unsynLine s - # - # |-----------------------| ------------ - # | | ^ - # | | | - # | | | unsynLines < 0 - # | | | - # | | \ / - # | | |-----------------------| - # | | | | - # | | | | - # |-----------------------| | | - # Master Burst | | - # | | - # | | - # | | - # | | - # |-----------------------| - # Slave Burst - # - # - ############################################################# ############################### - - ##For now keeping Cunren's text file format. - ##Could be streamlined - outfile = os.path.join(self._insar.burstSyncDirectory, 's{0}.txt'.format(swath)) - self._insar.writeBurstSyncFile(outfile, rgoff, azoff, - nb, nc, - unsynLines, synLines) - - synPerc = (synLines/nb)*100.0 - - if synPerc < self.burstOverlapThreshold: - print('Sync overlap {0} < {1}. Will trigger common azimuth spectra filter for swath {2}'.format(synPerc, self.burstOverlapThreshold, swath)) - else: - print('Sync overlap {0} >= {1}. No common azimuth spectra filter applied for swath {2}'.format(synPerc, self.burstOverlapThreshold, swath)) - - catalog.printToLog(logger, "runEstimateBurstSync") - self._insar.procDoc.addAllFromCatalog(catalog) diff --git a/components/isceobj/ScansarProc/runPreprocessor.py b/components/isceobj/ScansarProc/runPreprocessor.py deleted file mode 100644 index 097e604..0000000 --- a/components/isceobj/ScansarProc/runPreprocessor.py +++ /dev/null @@ -1,80 +0,0 @@ -# -# Author: Piyush Agram -# Copyright 2016 -# - -import logging -import isceobj -import mroipac -from mroipac.baseline.Baseline import Baseline -import copy -import os -logger = logging.getLogger('isce.scansarinsar.runPreprocessor') - -def runPreprocessor(self): - '''Extract images. - ''' - - virtual = self.useVirtualFiles - catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name) - - - ###First set maximum number of swaths possible for a sensor. - self._insar.numberOfSwaths = self.master.maxSwaths - swathList = self._insar.getInputSwathList(self.swaths) - - catalog.addItem('Input list of swaths to process: ', swathList, 'common') - - self.master.configure() - - ##Processing master first. - self.master.configure() - self.master.swaths = swathList - self.master.virtualFiles = self.useVirtualFiles - - ##Assume a single folder is provided for now. - ##Leaving room for future extensions. - self.master.inputDirList = self.master.inputDirList[0] - - swaths = self.master.extractImage() - - self.insar.masterSlcProduct = os.path.dirname(os.path.dirname(swaths[0].image.filename)) - print('Master product: ', self.insar.masterSlcProduct) - - for ind, swath in enumerate(swaths): - catalog.addInputsFrom(swath, 'master.sensor_{0}'.format(swathList[ind])) - catalog.addItem('swathWidth_{0}'.format(swathList[ind]), swath.numberOfSamples, 'master') - catalog.addItem('swathLength_{0}'.format(swathList[ind]), swath.numberOfLines, 'master') - #catalog.addItem('numberOfBursts_{0}'.format(swathList[ind]), len(swath.burstStartLines), 'master') - - self._insar.saveProduct(swath, os.path.dirname(swath.image.filename) + '.xml') - - - - ##Processing slave next. - self.slave.configure() - self.slave.swaths = swathList - self.slave.virtualFiles = self.useVirtualFiles - - ##Assume a single folder is provided for now. - ##Leaving room for future extensions. - self.slave.inputDirList = self.slave.inputDirList[0] - - swaths = self.slave.extractImage() - - self.insar.slaveSlcProduct = os.path.dirname( os.path.dirname(swaths[0].image.filename)) - - print('Slave Product: ', self.insar.slaveSlcProduct) - for ind, swath in enumerate(swaths): - catalog.addInputsFrom(swath, 'slave.sensor_{0}'.format(swathList[ind])) - catalog.addItem('swathWidth_{0}'.format(swathList[ind]), swath.numberOfSamples, 'slave') - catalog.addItem('swathLength_{0}'.format(swathList[ind]), swath.numberOfLines, 'slave') - #catalog.addItem('numberOfBursts_{0}'.format(swathList[ind]), len(swath.burstStartLines), 'master') - - self._insar.saveProduct(swath, os.path.dirname(swath.image.filename) + '.xml') - - - - - catalog.printToLog(logger, "runPreprocessor") - self._insar.procDoc.addAllFromCatalog(catalog) diff --git a/components/isceobj/Sensor/SConscript b/components/isceobj/Sensor/SConscript index 0c4492e..d82f020 100644 --- a/components/isceobj/Sensor/SConscript +++ b/components/isceobj/Sensor/SConscript @@ -56,5 +56,4 @@ SConscript(os.path.join('src', 'SConscript'), variant_dir = os.path.join(install, 'src')) SConscript(os.path.join('TOPS','SConscript')) SConscript(os.path.join('GRD', 'SConscript')) -SConscript(os.path.join('ScanSAR', 'SConscript')) SConscript(os.path.join('MultiMode', 'SConscript')) diff --git a/components/isceobj/Sensor/ScanSAR/ALOS2.py b/components/isceobj/Sensor/ScanSAR/ALOS2.py deleted file mode 100755 index 80b66b0..0000000 --- a/components/isceobj/Sensor/ScanSAR/ALOS2.py +++ /dev/null @@ -1,1027 +0,0 @@ -#!/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 -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - -import os -import datetime -import isceobj.Sensor.CEOS as CEOS -import logging -from isceobj.Orbit.Orbit import StateVector,Orbit -from isceobj.Planet.AstronomicalHandbook import Const -from isceobj.Planet.Planet import Planet -from iscesys.Component.Component import Component -from isceobj.Sensor import xmlPrefix -from isceobj.Util import Polynomial -from iscesys.DateTimeUtil import secondsSinceMidnight -import numpy as np -import struct - -INPUT_DIRECTORY_LIST = Component.Parameter( - 'inputDirList', - public_name='input directory', - type = str, - container = list, - mandatory = True, - doc = 'List of input directories to parse') - -INPUT_SWATH_LIST = Component.Parameter( - 'swaths', - public_name='swaths', - type=int, - container=list, - mandatory=False, - default=None, - doc = 'List of swaths to use') - -POLARIZATION = Component.Parameter( - 'polarization', - public_name='polarization', - type=str, - default='hh', - mandatory=False, - doc='Polarization to search for') - -VIRTUAL_FILES = Component.Parameter( - 'virtualFiles', - public_name='use virtual files', - type=bool, - default=True, - mandatory=False, - doc='Use virtual files instead of using disk space') - -OUTPUTDIR = Component.Parameter( - 'output', - public_name='output directory', - type = str, - default=None, - mandatory = True, - doc = 'Output directory for unpacking the data') - - -MAX_SWATHS = Component.Parameter( - 'maxSwaths', - public_name='maximum number of swaths', - type=int, - default=5, - mandatory=True, - doc = 'Maximum number of swaths to scan for') - -####ALOS2 directory browser -class ALOS2Scanner(Component): - - family = 'alos2scanner' - - parameter_list = (INPUT_DIRECTORY_LIST, - INPUT_SWATH_LIST, - POLARIZATION, - VIRTUAL_FILES, - OUTPUTDIR, - MAX_SWATHS) - - modes = ['WBS', 'WBD', 'WWS', 'WWD', 'VBS', 'VBD'] - - - def __init__(self, name=''): - super(ALOS2Scanner, self).__init__(family=self.__class__.family, name=name) - - - def scan(self): - - if isinstance(self.inputDirList, str): - self.inputDirList = [self.inputDirList] - - frames = [] - for indir in self.inputDirList: - frames.append( self.scanDir(indir)) - - if len(frames) == 0: - raise Exception('No products found in the input directories') - - ###Estimate common swaths - return frames - - - def extractImage(self): - ''' - Actual extraction of SLCs. - ''' - - totalSwaths = [] - - frames = self.scan() - - ###Currently assuming one frame - ###Modify here for multiple frames - for swathid, img in frames[0].items(): - - sensor = ALOS2() - sensor.configure() - sensor._leaderFile = img['leaderfile'] - sensor._imageFile = img['imgfile'] - - outdir = os.path.join(self.output, img['frame'], 's{0}'.format(swathid)) - sensor.output = os.path.join(outdir, 'swath.slc') - - if not os.path.isdir(outdir): - os.makedirs(outdir) - - sensor.extractImage(virtual=self.virtualFiles) - sensor.extractDoppler() - sensor.refineBurstTiming() - - totalSwaths.append(sensor.frame) - - return totalSwaths - - def scanDir(self, indir): - ''' - Scan directory for IMG files. - ''' - - import glob - import os - - imgFiles = glob.glob(os.path.join(indir, 'IMG-{0}-ALOS2*-*-*'.format(self.polarization.upper()))) - ###No IMG files found - if len(imgFiles) == 0: - return None - - ###Sort the filenames - imgFiles = sorted(imgFiles) - - ####### - wbFiles = [] - for infile in imgFiles: - basefile = os.path.basename(infile) - - ##Check for each mode - for mode in self.modes: - if mode in basefile: - wbFiles.append(infile) - break - - if len(wbFiles) == 0: - return None - - ###Check if user has requested specific files - frames = [] - datatakes = [] - imgmodes = [] - for infile in wbFiles: - basefile = os.path.basename(infile) - frames.append( basefile.split('-')[2][-4:]) - datatakes.append( basefile.split('-')[2][5:10]) - imgmodes.append( basefile.split('-')[-2][0:3]) - - if any([x!=frames[0] for x in frames]): - print('Multiple frames found in same dir') - print(set(frames)) - raise Exception('Multiple ALOS2 frames in same dir') - - if any([x!=datatakes[0] for x in datatakes]): - print('Multiple datatakes found in same dir') - print(set(datatakes)) - raise Exception('Multiple ALOS2 datatakes found in same dir') - - if any([x!=imgmodes[0] for x in imgmodes]): - print('Multiple imaging modes found in same dir') - print(set(imgmodes)) - raise Exception('Multiple ALOS2 imaging modes found in same dir') - - swaths = {} - for infile in wbFiles: - params = {} - params['datatake'] = datatakes[0] - params['frame'] = frames[0] - params['imgfile'] = infile - - swathid = int(os.path.basename(infile)[-1]) - - ##If user has requested specific swaths - if self.swaths: - if swathid in self.swaths: - swaths[swathid] = params - else: - swaths[swathid] = params - - - ###Ensure that a LED file exists that matches the data - ldrfiles = glob.glob(os.path.join(indir, 'LED-ALOS2{0}{1}-*'.format(datatakes[0], frames[0]))) - if len(ldrfiles) == 0: - raise Exception('No leader file found in ALOS2 directory') - - if len(ldrfiles) > 1: - raise Exception('More than one leader file found in ALOS2 directory') - - leaderFile = ldrfiles[0] - - for key, val in swaths.items(): - swaths[key]['leaderfile'] = leaderFile - - return swaths - - - - - - - -#####Actual ALOS reader -#Sometimes the wavelength in the meta data is not correct. -#If the user sets this parameter, then the value in the -#meta data file is ignored. -WAVELENGTH = Component.Parameter( - 'wavelength', - public_name='radar wavelength', - default=None, - type=float, - mandatory=False, - doc='Radar wavelength in meters.' -) - -LEADERFILE = Component.Parameter( - '_leaderFile', - public_name='leaderfile', - default=None, - type=str, - mandatory=True, - doc='Name of the leaderfile.' -) - -IMAGEFILE = Component.Parameter( - '_imageFile', - public_name='imagefile', - default=None, - type=str, - mandatory=True, - doc='Name of the imagefile.' -) - -OUTPUT = Component.Parameter('output', - public_name='OUTPUT', - default=None, - type=str, - doc = 'Directory where bursts get unpacked') - - -###List of facilities -FRAME = Component.Facility('frame', - public_name = 'frame', - module = 'isceobj.Sensor.ScanSAR', - factory = 'createFullApertureSwathSLCProduct', - args = (), - mandatory=True, - doc = 'Full aperture swath slc product populated by the reader') - - -class ALOS2(Component): - """ - Code to read CEOSFormat leader files for ALOS2 SLC data. - """ - - family = 'alos2' - - parameter_list = (WAVELENGTH, - LEADERFILE, - IMAGEFILE, - OUTPUT) - - facility_list = (FRAME,) - fsampConst = { 104: 1.047915957140240E+08, - 52: 5.239579785701190E+07, - 34: 3.493053190467460E+07, - 17: 1.746526595233730E+07 } - - #Orbital Elements (Quality) Designator - #ALOS-2/PALSAR-2 Level 1.1/1.5/2.1/3.1 CEOS SAR Product Format Description - #PALSAR-2_xx_Format_CEOS_E_r.pdf - orbitElementsDesignator = {'0':'preliminary', - '1':'decision', - '2':'high precision'} - - def __init__(self, name=''): - super().__init__(family=self.__class__.family, name=name) - self.leaderFile = None - self.imageFile = None - - #####Soecific doppler functions for ALOS2 - self.doppler_coeff = None - self.azfmrate_coeff = None - self.lineDirection = None - self.pixelDirection = None - - self.constants = {'polarization': 'HH', - 'antennaLength': 10} - - - def getFrame(self): - return self.frame - - def parse(self): - self.leaderFile = LeaderFile(self, file=self._leaderFile) - self.leaderFile.parse() - - self.imageFile = ImageFile(self, file=self._imageFile) - self.imageFile.parse() - - self.populateMetadata() - - def populateMetadata(self): - """ - Create the appropriate metadata objects from our CEOSFormat metadata - """ - frame = self._decodeSceneReferenceNumber(self.leaderFile.sceneHeaderRecord.metadata['Scene reference number']) - - fsamplookup = int(self.leaderFile.sceneHeaderRecord.metadata['Range sampling rate in MHz']) - - rangePixelSize = Const.c/(2*self.fsampConst[fsamplookup]) - - ins = self.frame.getInstrument() - platform = ins.getPlatform() - platform.setMission(self.leaderFile.sceneHeaderRecord.metadata['Sensor platform mission identifier']) - platform.setAntennaLength(self.constants['antennaLength']) - platform.setPointingDirection(1) - platform.setPlanet(Planet(pname='Earth')) - - if self.wavelength: - ins.setRadarWavelength(float(self.wavelength)) -# print('ins.radarWavelength = ', ins.getRadarWavelength(), -# type(ins.getRadarWavelength())) - else: - ins.setRadarWavelength(self.leaderFile.sceneHeaderRecord.metadata['Radar wavelength']) - - ins.setIncidenceAngle(self.leaderFile.sceneHeaderRecord.metadata['Incidence angle at scene centre']) - self.frame.getInstrument().setPulseRepetitionFrequency(self.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency in mHz']*1.0e-3) - ins.setRangePixelSize(rangePixelSize) - ins.setRangeSamplingRate(self.fsampConst[fsamplookup]) - ins.setPulseLength(self.leaderFile.sceneHeaderRecord.metadata['Range pulse length in microsec']*1.0e-6) - chirpSlope = self.leaderFile.sceneHeaderRecord.metadata['Nominal range pulse (chirp) amplitude coefficient linear term'] - chirpPulseBandwidth = abs(chirpSlope * self.leaderFile.sceneHeaderRecord.metadata['Range pulse length in microsec']*1.0e-6) - ins.setChirpSlope(chirpSlope) - ins.setInPhaseValue(7.5) - ins.setQuadratureValue(7.5) - - self.lineDirection = self.leaderFile.sceneHeaderRecord.metadata['Time direction indicator along line direction'].strip() - self.pixelDirection = self.leaderFile.sceneHeaderRecord.metadata['Time direction indicator along pixel direction'].strip() - - ######ALOS2 includes this information in clock angle - clockAngle = self.leaderFile.sceneHeaderRecord.metadata['Sensor clock angle'] - if clockAngle == 90.0: - platform.setPointingDirection(-1) - elif clockAngle == -90.0: - platform.setPointingDirection(1) - else: - raise Exception('Unknown look side. Clock Angle = {0}'.format(clockAngle)) - -# print(self.leaderFile.sceneHeaderRecord.metadata["Sensor ID and mode of operation for this channel"]) - self.frame.setFrameNumber(frame) - self.frame.setOrbitNumber(self.leaderFile.sceneHeaderRecord.metadata['Orbit number']) - self.frame.setProcessingFacility(self.leaderFile.sceneHeaderRecord.metadata['Processing facility identifier']) - self.frame.setProcessingSystem(self.leaderFile.sceneHeaderRecord.metadata['Processing system identifier']) - self.frame.setProcessingSoftwareVersion(self.leaderFile.sceneHeaderRecord.metadata['Processing version identifier']) - self.frame.setPolarization(self.constants['polarization']) - self.frame.setNumberOfLines(self.imageFile.imageFDR.metadata['Number of lines per data set']) - self.frame.setNumberOfSamples(self.imageFile.imageFDR.metadata['Number of pixels per line per SAR channel']) - - ###### - orb = self.frame.getOrbit() - - orb.setOrbitSource('Header') - orb.setOrbitQuality( - self.orbitElementsDesignator[ - self.leaderFile.platformPositionRecord.metadata['Orbital elements designator'] - ] - ) - t0 = datetime.datetime(year=self.leaderFile.platformPositionRecord.metadata['Year of data point'], - month=self.leaderFile.platformPositionRecord.metadata['Month of data point'], - day=self.leaderFile.platformPositionRecord.metadata['Day of data point']) - t0 = t0 + datetime.timedelta(seconds=self.leaderFile.platformPositionRecord.metadata['Seconds of day']) - - #####Read in orbit in inertial coordinates - deltaT = self.leaderFile.platformPositionRecord.metadata['Time interval between data points'] - numPts = self.leaderFile.platformPositionRecord.metadata['Number of data points'] - - - orb = self.frame.getOrbit() - for i in range(numPts): - vec = StateVector() - t = t0 + datetime.timedelta(seconds=i*deltaT) - vec.setTime(t) - - dataPoints = self.leaderFile.platformPositionRecord.metadata['Positional Data Points'][i] - pos = [dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z']] - vel = [dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z']] - vec.setPosition(pos) - vec.setVelocity(vel) - orb.addStateVector(vec) - - - ###This is usually available with ALOS SLC data. - ###Unfortunately set to all zeros for ScanSAR data - #self.doppler_coeff = [self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid constant term'], - #self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid linear term'], - #self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency centroid quadratic term']] - - - self.azfmrate_coeff = [self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency rate constant term'], - self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency rate linear term'], - self.leaderFile.sceneHeaderRecord.metadata['Cross track Doppler frequency rate quadratic term']] - - - ###Reading in approximate values instead - ###Note that these are coeffs vs slant range in km - self.doppler_coeff = [self.leaderFile.sceneHeaderRecord.metadata['Doppler center frequency constant term'], - self.leaderFile.sceneHeaderRecord.metadata['Doppler center frequency linear term']] - -# print('Terrain height: ', self.leaderFile.sceneHeaderRecord.metadata['Average terrain ellipsoid height']) - - - def extractImage(self, virtual=False): - import isceobj - if (self.imageFile is None) or (self.leaderFile is None): - self.parse() - - - ###Generating XML file first as renderHdr also creates a VRT - ###We want the virtual CEOS VRT to overwrite the general style VRT - rawImage = isceobj.createSlcImage() - rawImage.setByteOrder('l') - rawImage.setFilename(self.output) - rawImage.setAccessMode('read') - rawImage.setWidth(self.imageFile.width) - rawImage.setLength(self.imageFile.length) - rawImage.setXmin(0) - rawImage.setXmax(self.imageFile.width) - rawImage.renderHdr() - self.frame.setImage(rawImage) - - self.imageFile.extractImage(output=self.output, virtual=virtual) - - self.frame.setSensingStart(self.imageFile.sensingStart) - self.frame.setSensingStop(self.imageFile.sensingStop) - sensingMid = self.imageFile.sensingStart + datetime.timedelta(seconds = 0.5* (self.imageFile.sensingStop - self.imageFile.sensingStart).total_seconds()) - self.frame.setSensingMid(sensingMid) - - self.frame.setStartingRange(self.imageFile.nearRange) - - self.frame.getInstrument().setPulseRepetitionFrequency(self.imageFile.prf) - - pixelSize = self.frame.getInstrument().getRangePixelSize() - farRange = self.imageFile.nearRange + (pixelSize-1) * self.imageFile.width - self.frame.setFarRange(farRange) - - return - - - def extractDoppler(self): - ''' - Evaluate the doppler and fmrate polynomials. - ''' - import copy - - ##We typically use this ALOS2 SLCs - ####CEOS already provides function vs pixel - #self.frame._dopplerVsPixel = self.doppler_coeff - - - ##Instead for ScanSAR data, we have to do the mapping from approx coeffs - frame = self.frame - width = frame.getNumberOfSamples() - rng = frame.startingRange + np.arange(0,width,100) * 0.5 * Const.c/frame.rangeSamplingRate - doppler = self.doppler_coeff[0] + self.doppler_coeff[1] * rng/1000. - dfit = np.polyfit( np.arange(0, width, 100), doppler, 1) - self.frame._dopplerVsPixel=[dfit[1], dfit[0], 0., 0.] - - ##We have to compute FM rate here. - ##Cunren's observation that this is all set to zero in CEOS file. - ##Simplification from Cunren's fmrate.py script - ##Should be the same as the one in focus.py - planet = self.frame.instrument.platform.planet - elp = copy.copy(planet.ellipsoid) - svmid = self.frame.orbit.interpolateOrbit(self.frame.sensingMid, method='hermite') - xyz = svmid.getPosition() - vxyz = svmid.getVelocity() - llh = elp.xyz_to_llh(xyz) - hdg = self.frame.orbit.getENUHeading(self.frame.sensingMid) - - elp.setSCH(llh[0], llh[1], hdg) - sch, schvel = elp.xyzdot_to_schdot(xyz, vxyz) - - ##Computeation of acceleration - dist= np.linalg.norm(xyz) - r_spinvec = np.array([0., 0., planet.spin]) - r_tempv = np.cross(r_spinvec, xyz) - inert_acc = np.array([-planet.GM*x/(dist**3) for x in xyz]) - r_tempa = np.cross(r_spinvec, vxyz) - r_tempvec = np.cross(r_spinvec, r_tempv) - axyz = inert_acc - 2 * r_tempa - r_tempvec - - schbasis = elp.schbasis(sch) - schacc = np.dot(schbasis.xyz_to_sch, axyz).tolist()[0] - - - ##Jumping back straight into Cunren's script here - centerVel = schvel - centerAcc = schacc - avghgt = llh[2] - radiusOfCurvature = elp.pegRadCur - frame = self.frame - - fmrate = [] - width = self.frame.getNumberOfSamples() - lookSide = self.frame.instrument.platform.pointingDirection - centerVelNorm = np.linalg.norm(centerVel) - - ##Retaining Cunren's code for computing at every pixel. - ##Can be done every 10th pixel since we only fit a quadratic/ cubic. - ##Also can be vectorized for speed. - - for ii in range(width): - rg = frame.startingRange + ii * 0.5 * Const.c / frame.rangeSamplingRate - dop = np.polyval(frame._dopplerVsPixel[::-1], ii) - - th = np.arccos(((avghgt+radiusOfCurvature)**2 + rg**2 -radiusOfCurvature**2)/(2.0 * (avghgt + radiusOfCurvature) * rg)) - thaz = np.arcsin(((frame.radarWavelegth*dop/(2.0*np.sin(th))) + (centerVel[2] / np.tan(th))) / np.sqrt(centerVel[0]**2 + centerVel[1]**2)) - lookSide * np.arctan(centerVel[1]/centerVel[0]) - - lookVec = [ np.sin(th) * np.sin(thaz), - np.sin(th) * np.cos(thaz) * lookSide, - -np.cos(th)] - - vdotl = np.dot(lookVec, centerVel) - adotl = np.dot(lookVec, centerAcc) - fmratex = 2.0*(adotl + (vdotl**2 - centerVelNorm**2)/rg)/(frame.radarWavelegth) - fmrate.append(fmratex) - - - ##Fitting order 2 polynomial to FM rate - p = np.polyfit(np.arange(width), fmrate,2) - frame._fmrateVsPixel = list(p[::-1]) - - - def _decodeSceneReferenceNumber(self,referenceNumber): - return referenceNumber - - - def refineBurstTiming(self): - ''' - This is combination of burst_time2.py and burst_time.py from Cunren. - ''' - - slc = self.frame.image.filename - - ##First pass of burst_time.py - delta_line = 15000 - bursts1 = self.burst_time( slc, - firstLine=delta_line, firstPixel=1000) - - - ##Number of burst cycles - num_nc = np.around((self.frame.getNumberOfLines() - delta_line*2)/ self.frame.ncraw) - - ###Second pass - start_line2 = np.around( delta_line + num_nc * self.frame.ncraw) - bursts2 = self.burst_time( slc, - firstLine=start_line2, firstPixel=1000) - - ###Check if there were differences - LineDiffIndex = 0 - LineDiffMin = np.fabs( bursts1['estimatedStartLine'] + self.frame.ncraw * LineDiffIndex - bursts2['estimatedStartLine']) - - for ii in range(100000): - LineDiffMinx = np.fabs(bursts1['estimatedStartLine'] + self.frame.ncraw * ii - bursts2['estimatedStartLine']) - if LineDiffMinx <= LineDiffMin: - LineDiffMin = LineDiffMinx - LineDiffIndex = ii - - ###Update correct burst cycle value - print('Burst cycle length before correction: ', self.frame.ncraw) - self.frame.ncraw = self.frame.ncraw - (bursts1['estimatedStartLine'] + self.frame.ncraw * LineDiffIndex - bursts2['estimatedStartLine'])/LineDiffIndex - print('Burst cycle length after correction: ', self.frame.ncraw) - - - ###Final run with updated burst cycle length - start_line1 = np.around(self.frame.getNumberOfLines() / 2.0) - bursts = self.burst_time( slc, - firstLine=start_line1, firstPixel=1000) - - self.frame.burstStartLines = bursts['startLines'] - for ii, val in enumerate(self.frame.burstStartLines): - print('Burst: {0}, Line: {1}'.format(ii, val)) - - def burst_time(self, slcfile, - firstLine=500, firstPixel=500, - nRange=400): - ''' - Generates a linear FM signal and returns correlation with signal. - ''' - - def create_lfm(ns, it, offset, k): - ''' - Create linear FM signal. - ns: Number of samples - it: Time interval of samples - offset: offset - k: linear FM rate - ''' - ht = (ns-1)/2.0 - t = np.arange(-ht, ht+1.0, 1) - t = (t + offset) * it - lfm = np.exp(1j * np.pi * k * t**2) - return lfm - - from osgeo import gdal - - frame = self.frame - width = frame.getNumberOfSamples() - length = frame.getNumberOfLines() - prf = frame.PRF - nb = frame.nbraw - nc = frame.ncraw - fmrateCoeff = frame._fmrateVsPixel - sensing_start = frame.getSensingStart() - - ###Using convention that Fmrate is positive - ka = -np.polyval(fmrateCoeff[::-1], np.arange(width)) - - ###Area to be used for estimation - saz = firstLine #Startline to be included - naz = int(np.round(nc)) #Number of lines to be used - eaz = saz + naz-1 #Ending line to be used - caz = int(np.round((saz+eaz)/2.0)) #Central line of lines used - caz_deramp = (saz+eaz)/2.0 #Center of deramp signal - - srg = firstPixel #Start column to be used - nrg = nRange #Number columns to be used - erg = srg + nrg - 1 #Ending column to be used - crg = int(np.round((srg+erg)/2.0)) #Central column - - - if not (saz >=0 and saz <= length-1): - raise Exception('Invalid starting line \n') - - if not (eaz >=0 and eaz <= length-1): - raise Exception('Invalid ending line \n') - - if not (srg >= 0 and erg <= width-1): - raise Exception('Invalid starting column \n') - - if not (erg >=0 and erg <= width-1): - raise Exception('Invalid ending column \n') - - ###Calculate full aperture length - nFullAperture = int(np.round(prf/ka[crg]/(1.0/prf))) - nazfft = int(2**(int(np.ceil(np.log2(nFullAperture))))) - - ###Create the deramp function using fmrate - deramp = np.zeros((naz,nrg), dtype=np.complex64) - for ii in range(nrg): - deramp[:,ii] = create_lfm(naz, 1.0/prf, 0, -ka[ii+srg]) - - ###Read in chunk of data - ds = gdal.Open(slcfile + '.vrt', gdal.GA_ReadOnly) - data = ds.ReadAsArray(srg, saz, nrg, naz) - ds = None - - ###deramp the data - datadr = deramp * data - - #Compute spectrum - spec = np.fft.fft(datadr, n=nazfft, axis=0) - - #Center the spectrum - spec = np.fft.fftshift(spec, axes=0) - - ##Average the spectrum - avgSpec = np.mean( np.abs(spec), axis=1) - - ###Number of bursts in freq domain - nbs = int(np.round(nb*(1.0/prf)*ka[crg]/prf*nazfft)) - - ###Number of samples of the burst cycle in frequency domain - ncs = int(np.round(nc*(1.0/prf)*ka[crg]/prf*nazfft)) - - ###Create a signal corresponding to 1 burst spectrum length - rect = np.ones(nbs, dtype=np.float32) - - ##Correlated burst with average spectrum - corr = np.correlate(avgSpec, rect, 'same') - - ###Find burst spectrum center - ncs_rh = int(np.round((nazfft - ncs)/2.0)) - - ##Offset between spectrum center and center - offset_spec = np.argmax(corr[ncs_rh:ncs_rh+ncs]) + ncs_rh - (nazfft-1.0)/2.0 - - ##Offset in azimuth lines - offset_naz = offset_spec / nazfft * prf / ka[crg] / (1.0 / prf) - - ##Starting line of the burst (fractional line number) - saz_burst = -offset_naz + caz_deramp - (nb-1.0)/2.0 - - ####Find the start lines of all bursts - burstStartLines = [] - burstStartTimes = [] - - for ii in range(-100000, 100000): - saz_burstx = saz_burst + nc * ii - - if (saz_burstx >= 0.0) and (saz_burstx <= length): - st_burstx = sensing_start + datetime.timedelta(seconds=saz_burstx/prf) - burstStartLines.append(saz_burstx) - burstStartTimes.append(st_burstx) - - bursts = {} - bursts['startLines'] = burstStartLines - bursts['startTimes'] = burstStartTimes - bursts['estimatedStartLine'] = saz_burst - - #for ii in range(len(bursts['startLines'])): - # print(ii, bursts['startLines'][ii], bursts['startTimes'][ii]) - - return bursts - - - -class LeaderFile(object): - - def __init__(self, parent, file=None): - self.parent = parent - self.file = file - self.leaderFDR = None - self.sceneHeaderRecord = None - self.platformPositionRecord = None - - def parse(self): - """ - Parse the leader file to create a header object - """ - try: - fp = open(self.file,'rb') - except IOError as errs: - errno,strerr = errs - print("IOError: %s" % strerr) - return - # Leader record - self.leaderFDR = CEOS.CEOSDB(xml=os.path.join(xmlPrefix,'alos2_slc/leader_file.xml'),dataFile=fp) - self.leaderFDR.parse() - fp.seek(self.leaderFDR.getEndOfRecordPosition()) - - # Scene Header - self.sceneHeaderRecord = CEOS.CEOSDB(xml=os.path.join(xmlPrefix,'alos2_slc/scene_record.xml'),dataFile=fp) - self.sceneHeaderRecord.parse() - fp.seek(self.sceneHeaderRecord.getEndOfRecordPosition()) - - # Platform Position - self.platformPositionRecord = CEOS.CEOSDB(xml=os.path.join(xmlPrefix,'alos2_slc/platform_position_record.xml'),dataFile=fp) - self.platformPositionRecord.parse() - fp.seek(self.platformPositionRecord.getEndOfRecordPosition()) - - #####Skip attitude information - fp.seek(16384,1) - - #####Skip radiometric information - fp.seek(9860,1) - - ####Skip the data quality information - fp.seek(1620,1) - - - ####Skip facility 1-4 - fp.seek(325000 + 511000 + 3072 + 728000, 1) - - - ####Read facility 5 - self.facilityRecord = CEOS.CEOSDB(xml=os.path.join(xmlPrefix,'alos2_slc/facility_record.xml'), dataFile=fp) - self.facilityRecord.parse() - fp.close() - -class VolumeDirectoryFile(object): - - def __init__(self,file=None): - self.file = file - self.metadata = {} - - def parse(self): - try: - fp = open(self.file,'rb') - except IOError as errs: - errno,strerr = errs - print("IOError: %s" % strerr) - return - - volumeFDR = CEOS.CEOSDB(xml=os.path.join(xmlPrefix,'alos2_slc/volume_descriptor.xml'),dataFile=fp) - volumeFDR.parse() - fp.seek(volumeFDR.getEndOfRecordPosition()) - - fp.close() - - -class ImageFile(object): - - def __init__(self, parent, file=None): - self.parent = parent - self.file = file - self.imageFDR = None - self.sensingStart = None - self.sensingStop = None - self.nearRange = None - self.prf = None - self.image_record = os.path.join(xmlPrefix,'alos2_slc/image_record.xml') - self.logger = logging.getLogger('isce.sensor.alos2') - - def parse(self): - try: - fp = open(self.file,'rb') - except IOError as errs: - errno,strerr = errs - print("IOError: %s" % strerr) - return - - self.imageFDR = CEOS.CEOSDB(xml=os.path.join(xmlPrefix,'alos2_slc/image_file.xml'), dataFile=fp) - self.imageFDR.parse() - fp.seek(self.imageFDR.getEndOfRecordPosition()) - self._calculateRawDimensions(fp) - - fp.close() - - def writeRawData(self, fp, line): - ''' - Convert complex integer to complex64 format. - ''' - cJ = np.complex64(1j) - data = line[0::2] + cJ * line[1::2] - data.tofile(fp) - - - def extractImage(self, output=None, virtual=False): - """ - Extract I and Q channels from the image file - """ - if virtual: - output = output + '.vrt' - else: - try: - output = open(output, 'wb') - except IOError as strerr: - raise Exceptin("IOError: {0}".format(strerr)) - - - - if self.imageFDR is None: - self.parse() - - - ###Open the image file for reading - try: - fp = open(self.file, 'rb') - except IOError as strerr: - self.logger.error(" IOError: %s" % strerr) - return - - - fp.seek(self.imageFDR.getEndOfRecordPosition(),os.SEEK_SET) - offsetAfterImageFDR = fp.tell() - - - dataLen = self.imageFDR.metadata['Number of pixels per line per SAR channel'] - self.width = dataLen - - ##Leaderfile PRF - prf = self.parent.leaderFile.sceneHeaderRecord.metadata['Pulse Repetition Frequency in mHz']*1.0e-3 - - #choose PRF according to operation mode. Cunren Liang, 2015 - operationMode = "{}".format(self.parent.leaderFile.sceneHeaderRecord.metadata['Sensor ID and mode of operation for this channel']) - operationMode =operationMode[10:12] - if operationMode not in ['08', '09']: - # Operation mode - # '00': Spotlight mode - # '01': Ultra-fine - # '02': High-sensitive - # '03': Fine - # '08': ScanSAR nominal mode - # '09': ScanSAR wide mode - # '18': Full (Quad.) pol./High-sensitive - # '19': Full (Quad.) pol./Fine - print('This reader only supports ScanSAR full aperture data parsing.') - raise Exception('Use stripmap reader for other modes') - - if operationMode != '08': - raise Exception('Only ScanSAR nominal mode is currently supported') - - # Extract the I and Q channels - imageData = CEOS.CEOSDB(xml=self.image_record,dataFile=fp) - - ###If only a VRT needs to be written - for line in range(self.length): - if ((line%1000) == 0): - self.logger.debug("Extracting line %s" % line) - imageData.parseFast() - - ###Always read the first line virtual / not - if line==0: - offsetAfterFirstImageRecord = fp.tell() - yr = imageData.metadata['Sensor acquisition year'] - dys = imageData.metadata['Sensor acquisition day of year'] - msecs = imageData.metadata['Sensor acquisition milliseconds of day'] - usecs = imageData.metadata['Sensor acquisition micro-seconds of day'] - self.sensingStart = datetime.datetime(yr,1,1) + datetime.timedelta(days=(dys-1)) + datetime.timedelta(seconds = usecs*1e-6) - self.nearRange = imageData.metadata['Slant range to 1st data sample'] - self.prf = imageData.metadata['PRF'] * 1.0e-3 - sceneCenterIncidenceAngle = self.parent.leaderFile.sceneHeaderRecord.metadata['Incidence angle at scene centre'] - sarChannelId = imageData.metadata['SAR channel indicator'] - scanId = imageData.metadata['Scan ID'] #Scan ID starts with 1 - - ###Exit loop after first line if virtual - if virtual: - break - - - ###Write line to file if not virtual - IQLine = np.fromfile(fp, dtype='>f', count=2*dataLen) - self.writeRawData(output, IQLine) - - - fp.close() - - ####If virtual file was requested, create VRT here - if virtual: - ##Close input file - with open(output, 'w') as fid: - fid.write(''' - - {2} - MSB - {3} - 8 - {4} - -'''.format(self.width, self.length, - os.path.abspath(self.file), - offsetAfterFirstImageRecord, - dataLen*8 + offsetAfterFirstImageRecord - offsetAfterImageFDR)) - - else: - ##Close actual file on disk - output.close() - - - - #burst parameters, currently only for the second, dual polarization, ScanSAR nominal mode - #that is the second WBD mode. - #p.25 and p.115 of ALOS-2/PALSAR-2 Level 1.1/1.5/2.1/3.1 CEOS SAR Product Format Description - #for the definations of wide swath mode - nbraw = [358, 470, 358, 355, 487] - ncraw = [2086.26, 2597.80, 1886.18, 1779.60, 2211.17] - - self.parent.frame.nbraw = nbraw[scanId-1] - self.parent.frame.ncraw = ncraw[scanId-1] - - #this is the prf fraction (total azimuth bandwith) used in extracting burst. - #here the total bandwith is 0.93 * prfs[3] for all subswaths, which is the following values: - #[0.7933, 0.6371, 0.8774, 0.9300, 0.7485] - prfs=[2661.847, 3314.512, 2406.568, 2270.575, 2821.225] - - - #Only needed for burst extraction. Skipping for now .... - #self.parent.frame.prffrac = 0.93 * prfs[3]/prfs[scanId-1] - - - self.sensingStop = self.sensingStart + datetime.timedelta(seconds = (self.length-1)/self.prf) - - def _calculateRawDimensions(self,fp): - """ - Run through the data file once, and calculate the valid sampling window start time range. - """ - self.length = self.imageFDR.metadata['Number of SAR DATA records'] - #self.width = self.imageFDR.metadata['SAR DATA record length'] - self.width = self.imageFDR.metadata['Number of pixels per line per SAR channel'] - - return None diff --git a/components/isceobj/Sensor/ScanSAR/FullApertureSwathSLCProduct.py b/components/isceobj/Sensor/ScanSAR/FullApertureSwathSLCProduct.py deleted file mode 100755 index 4876e71..0000000 --- a/components/isceobj/Sensor/ScanSAR/FullApertureSwathSLCProduct.py +++ /dev/null @@ -1,119 +0,0 @@ -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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 -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - -import datetime -from iscesys.Component.Component import Component -from isceobj.Scene.Frame import Frame - -FMRATE_VS_PIXEL = Component.Parameter('_fmrateVsPixel', - public_name = 'FMRATE_VS_PIXEL', - default = [], - type = float, - mandatory = True, - container = list, - doc = 'Doppler polynomial coefficients vs pixel number') - -BURST_LENGTH = Component.Parameter('_burstLength', - public_name = 'Burst Length', - default = None, - type = int, - mandatory = True, - doc = 'Number of pulses in a burst') - -BURST_CYCLE_LENGTH = Component.Parameter('_burstCycleLength', - public_name = 'Burst cycle length', - default = None, - type = float, - mandatory = True, - doc = 'Number of pulses in a full cycle') - -BURST_START_LINES = Component.Parameter('burstStartLines', - public_name = 'Burst start lines', - default = [], - type = float, - container=list, - mandatory = True, - doc = 'Start lines of bursts in SLC') - -class FullApertureSwathSLCProduct(Frame): - """A class to represent a frame along a radar track""" - - family = 'frame' - logging_name = 'isce.isceobj.scansar.fullapertureswathslcproduct' - - parameter_list = Frame.parameter_list + (BURST_LENGTH, - BURST_CYCLE_LENGTH, - BURST_START_LINES, - FMRATE_VS_PIXEL) - - - def __init__(self, name=''): - super(FullApertureSwathSLCProduct, self).__init__(name=name) - return None - - - @property - def nbraw(self): - return self._burstLength - - @nbraw.setter - def nbraw(self, x): - self._burstLength = x - - @property - def ncraw(self): - return self._burstCycleLength - - @ncraw.setter - def ncraw(self, x): - self._burstCycleLength = x - - @property - def burstLength(self): - return self._burstLength - - @burstLength.setter - def burstLength(self, x): - self._burstLength = x - - @property - def burstCycleLength(self): - return self._burstCycleLength - - @burstCycleLength.setter - def burstCycleLength(self, x): - self._burstCycleLength = x - - @property - def fmrateVsPixel(self): - return self._fmrateVsPixel - - @fmrateVsPixel.setter - def fmrateVsPixel(self,x): - self._fmrateVsPixel = x diff --git a/components/isceobj/Sensor/ScanSAR/SConscript b/components/isceobj/Sensor/ScanSAR/SConscript deleted file mode 100644 index 8099bd2..0000000 --- a/components/isceobj/Sensor/ScanSAR/SConscript +++ /dev/null @@ -1,31 +0,0 @@ -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Walter Szeliga -# NASA Jet Propulsion Laboratory -# California Institute of Technology -# (c) 2010 All Rights Reserved -# -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -#!/usr/bin/env python -import os - -Import('envSensor') -envTOPS = envSensor.Clone() -project = 'ScanSAR' -package = envTOPS['PACKAGE'] -envTOPS['PROJECT'] = project -envTOPS['SENSOR_SCONS_INSTALL'] = os.path.join( - envTOPS['PRJ_SCONS_INSTALL'], package, 'Sensor',project) -install = envTOPS['SENSOR_SCONS_INSTALL'] - -listFiles = ['__init__.py','FullApertureSwathSLCProduct.py','ALOS2.py'] - -helpList,installHelp = envTOPS['HELP_BUILDER'](envTOPS,'__init__.py',install) - -envTOPS.Install(installHelp,helpList) -envTOPS.Alias('install',installHelp) - -envTOPS.Install(install,listFiles) -envTOPS.Alias('install',install) diff --git a/components/isceobj/Sensor/ScanSAR/__init__.py b/components/isceobj/Sensor/ScanSAR/__init__.py deleted file mode 100755 index c9827eb..0000000 --- a/components/isceobj/Sensor/ScanSAR/__init__.py +++ /dev/null @@ -1,74 +0,0 @@ -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright 2015 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: Piyush Agram -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - -def createFullApertureSwathSLCProduct(): - from .FullApertureSwathSLCProduct import FullApertureSwathSLCProduct - return FullApertureSwathSLCProduct() - -def createALOS2(name=None): - from .ALOS2 import ALOS2Scanner - return ALOS2Scanner() - - -SENSORS = { - 'ALOS2' : createALOS2, - } - -def getFactoriesInfo(): - """ - Returns a dictionary with information on how to create an object Sensor from its factory - """ - return {'ScanSARSensor': - {'args': - { - 'sensor':{'value':list(SENSORS.keys()),'type':'str','optional':False} - }, - 'factory':'createSensor' - } - } - - - -def createSensor(sensor='', name=None): - - try: - cls = SENSORS[str(sensor).upper()] - try: - instance = cls(name) - except AttributeError: - raise TypeError("'sensor name'=%s cannot be interpreted" % - str(sensor)) - pass - except: - print("Sensor type not recognized. Valid Sensor types:\n", - SENSORS.keys()) - instance = None - pass - return instance