Tessera¶
rslearn includes a wrapper for Tessera v1.1 QAT encoder checkpoints from https://github.com/ucam-eo/tessera.
The wrapper does not download weights automatically. We recommend using the
Microsoft Planetary Computer checkpoint because rslearn does not currently
support OPERA RTC-S1 here. Download the encoder-only
tessera_v1_1_mpc_encoder.pt
checkpoint from the official Tessera README, then pass it with
checkpoint_path.
Tessera inputs should be normalized with rslearn.models.tessera.TesseraNormalize
before they reach the model. Set the transform's data_source to match the
checkpoint family:
mpc: Microsoft Planetary Computer Sentinel-2 L2A and Sentinel-1 RTC.aws: AWS Open Data Earth-search Sentinel-2 L2A and ASF OPERA RTC-S1. This is not currently recommended because rslearn does not have an OPERA data source yet.
Tessera uses different normalization statistics for the two checkpoint families,
which are selected by the data_source argument of TesseraNormalize.
Inputs¶
The model expects three raster inputs:
s2: Sentinel-2 bands in Tessera order:B04, B02, B03, B08, B8A, B05, B06, B07, B11, B12.s1_ascending: Sentinel-1 ascending orbit bandsvv, vh.s1_descending: Sentinel-1 descending orbit bandsvv, vh.
All inputs must have timestamps. The wrapper uses each timestamp midpoint to compute day-of-year features.
TesseraNormalize expects Sentinel-1 values in standard power decibels
(10 * log10(linear)). For raw linear RTC sources, apply
Sentinel1ToDecibels before TesseraNormalize. If your Sentinel-1 layers are
already stored in standard dB, skip Sentinel1ToDecibels and still run
TesseraNormalize.
Example¶
Here is an example of a model config to compute embeddings with Tessera:
model:
class_path: rslearn.train.lightning_module.RslearnLightningModule
init_args:
model:
class_path: rslearn.models.singletask.SingleTaskModel
init_args:
encoder:
- class_path: rslearn.models.tessera.Tessera
init_args:
# Replace with the path to the downloaded checkpoint!
checkpoint_path: /path/to/tessera_v1_1_mpc_encoder.pt
pixel_batch_size: 1024
decoder:
- class_path: rslearn.train.tasks.embedding.EmbeddingHead
optimizer:
class_path: rslearn.train.optimizer.AdamW
data:
class_path: rslearn.train.data_module.RslearnDataModule
init_args:
inputs:
s2:
data_type: raster
layers: ["sentinel2_l2a"]
bands: ["B04", "B02", "B03", "B08", "B8A", "B05", "B06", "B07", "B11", "B12"]
passthrough: true
load_all_layers: true
s1_ascending:
data_type: raster
layers: ["sentinel1_ascending"]
bands: ["vv", "vh"]
passthrough: true
load_all_layers: true
s1_descending:
data_type: raster
layers: ["sentinel1_descending"]
bands: ["vv", "vh"]
passthrough: true
load_all_layers: true
transforms:
- class_path: rslearn.train.transforms.sentinel1.Sentinel1ToDecibels
init_args:
selectors: ["s1_ascending", "s1_descending"]
- class_path: rslearn.models.tessera.TesseraNormalize
init_args:
data_source: mpc
The wrapper returns float32 feature maps with 192 channels by default, so it can be
used with EmbeddingHead and RslearnWriter.
Data Source Example¶
Here is an example for obtaining Sentinel-2 L2A and Sentinel-1 RTC (with separated ascending and descending images) that are compatible with Tessera. It creates 12 chronological 30-day mosaics per layer, but note that Tessera can input more frequent images.
{
"layers": {
"sentinel2_l2a": {
"type": "raster",
"band_sets": [
{
"bands": [
"B01",
"B02",
"B03",
"B04",
"B05",
"B06",
"B07",
"B08",
"B8A",
"B09",
"B11",
"B12"
],
"dtype": "uint16"
}
],
"data_source": {
"class_path": "rslearn.data_sources.planetary_computer.Sentinel2",
"init_args": {
"cache_dir": "cache/planetary_computer",
"harmonize": true,
"sort_by": "eo:cloud_cover"
},
"ingest": false,
"query_config": {
"max_matches": 12,
"min_matches": 12,
"per_period_mosaic_reverse_time_order": false,
"period_duration": "30d",
"space_mode": "MOSAIC"
}
}
},
"sentinel1_ascending": {
"type": "raster",
"band_sets": [
{
"bands": ["vv", "vh"],
"dtype": "float32"
}
],
"data_source": {
"class_path": "rslearn.data_sources.planetary_computer.Sentinel1",
"init_args": {
"cache_dir": "cache/planetary_computer",
"query": {
"sar:instrument_mode": {
"eq": "IW"
},
"sar:polarizations": {
"eq": [
"VV",
"VH"
]
},
"sat:orbit_state": {
"eq": "ascending"
}
}
},
"ingest": false,
"query_config": {
"max_matches": 12,
"min_matches": 12,
"per_period_mosaic_reverse_time_order": false,
"period_duration": "30d",
"space_mode": "MOSAIC"
}
}
},
"sentinel1_descending": {
"type": "raster",
"band_sets": [
{
"bands": ["vv", "vh"],
"dtype": "float32"
}
],
"data_source": {
"class_path": "rslearn.data_sources.planetary_computer.Sentinel1",
"init_args": {
"cache_dir": "cache/planetary_computer",
"query": {
"sar:instrument_mode": {
"eq": "IW"
},
"sar:polarizations": {
"eq": [
"VV",
"VH"
]
},
"sat:orbit_state": {
"eq": "descending"
}
}
},
"ingest": false,
"query_config": {
"max_matches": 12,
"min_matches": 12,
"per_period_mosaic_reverse_time_order": false,
"period_duration": "30d",
"space_mode": "MOSAIC"
}
}
}
}
}