pycontrails 0.55.0__cp313-cp313-macosx_11_0_arm64.whl → 0.57.0__cp313-cp313-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pycontrails might be problematic. Click here for more details.
- pycontrails/_version.py +3 -3
- pycontrails/core/airports.py +1 -1
- pycontrails/core/cache.py +3 -3
- pycontrails/core/fleet.py +1 -1
- pycontrails/core/flight.py +47 -43
- pycontrails/core/met_var.py +1 -1
- pycontrails/core/rgi_cython.cpython-313-darwin.so +0 -0
- pycontrails/core/vector.py +28 -30
- pycontrails/datalib/geo_utils.py +261 -0
- pycontrails/datalib/gfs/gfs.py +58 -64
- pycontrails/datalib/goes.py +193 -399
- pycontrails/datalib/himawari/__init__.py +27 -0
- pycontrails/datalib/himawari/header_struct.py +266 -0
- pycontrails/datalib/himawari/himawari.py +654 -0
- pycontrails/datalib/landsat.py +49 -26
- pycontrails/datalib/leo_utils/__init__.py +5 -0
- pycontrails/datalib/leo_utils/correction.py +266 -0
- pycontrails/datalib/leo_utils/landsat_metadata.py +300 -0
- pycontrails/datalib/{_leo_utils → leo_utils}/search.py +1 -1
- pycontrails/datalib/leo_utils/sentinel_metadata.py +748 -0
- pycontrails/datalib/sentinel.py +236 -93
- pycontrails/models/dry_advection.py +1 -1
- pycontrails/models/extended_k15.py +8 -8
- {pycontrails-0.55.0.dist-info → pycontrails-0.57.0.dist-info}/METADATA +4 -2
- {pycontrails-0.55.0.dist-info → pycontrails-0.57.0.dist-info}/RECORD +31 -23
- /pycontrails/datalib/{_leo_utils → leo_utils}/static/bq_roi_query.sql +0 -0
- /pycontrails/datalib/{_leo_utils → leo_utils}/vis.py +0 -0
- {pycontrails-0.55.0.dist-info → pycontrails-0.57.0.dist-info}/WHEEL +0 -0
- {pycontrails-0.55.0.dist-info → pycontrails-0.57.0.dist-info}/licenses/LICENSE +0 -0
- {pycontrails-0.55.0.dist-info → pycontrails-0.57.0.dist-info}/licenses/NOTICE +0 -0
- {pycontrails-0.55.0.dist-info → pycontrails-0.57.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Support for Himawari-8/9 satellite data access."""
|
|
2
|
+
|
|
3
|
+
from pycontrails.datalib.himawari.header_struct import (
|
|
4
|
+
HEADER_STRUCT_SCHEMA,
|
|
5
|
+
parse_himawari_header,
|
|
6
|
+
)
|
|
7
|
+
from pycontrails.datalib.himawari.himawari import (
|
|
8
|
+
HIMAWARI_8_9_SWITCH_DATE,
|
|
9
|
+
HIMAWARI_8_BUCKET,
|
|
10
|
+
HIMAWARI_9_BUCKET,
|
|
11
|
+
Himawari,
|
|
12
|
+
HimawariRegion,
|
|
13
|
+
extract_visualization,
|
|
14
|
+
to_true_color,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"HEADER_STRUCT_SCHEMA",
|
|
19
|
+
"HIMAWARI_8_9_SWITCH_DATE",
|
|
20
|
+
"HIMAWARI_8_BUCKET",
|
|
21
|
+
"HIMAWARI_9_BUCKET",
|
|
22
|
+
"Himawari",
|
|
23
|
+
"HimawariRegion",
|
|
24
|
+
"extract_visualization",
|
|
25
|
+
"parse_himawari_header",
|
|
26
|
+
"to_true_color",
|
|
27
|
+
]
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""Support for parsing the Himawari-8/9 header structure.
|
|
2
|
+
|
|
3
|
+
See the latest user guide for details:
|
|
4
|
+
https://www.data.jma.go.jp/mscweb/en/himawari89/space_segment/hsd_sample/HS_D_users_guide_en_v13.pdf
|
|
5
|
+
|
|
6
|
+
If that link breaks, find the correct link here:
|
|
7
|
+
https://www.data.jma.go.jp/mscweb/en/himawari89/space_segment/sample_hisd.html
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import struct
|
|
11
|
+
from typing import Any, TypedDict
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _HeaderBlock(TypedDict):
|
|
15
|
+
"""An individual Himawari header block."""
|
|
16
|
+
|
|
17
|
+
name: str
|
|
18
|
+
fields: list[tuple[str, str, int, int, str | None]]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
HEADER_STRUCT_SCHEMA: dict[int, _HeaderBlock] = {
|
|
22
|
+
1: {
|
|
23
|
+
"name": "basic_information",
|
|
24
|
+
"fields": [
|
|
25
|
+
("header_block_number", "I1", 1, 1, None),
|
|
26
|
+
("block_length", "I2", 2, 1, None),
|
|
27
|
+
("total_header_blocks", "I2", 2, 1, None),
|
|
28
|
+
("byte_order", "I1", 1, 1, None),
|
|
29
|
+
("satellite_name", "C", 1, 16, None),
|
|
30
|
+
("processing_center_name", "C", 1, 16, None),
|
|
31
|
+
("observation_area", "C", 1, 4, None),
|
|
32
|
+
("other_obs_info", "C", 1, 2, None),
|
|
33
|
+
("obs_timeline", "I2", 2, 1, None),
|
|
34
|
+
("obs_start_time", "R8", 8, 1, None),
|
|
35
|
+
("obs_end_time", "R8", 8, 1, None),
|
|
36
|
+
("file_creation_time", "R8", 8, 1, None),
|
|
37
|
+
("total_header_length", "I4", 4, 1, None),
|
|
38
|
+
("total_data_length", "I4", 4, 1, None),
|
|
39
|
+
("quality_flag_1", "I1", 1, 1, None),
|
|
40
|
+
("quality_flag_2", "I1", 1, 1, None),
|
|
41
|
+
("quality_flag_3", "I1", 1, 1, None),
|
|
42
|
+
("quality_flag_4", "I1", 1, 1, None),
|
|
43
|
+
("file_format_version", "C", 1, 32, None),
|
|
44
|
+
("file_name", "C", 1, 128, None),
|
|
45
|
+
("spare", "C", 40, 1, None),
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
2: {
|
|
49
|
+
"name": "data_information",
|
|
50
|
+
"fields": [
|
|
51
|
+
("header_block_number", "I1", 1, 1, None),
|
|
52
|
+
("block_length", "I2", 2, 1, None),
|
|
53
|
+
("bits_per_pixel", "I2", 2, 1, None),
|
|
54
|
+
("num_columns", "I2", 2, 1, None),
|
|
55
|
+
("num_lines", "I2", 2, 1, None),
|
|
56
|
+
("compression_flag", "I1", 1, 1, None),
|
|
57
|
+
("spare", "C", 40, 1, None),
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
3: {
|
|
61
|
+
"name": "projection_information",
|
|
62
|
+
"fields": [
|
|
63
|
+
("header_block_number", "I1", 1, 1, None),
|
|
64
|
+
("block_length", "I2", 2, 1, None),
|
|
65
|
+
("sub_lon", "R8", 8, 1, None),
|
|
66
|
+
("cfac", "I4", 4, 1, None),
|
|
67
|
+
("lfac", "I4", 4, 1, None),
|
|
68
|
+
("coff", "R4", 4, 1, None),
|
|
69
|
+
("loff", "R4", 4, 1, None),
|
|
70
|
+
("dist_from_earth_center", "R8", 8, 1, None),
|
|
71
|
+
("equatorial_radius", "R8", 8, 1, None),
|
|
72
|
+
("polar_radius", "R8", 8, 1, None),
|
|
73
|
+
("rec_minus_rpol_div_req_sq", "R8", 8, 1, None),
|
|
74
|
+
("rpol_sq_div_req_sq", "R8", 8, 1, None),
|
|
75
|
+
("req_sq_div_rpol_sq", "R8", 8, 1, None),
|
|
76
|
+
("coeff_for_sd", "R8", 8, 1, None),
|
|
77
|
+
("resampling_types", "I2", 2, 1, None),
|
|
78
|
+
("resampling_size", "I2", 2, 1, None),
|
|
79
|
+
("spare", "C", 40, 1, None),
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
4: {
|
|
83
|
+
"name": "navigation_information",
|
|
84
|
+
"fields": [
|
|
85
|
+
("header_block_number", "I1", 1, 1, None),
|
|
86
|
+
("block_length", "I2", 2, 1, None),
|
|
87
|
+
("nav_info_time", "R8", 8, 1, None),
|
|
88
|
+
("ssp_longitude", "R8", 8, 1, None),
|
|
89
|
+
("ssp_latitude", "R8", 8, 1, None),
|
|
90
|
+
("dist_from_earth_center_to_sat", "R8", 8, 1, None),
|
|
91
|
+
("nadir_longitude", "R8", 8, 1, None),
|
|
92
|
+
("nadir_latitude", "R8", 8, 1, None),
|
|
93
|
+
("sun_position", "R8", 8, 3, None),
|
|
94
|
+
("moon_position", "R8", 8, 3, None),
|
|
95
|
+
("spare", "C", 40, 1, None),
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
5: {
|
|
99
|
+
"name": "calibration_information",
|
|
100
|
+
"fields": [
|
|
101
|
+
("header_block_number", "I1", 1, 1, None),
|
|
102
|
+
("block_length", "I2", 2, 1, None),
|
|
103
|
+
("band_number", "I2", 2, 1, None),
|
|
104
|
+
("central_wavelength", "R8", 8, 1, None),
|
|
105
|
+
("valid_bits_per_pixel", "I2", 2, 1, None),
|
|
106
|
+
("count_error_pixels", "I2", 2, 1, None),
|
|
107
|
+
("count_outside_scan_area", "I2", 2, 1, None),
|
|
108
|
+
("gain", "R8", 8, 1, None),
|
|
109
|
+
("constant", "R8", 8, 1, None),
|
|
110
|
+
("c0", "R8", 8, 1, "IR-BANDS"),
|
|
111
|
+
("c1", "R8", 8, 1, "IR-BANDS"),
|
|
112
|
+
("c2", "R8", 8, 1, "IR-BANDS"),
|
|
113
|
+
("C0", "R8", 8, 1, "IR-BANDS"),
|
|
114
|
+
("C1", "R8", 8, 1, "IR-BANDS"),
|
|
115
|
+
("C2", "R8", 8, 1, "IR-BANDS"),
|
|
116
|
+
("speed_of_light", "R8", 8, 1, "IR-BANDS"),
|
|
117
|
+
("planck_constant", "R8", 8, 1, "IR-BANDS"),
|
|
118
|
+
("boltzmann_constant", "R8", 8, 1, "IR-BANDS"),
|
|
119
|
+
("spare", "C", 40, 1, "IR-BANDS"),
|
|
120
|
+
("coeff_c_prime", "R8", 8, 1, "NIR-BANDS"),
|
|
121
|
+
("spare", "C", 104, 1, "NIR-BANDS"),
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
6: {
|
|
125
|
+
"name": "inter_calibration_information",
|
|
126
|
+
"fields": [
|
|
127
|
+
("header_block_number", "I1", 1, 1, None),
|
|
128
|
+
("block_length", "I2", 2, 1, None),
|
|
129
|
+
("gsics_intercept", "R8", 8, 1, None),
|
|
130
|
+
("gsics_slope", "R8", 8, 1, None),
|
|
131
|
+
("gsics_quad", "R8", 8, 1, None),
|
|
132
|
+
("rad_bias_standard", "R8", 8, 1, None),
|
|
133
|
+
("uncert_rad_bias", "R8", 8, 1, None),
|
|
134
|
+
("rad_standard_scene", "R8", 8, 1, None),
|
|
135
|
+
("gsics_validity_start", "R8", 8, 1, None),
|
|
136
|
+
("gsics_validity_end", "R8", 8, 1, None),
|
|
137
|
+
("rad_validity_upper", "R4", 4, 1, None),
|
|
138
|
+
("rad_validity_lower", "R4", 4, 1, None),
|
|
139
|
+
("gsics_file_name", "C", 1, 128, None),
|
|
140
|
+
("spare", "C", 56, 1, None),
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
7: {
|
|
144
|
+
"name": "segment_information",
|
|
145
|
+
"fields": [
|
|
146
|
+
("header_block_number", "I1", 1, 1, None),
|
|
147
|
+
("block_length", "I2", 2, 1, None),
|
|
148
|
+
("total_segments", "I1", 1, 1, None),
|
|
149
|
+
("segment_seq_number", "I1", 1, 1, None),
|
|
150
|
+
("first_line_number", "I2", 2, 1, None),
|
|
151
|
+
("spare", "C", 40, 1, None),
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
8: {
|
|
155
|
+
"name": "navigation_correction_information",
|
|
156
|
+
"fields": [
|
|
157
|
+
("header_block_number", "I1", 1, 1, None),
|
|
158
|
+
("block_length", "I2", 2, 1, None),
|
|
159
|
+
("center_col_rot", "R4", 4, 1, None),
|
|
160
|
+
("center_line_rot", "R4", 4, 1, None),
|
|
161
|
+
("rot_correction", "R8", 8, 1, None),
|
|
162
|
+
("num_corr_data", "I2", 2, 1, None),
|
|
163
|
+
# The following fields are variable and depend on 'num_corr_data'
|
|
164
|
+
# These are not currently parsed
|
|
165
|
+
# ("line_after_rot", "I2", 2, 1, None),
|
|
166
|
+
# ("shift_amount_col", "R4", 4, 1, None),
|
|
167
|
+
# ("shift_amount_line", "R4", 4, 1, None),
|
|
168
|
+
# ("spare", "C", 40, 1, None),
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
9: {
|
|
172
|
+
"name": "observation_time_information",
|
|
173
|
+
"fields": [
|
|
174
|
+
("header_block_number", "I1", 1, 1, None),
|
|
175
|
+
("block_length", "I2", 2, 1, None),
|
|
176
|
+
("num_obs_times", "I2", 2, 1, None),
|
|
177
|
+
# The following fields are variable and depend on 'num_obs_times'
|
|
178
|
+
# These are not currently parsed
|
|
179
|
+
# ("line_number", "I2", 2, 1, None),
|
|
180
|
+
# ("obs_time", "R8", 8, 1, None),
|
|
181
|
+
# ("spare", "C", 40, 1, None),
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
10: {
|
|
185
|
+
"name": "error_information",
|
|
186
|
+
"fields": [
|
|
187
|
+
("header_block_number", "I1", 1, 1, None),
|
|
188
|
+
("block_length", "I4", 4, 1, None),
|
|
189
|
+
("num_error_data", "I2", 2, 1, None),
|
|
190
|
+
# The following fields are variable and depend on 'num_error_data'
|
|
191
|
+
# These are not currently parsed
|
|
192
|
+
# ("line_number", "I2", 2, 1, None),
|
|
193
|
+
# ("num_error_pixels", "I2", 2, 1, None),
|
|
194
|
+
# ("spare", "C", 40, 1, None),
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
11: {
|
|
198
|
+
"name": "spare",
|
|
199
|
+
"fields": [
|
|
200
|
+
("header_block_number", "I1", 1, 1, None),
|
|
201
|
+
("block_length", "I2", 2, 1, None),
|
|
202
|
+
("spare", "C", 256, 1, None),
|
|
203
|
+
],
|
|
204
|
+
},
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def parse_himawari_header(content: bytes) -> dict:
|
|
209
|
+
"""Parse the Himawari header data.
|
|
210
|
+
|
|
211
|
+
Skips variable-length fields and spares.
|
|
212
|
+
"""
|
|
213
|
+
out = {}
|
|
214
|
+
offset = 0
|
|
215
|
+
|
|
216
|
+
# everything is little-endian (see the byte_order field in block #1)
|
|
217
|
+
typ_map = {
|
|
218
|
+
"I1": "B",
|
|
219
|
+
"I2": "H",
|
|
220
|
+
"I4": "I",
|
|
221
|
+
"R4": "f",
|
|
222
|
+
"R8": "d",
|
|
223
|
+
"C": "s",
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for block_num, block_info in HEADER_STRUCT_SCHEMA.items():
|
|
227
|
+
offset_block_start = offset # blocks 8, 9, 10 are dynamic
|
|
228
|
+
block_data: dict[str, Any] = {}
|
|
229
|
+
block_name = block_info["name"]
|
|
230
|
+
fields = block_info["fields"]
|
|
231
|
+
block_length_value: int | None = None
|
|
232
|
+
|
|
233
|
+
for name, typ, size, count, cond in fields:
|
|
234
|
+
if block_num == 5 and cond: # deal with dynamic block 5
|
|
235
|
+
band_number = block_data["band_number"]
|
|
236
|
+
if cond == "IR-BANDS" and band_number <= 6:
|
|
237
|
+
continue
|
|
238
|
+
if cond == "NIR-BANDS" and band_number >= 7:
|
|
239
|
+
continue
|
|
240
|
+
|
|
241
|
+
if name == "spare": # skip spare fields
|
|
242
|
+
offset += size * count
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
fmt = typ_map[typ]
|
|
246
|
+
if typ == "C":
|
|
247
|
+
raw = struct.unpack_from(f"{size * count}s", content, offset)[0]
|
|
248
|
+
value = raw.rstrip(b"\x00").decode("ascii", errors="ignore")
|
|
249
|
+
else:
|
|
250
|
+
value = struct.unpack_from(f"{count}{fmt}", content, offset)
|
|
251
|
+
if count == 1:
|
|
252
|
+
value = value[0]
|
|
253
|
+
|
|
254
|
+
block_data[name] = value
|
|
255
|
+
offset += size * count
|
|
256
|
+
|
|
257
|
+
if name == "block_length":
|
|
258
|
+
block_length_value = value
|
|
259
|
+
|
|
260
|
+
if block_length_value is None:
|
|
261
|
+
raise ValueError(f"Missing block_length in {block_name}")
|
|
262
|
+
offset = offset_block_start + block_length_value # only needed for blocks 8, 9, 10
|
|
263
|
+
|
|
264
|
+
out[block_name] = block_data
|
|
265
|
+
|
|
266
|
+
return out
|