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:
Orbit crossover detection —
orbitxpropagates satellite orbits and returns candidate matchup events: time windows and bounding boxes where two (or more) satellites are close enough to produce overlapping products.Product discovery — for each event,
scrappiqueries 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"))