2019-01-16 19:40:08 +00:00
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 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
from . import CEOS
import isceobj
from isceobj . Scene . Frame import Frame
from isceobj . Orbit . Orbit import Orbit
from isceobj . Orbit . Orbit import StateVector as OrbitStateVector
from isceobj . Attitude . Attitude import Attitude
from isceobj . Attitude . Attitude import StateVector as AttitudeStateVector
from isceobj . Constants import SPEED_OF_LIGHT
from isceobj . Planet . Planet import Planet
from isceobj . Sensor import alos , VolumeDirectoryBase , tkfunc , Constants
from isceobj . Sensor . Polarimetry import Distortion
from iscesys import DateTimeUtil as DTUtil
from iscesys . Component . Component import Component
from stdproc . alosreformat . ALOS_fbs2fbd . ALOS_fbs2fbdPy import ALOS_fbs2fbdPy
from stdproc . alosreformat . ALOS_fbd2fbs . ALOS_fbd2fbsPy import ALOS_fbd2fbsPy
from isceobj . Util . decorators import pickled , logged
from isceobj . Sensor import xmlPrefix
from isceobj . Util . decorators import use_api
# temporary comments: replaced a static dictionary with a class --convention
# precluded namedtuple (constants).
# Need to discuss how the _populate methods work.
# 2 state vectors?
LEADERFILE = Component . Parameter ( ' _leaderFileList ' ,
public_name = ' LEADERFILE ' ,
default = ' ' ,
container = list ,
type = str ,
mandatory = True ,
doc = " List of names of ALOS Leaderfile "
)
IMAGEFILE = Component . Parameter ( ' _imageFileList ' ,
public_name = ' IMAGEFILE ' ,
default = ' ' ,
container = list ,
type = str ,
mandatory = True ,
doc = " List of names of ALOS Imagefile "
)
RESAMPLE_FLAG = Component . Parameter ( ' _resampleFlag ' ,
public_name = ' RESAMPLE_FLAG ' ,
default = ' ' ,
type = str ,
mandatory = False ,
doc = """
Indicate whether to resample : empty string indicates no resample ;
' single2dual ' indicates resample single polarized data to dual
polarized data sample rate ;
' dual2single ' indicates resample dual polarized data to single
polarize data sample rate .
"""
)
from . Sensor import Sensor
@pickled
class ALOS ( Sensor ) :
""" Code to read CEOSFormat leader files for ALOS SAR data.
The tables used to create this parser are based on document number
ER - IS - EPO - GS - 5902.1 from the European
Space Agency .
"""
family = ' alos '
logging_name = ' isce.sensor.ALOS '
parameter_list = ( IMAGEFILE ,
LEADERFILE ,
RESAMPLE_FLAG ) + Sensor . parameter_list
# polarizationMap = ['H','V','H+V']
## This is manifestly better than a method complete the lazy instantation
## of an instance attribute
transmit = Distortion ( complex ( 2.427029e-3 , 1.293019e-2 ) ,
complex ( - 1.147240e-2 , - 6.228230e-3 ) ,
complex ( 9.572169e-1 , 3.829563e-1 ) )
receive = Distortion ( complex ( - 6.263392e-3 , 7.082863e-3 ) ,
complex ( - 6.297074e-3 , 8.026685e-3 ) ,
complex ( 7.217117e-1 , - 2.367683e-2 ) )
2020-10-20 02:45:01 +00:00
constants = Constants ( iBias = 63.5 ,
qBias = 63.5 ,
2019-01-16 19:40:08 +00:00
pointingDirection = - 1 ,
antennaLength = 8.9 )
HEADER_LINES = 720
RESAMPLE_FLAG = { ' ' : ' do Nothing ' ,
' single2dual ' : ' resample from single to dual pole ' ,
' dual2single ' : ' resample from dual to single ' }
@logged
def __init__ ( self , name = ' ' ) :
super ( ) . __init__ ( family = self . __class__ . family , name = name )
self . _leaderFile = None
self . _imageFile = None
self . frame = None
return None
#2013-06-03 Kosal: the functions below overwrite the transmit property
#initiated above
'''
@property
def transmit ( self ) :
return self . __class__ . transmit
@transmit.setter
def transmit ( self , x ) :
raise TypeError (
" ALOS.transmit is a protected class attribute and cannot be set "
)
@property
def receive ( self ) :
return self . __class__ . receive
@receive.setter
def receive ( self , x ) :
raise TypeError (
" ALOS.receive is a protected class attribute and cannot be set "
)
'''
#Kosal
def getFrame ( self ) :
return self . frame
def setLeaderFile ( self , ldr ) :
self . _leaderFile = ldr
return
def parse ( self ) :
self . leaderFile = LeaderFile ( file = self . _leaderFile )
self . imageFile = ImageFile ( self )
try :
self . leaderFile . parse ( )
self . imageFile . parse ( )
except IOError :
return
self . populateMetadata ( )
def populateMetadata ( self ) :
"""
Create the appropriate metadata objects from our CEOSFormat metadata
"""
self . _populatePlatform ( )
self . _populateInstrument ( )
self . _populateFrame ( )
# Header orbits
self . _populateOrbit ( )
self . _populateAttitude ( )
self . _populateDistortions ( )
productLevel = float ( self . leaderFile . sceneHeaderRecord . metadata [
' Product level code ' ] )
2022-02-14 19:13:23 +00:00
#this proves to be not accurate. Adjusting first frame is OK, but adjusting following frames would cause discontinuities between frames. C. Liang, 20-dec-2021
# if productLevel == 1.0:
# self.updateRawParameters()
2019-01-16 19:40:08 +00:00
pass
def _populatePlatform ( self ) :
platform = self . frame . getInstrument ( ) . getPlatform ( )
platform . setMission ( self . leaderFile . sceneHeaderRecord . metadata [
' Sensor platform mission identifier ' ] )
platform . setPointingDirection ( self . constants . pointing_direction )
platform . setAntennaLength ( self . constants . antenna_length )
platform . setPlanet ( Planet ( pname = ' Earth ' ) )
def _populateInstrument ( self ) :
instrument = self . frame . getInstrument ( )
rangePixelSize = None
rangeSamplingRate = None
chirpSlope = None
bandwidth = None
prf = None
try :
rangeSamplingRate = self . leaderFile . sceneHeaderRecord . metadata [
' Range sampling rate '
] * 1e6
pulseLength = self . leaderFile . sceneHeaderRecord . metadata [
' Range pulse length '
] * 1e-6
rangePixelSize = SPEED_OF_LIGHT / ( 2.0 * rangeSamplingRate )
prf = self . leaderFile . sceneHeaderRecord . metadata [
' Pulse Repetition Frequency ' ] / 1000.
2019-07-17 18:11:33 +00:00
###Fix for quad pol data
if prf > 3000 :
prf = prf / 2.0
2019-01-16 19:40:08 +00:00
print ( ' LEADER PRF: ' , prf )
beamNumber = self . leaderFile . sceneHeaderRecord . metadata [
' Antenna beam number ' ]
# if self.imageFile.prf:
# prf = self.imageFile.prf
# else:
# self.logger.info("Using nominal PRF")
bandwidth = self . leaderFile . calibrationRecord . metadata [
' Band width ' ] * 1e6
#if (not bandwidth):
# bandwidth = self.leaderFile.sceneHeaderRecord.metadata[
# 'Bandwidth per look in range']
chirpSlope = - ( bandwidth / pulseLength )
except AttributeError :
self . logger . info ( " Some of the instrument parameters were not set " )
self . logger . debug ( " PRF: %s " % prf )
self . logger . debug ( " Bandwidth: %s " % bandwidth )
self . logger . debug ( " Pulse Length: %s " % pulseLength )
self . logger . debug ( " Chirp Slope: %s " % chirpSlope )
self . logger . debug ( " Range Pixel Size: %s " % rangePixelSize )
self . logger . debug ( " Range Sampling Rate: %s " % rangeSamplingRate )
self . logger . debug ( " Beam Number: %s " % beamNumber )
instrument . setRadarWavelength (
self . leaderFile . sceneHeaderRecord . metadata [ ' Radar wavelength ' ]
)
instrument . setIncidenceAngle (
self . leaderFile . sceneHeaderRecord . metadata [
' Incidence angle at scene centre ' ]
)
instrument . setPulseRepetitionFrequency ( prf )
instrument . setRangePixelSize ( rangePixelSize )
instrument . setRangeSamplingRate ( rangeSamplingRate )
instrument . setPulseLength ( pulseLength )
instrument . setChirpSlope ( chirpSlope )
instrument . setInPhaseValue ( self . constants [ ' iBias ' ] )
instrument . setQuadratureValue ( self . constants [ ' qBias ' ] )
instrument . setBeamNumber ( beamNumber )
return None
def _populateFrame ( self , polarization = ' HH ' , farRange = None ) :
frame = self . _decodeSceneReferenceNumber (
self . leaderFile . sceneHeaderRecord . metadata [ ' Scene reference number ' ]
)
try :
first_line_utc = self . imageFile . start_time
last_line_utc = self . imageFile . stop_time
centerTime = DTUtil . timeDeltaToSeconds (
last_line_utc - first_line_utc
) / 2.0
center_line_utc = first_line_utc + datetime . timedelta (
microseconds = int ( centerTime * 1e6 )
)
self . frame . setSensingStart ( first_line_utc )
self . frame . setSensingMid ( center_line_utc )
self . frame . setSensingStop ( last_line_utc )
rangePixelSize = self . frame . getInstrument ( ) . getRangePixelSize ( )
farRange = (
self . imageFile . startingRange +
self . imageFile . width * rangePixelSize
)
except TypeError as strerr :
2021-09-09 18:05:12 +00:00
self . logger . warning ( strerr )
2019-01-16 19:40:08 +00:00
self . frame . frameNumber = frame
self . frame . setOrbitNumber (
self . leaderFile . sceneHeaderRecord . metadata [ ' Orbit number ' ]
)
self . frame . setStartingRange ( self . imageFile . startingRange )
self . frame . setFarRange ( farRange )
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 ( polarization )
self . frame . setNumberOfLines ( self . imageFile . length )
self . frame . setNumberOfSamples ( self . imageFile . width )
def _populateOrbit ( self ) :
orbit = self . frame . getOrbit ( )
velocityScale = 1.0
if ( self . leaderFile . sceneHeaderRecord . metadata [
' Processing facility identifier ' ] == ' ERSDAC ' ) :
# The ERSDAC header orbits are in mm/s
velocityScale = 1000.0
orbit . setReferenceFrame (
self . leaderFile . platformPositionRecord . metadata [
' Reference coordinate system ' ] )
orbit . setOrbitSource ( ' Header ' )
orbitQuality = self . _decodeOrbitQuality (
self . leaderFile . platformPositionRecord . metadata [
' Orbital elements designator ' ] )
orbit . setOrbitQuality ( orbitQuality )
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 ' ] )
for i in range (
self . leaderFile . platformPositionRecord . metadata [
' Number of data points ' ] ) :
vec = OrbitStateVector ( )
t = t0 + datetime . timedelta ( seconds =
i * self . leaderFile . platformPositionRecord . metadata [
' Time interval between DATA points ' ] )
vec . setTime ( t )
dataPoints = self . leaderFile . platformPositionRecord . metadata [
' Positional Data Points ' ] [ i ]
vec . setPosition ( [
dataPoints [ ' Position vector X ' ] ,
dataPoints [ ' Position vector Y ' ] ,
dataPoints [ ' Position vector Z ' ] ] )
vec . setVelocity ( [
dataPoints [ ' Velocity vector X ' ] / velocityScale ,
dataPoints [ ' Velocity vector Y ' ] / velocityScale ,
dataPoints [ ' Velocity vector Z ' ] / velocityScale ] )
orbit . addStateVector ( vec )
def _populateAttitude ( self ) :
if ( self . leaderFile . leaderFDR . metadata [
' Number of attitude data records ' ] != 1 ) :
return
attitude = self . frame . getAttitude ( )
attitude . setAttitudeSource ( " Header " )
year = int ( self . leaderFile . sceneHeaderRecord . metadata [
' Scene centre time ' ] [ 0 : 4 ] )
t0 = datetime . datetime ( year = year , month = 1 , day = 1 )
for i in range ( self . leaderFile . platformAttitudeRecord . metadata [
' Number of attitude data points ' ] ) :
vec = AttitudeStateVector ( )
dataPoints = self . leaderFile . platformAttitudeRecord . metadata [
' Attitude Data Points ' ] [ i ]
t = t0 + datetime . timedelta (
days = ( dataPoints [ ' Day of the year ' ] - 1 ) ,
milliseconds = dataPoints [ ' Millisecond of day ' ] )
vec . setTime ( t )
vec . setPitch ( dataPoints [ ' Pitch ' ] )
vec . setRoll ( dataPoints [ ' Roll ' ] )
vec . setYaw ( dataPoints [ ' Yaw ' ] )
attitude . addStateVector ( vec )
def _populateDistortions ( self ) :
return None
def readOrbitPulse ( self , leader , raw , width ) :
'''
No longer used . Can ' t rely on raw data headers. Should be done as part of extract Image.
'''
from isceobj . Sensor import readOrbitPulse as ROP
print ( ' TTTT ' )
rawImage = isceobj . createRawImage ( )
leaImage = isceobj . createStreamImage ( )
auxImage = isceobj . createImage ( )
rawImage . initImage ( raw , ' read ' , width )
rawImage . renderVRT ( )
rawImage . createImage ( )
rawAccessor = rawImage . getImagePointer ( )
leaImage . initImage ( leader , ' read ' )
leaImage . createImage ( )
leaAccessor = leaImage . getImagePointer ( )
widthAux = 2
auxName = raw + ' .aux '
self . frame . auxFile = auxName
auxImage . initImage ( auxName , ' write ' , widthAux , type = ' DOUBLE ' )
auxImage . createImage ( )
auxAccessor = auxImage . getImagePointer ( )
length = rawImage . getLength ( )
ROP . setNumberBitesPerLine_Py ( width )
ROP . setNumberLines_Py ( length )
ROP . readOrbitPulse_Py ( leaAccessor , rawAccessor , auxAccessor )
rawImage . finalizeImage ( )
leaImage . finalizeImage ( )
auxImage . finalizeImage ( )
return None
def makeFakeAux ( self , outputNow ) :
'''
Generate an aux file based on sensing start and prf .
'''
import math , array
prf = self . frame . getInstrument ( ) . getPulseRepetitionFrequency ( )
senStart = self . frame . getSensingStart ( )
numPulses = self . frame . numberOfLines
# the aux files has two entries per line. day of the year and microseconds in the day
musec0 = ( senStart . hour * 3600 + senStart . minute * 60 + senStart . second ) * 10 * * 6 + senStart . microsecond
maxMusec = ( 24 * 3600 ) * 10 * * 6 #use it to check if we went across a day. very rare
day0 = ( datetime . datetime ( senStart . year , senStart . month , senStart . day ) - datetime . datetime ( senStart . year , 1 , 1 ) ) . days + 1
outputArray = array . array ( ' d ' , [ 0 ] * 2 * numPulses )
self . frame . auxFile = outputNow + ' .aux '
fp = open ( self . frame . auxFile , ' wb ' )
j = - 1
for i1 in range ( numPulses ) :
j + = 1
musec = round ( ( j / prf ) * 10 * * 6 ) + musec0
if musec > = maxMusec :
day0 + = 1
musec0 = musec % maxMusec
musec = musec0
j = 0
outputArray [ 2 * i1 ] = day0
outputArray [ 2 * i1 + 1 ] = musec
outputArray . tofile ( fp )
fp . close ( )
## Can this even be done/
## should the pointer be an __Int__?
def readOrbitPulseDevelopement ( self , leader , raw , width ) :
from isceobj . Sensor import readOrbitPulse as ROP
with isceobj . contextRawImage ( width = width , accessMode = ' read ' , ) as rawImage :
with isceobj . contextStreamImage ( width = width , accessMode = ' read ' , ) as leaImage :
with isceobj . contextImage ( width = width , accessMode = ' write ' , ) as auxImage :
rawAccessor = rawImage . getImagePointer ( )
leaAccessor = leaImage . getImagePointer ( )
widthAux = 2
auxName = raw + ' .aux '
self . frame . auxFile = auxName
auxImage . initImage ( auxName , ' write ' , widthAux ,
type = ' DOUBLE ' )
auxImage . createImage ( )
auxAccessor = auxImage . getImagePointer ( )
length = rawImage . getLength ( )
ROP . setNumberBitesPerLine_Py ( width )
ROP . setNumberLines_Py ( length )
ROP . readOrbitPulse_Py ( leaAccessor , rawAccessor , auxAccessor )
pass #rawImage.finalizeImage()
pass #leaImage.finalizeImage()
pass #auxImage.finalizeImage()
return None
def extractImage ( self ) :
if ( len ( self . _imageFileList ) != len ( self . _leaderFileList ) ) :
self . logger . error (
" Number of leader files different from number of image files. " )
raise RuntimeError
self . frameList = [ ]
for i in range ( len ( self . _imageFileList ) ) :
appendStr = " _ " + str ( i )
#if only one file don't change the name
if ( len ( self . _imageFileList ) == 1 ) :
appendStr = ' '
self . frame = Frame ( )
self . frame . configure ( )
self . _leaderFile = self . _leaderFileList [ i ]
self . _imageFile = self . _imageFileList [ i ]
self . leaderFile = LeaderFile ( file = self . _leaderFile )
self . imageFile = ImageFile ( self )
try :
self . leaderFile . parse ( )
self . imageFile . parse ( calculateRawDimensions = False )
outputNow = self . output + appendStr
if not ( self . _resampleFlag == ' ' ) :
filein = self . output + ' __tmp__ '
2020-10-20 02:45:01 +00:00
self . imageFile . extractImage ( filein , i ) #image number start with 0
2019-01-16 19:40:08 +00:00
self . populateMetadata ( )
objResample = None
if ( self . _resampleFlag == ' single2dual ' ) :
objResample = ALOS_fbs2fbdPy ( )
else :
objResample = ALOS_fbd2fbsPy ( )
objResample . wireInputPort ( ' frame ' , object = self . frame )
objResample . setInputFilename ( filein )
objResample . setOutputFilename ( outputNow )
objResample . run ( )
objResample . updateFrame ( self . frame )
os . remove ( filein )
else :
2020-10-20 02:45:01 +00:00
self . imageFile . extractImage ( outputNow , i ) #image number start with 0
2019-01-16 19:40:08 +00:00
self . populateMetadata ( )
width = self . frame . getImage ( ) . getWidth ( )
# self.readOrbitPulse(self._leaderFile,outputNow,width)
self . makeFakeAux ( outputNow )
self . frameList . append ( self . frame )
except IOError :
return
pass
## refactor this with __init__.tkfunc
return tkfunc ( self )
def _decodeSceneReferenceNumber ( self , referenceNumber ) :
return referenceNumber
def _decodeOrbitQuality ( self , quality ) :
try :
quality = int ( quality )
except ValueError :
quality = None
qualityString = ' '
if ( quality == 0 ) :
qualityString = ' Preliminary '
elif ( quality == 1 ) :
qualityString = ' Decision '
elif ( quality == 2 ) :
qualityString = ' High Precision '
else :
qualityString = ' Unknown '
return qualityString
def updateRawParameters ( self ) :
'''
Parse the data in python .
'''
with open ( self . _imageFile , ' rb ' ) as fp :
width = self . imageFile . width
numberOfLines = self . imageFile . length
prefix = self . imageFile . prefix
suffix = self . imageFile . suffix
dataSize = self . imageFile . dataSize
fp . seek ( 720 , os . SEEK_SET ) # Skip the header
tags = [ ]
print ( ' WIDTH: ' , width )
print ( ' LENGTH: ' , numberOfLines )
print ( ' PREFIX: ' , prefix )
print ( ' SUFFIX: ' , suffix )
print ( ' DATASIZE: ' , dataSize )
for i in range ( numberOfLines ) :
if not i % 1000 : self . logger . info ( " Line %s " % i )
imageRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix , ' alos/image_record.xml ' ) ,
dataFile = fp )
imageRecord . parse ( )
tags . append ( float ( imageRecord . metadata [
' Sensor acquisition milliseconds of day ' ] ) )
data = fp . read ( dataSize )
pass
###Do parameter fit
import numpy as np
tarr = np . array ( tags ) - tags [ 0 ]
ref = np . arange ( tarr . size ) / self . frame . PRF
print ( ' PRF: ' , self . frame . PRF )
####Check every 20 microsecs
off = np . arange ( 50 ) * 2.0e-5
res = np . zeros ( off . size )
###Check which offset produces the same millisec truncation
###Assumes PRF is correct
for xx in range ( off . size ) :
ttrunc = np . floor ( ( ref + off [ xx ] ) * 1000 )
res [ xx ] = np . sum ( tarr - ttrunc )
res = np . abs ( res )
# import matplotlib.pyplot as plt
# plt.plot(res)
# plt.show()
delta = datetime . timedelta ( seconds = np . argmin ( res ) * 2.0e-5 )
print ( ' TIME OFFSET: ' , delta )
self . frame . sensingStart + = delta
self . frame . sensingMid + = delta
self . frame . sensingStop + = delta
return None
class LeaderFile ( object ) :
def __init__ ( self , file = None ) :
self . file = file
self . leaderFDR = None
self . sceneHeaderRecord = None
self . platformPositionRecord = None
self . platformAttitudeRecord = None
self . calibrationRecord = None
return None
def parse ( self ) :
""" Parse the leader file to create a header object """
try :
with open ( self . file , ' rb ' ) as fp :
# Leader record
self . leaderFDR = CEOS . CEOSDB ( xml = os . path . join ( xmlPrefix ,
' alos ' , ' leader_file.xml ' ) , dataFile = fp )
self . leaderFDR . parse ( )
fp . seek ( self . leaderFDR . getEndOfRecordPosition ( ) )
# Scene Header, called the "Data Set Summary Record" by JAXA
if ( self . leaderFDR . metadata [
' Number of data set summary records ' ] == 1 ) :
self . sceneHeaderRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix , ' alos ' , ' scene_record.xml ' ) ,
dataFile = fp )
self . sceneHeaderRecord . parse ( )
fp . seek ( self . sceneHeaderRecord . getEndOfRecordPosition ( ) )
pass
# Platform Position
if ( self . leaderFDR . metadata [
' Number of platform pos. data records ' ] == 1 ) :
self . platformPositionRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix ,
' alos/platform_position_record.xml ' ) , dataFile = fp )
self . platformPositionRecord . parse ( )
fp . seek (
self . platformPositionRecord . getEndOfRecordPosition ( ) )
pass
# Spacecraft Attitude
if ( self . leaderFDR . metadata [
' Number of attitude data records ' ] == 1 ) :
self . platformAttitudeRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix , ' alos/attitude_record.xml ' ) ,
dataFile = fp )
self . platformAttitudeRecord . parse ( )
fp . seek (
self . platformAttitudeRecord . getEndOfRecordPosition ( ) )
pass
# Spacecraft calibration
if ( self . leaderFDR . metadata [
' Number of calibration records ' ] == 1 ) :
self . calibrationRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix ,
' alos/calibration_record.xml ' ) , dataFile = fp )
self . calibrationRecord . parse ( )
fp . seek ( self . calibrationRecord . getEndOfRecordPosition ( ) )
pass
pass
pass
except IOError as errs :
strerr = errs . strerror
print ( " IOError: %s " % strerr )
return None
pass
class VolumeDirectoryFile ( VolumeDirectoryBase ) :
volume_fdr_arg = os . path . join ( ' alos ' , ' volume_descriptor.xml ' )
pass
class ImageFile ( object ) :
def __init__ ( self , parent ) :
self . parent = parent
self . length = None
self . width = None
self . start_time = None
self . stop_time = None
self . startingRange = None
self . imageFDR = None
self . numberOfSarChannels = None
self . prf = None
self . prefix = None
self . suffix = None
self . dataSize = None
return None
def parse ( self , calculateRawDimensions = True ) :
try :
with open ( self . parent . _imageFile , ' rb ' ) as fp :
# Image Header
self . imageFDR = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix , ' alos ' , ' image_file.xml ' ) ,
dataFile = fp )
self . imageFDR . parse ( )
fp . seek ( self . imageFDR . getEndOfRecordPosition ( ) , os . SEEK_SET )
self . numberOfSarChannels = self . imageFDR . metadata [
' Number of SAR channels in this file ' ]
if calculateRawDimensions : self . _calculateRawDimensions ( fp )
pass
except IOError as errs :
errno , strerr = errs
print ( " IOError: %s " % strerr )
return None
2020-10-20 02:45:01 +00:00
def extractImage ( self , output = None , image_i = 0 ) :
2019-01-16 19:40:08 +00:00
""" For now, call a wrapped version of ALOS_pre_process """
productLevel = float ( self . parent . leaderFile . sceneHeaderRecord . metadata [
' Product level code ' ] )
self . parent . logger . info ( " Extracting Level %s data " % ( productLevel ) )
if productLevel == 1.5 :
raise NotImplementedError
elif productLevel == 1.1 :
self . extractSLC ( output )
elif productLevel == 1.0 :
2020-10-20 02:45:01 +00:00
self . extractRaw ( output , image_i ) #image number start with 0
2019-01-16 19:40:08 +00:00
else :
raise ValueError ( productLevel )
return None
@use_api
2020-10-20 02:45:01 +00:00
def extractRaw ( self , output = None , image_i = 0 ) :
2019-01-16 19:40:08 +00:00
#if (self.numberOfSarChannels == 1):
# print "Single Pol Data Found"
# self.extractSinglePolImage(output=output)
#elif (self.numberOfSarChannels == 3):
# print "Dual Pol Data Found"
#elif (self.numberOfSarChannels == 6):
# print "Quad Pol Data Found"
if self . parent . leaderFile . sceneHeaderRecord . metadata [
' Processing facility identifier ' ] == ' ERSDAC ' :
prmDict = alos . alose_Py ( self . parent . _leaderFile ,
2020-10-20 02:45:01 +00:00
self . parent . _imageFile , output , image_i ) #image number start with 0
2019-01-16 19:40:08 +00:00
else :
prmDict = alos . alos_Py ( self . parent . _leaderFile ,
2020-10-20 02:45:01 +00:00
self . parent . _imageFile , output , image_i ) #image number start with 0
2019-01-16 19:40:08 +00:00
pass
# updated 07/24/2012
self . width = prmDict [ ' NUMBER_BYTES_PER_LINE ' ] - 2 * prmDict [ ' FIRST_SAMPLE ' ]
2020-10-20 02:45:01 +00:00
#self.length = self.imageFDR.metadata['Number of lines per data set']
self . length = prmDict [ ' NUMBER_LINES ' ]
2019-01-16 19:40:08 +00:00
self . prefix = self . imageFDR . metadata [
' Number of bytes of prefix data per record ' ]
self . suffix = self . imageFDR . metadata [
' Number of bytes of suffix data per record ' ]
self . dataSize = self . imageFDR . metadata [
' Number of bytes of SAR data per record ' ]
self . start_time = self . _parseClockTime ( prmDict [ ' SC_CLOCK_START ' ] )
self . stop_time = self . _parseClockTime ( prmDict [ ' SC_CLOCK_STOP ' ] )
self . startingRange = prmDict [ ' NEAR_RANGE ' ]
self . prf = prmDict [ ' PRF ' ]
rawImage = isceobj . createRawImage ( )
rawImage . setFilename ( output )
rawImage . setAccessMode ( ' read ' )
rawImage . setWidth ( self . width )
rawImage . setXmax ( self . width )
rawImage . setXmin ( 0 )
self . parent . getFrame ( ) . setImage ( rawImage )
rawImage . renderVRT ( )
# updated 07/24/2012
return None
def extractSLC ( self , output = None ) :
"""
For now , just skip the header and dump the SLC ;
it should be complete and without missing lines
"""
with open ( self . parent . _imageFile , ' rb ' ) as fp :
with open ( output , ' wb ' ) as out :
self . width = int ( self . imageFDR . metadata [
' Number of bytes of SAR data per record ' ] /
self . imageFDR . metadata [ ' Number of bytes per data group ' ] )
self . length = int ( self . imageFDR . metadata [
' Number of lines per data set ' ] )
## JEB: use arguments?
slcImage = isceobj . createSlcImage ( )
slcImage . setFilename ( output )
slcImage . setByteOrder ( ' b ' )
slcImage . setAccessMode ( ' read ' )
slcImage . setWidth ( self . width )
slcImage . setXmin ( 0 )
slcImage . setXmax ( self . width )
self . parent . getFrame ( ) . setImage ( slcImage )
numberOfLines = self . imageFDR . metadata [
' Number of lines per data set ' ]
prefix = self . imageFDR . metadata [
' Number of bytes of prefix data per record ' ]
suffix = self . imageFDR . metadata [
' Number of bytes of suffix data per record ' ]
dataSize = self . imageFDR . metadata [
' Number of bytes of SAR data per record ' ]
fp . seek ( self . HEADER_LINES , os . SEEK_SET ) # Skip the header
for i in range ( numberOfLines ) :
if not i % 1000 : self . parent . logger . info ( " Line %s " % i )
imageRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix , ' alos/image_record.xml ' ) ,
dataFile = fp )
imageRecord . parse ( )
if i == 0 :
self . start_time = self . _getAcquisitionTime ( imageRecord )
self . startingRange = self . _getSlantRange ( imageRecord )
self . prf = self . _getPRF ( imageRecord )
elif i == ( numberOfLines - 1 ) :
self . stop_time = self . _getAcquisitionTime ( imageRecord )
# else:
# Skip the first 412 bytes of each line
# fp.seek(prefix, os.SEEK_CUR)
# pass
data = fp . read ( dataSize )
out . write ( data )
fp . seek ( suffix , os . SEEK_CUR )
pass
pass
pass
return None
def _getSlantRange ( self , imageRecord ) :
slantRange = imageRecord . metadata [ ' Slant range to 1st pixel ' ]
return slantRange
def _getPRF ( self , imageRecord ) :
prf = imageRecord . metadata [ ' PRF ' ] / 1000.0 # PRF is in mHz
return prf
def _getAcquisitionTime ( self , imageRecord ) :
acquisitionTime = datetime . datetime (
year = imageRecord . metadata [ ' Sensor acquisition year ' ] , month = 1 , day = 1 )
acquisitionTime = acquisitionTime + datetime . timedelta (
days = ( imageRecord . metadata [ ' Sensor acquisition day of year ' ] - 1 ) ,
milliseconds = imageRecord . metadata [
' Sensor acquisition milliseconds of day ' ] )
return acquisitionTime
## Arguemnt doesn't make sense, since file is repopend
def _calculateRawDimensions ( self , fp = None ) :
""" "
Run through the data file once , and calculate the valid sampling window
start time range .
"""
## If you have a file, and you've parsed it: go for it
if fp and self . imageFDR :
lines = int ( self . imageFDR . metadata [ ' Number of lines per data set ' ] )
prefix = self . imageFDR . metadata [
' Number of bytes of prefix data per record ' ]
suffix = self . imageFDR . metadata [
' Number of bytes of suffix data per record ' ]
dataSize = self . imageFDR . metadata [
' Number of bytes of SAR data per record ' ]
self . length = lines
self . width = dataSize + suffix
# Need to get the Range sampling rate as well to calculate the
# number of pixels to shift each line when the starting range
# changes
fp . seek ( self . imageFDR . getEndOfRecordPosition ( ) , os . SEEK_SET )
lastPRF = 0
lastSlantRange = 0
for line in range ( lines ) :
if not line % 1000 :
self . parent . logger . info ( " Parsing line %s " % line )
imageRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix , ' alos/image_record.xml ' ) ,
dataFile = fp )
imageRecord . parse ( )
acquisitionTime = self . _getAcquisitionTime ( imageRecord )
prf = imageRecord . metadata [ ' PRF ' ]
if lastPRF == 0 :
lastPRF = prf
elif lastPRF != prf :
self . parent . logger . info ( " PRF change detected " )
lastPRF = prf
txPolarization = imageRecord . metadata [
' Transmitted polarization ' ]
rxPolarization = imageRecord . metadata [ ' Received polarization ' ]
slantRange = self . _getSlantRange ( imageRecord )
if lastSlantRange == 0 :
lastSlantRange = slantRange
elif lastSlantRange != slantRange :
self . parent . logger . info ( " Slant range offset detected " )
lastSlantRange = slantRange
pass
if line == 0 :
self . start_time = acquisitionTime
self . startingRange = slantRange
elif line == ( lines - 1 ) :
self . stop_time = acquisitionTime
pass
fp . seek ( dataSize + suffix , os . SEEK_CUR )
pass
pass
else :
## The parse method will call this one properly
self . parse ( True )
return None
def extractSinglePolImage ( self , output = None ) :
import array
if not self . imageFDR :
self . parse ( )
pass
try :
with open ( self . file , ' r ' ) as fp :
with open ( output , ' wb ' ) as out :
lines = self . imageFDR . metadata [
' Number of lines per data set ' ]
pixelCount = ( self . imageFDR . metadata [
' Number of left border pixels per line ' ] +
self . imageFDR . metadata [
' Number of pixels per line per SAR channel ' ] +
self . imageFDR . metadata [
' Number of right border pixels per line ' ]
)
# Need to get the Range sampling rate as well to calculate
# the number of pixels to shift each line when the starting
# range changes
fp . seek ( self . imageFDR . getEndOfRecordPosition ( ) , os . SEEK_SET )
lastSlantRange = 0
for line in range ( lines ) :
if not line % 1000 : print ( " Extracting line %s " % line )
imageRecord = CEOS . CEOSDB (
xml = os . path . join ( xmlPrefix , ' alos/image_record.xml ' ) ,
dataFile = fp )
imageRecord . parse ( )
prf = imageRecord . metadata [ ' PRF ' ]
txPolarization = imageRecord . metadata [
' Transmitted polarization ' ]
rxPolarization = imageRecord . metadata [
' Received polarization ' ]
slantRange = imageRecord . metadata [
' Slant range to 1st pixel ' ]
if lastSlantRange == 0 :
lastSlantRange = slantRange
elif lastSlantRange != slantRange :
print ( " Slant range offset detected " )
lastSlantRange = slantRange
pass
acquisitionTime = datetime . datetime (
year = imageRecord . metadata [
' Sensor acquisition year ' ] , month = 1 , day = 1 )
acquisitionTime = acquisitionTime + datetime . timedelta (
days = imageRecord . metadata [
' Sensor acquisition day of year ' ] ,
milliseconds = imageRecord . metadata [
' Sensor acquisition milliseconds of day ' ] )
IQ = array . array ( ' B ' )
IQ . fromfile ( fp , 2 * pixelCount )
IQ . tofile ( out )
pass
pass
pass
except IOError as errs :
errno , strerr = errs
print ( " IOError: %s " % strerr )
return None
@staticmethod
def _parseClockTime ( clockTime ) :
from iscesys . DateTimeUtil import DateTimeUtil as DTU
date , time = str ( clockTime ) . split ( ' . ' )
year = int ( date [ 0 : 4 ] )
doy = int ( date [ 4 : 7 ] )
utc_seconds = ( clockTime - int ( date ) ) * DTU . day
dt = datetime . datetime ( year = year , month = 1 , day = 1 )
dt = dt + datetime . timedelta ( days = ( doy - 1 ) , seconds = utc_seconds )
return dt
pass