Finding matchups#

A matchup is a pair (or group) of satellite image products that overlap in both space and time. EOMatch identifies them in two stages:

  1. Orbit crossover detectionorbitx propagates satellite orbits and returns candidate matchup events: time windows and bounding boxes where two (or more) satellites are close enough to produce overlapping products.

  2. Product discovery — for each event, scrappi queries the product catalogue and filters results down to products whose footprints actually intersect.

The result is a list of MatchupEvent objects, each with an attached MatchupSet of confirmed Matchup objects.

Running the finder#

Use Sat2SatMUFinder to run the full pipeline. Parameters are read from a EOMatchContext:

from eomatch import EOMatchContext
from eomatch.finder.sat2sat import Sat2SatMUFinder

ctx = EOMatchContext("my_config.yaml")
events = Sat2SatMUFinder(context=ctx).finder()

for event in events:
    print(event)
    for matchup in event.matchup_set:
        print("  ", matchup)
<eomatch.MatchupEvent (S2A_S3A, times: [...], bounds: {...})
  <eomatch.Matchup (bounds: (...), start_time: 2023-06-15T10:12:03)>
  Products:
    LANDSAT_C2L1:  LC08_L1TP_...
    S3_EFR:        S3A_OL_1_EFR...
...

The platforms and collections config keys (comma-separated) control which satellites and product collections are searched:

platforms: S2A, S3A
collections: S2_MSI_L1C, S3_EFR
start_time: "2023-06-01 00:00:00"
end_time:   "2023-06-30 23:59:59"
space_diff_threshold: 290          # km
time_diff_threshold:  900          # seconds

Using a pre-computed orbitx file#

Running orbitx can take time for long date ranges. You can point eomatch at a pre-computed NetCDF file to skip orbit propagation:

orbitx_netcdf_path: /data/matchups/S2A_S3A_2023-06.nc

Spatial and temporal filtering#

Events returned by orbitx can be further restricted before product queries are issued. Set any combination of the following keys in your config:

min_lat: 40.0
max_lat: 70.0
min_lon: -10.0
max_lon: 30.0
start_time: "2023-06-15 00:00:00"
end_time:   "2023-06-15 23:59:59"

Inspecting a matchup#

Each Matchup exposes the geometry and timing of the collocated products:

mu = events[0].matchup_set[0]

# Shapely polygon of the overlapping footprint
print(mu.collocation_region)

# Earliest start time and latest stop time across all products
print(mu.product_time_bounds)

# Absolute time difference between product start times (seconds)
print(mu.time_diff_abs)

# Signed time difference: collection2.start - collection1.start (seconds)
print(mu.time_diff("S3_EFR", "S2_MSI_L1C"))