hyplan 1.6.2__py3-none-any.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.
- hyplan/__init__.py +257 -0
- hyplan/_auth.py +50 -0
- hyplan/_trochoid_solver.py +669 -0
- hyplan/_version.py +24 -0
- hyplan/aircraft/__init__.py +102 -0
- hyplan/aircraft/_base.py +2265 -0
- hyplan/aircraft/_models.py +2577 -0
- hyplan/aircraft/_planned_sortie.py +829 -0
- hyplan/aircraft/adsb/__init__.py +35 -0
- hyplan/aircraft/adsb/airdata.py +209 -0
- hyplan/aircraft/adsb/fitting.py +434 -0
- hyplan/aircraft/adsb/io.py +205 -0
- hyplan/aircraft/adsb/models.py +155 -0
- hyplan/aircraft/adsb/phases.py +218 -0
- hyplan/aircraft/adsb/pipeline.py +195 -0
- hyplan/aircraft/adsb/priors.py +42 -0
- hyplan/aircraft/eol_ncar.py +55 -0
- hyplan/aircraft/icartt.py +332 -0
- hyplan/aircraft/iwg1.py +376 -0
- hyplan/aircraft/wind_path.py +202 -0
- hyplan/airports.py +521 -0
- hyplan/airspace.py +1970 -0
- hyplan/atmosphere.py +170 -0
- hyplan/campaign.py +829 -0
- hyplan/clouds/__init__.py +57 -0
- hyplan/clouds/analysis.py +175 -0
- hyplan/clouds/forecast.py +185 -0
- hyplan/clouds/plotting.py +327 -0
- hyplan/clouds/sources.py +574 -0
- hyplan/data/__init__.py +7 -0
- hyplan/data/de421.bsp +0 -0
- hyplan/data/faa_radar_exclusion_zones.geojson +26044 -0
- hyplan/download.py +45 -0
- hyplan/dubins3d.py +702 -0
- hyplan/exceptions.py +49 -0
- hyplan/exports/__init__.py +49 -0
- hyplan/exports/_common.py +191 -0
- hyplan/exports/csv.py +159 -0
- hyplan/exports/excel.py +323 -0
- hyplan/exports/gpx.py +54 -0
- hyplan/exports/icartt.py +180 -0
- hyplan/exports/kml.py +101 -0
- hyplan/exports/text.py +172 -0
- hyplan/flight_box.py +708 -0
- hyplan/flight_line.py +807 -0
- hyplan/flight_optimizer.py +931 -0
- hyplan/flight_patterns.py +797 -0
- hyplan/flight_plan.py +18 -0
- hyplan/geometry.py +852 -0
- hyplan/glint.py +795 -0
- hyplan/instruments/__init__.py +76 -0
- hyplan/instruments/_base.py +77 -0
- hyplan/instruments/awp.py +978 -0
- hyplan/instruments/frame_camera.py +853 -0
- hyplan/instruments/line_scanner.py +323 -0
- hyplan/instruments/lvis.py +937 -0
- hyplan/instruments/profilinglidar.py +294 -0
- hyplan/instruments/radar.py +396 -0
- hyplan/pattern.py +399 -0
- hyplan/phenology/__init__.py +39 -0
- hyplan/phenology/_appeears.py +223 -0
- hyplan/phenology/_qa.py +147 -0
- hyplan/phenology/analysis.py +125 -0
- hyplan/phenology/plotting.py +391 -0
- hyplan/phenology/sources.py +942 -0
- hyplan/planning/__init__.py +30 -0
- hyplan/planning/engine.py +554 -0
- hyplan/planning/isochrone.py +2915 -0
- hyplan/planning/segments.py +360 -0
- hyplan/plotting.py +1279 -0
- hyplan/py.typed +0 -0
- hyplan/satellites.py +884 -0
- hyplan/sun.py +412 -0
- hyplan/swath.py +295 -0
- hyplan/terrain/__init__.py +99 -0
- hyplan/terrain/_demgrid.py +42 -0
- hyplan/terrain/elevation.py +138 -0
- hyplan/terrain/intersection.py +237 -0
- hyplan/terrain/io.py +292 -0
- hyplan/units.py +176 -0
- hyplan/waypoint.py +208 -0
- hyplan/winds/__init__.py +82 -0
- hyplan/winds/base.py +38 -0
- hyplan/winds/factory.py +136 -0
- hyplan/winds/gridded.py +297 -0
- hyplan/winds/providers/__init__.py +8 -0
- hyplan/winds/providers/gfs.py +262 -0
- hyplan/winds/providers/gmao.py +87 -0
- hyplan/winds/providers/iwg1_trace.py +83 -0
- hyplan/winds/providers/merra2.py +91 -0
- hyplan/winds/simple.py +58 -0
- hyplan/winds/utils.py +358 -0
- hyplan-1.6.2.dist-info/METADATA +466 -0
- hyplan-1.6.2.dist-info/RECORD +97 -0
- hyplan-1.6.2.dist-info/WHEEL +5 -0
- hyplan-1.6.2.dist-info/licenses/LICENSE.md +250 -0
- hyplan-1.6.2.dist-info/top_level.txt +1 -0
hyplan/__init__.py
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HyPlan - Planning software for airborne remote sensing science campaigns.
|
|
3
|
+
|
|
4
|
+
Core objects are re-exported here for convenience::
|
|
5
|
+
|
|
6
|
+
from hyplan import FlightLine, FlightBox, Airport, ureg
|
|
7
|
+
from hyplan import KingAirB200, AVIRIS3
|
|
8
|
+
|
|
9
|
+
Specialized modules (clouds, terrain, satellites, glint, sun) should be
|
|
10
|
+
imported directly::
|
|
11
|
+
|
|
12
|
+
from hyplan.clouds import create_cloud_data_array_with_limit
|
|
13
|
+
from hyplan.terrain import download_dem
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
from ._version import version as __version__
|
|
18
|
+
except ImportError:
|
|
19
|
+
# Package not installed via setuptools-scm (e.g. editable dev install
|
|
20
|
+
# before first build), fall back to a default.
|
|
21
|
+
__version__ = "0.0.0.dev0"
|
|
22
|
+
|
|
23
|
+
import logging as _logging
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def setup_logging(
|
|
27
|
+
level: int = _logging.INFO,
|
|
28
|
+
format: str = "%(asctime)s %(name)s %(levelname)s: %(message)s",
|
|
29
|
+
) -> None:
|
|
30
|
+
"""Attach a StreamHandler to the ``hyplan`` logger.
|
|
31
|
+
|
|
32
|
+
Library code uses ``logging.getLogger(__name__)`` everywhere and never
|
|
33
|
+
configures handlers itself. Call this once from a notebook, script, or
|
|
34
|
+
CLI to see hyplan's INFO/WARNING messages. Idempotent — re-calling
|
|
35
|
+
replaces the handler instead of stacking duplicates.
|
|
36
|
+
"""
|
|
37
|
+
logger = _logging.getLogger("hyplan")
|
|
38
|
+
for h in list(logger.handlers):
|
|
39
|
+
if getattr(h, "_hyplan_managed", False):
|
|
40
|
+
logger.removeHandler(h)
|
|
41
|
+
handler = _logging.StreamHandler()
|
|
42
|
+
handler.setFormatter(_logging.Formatter(format))
|
|
43
|
+
handler._hyplan_managed = True # type: ignore[attr-defined] # custom attr on logging.Handler
|
|
44
|
+
logger.addHandler(handler)
|
|
45
|
+
logger.setLevel(level)
|
|
46
|
+
logger.propagate = False
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# --- Core re-exports ---
|
|
50
|
+
|
|
51
|
+
# Exceptions
|
|
52
|
+
from .exceptions import (
|
|
53
|
+
HyPlanError,
|
|
54
|
+
HyPlanValueError,
|
|
55
|
+
HyPlanTypeError,
|
|
56
|
+
HyPlanRuntimeError,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Units
|
|
60
|
+
from .units import ureg, convert_distance, convert_speed, convert_angle, convert_time, altitude_to_flight_level
|
|
61
|
+
|
|
62
|
+
# Flight geometry
|
|
63
|
+
from .flight_line import FlightLine
|
|
64
|
+
from .pattern import Pattern
|
|
65
|
+
from .flight_box import box_around_center_line, box_around_polygon, box_around_center_terrain, box_around_polygon_terrain, altitude_msl_for_pixel_size
|
|
66
|
+
|
|
67
|
+
# Aircraft
|
|
68
|
+
from .aircraft import (
|
|
69
|
+
Aircraft,
|
|
70
|
+
NASA_ER2,
|
|
71
|
+
NASA_GIII,
|
|
72
|
+
NASA_GIV,
|
|
73
|
+
NASA_GV,
|
|
74
|
+
NASA_C20A,
|
|
75
|
+
NASA_P3,
|
|
76
|
+
NOAA_WP3D,
|
|
77
|
+
NOAA_GIV,
|
|
78
|
+
NASA_WB57,
|
|
79
|
+
NASA_B777,
|
|
80
|
+
KingAirB200,
|
|
81
|
+
KingAirA90,
|
|
82
|
+
KingAir350,
|
|
83
|
+
NASA_C130,
|
|
84
|
+
NOAA_TwinOtter,
|
|
85
|
+
BAS_TwinOtter,
|
|
86
|
+
FAAM_BAe146,
|
|
87
|
+
SAFIRE_ATR42,
|
|
88
|
+
NERC_DO228,
|
|
89
|
+
AWI_BaslerBT67,
|
|
90
|
+
DLR_HALO,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Airports
|
|
94
|
+
from .airports import (
|
|
95
|
+
Airport,
|
|
96
|
+
initialize_data,
|
|
97
|
+
find_nearest_airport,
|
|
98
|
+
find_nearest_airports,
|
|
99
|
+
airports_within_radius,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Sensors
|
|
103
|
+
from .instruments import (
|
|
104
|
+
Sensor,
|
|
105
|
+
LineScanner,
|
|
106
|
+
AVIRISClassic,
|
|
107
|
+
AVIRISNextGen,
|
|
108
|
+
AVIRIS3,
|
|
109
|
+
AVIRIS5,
|
|
110
|
+
HyTES,
|
|
111
|
+
PRISM,
|
|
112
|
+
MASTER,
|
|
113
|
+
GLiHT_VNIR,
|
|
114
|
+
GLiHT_Thermal,
|
|
115
|
+
GLiHT_SIF,
|
|
116
|
+
GCAS_UV_Vis,
|
|
117
|
+
GCAS_VNIR,
|
|
118
|
+
eMAS,
|
|
119
|
+
PICARD,
|
|
120
|
+
SENSOR_REGISTRY,
|
|
121
|
+
create_sensor,
|
|
122
|
+
FrameCamera,
|
|
123
|
+
MultiCameraRig,
|
|
124
|
+
LVISLens,
|
|
125
|
+
LVIS_LENS_NARROW,
|
|
126
|
+
LVIS_LENS_MEDIUM,
|
|
127
|
+
LVIS_LENS_WIDE,
|
|
128
|
+
LVIS_LENSES,
|
|
129
|
+
LVIS,
|
|
130
|
+
AerosolWindProfiler,
|
|
131
|
+
flag_awp_stable_segments,
|
|
132
|
+
awp_profile_locations_for_flight_line,
|
|
133
|
+
awp_profile_locations_for_plan,
|
|
134
|
+
ProfilingLidar,
|
|
135
|
+
HSRL2,
|
|
136
|
+
HALO,
|
|
137
|
+
CPL,
|
|
138
|
+
RadarExclusionConflict,
|
|
139
|
+
check_lband_radar_exclusions,
|
|
140
|
+
SidelookingRadar,
|
|
141
|
+
UAVSAR_Lband,
|
|
142
|
+
UAVSAR_Pband,
|
|
143
|
+
UAVSAR_Kaband,
|
|
144
|
+
)
|
|
145
|
+
# Waypoint and Dubins path planning
|
|
146
|
+
from .waypoint import Waypoint
|
|
147
|
+
from .dubins3d import DubinsPath2D
|
|
148
|
+
|
|
149
|
+
# Swath
|
|
150
|
+
from .swath import generate_swath_polygon, calculate_swath_widths, analyze_swath_gaps_overlaps
|
|
151
|
+
|
|
152
|
+
# Flight patterns
|
|
153
|
+
from .flight_patterns import racetrack, rosette, polygon, sawtooth, spiral, flight_lines_to_waypoint_path, coordinated_line
|
|
154
|
+
|
|
155
|
+
# Flight planning and optimization
|
|
156
|
+
from .planning import compute_flight_plan, compute_isochrone, compute_concentric_isochrones, compute_refuel_isochrone, evaluate_target_reachability, isochrone_polygon, plot_isochrone
|
|
157
|
+
|
|
158
|
+
# Wind fields
|
|
159
|
+
from .winds import WindField, StillAirField, ConstantWindField, MERRA2WindField, GMAOWindField, GFSWindField, wind_field_from_plan
|
|
160
|
+
from .flight_optimizer import build_graph, greedy_optimize
|
|
161
|
+
|
|
162
|
+
# Plotting
|
|
163
|
+
from .plotting import (
|
|
164
|
+
map_flight_lines, plot_flight_plan, plot_altitude_trajectory,
|
|
165
|
+
terrain_profile_along_track,
|
|
166
|
+
plot_airspace_map, plot_isochrone_static,
|
|
167
|
+
plot_oceanic_tracks, plot_vertical_profile,
|
|
168
|
+
plot_conflict_matrix, map_airspace,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Exports
|
|
172
|
+
from .exports import (
|
|
173
|
+
to_excel, to_pilot_excel, to_foreflight_csv,
|
|
174
|
+
to_honeywell_fms, to_er2_csv, to_icartt,
|
|
175
|
+
to_kml, to_gpx, to_txt,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# Airspace
|
|
179
|
+
from .airspace import (
|
|
180
|
+
Airspace, AirspaceConflict, OpenAIPClient,
|
|
181
|
+
check_airspace_conflicts, check_airspace_proximity,
|
|
182
|
+
fetch_and_check, clear_airspace_cache,
|
|
183
|
+
classify_severity, FAATFRClient, NASRAirspaceSource,
|
|
184
|
+
convert_agl_floors, filter_by_schedule,
|
|
185
|
+
summarize_airspaces,
|
|
186
|
+
OceanicTrack, FlightPlanDBClient,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Campaign
|
|
190
|
+
from .campaign import Campaign
|
|
191
|
+
|
|
192
|
+
__all__ = [
|
|
193
|
+
# Logging
|
|
194
|
+
"setup_logging",
|
|
195
|
+
# Exceptions
|
|
196
|
+
"HyPlanError", "HyPlanValueError", "HyPlanTypeError", "HyPlanRuntimeError",
|
|
197
|
+
# Units
|
|
198
|
+
"ureg", "convert_distance", "convert_speed", "convert_angle", "convert_time", "altitude_to_flight_level",
|
|
199
|
+
# Flight geometry
|
|
200
|
+
"FlightLine", "Pattern", "box_around_center_line", "box_around_polygon", "box_around_center_terrain", "box_around_polygon_terrain", "altitude_msl_for_pixel_size",
|
|
201
|
+
# Aircraft
|
|
202
|
+
"Aircraft",
|
|
203
|
+
"NASA_ER2", "NASA_GIII", "NASA_GIV", "NASA_GV", "NASA_C20A", "NASA_P3", "NOAA_WP3D", "NOAA_GIV",
|
|
204
|
+
"NASA_WB57", "NASA_B777",
|
|
205
|
+
"KingAirB200", "KingAirA90", "KingAir350",
|
|
206
|
+
"NASA_C130", "NOAA_TwinOtter",
|
|
207
|
+
"BAS_TwinOtter", "FAAM_BAe146", "SAFIRE_ATR42", "NERC_DO228", "AWI_BaslerBT67", "DLR_HALO",
|
|
208
|
+
# Airports
|
|
209
|
+
"Airport", "initialize_data",
|
|
210
|
+
"find_nearest_airport", "find_nearest_airports", "airports_within_radius",
|
|
211
|
+
# Sensors
|
|
212
|
+
"Sensor", "LineScanner",
|
|
213
|
+
"AVIRISClassic", "AVIRISNextGen", "AVIRIS3", "AVIRIS5",
|
|
214
|
+
"HyTES", "PRISM", "MASTER",
|
|
215
|
+
"GLiHT_VNIR", "GLiHT_Thermal", "GLiHT_SIF",
|
|
216
|
+
"GCAS_UV_Vis", "GCAS_VNIR", "eMAS", "PICARD",
|
|
217
|
+
"SENSOR_REGISTRY", "create_sensor",
|
|
218
|
+
"FrameCamera", "MultiCameraRig",
|
|
219
|
+
"LVISLens", "LVIS_LENS_NARROW", "LVIS_LENS_MEDIUM", "LVIS_LENS_WIDE", "LVIS_LENSES", "LVIS",
|
|
220
|
+
"AerosolWindProfiler", "ProfilingLidar", "HSRL2", "HALO", "CPL",
|
|
221
|
+
"RadarExclusionConflict", "check_lband_radar_exclusions",
|
|
222
|
+
"SidelookingRadar", "UAVSAR_Lband", "UAVSAR_Pband", "UAVSAR_Kaband",
|
|
223
|
+
# Dubins
|
|
224
|
+
"Waypoint", "DubinsPath2D",
|
|
225
|
+
# Swath
|
|
226
|
+
"generate_swath_polygon", "calculate_swath_widths", "analyze_swath_gaps_overlaps",
|
|
227
|
+
# AWP profiling
|
|
228
|
+
"flag_awp_stable_segments", "awp_profile_locations_for_flight_line", "awp_profile_locations_for_plan",
|
|
229
|
+
# Flight patterns
|
|
230
|
+
"racetrack", "rosette", "polygon", "sawtooth", "spiral", "flight_lines_to_waypoint_path",
|
|
231
|
+
"coordinated_line",
|
|
232
|
+
# Wind
|
|
233
|
+
"WindField", "StillAirField", "ConstantWindField", "MERRA2WindField", "GMAOWindField", "GFSWindField", "wind_field_from_plan",
|
|
234
|
+
# Flight planning
|
|
235
|
+
"compute_flight_plan", "plot_flight_plan", "plot_altitude_trajectory",
|
|
236
|
+
"compute_isochrone", "compute_concentric_isochrones", "compute_refuel_isochrone", "evaluate_target_reachability", "isochrone_polygon", "plot_isochrone",
|
|
237
|
+
"build_graph", "greedy_optimize",
|
|
238
|
+
# Plotting
|
|
239
|
+
"map_flight_lines", "terrain_profile_along_track",
|
|
240
|
+
"plot_airspace_map", "plot_isochrone_static",
|
|
241
|
+
"plot_oceanic_tracks", "plot_vertical_profile",
|
|
242
|
+
"plot_conflict_matrix", "map_airspace",
|
|
243
|
+
# Exports
|
|
244
|
+
"to_excel", "to_pilot_excel", "to_foreflight_csv",
|
|
245
|
+
"to_honeywell_fms", "to_er2_csv", "to_icartt",
|
|
246
|
+
"to_kml", "to_gpx", "to_txt",
|
|
247
|
+
# Airspace
|
|
248
|
+
"Airspace", "AirspaceConflict", "OpenAIPClient",
|
|
249
|
+
"check_airspace_conflicts", "check_airspace_proximity",
|
|
250
|
+
"fetch_and_check", "clear_airspace_cache",
|
|
251
|
+
"classify_severity", "FAATFRClient", "NASRAirspaceSource",
|
|
252
|
+
"convert_agl_floors", "filter_by_schedule",
|
|
253
|
+
"summarize_airspaces",
|
|
254
|
+
"OceanicTrack", "FlightPlanDBClient",
|
|
255
|
+
# Campaign
|
|
256
|
+
"Campaign",
|
|
257
|
+
]
|
hyplan/_auth.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Shared NASA Earthdata authentication utilities."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from .exceptions import HyPlanRuntimeError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _require_earthaccess() -> Any:
|
|
11
|
+
"""Import and return earthaccess, raising a clear error if not installed."""
|
|
12
|
+
try:
|
|
13
|
+
import earthaccess
|
|
14
|
+
|
|
15
|
+
return earthaccess
|
|
16
|
+
except ImportError:
|
|
17
|
+
raise HyPlanRuntimeError(
|
|
18
|
+
"earthaccess is required for NASA Earthdata authentication. "
|
|
19
|
+
"Install with: pip install earthaccess"
|
|
20
|
+
) from None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _earthdata_login() -> Any:
|
|
24
|
+
"""Authenticate with NASA Earthdata using ``earthaccess``.
|
|
25
|
+
|
|
26
|
+
Tries strategies in order: ``EARTHDATA_TOKEN`` env var, ``~/.netrc``,
|
|
27
|
+
then interactive prompt. Returns an authenticated ``requests.Session``
|
|
28
|
+
with a bearer token suitable for OPeNDAP access.
|
|
29
|
+
|
|
30
|
+
Raises :class:`~hyplan.exceptions.HyPlanRuntimeError` if ``earthaccess``
|
|
31
|
+
is not installed or login fails.
|
|
32
|
+
"""
|
|
33
|
+
earthaccess = _require_earthaccess()
|
|
34
|
+
|
|
35
|
+
# Try non-interactive strategies first
|
|
36
|
+
for strategy in ("environment", "netrc"):
|
|
37
|
+
try:
|
|
38
|
+
auth = earthaccess.login(strategy=strategy)
|
|
39
|
+
if auth.authenticated:
|
|
40
|
+
return earthaccess.get_requests_https_session()
|
|
41
|
+
except Exception:
|
|
42
|
+
continue
|
|
43
|
+
|
|
44
|
+
raise HyPlanRuntimeError(
|
|
45
|
+
"NASA Earthdata login failed. Authenticate via one of:\n"
|
|
46
|
+
" 1. Set EARTHDATA_TOKEN environment variable\n"
|
|
47
|
+
" 2. Add to ~/.netrc:\n"
|
|
48
|
+
" machine urs.earthdata.nasa.gov login <user> password <pass>\n"
|
|
49
|
+
"Register at https://urs.earthdata.nasa.gov if needed."
|
|
50
|
+
)
|