Skip to content

Commit 75786fa

Browse files
gshiromaGitHub Enterprise
authored andcommitted
ALOS-2 PALSAR L1.1 to NISAR RSLC HDF5 (#529)
* adding first dirty (but "working") version of the ALOS-2 to HDF5 software * increase az. time precision, add Doppler, fix multiple bugs, and refactor code * address PR reviews. Throw exception for invalid time type when saving attitude records. Remove unnecessary code. * remove constraint to the number of polarization channels * pull changes from #531: Quick update to the Geocode Cython binding constructor * rename alos2 Python scripts * read HDF5 groups only if they exist * simplify code by importing functions from ALOS2NISARL0B.py, clean and refactor code, and update calls to pybind bindings * Write the ALOS-2 RSLC product using an RSLC template * allows for overwriting fields previously copied during h5_prep (e.g. isGeocoded)
1 parent ebbbf61 commit 75786fa

File tree

17 files changed

+1478
-10
lines changed

17 files changed

+1478
-10
lines changed

cxx/isce3/product/Serialization.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,26 @@ namespace isce3 {
4545

4646
// Load effective velocity LUT
4747
isce3::core::LUT2d<double> lut;
48-
isce3::core::loadCalGrid(group, "effectiveVelocity", lut);
49-
proc.effectiveVelocity(lut);
48+
if (isce3::io::exists(group, "effectiveVelocity")) {
49+
isce3::core::loadCalGrid(group, "effectiveVelocity", lut);
50+
proc.effectiveVelocity(lut);
51+
}
5052

51-
// Load azimuth FM rate and Doppler centroid for primary frequency (A)
52-
isce3::core::loadCalGrid(group, "frequencyA/azimuthFMRate", lut);
53-
proc.azimuthFMRate(lut, 'A');
53+
if (isce3::io::exists(group, "frequencyA/azimuthFMRate")) {
54+
// Load azimuth FM rate and Doppler centroid for primary frequency (A)
55+
isce3::core::loadCalGrid(group, "frequencyA/azimuthFMRate", lut);
56+
proc.azimuthFMRate(lut, 'A');
57+
}
5458
isce3::core::loadCalGrid(group, "frequencyA/dopplerCentroid", lut);
5559
proc.dopplerCentroid(lut, 'A');
5660

5761
// Check for existence of secondary frequencies
5862
if (isce3::io::exists(group, "frequencyB")) {
59-
isce3::core::loadCalGrid(group, "frequencyB/azimuthFMRate", lut);
60-
proc.azimuthFMRate(lut, 'B');
63+
64+
if (isce3::io::exists(group, "frequencyB/azimuthFMRate")) {
65+
isce3::core::loadCalGrid(group, "frequencyB/azimuthFMRate", lut);
66+
proc.azimuthFMRate(lut, 'B');
67+
}
6168
isce3::core::loadCalGrid(group, "frequencyB/dopplerCentroid", lut);
6269
proc.dopplerCentroid(lut, 'B');
6370
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from isce3.parsers.CEOS.AttitudeDataRecordType import (AttitudeDataRecordHeaderType,
2+
AttitudeDataRecordStateVectorType)
3+
4+
def AttitudeDataRecordTrailerType(inlen):
5+
'''
6+
Attitude Data Record Trailer.
7+
https://www.eorc.jaxa.jp/ALOS-2/en/doc/fdata/PALSAR-2_xx_Format_CEOS_E_f.pdf
8+
'''
9+
10+
from isce3.parsers.CEOS.BasicTypes import BlankType
11+
12+
return BlankType(inlen)
13+
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
def DatasetSummaryRecordType():
2+
'''
3+
Data Set Summary Record.
4+
https://www.eorc.jaxa.jp/ALOS-2/en/doc/fdata/PALSAR-2_xx_Format_CEOS_E_f.pdf
5+
'''
6+
from isce3.parsers.CEOS.BasicTypes import (BlankType, StringType, IntegerType, FloatType, MultiType)
7+
from isce3.parsers.CEOS.CEOSHeaderType import CEOSHeaderType
8+
9+
#Common part of CEOS header (modified)
10+
inlist = CEOSHeaderType().mapping
11+
inlist += [('DSRecordSequenceNumber', IntegerType(4)),
12+
('SARChannelIndicator', StringType(4)),
13+
('SceneIdentifier', StringType(32)),
14+
('SceneDesignator', StringType(16)),
15+
('InputSceneCenterTime', StringType(32)),
16+
('blanks1', BlankType(16)),
17+
('SceneCenterLatitude', BlankType(16)),
18+
('SceneCenterLongitude', BlankType(16)),
19+
('SceneCenterHeading', BlankType(16)),
20+
('EllipsoidDesignator', StringType(16)),
21+
('EllipsoidSemiMajorAxisInKm', FloatType(16)),
22+
('EllipsoidSemiMinorAxisInKm', FloatType(16)),
23+
('EarthMassIn1024Kg', FloatType(16)),
24+
('GravitationalConstant', FloatType(16)),
25+
('EllipsoidJ2Parameter', FloatType(16)),
26+
('EllipsoidJ3Parameter', FloatType(16)),
27+
('EllipsoidJ4Parameter', FloatType(16)),
28+
('blanks2', BlankType(16)),
29+
('AverageTerrainHeight', FloatType(16)),
30+
('SceneCenterLineNumber', IntegerType(8)),
31+
('SceneCenterPixelNumber', IntegerType(8)),
32+
('ProcessedSceneLengthInKm', FloatType(16)),
33+
('ProcessedSceneWidthInKm', FloatType(16)),
34+
('blanks3', BlankType(16)),
35+
('NumberOfSARChannels', IntegerType(4)),
36+
('blanks4', BlankType(4)),
37+
('SensorPlatformMissionIdentifier', StringType(16)),
38+
('SensorIDAndMode', StringType(32)),
39+
('OrbitNumber', IntegerType(8)),
40+
('SensorPlatformLatitude', BlankType(8)),
41+
('SensorPlatformLongitude', BlankType(8)),
42+
('SensorPlatformHeading', BlankType(8)),
43+
('SensorClockAngle', FloatType(8)),
44+
('SceneCenterIncidenceAngle', FloatType(8)),
45+
('blanks5', BlankType(8)),
46+
('RadarWavelengthInm', FloatType(16)),
47+
('MotionCompensationIndicator', StringType(2)),
48+
('RangePulseCodeSpecifier', StringType(16)),
49+
('RangePulseAmplitudeCoefficientDCTerm', FloatType(16)),
50+
('RangePulseAmplitudeCoefficientLinearTerm', FloatType(16)),
51+
('RangePulseAmplitudeCoefficientQuadraticTerm', FloatType(16)),
52+
('RangePulseAmplitudeCoefficientCubicTerm', FloatType(16)),
53+
('RangePulseAmplitudeCoefficientQuarticTerm', FloatType(16)),
54+
('RangePulsePhaseCoefficientDCTerm', FloatType(16)),
55+
('RangePulsePhaseCoefficientLinearTerm', FloatType(16)),
56+
('RangePulsePhaseCoefficientQuadraticTerm', FloatType(16)),
57+
('RangePulsePhaseCoefficientCubicTerm', FloatType(16)),
58+
('RangePulsePhaseCoefficientQuarticTerm', FloatType(16)),
59+
('DownlinkedDataChirpExtractionIndex', BlankType(8)),
60+
('blanks6', BlankType(8)),
61+
('SamplingRateInMHz', FloatType(16)),
62+
('RangeGateAtEarlyEdgeAtStartOfImageInusec', FloatType(16)),
63+
('RangePulseLengthInusec', FloatType(16)),
64+
('BasebandConversionFlag', StringType(4)),
65+
('RangeCompressedFlag', StringType(4)),
66+
('ReceiverGainCopolEarlyEdgeindB', FloatType(16)),
67+
('ReceiverGainXpolEarlyEdgeindB', FloatType(16)),
68+
('QuantizationBitsPerChannel', IntegerType(8)),
69+
('QuantizationDescriptor', StringType(12)),
70+
('DCBiasIComponent', FloatType(16)),
71+
('DCBiasQComponent', FloatType(16)),
72+
('GainImbalanceforIQ', FloatType(16)),
73+
('blanks7', BlankType(16)),
74+
('blanks8', BlankType(16)),
75+
('AntennaElectronicBoresightInDeg', FloatType(16)),
76+
('AntennaMechanicalBoresightInDeg', FloatType(16)),
77+
('EchoTrackerOnOffFlag', StringType(4)),
78+
('NominalPRFInmHz', FloatType(16)),
79+
('EffectiveTwoWayAntennaElevation3dBBeamwidthInDeg', FloatType(16)),
80+
('EffectiveTwoWayAntennaAzimuth3dBBeamwidthInDeg', FloatType(16)),
81+
('SatelliteEncodedBinaryTimeCode', IntegerType(16)),
82+
('SatelliteClockTime', StringType(32)),
83+
('SatelliteClockIncrementInnsec', IntegerType(16)),
84+
('ProcessingFacilityIdentifier', StringType(16)),
85+
('ProcessingSystemIdentifier', StringType(8)),
86+
('ProcessingVersionIdentifier', StringType(8)),
87+
('ProcessingFacilityProcessCode', StringType(16)),
88+
('ProductLevelCode', StringType(16)),
89+
('ProductTypeSpecifier', StringType(32)),
90+
('ProcessingAlgorithmIdentifier', StringType(32)),
91+
('NominalEffectiveAzimuthLooks', FloatType(16)),
92+
('NominalEffectiveRangeLooks', FloatType(16)),
93+
('BandwidthPerLookInAzimuthHz', FloatType(16)),
94+
('BandwidthPerLookInRangeHz', FloatType(16)),
95+
('TotalProcessorBandwidthInAzimuth', FloatType(16)),
96+
('TotalProcessorBandwidthInRange', FloatType(16)),
97+
('WeightingFunctionInAzimuth', StringType(32)),
98+
('WeightingFunctionInRange', StringType(32)),
99+
('DataInputSource', StringType(16)),
100+
('Nominal3dBResolutionInGroundRangeInm', FloatType(16)),
101+
('Nominal3dBResolutionInAzimuthInm', FloatType(16)),
102+
('ConstantRadiometricParameterBias', FloatType(16)),
103+
('LinearRadiometricParameterGain', FloatType(16)),
104+
('AlongTrackDopplerConstantTermInHz', FloatType(16)),
105+
('AlongTrackDopplerLinearTermInHzPerPixel', FloatType(16)),
106+
('AlongTrackDopplerQuadraticTermInHzPerPixel2', FloatType(16)),
107+
('blanks9', BlankType(16)),
108+
('CrossTrackDopplerConstantTermInHz', FloatType(16)),
109+
('CrossTrackDopplerLinearTermInHzPerPixel', FloatType(16)),
110+
('CrossTrackDopplerLinearTermInHzPerPixel2', FloatType(16)),
111+
('TimeDirectionIndicatorAlongPixel', StringType(8)),
112+
('TimeDirectionIndicatorAlongLine', StringType(8)),
113+
('AlongTrackDopplerRateConstantTermInHzPerSec', FloatType(16)),
114+
('AlongTrackDopplerRateLinearTermInHzPerSecPerPixel', FloatType(16)),
115+
('AlongTrackDopplerRateQuadraticTermInHzPerSecPerPixel2', FloatType(16)),
116+
('blanks10', BlankType(16)),
117+
('CrossTrackDopplerRateConstantTermInHzPerSec', FloatType(16)),
118+
('CrossTrackDopplerRateLinearTermInHzPerSecPerPixel', FloatType(16)),
119+
('CrossTrackDopplerRateQuadraticTermInHzPerSecPerPixel2', FloatType(16)),
120+
('blanks11', BlankType(16)),
121+
('LineContentIndicator', StringType(8)),
122+
('ClutterLockAppliedFlag', StringType(4)),
123+
('AutoFocusingAppliedFlag', StringType(4)),
124+
('LineSpacingInm', FloatType(16)),
125+
('PixelSpacingInm', FloatType(16)),
126+
('ProcessorRangeCompressionDesignator', StringType(16)),
127+
('DopplerCenterFrequencyConstantTerm', FloatType(16)),
128+
('DopplerCenterFrequencyLinearTerm', FloatType(16))]
129+
130+
#ALOS specific trailer
131+
inlist += [('CalibrationDataIndicator', IntegerType(4)),
132+
('StartLineNumberCalibrationUpper', IntegerType(8)),
133+
('StopLineNumberCalibrationUpper', IntegerType(8)),
134+
('StartLineNumberCalibrationBottom', IntegerType(8)),
135+
('StopLineNumberCalibrationBottom', IntegerType(8)),
136+
('PRFSwitchingIndicator', IntegerType(4)),
137+
('LineLocatorOfPRFSwitching', IntegerType(8)),
138+
('blanks14', BlankType(16)),
139+
('YawSteeringModeFlag', IntegerType(4)),
140+
('ParameterTableNumber', IntegerType(4)),
141+
('NominalOffNadirAngle', FloatType(16)),
142+
('AntennaBeamNumber', IntegerType(4)),
143+
('blanks15', BlankType(28)),
144+
('blanks16', BlankType(120)),
145+
('NumberOfAnnotationPoints', IntegerType(8)),
146+
('blanks17', BlankType(2082))]
147+
148+
return MultiType( inlist )
149+
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
##This is the first cut to get the HDF5 translation working.
2+
##Signal Record Iterator can be better designed
3+
##The code currently only iterates over the records - modification/ manipulation belongs to customer
4+
5+
class ImageFile(object):
6+
'''
7+
Class for parsing ALOS-2 L1.1 CEOS Imagefile.
8+
'''
9+
10+
def __init__(self, filename):
11+
'''
12+
Initialize object with leader filename.
13+
'''
14+
import os
15+
16+
#Save file name
17+
self.name = filename
18+
19+
#Save file size in bytes
20+
self.size = os.stat(filename).st_size
21+
22+
#Leader file always seems to consist of same set of records.
23+
#https://www.eorc.jaxa.jp/ALOS-2/en/doc/fdata/PALSAR-2_xx_Format_CEOS_E_f.pdf
24+
self.fid = open(self.name, 'rb')
25+
26+
#Leader file descriptor
27+
self.description = self.parseFileDescriptor()
28+
29+
#Line counter
30+
self.counter = 0
31+
32+
def close(self):
33+
'''
34+
Close file object.
35+
'''
36+
self.fid.close()
37+
38+
def parseFileDescriptor(self):
39+
'''
40+
Parse SAR Leaderfile descriptor record.
41+
'''
42+
from isce3.parsers.CEOS.ImageFileDescriptorType import ImageFileDescriptorType
43+
44+
#Description of record - seems to be common across missions
45+
record = ImageFileDescriptorType()
46+
47+
#Read the record
48+
record.fromfile(self.fid)
49+
50+
#Sensor specific validators
51+
#https://www.eorc.jaxa.jp/ALOS-2/en/doc/fdata/PALSAR-2_xx_Format_CEOS_E_f.pdf
52+
assert(record.RecordSequenceNumber == 1)
53+
assert(record.FirstRecordType == 50)
54+
assert(record.RecordTypeCode == 192)
55+
assert(record.SecondRecordSubType == 18)
56+
assert(record.ThirdRecordSubType == 18)
57+
assert(record.RecordLength == 720)
58+
assert(record.RecordSequenceType == 'FSEQ')
59+
assert(record.RecordCodeType == 'FTYP')
60+
assert(record.RecordFieldType == 'FLGT')
61+
assert(record.SampleDataLineNumberLocator == "13 4PB")
62+
assert(record.SARChannelNumberLocator == "49 2PB")
63+
assert(record.TimeOfSARDataLineLocator == "45 4PB")
64+
assert(record.LeftFillCountLocator == "21 4PB")
65+
assert(record.RightFillCountLocator == "29 4PB")
66+
assert(record.SARDataFormatTypeCode == "C*8")
67+
assert(record.NumberOfRightFillBitsWithinPixel == 0)
68+
assert(record.NumberOfBytesPerDataGroup % record.NumberOfSamplesPerDataGroup == 0)
69+
assert(record.NumberOfBytesOfSARDataPerRecord % (record.NumberOfBytesPerDataGroup//record.NumberOfSamplesPerDataGroup) == 0)
70+
71+
#Check length of record
72+
assert(self.fid.tell() == record.RecordLength)
73+
74+
#Return the validated record
75+
return record
76+
77+
def readNextLine(self):
78+
'''
79+
Read the next line from file.
80+
'''
81+
# from isce3.parsers.CEOS.SignalDataRecordType import SignalDataRecordType
82+
from isce3.stripmap.readers.l1.ALOS2.CEOS.SignalDataRecordType import SignalDataRecordType
83+
84+
#Create record type with information from description
85+
bytesperpixel = self.description.NumberOfBytesPerDataGroup // self.description.NumberOfSamplesPerDataGroup
86+
pixels = self.description.NumberOfBytesOfSARDataPerRecord // bytesperpixel
87+
record = SignalDataRecordType(pixels=pixels,
88+
bytesperpixel=bytesperpixel)
89+
90+
91+
#Read from file
92+
record.fromfile(self.fid)
93+
self.counter = self.counter + 1
94+
95+
#Sensor specific validators
96+
assert(record.RecordSequenceNumber == (self.counter+1))
97+
assert(record.FirstRecordType == 50)
98+
assert(record.RecordTypeCode == 10)
99+
assert(record.SecondRecordSubType == 18)
100+
assert(record.ThirdRecordSubType == 20)
101+
assert(record.ActualCountOfLeftFillPixels == 0)
102+
assert(record.SARChannelCode == 0)
103+
assert(record.ScanIDForScanSAR == 0)
104+
assert(record.OnboardRangeCompressedFlag == 0)
105+
assert(record.PulseTypeDesignator == 0)
106+
107+
return record
108+
109+

0 commit comments

Comments
 (0)