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 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 get_predicted_path(mission_id=None, output_file=None, print_result=False):
643
+ def get_flying_mission(mission_id, verify_flying=True):
626
644
  """
627
- Fetches the predicted flight path for a given mission.
628
- Displays currently flying missions if the provided mission ID is invalid.
645
+ Fetches a flying mission by ID.
646
+ If the mission is not flying, displays a list of currently flying missions.
629
647
 
630
- Args:
631
- mission_id (str): The ID of the mission to fetch the prediction for.
632
- output_file (str): Optional path to save the response data.
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
- Returns:
636
- list: The API response containing the predicted flight path data.
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
- print("To get the predicted flight path for a given mission you must provide a mission ID.")
640
- return
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.
@@ -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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: windborne
3
- Version: 1.1.3
3
+ Version: 1.1.5
4
4
  Summary: A Python library for interacting with WindBorne Data and Forecasts API
5
5
  Author-email: WindBorne Systems <data@windbornesystems.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (75.8.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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,,