aeronavx 0.3.1__tar.gz
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.
- aeronavx-0.3.1/LICENSE +21 -0
- aeronavx-0.3.1/PKG-INFO +196 -0
- aeronavx-0.3.1/README.md +150 -0
- aeronavx-0.3.1/aeronavx/__init__.py +69 -0
- aeronavx-0.3.1/aeronavx/api/__init__.py +3 -0
- aeronavx-0.3.1/aeronavx/api/server.py +180 -0
- aeronavx-0.3.1/aeronavx/cli/__init__.py +3 -0
- aeronavx-0.3.1/aeronavx/cli/main.py +221 -0
- aeronavx-0.3.1/aeronavx/core/__init__.py +97 -0
- aeronavx-0.3.1/aeronavx/core/airports.py +49 -0
- aeronavx-0.3.1/aeronavx/core/analytics.py +137 -0
- aeronavx-0.3.1/aeronavx/core/distance.py +167 -0
- aeronavx-0.3.1/aeronavx/core/emissions.py +96 -0
- aeronavx-0.3.1/aeronavx/core/geodesy.py +113 -0
- aeronavx-0.3.1/aeronavx/core/loader.py +281 -0
- aeronavx-0.3.1/aeronavx/core/routing.py +179 -0
- aeronavx-0.3.1/aeronavx/core/search.py +173 -0
- aeronavx-0.3.1/aeronavx/core/timezone.py +94 -0
- aeronavx-0.3.1/aeronavx/core/weather.py +97 -0
- aeronavx-0.3.1/aeronavx/data/airports.csv +84226 -0
- aeronavx-0.3.1/aeronavx/data/airports_minimal.csv +11 -0
- aeronavx-0.3.1/aeronavx/exceptions.py +22 -0
- aeronavx-0.3.1/aeronavx/models/__init__.py +3 -0
- aeronavx-0.3.1/aeronavx/models/airport.py +63 -0
- aeronavx-0.3.1/aeronavx/utils/__init__.py +54 -0
- aeronavx-0.3.1/aeronavx/utils/cache.py +27 -0
- aeronavx-0.3.1/aeronavx/utils/constants.py +30 -0
- aeronavx-0.3.1/aeronavx/utils/logging.py +34 -0
- aeronavx-0.3.1/aeronavx/utils/spatial_index.py +115 -0
- aeronavx-0.3.1/aeronavx/utils/units.py +86 -0
- aeronavx-0.3.1/aeronavx/utils/validators.py +31 -0
- aeronavx-0.3.1/aeronavx.egg-info/PKG-INFO +196 -0
- aeronavx-0.3.1/aeronavx.egg-info/SOURCES.txt +40 -0
- aeronavx-0.3.1/aeronavx.egg-info/dependency_links.txt +1 -0
- aeronavx-0.3.1/aeronavx.egg-info/entry_points.txt +2 -0
- aeronavx-0.3.1/aeronavx.egg-info/requires.txt +26 -0
- aeronavx-0.3.1/aeronavx.egg-info/top_level.txt +1 -0
- aeronavx-0.3.1/pyproject.toml +91 -0
- aeronavx-0.3.1/setup.cfg +4 -0
- aeronavx-0.3.1/tests/test_distance.py +58 -0
- aeronavx-0.3.1/tests/test_geodesy.py +67 -0
- aeronavx-0.3.1/tests/test_validators.py +54 -0
aeronavx-0.3.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Tefik Yildiz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
aeronavx-0.3.1/PKG-INFO
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aeronavx
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Production-grade airport data and flight geometry library
|
|
5
|
+
Author-email: Teyfik OZ <teyfikoz@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/teyfikoz/AeroNavX
|
|
8
|
+
Project-URL: Repository, https://github.com/teyfikoz/AeroNavX
|
|
9
|
+
Project-URL: Documentation, https://github.com/teyfikoz/AeroNavX/docs
|
|
10
|
+
Project-URL: Issues, https://github.com/teyfikoz/AeroNavX/issues
|
|
11
|
+
Keywords: airport,aviation,geodesy,geography,distance,routing
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
26
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
28
|
+
Provides-Extra: full
|
|
29
|
+
Requires-Dist: pandas>=2.0; extra == "full"
|
|
30
|
+
Requires-Dist: scipy>=1.10; extra == "full"
|
|
31
|
+
Requires-Dist: rapidfuzz>=3.0; extra == "full"
|
|
32
|
+
Requires-Dist: timezonefinder>=6.0; extra == "full"
|
|
33
|
+
Requires-Dist: requests>=2.31; extra == "full"
|
|
34
|
+
Provides-Extra: api
|
|
35
|
+
Requires-Dist: fastapi>=0.104; extra == "api"
|
|
36
|
+
Requires-Dist: uvicorn[standard]>=0.24; extra == "api"
|
|
37
|
+
Provides-Extra: all
|
|
38
|
+
Requires-Dist: pandas>=2.0; extra == "all"
|
|
39
|
+
Requires-Dist: scipy>=1.10; extra == "all"
|
|
40
|
+
Requires-Dist: rapidfuzz>=3.0; extra == "all"
|
|
41
|
+
Requires-Dist: timezonefinder>=6.0; extra == "all"
|
|
42
|
+
Requires-Dist: requests>=2.31; extra == "all"
|
|
43
|
+
Requires-Dist: fastapi>=0.104; extra == "all"
|
|
44
|
+
Requires-Dist: uvicorn[standard]>=0.24; extra == "all"
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
|
|
47
|
+
# AeroNavX
|
|
48
|
+
|
|
49
|
+
A production-grade Python library for airport data and flight geometry calculations.
|
|
50
|
+
|
|
51
|
+
**🆕 v0.2.0:** Now with **84,000+ airports** from [OurAirports](https://ourairports.com) (MIT License)
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- 🛫 **Airport Database**: 84,000+ global airports with efficient IATA/ICAO indexing
|
|
56
|
+
- 📏 **Distance Calculations**: Haversine, Vincenty, and Spherical Law of Cosines
|
|
57
|
+
- 🌍 **Geodesy**: Bearings, midpoints, great circle paths
|
|
58
|
+
- 🔍 **Search**: Fuzzy name search, nearest neighbor queries, radius search
|
|
59
|
+
- 🛤️ **Routing**: Multi-segment routes, flight time estimation, shortest paths
|
|
60
|
+
- 📊 **Analytics**: Statistics by country, continent, type, and elevation
|
|
61
|
+
- ⏰ **Timezone Support**: Automatic timezone detection and local time
|
|
62
|
+
- 🌱 **Emissions**: CO2 emissions estimation per passenger
|
|
63
|
+
- 🌤️ **Weather**: METAR and TAF data fetching
|
|
64
|
+
- 💻 **CLI**: Command-line interface for quick queries
|
|
65
|
+
- 🌐 **REST API**: FastAPI-based web service
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install aeronavx
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Or from source:**
|
|
74
|
+
```bash
|
|
75
|
+
git clone https://github.com/teyfikoz/AeroNavX.git
|
|
76
|
+
cd AeroNavX
|
|
77
|
+
pip install -e .
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import aeronavx
|
|
84
|
+
|
|
85
|
+
# Get airports
|
|
86
|
+
ist = aeronavx.get_airport("IST")
|
|
87
|
+
jfk = aeronavx.get_airport("JFK")
|
|
88
|
+
|
|
89
|
+
# Calculate distance
|
|
90
|
+
dist_km = ist.distance_to(jfk)
|
|
91
|
+
print(f"Distance: {dist_km:.2f} km")
|
|
92
|
+
|
|
93
|
+
# Find nearest airports
|
|
94
|
+
nearest = aeronavx.nearest_airport(41.0, 29.0, n=5)
|
|
95
|
+
|
|
96
|
+
# Estimate emissions
|
|
97
|
+
co2 = aeronavx.estimate_co2_kg_for_segment("IST", "JFK")
|
|
98
|
+
print(f"CO2: {co2:.2f} kg per passenger")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Advanced: Filtering Airports
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from aeronavx.core import loader
|
|
105
|
+
|
|
106
|
+
# Load only major airports (large + medium with scheduled service)
|
|
107
|
+
major_airports = loader.load_airports(
|
|
108
|
+
include_types=['large_airport', 'medium_airport'],
|
|
109
|
+
scheduled_service_only=True
|
|
110
|
+
)
|
|
111
|
+
print(f"Major airports: {len(major_airports):,}") # ~3,200
|
|
112
|
+
|
|
113
|
+
# Load specific countries
|
|
114
|
+
us_airports = loader.load_airports(countries=['US'])
|
|
115
|
+
print(f"US airports: {len(us_airports):,}") # ~20,000
|
|
116
|
+
|
|
117
|
+
# Load airports with IATA codes only
|
|
118
|
+
iata_airports = loader.load_airports(has_iata_only=True)
|
|
119
|
+
print(f"IATA airports: {len(iata_airports):,}") # ~9,000
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## CLI Usage
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Calculate distance
|
|
126
|
+
aeronavx distance --from IST --to JFK --unit nmi
|
|
127
|
+
|
|
128
|
+
# Find nearest airports
|
|
129
|
+
aeronavx nearest --lat 41.0 --lon 29.0 --n 5
|
|
130
|
+
|
|
131
|
+
# Search by name
|
|
132
|
+
aeronavx search --name "Heathrow"
|
|
133
|
+
|
|
134
|
+
# Estimate emissions
|
|
135
|
+
aeronavx emissions --from IST --to LHR
|
|
136
|
+
|
|
137
|
+
# Flight time
|
|
138
|
+
aeronavx flight-time --from IST --to JFK
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## API Server
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
python -m aeronavx.api.server
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Then access:
|
|
148
|
+
- http://localhost:8000/health
|
|
149
|
+
- http://localhost:8000/airport/IST
|
|
150
|
+
- http://localhost:8000/distance?from=IST&to=JFK
|
|
151
|
+
- http://localhost:8000/nearest?lat=41.0&lon=29.0&n=5
|
|
152
|
+
|
|
153
|
+
## Data
|
|
154
|
+
|
|
155
|
+
AeroNavX includes **84,000+ airports** from [OurAirports](https://ourairports.com/data/), which provides:
|
|
156
|
+
- ✅ **Global Coverage**: Airports, heliports, seaplane bases, and more
|
|
157
|
+
- ✅ **MIT License**: Free to use commercially
|
|
158
|
+
- ✅ **Regular Updates**: Community-maintained and updated
|
|
159
|
+
- ✅ **Comprehensive Data**: IATA/ICAO codes, coordinates, types, and more
|
|
160
|
+
|
|
161
|
+
**Data Attribution:**
|
|
162
|
+
Airport data from [OurAirports](https://ourairports.com) (David Megginson et al.) - Licensed under [MIT License](https://github.com/davidmegginson/ourairports-data)
|
|
163
|
+
|
|
164
|
+
## Examples
|
|
165
|
+
|
|
166
|
+
See `examples/` directory for:
|
|
167
|
+
- `basic_distance.py`: Distance calculations
|
|
168
|
+
- `nearest_airports.py`: Finding nearby airports
|
|
169
|
+
- `routing_example.py`: Multi-segment routes
|
|
170
|
+
- `emissions_example.py`: CO2 estimation
|
|
171
|
+
|
|
172
|
+
## Testing
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
pytest
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Dependencies
|
|
179
|
+
|
|
180
|
+
**Required**: Python >= 3.10
|
|
181
|
+
|
|
182
|
+
**Optional**:
|
|
183
|
+
- `pandas`: DataFrame support
|
|
184
|
+
- `scipy`: Faster spatial indexing
|
|
185
|
+
- `rapidfuzz`: Better fuzzy search
|
|
186
|
+
- `timezonefinder`: Timezone support
|
|
187
|
+
- `fastapi`, `uvicorn`: API server
|
|
188
|
+
- `requests`: Weather data
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT License
|
|
193
|
+
|
|
194
|
+
## Contributing
|
|
195
|
+
|
|
196
|
+
Contributions welcome! Please open an issue or pull request.
|
aeronavx-0.3.1/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# AeroNavX
|
|
2
|
+
|
|
3
|
+
A production-grade Python library for airport data and flight geometry calculations.
|
|
4
|
+
|
|
5
|
+
**🆕 v0.2.0:** Now with **84,000+ airports** from [OurAirports](https://ourairports.com) (MIT License)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🛫 **Airport Database**: 84,000+ global airports with efficient IATA/ICAO indexing
|
|
10
|
+
- 📏 **Distance Calculations**: Haversine, Vincenty, and Spherical Law of Cosines
|
|
11
|
+
- 🌍 **Geodesy**: Bearings, midpoints, great circle paths
|
|
12
|
+
- 🔍 **Search**: Fuzzy name search, nearest neighbor queries, radius search
|
|
13
|
+
- 🛤️ **Routing**: Multi-segment routes, flight time estimation, shortest paths
|
|
14
|
+
- 📊 **Analytics**: Statistics by country, continent, type, and elevation
|
|
15
|
+
- ⏰ **Timezone Support**: Automatic timezone detection and local time
|
|
16
|
+
- 🌱 **Emissions**: CO2 emissions estimation per passenger
|
|
17
|
+
- 🌤️ **Weather**: METAR and TAF data fetching
|
|
18
|
+
- 💻 **CLI**: Command-line interface for quick queries
|
|
19
|
+
- 🌐 **REST API**: FastAPI-based web service
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install aeronavx
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Or from source:**
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/teyfikoz/AeroNavX.git
|
|
30
|
+
cd AeroNavX
|
|
31
|
+
pip install -e .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import aeronavx
|
|
38
|
+
|
|
39
|
+
# Get airports
|
|
40
|
+
ist = aeronavx.get_airport("IST")
|
|
41
|
+
jfk = aeronavx.get_airport("JFK")
|
|
42
|
+
|
|
43
|
+
# Calculate distance
|
|
44
|
+
dist_km = ist.distance_to(jfk)
|
|
45
|
+
print(f"Distance: {dist_km:.2f} km")
|
|
46
|
+
|
|
47
|
+
# Find nearest airports
|
|
48
|
+
nearest = aeronavx.nearest_airport(41.0, 29.0, n=5)
|
|
49
|
+
|
|
50
|
+
# Estimate emissions
|
|
51
|
+
co2 = aeronavx.estimate_co2_kg_for_segment("IST", "JFK")
|
|
52
|
+
print(f"CO2: {co2:.2f} kg per passenger")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Advanced: Filtering Airports
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from aeronavx.core import loader
|
|
59
|
+
|
|
60
|
+
# Load only major airports (large + medium with scheduled service)
|
|
61
|
+
major_airports = loader.load_airports(
|
|
62
|
+
include_types=['large_airport', 'medium_airport'],
|
|
63
|
+
scheduled_service_only=True
|
|
64
|
+
)
|
|
65
|
+
print(f"Major airports: {len(major_airports):,}") # ~3,200
|
|
66
|
+
|
|
67
|
+
# Load specific countries
|
|
68
|
+
us_airports = loader.load_airports(countries=['US'])
|
|
69
|
+
print(f"US airports: {len(us_airports):,}") # ~20,000
|
|
70
|
+
|
|
71
|
+
# Load airports with IATA codes only
|
|
72
|
+
iata_airports = loader.load_airports(has_iata_only=True)
|
|
73
|
+
print(f"IATA airports: {len(iata_airports):,}") # ~9,000
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## CLI Usage
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Calculate distance
|
|
80
|
+
aeronavx distance --from IST --to JFK --unit nmi
|
|
81
|
+
|
|
82
|
+
# Find nearest airports
|
|
83
|
+
aeronavx nearest --lat 41.0 --lon 29.0 --n 5
|
|
84
|
+
|
|
85
|
+
# Search by name
|
|
86
|
+
aeronavx search --name "Heathrow"
|
|
87
|
+
|
|
88
|
+
# Estimate emissions
|
|
89
|
+
aeronavx emissions --from IST --to LHR
|
|
90
|
+
|
|
91
|
+
# Flight time
|
|
92
|
+
aeronavx flight-time --from IST --to JFK
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## API Server
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python -m aeronavx.api.server
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then access:
|
|
102
|
+
- http://localhost:8000/health
|
|
103
|
+
- http://localhost:8000/airport/IST
|
|
104
|
+
- http://localhost:8000/distance?from=IST&to=JFK
|
|
105
|
+
- http://localhost:8000/nearest?lat=41.0&lon=29.0&n=5
|
|
106
|
+
|
|
107
|
+
## Data
|
|
108
|
+
|
|
109
|
+
AeroNavX includes **84,000+ airports** from [OurAirports](https://ourairports.com/data/), which provides:
|
|
110
|
+
- ✅ **Global Coverage**: Airports, heliports, seaplane bases, and more
|
|
111
|
+
- ✅ **MIT License**: Free to use commercially
|
|
112
|
+
- ✅ **Regular Updates**: Community-maintained and updated
|
|
113
|
+
- ✅ **Comprehensive Data**: IATA/ICAO codes, coordinates, types, and more
|
|
114
|
+
|
|
115
|
+
**Data Attribution:**
|
|
116
|
+
Airport data from [OurAirports](https://ourairports.com) (David Megginson et al.) - Licensed under [MIT License](https://github.com/davidmegginson/ourairports-data)
|
|
117
|
+
|
|
118
|
+
## Examples
|
|
119
|
+
|
|
120
|
+
See `examples/` directory for:
|
|
121
|
+
- `basic_distance.py`: Distance calculations
|
|
122
|
+
- `nearest_airports.py`: Finding nearby airports
|
|
123
|
+
- `routing_example.py`: Multi-segment routes
|
|
124
|
+
- `emissions_example.py`: CO2 estimation
|
|
125
|
+
|
|
126
|
+
## Testing
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
pytest
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Dependencies
|
|
133
|
+
|
|
134
|
+
**Required**: Python >= 3.10
|
|
135
|
+
|
|
136
|
+
**Optional**:
|
|
137
|
+
- `pandas`: DataFrame support
|
|
138
|
+
- `scipy`: Faster spatial indexing
|
|
139
|
+
- `rapidfuzz`: Better fuzzy search
|
|
140
|
+
- `timezonefinder`: Timezone support
|
|
141
|
+
- `fastapi`, `uvicorn`: API server
|
|
142
|
+
- `requests`: Weather data
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT License
|
|
147
|
+
|
|
148
|
+
## Contributing
|
|
149
|
+
|
|
150
|
+
Contributions welcome! Please open an issue or pull request.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from .models import Airport, Runway
|
|
2
|
+
from .core.airports import get as get_airport, get_by_iata, get_by_icao, search_by_name as search_airports_by_name
|
|
3
|
+
from .core.distance import distance, distance_km, distance_mi, distance_nmi
|
|
4
|
+
from .core.geodesy import initial_bearing, midpoint, great_circle_path
|
|
5
|
+
from .core.search import nearest_airport, nearest_airports, airports_within_radius
|
|
6
|
+
from .core.routing import estimate_flight_time_hours as estimate_flight_time, route_distance
|
|
7
|
+
from .core.emissions import estimate_co2_kg_by_codes as estimate_co2_kg_for_segment
|
|
8
|
+
from .core.weather import get_metar, get_taf
|
|
9
|
+
from .core.runways import (
|
|
10
|
+
get_runways_by_airport,
|
|
11
|
+
get_longest_runway,
|
|
12
|
+
get_paved_runways,
|
|
13
|
+
)
|
|
14
|
+
from .core.statistics import (
|
|
15
|
+
get_country_stats,
|
|
16
|
+
get_continent_stats,
|
|
17
|
+
get_global_stats,
|
|
18
|
+
get_top_countries_by_airports,
|
|
19
|
+
get_top_countries_by_large_airports,
|
|
20
|
+
)
|
|
21
|
+
from .exceptions import (
|
|
22
|
+
AeroNavXError,
|
|
23
|
+
AirportNotFoundError,
|
|
24
|
+
InvalidAirportCodeError,
|
|
25
|
+
DataLoadError,
|
|
26
|
+
RoutingError,
|
|
27
|
+
WeatherDataError,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
__version__ = "0.3.1"
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"Airport",
|
|
35
|
+
"Runway",
|
|
36
|
+
"get_airport",
|
|
37
|
+
"get_by_iata",
|
|
38
|
+
"get_by_icao",
|
|
39
|
+
"distance",
|
|
40
|
+
"distance_km",
|
|
41
|
+
"distance_mi",
|
|
42
|
+
"distance_nmi",
|
|
43
|
+
"initial_bearing",
|
|
44
|
+
"midpoint",
|
|
45
|
+
"great_circle_path",
|
|
46
|
+
"nearest_airport",
|
|
47
|
+
"nearest_airports",
|
|
48
|
+
"airports_within_radius",
|
|
49
|
+
"estimate_flight_time",
|
|
50
|
+
"route_distance",
|
|
51
|
+
"estimate_co2_kg_for_segment",
|
|
52
|
+
"search_airports_by_name",
|
|
53
|
+
"get_metar",
|
|
54
|
+
"get_taf",
|
|
55
|
+
"get_runways_by_airport",
|
|
56
|
+
"get_longest_runway",
|
|
57
|
+
"get_paved_runways",
|
|
58
|
+
"get_country_stats",
|
|
59
|
+
"get_continent_stats",
|
|
60
|
+
"get_global_stats",
|
|
61
|
+
"get_top_countries_by_airports",
|
|
62
|
+
"get_top_countries_by_large_airports",
|
|
63
|
+
"AeroNavXError",
|
|
64
|
+
"AirportNotFoundError",
|
|
65
|
+
"InvalidAirportCodeError",
|
|
66
|
+
"DataLoadError",
|
|
67
|
+
"RoutingError",
|
|
68
|
+
"WeatherDataError",
|
|
69
|
+
]
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from fastapi import FastAPI, HTTPException, Query
|
|
3
|
+
from fastapi.responses import JSONResponse
|
|
4
|
+
|
|
5
|
+
from ..core.airports import get
|
|
6
|
+
from ..core.distance import distance
|
|
7
|
+
from ..core.search import nearest_airports, search_airports_by_name
|
|
8
|
+
from ..core.routing import estimate_flight_time_hours
|
|
9
|
+
from ..core.emissions import estimate_co2_kg_by_codes
|
|
10
|
+
from ..exceptions import AeroNavXError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
app = FastAPI(
|
|
14
|
+
title="AeroNavX API",
|
|
15
|
+
description="Airport and flight geometry utilities",
|
|
16
|
+
version="0.1.0"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@app.get("/health")
|
|
21
|
+
async def health():
|
|
22
|
+
return {"status": "ok", "service": "AeroNavX API"}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@app.get("/airport/{code}")
|
|
26
|
+
async def get_airport(
|
|
27
|
+
code: str,
|
|
28
|
+
code_type: str = Query("auto", regex="^(iata|icao|auto)$")
|
|
29
|
+
):
|
|
30
|
+
try:
|
|
31
|
+
airport = get(code, code_type=code_type)
|
|
32
|
+
|
|
33
|
+
if airport is None:
|
|
34
|
+
raise HTTPException(status_code=404, detail=f"Airport not found: {code}")
|
|
35
|
+
|
|
36
|
+
return airport.as_dict()
|
|
37
|
+
|
|
38
|
+
except AeroNavXError as e:
|
|
39
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@app.get("/distance")
|
|
43
|
+
async def calculate_distance(
|
|
44
|
+
from_code: str = Query(..., alias="from"),
|
|
45
|
+
to_code: str = Query(..., alias="to"),
|
|
46
|
+
code_type: str = Query("auto", regex="^(iata|icao|auto)$"),
|
|
47
|
+
model: str = Query("haversine", regex="^(haversine|slc|vincenty)$"),
|
|
48
|
+
unit: str = Query("km", regex="^(km|mi|nmi)$")
|
|
49
|
+
):
|
|
50
|
+
try:
|
|
51
|
+
from_airport = get(from_code, code_type=code_type)
|
|
52
|
+
to_airport = get(to_code, code_type=code_type)
|
|
53
|
+
|
|
54
|
+
if from_airport is None:
|
|
55
|
+
raise HTTPException(status_code=404, detail=f"Origin airport not found: {from_code}")
|
|
56
|
+
|
|
57
|
+
if to_airport is None:
|
|
58
|
+
raise HTTPException(status_code=404, detail=f"Destination airport not found: {to_code}")
|
|
59
|
+
|
|
60
|
+
dist = distance(
|
|
61
|
+
from_airport.latitude_deg,
|
|
62
|
+
from_airport.longitude_deg,
|
|
63
|
+
to_airport.latitude_deg,
|
|
64
|
+
to_airport.longitude_deg,
|
|
65
|
+
model=model,
|
|
66
|
+
unit=unit
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
"from": from_airport.as_dict(),
|
|
71
|
+
"to": to_airport.as_dict(),
|
|
72
|
+
"distance": dist,
|
|
73
|
+
"unit": unit,
|
|
74
|
+
"model": model
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
except AeroNavXError as e:
|
|
78
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@app.get("/nearest")
|
|
82
|
+
async def find_nearest(
|
|
83
|
+
lat: float = Query(..., ge=-90, le=90),
|
|
84
|
+
lon: float = Query(..., ge=-180, le=180),
|
|
85
|
+
n: int = Query(5, ge=1, le=100)
|
|
86
|
+
):
|
|
87
|
+
try:
|
|
88
|
+
airports = nearest_airports(lat, lon, n=n)
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
"query": {"lat": lat, "lon": lon},
|
|
92
|
+
"count": len(airports),
|
|
93
|
+
"airports": [a.as_dict() for a in airports]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
except AeroNavXError as e:
|
|
97
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@app.get("/search")
|
|
101
|
+
async def search(
|
|
102
|
+
q: str = Query(..., min_length=1),
|
|
103
|
+
limit: int = Query(20, ge=1, le=100)
|
|
104
|
+
):
|
|
105
|
+
try:
|
|
106
|
+
airports = search_airports_by_name(q, limit=limit)
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
"query": q,
|
|
110
|
+
"count": len(airports),
|
|
111
|
+
"airports": [a.as_dict() for a in airports]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
except AeroNavXError as e:
|
|
115
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@app.get("/flight-time")
|
|
119
|
+
async def flight_time(
|
|
120
|
+
from_code: str = Query(..., alias="from"),
|
|
121
|
+
to_code: str = Query(..., alias="to"),
|
|
122
|
+
speed_kts: float = Query(450.0, ge=100, le=1000)
|
|
123
|
+
):
|
|
124
|
+
try:
|
|
125
|
+
from_airport = get(from_code, code_type="auto")
|
|
126
|
+
to_airport = get(to_code, code_type="auto")
|
|
127
|
+
|
|
128
|
+
if from_airport is None:
|
|
129
|
+
raise HTTPException(status_code=404, detail=f"Origin airport not found: {from_code}")
|
|
130
|
+
|
|
131
|
+
if to_airport is None:
|
|
132
|
+
raise HTTPException(status_code=404, detail=f"Destination airport not found: {to_code}")
|
|
133
|
+
|
|
134
|
+
time_hours = estimate_flight_time_hours(from_airport, to_airport, speed_kts=speed_kts)
|
|
135
|
+
|
|
136
|
+
hours = int(time_hours)
|
|
137
|
+
minutes = int((time_hours - hours) * 60)
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
"from": from_airport.as_dict(),
|
|
141
|
+
"to": to_airport.as_dict(),
|
|
142
|
+
"speed_kts": speed_kts,
|
|
143
|
+
"time_hours": time_hours,
|
|
144
|
+
"time_formatted": f"{hours}h {minutes}m"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
except AeroNavXError as e:
|
|
148
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@app.get("/emissions")
|
|
152
|
+
async def emissions(
|
|
153
|
+
from_code: str = Query(..., alias="from"),
|
|
154
|
+
to_code: str = Query(..., alias="to"),
|
|
155
|
+
model: str = Query("haversine", regex="^(haversine|slc|vincenty)$")
|
|
156
|
+
):
|
|
157
|
+
try:
|
|
158
|
+
co2_kg = estimate_co2_kg_by_codes(from_code, to_code, code_type="auto", model=model)
|
|
159
|
+
|
|
160
|
+
from_airport = get(from_code, code_type="auto")
|
|
161
|
+
to_airport = get(to_code, code_type="auto")
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
"from": from_airport.as_dict(),
|
|
165
|
+
"to": to_airport.as_dict(),
|
|
166
|
+
"co2_kg_per_passenger": co2_kg,
|
|
167
|
+
"model": model
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
except AeroNavXError as e:
|
|
171
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def run_server(host: str = "0.0.0.0", port: int = 8000):
|
|
175
|
+
import uvicorn
|
|
176
|
+
uvicorn.run(app, host=host, port=port)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
if __name__ == "__main__":
|
|
180
|
+
run_server()
|