Skip to content

Commit 7e9ce27

Browse files
adapt tp new api routes
1 parent f8e1339 commit 7e9ce27

File tree

8 files changed

+163
-194
lines changed

8 files changed

+163
-194
lines changed

app/callbacks/data_callbacks.py

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
# See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0> for full license details.
55

66
import json
7-
from datetime import datetime, timedelta
7+
from io import StringIO
88

99
import dash
1010
import logging_config
1111
import pandas as pd
12-
from dash import dcc, html
12+
from dash import callback_context, dcc, html
1313
from dash.dependencies import Input, Output, State
1414
from dash.exceptions import PreventUpdate
1515
from main import app
1616

1717
import config as cfg
1818
from services import api_client, get_token
19-
from utils.data import assign_event_ids, process_bbox, read_stored_DataFrame
19+
from utils.data import process_bbox
2020

2121
logger = logging_config.configure_logging(cfg.DEBUG, cfg.SENTRY_DSN)
2222

@@ -145,19 +145,19 @@ def get_cameras(user_token):
145145
logger.info("Get cameras data")
146146
cameras = pd.DataFrame(api_client.fetch_cameras().json())
147147

148-
return json.dumps({"data": cameras.to_json(orient="split"), "data_loaded": True})
148+
return cameras.to_json(orient="split")
149149

150150

151151
@app.callback(
152-
Output("api_detections", "data"),
152+
Output("api_sequences", "data"),
153153
[Input("main_api_fetch_interval", "n_intervals"), Input("api_cameras", "data")],
154154
[
155-
State("api_detections", "data"),
155+
State("api_sequences", "data"),
156156
State("user_token", "data"),
157157
],
158158
prevent_initial_call=True,
159159
)
160-
def api_watcher(n_intervals, api_cameras, local_detections, user_token):
160+
def api_watcher(n_intervals, api_cameras, local_sequences, user_token):
161161
"""
162162
Callback to periodically fetch alerts data from the API.
163163
@@ -176,27 +176,82 @@ def api_watcher(n_intervals, api_cameras, local_detections, user_token):
176176
if user_token is None:
177177
raise PreventUpdate
178178

179-
logger.info("Start Fetching the events")
180-
# Fetch Detections
181-
previous_time_event = (datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d_%H:%M:%S")
182-
response = api_client.fetch_unlabeled_detections(from_date=previous_time_event, limit=50)
183-
api_detections = pd.DataFrame(response.json())
184-
185-
local_detections, _ = read_stored_DataFrame(local_detections)
186-
if len(api_detections) == 0:
187-
return json.dumps(
188-
{
189-
"data": pd.DataFrame().to_json(orient="split"),
190-
"data_loaded": True,
191-
}
192-
)
179+
logger.info("Start Fetching Sequences")
180+
# Fetch Sequences
181+
response = api_client.fetch_latest_sequences()
182+
api_sequences = pd.DataFrame(response.json())
183+
184+
local_sequences = pd.read_json(StringIO(local_sequences), orient="split")
185+
if len(api_sequences) == 0:
186+
return pd.DataFrame().to_json(orient="split")
193187

194188
else:
195-
api_detections["processed_bboxes"] = api_detections["bboxes"].apply(process_bbox)
196-
api_detections = assign_event_ids(api_detections, time_threshold=30 * 60)
197-
if not local_detections.empty:
198-
aligned_api_detections, aligned_local_detections = api_detections["id"].align(local_detections["id"])
199-
if all(aligned_api_detections == aligned_local_detections):
189+
if not local_sequences.empty:
190+
aligned_api_sequences, aligned_local_sequences = api_sequences["id"].align(local_sequences["id"])
191+
if all(aligned_api_sequences == aligned_local_sequences):
200192
return dash.no_update
201193

202-
return json.dumps({"data": api_detections.to_json(orient="split"), "data_loaded": True})
194+
return api_sequences.to_json(orient="split")
195+
196+
197+
@app.callback(
198+
[Output("are_detections_loaded", "data"), Output("sequence_on_display", "data"), Output("api_detections", "data")],
199+
[Input("api_sequences", "data"), Input("sequence_id_on_display", "data"), Input("api_detections", "data")],
200+
State("are_detections_loaded", "data"),
201+
prevent_initial_call=True,
202+
)
203+
def load_detections(api_sequences, sequence_id_on_display, api_detections, are_detections_loaded):
204+
# Deserialize data
205+
api_sequences = pd.read_json(StringIO(api_sequences), orient="split")
206+
sequence_id_on_display = str(sequence_id_on_display)
207+
are_detections_loaded = json.loads(are_detections_loaded)
208+
api_detections = json.loads(api_detections)
209+
210+
# Initialize sequence_on_display
211+
sequence_on_display = pd.DataFrame().to_json(orient="split")
212+
213+
# Identify which input triggered the callback
214+
ctx = callback_context
215+
if not ctx.triggered:
216+
raise PreventUpdate
217+
218+
triggered_input = ctx.triggered[0]["prop_id"].split(".")[0]
219+
220+
if triggered_input == "sequence_id_on_display":
221+
# If the displayed sequence changes, load its detections if not already loaded
222+
if sequence_id_on_display not in api_detections:
223+
response = api_client.fetch_sequences_detections(sequence_id_on_display)
224+
detections = pd.DataFrame(response.json())
225+
detections["processed_bboxes"] = detections["bboxes"].apply(process_bbox)
226+
api_detections[sequence_id_on_display] = detections.to_json(orient="split")
227+
228+
sequence_on_display = api_detections[sequence_id_on_display]
229+
last_seen_at = api_sequences.loc[
230+
api_sequences["id"].astype("str") == sequence_id_on_display, "last_seen_at"
231+
].iloc[0]
232+
233+
# Ensure last_seen_at is stored as a string
234+
are_detections_loaded[sequence_id_on_display] = str(last_seen_at)
235+
236+
else:
237+
# If no specific sequence is triggered, load detections for the first missing sequence
238+
for _, row in api_sequences.iterrows():
239+
sequence_id = str(row["id"])
240+
last_seen_at = row["last_seen_at"]
241+
242+
if sequence_id not in are_detections_loaded or are_detections_loaded[sequence_id] != str(last_seen_at):
243+
response = api_client.fetch_sequences_detections(sequence_id)
244+
detections = pd.DataFrame(response.json())
245+
detections["processed_bboxes"] = detections["bboxes"].apply(process_bbox)
246+
api_detections[sequence_id] = detections.to_json(orient="split")
247+
are_detections_loaded[sequence_id] = str(last_seen_at)
248+
break
249+
250+
# Clean up old sequences that are no longer in api_sequences
251+
sequences_in_api = api_sequences["id"].astype("str").values
252+
to_drop = [key for key in are_detections_loaded if key not in sequences_in_api]
253+
for key in to_drop:
254+
are_detections_loaded.pop(key, None)
255+
256+
# Serialize and return data
257+
return json.dumps(are_detections_loaded), sequence_on_display, json.dumps(api_detections)

0 commit comments

Comments
 (0)