## resolution_weighter.ResolutionWeighter


Compute LRW and per-pass composites for Sentinel-1 products.


Usage

``` python
resolution_weighter.ResolutionWeighter(
    file_manager, *, rasterio_profile=None, max_workers=8, checksum=False
)
```


Each compose call receives its target `geobox`, so one instance can be reused across MGRS grid cells.


## Parameters


`file_manager: FileManager`  
Used to resolve input file paths and output product paths.

`max_workers: int = ``8`  
Number of threads for parallel file I/O during product loading.

`rasterio_profile: dict[str, Any] | None = None`  
GeoTIFF profile applied to every product, or profiles keyed by product type with an optional `"default"` entry. Product-specific settings override the default. If omitted, uses the library defaults with float32 data and NaN no-data.

`checksum: bool = ``False`  
Compute a SHA-256 multihash of every written file's exact bytes and record it in `checksums`, keyed by output path. Costs holding the encoded COG in memory a second time per write.


## Attributes


`checksums: dict[str, str]`  
SHA-256 multihash of every file written so far, keyed by output path as a string. Populated only when `checksum=True`.


## References

1.  <span style="font-weight: 600; color: #6c757d;">\[1\]</span> Small, D., Rohner, C., Miranda, N., Ruetschi, M., & Schaepman, M. E. (2022). Wide-Area Analysis-Ready Radar Backscatter Composites. IEEE Transactions on Geoscience and Remote Sensing, 60, 5201814. [https://doi.org/10.1109/TGRS.2021.3055562](https://doi.org/10.1109/TGRS.2021.3055562)
2.  <span style="font-weight: 600; color: #6c757d;">\[2\]</span> CEOS-ARD Product Family Specification: Synthetic Aperture Radar, version 1.3.1 (2026). Committee on Earth Observation Satellites. [https://ceos.org/ard/files/PFS/SAR/v1.3.1/CEOS-ARD_PFS_SAR_v1.3.1.pdf](https://ceos.org/ard/files/PFS/SAR/v1.3.1/CEOS-ARD_PFS_SAR_v1.3.1.pdf)


## Methods

| Name | Description |
|----|----|
| [compose_coherence_by_pass()](#compose_coherence_by_pass) | Compute unweighted coherence composites stratified by pass direction. |
| [compose_coherence_lrw()](#compose_coherence_lrw) | Compute a locally resolution weighted (LRW) coherence composite. |
| [compose_gtc_by_pass()](#compose_gtc_by_pass) | Compute unweighted GTC beta0 composites stratified by pass direction. |
| [compose_rtc_by_pass()](#compose_rtc_by_pass) | Compute unweighted RTC composites stratified by pass direction. |
| [compose_rtc_lrw()](#compose_rtc_lrw) | Compute a locally resolution weighted (LRW) RTC intensity composite. |

------------------------------------------------------------------------


#### compose_coherence_by_pass()


Compute unweighted coherence composites stratified by pass direction.


Usage

``` python
compose_coherence_by_pass(
    coh_products,
    geobox,
    *,
    aggregation="mean",
    write_qa=False,
    overwrite=False,
    time_range=None,
    burst_edge_trim=True
)
```


Bursts from the same orbit and primary acquisition date are mosaicked without the darkened edge of each burst, splitting each overlap at its midline. The resulting orbit-date observations are then aggregated temporally (mean or median) per pass direction (ascending / descending).


##### Parameters


`coh_products: Collection[CoherenceProduct]`  
Coherence products to composite. All must share the same [baseline_days](burst.BurstPair.md#s1bursts.burst.BurstPair.baseline_days).

`geobox: MGRSGeoBox`  
Target MGRS grid cell.

`aggregation: Literal[``"mean", `<span class="st">`"median"``] | float`</span>` = ``"mean"`  
Temporal aggregation method. Pass `"mean"` or `"median"` for the corresponding statistic, or a float in `(0, 1)` for an interpolated quantile at that level.

`write_qa: bool = ``False`  
If `True`, also write the contributing-observations QA layer ([Layer.QA_NUM](product.Layer.md#s1bursts.product.Layer.QA_NUM)) of each pass direction.

`overwrite: bool = ``False`  
If `False` and every requested layer's file already exists, skip computation and return the existing product, after checking that each file records the requested grid and compositing parameters and linear units; any other difference, such as the DEM of the inputs, is not checked. Otherwise every requested layer is written, replacing an existing file, so the measurement and its QA layers always come from the same run. A direction that no input reaches has the files of an earlier composite of the same identity deleted; with `overwrite=False` they are left alone.

`time_range: TimeRange | None = None`  
The compositing window, as calendar days; pass the same `~s1bursts.time_range.TimeRange` the search was made with. When given, the product is named and tagged with its days rather than with the first and last acquisition, so every tile composited from one search shares them; the observed span is kept in the `FIRST_ACQUISITION_DATE` and `LAST_ACQUISITION_DATE` tags. An input outside the window is a `ValueError`.

`burst_edge_trim: bool = ``True`  
Drop the edge of each burst before mosaicking, where the coherence window has darkened it. Its width follows the inputs' estimation window and the grid spacing: 5 pixels at the default window on a 10 m grid. `False` keeps every pixel.


##### Returns


`dict[PassDirection, CohPassComposite]`  
One composite per pass direction among the inputs, whose `layers` are the measurement and, with `write_qa=True`, the QA layer. A direction whose inputs have no valid pixel in `geobox` is left out and gets no file, as if it had no inputs.


##### Raises


`TypeError`  
If `time_range` is not a [TimeRange](time_range.TimeRange.md#s1bursts.time_range.TimeRange).

`ValueError`  
If `coh_products` is empty, `aggregation` is neither `"mean"`, `"median"` nor a quantile level in `(0, 1)`, an input lies outside `time_range`, or `burst_edge_trim` is `True` and the coherence inputs, or with `overwrite=False` the existing composite, do not record the estimation window.

`EmptyCompositeError`  
If no input of any direction has a valid pixel in `geobox`; nothing is written.

`InconsistentInputsError`  
If the inputs differ in polarization or temporal baseline, an input is on another CRS, pixel size or grid than `geobox`, or the inputs were made with different DEMs, processing settings or SNAP versions, where an undetermined SNAP version matches any. When a direction is built, the composite of a direction skipped as existing must agree with its inputs too. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells given these inputs would meet it too.

`CompositeInputError`  
If an input product is missing or cannot be read.

`ProductSettingsMismatchError`  
If `overwrite` is `False` and an existing layer file records another grid than `geobox`, other or no compositing parameters, or values in decibels. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells would meet it too.

`OSError or RasterioError`  
If `overwrite` is `False` and an existing layer file cannot be read to check its settings.


------------------------------------------------------------------------


#### compose_coherence_lrw()


Compute a locally resolution weighted (LRW) coherence composite.


Usage

``` python
compose_coherence_lrw(
    coh_products,
    rtc_products,
    geobox,
    *,
    aggregation="mean",
    clip_max_resolution=None,
    write_qa=False,
    overwrite=False,
    time_range=None,
    burst_edge_trim=True
)
```


Coherence observations are weighted by normalized 1/A (\[1\] eq. 3-4) from matching RTC products. The bursts of one relative orbit and primary acquisition date are mosaicked without the darkened edge of each burst, splitting each overlap at its midline, and each pixel is weighted by the RTC product of its own burst.


##### Parameters


`coh_products: Collection[CoherenceProduct]`  
Coherence products to composite. All must share the same polarization and [baseline_days](burst.BurstPair.md#s1bursts.burst.BurstPair.baseline_days).

`rtc_products: Collection[RTCProduct]`  
RTC products providing the local scattering area (band 2) used as weights. Each coherence burst needs the RTC product of the same burst and primary date.

`geobox: MGRSGeoBox`  
Target MGRS grid cell.

`aggregation: Literal[``"mean", `<span class="st">`"median"``] | float`</span>` = ``"mean"`  
Temporal aggregation applied after weighting. Pass `"mean"` or `"median"` for the corresponding statistic, or a float in `(0, 1)` to compute a weighted quantile at that level.

`clip_max_resolution: float | None = None`  
Upper limit for W = 1/A, used to suppress extreme weights in radar shadow. `1.0` is the weight of a facet at 45° local incidence; flat terrain weighs `tan(θ)`, about 0.6 to 1.0.

`write_qa: bool = ``False`  
If `True`, also write the two QA layers: a contributing-observations map ([Layer.QA_NUM](product.Layer.md#s1bursts.product.Layer.QA_NUM)) and a composite quality map ([Layer.QA_CQM](product.Layer.md#s1bursts.product.Layer.QA_CQM)). `QA-CQM` is 1 / \sum_i W_i A_i under every `aggregation`: under `median` or a quantile it describes the weighting, not the observations the composite's value was taken from.

`overwrite: bool = ``False`  
If `False` and every requested layer's file already exists, skip computation and return the existing product, after checking that each file records the requested grid and compositing parameters and linear units; any other difference, such as the DEM of the inputs, is not checked. Otherwise every requested layer is written, replacing an existing file, so the measurement and its QA layers always come from the same run. If no input reaches the cell, an earlier composite of the same identity is deleted, all its layers, before the error is raised; with `overwrite=False` it is left alone.

`time_range: TimeRange | None = None`  
The compositing window, as calendar days; pass the same `~s1bursts.time_range.TimeRange` the search was made with. When given, the product is named and tagged with its days rather than with the first and last acquisition, so every tile composited from one search shares them; the observed span is kept in the `FIRST_ACQUISITION_DATE` and `LAST_ACQUISITION_DATE` tags. An input outside the window is a `ValueError`.

`burst_edge_trim: bool = ``True`  
Drop the edge of each burst before mosaicking, where the coherence window has darkened it. Its width follows the inputs' estimation window and the grid spacing: 5 pixels at the default window on a 10 m grid. `False` keeps every pixel.


##### Returns


`CohLRWComposite`  
The composite, whose `layers` are the measurement and, with `write_qa=True`, the QA layers. Pass a layer to [FileManager.get_product_path](filemanager.FileManager.md#s1bursts.filemanager.FileManager.get_product_path) for its file.


##### Raises


`TypeError`  
If `time_range` is not a [TimeRange](time_range.TimeRange.md#s1bursts.time_range.TimeRange).

`ValueError`  
If `coh_products` or `rtc_products` is empty, `aggregation` is neither `"mean"`, `"median"` nor a quantile level in `(0, 1)`, an input lies outside `time_range`, or `burst_edge_trim` is `True` and the coherence inputs, or with `overwrite=False` the existing composite, do not record the estimation window.

`EmptyCompositeError`  
If no input has a valid pixel in `geobox`; nothing is written.

`InconsistentInputsError`  
If the inputs differ in polarization or temporal baseline, an input is on another CRS, pixel size or grid than `geobox`, the inputs were made with different DEMs or SNAP versions, where an undetermined SNAP version matches any, or the coherence products, or the RTC products that weight them, among themselves with different processing settings. RTC products that weight no observation are not compared. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells given these inputs would meet it too.

`CompositeInputError`  
If an input product is missing or cannot be read, or a burst some pixel is taken from has no RTC product of the same burst and primary date to supply its scattering area.

`ProductSettingsMismatchError`  
If `overwrite` is `False` and an existing layer file records another grid than `geobox`, other or no compositing parameters, or values in decibels. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells would meet it too.

`OSError or RasterioError`  
If `overwrite` is `False` and an existing layer file cannot be read to check its settings.


------------------------------------------------------------------------


#### compose_gtc_by_pass()


Compute unweighted GTC beta0 composites stratified by pass direction.


Usage

``` python
compose_gtc_by_pass(
    gtc_products,
    geobox,
    *,
    aggregation="mean",
    write_qa=False,
    overwrite=False,
    time_range=None,
    burst_edge_trim=True
)
```


Bursts from the same orbit and acquisition date are mosaicked without the darkened edge of each burst, splitting each overlap at its midline. The resulting orbit-date observations are then aggregated temporally (mean or median) per pass direction (ascending / descending). The stored value is beta-0 power.


##### Parameters


`gtc_products: Collection[GTCProduct]`  
GTC products to composite. Products from both pass directions may be mixed; they are split by their [pass_direction](burst.Burst.md#s1bursts.burst.Burst.pass_direction).

`geobox: MGRSGeoBox`  
Target MGRS grid cell.

`aggregation: Literal[``"mean", `<span class="st">`"median"``] | float`</span>` = ``"mean"`  
Temporal aggregation method. Pass `"mean"` or `"median"` for the corresponding statistic, or a float in `(0, 1)` for an interpolated quantile at that level.

`write_qa: bool = ``False`  
If `True`, also write the contributing-observations QA layer ([Layer.QA_NUM](product.Layer.md#s1bursts.product.Layer.QA_NUM)) of each pass direction.

`overwrite: bool = ``False`  
If `False` and every requested layer's file already exists, skip computation and return the existing product, after checking that each file records the requested grid and compositing parameters and linear units; any other difference, such as the DEM of the inputs, is not checked. Otherwise every requested layer is written, replacing an existing file, so the measurement and its QA layers always come from the same run. A direction that no input reaches has the files of an earlier composite of the same identity deleted; with `overwrite=False` they are left alone.

`time_range: TimeRange | None = None`  
The compositing window, as calendar days; pass the same `~s1bursts.time_range.TimeRange` the search was made with. When given, the product is named and tagged with its days rather than with the first and last acquisition; the observed span is kept in the `FIRST_ACQUISITION_DATE` and `LAST_ACQUISITION_DATE` tags. An input outside the window is a `ValueError`.

`burst_edge_trim: bool = ``True`  
Drop the edge of each burst before mosaicking, where multilooking has darkened it. Its width follows the inputs' looks and the grid spacing: 4 pixels at the default looks on a 10 m grid. `False` keeps every pixel.


##### Returns


`dict[PassDirection, GTCPassComposite]`  
One composite per pass direction among the inputs, whose `layers` are the measurement and, with `write_qa=True`, the QA layer. A direction whose inputs have no valid pixel in `geobox` is left out and gets no file, as if it had no inputs.


##### Raises


`TypeError`  
If `time_range` is not a [TimeRange](time_range.TimeRange.md#s1bursts.time_range.TimeRange).

`ValueError`  
If `gtc_products` is empty, `aggregation` is neither `"mean"`, `"median"` nor a quantile level in `(0, 1)`, or an input lies outside `time_range`.

`EmptyCompositeError`  
If no input of any direction has a valid pixel in `geobox`; nothing is written.

`InconsistentInputsError`  
If the inputs differ in polarization, an input is on another CRS, pixel size or grid than `geobox`, or the inputs were made with different DEMs, processing settings or SNAP versions, where an undetermined SNAP version matches any. When a direction is built, the composite of a direction skipped as existing must agree with its inputs too. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells given these inputs would meet it too.

`CompositeInputError`  
If an input product is missing or cannot be read.

`ProductSettingsMismatchError`  
If `overwrite` is `False` and an existing layer file records another grid than `geobox`, other or no compositing parameters, or values in decibels. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells would meet it too.

`OSError or RasterioError`  
If `overwrite` is `False` and an existing layer file cannot be read to check its settings.


------------------------------------------------------------------------


#### compose_rtc_by_pass()


Compute unweighted RTC composites stratified by pass direction.


Usage

``` python
compose_rtc_by_pass(
    rtc_products,
    geobox,
    *,
    aggregation="mean",
    write_qa=False,
    overwrite=False,
    time_range=None,
    burst_edge_trim=True
)
```


Bursts from the same orbit and acquisition date are mosaicked without the darkened edge of each burst, splitting each overlap at its midline. The resulting orbit-date observations are then aggregated temporally (mean or median) per pass direction (ascending / descending).


##### Parameters


`rtc_products: Collection[RTCProduct]`  
RTC products to composite. Products from both pass directions may be mixed; they are split by their [pass_direction](burst.Burst.md#s1bursts.burst.Burst.pass_direction).

`geobox: MGRSGeoBox`  
Target MGRS grid cell.

`aggregation: Literal[``"mean", `<span class="st">`"median"``] | float`</span>` = ``"mean"`  
Temporal aggregation method. Pass `"mean"` or `"median"` for the corresponding statistic, or a float in `(0, 1)` for an interpolated quantile at that level.

`write_qa: bool = ``False`  
If `True`, also write the contributing-observations QA layer ([Layer.QA_NUM](product.Layer.md#s1bursts.product.Layer.QA_NUM)) of each pass direction.

`overwrite: bool = ``False`  
If `False` and every requested layer's file already exists, skip computation and return the existing product, after checking that each file records the requested grid and compositing parameters and linear units; any other difference, such as the DEM of the inputs, is not checked. Otherwise every requested layer is written, replacing an existing file, so the measurement and its QA layers always come from the same run. A direction that no input reaches has the files of an earlier composite of the same identity deleted; with `overwrite=False` they are left alone.

`time_range: TimeRange | None = None`  
The compositing window, as calendar days; pass the same `~s1bursts.time_range.TimeRange` the search was made with. When given, the product is named and tagged with its days rather than with the first and last acquisition, so every tile composited from one search shares them; the observed span is kept in the `FIRST_ACQUISITION_DATE` and `LAST_ACQUISITION_DATE` tags. An input outside the window is a `ValueError`.

`burst_edge_trim: bool = ``True`  
Drop the edge of each burst before mosaicking, where multilooking has darkened it. Its width follows the inputs' looks and the grid spacing: 4 pixels at the default looks on a 10 m grid. `False` keeps every pixel.


##### Returns


`dict[PassDirection, RTCPassComposite]`  
One composite per pass direction among the inputs, whose `layers` are the measurement and, with `write_qa=True`, the QA layer. A direction whose inputs have no valid pixel in `geobox` is left out and gets no file, as if it had no inputs.


##### Raises


`TypeError`  
If `time_range` is not a [TimeRange](time_range.TimeRange.md#s1bursts.time_range.TimeRange).

`ValueError`  
If `rtc_products` is empty, `aggregation` is neither `"mean"`, `"median"` nor a quantile level in `(0, 1)`, or an input lies outside `time_range`.

`EmptyCompositeError`  
If no input of any direction has a valid pixel in `geobox`; nothing is written.

`InconsistentInputsError`  
If the inputs differ in polarization, an input is on another CRS, pixel size or grid than `geobox`, or the inputs were made with different DEMs, processing settings or SNAP versions, where an undetermined SNAP version matches any. When a direction is built, the composite of a direction skipped as existing must agree with its inputs too. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells given these inputs would meet it too.

`CompositeInputError`  
If an input product is missing or cannot be read.

`ProductSettingsMismatchError`  
If `overwrite` is `False` and an existing layer file records another grid than `geobox`, other or no compositing parameters, or values in decibels. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells would meet it too.

`OSError or RasterioError`  
If `overwrite` is `False` and an existing layer file cannot be read to check its settings.


------------------------------------------------------------------------


#### compose_rtc_lrw()


Compute a locally resolution weighted (LRW) RTC intensity composite.


Usage

``` python
compose_rtc_lrw(
    rtc_products,
    geobox,
    *,
    aggregation="mean",
    clip_max_resolution=None,
    write_qa=False,
    overwrite=False,
    time_range=None,
    burst_edge_trim=True
)
```


Band 1 supplies intensity and band 2 the local scattering area A. Observations are weighted by normalized 1/A (\[1\] eq. 3-4, \[2\] eq. A5.1-A5.3) after mosaicking each orbit and acquisition date, without the darkened edge of each burst and splitting each overlap at its midline.


##### Parameters


`rtc_products: Collection[RTCProduct]`  
RTC products to composite. All products must share the same polarization.

`geobox: MGRSGeoBox`  
Target MGRS grid cell.

`aggregation: Literal[``"mean", `<span class="st">`"median"``] | float`</span>` = ``"mean"`  
Temporal aggregation applied after weighting. Pass `"mean"` or `"median"` for the corresponding statistic, or a float in `(0, 1)` to compute a weighted quantile at that level.

`clip_max_resolution: float | None = None`  
Upper limit for W = 1/A, used to suppress extreme weights in radar shadow. `1.0` is the weight of a facet at 45° local incidence; flat terrain weighs `tan(θ)`, about 0.6 to 1.0.

`write_qa: bool = ``False`  
If `True`, also write the two QA layers: a contributing-observations map ([Layer.QA_NUM](product.Layer.md#s1bursts.product.Layer.QA_NUM)) and a composite quality map ([Layer.QA_CQM](product.Layer.md#s1bursts.product.Layer.QA_CQM)). `QA-CQM` is 1 / \sum_i W_i A_i under every `aggregation`: under `median` or a quantile it describes the weighting, not the observations the composite's value was taken from.

`overwrite: bool = ``False`  
If `False` and every requested layer's file already exists, skip computation and return the existing product, after checking that each file records the requested grid and compositing parameters and linear units; any other difference, such as the DEM of the inputs, is not checked. Otherwise every requested layer is written, replacing an existing file, so the measurement and its QA layers always come from the same run. If no input reaches the cell, an earlier composite of the same identity is deleted, all its layers, before the error is raised; with `overwrite=False` it is left alone.

`time_range: TimeRange | None = None`  
The compositing window, as calendar days; pass the same `~s1bursts.time_range.TimeRange` the search was made with. When given, the product is named and tagged with its days rather than with the first and last acquisition, so every tile composited from one search shares them; the observed span is kept in the `FIRST_ACQUISITION_DATE` and `LAST_ACQUISITION_DATE` tags. An input outside the window is a `ValueError`.

`burst_edge_trim: bool = ``True`  
Drop the edge of each burst before mosaicking, where multilooking has darkened it. Its width follows the inputs' looks and the grid spacing: 4 pixels at the default looks on a 10 m grid. `False` keeps every pixel.


##### Returns


`RTCLRWComposite`  
The composite, whose `layers` are the measurement and, with `write_qa=True`, the QA layers. Pass a layer to [FileManager.get_product_path](filemanager.FileManager.md#s1bursts.filemanager.FileManager.get_product_path) for its file.


##### Raises


`TypeError`  
If `time_range` is not a [TimeRange](time_range.TimeRange.md#s1bursts.time_range.TimeRange).

`ValueError`  
If `rtc_products` is empty, `aggregation` is neither `"mean"`, `"median"` nor a quantile level in `(0, 1)`, or an input lies outside `time_range`.

`EmptyCompositeError`  
If no input has a valid pixel in `geobox`; nothing is written.

`InconsistentInputsError`  
If the inputs differ in polarization, an input is on another CRS, pixel size or grid than `geobox`, or the inputs were made with different DEMs, processing settings or SNAP versions, where an undetermined SNAP version matches any. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells given these inputs would meet it too.

`CompositeInputError`  
If an input product is missing or cannot be read.

`ProductSettingsMismatchError`  
If `overwrite` is `False` and an existing layer file records another grid than `geobox`, other or no compositing parameters, or values in decibels. Not a [CompositeError](errors.CompositeError.md#s1bursts.errors.CompositeError): other cells would meet it too.

`OSError or RasterioError`  
If `overwrite` is `False` and an existing layer file cannot be read to check its settings.
