11#!/usr/bin/env python3
22# -*- coding: utf-8 -*-
33
4- import numpy as np
5- import os
64import glob
7- import datetime
5+ import os
6+ import sys
7+
8+ import numpy as np
89from osgeo import gdal
910
11+
1012def 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+
3649def 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
7289def 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