Horizontal Patterns after Applying Boxcar Filter in Sentinel-1 SLC products

Hi all,

I am experiencing an issue when preprocessing Sentinel-1 SLC products for interferometric coherence estimation. My current processing workflow is as follows:

  1. S-1 TOPS Split
  2. Apply Orbit File
  3. Calibration to complex numbers
  4. S-1 Back Geocoding
  5. S-1 TOPS Deburst
  6. Multilooking (4:1 ratio)

Before estimating coherence, I intended to apply a Boxcar filter (3x3 window size) for additional smoothing. I tried applying the filter using:

  • The Filter Band option (from Raster menu in SNAP)
  • A Python script (code attached below)
import os
import sys
import numpy as np
import scipy.ndimage
sys.path.append(r'C:\Users\user\.snap\snap-python\esa_snappy')

from esa_snappy import ProductIO, ProductUtils, ProductData, Product, HashMap, GPF

dirfiles = r'...\SLCimgs'
kernel_size = (3,3)
# Load the Sentinel-1 product
file = 'S1B_IW_SLC__1SDV_20170529_split_Orb_Cal_Stack_Deb_ML.dim'
rimg = os.path.join(dirfiles,file)
product = ProductIO.readProduct(rimg)

# Get image dimensions
width = product.getSceneRasterWidth()
height = product.getSceneRasterHeight()

#Initialize the filtered product
filtered_product = Product('Filtered_Product', 'Filtered_Type', width, height)

# Copy metadata from original product
ProductUtils.copyMetadata(product, filtered_product)
ProductUtils.copyVectorData(product, filtered_product)
ProductUtils.copyTiePointGrids(product, filtered_product)
ProductUtils.copyGeoCoding(product, filtered_product)

# Define a 3x3 Boxcar filter (uniform weights)
boxcar_kernel = np.ones((kernel_size[1], kernel_size[0]), dtype=np.float32) / (kernel_size[0] * kernel_size[1])

# Attach a product writer
output_path = os.path.join(dirfiles,file.replace('.dim',f'_spkl{kernel_size[0]}x{kernel_size[1]}.dim'))
data_format = 'BEAM-DIMAP'
writer = ProductIO.getProductWriter(data_format)
filtered_product.setProductWriter(writer)

# Select the band to filter
for band_name in list(product.getBandNames()):
    if 'Intensity' in band_name: continue
    print(band_name)
    band = product.getBand(band_name)
    print('Creating new band...')
    # Create a new band
    filtered_band = filtered_product.addBand(band_name, band.getDataType()) #Importante mantener el nombre

    #copy important data
    filtered_band.setNoDataValueUsed(band.isNoDataValueUsed())
    filtered_band.setNoDataValue(band.getNoDataValue())
    filtered_band.setUnit(band.getUnit())
    filtered_band.setDescription(band.getDescription())

    # Read band data into a NumPy array
    band_data = np.zeros((height, width), dtype=np.float32)
    band.readPixels(0, 0, width, height, band_data)

    print('Applying filter...')
    # Apply the filter using 2D convolution
    filtered_data = scipy.ndimage.convolve(band_data, boxcar_kernel, mode='nearest')
    
    
    # filtered_band.setModified(True)
    print('Writing pixels...\n')
    # '''
    # Convert NumPy array to SNAP-compatible raster data buffer
    filtered_band_data = np.ravel(filtered_data)  # Flatten array
    filtered_band.setRasterData(ProductData.createInstance(filtered_band_data))
    # '''
# del filtered_band,  filtered_band_data, band_data

# Save the new product
ProductIO.writeProduct(filtered_product, output_path, data_format)
print(f"Filtered product saved at: {output_path}")

The issue arises after applying the filter—I observe horizontal patterns in the output. I checked the original images and noticed a slight horizontal pattern when zooming into specific locations (these horizontal patterns appear in the phase images but not in the amplitude images). However, when I skip the Boxcar filter, no such patterns appear in the final coherence result.

Has anyone encountered a similar issue? Any insights or recommendations would be greatly appreciated!

Thank you!

PS: I have also noticed that these patterns appear even when I do not apply multilooking and when using an irregular window size Boxcar filter.