DEV Community

Rahim Ranxx
Rahim Ranxx

Posted on

From NISAR L-Band Data to a Farm Polygon: Building NISAR Into a Farm-Intelligence Platform

What it took to turn a NISAR GCOV observation into a farm-level L-band radar measurement.

I have been building a farm-intelligence platform that combines software engineering with Earth observation.

Recently, I wanted to take the platform one step further.

Instead of relying primarily on optical observations, I wanted it to process NISAR L-band SAR data and produce observations at the level that actually matters to the application:

the farm polygon.

That sounds straightforward.

It wasn't.

The interesting part wasn't simply downloading a NISAR product.

The challenge was taking a large scientific dataset, understanding how its geolocation worked, extracting a tiny agricultural area from it, applying the actual farm geometry, calculating an L-band vegetation metric, and making the resulting observation useful inside a production software system.

This is what that process looked like.


Why NISAR?

Optical satellite imagery is extremely useful for agriculture.

Vegetation indices such as EVI and NDVI can provide valuable information about vegetation condition.

But radar provides a different observation mechanism.

NISAR's L-band SAR operates at a longer wavelength than Sentinel-1's C-band system, making it particularly interesting for studying vegetation structure and other surface characteristics.

For my platform, that creates an opportunity.

Instead of asking a single sensor to tell me everything about a farm, I can begin treating Earth observation as a collection of complementary measurements.

Conceptually:

                FARM
                  │
        ┌─────────┴─────────┐
        │                   │
     Optical              Radar
        │                   │
   Vegetation            Structure
   reflectance           scattering
        │                   │
        └─────────┬─────────┘
                  │
          Farm Intelligence
Enter fullscreen mode Exit fullscreen mode

NISAR therefore isn't replacing the other observations in the platform.

It adds another physical perspective.


What I wanted the platform to do

My target workflow was simple:

NISAR
  ↓
STAC discovery
  ↓
ASF DAAC
  ↓
GCOV product
  ↓
HDF5 subdataset
  ↓
Geolocation
  ↓
Farm AOI
  ↓
Polygon masking
  ↓
L-band RVI
  ↓
Farm observation
Enter fullscreen mode Exit fullscreen mode

The important part is the last part.

I wasn't interested in simply displaying a NISAR scene.

I wanted the system to answer something closer to:

What does NISAR observe over this specific farm?

That means the farm's geometry has to remain part of the processing pipeline.


The first challenge: getting the NISAR asset into the processing pipeline

The NISAR products are distributed through NASA's data infrastructure, and I use STAC to discover the relevant assets.

The STAC catalog gives the application information about the available observation and the associated assets.

However, the asset URL wasn't immediately usable by the GDAL access path I was using.

The URL redirected to a signed CloudFront URL.

Rather than relying on the raster reader to transparently handle the entire redirect and signing process, I made the redirect resolution explicit.

Conceptually:

def _resolve_redirected_href(href: str) -> str:
    with httpx.stream(
        "GET",
        href,
        headers=_auth_headers(),
        follow_redirects=True,
        max_redirects=5,
        timeout=10.0,
    ) as response:
        return str(response.url)
Enter fullscreen mode Exit fullscreen mode

The important engineering lesson here wasn't that one particular service was “broken.”

It was that every boundary in a geospatial processing pipeline needs to be explicit.

In this case:

STAC
 ↓
HTTP
 ↓
Authentication
 ↓
Signed asset
 ↓
Raster reader
Enter fullscreen mode Exit fullscreen mode

Each layer has different assumptions.

Making the handoff explicit made the system easier to debug.


The second challenge: NISAR wasn't presenting geolocation like a normal GeoTIFF

This was probably the most interesting part of the investigation.

When opening the relevant HDF5 subdataset, I didn't get the conventional geospatial metadata I expected from a GeoTIFF.

For example:

src.crs is None
Enter fullscreen mode Exit fullscreen mode

At first glance, that looks like a problem.

But it doesn't necessarily mean that the dataset has no geolocation.

It means the geolocation isn't exposed through the interface I was expecting.

The product contained coordinate information in dedicated coordinate arrays, including X and Y coordinates, while projection information was available through the product metadata.

That changed the question.

Instead of asking:

Why doesn't this raster have a CRS?

I needed to ask:

Where does this product store its geolocation information?

That distinction is important when working with scientific data products.

Not every Earth-observation dataset behaves like a conventional GeoTIFF.


Reconstructing the spatial relationship

Once the coordinate arrays were available, I could derive the relationship between raster indices and projected coordinates.

The basic idea was to construct an affine representation from the coordinate spacing and then transform the farm's geographic bounding box into the product's projected coordinate system.

Conceptually:

Farm geometry
     ↓
Farm bounding box
     ↓
EPSG:4326
     ↓
Product projection
     ↓
Source pixel coordinates
     ↓
Raster window
Enter fullscreen mode Exit fullscreen mode

A simplified version of the calculation looked like:

x_vals, y_vals = _coordinate_axes(src, sub_path)

dx = (x_vals[-1] - x_vals[0]) / (x_vals.size - 1)
dy = (y_vals[-1] - y_vals[0]) / (y_vals.size - 1)

affine = Affine(
    dx,
    0.0,
    x_vals[0] - dx / 2,
    0.0,
    -dy,
    y_vals[0] - dy / 2,
)
Enter fullscreen mode Exit fullscreen mode

Then the farm bounding box could be transformed into the product's coordinate system.

The exact implementation contains additional boundary handling and validation, but the principle is straightforward:

Use the product's own geolocation information to determine which source pixels correspond to the farm.


The third challenge: the satellite swath was enormous

This was where the performance problem became obvious.

The source grid was approximately:

33,552 × 32,760 pixels
Enter fullscreen mode Exit fullscreen mode

My farm, however, was a tiny agricultural plot.

Reading an entire NISAR swath simply to calculate statistics for a fraction of a hectare is not a sensible production strategy.

The initial approach effectively looked like:

Read entire scene
       ↓
Find farm
       ↓
Mask farm
       ↓
Calculate statistics
Enter fullscreen mode Exit fullscreen mode

I changed the strategy to:

Find farm
       ↓
Transform farm bounds
       ↓
Calculate source window
       ↓
Read only required pixels
       ↓
Apply polygon mask
       ↓
Calculate statistics
Enter fullscreen mode Exit fullscreen mode

This is a small architectural change with a large practical effect.


From full-swath processing to AOI processing

For one of the NISAR scenes I was testing, the difference was substantial.

Measurement Before After
Source read Full swath AOI window
Source dimensions ~33,552 × 32,760 ~15 × 27 pixels in the tested window
Processing time 20+ minutes ~86 seconds
Spatial processing Large source grid Farm-specific window
Farm geometry Not sufficiently reflected in statistics semantics Explicitly applied

The important result wasn't simply:

20 minutes → 86 seconds.

The bigger improvement was that the processing model became much more closely aligned with the question being asked.

I wasn't processing an entire satellite scene when the application only needed a small agricultural area.


Another lesson: HDF5 datasets require careful subdataset selection

NISAR GCOV products contain multiple datasets and metadata structures.

Some calibration-related datasets can have names that resemble the polarization identifiers being requested.

For example, the product can contain datasets associated with:

HH
HV
Enter fullscreen mode Exit fullscreen mode

A naive exact-name lookup can therefore select an unintended dataset.

The solution was to make the matcher aware of the product structure rather than simply searching for the first exact string match.

For short polarization keys, the matching logic considers leaves ending with the requested key and prefers the appropriate shallow path.

This is one of those problems that doesn't appear in a simple example.

It appears when you start running real scientific products through an automated pipeline.

The lesson is broader:

Dataset names are part of a scientific data model, not merely strings to search for.


Turning the result into L-band RVI

After solving the data-access and spatial extraction problems, the next step was to calculate a farm-level L-band radar vegetation metric.

For the test scene, the resulting observations produced this ranking across three plots:

L-band RVI

Tea      1.06
Hass     1.00
Napier   0.96
Enter fullscreen mode Exit fullscreen mode

I also compared the ranking with optical EVI observations:

EVI

Tea      0.52
Hass     0.44
Napier   0.32
Enter fullscreen mode Exit fullscreen mode

The two measurements showed a broadly similar ordering in this particular test.

That was interesting.

But I don't consider that, by itself, scientific validation.

The sensors observe the surface through different physical mechanisms, and a similar ranking from three plots is not enough to establish a general relationship.

For now, I treat it as a consistency signal worth investigating further.

That distinction is important.

There is a difference between:

“The pipeline produced a result that is consistent with another observation.”

and:

“The pipeline has scientifically validated the result.”

The first is what I can currently claim.

The second requires a much larger validation exercise.


What NISAR adds to the platform

At this point, NISAR is no longer just an external dataset that I can download.

It is becoming another observation source inside the farm-intelligence architecture.

The platform can now work through a processing chain involving:

NISAR STAC discovery
        ↓
Asset resolution
        ↓
GCOV product access
        ↓
HDF5 subdataset identification
        ↓
Product geolocation
        ↓
AOI calculation
        ↓
Farm geometry masking
        ↓
L-band metric calculation
        ↓
Farm-level observation
Enter fullscreen mode Exit fullscreen mode

That is the capability I was actually trying to build.

Not a NISAR viewer.

Not a satellite-image downloader.

A system that can take a satellite observation and connect it to a specific piece of agricultural land.


Why farm geometry matters

This investigation also changed how I think about statistics in Earth-observation software.

A number such as:

sample_count = 12544
Enter fullscreen mode Exit fullscreen mode

doesn't tell you enough by itself.

You need to know:

  • What constitutes a sample?
  • Is it a native pixel?
  • Is it a resampled cell?
  • What spatial extent was used?
  • Was the farm polygon applied?
  • Were invalid pixels removed?
  • Was the statistic calculated at native resolution?
  • What transformations happened before the count?

These questions become especially important when dealing with very small farms.

A smallholder farm can occupy only a tiny portion of a satellite scene.

So the processing system has to preserve the distinction between:

the satellite product, the analysis grid, and the physical farm.

Those are three different things.


What I am not claiming

This is probably the most important section of the article.

I am not claiming that one NISAR observation can determine crop health.

I am not claiming that L-band RVI alone can estimate biomass or yield for a farm.

I am not claiming that agreement with EVI constitutes formal validation.

And I am not claiming that every observation produced by the pipeline is automatically scientifically correct.

The platform is an engineering system.

Its observations still require calibration, quality control, uncertainty analysis, and independent validation.

That's especially important when the eventual goal is to support agricultural decisions.


The next step: validating the measurements

The next stage is therefore not simply adding more indices.

It is validation.

For the NISAR workflow, that means investigating:

Satellite observation
        ↓
Processing
        ↓
Farm-level metric
        ↓
Independent observation
        ↓
In-situ measurement
        ↓
Validation
        ↓
Confidence
Enter fullscreen mode Exit fullscreen mode

I am particularly interested in validating the L-band soil-moisture workflow next.

There are currently small-AOI artifacts in that path that I don't consider trustworthy enough to use as scientific conclusions.

So they remain engineering issues until the underlying processing is understood and independently checked.


What building with NISAR taught me

The most valuable part of this project wasn't the final RVI number.

It was learning how much engineering exists between:

“I have a satellite product.”

and:

“I have a farm observation.”

The pipeline crosses multiple technical boundaries:

STAC
 ↓
HTTP
 ↓
Authentication
 ↓
HDF5
 ↓
Geolocation
 ↓
Coordinate transformation
 ↓
Raster windowing
 ↓
Polygon geometry
 ↓
Masking
 ↓
Radar metric
 ↓
Database
 ↓
Farm intelligence
Enter fullscreen mode Exit fullscreen mode

Every boundary introduces assumptions.

And every assumption needs to be tested.

That is probably the biggest lesson I have taken from integrating NISAR into the platform.


Where I want to take this

The long-term goal isn't to build a dashboard with as many satellite indices as possible.

It is to build a system where different observations can contribute evidence about the same piece of land.

NISAR can provide an L-band radar perspective.

Optical sensors can provide spectral information.

Weather data provides environmental context.

In-situ measurements provide an independent reference.

The platform's job is to bring those observations together without losing their meaning.

Eventually, the useful question becomes less:

“What is the satellite index today?”

and more:

“What evidence do we have about what is happening on this farm?”

That's the direction I am building toward.


Final thought

NISAR initially looked like another data source I needed to integrate.

It turned out to be a much better engineering exercise.

It forced me to understand how a scientific product stores its geolocation, how a massive radar swath can be reduced to a tiny agricultural AOI, how farm geometry should participate in the calculation, and how much care is required before turning a satellite measurement into a farm-level conclusion.

The interesting part isn't simply getting NISAR data into a Django application.

It's building the processing chain that allows a satellite observation to retain its physical meaning all the way down to a farm polygon.

And that is what I am continuing to work on.

Built and tested on real agricultural plots in Gatundu, Kenya.

Top comments (0)