Skip to content

Commit 439c1ee

Browse files
authored
Merge pull request #47 from vbrancat/fix_tops2vrt
Fix tops2vrt script
2 parents 2f50d5e + 02e13d5 commit 439c1ee

File tree

1 file changed

+107
-131
lines changed

1 file changed

+107
-131
lines changed

python/tops2vrt.py

Lines changed: 107 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33

4-
import numpy as np
5-
import os
64
import glob
7-
import datetime
5+
import os
6+
import sys
7+
8+
import numpy as np
89
from osgeo import gdal
910

11+
1012
def cmdLineParse():
1113
'''
1214
Command line parser.
@@ -15,53 +17,68 @@ def cmdLineParse():
1517

1618
parser = argparse.ArgumentParser(description='Tops SLC stack to VRT')
1719
parser.add_argument('-i', '--input', dest='indir', type=str,
18-
required=True, help='Merged directory of tops stack generation')
20+
required=True,
21+
help='Merged directory from ISCE2 Sentinel stack processor')
22+
parser.add_argument('-S', '--slc_dir', dest='slc_dir', type=str,
23+
default='SLC',
24+
help='Name of the directory containing stack of SLCs (default: "SLC")')
25+
parser.add_argument('-e', '--extension', dest='ext', type=str,
26+
default='slc.full.vrt',
27+
help='File extension of co-registered SLC files (default: "slc.full.vrt")')
28+
parser.add_argument('-w', '--wavelength', dest='wavelength', type=float,
29+
default=0.05546576,
30+
help='Radar wavelenght for SLC stack (default: "0.05546576")')
1931
parser.add_argument('-s', '--stack', dest='stackdir', type=str,
20-
default='stack', help='Directory where the vrt stack will be stored (default is "stack")')
32+
default='stack',
33+
help='Directory where the co-registered SLC stack VRT will be stored (default: "stack")')
2134
parser.add_argument('-g', '--geom', dest='geomdir', type=str,
22-
default='geometry', help='Directory where the geometry vrts will be stored (default is "geometry")')
23-
parser.add_argument('-c', '--slcs', dest='outdir', type=str,
24-
default='slcs', help='Directory where the individual slc vrts will be stored (default is "slcs")')
25-
26-
parser.add_argument('-b', '--bbox', dest='bbox', nargs=4, type=int, default=None, metavar=('Y0','Y1','X0','X1'),
27-
help='bounding box in row col: minLine maxLine minPixel maxPixel')
28-
29-
parser.add_argument('-B', '--geo_bbox', dest='geobbox', nargs=4, type=float, default=None, metavar=('S', 'N', 'W', 'E'),
30-
help='bounding box in lat lon: South North West East')
35+
default='geometry',
36+
help='Directory where the geometry VRTs will be stored (default: "geometry")')
37+
parser.add_argument('-b', '--bbox', dest='bbox', nargs=4, type=int,
38+
default=None, metavar=('Y0', 'Y1', 'X0', 'X1'),
39+
help='bounding box in row col: minLine maxLine minPixel maxPixel')
40+
parser.add_argument('-B', '--geo_bbox', dest='geobbox', nargs=4, type=float,
41+
default=None, metavar=('S', 'N', 'W', 'E'),
42+
help='bounding box in lat lon: South North West East')
3143

3244
inps = parser.parse_args()
3345

3446
return inps
3547

48+
3649
def radarGeometryTransformer(latfile, lonfile, epsg=4326):
3750
'''
3851
Create a coordinate transformer to convert map coordinates to radar image line/pixels.
3952
'''
40-
53+
4154
driver = gdal.GetDriverByName('VRT')
4255
inds = gdal.OpenShared(latfile, gdal.GA_ReadOnly)
4356
tempds = driver.Create('', inds.RasterXSize, inds.RasterYSize, 0)
4457
inds = None
45-
46-
tempds.SetMetadata({'SRS' : 'EPSG:{0}'.format(epsg),
58+
59+
tempds.SetMetadata({'SRS': 'EPSG:{0}'.format(epsg),
4760
'X_DATASET': lonfile,
48-
'X_BAND' : '1',
61+
'X_BAND': '1',
4962
'Y_DATASET': latfile,
50-
'Y_BAND' : '1',
51-
'PIXEL_OFFSET' : '0',
52-
'LINE_OFFSET' : '0',
53-
'PIXEL_STEP' : '1',
54-
'LINE_STEP' : '1'}, 'GEOLOCATION')
55-
56-
trans = gdal.Transformer( tempds, None, ['METHOD=GEOLOC_ARRAY'])
57-
58-
return trans
63+
'Y_BAND': '1',
64+
'PIXEL_OFFSET': '0',
65+
'LINE_OFFSET': '0',
66+
'PIXEL_STEP': '1',
67+
'LINE_STEP': '1'}, 'GEOLOCATION')
68+
69+
trans = gdal.Transformer(tempds, None, ['METHOD=GEOLOC_ARRAY'])
70+
71+
return trans
5972

60-
def lonlat2pixeline(lonFile, latFile, lon, lat):
6173

74+
def lonlat2pixeline(lonFile, latFile, lon, lat):
75+
'''
76+
Check if the pixel with lat, lon coordinates is
77+
within the processed SLC area
78+
'''
6279
trans = radarGeometryTransformer(latFile, lonFile)
6380

64-
###Checkour our location of interest
81+
# Check out our location of interest
6582
success, location = trans.TransformPoint(1, lon, lat, 0.)
6683
if not success:
6784
print('Location outside the geolocation array range')
@@ -70,17 +87,19 @@ def lonlat2pixeline(lonFile, latFile, lon, lat):
7087

7188

7289
def getLinePixelBbox(geobbox, latFile, lonFile):
73-
74-
south,north, west, east = geobbox
90+
'''
91+
Convert lat/lon box to an area in the SLCs image
92+
'''
93+
south, north, west, east = geobbox
7594

7695
se = lonlat2pixeline(lonFile, latFile, east, south)
7796
nw = lonlat2pixeline(lonFile, latFile, west, north)
7897

79-
ymin = np.int(np.round(np.min([se[1], nw[1]])))
80-
ymax = np.int(np.round(np.max([se[1], nw[1]])))
98+
ymin = int(np.round(np.min([se[1], nw[1]])))
99+
ymax = int(np.round(np.max([se[1], nw[1]])))
81100

82-
xmin = np.int(np.round(np.min([se[0], nw[0]])))
83-
xmax = np.int(np.round(np.max([se[0], nw[0]])))
101+
xmin = int(np.round(np.min([se[0], nw[0]])))
102+
xmax = int(np.round(np.max([se[0], nw[0]])))
84103

85104
print("x min-max: ", xmin, xmax)
86105
print("y min-max: ", ymin, ymax)
@@ -92,115 +111,70 @@ def getLinePixelBbox(geobbox, latFile, lonFile):
92111
'''
93112
Main driver.
94113
'''
95-
96-
##Parse command line
114+
115+
# Parse command line
97116
inps = cmdLineParse()
98117

99-
###Get ann list and slc list
100-
slclist = glob.glob(os.path.join(inps.indir,'SLC','*','*.slc.full'))
118+
# Get a list of co-registered full SLC VRTs
119+
slclist = glob.glob(os.path.join(inps.indir, inps.slc_dir, '*', f'*{inps.ext}'))
101120
num_slc = len(slclist)
102121

103122
print('number of SLCs discovered: ', num_slc)
104-
print('we assume that the SLCs and the vrt files are sorted in the same order')
105-
106123
slclist.sort()
107124

108-
109-
###Read the first ann file to get some basic things like dimensions
110-
###Just walk through each of them and create a separate VRT first
111-
if not os.path.exists(inps.outdir):
112-
print('creating directory: {0}'.format(inps.outdir))
113-
os.makedirs(inps.outdir)
114-
else:
115-
print('directory "{0}" already exists.'.format(inps.outdir))
116-
117-
data = []
118-
dates = []
119-
120-
width = None
121-
height = None
122-
123-
print('write vrt file for each SLC ...')
124-
for ind, slc in enumerate(slclist):
125-
126-
###Parse the vrt file information.
127-
metadata = {}
128-
width = None
129-
height = None
130-
path = None
131-
132-
ds = gdal.Open(slc , gdal.GA_ReadOnly)
125+
# This is a stack of SLCs. All the co-registered SLCs will have
126+
# the same width and height. Just extract shape of first SLCs
127+
if num_slc != 0:
128+
ds = gdal.Open(slclist[0], gdal.GA_ReadOnly)
133129
width = ds.RasterXSize
134130
height = ds.RasterYSize
135131
ds = None
132+
else:
133+
# Exit program if no SLC VRT has been found
134+
sys.exit('No SLC discovered. Stop and return')
136135

137-
metadata['WAVELENGTH'] = 0.05546576
138-
metadata['ACQUISITION_TIME'] = os.path.basename(os.path.dirname(slc))
139-
140-
path = os.path.abspath(slc)
141-
142-
tag = metadata['ACQUISITION_TIME']
143-
144-
vrttmpl='''<VRTDataset rasterXSize="{width}" rasterYSize="{height}">
145-
<VRTRasterBand dataType="CFloat32" band="1" subClass="VRTRawRasterBand">
146-
<sourceFilename>{PATH}</sourceFilename>
147-
<ImageOffset>0</ImageOffset>
148-
<PixelOffset>8</PixelOffset>
149-
<LineOffset>{linewidth}</LineOffset>
150-
<ByteOrder>LSB</ByteOrder>
151-
</VRTRasterBand>
152-
</VRTDataset>'''
153-
154-
155-
# outname = datetime.datetime.strptime(tag.upper(), '%d-%b-%Y %H:%M:%S UTC').strftime('%Y%m%d')
156-
157-
outname = metadata['ACQUISITION_TIME']
158-
out_file = os.path.join(inps.outdir, '{0}.vrt'.format(outname))
159-
print('{} / {}: {}'.format(ind+1, num_slc, out_file))
160-
with open(out_file, 'w') as fid:
161-
fid.write( vrttmpl.format(width=width,
162-
height=height,
163-
PATH=path,
164-
linewidth=8*width))
165-
166-
data.append(metadata)
167-
dates.append(outname)
168-
169-
170-
####Set up single stack file
171-
if os.path.exists( inps.stackdir):
136+
# Creating stack directory
137+
if os.path.exists(inps.stackdir):
172138
print('stack directory: {0} already exists'.format(inps.stackdir))
173139
else:
174140
print('creating stack directory: {0}'.format(inps.stackdir))
175-
os.makedirs(inps.stackdir)
141+
os.makedirs(inps.stackdir)
176142

143+
# Open full-res lat/lon arrays in radar geometry
177144
latFile = os.path.join(inps.indir, "geom_reference", "lat.rdr.full.vrt")
178145
lonFile = os.path.join(inps.indir, "geom_reference", "lon.rdr.full.vrt")
179146

180-
# setting up a subset of the stack
147+
# Identify a subset area in the stack of co-registered SLCs
181148
if inps.geobbox:
182149
# if the bounding box in geo-coordinate is given, this has priority
183-
print("finding bbox based on geo coordinates of {} ...".format(inps.geobbox))
184-
ymin, ymax, xmin, xmax = getLinePixelBbox(inps.geobbox, latFile, lonFile)
185-
150+
print("finding bbox based on geo coordinates of {} ...".format(
151+
inps.geobbox))
152+
ymin, ymax, xmin, xmax = getLinePixelBbox(inps.geobbox, latFile,
153+
lonFile)
186154
elif inps.bbox:
187155
# if bbox in geo not given then look for line-pixel bbox
188156
print("using the input bbox based on line and pixel subset")
189157
ymin, ymax, xmin, xmax = inps.bbox
190-
191158
else:
192159
# if no bbox provided, the take the full size
193-
ymin, ymax, xmin, xmax = [0 , height, 0 , width]
160+
ymin, ymax, xmin, xmax = [0, height, 0, width]
194161

195162
xsize = xmax - xmin
196163
ysize = ymax - ymin
197164

165+
# Set-up filepath for VRT containing co-registered stack of SLCs
198166
slcs_base_file = os.path.join(inps.stackdir, 'slcs_base.vrt')
199167
print('write vrt file for stack directory')
168+
200169
with open(slcs_base_file, 'w') as fid:
201-
fid.write( '<VRTDataset rasterXSize="{xsize}" rasterYSize="{ysize}">\n'.format(xsize=xsize, ysize=ysize))
170+
fid.write(
171+
'<VRTDataset rasterXSize="{xsize}" rasterYSize="{ysize}">\n'.format(
172+
xsize=xsize, ysize=ysize))
173+
174+
for ind, slc in enumerate(slclist):
175+
# Extract date from co-registered SLCs
176+
date = os.path.basename(os.path.dirname(slc))
202177

203-
for ind, (date, meta) in enumerate( zip(dates, data)):
204178
outstr = ''' <VRTRasterBand dataType="CFloat32" band="{index}">
205179
<SimpleSource>
206180
<SourceFilename>{path}</SourceFilename>
@@ -215,25 +189,24 @@ def getLinePixelBbox(geobbox, latFile, lonFile):
215189
<MDI key="AcquisitionTime">{acq}</MDI>
216190
</Metadata>
217191
</VRTRasterBand>\n'''.format(width=width, height=height,
218-
xmin=xmin, ymin=ymin,
219-
xsize=xsize, ysize=ysize,
220-
date=date, acq=meta['ACQUISITION_TIME'],
221-
wvl = meta['WAVELENGTH'], index=ind+1,
222-
path = os.path.abspath( os.path.join(inps.outdir, date+'.vrt')))
192+
xmin=xmin, ymin=ymin,
193+
xsize=xsize, ysize=ysize,
194+
date=date, acq=date,
195+
wvl=inps.wavelength, index=ind + 1,
196+
path=slc)
223197
fid.write(outstr)
224198

225199
fid.write('</VRTDataset>')
226200

227-
####Set up latitude, longitude and height files
228-
229-
if os.path.exists( inps.geomdir):
201+
# Set-up latitude and longitude files
202+
203+
if os.path.exists(inps.geomdir):
230204
print('directory {0} already exists.'.format(inps.geomdir))
231205
else:
232206
print('creating geometry directory: {0}'.format(inps.geomdir))
233-
os.makedirs( inps.geomdir)
207+
os.makedirs(inps.geomdir)
234208

235-
236-
vrttmpl='''<VRTDataset rasterXSize="{xsize}" rasterYSize="{ysize}">
209+
vrttmpl = '''<VRTDataset rasterXSize="{xsize}" rasterYSize="{ysize}">
237210
<VRTRasterBand dataType="Float64" band="1">
238211
<SimpleSource>
239212
<SourceFilename>{PATH}</SourceFilename>
@@ -247,14 +220,17 @@ def getLinePixelBbox(geobbox, latFile, lonFile):
247220

248221
print('write vrt file for geometry dataset')
249222
layers = ['lat', 'lon', 'hgt']
250-
for ind, val in enumerate(layers):
251-
with open( os.path.join(inps.geomdir, val+'.vrt'), 'w') as fid:
252-
fid.write( vrttmpl.format( xsize = xsize, ysize = ysize,
253-
xmin = xmin, ymin = ymin,
254-
width = width,
255-
height = height,
256-
PATH = os.path.abspath( os.path.join(inps.indir, 'geom_reference', val+'.rdr.full.vrt')),
257-
linewidth = width * 8))
258-
259-
260223

224+
# Define pixel_offset variable (bytes)
225+
pixel_offset = 8
226+
for ind, val in enumerate(layers):
227+
with open(os.path.join(inps.geomdir, val + '.vrt'), 'w') as fid:
228+
fid.write(vrttmpl.format(xsize=xsize, ysize=ysize,
229+
xmin=xmin, ymin=ymin,
230+
width=width,
231+
height=height,
232+
PATH=os.path.abspath(
233+
os.path.join(inps.indir,
234+
'geom_reference',
235+
val + '.rdr.full.vrt')),
236+
linewidth=width * pixel_offset))

0 commit comments

Comments
 (0)