From c36caafa24059bb57d644df3fe4511a9e6b97744 Mon Sep 17 00:00:00 2001 From: piyushrpt Date: Sun, 16 Jun 2019 18:59:42 -0700 Subject: [PATCH 1/5] Adding ICEYE_SLC Sensor --- components/isceobj/Sensor/ICEYE_SLC.py | 285 +++++++++++++++++++ components/isceobj/Sensor/SConscript | 2 +- components/isceobj/Sensor/__init__.py | 4 +- components/isceobj/StripmapProc/Factories.py | 6 +- 4 files changed, 292 insertions(+), 5 deletions(-) create mode 100755 components/isceobj/Sensor/ICEYE_SLC.py diff --git a/components/isceobj/Sensor/ICEYE_SLC.py b/components/isceobj/Sensor/ICEYE_SLC.py new file mode 100755 index 0000000..47b0146 --- /dev/null +++ b/components/isceobj/Sensor/ICEYE_SLC.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Copyright 2013 California Institute of Technology. ALL RIGHTS RESERVED. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# United States Government Sponsorship acknowledged. This software is subject to +# U.S. export control laws and regulations and has been classified as 'EAR99 NLR' +# (No [Export] License Required except when exporting to an embargoed country, +# end user, or in support of a prohibited end use). By downloading this software, +# the user agrees to comply with all applicable U.S. export laws and regulations. +# The user has the responsibility to obtain export licenses, or other export +# authority as may be required before exporting this software to any 'EAR99' +# embargoed foreign country or citizen of those countries. +# +# Author: Piyush Agram +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +import datetime +import logging +try: + import h5py +except ImportError: + raise ImportError( + "Python module h5py is required to process ICEYE data" + ) + +import isceobj +from isceobj.Scene.Frame import Frame +from isceobj.Orbit.Orbit import StateVector +from isceobj.Planet.Planet import Planet +from isceobj.Planet.AstronomicalHandbook import Const +from isceobj.Sensor import cosar +from iscesys.DateTimeUtil.DateTimeUtil import DateTimeUtil as DTU +from isceobj.Sensor import tkfunc,createAuxFile +from iscesys.Component.Component import Component + +HDF5 = Component.Parameter( + 'hdf5', + public_name='HDF5', + default=None, + type=str, + mandatory=True, + intent='input', + doc='ICEYE slc hdf5 input file' +) + +APPLY_SLANT_RANGE_PHASE = Component.Parameter( + 'applySlantRangePhase', + public_name='APPLY_SLANT_RANGE_PHASE', + default=False, + type=bool, + mandatory=True, + intent='input', + doc='Recenter spectra by applying range spectra shift' +) + +from .Sensor import Sensor +class ICEYE_SLC(Sensor): + """ + A class representing a Level1Product meta data. + Level1Product(hdf5=h5filename) will parse the hdf5 + file and produce an object with attributes for metadata. + """ + parameter_list = (HDF5, APPLY_SLANT_RANGE_PHASE) + Sensor.parameter_list + logging_name = 'isce.Sensor.ICEYE_SLC' + family = 'iceye_slc' + + def __init__(self,family='',name=''): + super(ICEYE_SLC,self).__init__(family if family else self.__class__.family, name=name) + self.frame = Frame() + self.frame.configure() + # Some extra processing parameters unique to CSK SLC (currently) + self.dopplerRangeTime = [] + self.dopplerAzimuthTime = [] + self.azimuthRefTime = None + self.rangeRefTime = None + self.rangeFirstTime = None + self.rangeLastTime = None + + + self.lookMap = {'RIGHT': -1, + 'LEFT': 1} + return + + def __getstate__(self): + d = dict(self.__dict__) + del d['logger'] + return d + + def __setstate__(self,d): + self.__dict__.update(d) + self.logger = logging.getLogger('isce.Sensor.ICEYE_SLC') + return + + + def getFrame(self): + return self.frame + + def parse(self): + try: + fp = h5py.File(self.hdf5,'r') + except Exception as strerr: + self.logger.error("IOError: %s" % strerr) + return None + + self.populateMetadata(fp) + fp.close() + + def populateMetadata(self, file): + """ + Populate our Metadata objects + """ + + self._populatePlatform(file) + self._populateInstrument(file) + self._populateFrame(file) + self._populateOrbit(file) + self._populateExtras(file) + + + def _populatePlatform(self, file): + platform = self.frame.getInstrument().getPlatform() + + platform.setMission(file['satellite_name'][()]) + platform.setPointingDirection(self.lookMap[file['look_side'][()].upper()]) + platform.setPlanet(Planet(pname="Earth")) + + ####This is an approximation for spotlight mode + ####In spotlight mode, antenna length changes with azimuth position + platform.setAntennaLength(2 * file['azimuth_ground_spacing'][()]) + + assert( file['range_looks'][()] == 1) + assert( file['azimuth_looks'][()] == 1) + + def _populateInstrument(self, file): + instrument = self.frame.getInstrument() + + rangePixelSize = file['slant_range_spacing'][()] + instrument.setRadarWavelength(Const.c / file['carrier_frequency'][()]) + instrument.setPulseRepetitionFrequency(file['processing_prf'][()]) + instrument.setRangePixelSize(rangePixelSize) + instrument.setPulseLength(file['chirp_duration'][()]) + instrument.setChirpSlope(file['chirp_bandwidth'][()]/ file['chirp_duration'][()]) + instrument.setRangeSamplingRate(file['range_sampling_rate'][()]) + + incangle = file['local_incidence_angle'] + instrument.setIncidenceAngle(incangle[incangle.size//2]) + + + def _populateFrame(self, file): + + rft = file['first_pixel_time'][()] + slantRange = rft*Const.c/2.0 + self.frame.setStartingRange(slantRange) + + + sensingStart = datetime.datetime.strptime(file['zerodoppler_start_utc'][()].decode('utf-8'),'%Y-%m-%dT%H:%M:%S.%f') + sensingStop = datetime.datetime.strptime(file['zerodoppler_end_utc'][()].decode('utf-8'),'%Y-%m-%dT%H:%M:%S.%f') + sensingMid = sensingStart + 0.5 * (sensingStop - sensingStart) + + self.frame.setPassDirection(file['orbit_direction'][()]) + self.frame.setOrbitNumber(file['orbit_absolute_number'][()]) + self.frame.setProcessingFacility('ICEYE') + self.frame.setProcessingSoftwareVersion(str(file['processor_version'][()])) + self.frame.setPolarization(file['polarization'][()]) + self.frame.setNumberOfLines(file['number_of_azimuth_samples'][()]) + self.frame.setNumberOfSamples(file['number_of_range_samples'][()]) + self.frame.setSensingStart(sensingStart) + self.frame.setSensingMid(sensingMid) + self.frame.setSensingStop(sensingStop) + + rangePixelSize = self.frame.getInstrument().getRangePixelSize() + farRange = slantRange + (self.frame.getNumberOfSamples()-1)*rangePixelSize + self.frame.setFarRange(farRange) + + def _populateOrbit(self,file): + import numpy as np + orbit = self.frame.getOrbit() + + orbit.setReferenceFrame('ECR') + orbit.setOrbitSource('Header') + t = file['state_vector_time_utc'][:] + position = np.zeros((t.size,3)) + position[:,0] = file['posX'][:] + position[:,1] = file['posY'][:] + position[:,2] = file['posZ'][:] + + velocity = np.zeros((t.size,3)) + velocity[:,0] = file['velX'][:] + velocity[:,1] = file['velY'][:] + velocity[:,2] = file['velZ'][:] + + for ii in range(t.size): + vec = StateVector() + vec.setTime(datetime.datetime.strptime(t[ii][0].decode('utf-8'), '%Y-%m-%dT%H:%M:%S.%f')) + vec.setPosition([position[ii,0],position[ii,1],position[ii,2]]) + vec.setVelocity([velocity[ii,0],velocity[ii,1],velocity[ii,2]]) + orbit.addStateVector(vec) + + + def _populateExtras(self, file): + """ + Populate some of the extra fields unique to processing TSX data. + In the future, other sensors may need this information as well, + and a re-organization may be necessary. + """ + import numpy as np + self.dcpoly = np.mean(file['dc_estimate_coeffs'][:], axis=0) + + def extractImage(self): + import numpy as np + import h5py + + self.parse() + + fid = h5py.File(self.hdf5, 'r') + + si = fid['s_i'] + sq = fid['s_q'] + + nLines = si.shape[0] + spectralShift = 2 * self.frame.getInstrument().getRangePixelSize() / self.frame.getInstrument().getRadarWavelength() + spectralShift -= np.floor(spectralShift) + phsShift = np.exp(-1j * 2 * np.pi * spectralShift * np.arange(si.shape[1])) + with open(self.output, 'wb') as fout: + for ii in range(nLines): + line = (si[ii,:] + 1j*sq[ii,:]) + if self.applySlantRangePhase: + line *= phsShift + line.astype(np.complex64).tofile(fout) + + fid.close() + + slcImage = isceobj.createSlcImage() + slcImage.setFilename(self.output) + slcImage.setXmin(0) + slcImage.setXmax(self.frame.getNumberOfSamples()) + slcImage.setWidth(self.frame.getNumberOfSamples()) + slcImage.setAccessMode('r') + self.frame.setImage(slcImage) + + def extractDoppler(self): + """ + Return the doppler centroid as defined in the HDF5 file. + """ + import numpy as np + + quadratic = {} + + rangePixelSize = self.frame.getInstrument().getRangePixelSize() + rt0 = self.frame.getStartingRange() / (2 * Const.c) + rt1 = rt0 +((self.frame.getNumberOfSamples()-1)*rangePixelSize) / (2 * Const.c) + + + ####insarApp style + quadratic['a'] = np.polyval( self.dcpoly, 0.5 * (rt0 + rt1)) / self.frame.PRF + quadratic['b'] = 0. + quadratic['c'] = 0. + + + ####For roiApp more accurate + ####Convert stuff to pixel wise coefficients + x = np.linspace(rt0, rt1, num=len(self.dcpoly)+1) + pix = np.linspace(0, self.frame.getNumberOfSamples(), num=len(self.dcpoly)+1) + evals = np.polyval(self.dcpoly, x) + fit = np.polyfit(pix, evals, len(self.dcpoly)-1) + self.frame._dopplerVsPixel = list(fit[::-1]) + print('Doppler Fit: ', self.frame._dopplerVsPixel) + + return quadratic diff --git a/components/isceobj/Sensor/SConscript b/components/isceobj/Sensor/SConscript index f512f62..32d6817 100644 --- a/components/isceobj/Sensor/SConscript +++ b/components/isceobj/Sensor/SConscript @@ -25,7 +25,7 @@ listFiles = ['ALOS.py','CEOS.py','COSMO_SkyMed.py','COSMO_SkyMed_SLC.py', 'Radarsat2.py','TerraSARX.py','Polarimetry.py','Sensor.py', 'ROI_PAC.py','Sentinel1.py','TanDEMX.py','KOMPSAT5.py', 'Risat1.py', 'Risat1_SLC.py', 'UAVSAR_RPI.py', 'UAVSAR_Stack.py', - 'UAVSAR_Polsar.py', 'ERS_EnviSAT.py', + 'UAVSAR_Polsar.py', 'ERS_EnviSAT.py', 'ICEYE_SLC.py', 'ALOS2.py', 'ERS_SLC.py', 'ALOS_SLC.py', 'EnviSAT_SLC.py', 'ERS_EnviSAT_SLC.py', 'SICD_RGZERO.py','__init__.py'] diff --git a/components/isceobj/Sensor/__init__.py b/components/isceobj/Sensor/__init__.py index cb63767..39fe672 100755 --- a/components/isceobj/Sensor/__init__.py +++ b/components/isceobj/Sensor/__init__.py @@ -96,6 +96,7 @@ createEnviSAT_SLC = partial(factory_template, 'EnviSAT_SLC') createERS_ENVISAT = partial(factory_template, 'ERS_EnviSAT') createERS_EnviSAT_SLC = partial(factory_template, 'ERS_EnviSAT_SLC') createSICD_RGZERO = partial(factory_template, 'SICD_RGZERO') +createICEYE_SLC = partial(factory_template, 'ICEYE_SLC') SENSORS = {'ALOS' : createALOS, 'ALOS_SLC' : createALOS_SLC, @@ -119,7 +120,8 @@ SENSORS = {'ALOS' : createALOS, 'ENVISAT_SLC': createEnviSAT_SLC, 'ERS_ENVISAT' : createERS_ENVISAT, 'ERS_ENVISAT_SLC' : createERS_EnviSAT_SLC, - 'SICD_RGZERO' : createSICD_RGZERO} + 'SICD_RGZERO' : createSICD_RGZERO, + 'ICEYE_SLC' : createICEYE_SLC} #These are experimental and can be added in as they become ready # 'JERS': createJERS, diff --git a/components/isceobj/StripmapProc/Factories.py b/components/isceobj/StripmapProc/Factories.py index 9f65fc1..c465f4c 100644 --- a/components/isceobj/StripmapProc/Factories.py +++ b/components/isceobj/StripmapProc/Factories.py @@ -52,7 +52,7 @@ def isRawSensor(sensor): ''' Check if input data is raw / slc. ''' - if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','ers_envisat_slc','sicd_rgzero']: + if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','ers_envisat_slc','sicd_rgzero', 'iceye_slc']: return False else: return True @@ -63,7 +63,7 @@ def isZeroDopplerSLC(sensor): Check if SLC is zero doppler / native doppler. ''' - if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','envisat_slc','ers_envisat_slc','sicd_rgzero']: + if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','envisat_slc','ers_envisat_slc','sicd_rgzero', 'iceye_slc']: return True elif sensor.lower() in ['alos_slc', 'uavsar_rpi']: return False @@ -76,7 +76,7 @@ def getDopplerMethod(sensor): Return appropriate doppler method based on user input. ''' - if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','cosmo_skymed','ers_envisat_slc','sicd_rgzero']: + if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','cosmo_skymed','ers_envisat_slc','sicd_rgzero', 'iceye_slc']: res = 'useDEFAULT' else: res = 'useDOPIQ' From 6ca61fb42b780bd9fdfc570d67c3e2ae274fb45e Mon Sep 17 00:00:00 2001 From: hfattahi Date: Tue, 16 Jul 2019 21:37:06 +0000 Subject: [PATCH 2/5] adding UAVSAR_HDF5_SLC Sensor --- applications/make_raw.py | 2 +- components/isceobj/Sensor/UAVSAR_HDF5_SLC.py | 325 +++++++++++++++++++ components/isceobj/Sensor/__init__.py | 4 +- components/isceobj/StripmapProc/Factories.py | 6 +- 4 files changed, 332 insertions(+), 5 deletions(-) create mode 100755 components/isceobj/Sensor/UAVSAR_HDF5_SLC.py diff --git a/applications/make_raw.py b/applications/make_raw.py index e0df488..a3b1f44 100755 --- a/applications/make_raw.py +++ b/applications/make_raw.py @@ -167,7 +167,7 @@ class make_raw(Component, FrameMixin): startHeight = sv0.calculateHeight(ellipsoid) midHeight = sv1.calculateHeight(ellipsoid) - if 'uav' in self.sensor.family.lower(): + if ('uav' in self.sensor.family.lower()) and (hasattr(self.sensor, 'platformHeight')): self.spacecraftHeight = self.sensor.platformHeight else: self.spacecraftHeight = startHeight diff --git a/components/isceobj/Sensor/UAVSAR_HDF5_SLC.py b/components/isceobj/Sensor/UAVSAR_HDF5_SLC.py new file mode 100755 index 0000000..6323f5b --- /dev/null +++ b/components/isceobj/Sensor/UAVSAR_HDF5_SLC.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python3 + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Copyright 2013 California Institute of Technology. ALL RIGHTS RESERVED. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# United States Government Sponsorship acknowledged. This software is subject to +# U.S. export control laws and regulations and has been classified as 'EAR99 NLR' +# (No [Export] License Required except when exporting to an embargoed country, +# end user, or in support of a prohibited end use). By downloading this software, +# the user agrees to comply with all applicable U.S. export laws and regulations. +# The user has the responsibility to obtain export licenses, or other export +# authority as may be required before exporting this software to any 'EAR99' +# embargoed foreign country or citizen of those countries. +# +# Author: Heresh Fattahi +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +import datetime +import logging +try: + import h5py +except ImportError: + raise ImportError( + "Python module h5py is required to process COSMO-SkyMed data" + ) + +import isceobj +from isceobj.Scene.Frame import Frame +from isceobj.Orbit.Orbit import StateVector +from isceobj.Planet.Planet import Planet +from isceobj.Planet.AstronomicalHandbook import Const +from isceobj.Sensor import cosar +from iscesys.DateTimeUtil.DateTimeUtil import DateTimeUtil as DTU +from isceobj.Sensor import tkfunc,createAuxFile +from iscesys.Component.Component import Component +from isceobj.Constants import SPEED_OF_LIGHT + +HDF5 = Component.Parameter( + 'hdf5', + public_name='HDF5', + default=None, + type=str, + mandatory=True, + intent='input', + doc='UAVSAR slc input file in HDF5 format' +) + +FREQUENCY = Component.Parameter( + 'frequency', + public_name='FREQUENCY', + default='frequencyA', + type=str, + mandatory=True, + intent='input', + doc='frequency band of the UAVSAR slc file to be processed (frequencyA or frequencyB)' +) + +POLARIZATION = Component.Parameter( + 'polarization', + public_name='POLARIZATION', + default='HH', + type=str, + mandatory=True, + intent='input', + doc='polarization channel of the UAVSAR slc file to be processed' +) + +from .Sensor import Sensor +class UAVSAR_HDF5_SLC(Sensor): + """ + A class representing a Level1Product meta data. + Level1Product(hdf5=h5filename) will parse the hdf5 + file and produce an object with attributes for metadata. + """ + parameter_list = (HDF5, + FREQUENCY, + POLARIZATION) + Sensor.parameter_list + + logging_name = 'isce.Sensor.UAVSAR_HDF5_SLC' + family = 'uavsar_hdf5_slc' + + def __init__(self,family='',name=''):# , frequency='frequencyA', polarization='HH'): + super(UAVSAR_HDF5_SLC,self).__init__(family if family else self.__class__.family, name=name) + self.frame = Frame() + self.frame.configure() + # Some extra processing parameters unique to UAVSAR HDF5 SLC (currently) + self.dopplerRangeTime = [] + self.dopplerAzimuthTime = [] + self.azimuthRefTime = None + self.rangeRefTime = None + self.rangeFirstTime = None + self.rangeLastTime = None + #self.frequency = frequency + #self.polarization = polarization + + self.lookMap = {'right': -1, + 'left': 1} + return + + def __getstate__(self): + d = dict(self.__dict__) + del d['logger'] + return d + + def __setstate__(self,d): + self.__dict__.update(d) + self.logger = logging.getLogger('isce.Sensor.UAVSAR_HDF5_SLC') + return + + + def getFrame(self): + return self.frame + + def parse(self): + try: + fp = h5py.File(self.hdf5,'r') + except Exception as strerr: + self.logger.error("IOError: %s" % strerr) + return None + + self.populateMetadata(fp) + fp.close() + + def populateMetadata(self, file): + """ + Populate our Metadata objects + """ + + self._populatePlatform(file) + self._populateInstrument(file) + self._populateFrame(file) + self._populateOrbit(file) + + + def _populatePlatform(self, file): + platform = self.frame.getInstrument().getPlatform() + + platform.setMission(file['/science/LSAR/identification'].get('missionId')[()].decode('utf-8')) + platform.setPointingDirection(self.lookMap[file['/science/LSAR/identification'].get('lookDirection')[()].decode('utf-8')]) + platform.setPlanet(Planet(pname="Earth")) + + # We are not using this value anywhere. Let's fix it for now. + platform.setAntennaLength(12.0) + + def _populateInstrument(self, file): + instrument = self.frame.getInstrument() + + rangePixelSize = file['/science/LSAR/SLC/swaths/' + self.frequency + '/slantRangeSpacing'][()] + wvl = SPEED_OF_LIGHT/file['/science/LSAR/SLC/swaths/' + self.frequency + '/processedCenterFrequency'][()] + instrument.setRadarWavelength(wvl) + instrument.setPulseRepetitionFrequency(1.0/file['/science/LSAR/SLC/swaths/zeroDopplerTimeSpacing'][()]) + rangePixelSize = file['/science/LSAR/SLC/swaths/' + self.frequency + '/slantRangeSpacing'][()] + instrument.setRangePixelSize(rangePixelSize) + + # Chrip slope and length only are used in the split spectrum workflow to compute the bandwidth. + # Therefore fixing it to 1.0 won't breack anything + Chirp_slope = 1.0 + rangeBandwidth = file['/science/LSAR/SLC/swaths/' + self.frequency + '/processedRangeBandwidth'][()] + Chirp_length = rangeBandwidth/Chirp_slope + instrument.setPulseLength(Chirp_length) + instrument.setChirpSlope(Chirp_slope) + rangeSamplingFrequency = SPEED_OF_LIGHT/2./rangePixelSize + instrument.setRangeSamplingRate(rangeSamplingFrequency) + + incangle = 0.0 + instrument.setIncidenceAngle(incangle) + + + def _populateFrame(self, file): + + slantRange = file['/science/LSAR/SLC/swaths/' + self.frequency + '/slantRange'][0] + self.frame.setStartingRange(slantRange) + + referenceUTC = file['/science/LSAR/SLC/swaths/zeroDopplerTime'].attrs['units'].decode('utf-8') + referenceUTC = referenceUTC.replace('seconds since ','') + referenceUTC = datetime.datetime.strptime(referenceUTC,'%Y-%m-%d %H:%M:%S') + + relStart = file['/science/LSAR/SLC/swaths/zeroDopplerTime'][0] + relEnd = file['/science/LSAR/SLC/swaths/zeroDopplerTime'][-1] + relMid = 0.5*(relStart + relEnd) + + sensingStart = self._combineDateTime(referenceUTC, relStart) + sensingStop = self._combineDateTime(referenceUTC, relEnd) + sensingMid = self._combineDateTime(referenceUTC, relMid) + + + self.frame.setPassDirection(file['/science/LSAR/identification'].get('orbitPassDirection')[()].decode('utf-8')) + self.frame.setOrbitNumber(file['/science/LSAR/identification'].get('trackNumber')[()]) + self.frame.setProcessingFacility('JPL') + self.frame.setProcessingSoftwareVersion(file['/science/LSAR/SLC/metadata/processingInformation/algorithms'].get('ISCEVersion')[()].decode('utf-8')) + self.frame.setPolarization(self.polarization) + self.frame.setNumberOfLines(file['/science/LSAR/SLC/swaths/' + self.frequency + '/' + self.polarization].shape[0]) + self.frame.setNumberOfSamples(file['/science/LSAR/SLC/swaths/' + self.frequency + '/' + self.polarization].shape[1]) + self.frame.setSensingStart(sensingStart) + self.frame.setSensingMid(sensingMid) + self.frame.setSensingStop(sensingStop) + + rangePixelSize = self.frame.instrument.rangePixelSize + farRange = slantRange + (self.frame.getNumberOfSamples()-1)*rangePixelSize + self.frame.setFarRange(farRange) + + def _populateOrbit(self,file): + orbit = self.frame.getOrbit() + + orbit.setReferenceFrame('ECR') + orbit.setOrbitSource('Header') + + referenceUTC = file['/science/LSAR/SLC/swaths/zeroDopplerTime'].attrs['units'].decode('utf-8') + referenceUTC = referenceUTC.replace('seconds since ','') + t0 = datetime.datetime.strptime(referenceUTC,'%Y-%m-%d %H:%M:%S') + t = file['/science/LSAR/SLC/metadata/orbit/time'] + position = file['/science/LSAR/SLC/metadata/orbit/position'] + velocity = file['/science/LSAR/SLC/metadata/orbit/velocity'] + + for i in range(len(position)): + vec = StateVector() + dt = t0 + datetime.timedelta(seconds=t[i]) + vec.setTime(dt) + vec.setPosition([position[i,0],position[i,1],position[i,2]]) + vec.setVelocity([velocity[i,0],velocity[i,1],velocity[i,2]]) + orbit.addStateVector(vec) + + + def extractImage(self): + + import numpy as np + import h5py + + self.parse() + + fid = h5py.File(self.hdf5, 'r') + ds = fid['/science/LSAR/SLC/swaths/' + self.frequency + '/' + self.polarization] + nLines = ds.shape[0] + + with open(self.output, 'wb') as fout: + for ii in range(nLines): + ds[ii,:].astype(np.complex64).tofile(fout) + + fid.close() + + slcImage = isceobj.createSlcImage() + slcImage.setFilename(self.output) + slcImage.setXmin(0) + slcImage.setXmax(self.frame.getNumberOfSamples()) + slcImage.setWidth(self.frame.getNumberOfSamples()) + slcImage.setAccessMode('r') + slcImage.renderHdr() + self.frame.setImage(slcImage) + + + def _parseNanoSecondTimeStamp(self,timestamp): + """ + Parse a date-time string with nanosecond precision and return a datetime object + """ + dateTime,nanoSeconds = timestamp.decode('utf-8').split('.') + microsec = float(nanoSeconds)*1e-3 + dt = datetime.datetime.strptime(dateTime,'%Y-%m-%d %H:%M:%S') + dt = dt + datetime.timedelta(microseconds=microsec) + return dt + + def _combineDateTime(self,dobj, secsstr): + '''Takes the date from dobj and time from secs to spit out a date time object. + ''' + sec = float(secsstr) + dt = datetime.timedelta(seconds = sec) + return dobj + dt + + def extractDoppler(self): + """ + Return the doppler centroid as defined in the HDF5 file. + """ + + import h5py + from scipy.interpolate import UnivariateSpline + import numpy as np + + h5 = h5py.File(self.hdf5,'r') + + # extract the 2D LUT of Doppler and choose only one range line as the data duplicates for other range lines + dop = h5['/science/LSAR/SLC/metadata/processingInformation/parameters/' + self.frequency + '/dopplerCentroid'][0,:] + rng = h5['/science/LSAR/SLC/metadata/processingInformation/parameters/slantRange'] + + # extract the slant range of the image grid + imgRng = h5['/science/LSAR/SLC/swaths/' + self.frequency + '/slantRange'] + + # use only part of the slant range that closely covers image ranges and ignore the rest + ind0 = np.argmin(np.abs(rng-imgRng[0])) - 1 + ind0 = np.max([0,ind0]) + ind1 = np.argmin(np.abs(rng-imgRng[-1])) + 1 + ind1 = np.min([ind1, rng.shape[0]]) + + dop = dop[ind0:ind1] + rng = rng[ind0:ind1] + + f = UnivariateSpline(rng, dop) + imgDop = f(imgRng) + + dr = imgRng[1]-imgRng[0] + pix = (imgRng - imgRng[0])/dr + fit = np.polyfit(pix, imgDop, 41) + + self.frame._dopplerVsPixel = list(fit[::-1]) + + ####insarApp style (doesn't get used for stripmapApp). A fixed Doppler at the middle of the scene + quadratic = {} + quadratic['a'] = imgDop[int(imgDop.shape[0]/2)]/self.frame.getInstrument().getPulseRepetitionFrequency() + quadratic['b'] = 0. + quadratic['c'] = 0. + + return quadratic diff --git a/components/isceobj/Sensor/__init__.py b/components/isceobj/Sensor/__init__.py index 39fe672..e4ba2f2 100755 --- a/components/isceobj/Sensor/__init__.py +++ b/components/isceobj/Sensor/__init__.py @@ -97,6 +97,7 @@ createERS_ENVISAT = partial(factory_template, 'ERS_EnviSAT') createERS_EnviSAT_SLC = partial(factory_template, 'ERS_EnviSAT_SLC') createSICD_RGZERO = partial(factory_template, 'SICD_RGZERO') createICEYE_SLC = partial(factory_template, 'ICEYE_SLC') +createUAVSAR_Hdf5_SLC = partial(factory_template, 'UAVSAR_HDF5_SLC') SENSORS = {'ALOS' : createALOS, 'ALOS_SLC' : createALOS_SLC, @@ -121,7 +122,8 @@ SENSORS = {'ALOS' : createALOS, 'ERS_ENVISAT' : createERS_ENVISAT, 'ERS_ENVISAT_SLC' : createERS_EnviSAT_SLC, 'SICD_RGZERO' : createSICD_RGZERO, - 'ICEYE_SLC' : createICEYE_SLC} + 'ICEYE_SLC' : createICEYE_SLC, + 'UAVSAR_HDF5_SLC' : createUAVSAR_Hdf5_SLC} #These are experimental and can be added in as they become ready # 'JERS': createJERS, diff --git a/components/isceobj/StripmapProc/Factories.py b/components/isceobj/StripmapProc/Factories.py index c465f4c..7727f48 100644 --- a/components/isceobj/StripmapProc/Factories.py +++ b/components/isceobj/StripmapProc/Factories.py @@ -52,7 +52,7 @@ def isRawSensor(sensor): ''' Check if input data is raw / slc. ''' - if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','ers_envisat_slc','sicd_rgzero', 'iceye_slc']: + if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','ers_envisat_slc','sicd_rgzero', 'iceye_slc', 'uavsar_hdf5_slc']: return False else: return True @@ -63,7 +63,7 @@ def isZeroDopplerSLC(sensor): Check if SLC is zero doppler / native doppler. ''' - if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','envisat_slc','ers_envisat_slc','sicd_rgzero', 'iceye_slc']: + if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','envisat_slc','ers_envisat_slc','sicd_rgzero', 'iceye_slc', 'uavsar_hdf5_slc']: return True elif sensor.lower() in ['alos_slc', 'uavsar_rpi']: return False @@ -76,7 +76,7 @@ def getDopplerMethod(sensor): Return appropriate doppler method based on user input. ''' - if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','cosmo_skymed','ers_envisat_slc','sicd_rgzero', 'iceye_slc']: + if str(sensor).lower() in ["terrasarx","cosmo_skymed_slc","radarsat2",'tandemx', 'kompsat5','risat1_slc','sentinel1', 'alos2','ers_slc','alos_slc','envisat_slc', 'uavsar_rpi','cosmo_skymed','ers_envisat_slc','sicd_rgzero', 'iceye_slc', 'uavsar_hdf5_slc']: res = 'useDEFAULT' else: res = 'useDOPIQ' From 29bcd788420803737aa16aaaa2f29ba3d440d137 Mon Sep 17 00:00:00 2001 From: piyushrpt Date: Wed, 17 Jul 2019 11:11:33 -0700 Subject: [PATCH 3/5] ALOS Quad pol fix --- components/isceobj/Sensor/ALOS.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/isceobj/Sensor/ALOS.py b/components/isceobj/Sensor/ALOS.py index cacc39b..fc494e8 100755 --- a/components/isceobj/Sensor/ALOS.py +++ b/components/isceobj/Sensor/ALOS.py @@ -218,6 +218,10 @@ class ALOS(Sensor): prf = self.leaderFile.sceneHeaderRecord.metadata[ 'Pulse Repetition Frequency']/1000. + ###Fix for quad pol data + if prf > 3000: + prf = prf / 2.0 + print('LEADER PRF: ', prf) beamNumber = self.leaderFile.sceneHeaderRecord.metadata[ 'Antenna beam number'] From 2d95cafd118b471cee45b3ce49ba711cd13cf853 Mon Sep 17 00:00:00 2001 From: piyushrpt Date: Thu, 18 Jul 2019 13:23:52 -0700 Subject: [PATCH 4/5] Adding UAVSAR_HDF5_SLC to SConscript --- components/isceobj/Sensor/SConscript | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/isceobj/Sensor/SConscript b/components/isceobj/Sensor/SConscript index 32d6817..53d8ee5 100644 --- a/components/isceobj/Sensor/SConscript +++ b/components/isceobj/Sensor/SConscript @@ -27,7 +27,8 @@ listFiles = ['ALOS.py','CEOS.py','COSMO_SkyMed.py','COSMO_SkyMed_SLC.py', 'Risat1.py', 'Risat1_SLC.py', 'UAVSAR_RPI.py', 'UAVSAR_Stack.py', 'UAVSAR_Polsar.py', 'ERS_EnviSAT.py', 'ICEYE_SLC.py', 'ALOS2.py', 'ERS_SLC.py', 'ALOS_SLC.py', 'EnviSAT_SLC.py', - 'ERS_EnviSAT_SLC.py', 'SICD_RGZERO.py','__init__.py'] + 'ERS_EnviSAT_SLC.py', 'SICD_RGZERO.py','UAVSAR_HDF5_SLC.py', + '__init__.py'] helpList,installHelp = envSensor['HELP_BUILDER'](envSensor,'__init__.py',install) envSensor.Install(installHelp,helpList) From 83453184349b54df9eb77bd4c143665f84b8d428 Mon Sep 17 00:00:00 2001 From: piyushrpt Date: Fri, 19 Jul 2019 01:15:10 -0700 Subject: [PATCH 5/5] Fix for importlib has no attribute util --- configuration/buildHelper.py | 4 ++-- contrib/stack/stripmapStack/stripmapWrapper.py | 4 ++-- contrib/stack/topsStack/SentinelWrapper.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configuration/buildHelper.py b/configuration/buildHelper.py index d6971b8..138bdb3 100755 --- a/configuration/buildHelper.py +++ b/configuration/buildHelper.py @@ -98,9 +98,9 @@ def main(factoryFile,package,buildDir): # import isce import filecmp try: - import importlib + from importlib import util factoryFile = os.path.abspath(factoryFile) - mod = importlib.util.spec_from_file_location('.', factoryFile) + mod = util.spec_from_file_location('.', factoryFile) factModule = mod.loader.load_module() factoriesInfo = factModule.getFactoriesInfo() nameList = [] diff --git a/contrib/stack/stripmapStack/stripmapWrapper.py b/contrib/stack/stripmapStack/stripmapWrapper.py index 7d27b91..441235d 100755 --- a/contrib/stack/stripmapStack/stripmapWrapper.py +++ b/contrib/stack/stripmapStack/stripmapWrapper.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import os, sys -import importlib +from importlib import util as importlibutil import argparse import configparser @@ -95,7 +95,7 @@ class ConfigParser: # If any of the following calls raises an exception, # there's a problem we can't handle -- let the caller handle it. - spec = importlib.util.find_spec(name) + spec = importlibutil.find_spec(name) try: return spec.loader.load_module() diff --git a/contrib/stack/topsStack/SentinelWrapper.py b/contrib/stack/topsStack/SentinelWrapper.py index 30b4a19..e8a9577 100755 --- a/contrib/stack/topsStack/SentinelWrapper.py +++ b/contrib/stack/topsStack/SentinelWrapper.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import os, sys -import importlib +from importlib import util as importlibutil import argparse import configparser @@ -158,7 +158,7 @@ class ConfigParser: # If any of the following calls raises an exception, # there's a problem we can't handle -- let the caller handle it. - spec = importlib.util.find_spec(name) + spec = importlibutil.find_spec(name) try: return spec.loader.load_module()