From 78baf38746081f59ccc96e080e63887304933362 Mon Sep 17 00:00:00 2001 From: Xavier Olive Date: Mon, 28 Oct 2024 21:55:49 +0100 Subject: [PATCH 1/4] fix #466 flight.split --- src/traffic/core/flight.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/traffic/core/flight.py b/src/traffic/core/flight.py index f2de0b40..5d301fed 100644 --- a/src/traffic/core/flight.py +++ b/src/traffic/core/flight.py @@ -116,17 +116,17 @@ def _split( # This method helps splitting a flight into several. if data.shape[0] < 2: return - diff = data.timestamp.diff().values + diff = data.timestamp.diff() if unit is None: delta = pd.Timedelta(value).to_timedelta64() else: delta = np.timedelta64(value, unit) # There seems to be a change with numpy >= 1.18 # max() now may return NaN, therefore the following fix - max_ = np.nanmax(diff) + max_ = diff.max() if max_ > delta: # np.nanargmax seems bugged with timestamps - argmax = np.where(diff == max_)[0][0] + argmax = diff.argmax() yield from _split(data.iloc[:argmax], value, unit) yield from _split(data.iloc[argmax:], value, unit) else: @@ -1490,7 +1490,7 @@ def split( - in the NumPy style: ``Flight.split(10, 'm')`` (see ``np.timedelta64``); - - in the pandas style: ``Flight.split('10T')`` (see ``pd.Timedelta``) + - in the pandas style: ``Flight.split('10 min')`` (see ``pd.Timedelta``) If the `condition` parameter is set, the flight is split between two segments only if `condition(f1, f2)` is verified. @@ -2720,6 +2720,7 @@ def query_ehs( self, data: Union[None, pd.DataFrame, "RawData"] = None, failure_mode: str = "info", + **kwargs: Any, ) -> Flight: """Extends data with extra columns from EHS messages. @@ -2779,7 +2780,9 @@ def fail_silent() -> Flight: failure = failure_dict[failure_mode] if data is None: - ext = opensky.extended(self.start, self.stop, icao24=self.icao24) + ext = opensky.extended( + self.start, self.stop, icao24=self.icao24, **kwargs + ) df = ext.data if ext is not None else None else: df = data if isinstance(data, pd.DataFrame) else data.data @@ -2793,11 +2796,7 @@ def fail_silent() -> Flight: timestamped_df = ( df.sort_values("mintime") - .assign( - timestamp=lambda df: pd.to_datetime( - df.mintime, unit="s", utc=True - ) - ) + .assign(timestamp=lambda df: df.mintime) # TODO shouldn't be necessary after pyopensky 2.10 .convert_dtypes(dtype_backend="pyarrow") ) @@ -2805,7 +2804,9 @@ def fail_silent() -> Flight: referenced_df = ( timestamped_df.merge( # TODO shouldn't be necessary after pyopensky 2.10 - self.data.convert_dtypes(dtype_backend="pyarrow"), + self.data.convert_dtypes(dtype_backend="pyarrow").assign( + timestamp=lambda df: df.timestamp.astype("int64") * 1e-9 + ), on="timestamp", how="outer", ) @@ -2829,7 +2830,7 @@ def fail_silent() -> Flight: decoded = rs1090.decode( referenced_df.rawmsg, - referenced_df.timestamp.astype("int64") * 1e-9, + referenced_df.timestamp.astype("int64"), ) if len(decoded) == 0: From afae804163bed86c3a78213cdef2c09a9a393436 Mon Sep 17 00:00:00 2001 From: Xavier Olive Date: Mon, 28 Oct 2024 21:56:02 +0100 Subject: [PATCH 2/4] fix #467 flight.phases --- src/traffic/algorithms/openap.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/traffic/algorithms/openap.py b/src/traffic/algorithms/openap.py index 88a0363a..9b9e990a 100644 --- a/src/traffic/algorithms/openap.py +++ b/src/traffic/algorithms/openap.py @@ -32,8 +32,7 @@ def phases(self, twindow: int = 60) -> "Flight": fp = FlightPhase() fp.set_trajectory( - (self.data.timestamp.values - np.datetime64("1970-01-01")) - / np.timedelta64(1, "s"), + (self.data.timestamp.astype(int) // 1_000_000_000).values, altitude, groundspeed, vertical_rate, From f77c0f787a14725c3090da5a49b3d312167713a0 Mon Sep 17 00:00:00 2001 From: Xavier Olive Date: Mon, 28 Oct 2024 21:59:41 +0100 Subject: [PATCH 3/4] fix #465 onground, alert and spi are now already bool with trino/sqlalchemy --- src/traffic/data/adsb/opensky.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/traffic/data/adsb/opensky.py b/src/traffic/data/adsb/opensky.py index 3c0d2a9d..87ceb03a 100644 --- a/src/traffic/data/adsb/opensky.py +++ b/src/traffic/data/adsb/opensky.py @@ -150,11 +150,6 @@ def format_history( if column_name in df.columns: df[column_name] = df[column_name].astype(float) - if "onground" in df.columns and df.onground.dtype != bool: - df.onground = df.onground == "true" - df.alert = df.alert == "true" - df.spi = df.spi == "true" - # better (to me) formalism about columns df = df.rename( columns={ From 1459c803f27045abdc2453ac0a613524392bcd58 Mon Sep 17 00:00:00 2001 From: Xavier Olive Date: Mon, 28 Oct 2024 22:11:44 +0100 Subject: [PATCH 4/4] fix #465 to_datetime now returns a pd.Timestamp --- src/traffic/core/time.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traffic/core/time.py b/src/traffic/core/time.py index 3a730c71..c4e06530 100644 --- a/src/traffic/core/time.py +++ b/src/traffic/core/time.py @@ -24,7 +24,7 @@ _log = logging.getLogger(__name__) -def to_datetime(time: timelike) -> datetime: +def to_datetime(time: timelike) -> pd.Timestamp: """Facility to convert anything to a datetime. This function will soon be replaced by pd.to_datetime. @@ -41,10 +41,10 @@ def to_datetime(time: timelike) -> datetime: if isinstance(time, str): time = pd.Timestamp(time, tz="utc") - if isinstance(time, pd.Timestamp): - time = time.to_pydatetime() + if isinstance(time, datetime): + time = pd.Timestamp(time) if isinstance(time, Real): - time = datetime.fromtimestamp(float(time), timezone.utc) + time = pd.Timestamp(float(time), tz="utc", unit="s") if time.tzinfo is None: # coverage: ignore _log.warning( "This timestamp is tz-naive. Things may not work as expected. "