windborne 1.1.3__py3-none-any.whl → 1.1.5__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.
- windborne/__init__.py +4 -0
- windborne/cli.py +27 -1
- windborne/data_api.py +89 -13
- windborne/forecasts_api.py +3 -0
- {windborne-1.1.3.dist-info → windborne-1.1.5.dist-info}/METADATA +1 -1
- windborne-1.1.5.dist-info/RECORD +13 -0
- {windborne-1.1.3.dist-info → windborne-1.1.5.dist-info}/WHEEL +1 -1
- windborne-1.1.3.dist-info/RECORD +0 -13
- {windborne-1.1.3.dist-info → windborne-1.1.5.dist-info}/entry_points.txt +0 -0
- {windborne-1.1.3.dist-info → windborne-1.1.5.dist-info}/top_level.txt +0 -0
windborne/__init__.py
CHANGED
@@ -14,6 +14,7 @@ from .data_api import (
|
|
14
14
|
get_flying_missions,
|
15
15
|
get_mission_launch_site,
|
16
16
|
get_predicted_path,
|
17
|
+
get_current_location,
|
17
18
|
get_flight_path
|
18
19
|
)
|
19
20
|
|
@@ -22,6 +23,7 @@ from .forecasts_api import (
|
|
22
23
|
get_point_forecasts,
|
23
24
|
get_initialization_times,
|
24
25
|
|
26
|
+
get_full_gridded_forecast,
|
25
27
|
get_temperature_2m,
|
26
28
|
# get_dewpoint_2m,
|
27
29
|
get_wind_u_10m, get_wind_v_10m,
|
@@ -51,11 +53,13 @@ __all__ = [
|
|
51
53
|
"get_flying_missions",
|
52
54
|
"get_mission_launch_site",
|
53
55
|
"get_predicted_path",
|
56
|
+
"get_current_location",
|
54
57
|
"get_flight_path",
|
55
58
|
|
56
59
|
"get_point_forecasts",
|
57
60
|
"get_initialization_times",
|
58
61
|
|
62
|
+
"get_full_gridded_forecast",
|
59
63
|
"get_temperature_2m",
|
60
64
|
# "get_dewpoint_2m",
|
61
65
|
"get_wind_u_10m",
|
windborne/cli.py
CHANGED
@@ -14,10 +14,12 @@ from . import (
|
|
14
14
|
get_flying_missions,
|
15
15
|
get_mission_launch_site,
|
16
16
|
get_predicted_path,
|
17
|
+
get_current_location,
|
17
18
|
get_flight_path,
|
18
19
|
|
19
20
|
get_point_forecasts,
|
20
21
|
get_initialization_times,
|
22
|
+
get_full_gridded_forecast,
|
21
23
|
get_temperature_2m,
|
22
24
|
# get_dewpoint_2m,
|
23
25
|
get_wind_u_10m, get_wind_v_10m,
|
@@ -121,6 +123,11 @@ def main():
|
|
121
123
|
launch_site_parser.add_argument('mission_id', help='Mission ID')
|
122
124
|
launch_site_parser.add_argument('output', nargs='?', help='Output file')
|
123
125
|
|
126
|
+
# Get Current Location Command
|
127
|
+
current_location_parser = subparsers.add_parser('current-location', help='Get current location')
|
128
|
+
current_location_parser.add_argument('mission_id', help='Mission ID')
|
129
|
+
current_location_parser.add_argument('output', nargs='?', help='Output file')
|
130
|
+
|
124
131
|
# Get Predicted Path Command
|
125
132
|
prediction_parser = subparsers.add_parser('predict-path', help='Get predicted flight path')
|
126
133
|
prediction_parser.add_argument('mission_id', help='Mission ID')
|
@@ -149,6 +156,9 @@ def main():
|
|
149
156
|
|
150
157
|
# GRIDDED FORECASTS
|
151
158
|
####################################################################################################################
|
159
|
+
full_gridded_parser = subparsers.add_parser('grid_full', help='Get full gridded forecast')
|
160
|
+
full_gridded_parser.add_argument('args', nargs='*', help='time output_file')
|
161
|
+
|
152
162
|
# Gridded 2m temperature Command
|
153
163
|
gridded_temperature_2m_parser = subparsers.add_parser('grid_temp_2m', help='Get gridded output of global 2m temperature forecasts')
|
154
164
|
gridded_temperature_2m_parser.add_argument('args', nargs='*', help='time output_file')
|
@@ -379,7 +389,12 @@ def main():
|
|
379
389
|
output_file=args.output,
|
380
390
|
print_result=(not args.output)
|
381
391
|
)
|
382
|
-
|
392
|
+
elif args.command == 'current-location':
|
393
|
+
get_current_location(
|
394
|
+
mission_id=args.mission_id,
|
395
|
+
output_file=args.output,
|
396
|
+
print_result=(not args.output)
|
397
|
+
)
|
383
398
|
elif args.command == 'predict-path':
|
384
399
|
get_predicted_path(
|
385
400
|
mission_id=args.mission_id,
|
@@ -419,6 +434,17 @@ def main():
|
|
419
434
|
elif args.command == 'init_times':
|
420
435
|
get_initialization_times(print_response=True)
|
421
436
|
|
437
|
+
if args.command == 'grid_full':
|
438
|
+
# Parse get_full_gridded_forecast arguments
|
439
|
+
if len(args.args) in [0,1]:
|
440
|
+
print("To get the full gridded forecast you need to provide the time for which to get the forecast and an output file.")
|
441
|
+
print("\nUsage: windborne get_full_gridded_forecast time output_file")
|
442
|
+
elif len(args.args) == 2:
|
443
|
+
get_full_gridded_forecast(time=args.args[0], output_file=args.args[1])
|
444
|
+
else:
|
445
|
+
print("Too many arguments")
|
446
|
+
print("\nUsage: windborne get_full_gridded_forecast time output_file")
|
447
|
+
|
422
448
|
elif args.command == 'grid_temp_2m':
|
423
449
|
# Parse grid_temp_2m arguments
|
424
450
|
if len(args.args) in [0,1]:
|
windborne/data_api.py
CHANGED
@@ -548,10 +548,28 @@ def get_flying_missions(output_file=None, print_results=False):
|
|
548
548
|
Returns:
|
549
549
|
dict: The API response containing list of flying missions.
|
550
550
|
"""
|
551
|
+
page_size = 64
|
552
|
+
|
553
|
+
# Initial query to get total flying
|
554
|
+
query_params = {
|
555
|
+
'page': 0,
|
556
|
+
'page_size': page_size
|
557
|
+
}
|
551
558
|
|
552
559
|
url = f"{DATA_API_BASE_URL}/missions.json"
|
553
|
-
flying_missions_response = make_api_request(url)
|
560
|
+
flying_missions_response = make_api_request(url, params=query_params)
|
561
|
+
|
554
562
|
flying_missions = flying_missions_response.get("missions", [])
|
563
|
+
num_fetched_missions = len(flying_missions)
|
564
|
+
|
565
|
+
while num_fetched_missions == page_size:
|
566
|
+
query_params['page'] += 1
|
567
|
+
|
568
|
+
new_missions = make_api_request(url, params=query_params).get('missions', [])
|
569
|
+
num_fetched_missions = len(new_missions)
|
570
|
+
|
571
|
+
flying_missions += new_missions
|
572
|
+
|
555
573
|
for mission in flying_missions:
|
556
574
|
if mission.get('number'):
|
557
575
|
mission['name'] = f"W-{mission['number']}"
|
@@ -622,22 +640,22 @@ def get_mission_launch_site(mission_id=None, output_file=None, print_result=Fals
|
|
622
640
|
return response.get('launch_site')
|
623
641
|
|
624
642
|
|
625
|
-
def
|
643
|
+
def get_flying_mission(mission_id, verify_flying=True):
|
626
644
|
"""
|
627
|
-
|
628
|
-
|
645
|
+
Fetches a flying mission by ID.
|
646
|
+
If the mission is not flying, displays a list of currently flying missions.
|
629
647
|
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
print_result (bool): Whether to print the results in the CLI.
|
648
|
+
Args:
|
649
|
+
mission_id (str): The ID of the mission to fetch.
|
650
|
+
verify_flying (bool): Whether to always check if the mission is flying.
|
634
651
|
|
635
|
-
|
636
|
-
|
652
|
+
Returns:
|
653
|
+
dict: The API response containing the mission data, or None if the mission is not flying.
|
637
654
|
"""
|
638
|
-
if not mission_id:
|
639
|
-
|
640
|
-
|
655
|
+
if not verify_flying and not mission_id.startswith('W-'):
|
656
|
+
return {
|
657
|
+
'id': mission_id,
|
658
|
+
}
|
641
659
|
|
642
660
|
# Check if provided mission ID belong to a flying mission
|
643
661
|
flying_missions = get_flying_missions()
|
@@ -658,8 +676,30 @@ def get_predicted_path(mission_id=None, output_file=None, print_result=False):
|
|
658
676
|
print_table(flying_missions, keys=['id', 'name'], headers=['Mission ID', 'Mission Name'])
|
659
677
|
else:
|
660
678
|
print("No missions are currently flying.")
|
679
|
+
return None
|
680
|
+
|
681
|
+
return mission
|
682
|
+
|
683
|
+
|
684
|
+
def get_predicted_path(mission_id=None, output_file=None, print_result=False):
|
685
|
+
"""
|
686
|
+
Fetches the predicted flight path for a given mission.
|
687
|
+
Displays currently flying missions if the provided mission ID is invalid.
|
688
|
+
|
689
|
+
Args:
|
690
|
+
mission_id (str): The ID of the mission to fetch the prediction for.
|
691
|
+
output_file (str): Optional path to save the response data.
|
692
|
+
print_result (bool): Whether to print the results in the CLI.
|
693
|
+
|
694
|
+
Returns:
|
695
|
+
list: The API response containing the predicted flight path data.
|
696
|
+
"""
|
697
|
+
if not mission_id:
|
698
|
+
print("To get the predicted flight path for a given mission you must provide a mission ID.")
|
661
699
|
return
|
662
700
|
|
701
|
+
mission = get_flying_mission(mission_id)
|
702
|
+
|
663
703
|
url = f"{DATA_API_BASE_URL}/missions/{mission.get('id')}/prediction.json"
|
664
704
|
response = make_api_request(url)
|
665
705
|
|
@@ -677,6 +717,42 @@ def get_predicted_path(mission_id=None, output_file=None, print_result=False):
|
|
677
717
|
return response.get('prediction')
|
678
718
|
|
679
719
|
|
720
|
+
def get_current_location(mission_id=None, output_file=None, print_result=False, verify_flying=True):
|
721
|
+
"""
|
722
|
+
Fetches the current location for a given mission.
|
723
|
+
|
724
|
+
Args:
|
725
|
+
mission_id (str): The ID of the mission to fetch the current location for.
|
726
|
+
output_file (str): Optional path to save the response data.
|
727
|
+
print_result (bool): Whether to print the results in the CLI.
|
728
|
+
verify_flying (bool): Whether to verify the mission is flying before trying to fetch the current location
|
729
|
+
|
730
|
+
Returns:
|
731
|
+
dict: Current location with latitude, longitude, and altitude, or None if not found
|
732
|
+
"""
|
733
|
+
if not mission_id:
|
734
|
+
print("To get the current location for a given mission you must provide a mission ID.")
|
735
|
+
return
|
736
|
+
|
737
|
+
mission = get_flying_mission(mission_id, verify_flying=verify_flying)
|
738
|
+
|
739
|
+
url = f"{DATA_API_BASE_URL}/missions/{mission.get('id')}/current_location.json"
|
740
|
+
response = make_api_request(url)
|
741
|
+
|
742
|
+
if response is None:
|
743
|
+
return
|
744
|
+
|
745
|
+
if output_file:
|
746
|
+
save_arbitrary_response(output_file, response, csv_data_key=None)
|
747
|
+
|
748
|
+
if print_result:
|
749
|
+
print("Current location\n")
|
750
|
+
print_table([response], keys=['latitude', 'longitude', 'altitude'],
|
751
|
+
headers=['Latitude', 'Longitude', 'Altitude'])
|
752
|
+
|
753
|
+
return response
|
754
|
+
|
755
|
+
|
680
756
|
def get_flight_path(mission_id=None, output_file=None, print_result=False):
|
681
757
|
"""
|
682
758
|
Fetches the flight path for a given mission.
|
windborne/forecasts_api.py
CHANGED
@@ -141,6 +141,9 @@ def get_gridded_forecast(time, variable, output_file=None):
|
|
141
141
|
|
142
142
|
return response
|
143
143
|
|
144
|
+
def get_full_gridded_forecast(time, output_file=None):
|
145
|
+
return get_gridded_forecast(time, "FULL", output_file)
|
146
|
+
|
144
147
|
def get_temperature_2m(time, output_file=None):
|
145
148
|
return get_gridded_forecast(time, "temperature_2m", output_file)
|
146
149
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
windborne/__init__.py,sha256=jPqxHTqOEcAnPU-7VCJionGToE2tqY7Q3SuSdQrdl9Q,1944
|
2
|
+
windborne/api_request.py,sha256=zh1TaaZAaRfAXp2NYMja75fKeduWLfao02JRRFVpQCA,11108
|
3
|
+
windborne/cli.py,sha256=fJ4cLcBpc7YasfMu3pNrqCX9idGCWA-2j2necNpDfck,36696
|
4
|
+
windborne/data_api.py,sha256=sYZkcQog8RuLErfdLLa4gC8fRkAoPGNKKQJ8i6o-LTQ,33826
|
5
|
+
windborne/forecasts_api.py,sha256=Jea1hGd2CQHbyRXnJXLamF1GdgBsoqX7oGyg8S6YoRo,14102
|
6
|
+
windborne/observation_formatting.py,sha256=c739aaun6aaYhXl5VI-SRGR-TDS355_0Bfu1t6McoiM,14993
|
7
|
+
windborne/track_formatting.py,sha256=LaLfTyjpWoOtHmReJPLViY0MKm_iPL_5I2OB_lNvGGA,10054
|
8
|
+
windborne/utils.py,sha256=H8gvZ4Lrr0UmLl25iMZs6NsZliCY_73Ved_rBIqxJg4,7240
|
9
|
+
windborne-1.1.5.dist-info/METADATA,sha256=M_INOFolggNfzz5IyYivgBT-lzgmp4ax8G-cSNhjZIg,1235
|
10
|
+
windborne-1.1.5.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
11
|
+
windborne-1.1.5.dist-info/entry_points.txt,sha256=j_YrqdCDrCd7p5MIwQ2BYwNXEi95VNANzLRJmcXEg1U,49
|
12
|
+
windborne-1.1.5.dist-info/top_level.txt,sha256=PE9Lauriu5S5REf7JKhXprufZ_V5RiZ_TnfnrLGJrmE,10
|
13
|
+
windborne-1.1.5.dist-info/RECORD,,
|
windborne-1.1.3.dist-info/RECORD
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
windborne/__init__.py,sha256=DcxmiLq4UnjoRjZd4UeuYt29FBsi9paMXGtI91Itn04,1826
|
2
|
-
windborne/api_request.py,sha256=zh1TaaZAaRfAXp2NYMja75fKeduWLfao02JRRFVpQCA,11108
|
3
|
-
windborne/cli.py,sha256=xRPRLh50iC4Uu0AYEHL-LHRxUnpxqB_Mn-easp5VSK4,35370
|
4
|
-
windborne/data_api.py,sha256=QsG1NJyOCzTrTLRaoz5Z4nGRI0HCMEJvbDyRUlY3Usg,31388
|
5
|
-
windborne/forecasts_api.py,sha256=E0X9FyUW2yz3pQZKkFBYDMeg6PhFJ1bp4z1Cg1g0uGs,13987
|
6
|
-
windborne/observation_formatting.py,sha256=c739aaun6aaYhXl5VI-SRGR-TDS355_0Bfu1t6McoiM,14993
|
7
|
-
windborne/track_formatting.py,sha256=LaLfTyjpWoOtHmReJPLViY0MKm_iPL_5I2OB_lNvGGA,10054
|
8
|
-
windborne/utils.py,sha256=H8gvZ4Lrr0UmLl25iMZs6NsZliCY_73Ved_rBIqxJg4,7240
|
9
|
-
windborne-1.1.3.dist-info/METADATA,sha256=unPmA3uPzt8obgqSmJSrsSzSLat4yH7o3uJtb-i3wy0,1235
|
10
|
-
windborne-1.1.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
11
|
-
windborne-1.1.3.dist-info/entry_points.txt,sha256=j_YrqdCDrCd7p5MIwQ2BYwNXEi95VNANzLRJmcXEg1U,49
|
12
|
-
windborne-1.1.3.dist-info/top_level.txt,sha256=PE9Lauriu5S5REf7JKhXprufZ_V5RiZ_TnfnrLGJrmE,10
|
13
|
-
windborne-1.1.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|