diff --git a/README.rst b/README.rst index dbae11c..53c85d9 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,12 @@ OpenSoar ======== +busy with making everything timezone aware +- wait on aerofiles fix for deepcopy +- decide on dependencies. pinned or not? +- run test with pysoar, same results? +- how to keep backwards compatible? add flag? + .. image:: https://img.shields.io/pypi/v/opensoar.svg :target: https://pypi.org/project/opensoar/ :alt: pypi version and link diff --git a/opensoar/competition/soaringspot.py b/opensoar/competition/soaringspot.py index ff7acaa..97e52b4 100644 --- a/opensoar/competition/soaringspot.py +++ b/opensoar/competition/soaringspot.py @@ -17,8 +17,9 @@ from opensoar.task.race_task import RaceTask from opensoar.task.task import Task from opensoar.task.waypoint import Waypoint -from opensoar.utilities.helper_functions import dm2dd, subtract_times +from opensoar.utilities.helper_functions import dm2dd from opensoar.competition.daily_results_page import DailyResultsPage +from opensoar.utilities.helper_functions import double_iterator def get_comment_lines_from_parsed_file(parsed_igc_file: dict) -> List[str]: @@ -46,7 +47,7 @@ def get_task_rules(lseeyou_tsk_line: str) -> Tuple[datetime.time, datetime.timed return start_opening, t_min, multi_start -def get_info_from_comment_lines(parsed_igc_file: dict, start_time_buffer: int=0) -> Tuple[Optional[Task], dict, dict]: +def get_info_from_comment_lines(parsed_igc_file: dict, date: datetime.date, start_time_buffer: int=0) -> Tuple[Optional[Task], dict, dict]: """ There is specific contest information stored in the comment lines of the IGC files. This function extracts this information @@ -84,8 +85,8 @@ def get_info_from_comment_lines(parsed_igc_file: dict, start_time_buffer: int=0) timezone = int(line.split(':')[3]) if start_opening is not None: - # convert start opening to UTC time - start_opening = subtract_times(start_opening, datetime.timedelta(hours=timezone)) + # make timezone aware datetime object + start_opening = datetime.datetime.combine(date=date, time=start_opening, tzinfo=datetime.timezone(datetime.timedelta(hours=timezone))) if len(lcu_lines) == 0 or len(lseeyou_lines) == 0: # somehow some IGC files do not contain the LCU or LSEEYOU lines with task information @@ -345,10 +346,10 @@ def generate_competition_day(self, target_directory: str, download_progress=None try: try: # try utf-8 with open(file_path, 'r', encoding='utf-8') as f: - parsed_igc_file = Reader().read(f) + parsed_igc_file = Reader(skip_duplicates=True).read(f) except UnicodeDecodeError: # if not utf-8 use latin1 with open(file_path, 'r', encoding='latin1') as f: - parsed_igc_file = Reader().read(f) + parsed_igc_file = Reader(skip_duplicates=True).read(f) except Exception: print('{} is skipped because the file could not be parsed'.format(competition_id)) continue @@ -359,7 +360,7 @@ def generate_competition_day(self, target_directory: str, download_progress=None continue # get info from file - task, contest_information, competitor_information = get_info_from_comment_lines(parsed_igc_file, start_time_buffer) + task, _, competitor_information = get_info_from_comment_lines(parsed_igc_file, date, start_time_buffer) plane_model = competitor_information.get('plane_model', None) pilot_name = competitor_information.get('pilot_name', None) diff --git a/opensoar/task/aat.py b/opensoar/task/aat.py index 12544e4..93b60c2 100644 --- a/opensoar/task/aat.py +++ b/opensoar/task/aat.py @@ -2,8 +2,7 @@ from copy import deepcopy from opensoar.task.task import Task -from opensoar.utilities.helper_functions import double_iterator, calculate_distance_bearing, calculate_destination, \ - seconds_time_difference_fixes, add_times +from opensoar.utilities.helper_functions import double_iterator, calculate_distance_bearing, calculate_destination class AAT(Task): @@ -51,12 +50,12 @@ def apply_rules(self, trace): return fixes, start_time, outlanding_fix, distances, finish_time, sector_fixes def _determine_finish_time(self, fixes, outlanding_fix): - total_trip_time = seconds_time_difference_fixes(fixes[0], fixes[-1]) + total_trip_time = (fixes[-1]['datetime'] - fixes[0]['datetime']).total_seconds() minimum_trip_time = self._t_min.total_seconds() if outlanding_fix is None and total_trip_time < minimum_trip_time: - finish_time = add_times(fixes[0]['time'], self._t_min) + finish_time = fixes[0]['datetime'] + self._t_min else: - finish_time = fixes[-1]['time'] + finish_time = fixes[-1]['datetime'] return finish_time def _calculate_trip_fixes(self, trace): @@ -118,7 +117,7 @@ def _get_sector_fixes(self, trace): if enl_first_fix is None: enl_first_fix = fix - enl_time = seconds_time_difference_fixes(enl_first_fix, fix) + enl_time = (fix['datetime'] - enl_first_fix['datetime']).total_seconds() if self.enl_time_exceeded(enl_time): enl_registered = True if current_leg > 0: @@ -357,6 +356,7 @@ def _get_waypoint_fixes(self, outlanded, sector_fixes, outside_sector_fixes=None if outside_sector_fixes is None: outside_sector_fixes = list() + # this doesnt work due to latest aerofiles version waypoint_fixes = deepcopy(sector_fixes) if outlanded: waypoint_fixes.append(sector_fixes[-1]) diff --git a/opensoar/task/race_task.py b/opensoar/task/race_task.py index 86e2b57..69a03fe 100644 --- a/opensoar/task/race_task.py +++ b/opensoar/task/race_task.py @@ -1,7 +1,7 @@ -from opensoar.task.task import Task -from opensoar.utilities.helper_functions import calculate_distance_bearing, double_iterator, \ - seconds_time_difference_fixes, add_seconds +import datetime +from opensoar.task.task import Task +from opensoar.utilities.helper_functions import calculate_distance_bearing, double_iterator class RaceTask(Task): """ @@ -82,7 +82,7 @@ def apply_rules(self, trace): fixes, outlanding_fix = self.determine_trip_fixes(trace) distances = self.determine_trip_distances(fixes, outlanding_fix) refined_start = self.determine_refined_start(trace, fixes) - finish_time = fixes[-1]['time'] + finish_time = fixes[-1]['datetime'] sector_fixes = [] # not applicable for race tasks return fixes, refined_start, outlanding_fix, distances, finish_time, sector_fixes @@ -100,7 +100,7 @@ def determine_trip_fixes(self, trace): if enl_first_fix is None: enl_first_fix = fix_minus1 - enl_time = seconds_time_difference_fixes(enl_first_fix, fix) + enl_time = (fix['datetime'] - enl_first_fix['datetime']).total_seconds() enl_registered = enl_registered or self.enl_time_exceeded(enl_time) elif not enl_registered: enl_first_fix = None @@ -108,7 +108,7 @@ def determine_trip_fixes(self, trace): if self.start_opening is None: after_start_opening = True else: - after_start_opening = add_seconds(fix['time'], self.start_time_buffer) > self.start_opening + after_start_opening = self.start_opening + datetime.timedelta(seconds=self.start_time_buffer) < fix['datetime'] if leg == -1 and after_start_opening: if self.started(fix_minus1, fix): diff --git a/opensoar/task/task.py b/opensoar/task/task.py index 78f8ff1..8632939 100644 --- a/opensoar/task/task.py +++ b/opensoar/task/task.py @@ -14,8 +14,8 @@ class Task: ENL_VALUE_THRESHOLD = 500 ENL_TIME_THRESHOLD = 30 - def __init__(self, waypoints: List[Waypoint], timezone: int, start_opening: datetime.time, start_time_buffer: int, - multistart: bool): + def __init__(self, waypoints: List[Waypoint], timezone: int, start_opening: datetime.datetime, + start_time_buffer: int, multistart: bool): """ :param waypoints: :param timezone: time difference wrt UTC in hours @@ -150,7 +150,7 @@ def determine_refined_start(self, trace, fixes): for fix, next_fix in double_iterator(interpolated_fixes): if self.started(fix, next_fix): - return fix['time'] + return fix['datetime'] raise ValueError('Start should have been determined') diff --git a/opensoar/task/trip.py b/opensoar/task/trip.py index 493214c..ec9c933 100644 --- a/opensoar/task/trip.py +++ b/opensoar/task/trip.py @@ -1,6 +1,3 @@ -from opensoar.utilities.helper_functions import seconds_time_difference - - class Trip: """ Realised @@ -47,11 +44,11 @@ def fix_on_leg(self, fix, leg): return larger_than_minimum and smaller_than_maximum def fix_before_leg(self, fix, leg): - return seconds_time_difference(fix['time'], self.fixes[leg]['time']) >= 0 + return (self.fixes[leg]['datetime'] - fix['datetime']).total_seconds() >= 0 def fix_after_leg(self, fix, leg): if leg + 1 <= self.completed_legs(): - return seconds_time_difference(self.fixes[leg + 1]['time'], fix['time']) >= 0 + return (fix['datetime'] - self.fixes[leg + 1]['datetime']).total_seconds() >= 0 elif self.outlanded() and leg == self.outlanding_leg(): return False else: # leg > self.completed_legs() + 1 diff --git a/opensoar/thermals/pysoar_thermal_detector.py b/opensoar/thermals/pysoar_thermal_detector.py index 120d38f..693e51d 100644 --- a/opensoar/thermals/pysoar_thermal_detector.py +++ b/opensoar/thermals/pysoar_thermal_detector.py @@ -1,5 +1,4 @@ -from opensoar.utilities.helper_functions import triple_iterator, calculate_bearing_change, calculate_distance_bearing, \ - seconds_time_difference +from opensoar.utilities.helper_functions import triple_iterator, calculate_bearing_change, calculate_distance_bearing class PySoarThermalDetector: @@ -34,13 +33,13 @@ def analyse(self, trace): for fix_minus2, fix_minus1, fix in triple_iterator(trace): - time_minus2 = fix_minus2['time'] - time_minus1 = fix_minus1['time'] - time = fix['time'] + time_minus2 = fix_minus2['datetime'] + time_minus1 = fix_minus1['datetime'] + time = fix['datetime'] bearing_change = calculate_bearing_change(fix_minus2, fix_minus1, fix) - delta_t = (0.5 * seconds_time_difference(time_minus1, time) + - 0.5 * seconds_time_difference(time_minus2, time)) + delta_t = (0.5 * (time - time_minus1).total_seconds() + + 0.5 * (time - time_minus2).total_seconds()) bearing_change_rate = bearing_change / delta_t if cruise: @@ -101,7 +100,7 @@ def analyse(self, trace): possible_cruise_fixes.append(fix) total_bearing_change += bearing_change - delta_t = seconds_time_difference(possible_cruise_fixes[0]['time'], time) + delta_t = (time - possible_cruise_fixes[0]['datetime']).total_seconds() cruise_distance, _ = calculate_distance_bearing(possible_cruise_fixes[0], fix) temp_bearing_rate_avg = 0 if delta_t == 0 else total_bearing_change / delta_t diff --git a/opensoar/utilities/helper_functions.py b/opensoar/utilities/helper_functions.py index 746c487..4941a06 100644 --- a/opensoar/utilities/helper_functions.py +++ b/opensoar/utilities/helper_functions.py @@ -124,10 +124,6 @@ def altitude_gain_and_loss(fixes: List[dict], gps_altitude=True): return gain, loss -def seconds_time_difference_fixes(fix1, fix2): - return seconds_time_difference(fix1['time'], fix2['time']) - - def total_distance_travelled(fixes: List[dict]): """Calculates the total distance, summing over the inter fix distances""" distance = 0 @@ -138,61 +134,6 @@ def total_distance_travelled(fixes: List[dict]): return distance -def seconds_time_difference(time1: datetime.time, time2: datetime.time): - """ - Determines the time difference between to datetime.time instances, mocking the operation time2 - time1 - It is assumed that both take place at the same day. - :param time1: - :param time2: - :return: time difference in seconds - """ - - today = datetime.date.today() - time_diff = datetime.datetime.combine(today, time2) - datetime.datetime.combine(today, time1) - return time_diff.total_seconds() - - -def add_times(start_time: datetime.time, delta_time: datetime.timedelta): - """ - Helper to circumvent problem that normal datetime.time instances can not be added. - :param start_time: - :param delta_time: - :return: - """ - full_datetime_start = datetime.datetime.combine(datetime.date.today(), start_time) - - full_datetime_result = full_datetime_start + delta_time - return full_datetime_result.time() - - -def subtract_times(start_time: datetime.time, delta_time: datetime.timedelta): - full_datetime_start = datetime.datetime.combine(datetime.date.today(), start_time) - full_datetime_result = full_datetime_start - delta_time - return full_datetime_result.time() - - -def add_seconds(time: datetime.time, seconds: int) -> datetime.time: - """ - Add seconds to datetime.time object and return resulting datetime.time object. - - :param time: - :param seconds: not limited to 0-59. - :return: - """ - - additional_seconds = seconds - - additional_hours = additional_seconds // 3600 - additional_seconds -= additional_hours * 3600 - - additional_minutes = additional_seconds // 60 - additional_seconds -= additional_minutes * 60 - - return add_times(time, datetime.timedelta(hours=additional_hours, - minutes=additional_minutes, - seconds=additional_seconds)) - - def range_with_bounds(start: int, stop: int, interval: int) -> List[int]: """Return list""" result = [int(val) for val in range(start, stop, interval)] @@ -202,8 +143,7 @@ def range_with_bounds(start: int, stop: int, interval: int) -> List[int]: def calculate_time_differences(time1, time2, interval): - total_difference = int(seconds_time_difference(time1, time2)) - differences = range_with_bounds(0, total_difference, interval) + differences = range_with_bounds(0, int((time2 - time1).total_seconds()), interval) return differences @@ -217,7 +157,7 @@ def interpolate_fixes(fix1, fix2, interval=1): :return: list of fixes between fix1 and fix2 with given interval """ - time_differences = calculate_time_differences(fix1['time'], fix2['time'], interval) + time_differences = calculate_time_differences(fix1['datetime'], fix2['datetime'], interval) fixes = list() for difference in time_differences: @@ -225,9 +165,8 @@ def interpolate_fixes(fix1, fix2, interval=1): lat = fix1['lat'] + fraction * (fix2['lat'] - fix1['lat']) lon = fix1['lon'] + fraction * (fix2['lon'] - fix1['lon']) - time = add_seconds(fix1['time'], difference) - - fixes.append(dict(time=time, lat=lat, lon=lon)) + time = fix1['datetime'] + datetime.timedelta(seconds=difference) + fixes.append(dict(datetime=time, lat=lat, lon=lon)) return fixes diff --git a/requirements.txt b/requirements.txt index 2104fd4..9e9810d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ pyproj -aerofiles -beautifulsoup4 -geojson -shapely +aerofiles==1.4.0 +beautifulsoup4==4.12.3 +geojson==3.1.0 +shapely==2.0.6 diff --git a/tests/competition/test_soaringspot.py b/tests/competition/test_soaringspot.py index a809cd7..569ccfc 100644 --- a/tests/competition/test_soaringspot.py +++ b/tests/competition/test_soaringspot.py @@ -194,5 +194,5 @@ def test_get_info_from_comment_lines_no_lcu_no_lseeyou(self): with open(igc_path, 'r', encoding='latin1') as f: parsed_igc_file = Reader().read(f) - task, contest_information, competitor_information = get_info_from_comment_lines(parsed_igc_file) + task, contest_information, competitor_information = get_info_from_comment_lines(parsed_igc_file, date=datetime.date(2023, 7, 4)) self.assertIsNone(task, None) diff --git a/tests/competition/test_strepla.py b/tests/competition/test_strepla.py index e9db984..5d09c47 100644 --- a/tests/competition/test_strepla.py +++ b/tests/competition/test_strepla.py @@ -9,7 +9,6 @@ from opensoar.competition.competitor import Competitor from opensoar.competition.strepla import get_waypoint_name_lat_long, get_waypoints, get_waypoint, get_task_and_competitor_info, get_info_from_comment_lines from opensoar.task.aat import AAT -from opensoar.utilities.helper_functions import seconds_time_difference class TestStrepla(unittest.TestCase): @@ -107,8 +106,11 @@ def test_aat_from_file(self): competitor = Competitor(trace, 'CX', 'Discus2b', 1, 'Karsten Leucker') competitor.analyse(task, 'pysoar') - time_diff = seconds_time_difference(competitor.trip.refined_start_time, datetime.time(13, 22, 40)) + self.assertEqual(competitor.trip.refined_start_time.hour, 13) + self.assertEqual(competitor.trip.refined_start_time.minute, 22) + seconds = competitor.trip.refined_start_time.second + dist_diff = sum(competitor.trip.distances) - 283500 - self.assertLessEqual(abs(time_diff), 1) + self.assertLessEqual(abs(seconds-40), 1) self.assertEqual(len(competitor.trip.fixes), len(expected_waypoints)) self.assertLessEqual(abs(dist_diff), 1000) diff --git a/tests/task/helper_functions.py b/tests/task/helper_functions.py index 66afb46..7d2bc5d 100644 --- a/tests/task/helper_functions.py +++ b/tests/task/helper_functions.py @@ -5,7 +5,7 @@ def get_trace(igc_path): with open(igc_path, 'r') as f: - parsed_igc_file = Reader().read(f) + parsed_igc_file = Reader(skip_duplicates=True).read(f) _, trace = parsed_igc_file['fix_records'] @@ -14,7 +14,7 @@ def get_trace(igc_path): def get_task(igc_path): with open(igc_path, 'r') as f: - parsed_igc_file = Reader().read(f) + parsed_igc_file = Reader(skip_duplicates=True).read(f) - task, contest_information, competitor_information = get_info_from_comment_lines(parsed_igc_file) + task, contest_information, competitor_information = get_info_from_comment_lines(parsed_igc_file, date=parsed_igc_file["header"][1]["utc_date"]) return task diff --git a/tests/task/test_aat_trip.py b/tests/task/test_aat_trip.py index 7ac4113..963e2bc 100644 --- a/tests/task/test_aat_trip.py +++ b/tests/task/test_aat_trip.py @@ -23,13 +23,13 @@ def test_total_distance(self): self.assertAlmostEqual(total_distance / 1e3, 199.42, places=2) def test_start_time(self): - start_time = self.trip.fixes[0]['time'] - expected_start_time = datetime.time(12, 22, 8) + start_time = self.trip.fixes[0]['datetime'] + expected_start_time = datetime.datetime(2012, 5, 26, 12, 22, 8, tzinfo=datetime.timezone.utc) self.assertEqual(expected_start_time, start_time) def test_finish_time(self): finish_time = self.trip.finish_time - expected_finish_time = datetime.time(15, 52, 8) + expected_finish_time = datetime.datetime(2012, 5, 26, 15, 52, 8, tzinfo=datetime.timezone.utc) self.assertEqual(expected_finish_time, finish_time) @@ -54,10 +54,10 @@ def test_trip_fixes(self): # assert if opensoar finds same fixes as seeyou, based on time fix_times = [ # tuple with (opensoar time, SeeYou time) - (self.trip.refined_start_time, datetime.time(12, 14, 21)), - (self.trip.fixes[1]['time'], datetime.time(12, 49, 22)), - (self.trip.fixes[2]['time'], datetime.time(13, 26, 14)), - (self.trip.outlanding_fix['time'], datetime.time(14, 8, 0)), + (self.trip.refined_start_time, datetime.datetime(2012, 5, 26, 12, 14, 21, tzinfo=datetime.timezone.utc)), + (self.trip.fixes[1]['datetime'], datetime.datetime(2012, 5, 26, 12, 49, 22, tzinfo=datetime.timezone.utc)), + (self.trip.fixes[2]['datetime'], datetime.datetime(2012, 5, 26, 13, 26, 14, tzinfo=datetime.timezone.utc)), + (self.trip.outlanding_fix['datetime'], datetime.datetime(2012, 5, 26, 14, 8, 0, tzinfo=datetime.timezone.utc)), ] for opensoar_time, seeyou_time in fix_times: @@ -90,11 +90,11 @@ def test_trip_fixes(self): # assert if opensoar finds same fixes as seeyou, based on time fix_times = [ # tuple with (opensoar time, SeeYou time) - (self.trip.refined_start_time, datetime.time(12, 24, 14)), - (self.trip.fixes[1]['time'], datetime.time(12, 57, 53)), - (self.trip.fixes[2]['time'], datetime.time(13, 42, 31)), - (self.trip.fixes[3]['time'], datetime.time(14, 4, 5)), - (self.trip.outlanding_fix['time'], datetime.time(14, 5, 49)), + (self.trip.refined_start_time, datetime.datetime(2012, 5, 26, 12, 24, 14, tzinfo=datetime.timezone.utc)), + (self.trip.fixes[1]['datetime'], datetime.datetime(2012, 5, 26, 12, 57, 53, tzinfo=datetime.timezone.utc)), + (self.trip.fixes[2]['datetime'], datetime.datetime(2012, 5, 26, 13, 42, 31, tzinfo=datetime.timezone.utc)), + (self.trip.fixes[3]['datetime'], datetime.datetime(2012, 5, 26, 14, 4, 5, tzinfo=datetime.timezone.utc)), + (self.trip.outlanding_fix['datetime'], datetime.datetime(2012, 5, 26, 14, 5, 49, tzinfo=datetime.timezone.utc)), ] for opensoar_time, seeyou_time in fix_times: diff --git a/tests/task/test_trip.py b/tests/task/test_trip.py index c792ba0..f6467ae 100644 --- a/tests/task/test_trip.py +++ b/tests/task/test_trip.py @@ -31,13 +31,12 @@ def test_outlanded(self): def test_start_time(self): start_fix = self.trip.fixes[0] refined_start_time = self.trip.refined_start_time - self.assertEqual(start_fix['time'], datetime.time(12, 12, 54)) - self.assertEqual(refined_start_time, datetime.time(12, 12, 55)) + self.assertEqual(start_fix['datetime'], datetime.datetime(2014, 6, 21, 12, 12, 54, tzinfo=datetime.timezone.utc)) + self.assertEqual(refined_start_time, datetime.datetime(2014, 6, 21, 12, 12, 55, tzinfo=datetime.timezone.utc)) def test_finish_time(self): finish_fix = self.trip.fixes[-1] - self.assertEqual(finish_fix['time'], datetime.time(13, 21, 58)) - + self.assertEqual(finish_fix['datetime'], datetime.datetime(2014, 6, 21, 13, 21, 58, tzinfo=datetime.timezone.utc)) class TestOutlandingTrip(unittest.TestCase): """ @@ -59,7 +58,7 @@ def test_completed_legs(self): def test_fix_after_leg_on_outlanding_leg(self): """A fix happening on the outlanding leg can never be after the leg, because that leg is never finished.""" - fix = {'time': datetime.time(14, 44, 45)} + fix = {'datetime': datetime.datetime(2014, 6, 21, 14, 44, 45)} fix_after_leg = self.trip.fix_after_leg(fix, leg=2) self.assertFalse(fix_after_leg) diff --git a/tests/thermals/test_flight_phases.py b/tests/thermals/test_flight_phases.py index dc82760..c68cfa0 100644 --- a/tests/thermals/test_flight_phases.py +++ b/tests/thermals/test_flight_phases.py @@ -5,7 +5,7 @@ from opensoar.task.trip import Trip from opensoar.thermals.flight_phases import FlightPhases -from opensoar.utilities.helper_functions import double_iterator, seconds_time_difference +from opensoar.utilities.helper_functions import double_iterator from tests.task.helper_functions import get_trace, get_task @@ -13,17 +13,17 @@ class TestFlightPhases(unittest.TestCase): pysoar_phase_start_times = [ - datetime.time(12, 12, 52), - datetime.time(12, 20, 22), - datetime.time(12, 24, 14), - datetime.time(12, 29, 22), - datetime.time(12, 33, 6), - datetime.time(12, 34, 50), - datetime.time(12, 37, 42), - datetime.time(12, 47, 14), - datetime.time(12, 52, 42), - datetime.time(13, 1, 0), - datetime.time(13, 4, 52), + datetime.datetime(2014, 6, 21, 12, 12, 52, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 20, 22, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 24, 14, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 29, 22, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 33, 6, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 34, 50, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 37, 42, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 47, 14, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 12, 52, 42, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 13, 1, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2014, 6, 21, 13, 4, 52, tzinfo=datetime.timezone.utc), ] cwd = os.path.dirname(__file__) @@ -47,7 +47,7 @@ def test_all_phases(self): # check if start times of phases are within 2 seconds for phase, pysoar_phase_start_time in zip(all_phases, self.pysoar_phase_start_times): - time_diff = seconds_time_difference(phase.fixes[0]['time'], pysoar_phase_start_time) + time_diff = (pysoar_phase_start_time - phase.fixes[0]['datetime']).total_seconds() self.assertLessEqual(abs(time_diff), 2) def test_thermals(self): @@ -60,7 +60,7 @@ def test_thermals(self): # check if correct phases are classified as thermals for thermal, pysoar_start_time in zip(thermals, self.pysoar_phase_start_times[1::2]): - time_diff = seconds_time_difference(thermal.fixes[0]['time'], pysoar_start_time) + time_diff = (pysoar_start_time - thermal.fixes[0]['datetime']).total_seconds() self.assertLessEqual(abs(time_diff), 2) def test_cruises(self): @@ -73,7 +73,7 @@ def test_cruises(self): # check if correct phases are classified as cruises for cruise, pysoar_start_time in zip(cruises, self.pysoar_phase_start_times[0::2]): - time_diff = seconds_time_difference(cruise.fixes[0]['time'], pysoar_start_time) + time_diff = (pysoar_start_time - cruise.fixes[0]['datetime']).total_seconds() self.assertLessEqual(abs(time_diff), 2) def test_thermals_on_leg(self): @@ -87,16 +87,18 @@ def test_thermals_on_leg(self): for thermal in thermals_leg2: self.assertFalse(thermal.is_cruise) - leg_start_time = self.trip.fixes[1]['time'] - leg_end_time = self.trip.fixes[2]['time'] + leg_start_time = self.trip.fixes[1]['datetime'] + leg_end_time = self.trip.fixes[2]['datetime'] - # check starttime of first thermal - start_time = thermals_leg2[0].fixes[0]['time'] - self.assertEqual(seconds_time_difference(start_time, leg_start_time), 0) + # check start-time of first thermal + start_time = thermals_leg2[0].fixes[0]['datetime'] + diff = (leg_start_time - start_time).total_seconds() + self.assertEqual(diff, 0) # check endtime of last thermal - end_time = thermals_leg2[-1].fixes[-1]['time'] - self.assertEqual(seconds_time_difference(end_time, leg_end_time), 0) + end_time = thermals_leg2[-1].fixes[-1]['datetime'] + diff = (leg_end_time - end_time).total_seconds() + self.assertEqual(diff, 0) def test_cruises_on_leg(self): @@ -114,21 +116,26 @@ def test_phases_on_leg_spanning_complete_leg(self): the end of the leg.""" trace = [ - {'time': datetime.time(11, 33, 26), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', + {'datetime': datetime.datetime(2012, 5, 26, 11, 33, 26, tzinfo=datetime.timezone.utc), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', 'pressure_alt': -37, 'gps_alt': 47, 'FXA': 2, 'SIU': 1}, - {'time': datetime.time(11, 33, 34), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', + {'datetime': datetime.datetime(2012, 5, 26, 11, 33, 34, tzinfo=datetime.timezone.utc), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', 'pressure_alt': -37, 'gps_alt': 47, 'FXA': 2, 'SIU': 1}, - {'time': datetime.time(11, 33, 42), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', + {'datetime': datetime.datetime(2012, 5, 26, 11, 33, 42, tzinfo=datetime.timezone.utc), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', 'pressure_alt': -37, 'gps_alt': 47, 'FXA': 2, 'SIU': 1}, - {'time': datetime.time(11, 33, 50), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', + {'datetime': datetime.datetime(2012, 5, 26, 11, 33, 50, tzinfo=datetime.timezone.utc), 'lat': 52.468183333333336, 'lon': 6.3402, 'validity': 'A', 'pressure_alt': -37, 'gps_alt': 48, 'FXA': 1, 'SIU': 1}, - {'time': datetime.time(11, 33, 58), 'lat': 52.468183333333336, 'lon': 6.340216666666667, 'validity': 'A', + {'datetime': datetime.datetime(2012, 5, 26, 11, 33, 58, tzinfo=datetime.timezone.utc), 'lat': 52.468183333333336, 'lon': 6.340216666666667, 'validity': 'A', 'pressure_alt': -37, 'gps_alt': 48, 'FXA': 1, 'SIU': 1}, - {'time': datetime.time(11, 34, 6), 'lat': 52.46816666666667, 'lon': 6.339666666666667, 'validity': 'A', + {'datetime': datetime.datetime(2012, 5, 26, 11, 34, 6, tzinfo=datetime.timezone.utc), 'lat': 52.46816666666667, 'lon': 6.339666666666667, 'validity': 'A', 'pressure_alt': -38, 'gps_alt': 49, 'FXA': 1, 'SIU': 1}, ] - trip = deepcopy(self.trip) + # originally this did trip = deepcopy(self._trip) + # but this is broken with current aerofiles version + _trace = get_trace(self.igc_path) + race_task = get_task(self.igc_path) + trip = Trip(race_task, _trace) + trip.fixes = [ trace[1], trace[4] @@ -139,8 +146,8 @@ def test_phases_on_leg_spanning_complete_leg(self): # there should only be one phase: starting at first fix and ending at last fix of trace # these are conditions to a correct test setup, therefore no actual tests assert len(phases._phases) == 1 - assert phases._phases[0].fixes[0]['time'] == trace[0]['time'] - assert phases._phases[0].fixes[-1]['time'] == trace[-1]['time'] + assert phases._phases[0].fixes[0]['datetime'] == trace[0]['datetime'] + assert phases._phases[0].fixes[-1]['datetime'] == trace[-1]['datetime'] all_phases_leg0 = phases.all_phases(leg=0) @@ -150,5 +157,5 @@ def test_phases_on_leg_spanning_complete_leg(self): # check if phase correctly starts and ends at the trip fixes and not the trace fixes first_phase_fix = all_phases_leg0[0].fixes[0] last_phase_fix = all_phases_leg0[0].fixes[-1] - self.assertEqual(first_phase_fix['time'], trip.fixes[0]['time']) - self.assertEqual(last_phase_fix['time'], trip.fixes[-1]['time']) + self.assertEqual(first_phase_fix['datetime'], trip.fixes[0]['datetime']) + self.assertEqual(last_phase_fix['datetime'], trip.fixes[-1]['datetime']) diff --git a/tests/utilities/test_helper_functions.py b/tests/utilities/test_helper_functions.py index 616d37a..730d554 100644 --- a/tests/utilities/test_helper_functions.py +++ b/tests/utilities/test_helper_functions.py @@ -2,12 +2,11 @@ import datetime -from opensoar.utilities.helper_functions import seconds_time_difference, interpolate_fixes, dm2dd, dms2dd, \ - both_none_or_same_float, both_none_or_same_str, add_times, subtract_times +from opensoar.utilities.helper_functions import interpolate_fixes, dm2dd, dms2dd, \ + both_none_or_same_float, both_none_or_same_str from opensoar.utilities.helper_functions import double_iterator from opensoar.utilities.helper_functions import triple_iterator from opensoar.utilities.helper_functions import calculate_distance_bearing -from opensoar.utilities.helper_functions import add_seconds from opensoar.utilities.helper_functions import range_with_bounds from opensoar.utilities.helper_functions import calculate_time_differences @@ -31,43 +30,6 @@ def test_calculate_distance_equal_fixes(self): self.assertEqual(calculate_distance_bearing(fix1, fix2)[0], 0) - def test_seconds_time_difference(self): - - time1 = datetime.time(0, 0, 10) - time2 = datetime.time(0, 0, 15) - - result = seconds_time_difference(time1, time2) - expected_result = 5 - - self.assertEqual(result, expected_result) - - def test_add_seconds(self): - - time1 = datetime.time(12, 0, 0) - time2 = datetime.time(12, 0, 55) - - self.assertEqual(add_seconds(time1, 20), datetime.time(12, 0, 20)) - self.assertEqual(add_seconds(time2, 20), datetime.time(12, 1, 15)) - self.assertEqual(add_seconds(time1, 3665), datetime.time(13, 1, 5)) - - def test_add_times(self): - time1 = datetime.time(12, 0, 0) - time2 = datetime.timedelta(hours=1, minutes=10, seconds=20) - - result = add_times(time1, time2) - expected_result = datetime.time(13, 10, 20) - - self.assertEqual(result, expected_result) - - def test_subtract_times(self): - time1 = datetime.time(12, 20, 10) - time2 = datetime.timedelta(hours=1, minutes=10, seconds=5) - - result = subtract_times(time1, time2) - expected_result = datetime.time(11, 10, 5) - - self.assertEqual(result, expected_result) - def test_range_with_bounds(self): self.assertListEqual(range_with_bounds(start=2, stop=4, interval=2), [2, 4]) self.assertListEqual(range_with_bounds(start=2, stop=6, interval=2), [2, 4, 6]) @@ -76,16 +38,16 @@ def test_range_with_bounds(self): def test_calculate_time_differences(self): - time1 = datetime.time(12, 0, 50) - time2 = datetime.time(12, 0, 55) - time3 = datetime.time(12, 1, 2) + time1 = datetime.datetime(2012, 5, 26, 12, 0, 50, tzinfo=datetime.timezone.utc) + time2 = datetime.datetime(2012, 5, 26, 12, 0, 55, tzinfo=datetime.timezone.utc) + time3 = datetime.datetime(2012, 5, 26, 12, 1, 2, tzinfo=datetime.timezone.utc) self.assertListEqual(calculate_time_differences(time1, time2, 2), [0, 2, 4, 5]) self.assertListEqual(calculate_time_differences(time2, time3, 2), [0, 2, 4, 6, 7]) def test_interpolate_fixes(self): - fix1 = dict(time=datetime.time(12, 0, 10), lat=50, lon=6) - fix2 = dict(time=datetime.time(12, 0, 14), lat=58, lon=8) + fix1 = dict(datetime=datetime.datetime(2012, 5, 26, 12, 0, 10, tzinfo=datetime.timezone.utc), lat=50, lon=6) + fix2 = dict(datetime=datetime.datetime(2012, 5, 26, 12, 0, 14, tzinfo=datetime.timezone.utc), lat=58, lon=8) interpolated_fixes = interpolate_fixes(fix1, fix2) @@ -93,18 +55,18 @@ def test_interpolate_fixes(self): self.assertEqual(len(interpolated_fixes), 5) times = [ - datetime.time(12, 0, 10), - datetime.time(12, 0, 11), - datetime.time(12, 0, 12), - datetime.time(12, 0, 13), - datetime.time(12, 0, 14) + datetime.datetime(2012, 5, 26, 12, 0, 10, tzinfo=datetime.timezone.utc), + datetime.datetime(2012, 5, 26, 12, 0, 11, tzinfo=datetime.timezone.utc), + datetime.datetime(2012, 5, 26, 12, 0, 12, tzinfo=datetime.timezone.utc), + datetime.datetime(2012, 5, 26, 12, 0, 13, tzinfo=datetime.timezone.utc), + datetime.datetime(2012, 5, 26, 12, 0, 14, tzinfo=datetime.timezone.utc) ] lats = [50, 52, 54, 56, 58] lons = [6, 6.5, 7.0, 7.5, 8.0] # check individual entries for time, lat, lon, interpolated_fix in zip(times, lats, lons, interpolated_fixes): - self.assertEqual(interpolated_fix['time'], time) + self.assertEqual(interpolated_fix['datetime'], time) self.assertEqual(interpolated_fix['lat'], lat) self.assertEqual(interpolated_fix['lon'], lon)