BiliSakura commited on
Commit
6f76ec7
·
verified ·
1 Parent(s): 6b2f4fa

Sync updated code and configs (no weight re-upload)

Browse files
README.md ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ tags:
6
+ - remote-sensing
7
+ - earth-observation
8
+ - self-supervised-learning
9
+ - satellite
10
+ - multispectral
11
+ - multimodal
12
+ - feature-extraction
13
+ - anysat
14
+ - transformers
15
+ library_name: transformers
16
+ pipeline_tag: feature-extraction
17
+ ---
18
+
19
+ # AnySat Transformers Models
20
+
21
+ Hugging Face–compatible checkpoints converted from the official [AnySat](https://arxiv.org/abs/2503.16990) GeoPlex-pretrained weights. Each subfolder is a standalone model repo (`config.json`, `model.safetensors`, processor, pipeline, and remote code) for multimodal Earth observation feature extraction.
22
+
23
+ ## Model Description
24
+
25
+ [AnySat](https://github.com/gastruc/AnySat) is a scale-adaptive, multimodal Earth Observation foundation model supporting 11 sensor modalities (aerial, Sentinel-1/2, Landsat, MODIS, etc.) at variable resolutions. The `anysat-base` checkpoint is the published base encoder (768-dim, 6 layers, 12 heads).
26
+
27
+ All hyperparameters live in `config.json` and `preprocessor_config.json` — Python remote code does not embed global defaults.
28
+
29
+ **Developed by:** [AnySat Authors](https://github.com/gastruc/AnySat)
30
+ **Converted for Hugging Face by:** BiliSakura
31
+ **License (weights):** MIT
32
+ **Original paper:** [AnySat: One Earth Observation Model for Many Resolutions, Scales, and Modalities](https://arxiv.org/abs/2503.16990) (CVPR 2025 Highlight)
33
+
34
+ ## Available checkpoints
35
+
36
+ | Folder | Size | Embed dim | Depth | Heads | Modalities |
37
+ |--------|------|-----------|-------|-------|------------|
38
+ | `anysat-base` | base | 768 | 6 | 12 | 11 |
39
+
40
+ Legacy source: `models/raw/AnySat_full.pth` (see [`conversion_manifest.json`](conversion_manifest.json)).
41
+
42
+ ## Usage
43
+
44
+ Inputs must be **normalized** `(data - mean) / std` per modality when `normalize=True` in the processor. Set `normalization_stats` in `preprocessor_config.json` for your dataset statistics.
45
+
46
+ ### Custom pipeline (recommended)
47
+
48
+ ```python
49
+ from transformers import pipeline
50
+ import numpy as np
51
+
52
+ MODEL = "/path/to/AnySat-transformers/anysat-base"
53
+
54
+ pipe = pipeline(
55
+ task="anysat-feature-extraction",
56
+ model=MODEL,
57
+ trust_remote_code=True,
58
+ )
59
+
60
+ # Sentinel-2 time series: (B, T, C, H, W)
61
+ s2 = np.random.randn(1, 4, 10, 32, 32).astype(np.float32)
62
+ dates = np.array([[100, 120, 140, 160]])
63
+
64
+ # Tile features (CLS token)
65
+ features = pipe(s2=s2, s2_dates=dates, patch_size=10, pool=True, return_tensors=True)
66
+ print(features.shape) # torch.Size([1, 768])
67
+
68
+ # Patch features
69
+ patch_features = pipe(s2=s2, s2_dates=dates, patch_size=10, output="patch", return_tensors=True)
70
+ print(patch_features.shape) # torch.Size([1, 1024, 768])
71
+ ```
72
+
73
+ ### Multimodal example
74
+
75
+ ```python
76
+ pipe = pipeline(task="anysat-feature-extraction", model=MODEL, trust_remote_code=True)
77
+
78
+ s2 = np.random.randn(1, 4, 10, 32, 32).astype(np.float32)
79
+ s1 = np.random.randn(1, 4, 3, 32, 32).astype(np.float32)
80
+ features = pipe(
81
+ s2=s2,
82
+ s2_dates=np.array([[100, 120, 140, 160]]),
83
+ s1=s1,
84
+ s1_dates=np.array([[100, 120, 140, 160]]),
85
+ patch_size=10,
86
+ pool=True,
87
+ return_tensors=True,
88
+ )
89
+ ```
90
+
91
+ ### Built-in ImageFeatureExtractionPipeline
92
+
93
+ `AnySatModel` returns `BaseModelOutputWithPooling`, so the registered `image-feature-extraction` task also works:
94
+
95
+ ```python
96
+ pipe = pipeline(
97
+ task="image-feature-extraction",
98
+ model=MODEL,
99
+ trust_remote_code=True,
100
+ )
101
+ ```
102
+
103
+ ## Supported modalities
104
+
105
+ | Key | Type | Channels | Resolution |
106
+ |-----|------|----------|------------|
107
+ | `aerial` | image | 4 | 0.2 m |
108
+ | `aerial-flair` | image | 5 | 0.2 m |
109
+ | `spot` | image | 3 | 1 m |
110
+ | `naip` | image | 4 | 1.25 m |
111
+ | `s2` | time series | 10 | 10 m |
112
+ | `s1-asc`, `s1` | time series | 2–3 | 10 m |
113
+ | `l7`, `l8` | time series | 6–11 | 10–30 m |
114
+ | `alos` | time series | 3 | 30 m |
115
+ | `modis` | time series | 7 | 250 m |
116
+
117
+ Time-series modalities require `{modality}_dates` (day-of-year, 0–364). Images must be square. `patch_size` is in **meters** (internally divided by 10).
118
+
119
+ ## Output modes
120
+
121
+ | `output` | Shape | Description |
122
+ |----------|-------|-------------|
123
+ | `tile` | `[B, 768]` | CLS / global embedding (`pool=True`) |
124
+ | `patch` | `[B, H*W, 768]` | Patch tokens |
125
+ | `dense` | high-res map | Dense features for segmentation |
126
+ | `all` | all tokens | Full token sequence |
anysat-base/config.json ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "AnySatModel"
4
+ ],
5
+ "attn_drop_rate": 0.0,
6
+ "class_token": true,
7
+ "default_output": "patch",
8
+ "default_patch_size": 10,
9
+ "depth": 6,
10
+ "drop_path_rate": 0.0,
11
+ "drop_rate": 0.0,
12
+ "dtype": "float32",
13
+ "embed_dim": 768,
14
+ "flash_attn": false,
15
+ "hidden_size": 768,
16
+ "image_modalities": [
17
+ "aerial",
18
+ "aerial-flair",
19
+ "spot",
20
+ "naip"
21
+ ],
22
+ "mlp_ratio": 4.0,
23
+ "modalities": [
24
+ "aerial",
25
+ "aerial-flair",
26
+ "spot",
27
+ "naip",
28
+ "s2",
29
+ "s1-asc",
30
+ "s1",
31
+ "alos",
32
+ "l7",
33
+ "l8",
34
+ "modis"
35
+ ],
36
+ "modality_resolutions": {
37
+ "aerial": 0.2,
38
+ "aerial-flair": 0.2,
39
+ "alos": 30,
40
+ "l7": 30,
41
+ "l8": 10,
42
+ "modis": 250,
43
+ "naip": 1.25,
44
+ "s1": 10,
45
+ "s1-asc": 10,
46
+ "s1-des": 10,
47
+ "s2": 10,
48
+ "spot": 1.0
49
+ },
50
+ "model_size": "base",
51
+ "model_type": "anysat",
52
+ "normalization_stats": null,
53
+ "num_heads": 12,
54
+ "patch_drop_rate": 0.0,
55
+ "pre_norm": false,
56
+ "projectors": {
57
+ "aerial": {
58
+ "bias": false,
59
+ "embed_dim": 768,
60
+ "in_chans": 4,
61
+ "mlp": [
62
+ 768,
63
+ 1536,
64
+ 768
65
+ ],
66
+ "patch_size": 10
67
+ },
68
+ "aerial-flair": {
69
+ "bias": false,
70
+ "embed_dim": 768,
71
+ "in_chans": 5,
72
+ "mlp": [
73
+ 768,
74
+ 1536,
75
+ 768
76
+ ],
77
+ "patch_size": 10
78
+ },
79
+ "alos": {
80
+ "T": 367,
81
+ "d_k": 8,
82
+ "dropout": 0.2,
83
+ "in_channels": 3,
84
+ "in_norm": false,
85
+ "mlp": [
86
+ 768
87
+ ],
88
+ "mlp_in": [
89
+ 96,
90
+ 384,
91
+ 768,
92
+ 1536,
93
+ 768
94
+ ],
95
+ "n_head": 16,
96
+ "positional_encoding": true,
97
+ "reduce_scale": 3,
98
+ "return_att": false
99
+ },
100
+ "l7": {
101
+ "T": 367,
102
+ "d_k": 8,
103
+ "dropout": 0.2,
104
+ "in_channels": 6,
105
+ "in_norm": false,
106
+ "mlp": [
107
+ 768
108
+ ],
109
+ "mlp_in": [
110
+ 96,
111
+ 384,
112
+ 768,
113
+ 1536,
114
+ 768
115
+ ],
116
+ "n_head": 16,
117
+ "positional_encoding": true,
118
+ "reduce_scale": 3,
119
+ "return_att": false
120
+ },
121
+ "l8": {
122
+ "T": 366,
123
+ "d_k": 8,
124
+ "dropout": 0.0,
125
+ "in_channels": 11,
126
+ "in_norm": false,
127
+ "mlp": [
128
+ 768
129
+ ],
130
+ "mlp_in": [
131
+ 96,
132
+ 384,
133
+ 768,
134
+ 1536,
135
+ 768
136
+ ],
137
+ "n_head": 16,
138
+ "positional_encoding": true,
139
+ "return_att": false
140
+ },
141
+ "modis": {
142
+ "T": 367,
143
+ "d_k": 8,
144
+ "dropout": 0.2,
145
+ "in_channels": 7,
146
+ "in_norm": false,
147
+ "mlp": [
148
+ 768
149
+ ],
150
+ "mlp_in": [
151
+ 96,
152
+ 384,
153
+ 768,
154
+ 1536,
155
+ 768
156
+ ],
157
+ "n_head": 16,
158
+ "positional_encoding": true,
159
+ "reduce_scale": 12,
160
+ "return_att": false
161
+ },
162
+ "naip": {
163
+ "bias": false,
164
+ "embed_dim": 768,
165
+ "in_chans": 4,
166
+ "mlp": [
167
+ 768,
168
+ 1536,
169
+ 768
170
+ ],
171
+ "patch_size": 8,
172
+ "resolution": 1.25
173
+ },
174
+ "s1": {
175
+ "T": 367,
176
+ "d_k": 8,
177
+ "dropout": 0.2,
178
+ "in_channels": 3,
179
+ "in_norm": false,
180
+ "mlp": [
181
+ 768
182
+ ],
183
+ "mlp_in": [
184
+ 96,
185
+ 384,
186
+ 768,
187
+ 1536,
188
+ 768
189
+ ],
190
+ "n_head": 16,
191
+ "positional_encoding": true,
192
+ "return_att": false
193
+ },
194
+ "s1-asc": {
195
+ "T": 367,
196
+ "d_k": 8,
197
+ "dropout": 0.2,
198
+ "in_channels": 2,
199
+ "in_norm": false,
200
+ "mlp": [
201
+ 768
202
+ ],
203
+ "mlp_in": [
204
+ 96,
205
+ 384,
206
+ 768,
207
+ 1536,
208
+ 768
209
+ ],
210
+ "n_head": 16,
211
+ "positional_encoding": true,
212
+ "return_att": false
213
+ },
214
+ "s2": {
215
+ "T": 367,
216
+ "d_k": 8,
217
+ "dropout": 0.0,
218
+ "in_channels": 10,
219
+ "in_norm": true,
220
+ "mlp": [
221
+ 768
222
+ ],
223
+ "mlp_in": [
224
+ 96,
225
+ 384,
226
+ 768,
227
+ 1536,
228
+ 768
229
+ ],
230
+ "n_head": 16,
231
+ "positional_encoding": true,
232
+ "return_att": false
233
+ },
234
+ "spot": {
235
+ "bias": false,
236
+ "embed_dim": 768,
237
+ "in_chans": 3,
238
+ "mlp": [
239
+ 768,
240
+ 1536,
241
+ 768
242
+ ],
243
+ "patch_size": 10,
244
+ "resolution": 1.0
245
+ }
246
+ },
247
+ "release": true,
248
+ "spatial_encoder_input_res": {
249
+ "aerial": 2,
250
+ "aerial-flair": 2,
251
+ "alos": 30,
252
+ "l7": 30,
253
+ "l8": 10,
254
+ "modis": 250,
255
+ "naip": 10,
256
+ "s1": 10,
257
+ "s1-asc": 10,
258
+ "s1-des": 10,
259
+ "s2": 10,
260
+ "spot": 10
261
+ },
262
+ "time_series_modalities": [
263
+ "s2",
264
+ "s1-asc",
265
+ "s1",
266
+ "alos",
267
+ "l7",
268
+ "l8",
269
+ "modis"
270
+ ],
271
+ "transformers_version": "5.0.0",
272
+ "auto_map": {
273
+ "AutoConfig": "modeling_anysat.AnySatConfig",
274
+ "AutoModel": "modeling_anysat.AnySatModel"
275
+ },
276
+ "custom_pipelines": {
277
+ "anysat-feature-extraction": {
278
+ "impl": "pipeline_anysat.AnySatImageFeatureExtractionPipeline",
279
+ "pt": [
280
+ "AutoModel"
281
+ ]
282
+ },
283
+ "image-feature-extraction": {
284
+ "impl": "pipeline_anysat.AnySatImageFeatureExtractionPipeline",
285
+ "pt": [
286
+ "AutoModel"
287
+ ]
288
+ }
289
+ }
290
+ }
anysat-base/modeling_anysat.py ADDED
The diff for this file is too large to render. See raw diff
 
anysat-base/pipeline_anysat.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 AnySat Authors and The HuggingFace Inc. team.
2
+ """Self-contained AnySat feature extraction pipeline for trust_remote_code loading."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, Union
7
+
8
+ import torch
9
+
10
+ from transformers.pipelines.base import GenericTensor, build_pipeline_init_args
11
+ from transformers.pipelines.image_feature_extraction import ImageFeatureExtractionPipeline
12
+ from transformers.utils import add_end_docstrings
13
+
14
+
15
+ @add_end_docstrings(
16
+ build_pipeline_init_args(has_processor=True),
17
+ """
18
+ patch_size (`int`, *optional*, defaults to `10`):
19
+ Patch size in meters passed to the scale-adaptive encoder.
20
+ output (`str`, *optional*, defaults to `"patch"`):
21
+ Output mode. One of `"tile"`, `"patch"`, `"dense"`, or `"all"`.
22
+ pool (`bool`, *optional*, defaults to `False`):
23
+ Whether to return pooled tile features instead of patch hidden states.
24
+ """,
25
+ )
26
+ class AnySatImageFeatureExtractionPipeline(ImageFeatureExtractionPipeline):
27
+ _load_processor = True
28
+ _load_image_processor = False
29
+ _load_feature_extractor = False
30
+ _load_tokenizer = False
31
+
32
+ def _sanitize_parameters(
33
+ self,
34
+ processor_kwargs=None,
35
+ image_processor_kwargs=None,
36
+ return_tensors=None,
37
+ pool=None,
38
+ normalize=None,
39
+ patch_size=None,
40
+ output=None,
41
+ output_modality=None,
42
+ **kwargs,
43
+ ):
44
+ preprocess_params = {}
45
+ if processor_kwargs is not None:
46
+ preprocess_params.update(processor_kwargs)
47
+ if image_processor_kwargs is not None:
48
+ preprocess_params.update(image_processor_kwargs)
49
+
50
+ for modality in (
51
+ "aerial",
52
+ "aerial-flair",
53
+ "spot",
54
+ "naip",
55
+ "s2",
56
+ "s1-asc",
57
+ "s1",
58
+ "alos",
59
+ "l7",
60
+ "l8",
61
+ "modis",
62
+ ):
63
+ if modality in kwargs:
64
+ preprocess_params[modality] = kwargs.pop(modality)
65
+ dates_key = f"{modality}_dates"
66
+ if dates_key in kwargs:
67
+ preprocess_params[dates_key] = kwargs.pop(dates_key)
68
+
69
+ if normalize is not None:
70
+ preprocess_params["normalize"] = normalize
71
+ if patch_size is not None:
72
+ preprocess_params["patch_size"] = patch_size
73
+ if output is not None:
74
+ preprocess_params["output"] = output
75
+
76
+ forward_params = {}
77
+ if output_modality is not None:
78
+ forward_params["output_modality"] = output_modality
79
+
80
+ postprocess_params = {}
81
+ if pool is not None:
82
+ postprocess_params["pool"] = pool
83
+ if pool:
84
+ preprocess_params.setdefault("output", "tile")
85
+ if return_tensors is not None:
86
+ postprocess_params["return_tensors"] = return_tensors
87
+
88
+ return preprocess_params, forward_params, postprocess_params
89
+
90
+ def preprocess(self, image=None, timeout=None, **processor_kwargs) -> dict[str, GenericTensor]:
91
+ del image, timeout
92
+ model_inputs = self.processor(return_tensors="pt", **processor_kwargs)
93
+ if hasattr(model_inputs, "to"):
94
+ model_inputs = model_inputs.to(self.device)
95
+ model_inputs = model_inputs.to(self.dtype)
96
+ return model_inputs
97
+
98
+ def _forward(self, model_inputs, output_modality: str = ""):
99
+ patch_size = model_inputs.pop("patch_size", None)
100
+ output = model_inputs.pop("output", None)
101
+ if torch.is_tensor(patch_size):
102
+ patch_size = int(patch_size.item())
103
+ return self.model(
104
+ patch_size=patch_size,
105
+ output=output,
106
+ output_modality=output_modality,
107
+ **model_inputs,
108
+ )
109
+
110
+ def postprocess(self, model_outputs, pool=None, return_tensors=False):
111
+ if pool:
112
+ outputs = model_outputs.pooler_output
113
+ if outputs is None and model_outputs.last_hidden_state is not None:
114
+ outputs = model_outputs.last_hidden_state
115
+ if outputs.ndim > 2:
116
+ outputs = outputs[:, 0]
117
+ else:
118
+ outputs = model_outputs.last_hidden_state
119
+ if outputs is None:
120
+ outputs = model_outputs[0]
121
+ if return_tensors:
122
+ return outputs
123
+ return outputs.detach().cpu().tolist()
124
+
125
+ def __call__(self, *args: Union[Any, list[Any]], **kwargs: Any) -> list[Any]:
126
+ if not args:
127
+ args = (None,)
128
+ return super().__call__(*args, **kwargs)
129
+
130
+
131
+ __all__ = ["AnySatImageFeatureExtractionPipeline"]
anysat-base/preprocessor_config.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "processor_class": "AnySatProcessor",
3
+ "normalize": true,
4
+ "patch_size": 10,
5
+ "output": "patch",
6
+ "modalities": [
7
+ "aerial",
8
+ "aerial-flair",
9
+ "spot",
10
+ "naip",
11
+ "s2",
12
+ "s1-asc",
13
+ "s1",
14
+ "alos",
15
+ "l7",
16
+ "l8",
17
+ "modis"
18
+ ],
19
+ "normalization_stats": null,
20
+ "auto_map": {
21
+ "AutoProcessor": "processing_anysat.AnySatProcessor"
22
+ }
23
+ }
anysat-base/processing_anysat.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 AnySat Authors and The HuggingFace Inc. team.
2
+ """Self-contained AnySat processor for trust_remote_code loading."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, Optional, Union
7
+
8
+ import numpy as np
9
+ import torch
10
+
11
+ from transformers.feature_extraction_utils import BatchFeature
12
+ from transformers.processing_utils import ProcessorMixin
13
+ from transformers.utils import TensorType
14
+
15
+
16
+ def _to_numpy(value):
17
+ if torch.is_tensor(value):
18
+ return value.detach().cpu().numpy()
19
+ return np.asarray(value)
20
+
21
+
22
+ def _normalize_modality(array, mean, std):
23
+ if mean is None or std is None:
24
+ return array.astype(np.float32)
25
+ mean_arr = np.asarray(mean, dtype=np.float32)
26
+ std_arr = np.asarray(std, dtype=np.float32)
27
+ if array.ndim >= 3 and array.shape[-3] <= mean_arr.shape[0]:
28
+ channels = array.shape[-3]
29
+ mean_arr = mean_arr[:channels]
30
+ std_arr = std_arr[:channels]
31
+ reshape = (1,) * (array.ndim - 3) + (channels,) + (1,) * 2
32
+ mean_arr = mean_arr.reshape(reshape)
33
+ std_arr = std_arr.reshape(reshape)
34
+ return ((array - mean_arr) / std_arr).astype(np.float32)
35
+
36
+
37
+ class AnySatProcessor(ProcessorMixin):
38
+ attributes = []
39
+
40
+ def __init__(
41
+ self,
42
+ normalize=None,
43
+ patch_size=None,
44
+ output=None,
45
+ normalization_stats=None,
46
+ modalities=None,
47
+ **kwargs,
48
+ ):
49
+ super().__init__(**kwargs)
50
+ self.normalize = normalize
51
+ self.patch_size = patch_size
52
+ self.output = output
53
+ self.normalization_stats = normalization_stats
54
+ self.modalities = modalities
55
+
56
+ def __call__(
57
+ self,
58
+ return_tensors: Optional[Union[str, TensorType]] = None,
59
+ normalize: Optional[bool] = None,
60
+ patch_size: Optional[int] = None,
61
+ output: Optional[str] = None,
62
+ **kwargs: Any,
63
+ ) -> BatchFeature:
64
+ normalize = self.normalize if normalize is None else normalize
65
+ patch_size = patch_size if patch_size is not None else self.patch_size
66
+ output = output if output is not None else self.output
67
+ data = {"patch_size": patch_size, "output": output}
68
+
69
+ for key, value in kwargs.items():
70
+ if value is None:
71
+ continue
72
+ if key.endswith("_dates"):
73
+ dates = _to_numpy(value)
74
+ if dates.ndim == 1:
75
+ dates = dates[np.newaxis, ...]
76
+ data[key] = dates.astype(np.int64)
77
+ continue
78
+ if self.modalities and key in self.modalities:
79
+ array = _to_numpy(value).astype(np.float32)
80
+ if array.ndim == 3:
81
+ array = array[np.newaxis, ...]
82
+ if normalize and self.normalization_stats and key in self.normalization_stats:
83
+ stats = self.normalization_stats[key]
84
+ array = _normalize_modality(array, stats.get("mean"), stats.get("std"))
85
+ data[key] = array
86
+ continue
87
+ data[key] = value
88
+
89
+ if return_tensors == TensorType.PYTORCH:
90
+ for key, value in list(data.items()):
91
+ if key in {"patch_size", "output"}:
92
+ continue
93
+ if not torch.is_tensor(value):
94
+ dtype = torch.long if key.endswith("_dates") else torch.float32
95
+ data[key] = torch.as_tensor(value, dtype=dtype)
96
+
97
+ return BatchFeature(data=data, tensor_type=return_tensors)
98
+
99
+
100
+ __all__ = ["AnySatProcessor"]