diff --git a/PySoar/analysis.py b/PySoar/analysis.py index a8f99fc..1af4fb5 100644 --- a/PySoar/analysis.py +++ b/PySoar/analysis.py @@ -10,7 +10,7 @@ settings = Settings() -def run(url, source, download_progress=None, analysis_progress=None, on_success=None, on_failure=None): +def run(url, source, to_elevation, download_progress=None, analysis_progress=None, on_success=None, on_failure=None): target_directory = os.path.join(settings.current_dir, 'bin') if source == 'cuc': daily_result_page = SoaringSpotDaily(url) @@ -42,8 +42,13 @@ def run(url, source, download_progress=None, analysis_progress=None, on_success= if fix['pressure_alt'] != 0: gps_altitude = False + # if field elevation of takeoff is provided then calculate the altitude correction to be used in alitudes + elevation_correction = 0 + if to_elevation != None: + elevation_correction = (competitor.trace[0]['gps_alt'] if gps_altitude else competitor.trace[0]['pressure_alt']) - to_elevation + competitor.performance = Performance(competition_day.task, competitor.trip, competitor.phases, - gps_altitude) + gps_altitude, elevation_correction) except Exception: failed_comp_ids.append(competitor.competition_id) diff --git a/PySoar/main_pysoar.py b/PySoar/main_pysoar.py index a2dff6c..7c27b87 100644 --- a/PySoar/main_pysoar.py +++ b/PySoar/main_pysoar.py @@ -71,15 +71,23 @@ def __init__(self, current_version, latest_version): self.url_input = wx.TextCtrl(panel) my_sizer.Add(self.url_input, 0, wx.ALL | wx.EXPAND, 5) + to_elevation_sizer = wx.BoxSizer(wx.HORIZONTAL) + + text = wx.StaticText(panel, label="Field elevation:") + to_elevation_sizer.Add(text, 0, wx.ALL, 5) + self.to_elevation_input = wx.TextCtrl(panel) + to_elevation_sizer.Add(self.to_elevation_input, 0, wx.ALL | wx.EXPAND, 5) + + status_sizer = wx.BoxSizer(wx.VERTICAL) self.status = wx.StaticText(panel, label="") - my_sizer.Add(self.status) + status_sizer.Add(self.status) self.download_status = wx.StaticText(panel, label="") - my_sizer.Add(self.download_status) + status_sizer.Add(self.download_status) self.analyse_status = wx.StaticText(panel, label="") - my_sizer.Add(self.analyse_status) - + status_sizer.Add(self.analyse_status) + buttons_sizer = wx.BoxSizer(wx.HORIZONTAL) self.start_analysis = wx.Button(panel, label='Start analysis') @@ -96,6 +104,8 @@ def __init__(self, current_version, latest_version): buttons_sizer.Add(bug_report) complete_sizer.Add(my_sizer, 0, wx.ALL | wx.EXPAND, 5) + complete_sizer.Add(to_elevation_sizer, 0, wx.ALL | wx.LEFT, 5) + complete_sizer.Add(status_sizer, 0, wx.ALL | wx.LEFT, 5) complete_sizer.Add(buttons_sizer, 0, wx.ALL | wx.CENTER, 5) panel.SetSizer(complete_sizer) @@ -159,7 +169,12 @@ def on_press(self, event): url = self.url_input.GetValue() if url_format_correct(url, self.update_status): - args = (url, get_url_source(url), self.set_download_status, self.set_analyse_status, + try: + to_elevation = int(self.to_elevation_input.GetValue()) + except: + to_elevation = None + + args = (url, get_url_source(url), to_elevation, self.set_download_status, self.set_analyse_status, self.after_successful_run, self.after_unsuccessful_run) x = Thread(target=run, args=args) x.start() @@ -188,7 +203,9 @@ def run_commandline_program(sys_argv, current_version, latest_version): def print_help(): print('There are two options for running PySoar from the commandline:\n' '1. `python main_python` for GUI\n' - '2. `python main_pysoar [url]` - where [url] is the daily competition url') + '2. `python main_pysoar [url] ` - where:\n' \ + ' - [url] is the daily competition url,\n'\ + ' - (optional) is the elevation of the takeoff field to be used in altitude corrections') def status_handle(message): print(message) @@ -216,15 +233,17 @@ def analysis_handle(new, total=None): if latest_version and latest_version.lstrip('v') != current_version: print('Latest version is %s! Current: %s' % (latest_version, current_version)) - if len(sys_argv) == 2: + if len(sys_argv) >= 2: if sys_argv[1] == '--help': print_help() else: url = sys_argv[1] + to_elevation = None if len(sys_argv) == 2 else int(sys_argv[2]) if url_format_correct(url, status_handle): source = get_url_source(url) run(url, source, + to_elevation, download_progress=download_handle, analysis_progress=analysis_handle, on_success=on_success, diff --git a/PySoar/performanceClass.py b/PySoar/performanceClass.py index 9c3a16a..1eeb000 100644 --- a/PySoar/performanceClass.py +++ b/PySoar/performanceClass.py @@ -9,13 +9,16 @@ class Performance(object): 'v_turn_avg', 'LD_avg', 'turn_percentage', 'h_loss_turn', 's_glide_avg', 'dh_cruise_avg', 's_extra', 'tsk_v'] - def __init__(self, task, trip, phases, gps_altitude): + def __init__(self, task, trip, phases, gps_altitude, elevation_correction): self.all = None self.leg = None self.tsk_distance_all = sum(trip.distances) self.tsk_distance_leg = trip.distances + self.trip = trip + self.gps_altitude = gps_altitude + self.elevation_correction = elevation_correction # why not use phases directly? pass in functions as argument? self.no_cruises_leg = [len(phases.cruises(leg)) for leg in range(trip.started_legs())] @@ -23,23 +26,31 @@ def __init__(self, task, trip, phases, gps_altitude): self.no_thermals_leg = [len(phases.thermals(leg)) for leg in range(trip.started_legs())] self.no_thermals = len(phases.thermals(leg='all')) - self.init_all(trip, gps_altitude) - self.init_leg(trip, gps_altitude) + self.init_all() + self.init_leg() self.determine_performance(task, trip, phases, gps_altitude) - def init_all(self, trip, gps_altitude): - start_h = trip.fixes[0]['gps_alt'] if gps_altitude else trip.fixes[0]['pressure_alt'] - start_t = trip.refined_start_time + def get_height(self, trip_index): + if (self.gps_altitude): + # return gps altitude corrected for start elevation + return self.trip.fixes[trip_index]['gps_alt'] - self.elevation_correction + else: + # return pressure altitude corrected for start elevation + return self.trip.fixes[trip_index]['pressure_alt'] - self.elevation_correction + + def init_all(self): + start_h = self.get_height(0) + start_t = self.trip.refined_start_time - if len(trip.fixes) == 1: + if len(self.trip.fixes) == 1: finish_h = None finish_t = None else: - finish_h = trip.fixes[-1]['gps_alt'] if gps_altitude else trip.fixes[-1]['pressure_alt'] - finish_t = trip.fixes[-1]['time'] + finish_h = self.get_height(-1) + finish_t = self.trip.fixes[-1]['time'] - s_flown_task_all = sum(trip.distances) / 1000 + s_flown_task_all = sum(self.trip.distances) / 1000 self.all = {"t_start": start_t, "t_finish": finish_t, @@ -47,19 +58,19 @@ def init_all(self, trip, gps_altitude): "h_finish": finish_h, "s_flown_task": s_flown_task_all} - def init_leg(self, trip, gps_altitude): + def init_leg(self): leg_values = [] - for leg in range(len(trip.distances)): - if trip.outlanding_fix is not None and leg == trip.outlanding_leg(): - start_h = trip.fixes[leg]['gps_alt'] if gps_altitude else trip.fixes[leg]['pressure_alt'] - start_t = trip.refined_start_time if leg == 0 else trip.fixes[leg]['time'] + for leg in range(len(self.trip.distances)): + if self.trip.outlanding_fix is not None and leg == self.trip.outlanding_leg(): + start_h = self.get_height(leg) + start_t = self.trip.refined_start_time if leg == 0 else self.trip.fixes[leg]['time'] finish_t = 0 finish_h = 0 - s_flown_task_leg = trip.distances[-1] / 1000 - elif trip.outlanding_fix is not None and leg > trip.outlanding_leg(): + s_flown_task_leg = self.trip.distances[-1] / 1000 + elif self.trip.outlanding_fix is not None and leg > self.trip.outlanding_leg(): start_t = 0 start_h = 0 @@ -68,13 +79,13 @@ def init_leg(self, trip, gps_altitude): s_flown_task_leg = 0 else: - start_h = trip.fixes[leg]['gps_alt'] if gps_altitude else trip.fixes[leg]['pressure_alt'] - start_t = trip.refined_start_time if leg == 0 else trip.fixes[leg]['time'] + start_h = self.get_height(leg) + start_t = self.trip.refined_start_time if leg == 0 else self.trip.fixes[leg]['time'] - finish_t = trip.fixes[leg+1]['time'] - finish_h = trip.fixes[leg+1]['gps_alt'] if gps_altitude else trip.fixes[leg+1]['pressure_alt'] + finish_t = self.trip.fixes[leg+1]['time'] + finish_h = self.get_height(leg+1) - s_flown_task_leg = trip.distances[leg] / 1000 + s_flown_task_leg = self.trip.distances[leg] / 1000 leg_values.append({"t_start": start_t, "t_finish": finish_t, diff --git a/PySoar/settingsClass.py b/PySoar/settingsClass.py index 3831068..21f6c3b 100644 --- a/PySoar/settingsClass.py +++ b/PySoar/settingsClass.py @@ -18,7 +18,7 @@ def determine_performance_dictionary(self): self.set_performance_entry("t_start", "Start time", "text", "neutral", "[local time]", True, True, True, True) self.set_performance_entry("t_finish", "Finish time", "text", "neutral", "[local time]", True, False, True, True) self.set_performance_entry("h_start", "Start height", "number", "high", "[m]", True, True, True, True) - self.set_performance_entry("h_finish", "Finish height", "number", "high", "[m]", True, False, True, False) + self.set_performance_entry("h_finish", "Finish height", "number", "low", "[m]", True, False, True, True) self.set_performance_entry("vario_gem", "Average rate of climb", "number", "high", "[m/s]", False, False, True, True) self.set_performance_entry("v_glide_avg", "Average cruise speed (GS)", "number", "high", "[km/h]", True, False, True, True) self.set_performance_entry("v_turn_avg", "Average thermal speed (GS)", "number", "low", "[km/h]", False, False, True, True)