pycontrails 0.58.0__cp314-cp314-win_amd64.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.

Files changed (122) hide show
  1. pycontrails/__init__.py +70 -0
  2. pycontrails/_version.py +34 -0
  3. pycontrails/core/__init__.py +30 -0
  4. pycontrails/core/aircraft_performance.py +679 -0
  5. pycontrails/core/airports.py +228 -0
  6. pycontrails/core/cache.py +889 -0
  7. pycontrails/core/coordinates.py +174 -0
  8. pycontrails/core/fleet.py +483 -0
  9. pycontrails/core/flight.py +2185 -0
  10. pycontrails/core/flightplan.py +228 -0
  11. pycontrails/core/fuel.py +140 -0
  12. pycontrails/core/interpolation.py +702 -0
  13. pycontrails/core/met.py +2931 -0
  14. pycontrails/core/met_var.py +387 -0
  15. pycontrails/core/models.py +1321 -0
  16. pycontrails/core/polygon.py +549 -0
  17. pycontrails/core/rgi_cython.cp314-win_amd64.pyd +0 -0
  18. pycontrails/core/vector.py +2249 -0
  19. pycontrails/datalib/__init__.py +12 -0
  20. pycontrails/datalib/_met_utils/metsource.py +746 -0
  21. pycontrails/datalib/ecmwf/__init__.py +73 -0
  22. pycontrails/datalib/ecmwf/arco_era5.py +345 -0
  23. pycontrails/datalib/ecmwf/common.py +114 -0
  24. pycontrails/datalib/ecmwf/era5.py +554 -0
  25. pycontrails/datalib/ecmwf/era5_model_level.py +490 -0
  26. pycontrails/datalib/ecmwf/hres.py +804 -0
  27. pycontrails/datalib/ecmwf/hres_model_level.py +466 -0
  28. pycontrails/datalib/ecmwf/ifs.py +287 -0
  29. pycontrails/datalib/ecmwf/model_levels.py +435 -0
  30. pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +139 -0
  31. pycontrails/datalib/ecmwf/variables.py +268 -0
  32. pycontrails/datalib/geo_utils.py +261 -0
  33. pycontrails/datalib/gfs/__init__.py +28 -0
  34. pycontrails/datalib/gfs/gfs.py +656 -0
  35. pycontrails/datalib/gfs/variables.py +104 -0
  36. pycontrails/datalib/goes.py +757 -0
  37. pycontrails/datalib/himawari/__init__.py +27 -0
  38. pycontrails/datalib/himawari/header_struct.py +266 -0
  39. pycontrails/datalib/himawari/himawari.py +667 -0
  40. pycontrails/datalib/landsat.py +589 -0
  41. pycontrails/datalib/leo_utils/__init__.py +5 -0
  42. pycontrails/datalib/leo_utils/correction.py +266 -0
  43. pycontrails/datalib/leo_utils/landsat_metadata.py +300 -0
  44. pycontrails/datalib/leo_utils/search.py +250 -0
  45. pycontrails/datalib/leo_utils/sentinel_metadata.py +748 -0
  46. pycontrails/datalib/leo_utils/static/bq_roi_query.sql +6 -0
  47. pycontrails/datalib/leo_utils/vis.py +59 -0
  48. pycontrails/datalib/sentinel.py +650 -0
  49. pycontrails/datalib/spire/__init__.py +5 -0
  50. pycontrails/datalib/spire/exceptions.py +62 -0
  51. pycontrails/datalib/spire/spire.py +604 -0
  52. pycontrails/ext/bada.py +42 -0
  53. pycontrails/ext/cirium.py +14 -0
  54. pycontrails/ext/empirical_grid.py +140 -0
  55. pycontrails/ext/synthetic_flight.py +431 -0
  56. pycontrails/models/__init__.py +1 -0
  57. pycontrails/models/accf.py +425 -0
  58. pycontrails/models/apcemm/__init__.py +8 -0
  59. pycontrails/models/apcemm/apcemm.py +983 -0
  60. pycontrails/models/apcemm/inputs.py +226 -0
  61. pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +183 -0
  62. pycontrails/models/apcemm/utils.py +437 -0
  63. pycontrails/models/cocip/__init__.py +29 -0
  64. pycontrails/models/cocip/cocip.py +2742 -0
  65. pycontrails/models/cocip/cocip_params.py +305 -0
  66. pycontrails/models/cocip/cocip_uncertainty.py +291 -0
  67. pycontrails/models/cocip/contrail_properties.py +1530 -0
  68. pycontrails/models/cocip/output_formats.py +2270 -0
  69. pycontrails/models/cocip/radiative_forcing.py +1260 -0
  70. pycontrails/models/cocip/radiative_heating.py +520 -0
  71. pycontrails/models/cocip/unterstrasser_wake_vortex.py +508 -0
  72. pycontrails/models/cocip/wake_vortex.py +396 -0
  73. pycontrails/models/cocip/wind_shear.py +120 -0
  74. pycontrails/models/cocipgrid/__init__.py +9 -0
  75. pycontrails/models/cocipgrid/cocip_grid.py +2552 -0
  76. pycontrails/models/cocipgrid/cocip_grid_params.py +138 -0
  77. pycontrails/models/dry_advection.py +602 -0
  78. pycontrails/models/emissions/__init__.py +21 -0
  79. pycontrails/models/emissions/black_carbon.py +599 -0
  80. pycontrails/models/emissions/emissions.py +1353 -0
  81. pycontrails/models/emissions/ffm2.py +336 -0
  82. pycontrails/models/emissions/static/default-engine-uids.csv +239 -0
  83. pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +596 -0
  84. pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +215 -0
  85. pycontrails/models/extended_k15.py +1327 -0
  86. pycontrails/models/humidity_scaling/__init__.py +37 -0
  87. pycontrails/models/humidity_scaling/humidity_scaling.py +1075 -0
  88. pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
  89. pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
  90. pycontrails/models/issr.py +210 -0
  91. pycontrails/models/pcc.py +326 -0
  92. pycontrails/models/pcr.py +154 -0
  93. pycontrails/models/ps_model/__init__.py +18 -0
  94. pycontrails/models/ps_model/ps_aircraft_params.py +381 -0
  95. pycontrails/models/ps_model/ps_grid.py +701 -0
  96. pycontrails/models/ps_model/ps_model.py +1000 -0
  97. pycontrails/models/ps_model/ps_operational_limits.py +525 -0
  98. pycontrails/models/ps_model/static/ps-aircraft-params-20250328.csv +69 -0
  99. pycontrails/models/ps_model/static/ps-synonym-list-20250328.csv +104 -0
  100. pycontrails/models/sac.py +442 -0
  101. pycontrails/models/tau_cirrus.py +183 -0
  102. pycontrails/physics/__init__.py +1 -0
  103. pycontrails/physics/constants.py +117 -0
  104. pycontrails/physics/geo.py +1138 -0
  105. pycontrails/physics/jet.py +968 -0
  106. pycontrails/physics/static/iata-cargo-load-factors-20250221.csv +74 -0
  107. pycontrails/physics/static/iata-passenger-load-factors-20250221.csv +74 -0
  108. pycontrails/physics/thermo.py +551 -0
  109. pycontrails/physics/units.py +472 -0
  110. pycontrails/py.typed +0 -0
  111. pycontrails/utils/__init__.py +1 -0
  112. pycontrails/utils/dependencies.py +66 -0
  113. pycontrails/utils/iteration.py +13 -0
  114. pycontrails/utils/json.py +187 -0
  115. pycontrails/utils/temp.py +50 -0
  116. pycontrails/utils/types.py +163 -0
  117. pycontrails-0.58.0.dist-info/METADATA +180 -0
  118. pycontrails-0.58.0.dist-info/RECORD +122 -0
  119. pycontrails-0.58.0.dist-info/WHEEL +5 -0
  120. pycontrails-0.58.0.dist-info/licenses/LICENSE +178 -0
  121. pycontrails-0.58.0.dist-info/licenses/NOTICE +43 -0
  122. pycontrails-0.58.0.dist-info/top_level.txt +3 -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[str, dict[str, Any]]:
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