diff --git a/ogn/collect/takeoff_landing.py b/ogn/collect/takeoff_landing.py index 26f53b6..539e60c 100644 --- a/ogn/collect/takeoff_landing.py +++ b/ogn/collect/takeoff_landing.py @@ -54,7 +54,22 @@ def update_takeoff_landing(session=None): func.lead(AircraftBeacon.id).over(order_by=wo).label('id_next'), AircraftBeacon.device_id, func.lag(AircraftBeacon.device_id).over(order_by=wo).label('device_id_prev'), - func.lead(AircraftBeacon.device_id).over(order_by=wo).label('device_id_next')) \ + func.lead(AircraftBeacon.device_id).over(order_by=wo).label('device_id_next'), + AircraftBeacon.timestamp, + func.lag(AircraftBeacon.timestamp).over(order_by=wo).label('timestamp_prev'), + func.lead(AircraftBeacon.timestamp).over(order_by=wo).label('timestamp_next'), + AircraftBeacon.location_wkt, + func.lag(AircraftBeacon.location_wkt).over(order_by=wo).label('location_wkt_prev'), + func.lead(AircraftBeacon.location_wkt).over(order_by=wo).label('location_wkt_next'), + AircraftBeacon.track, + func.lag(AircraftBeacon.track).over(order_by=wo).label('track_prev'), + func.lead(AircraftBeacon.track).over(order_by=wo).label('track_next'), + AircraftBeacon.ground_speed, + func.lag(AircraftBeacon.ground_speed).over(order_by=wo).label('ground_speed_prev'), + func.lead(AircraftBeacon.ground_speed).over(order_by=wo).label('ground_speed_next'), + AircraftBeacon.altitude, + func.lag(AircraftBeacon.altitude).over(order_by=wo).label('altitude_prev'), + func.lead(AircraftBeacon.altitude).over(order_by=wo).label('altitude_next')) \ .filter(AircraftBeacon.id == beacon_selection.c.id) \ .subquery() @@ -63,77 +78,48 @@ def update_takeoff_landing(session=None): .filter(sq.c.device_id_prev == sq.c.device_id == sq.c.device_id_next) \ .subquery() - # Get timestamps, locations, tracks, ground_speeds and altitudes - prev_ab = aliased(AircraftBeacon, name="prev_ab") - lead_ab = aliased(AircraftBeacon, name="lead_ab") - + # find possible takeoffs and landings sq3 = session.query( sq2.c.id, - sq2.c.id_prev, - sq2.c.id_next, - sq2.c.device_id, - sq2.c.device_id_prev, - sq2.c.device_id_next, - AircraftBeacon.timestamp, - prev_ab.timestamp.label('timestamp_prev'), - lead_ab.timestamp.label('timestamp_next'), - AircraftBeacon.location_wkt, - prev_ab.location_wkt.label('location_wkt_prev'), - lead_ab.location_wkt.label('location_wkt_next'), - AircraftBeacon.track, - prev_ab.track.label('track_prev'), - lead_ab.track.label('track_next'), - AircraftBeacon.ground_speed, - prev_ab.ground_speed.label('ground_speed_prev'), - lead_ab.ground_speed.label('ground_speed_next'), - AircraftBeacon.altitude, - prev_ab.altitude.label('altitude_prev'), - lead_ab.altitude.label('altitude_next')) \ - .filter(and_(sq2.c.id == AircraftBeacon.id, sq2.c.id_prev == prev_ab.id, sq2.c.id_next == lead_ab.id)) \ - .subquery() - - # find possible takeoffs and landings - sq4 = session.query( - sq3.c.id, - sq3.c.timestamp, - case([(sq3.c.ground_speed > takeoff_speed, sq3.c.location_wkt_prev), # on takeoff we take the location from the previous fix because it is nearer to the airport - (sq3.c.ground_speed < landing_speed, sq3.c.location)]).label('location'), - case([(sq3.c.ground_speed > takeoff_speed, sq3.c.track), - (sq3.c.ground_speed < landing_speed, sq3.c.track_prev)]).label('track'), # on landing we take the track from the previous fix because gliders tend to leave the runway quickly - sq3.c.ground_speed, - sq3.c.altitude, - case([(sq3.c.ground_speed > takeoff_speed, True), - (sq3.c.ground_speed < landing_speed, False)]).label('is_takeoff'), - sq3.c.device_id) \ - .filter(sq3.c.timestamp_next - sq3.c.timestamp_prev < timedelta(seconds=duration)) \ - .filter(and_(func.ST_DFullyWithin(sq3.c.location, sq3.c.location_wkt_prev, radius), - func.ST_DFullyWithin(sq3.c.location, sq3.c.location_wkt_next, radius))) \ - .filter(or_(and_(sq3.c.ground_speed_prev < takeoff_speed, # takeoff - sq3.c.ground_speed > takeoff_speed, - sq3.c.ground_speed_next > takeoff_speed), - and_(sq3.c.ground_speed_prev > landing_speed, # landing - sq3.c.ground_speed < landing_speed, - sq3.c.ground_speed_next < landing_speed))) \ + sq2.c.timestamp, + case([(sq2.c.ground_speed > takeoff_speed, sq2.c.location_wkt_prev), # on takeoff we take the location from the previous fix because it is nearer to the airport + (sq2.c.ground_speed < landing_speed, sq2.c.location)]).label('location'), + case([(sq2.c.ground_speed > takeoff_speed, sq2.c.track), + (sq2.c.ground_speed < landing_speed, sq2.c.track_prev)]).label('track'), # on landing we take the track from the previous fix because gliders tend to leave the runway quickly + sq2.c.ground_speed, + sq2.c.altitude, + case([(sq2.c.ground_speed > takeoff_speed, True), + (sq2.c.ground_speed < landing_speed, False)]).label('is_takeoff'), + sq2.c.device_id) \ + .filter(sq2.c.timestamp_next - sq2.c.timestamp_prev < timedelta(seconds=duration)) \ + .filter(and_(func.ST_DFullyWithin(sq2.c.location, sq2.c.location_wkt_prev, radius), + func.ST_DFullyWithin(sq2.c.location, sq2.c.location_wkt_next, radius))) \ + .filter(or_(and_(sq2.c.ground_speed_prev < takeoff_speed, # takeoff + sq2.c.ground_speed > takeoff_speed, + sq2.c.ground_speed_next > takeoff_speed), + and_(sq2.c.ground_speed_prev > landing_speed, # landing + sq2.c.ground_speed < landing_speed, + sq2.c.ground_speed_next < landing_speed))) \ .subquery() # consider them if they are near a airport - sq5 = session.query( - sq4.c.timestamp, - sq4.c.track, - sq4.c.is_takeoff, - sq4.c.device_id, + sq4 = session.query( + sq3.c.timestamp, + sq3.c.track, + sq3.c.is_takeoff, + sq3.c.device_id, Airport.id.label('airport_id')) \ - .filter(and_(func.ST_DFullyWithin(sq4.c.location, Airport.location_wkt, airport_radius), - between(sq4.c.altitude, Airport.altitude - airport_delta, Airport.altitude + airport_delta))) \ + .filter(and_(func.ST_DFullyWithin(sq3.c.location, Airport.location_wkt, airport_radius), + between(sq3.c.altitude, Airport.altitude - airport_delta, Airport.altitude + airport_delta))) \ .filter(between(Airport.style, 2, 5)) \ .subquery() # consider them only if they are not already existing in db - takeoff_landing_query = session.query(sq5) \ + takeoff_landing_query = session.query(sq4) \ .filter(~exists().where( - and_(TakeoffLanding.timestamp == sq5.c.timestamp, - TakeoffLanding.device_id == sq5.c.device_id, - TakeoffLanding.airport_id == sq5.c.airport_id))) + and_(TakeoffLanding.timestamp == sq4.c.timestamp, + TakeoffLanding.device_id == sq4.c.device_id, + TakeoffLanding.airport_id == sq4.c.airport_id))) # ... and save them ins = insert(TakeoffLanding).from_select((TakeoffLanding.timestamp,