#!/usr/bin/env python3 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Copyright 2019 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: Piyush Agram, Yang Lei #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import isce from iscesys.Component.Component import Component import pdb import subprocess import re import string class Geogrid(Component): ''' Class for mapping regular geographic grid on radar imagery. ''' def geogrid(self): ''' Do the actual processing. ''' import isce from components.contrib.geo_autoRIFT.geogrid import geogrid ##Determine appropriate EPSG system self.epsg = self.getProjectionSystem() ###Determine extent of data needed bbox = self.determineBbox() ###Load approrpriate DEM from database if self.demname is None: self.demname, self.dhdxname, self.dhdyname, self.vxname, self.vyname, self.srxname, self.sryname, self.csminxname, self.csminyname, self.csmaxxname, self.csmaxyname, self.ssmname = self.getDEM(bbox) ##Create and set parameters self.setState() ##Run geogrid.geogrid_Py(self._geogrid) ##Clean up self.finalize() def getProjectionSystem(self): ''' Testing with Greenland. ''' if not self.demname: raise Exception('At least the DEM parameter must be set for geogrid') from osgeo import gdal, osr ds = gdal.Open(self.demname, gdal.GA_ReadOnly) srs = osr.SpatialReference() srs.ImportFromWkt(ds.GetProjection()) srs.AutoIdentifyEPSG() ds = None # pdb.set_trace() if srs.IsGeographic(): epsgstr = srs.GetAuthorityCode('GEOGCS') elif srs.IsProjected(): epsgstr = srs.GetAuthorityCode('PROJCS') elif srs.IsLocal(): raise Exception('Local coordinate system encountered') else: raise Exception('Non-standard coordinate system encountered') if not epsgstr: #Empty string->use shell command gdalsrsinfo for last trial cmd = 'gdalsrsinfo -o epsg {0}'.format(self.demname) epsgstr = subprocess.check_output(cmd, shell=True) # pdb.set_trace() epsgstr = re.findall("EPSG:(\d+)", str(epsgstr))[0] # pdb.set_trace() if not epsgstr: #Empty string raise Exception('Could not auto-identify epsg code') # pdb.set_trace() epsgcode = int(epsgstr) # pdb.set_trace() return epsgcode def determineBbox(self, zrange=[-200,4000]): ''' Dummy. ''' import numpy as np import datetime from osgeo import osr,gdal # import pdb # pdb.set_trace() # rng = self.startingRange + np.linspace(0, self.numberOfSamples, num=21) rng = self.startingRange + np.linspace(0, self.numberOfSamples-1, num=21) * self.rangePixelSize deltat = np.linspace(0, 1., num=21)[1:-1] lonlat = osr.SpatialReference() lonlat.ImportFromEPSG(4326) coord = osr.SpatialReference() coord.ImportFromEPSG(self.epsg) trans = osr.CoordinateTransformation(lonlat, coord) llhs = [] xyzs = [] ###First range line for rr in rng: for zz in zrange: llh = self.orbit.rdr2geo(self.sensingStart, rr, side=self.lookSide, height=zz) llhs.append(llh) if gdal.__version__[0] == '2': x,y,z = trans.TransformPoint(llh[1], llh[0], llh[2]) else: x,y,z = trans.TransformPoint(llh[0], llh[1], llh[2]) xyzs.append([x,y,z]) ##Last range line sensingStop = self.sensingStart + datetime.timedelta(seconds = (self.numberOfLines-1) / self.prf) for rr in rng: for zz in zrange: llh = self.orbit.rdr2geo(sensingStop, rr, side=self.lookSide, height=zz) llhs.append(llh) if gdal.__version__[0] == '2': x,y,z = trans.TransformPoint(llh[1], llh[0], llh[2]) else: x,y,z = trans.TransformPoint(llh[0], llh[1], llh[2]) xyzs.append([x,y,z]) ##For each line in middle, consider the edges for frac in deltat: sensingTime = self.sensingStart + datetime.timedelta(seconds = frac * (self.numberOfLines-1)/self.prf) # print('sensing Time: %f %f %f'%(sensingTime.minute,sensingTime.second,sensingTime.microsecond)) for rr in [rng[0], rng[-1]]: for zz in zrange: llh = self.orbit.rdr2geo(sensingTime, rr, side=self.lookSide, height=zz) llhs.append(llh) if gdal.__version__[0] == '2': x,y,z = trans.TransformPoint(llh[1], llh[0], llh[2]) else: x,y,z = trans.TransformPoint(llh[0], llh[1], llh[2]) xyzs.append([x,y,z]) llhs = np.array(llhs) xyzs = np.array(xyzs) self._xlim = [np.min(xyzs[:,0]), np.max(xyzs[:,0])] self._ylim = [np.min(xyzs[:,1]), np.max(xyzs[:,1])] def getIncidenceAngle(self, zrange=[-200,4000]): ''' Dummy. ''' import numpy as np import datetime from osgeo import osr,gdal from isceobj.Util.geo.ellipsoid import Ellipsoid from isceobj.Planet.Planet import Planet planet = Planet(pname='Earth') refElp = Ellipsoid(a=planet.ellipsoid.a, e2=planet.ellipsoid.e2, model='WGS84') deg2rad = np.pi/180.0 thetas = [] midrng = self.startingRange + (np.floor(self.numberOfSamples/2)-1) * self.rangePixelSize midsensing = self.sensingStart + datetime.timedelta(seconds = (np.floor(self.numberOfLines/2)-1) / self.prf) masterSV = self.orbit.interpolateOrbit(midsensing, method='hermite') mxyz = np.array(masterSV.getPosition()) for zz in zrange: llh = self.orbit.rdr2geo(midsensing, midrng, side=self.lookSide, height=zz) targxyz = np.array(refElp.LLH(llh[0], llh[1], llh[2]).ecef().tolist()) los = (mxyz-targxyz) / np.linalg.norm(mxyz-targxyz) n_vec = np.array([np.cos(llh[0]*deg2rad)*np.cos(llh[1]*deg2rad), np.cos(llh[0]*deg2rad)*np.sin(llh[1]*deg2rad), np.sin(llh[0]*deg2rad)]) theta = np.arccos(np.dot(los, n_vec)) thetas.append([theta]) thetas = np.array(thetas) self.incidenceAngle = np.mean(thetas) def getDEM(self, bbox): ''' Look up database and return values. ''' return "", "", "", "", "" def setState(self): ''' Create C object and populate. ''' from components.contrib.geo_autoRIFT.geogrid import geogrid from iscesys import DateTimeUtil as DTU if self._geogrid is not None: geogrid.destroyGeoGrid_Py(self._geogrid) self._geogrid = geogrid.createGeoGrid_Py() geogrid.setRadarImageDimensions_Py( self._geogrid, self.numberOfSamples, self.numberOfLines) geogrid.setRangeParameters_Py( self._geogrid, self.startingRange, self.rangePixelSize) geogrid.setAzimuthParameters_Py( self._geogrid, DTU.seconds_since_midnight(self.sensingStart), self.prf) geogrid.setRepeatTime_Py(self._geogrid, self.repeatTime) geogrid.setEPSG_Py(self._geogrid, self.epsg) geogrid.setIncidenceAngle_Py(self._geogrid, self.incidenceAngle) geogrid.setChipSizeX0_Py(self._geogrid, self.chipSizeX0) geogrid.setXLimits_Py(self._geogrid, self._xlim[0], self._xlim[1]) geogrid.setYLimits_Py(self._geogrid, self._ylim[0], self._ylim[1]) if self.demname: geogrid.setDEM_Py(self._geogrid, self.demname) if (self.dhdxname is not None) and (self.dhdyname is not None): geogrid.setSlopes_Py(self._geogrid, self.dhdxname, self.dhdyname) if (self.vxname is not None) and (self.vyname is not None): geogrid.setVelocities_Py(self._geogrid, self.vxname, self.vyname) if (self.srxname is not None) and (self.sryname is not None): geogrid.setSearchRange_Py(self._geogrid, self.srxname, self.sryname) if (self.csminxname is not None) and (self.csminyname is not None): geogrid.setChipSizeMin_Py(self._geogrid, self.csminxname, self.csminyname) if (self.csmaxxname is not None) and (self.csmaxyname is not None): geogrid.setChipSizeMax_Py(self._geogrid, self.csmaxxname, self.csmaxyname) if (self.ssmname is not None): geogrid.setStableSurfaceMask_Py(self._geogrid, self.ssmname) geogrid.setWindowLocationsFilename_Py( self._geogrid, self.winlocname) geogrid.setWindowOffsetsFilename_Py( self._geogrid, self.winoffname) geogrid.setWindowSearchRangeFilename_Py( self._geogrid, self.winsrname) geogrid.setWindowChipSizeMinFilename_Py( self._geogrid, self.wincsminname) geogrid.setWindowChipSizeMaxFilename_Py( self._geogrid, self.wincsmaxname) geogrid.setWindowStableSurfaceMaskFilename_Py( self._geogrid, self.winssmname) geogrid.setRO2VXFilename_Py( self._geogrid, self.winro2vxname) geogrid.setRO2VYFilename_Py( self._geogrid, self.winro2vyname) geogrid.setLookSide_Py(self._geogrid, self.lookSide) geogrid.setNodataOut_Py(self._geogrid, self.nodata_out) self._orbit = self.orbit.exportToC() geogrid.setOrbit_Py(self._geogrid, self._orbit) def finalize(self): ''' Clean up all the C pointers. ''' from components.contrib.geo_autoRIFT.geogrid import geogrid from isceobj.Util import combinedlibmodule combinedlibmodule.freeCOrbit(self._orbit) self._orbit = None geogrid.destroyGeoGrid_Py(self._geogrid) self._geogrid = None def __init__(self): super(Geogrid, self).__init__() ##Radar image related parameters self.orbit = None self.sensingStart = None self.startingRange = None self.prf = None self.rangePixelSize = None self.numberOfSamples = None self.numberOfLines = None self.lookSide = None self.repeatTime = None self.incidenceAngle = None self.chipSizeX0 = None ##Input related parameters self.demname = None self.dhdxname = None self.dhdyname = None self.vxname = None self.vyname = None self.srxname = None self.sryname = None self.csminxname = None self.csminyname = None self.csmaxxname = None self.csmaxyname = None self.ssmname = None ##Output related parameters self.winlocname = None self.winoffname = None self.winsrname = None self.wincsminname = None self.wincsmaxname = None self.winssmname = None self.winro2vxname = None self.winro2vyname = None ##Coordinate system self.epsg = None self._xlim = None self._ylim = None self.nodata_out = None ##Pointer to C self._geogrid = None self._orbit = None