Skip to content

range_split_spectrum

find_next_power(number)

Finds the next power of 2 of 'number'

Parameters:

Name Type Description Default
number

Number for which to find next power of two

required

Returns:

Name Type Description
power int

Next power of 2 of 'number'

Source code in src/compass/utils/range_split_spectrum.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def find_next_power(number):
    '''
    Finds the next power of 2 of 'number'

    Parameters
    ----------
    number: int
        Number for which to find next power of two

    Returns
    -------
    power: int
        Next power of 2 of 'number'
    '''
    power = 1
    if (number and not (number & (number - 1))):
        return number

    while (power < number):
        power <<= 1
    return number

range_split_spectrum(burst, burst_path, cfg_split_spectrum, scratch_path)

Split burst range spectrum

Parameters:

Name Type Description Default
burst

S1-A/B burst object

required
burst_path

Path to the burst SLC to apply split spectrum

required
cfg_split_spectrum

Dictionary with split-spectrum options

required
scratch_path

Directory for storing temp files

required

Returns:

Name Type Description
burst_raster Raster

3-bands ISCE3 Raster. Band #1: low band; Band #2: main band; Band #3: high band

Source code in src/compass/utils/range_split_spectrum.py
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
def range_split_spectrum(burst,
                         burst_path,
                         cfg_split_spectrum,
                         scratch_path):
    '''
    Split burst range spectrum
    Parameters
    ----------
    burst: Sentinel1BurstSlc
        S1-A/B burst object
    burst_path: str
        Path to the burst SLC to apply split spectrum
    cfg_split_spectrum: dict
        Dictionary with split-spectrum options
    scratch_path: str
        Directory for storing temp files

    Returns
    -------
    burst_raster: isce3.io.Raster
        3-bands ISCE3 Raster. Band #1: low band;
        Band #2: main band; Band #3: high band
    '''
    length, width = burst.shape
    lines_per_block = cfg_split_spectrum.lines_per_block
    burst_id_pol = f'{str(burst.burst_id)}_{burst.polarization}'

    # In ISCE3, we can use raised cosine to implement S1-A/B Hamming
    window_type = burst.range_window_type
    window_type = 'Cosine' if window_type.casefold() == 'hamming' else window_type
    window_shape = 2 * burst.range_window_coefficient - 1.0 if \
    window_type.casefold() == 'hamming' else burst.range_window_coefficient

    # Extract bandwidths (bw) and create frequency vectors
    half_bw = 0.5 * burst.range_bandwidth
    low_bw = cfg_split_spectrum.low_band_bandwidth
    high_bw = cfg_split_spectrum.high_band_bandwidth

    low_freq_burst = burst.radar_center_frequency - half_bw
    high_freq_burst = burst.radar_center_frequency + half_bw

    low_band_freqs = np.array([low_freq_burst, low_freq_burst + low_bw])
    high_band_freqs = np.array([high_freq_burst - high_bw, high_freq_burst])
    low_center_freq = low_freq_burst + low_bw / 2
    high_center_freq = high_freq_burst - high_bw / 2

    # Initialize the split-spectrum parameter object. Note, constructor
    # requires frequency (A/B) but this is not used anywhere below
    rdr_grid = burst.as_isce3_radargrid()
    split_spectrum_obj = splitspectrum.SplitSpectrum(
        rg_sample_freq=burst.range_sampling_rate,
        rg_bandwidth=burst.range_bandwidth,
        center_frequency=burst.radar_center_frequency,
        slant_range=rdr_grid.slant_range,
        freq='A')


    # The output burst will
    # contain 3 bands: Band #1: low-band image; Band #2 main-band image;
    # Band #3: high-band image.
    in_ds = gdal.Open(burst_path, gdal.GA_ReadOnly)
    driver = gdal.GetDriverByName('GTiff')
    out_ds = driver.Create(f'{scratch_path}/{burst_id_pol}_low_main_high.slc.tif',
                           width, length, 3, gdal.GDT_CFloat32)

    # Prepare necessary variables for block processing
    lines_per_block = min(length, lines_per_block)
    num_blocks = int(np.ceil(length / lines_per_block))

    for block in range(num_blocks):
        line_start = block * lines_per_block
        if block == num_blocks - 1:
            block_length = length - line_start
        else:
            block_length = lines_per_block

        # Read a block of valid burst data
        burst_data = in_ds.GetRasterBand(1).ReadAsArray(0, line_start,
                                                        width, block_length)
        # Get the low band sub-image and corresponding metadata
        burst_low_data, _ = split_spectrum_obj.bandpass_shift_spectrum(
            slc_raster=burst_data, low_frequency=low_band_freqs[0],
            high_frequency=low_band_freqs[1],
            new_center_frequency=low_center_freq,
            fft_size=find_next_power(width), window_shape=window_shape,
            window_function=window_type, resampling=False
        )
        # Get the high sub-image and corresponding metadata
        burst_high_data, _ = split_spectrum_obj.bandpass_shift_spectrum(
            slc_raster=burst_data, low_frequency=high_band_freqs[0],
            high_frequency=high_band_freqs[1],
            new_center_frequency=high_center_freq,
            fft_size=find_next_power(width), window_shape=window_shape,
            window_function=window_type, resampling=False
        )
        # Write back all the processed data
        out_ds.GetRasterBand(1).WriteArray(burst_low_data[0:block_length],
                                           yoff=line_start)
        out_ds.GetRasterBand(2).WriteArray(burst_data[0:block_length],
                                           yoff=line_start)
        out_ds.GetRasterBand(3).WriteArray(burst_high_data[0:block_length],
                                           yoff=line_start)

    out_ds.FlushCache()
    out_ds = None
    burst_raster = isce3.io.Raster(
        f'{scratch_path}/{burst_id_pol}_low_main_high.slc')

    return burst_raster