Skip to content

Commit 1f5d3b3

Browse files
authored
az time and slant corrections as functions of az time and slant range (#82)
* option to make az time and slant corrections functions of az time and slant range * change LUT axis units from pixels to meters and seconds
1 parent 4a6291a commit 1f5d3b3

File tree

1 file changed

+84
-50
lines changed

1 file changed

+84
-50
lines changed

src/s1reader/s1_burst_slc.py

Lines changed: 84 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,12 @@ class represents a polynomial function of range
7979
A = A / snr[:, None]
8080
z = z / snr
8181

82-
return_val = True
83-
val, res, _, eigs = np.linalg.lstsq(A, z, rcond=cond)
82+
val, res, _, _ = np.linalg.lstsq(A, z, rcond=cond)
8483
if len(res) > 0:
8584
print('Chi squared: %f' % (np.sqrt(res / (1.0 * len(z)))))
8685
else:
8786
print('No chi squared value....')
8887
print('Try reducing rank of polynomial.')
89-
return_val = False
9088

9189
coeffs = []
9290
count = 0
@@ -252,7 +250,7 @@ def slc_to_vrt_file(self, out_path):
252250
Path of output VRT file.
253251
'''
254252
if not self.tiff_path:
255-
warn_str = f'Unable write SLC to file. Burst does not contain image data; only metadata.'
253+
warn_str = 'Unable write SLC to file. Burst does not contain image data; only metadata.'
256254
warnings.warn(warn_str)
257255
return
258256

@@ -404,7 +402,42 @@ def as_dict(self):
404402
self_as_dict[key] = val
405403
return self_as_dict
406404

407-
def bistatic_delay(self, xstep=1, ystep=1):
405+
406+
def _steps_to_vecs(self, range_step, az_step):
407+
''' convert range_step (meters) and az_step (seconds) into aranges to
408+
generate LUT2ds
409+
'''
410+
step_errs = []
411+
if range_step <= 0:
412+
step_errs.append('range')
413+
if az_step <= 0:
414+
step_errs.append('azimuth')
415+
if step_errs:
416+
step_errs = ', '.join(step_errs)
417+
err_str = f'Following step size(s) <=0: {step_errs}'
418+
raise ValueError(err_str)
419+
420+
n_range = np.ceil(self.width * self.range_pixel_spacing / range_step).astype(int)
421+
range_vec = self.starting_range + np.arange(0, n_range) * range_step
422+
423+
n_az = np.ceil(self.length * self.azimuth_time_interval / az_step).astype(int)
424+
rdrgrid = self.as_isce3_radargrid()
425+
az_vec = rdrgrid.sensing_start + np.arange(0, n_az) * az_step
426+
427+
vec_errs = []
428+
if not range_vec:
429+
vec_errs.append('range')
430+
if not az_vec:
431+
vec_errs.append('azimuth')
432+
if vec_errs:
433+
vec_errs = ', '.join(vec_errs)
434+
err_str = f'Cannot build aranges from following step(s): {vec_errs}'
435+
raise ValueError(err_str)
436+
437+
return range_vec, az_vec
438+
439+
440+
def bistatic_delay(self, range_step=1, az_step=1):
408441
'''Computes the bistatic delay correction in azimuth direction
409442
due to the movement of the platform between pulse transmission and echo reception
410443
as described in equation (21) in Gisinger et al. (2021, TGRS).
@@ -421,30 +454,26 @@ def bistatic_delay(self, xstep=1, ystep=1):
421454
422455
Parameters
423456
-------
424-
xstep : int
425-
spacing along x direction (range direction) in units of pixels
426-
427-
ystep : int
428-
spacing along y direction (azimuth direction) in units of pixels
457+
range_step : int
458+
Spacing along x/range direction [meters]
459+
az_step : int
460+
Spacing along y/azimuth direction [seconds]
429461
430462
Returns
431463
-------
432464
LUT2D object of bistatic delay correction in seconds as a function
433-
of the range and zimuth indices. This correction needs to be added
434-
to the SLC tagged azimuth time to get the corrected azimuth times.
465+
of the azimuth time and slant range, or range and azimuth indices.
466+
This correction needs to be added to the SLC tagged azimuth time to
467+
get the corrected azimuth times.
435468
'''
436469

437470
pri = 1.0 / self.prf_raw_data
438471
tau0 = self.rank * pri
439472
tau_mid = self.iw2_mid_range * 2.0 / isce3.core.speed_of_light
440473

441-
nx = np.ceil(self.width / xstep).astype(int)
442-
ny = np.ceil(self.length / ystep).astype(int)
443-
x = np.arange(0, nx*xstep, xstep, dtype=int)
444-
y = np.arange(0, ny*ystep, ystep, dtype=int)
474+
slant_vec, az_vec = self._steps_to_vecs(range_step, az_step)
445475

446-
slant_range = self.starting_range + x * self.range_pixel_spacing
447-
tau = slant_range * 2.0 / isce3.core.speed_of_light
476+
tau = slant_vec * 2.0 / isce3.core.speed_of_light
448477

449478
# the first term (tau_mid/2) is the bulk bistatic delay which was
450479
# removed from the orginial azimuth time by the ESA IPF. Based on
@@ -454,11 +483,13 @@ def bistatic_delay(self, xstep=1, ystep=1):
454483
# This implementation follows the Gisinger et al. (2021) for now, we
455484
# can revise when we hear back from ESA folks.
456485
bistatic_correction_vec = tau_mid / 2 + tau / 2 - tau0
457-
bistatic_correction = np.tile(bistatic_correction_vec.reshape(1,-1), (ny,1))
486+
ny = az_vec.size
487+
bistatic_correction = np.tile(bistatic_correction_vec.reshape(1,-1),
488+
(ny,1))
458489

459-
return isce3.core.LUT2d(x, y, bistatic_correction)
490+
return isce3.core.LUT2d(slant_vec, az_vec, bistatic_correction)
460491

461-
def geometrical_and_steering_doppler(self, xstep=500, ystep=50):
492+
def geometrical_and_steering_doppler(self, range_step=500, az_step=50):
462493
"""
463494
Compute total Doppler which is the sum of two components:
464495
(1) the geometrical Doppler induced by the relative movement
@@ -468,61 +499,65 @@ def geometrical_and_steering_doppler(self, xstep=500, ystep=50):
468499
with azimuth time.
469500
Parameters
470501
----------
471-
xstep: int
472-
Spacing along x direction [pixels]
473-
ystep: int
474-
Spacing along y direction [pixels]
502+
range_step: int
503+
Spacing along x/range direction [meters]
504+
az_step: int
505+
Spacing along y/azimuth direction [seconds]
475506
476507
Returns
477508
-------
478-
x : int
479-
The index of samples in range direction as an 1D array
480-
y : int
481-
The index of samples in azimuth direction as an 1D array
482-
total_doppler : float
483-
Total Doppler which is the sum of the geometrical Doppler and
484-
beam steering induced Doppler [Hz] as a 2D array
509+
LUT2D object of total doppler in Hz as a function of the azimuth
510+
time and slant range, or range and azimuth indices.
511+
This correction needs to be added to the SLC tagged azimuth time to
512+
get the corrected azimuth times.
485513
"""
514+
range_vec, az_vec = self._steps_to_vecs(range_step, az_step)
486515

487-
x = np.arange(0, self.width, xstep, dtype=int)
488-
y = np.arange(0, self.length, ystep, dtype=int)
489-
x_mesh, y_mesh = np.meshgrid(x, y)
516+
# convert from meters to pixels
517+
x_vec = (range_vec - self.starting_range) / self.range_pixel_spacing
518+
519+
# convert from seconds to pixels
520+
rdrgrid = self.as_isce3_radargrid()
521+
y_vec = (az_vec - rdrgrid.sensing_start) / self.azimuth_time_interval
522+
523+
# compute az carrier components with pixels
524+
x_mesh, y_mesh = np.meshgrid(x_vec, y_vec)
490525
az_carr_comp = self.az_carrier_components(
491526
offset=0.0,
492527
position=(y_mesh, x_mesh))
493528

494-
slant_range = self.starting_range + x * self.range_pixel_spacing
495-
geometrical_doppler = self.doppler.poly1d.eval(slant_range)
529+
geometrical_doppler = self.doppler.poly1d.eval(range_vec)
496530

497531
total_doppler = az_carr_comp.antenna_steering_doppler + geometrical_doppler
498532

499-
return x, y, total_doppler
533+
return isce3.core.LUT2d(range_vec, az_vec, total_doppler)
500534

501-
def doppler_induced_range_shift(self, xstep=500, ystep=50):
535+
def doppler_induced_range_shift(self, range_step=500, az_step=50):
502536
"""
503537
Computes the range delay caused by the Doppler shift as described
504538
by Gisinger et al 2021
505539
506540
Parameters
507541
----------
508-
xstep: int
509-
Spacing along x direction [pixels]
510-
ystep: int
511-
Spacing along y direction [pixels]
542+
range_step: int
543+
Spacing along x/range direction [meters]
544+
az_step: int
545+
Spacing along y/azimuth direction [seconds]
512546
513547
Returns
514548
-------
515549
isce3.core.LUT2d:
516550
LUT2D object of range delay correction [seconds] as a function
517-
of the x and y indices.
551+
of the azimuth time and slant range, or x and y indices.
518552
519553
"""
554+
range_vec, az_vec = self._steps_to_vecs(range_step, az_step)
520555

521-
x, y, doppler_shift = self.geometrical_and_steering_doppler(
522-
xstep=xstep, ystep=ystep)
523-
tau_corr = doppler_shift / self.range_chirp_rate
556+
doppler_shift = self.geometrical_and_steering_doppler(range_step=range_step,
557+
az_step=az_step)
558+
tau_corr = doppler_shift.data / self.range_chirp_rate
524559

525-
return isce3.core.LUT2d(x, y, tau_corr)
560+
return isce3.core.LUT2d(range_vec, az_vec, tau_corr)
526561

527562
def az_carrier_components(self, offset, position):
528563
'''
@@ -534,7 +569,7 @@ def az_carrier_components(self, offset, position):
534569
offset: float
535570
Offset between reference and secondary burst
536571
position: tuple
537-
Tuple of locations along y and x directions
572+
Tuple of locations along y and x directions in pixels
538573
539574
Returns
540575
-------
@@ -576,7 +611,6 @@ def az_carrier_components(self, offset, position):
576611
self.starting_range)) - (f_etac / ka)
577612
kt = ks / (1.0 - ks / ka)
578613

579-
580614
return AzimuthCarrierComponents(kt, eta, eta_ref)
581615

582616

0 commit comments

Comments
 (0)