From f6519fb2d64c190bc3942307ba389353b9851a6d Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:46:20 +0200 Subject: [PATCH 1/2] feat: add download sequence notebook --- ...oad_Sequences_from_a_DistantAlertAPI.ipynb | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 containers/notebooks/app/Download_Sequences_from_a_DistantAlertAPI.ipynb diff --git a/containers/notebooks/app/Download_Sequences_from_a_DistantAlertAPI.ipynb b/containers/notebooks/app/Download_Sequences_from_a_DistantAlertAPI.ipynb new file mode 100644 index 0000000..af39784 --- /dev/null +++ b/containers/notebooks/app/Download_Sequences_from_a_DistantAlertAPI.ipynb @@ -0,0 +1,140 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a1c721ae-469b-48d7-a1df-3cd24623b3ee", + "metadata": {}, + "source": [ + "# Intro\n", + "\n", + "This notebook aims at downloading sequences infos(images and bboxes) from a Distant/Real Pyronear Alert API isntance in order to recreate alerts/sequences with ease in local dev environnement\n", + "\n", + "You need to have accesses to a distant api and provide ```DISTANT_API_URL```, ```DISTANT_ALERT_API_LOGIN```, ```DISTANT_ALERT_API_PASSWORD```\n", + "\n", + "And obvisouly, fill ```SEQUENCE_ID_LIST``` with the sequence id you want in order to download related data\n", + "\n", + "\n", + "If you do not have anything from above, do not worry, you can use the notebook \"send_real_alerts\" to send some alerts to local env dev" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "649157c6-0ce3-4324-a7b6-15c911ddaf36", + "metadata": {}, + "outputs": [], + "source": [ + "SEQUENCE_ID_LIST = [13802, 9456]\n", + "BASE_DIRECTORY = \"alerts\" # directory where to put sequences data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e511d97-245c-45cc-9216-a16d31b663aa", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "from dotenv import load_dotenv\n", + "import os\n", + "\n", + "from pyroclient import Client\n", + "\n", + "load_dotenv(\"../.env\")\n", + "DISTANT_API_URL = os.environ.get(\"DISTANT_API_URL\")\n", + "DISTANT_ALERT_API_LOGIN = os.environ.get(\"DISTANT_ALERT_API_LOGIN\")\n", + "DISTANT_ALERT_API_PASSWORD = os.environ.get(\"DISTANT_ALERT_API_PASSWORD\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac07ba29-68d0-42d2-bafe-e94d961ec6c2", + "metadata": {}, + "outputs": [], + "source": [ + "token = requests.post(\n", + " f\"{DISTANT_API_URL}api/v1/login/creds\",\n", + " data={\"username\": DISTANT_ALERT_API_LOGIN, \"password\": DISTANT_ALERT_API_PASSWORD},\n", + " timeout=5,\n", + ").json()['access_token']\n", + "\n", + "api_client = Client(token, DISTANT_API_URL)\n", + "\n", + "# get cameras -> in order to get cam name from cam id\n", + "cameras = api_client.fetch_cameras().json()\n", + "\n", + "# define base directory\n", + "base_dir = os.path.join(BASE_DIRECTORY)\n", + "os.makedirs(base_dir, exist_ok=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3c12b1d-54f1-4d8d-b591-dc04ecc35db2", + "metadata": {}, + "outputs": [], + "source": [ + "for seq_id in SEQUENCE_ID_LIST: \n", + " sequences = api_client.fetch_sequences_detections(sequence_id=seq_id).json()\n", + "\n", + " cam_name = [item['name'] for item in cameras if item['id'] == sequences[0]['camera_id']][0]\n", + " created_at_rounded = sequences[0][\"created_at\"].split('.')[0].replace(':', '-').replace('T', '_')\n", + " \n", + " print(f\"== Download Alerts data for sequence ID {seq_id} - camera {cam_name} at {created_at_rounded}\")\n", + " \n", + " alert_dir = os.path.join(f\"{cam_name}_{created_at_rounded}\")\n", + " image_dir = os.path.join(base_dir,alert_dir, \"images\")\n", + " pred_dir = os.path.join(base_dir, alert_dir, \"labels_predictions\")\n", + " os.makedirs(image_dir, exist_ok=True)\n", + " os.makedirs(pred_dir, exist_ok=True)\n", + "\n", + " for seq in sequences:\n", + " \n", + " # bbox\n", + " #yolo_format_bbox = ' '.join(map(str,ast.literal_eval(seq[\"bboxes\"])[0]))\n", + " bboxes = seq[\"bboxes\"]\n", + "\n", + " bbox_file_name = seq[\"bucket_key\"][:-4] + \".txt\"\n", + " \n", + " with open(os.path.join(base_dir, alert_dir, \"labels_predictions\",bbox_file_name), 'w') as f:\n", + " f.write(bboxes)\n", + "\n", + " url = seq['url']\n", + " nom_fichier = seq[\"bucket_key\"]\n", + " # image\n", + " response = requests.get(url, stream=True)\n", + " if response.status_code == 200:\n", + " full_img_path = os.path.join(image_dir, nom_fichier)\n", + " with open(full_img_path, 'wb') as f:\n", + " for chunk in response.iter_content(1024):\n", + " f.write(chunk)\n", + " else:\n", + " print(f\"Error during download.\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.20" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From ab8252d3657e45e03b712f738f3469233bf0379c Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:46:37 +0200 Subject: [PATCH 2/2] updates .env.test --- .env.test | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.env.test b/.env.test index 7668648..254813f 100644 --- a/.env.test +++ b/.env.test @@ -20,3 +20,8 @@ S3_REGION=us-east-1 DB_UI_MAIL=dummy@pyronear.com DB_UI_PWD=strong-password + +# only usefull to download some real sequences from real/distant Pyronear alert API +DISTANT_API_URL='' +DISTANT_ALERT_API_LOGIN='' +DISTANT_ALERT_API_PASSWORD=''