<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ingénierie Des Données on Boris Dupoux</title><link>https://borisdupoux.com/fr/categories/ing%C3%A9nierie-des-donn%C3%A9es/</link><description>Recent content in Ingénierie Des Données on Boris Dupoux</description><generator>Hugo -- gohugo.io</generator><language>fr</language><lastBuildDate>Thu, 01 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://borisdupoux.com/fr/categories/ing%C3%A9nierie-des-donn%C3%A9es/index.xml" rel="self" type="application/rss+xml"/><item><title>Points d'intérêt et flux urbains dans le centre-ville de Fort-de-France à partir de données ouvertes</title><link>https://borisdupoux.com/fr/research/urban-flows-fort-de-france/</link><pubDate>Thu, 01 Oct 2026 00:00:00 +0000</pubDate><guid>https://borisdupoux.com/fr/research/urban-flows-fort-de-france/</guid><description>&lt;h2 id="contexte"&gt;&lt;a href="#contexte" class="header-anchor"&gt;&lt;/a&gt;Contexte
&lt;/h2&gt;&lt;p&gt;Fort-de-France (Martinique) ne dispose de presque aucune donnée ouverte
locale. Les jeux de données de la ville ont été mis à jour pour la dernière
fois en 2019, et il n&amp;rsquo;existe ni compteurs piétons publics, ni chiffres ouverts
de fréquentation des transports en commun, ni comptages routiers ouverts à
l&amp;rsquo;échelle du centre-ville. Le projet cherche à savoir jusqu&amp;rsquo;où les données
ouvertes nationales et des flux archivés en continu permettent de décrire le
centre-ville comme un système de &lt;strong&gt;points d&amp;rsquo;intérêt&lt;/strong&gt; (commerces,
administrations, établissements scolaires, santé, culture, portes d&amp;rsquo;entrée) et
de &lt;strong&gt;flux&lt;/strong&gt; (résidents, navetteurs, élèves, visiteurs, croisiéristes,
véhicules, bus) sur un horizon de dix ans (2016–2026).&lt;/p&gt;
&lt;p&gt;Aucune source ne répond seule à cette question. Le répertoire des
entreprises sait où sont les établissements, mais pas qui les fréquente. Le
recensement sait où les habitants dorment, mais pas où ils passent la
journée. Les flux de transport montrent les bus, pas leurs passagers ; les
calendriers d&amp;rsquo;escales montrent les navires, pas les croisiéristes à terre.
La démarche consiste donc à &lt;strong&gt;croiser de nombreuses sources hétérogènes&lt;/strong&gt; sur
un cadre spatial et temporel commun, pour que chacune comble un angle mort
des autres, puis à confronter le résultat aux rares signaux mesurés qui
existent.&lt;/p&gt;
&lt;h2 id="approche"&gt;&lt;a href="#approche" class="header-anchor"&gt;&lt;/a&gt;Approche
&lt;/h2&gt;&lt;p&gt;La méthode est issue d&amp;rsquo;un précédent projet de base de connaissances que j&amp;rsquo;ai
mené. Les données brutes sont immuables et adressées par leur contenu. Chaque
base de données est jetable et reconstruite à partir d&amp;rsquo;elles. Chaque valeur
conserve sa provenance, et un ensemble d&amp;rsquo;invariants est vérifié à chaque
reconstruction.&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 A[Catalogue des sources&lt;br/&gt;sources.yaml] --&gt; B[Stockage brut immuable&lt;br/&gt;sha256 + manifeste JSONL]
 C[Collecteurs planifiés&lt;br/&gt;Meta tous les 14 jours · GTFS-RT 60 s] --&gt; B
 B --&gt; D[Extracteurs versionnés&lt;br/&gt;Parquet normalisé]
 D --&gt; E[Entrepôt spatial DuckDB&lt;br/&gt;reconstruit, jamais modifié]
 E --&gt; F[Invariants QA I1–I6]
 E --&gt; G[Statistiques&lt;br/&gt;requetes/*.sql]
 E --&gt; H[Application de bureau&lt;br/&gt;carte + sélecteur temporel]
 G --&gt; I[Calage sur&lt;br/&gt;des signaux mesurés]&lt;/pre&gt;&lt;h2 id="méthodes"&gt;&lt;a href="#m%c3%a9thodes" class="header-anchor"&gt;&lt;/a&gt;Méthodes
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Acquisition.&lt;/strong&gt; Chaque téléchargement est haché (SHA-256) et consigné dans
un manifeste JSONL, et l&amp;rsquo;acquisition est idempotente. Les fichiers nationaux
de plus de 1 Go (répertoire Sirene des entreprises) sont lus sous forme
d&amp;rsquo;extraits distants par requêtes HTTP Range, filtrés sur la commune. La
requête de filtrage est enregistrée comme partie intégrante de la
provenance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sources éphémères.&lt;/strong&gt; Meta Movement Distribution ne conserve que 90 jours
en ligne : une tâche planifiée l&amp;rsquo;archive donc tous les 14 jours. Un
collecteur de bus interroge les positions des véhicules GTFS-RT toutes les
60 s et les prévisions toutes les 10 min, et compresse chaque journée en zip
avec une somme de contrôle SHA-256.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cadre spatial.&lt;/strong&gt; Les données sont stockées en WGS84 et calculées en
EPSG:5490 sur la grille INSEE de 200 m. Les points d&amp;rsquo;intérêt sont classés
selon une typologie unique (codes NAF, balises OSM, arrêts), avec une
famille, un poids et un rythme horaire sur sept créneaux.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modèles.&lt;/strong&gt; La présence horaire par carreau combine résidents (Filosofi
2021, répartis de manière dasymétrique sur les bâtiments), salariés, élèves
et touristes. Un modèle de Huff estime les zones de chalandise. Les
croisiéristes à terre sont modélisés à partir des horaires et des capacités
des navires. Un modèle gravitaire à l&amp;rsquo;échelle de l&amp;rsquo;île, avec affectation
BPR, couvre les visiteurs et le trafic de transit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Qualité.&lt;/strong&gt; Six invariants sont vérifiés, de la provenance à l&amp;rsquo;absence de
données personnelles. Les paramètres non confirmés sont consignés dans un
journal des décisions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sources-de-données"&gt;&lt;a href="#sources-de-donn%c3%a9es" class="header-anchor"&gt;&lt;/a&gt;Sources de données
&lt;/h2&gt;&lt;p&gt;Le croisement des sources est le cœur du projet. Les registres d&amp;rsquo;entreprises
(Sirene, BODACC, URSSAF) donnent le stock et la rotation des activités, mais
ne disent rien des personnes qui les entourent. Le recensement et les données
fiscales (RP, Filosofi) situent les habitants, leurs revenus et la vacance
des logements, mais seulement la nuit. Les fichiers de navettes et l&amp;rsquo;enquête
nationale de mobilité (MOBPRO, MOBSCO, EMP) disent qui se déplace, pourquoi
et quand. Les flux de transport, d&amp;rsquo;accidents et de qualité de l&amp;rsquo;air
(GTFS-RT, BAAC, Madininair) sont les seules traces mesurées du mouvement. Les
calendriers d&amp;rsquo;escales et les capacités des navires apportent une population
qu&amp;rsquo;aucun recensement ne compte. Les référentiels géographiques (IGN,
OpenStreetMap, grille INSEE de 200 m) rendent enfin tout cela comparable,
carreau par carreau.&lt;/p&gt;
&lt;p&gt;Le catalogue recense &lt;strong&gt;120 sources&lt;/strong&gt; : 51 intégrées, 32 à intégrer, 7 à
vérifier, 13 disponibles uniquement sur demande, 5 payantes, 1 sur
partenariat et 11 non retenues. Les tableaux ci-dessous listent toutes les
sources intégrées et résument les autres par thème.&lt;/p&gt;
&lt;h3 id="entreprises-emplois-et-équipements"&gt;&lt;a href="#entreprises-emplois-et-%c3%a9quipements" class="header-anchor"&gt;&lt;/a&gt;Entreprises, emplois et équipements
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Source&lt;/th&gt;
					&lt;th&gt;Apport&lt;/th&gt;
					&lt;th&gt;Période / fréquence&lt;/th&gt;
					&lt;th&gt;Statut&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/fr/datasets/base-sirene-des-entreprises-et-de-leurs-etablissements-siren-siret/" target="_blank" rel="noopener"
 &gt;Base Sirene des entreprises&lt;/a&gt; — INSEE&lt;/td&gt;
					&lt;td&gt;Établissements, code d&amp;rsquo;activité (NAF), dates de création et de fermeture, tranches d&amp;rsquo;effectif&lt;/td&gt;
					&lt;td&gt;Historique complet ; stock reconstituable à toute date 2016–2026&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;BODACC — DILA&lt;/td&gt;
					&lt;td&gt;Rotation et défaillances des commerces (ventes de fonds, procédures collectives)&lt;/td&gt;
					&lt;td&gt;2016–2026, quotidienne&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.insee.fr/fr/statistiques/8217525" target="_blank" rel="noopener"
 &gt;Base permanente des équipements (BPE)&lt;/a&gt; géolocalisée — INSEE&lt;/td&gt;
					&lt;td&gt;Commerces, services, santé, administrations, enseignement, sport, tourisme&lt;/td&gt;
					&lt;td&gt;Éditions 2024 et 2025, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://open.urssaf.fr/explore/dataset/etablissements-et-effectifs-salaries-au-niveau-commune-x-ape-last/" target="_blank" rel="noopener"
 &gt;Établissements et effectifs salariés commune × APE&lt;/a&gt; — URSSAF / Acoss&lt;/td&gt;
					&lt;td&gt;Emploi salarié privé par activité&lt;/td&gt;
					&lt;td&gt;2006–2025, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://data.education.gouv.fr/explore/dataset/fr-en-annuaire-education/" target="_blank" rel="noopener"
 &gt;Annuaire de l&amp;rsquo;éducation et effectifs d&amp;rsquo;élèves&lt;/a&gt; — MENJ / DEPP&lt;/td&gt;
					&lt;td&gt;Écoles, localisation, élèves par rentrée, personnels&lt;/td&gt;
					&lt;td&gt;Effectifs 2016–2025&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;FINESS — DREES / ARS&lt;/td&gt;
					&lt;td&gt;Établissements sanitaires et sociaux, pharmacies&lt;/td&gt;
					&lt;td&gt;Extraction de mai 2026, bimestrielle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://docs.overturemaps.org/guides/places" target="_blank" rel="noopener"
 &gt;Overture Maps (places)&lt;/a&gt; — Overture Maps Foundation&lt;/td&gt;
					&lt;td&gt;Points d&amp;rsquo;intérêt avec score de confiance (couche de comparaison)&lt;/td&gt;
					&lt;td&gt;Extrait figé de la release 2026-09-23, mensuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OpenStreetMap (Overpass) — contributeurs OpenStreetMap&lt;/td&gt;
					&lt;td&gt;Points d&amp;rsquo;intérêt, commerces, voirie, cheminements piétons&lt;/td&gt;
					&lt;td&gt;État courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Monuments historiques (Mérimée / POP) — ministère de la Culture&lt;/td&gt;
					&lt;td&gt;Attracteurs patrimoniaux (cathédrale, bibliothèque Schœlcher, fort Saint-Louis)&lt;/td&gt;
					&lt;td&gt;Courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;em&gt;23 autres&lt;/em&gt; — par ex. Flores, emploi salarié localisé (INSEE), Foursquare Open Source Places, LOCOMVAC, locaux commerciaux vacants (DGFiP), Google Places&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;Cataloguées&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="population-revenus-et-logement"&gt;&lt;a href="#population-revenus-et-logement" class="header-anchor"&gt;&lt;/a&gt;Population, revenus et logement
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Source&lt;/th&gt;
					&lt;th&gt;Apport&lt;/th&gt;
					&lt;th&gt;Période / fréquence&lt;/th&gt;
					&lt;th&gt;Statut&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.insee.fr/fr/statistiques/8647014" target="_blank" rel="noopener"
 &gt;Recensement, bases infracommunales IRIS (RP)&lt;/a&gt; — INSEE&lt;/td&gt;
					&lt;td&gt;Résidents, âge, CSP, logements (vacance, motorisation), actifs&lt;/td&gt;
					&lt;td&gt;RP 2016 → RP 2022, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.insee.fr/fr/statistiques/8229323" target="_blank" rel="noopener"
 &gt;Filosofi par IRIS&lt;/a&gt; — INSEE&lt;/td&gt;
					&lt;td&gt;Revenus disponibles et déclarés, pauvreté&lt;/td&gt;
					&lt;td&gt;2016–2021, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.insee.fr/fr/statistiques/fichier/8735162/Filosofi2021_carreaux_200m_csv.zip" target="_blank" rel="noopener"
 &gt;Filosofi carroyé 200 m, fichiers&lt;/a&gt; — INSEE&lt;/td&gt;
					&lt;td&gt;Ménages fiscaux, individus, pauvreté, logements sociaux et âges au carreau de 200 m&lt;/td&gt;
					&lt;td&gt;2015, 2017, 2019, 2021&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Filosofi carroyé 200 m, couche WFS Géoplateforme — INSEE&lt;/td&gt;
					&lt;td&gt;Géométries des carreaux&lt;/td&gt;
					&lt;td&gt;Couche 2015&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/536998cba3a729239d20505e" target="_blank" rel="noopener"
 &gt;IRCOM, impôt sur le revenu par commune&lt;/a&gt; — DGFiP&lt;/td&gt;
					&lt;td&gt;Foyers fiscaux, revenus déclarés&lt;/td&gt;
					&lt;td&gt;2016–2024, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://data.caf.fr/explore/dataset/s_ben_com_f/information/" target="_blank" rel="noopener"
 &gt;Cafdata&lt;/a&gt; — CNAF&lt;/td&gt;
					&lt;td&gt;Allocataires du RSA, des aides au logement et des prestations familiales&lt;/td&gt;
					&lt;td&gt;2020–2024 (2022 manquant), annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/5a561801c751df42d7fca9b6" target="_blank" rel="noopener"
 &gt;Quartiers prioritaires (QPV)&lt;/a&gt; — ANCT / INSEE&lt;/td&gt;
					&lt;td&gt;Géographie prioritaire, qui inclut le centre-ville&lt;/td&gt;
					&lt;td&gt;Contours 2024&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/61816c6e23197bb34835228e" target="_blank" rel="noopener"
 &gt;LOVAC&lt;/a&gt; — Cerema / DGALN&lt;/td&gt;
					&lt;td&gt;Vacance courte et structurelle (≥ 2 ans) du parc privé&lt;/td&gt;
					&lt;td&gt;Éditions 2020–2026, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;RPLS, parc locatif social — SDES&lt;/td&gt;
					&lt;td&gt;Logements sociaux (adresse, surface, loyer, vacance)&lt;/td&gt;
					&lt;td&gt;2023 et 2025&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Sitadel, permis de construire — SDES&lt;/td&gt;
					&lt;td&gt;Logements et locaux autorisés, commencés, démolis&lt;/td&gt;
					&lt;td&gt;2013–2026, mensuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://files.data.gouv.fr/geo-dvf/latest/csv/" target="_blank" rel="noopener"
 &gt;DVF géolocalisées&lt;/a&gt; — DGFiP / Etalab&lt;/td&gt;
					&lt;td&gt;Mutations immobilières (prix, surfaces, locaux commerciaux)&lt;/td&gt;
					&lt;td&gt;2021–2025, fenêtre glissante de 5 ans&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;em&gt;8 autres&lt;/em&gt; — par ex. fichiers détail du recensement et populations légales (INSEE), DV3F et Fichiers fonciers (Cerema / DGFiP), population carroyée WorldPop / GHSL&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;Cataloguées&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mobilité-et-transports"&gt;&lt;a href="#mobilit%c3%a9-et-transports" class="header-anchor"&gt;&lt;/a&gt;Mobilité et transports
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Source&lt;/th&gt;
					&lt;th&gt;Apport&lt;/th&gt;
					&lt;th&gt;Période / fréquence&lt;/th&gt;
					&lt;th&gt;Statut&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.insee.fr/fr/statistiques/8582949" target="_blank" rel="noopener"
 &gt;Mobilités professionnelles (MOBPRO)&lt;/a&gt; — INSEE&lt;/td&gt;
					&lt;td&gt;Navettes domicile → travail entre communes&lt;/td&gt;
					&lt;td&gt;2016–2022, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.insee.fr/fr/statistiques/8582969" target="_blank" rel="noopener"
 &gt;Mobilités scolaires (MOBSCO)&lt;/a&gt; — INSEE&lt;/td&gt;
					&lt;td&gt;Navettes domicile → études entre communes&lt;/td&gt;
					&lt;td&gt;2016–2022, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/donnees-detaillees-de-lenquete-mobilite-des-personnes-2018-2019" target="_blank" rel="noopener"
 &gt;Enquête mobilité des personnes 2018-2019 (EMP)&lt;/a&gt; — SDES&lt;/td&gt;
					&lt;td&gt;Motifs, horaires de départ et de retour, durées d&amp;rsquo;activité, distances&lt;/td&gt;
					&lt;td&gt;2018–2019&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://transport.data.gouv.fr/datasets/gtfs-urbain-de-la-zone-centre" target="_blank" rel="noopener"
 &gt;GTFS, réseau urbain zone Centre&lt;/a&gt; (Mozaïk, BHNS) — Martinique Transport&lt;/td&gt;
					&lt;td&gt;Offre théorique de transports collectifs&lt;/td&gt;
					&lt;td&gt;Archives depuis juin 2023&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;GTFS-RT, collecte continue — Martinique Transport&lt;/td&gt;
					&lt;td&gt;Vitesses observées des bus, bus en service, remplissage déclaré&lt;/td&gt;
					&lt;td&gt;Depuis le 7 octobre 2026 ; 60 s (positions), 10 min (prévisions)&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://transport.data.gouv.fr/datasets/gtfs-du-reseau-maritime-de-martinique" target="_blank" rel="noopener"
 &gt;GTFS, navettes maritimes&lt;/a&gt; — Martinique Transport&lt;/td&gt;
					&lt;td&gt;Navettes débarquant au front de mer&lt;/td&gt;
					&lt;td&gt;Versions depuis août 2024&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/53698f4ca3a729239d2036df/" target="_blank" rel="noopener"
 &gt;Accidents corporels de la circulation (BAAC)&lt;/a&gt; — ONISR&lt;/td&gt;
					&lt;td&gt;Accidents localisés (piétons, véhicules), avec l&amp;rsquo;heure&lt;/td&gt;
					&lt;td&gt;2016–2024 chargés&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://data.humdata.org/dataset/movement-distribution" target="_blank" rel="noopener"
 &gt;Movement Distribution&lt;/a&gt; — Meta Data for Good / HDX&lt;/td&gt;
					&lt;td&gt;Part des usagers restés à domicile, à moins de 10 km, entre 10 et 100 km, au-delà de 100 km&lt;/td&gt;
					&lt;td&gt;Quotidienne ; fenêtre de 90 jours, archivée tous les 14 jours&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://data.humdata.org/dataset/movement-range-maps" target="_blank" rel="noopener"
 &gt;Movement Range Maps&lt;/a&gt; — Meta Data for Good / HDX&lt;/td&gt;
					&lt;td&gt;Variation des déplacements, part des usagers restés sur place&lt;/td&gt;
					&lt;td&gt;Mars 2020 → mai 2022, quotidienne (arrêtée)&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;BD TOPO, réseau routier principal — IGN&lt;/td&gt;
					&lt;td&gt;Graphe routier de l&amp;rsquo;île pour l&amp;rsquo;affectation du trafic&lt;/td&gt;
					&lt;td&gt;Courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;BD TOPO, tronçons de route — IGN&lt;/td&gt;
					&lt;td&gt;Largeur de chaussée, voies et sens, pour métrer le stationnement le long des rues&lt;/td&gt;
					&lt;td&gt;Courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Parkings OpenStreetMap — contributeurs OpenStreetMap&lt;/td&gt;
					&lt;td&gt;Parkings, type, capacité déclarée&lt;/td&gt;
					&lt;td&gt;Courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;em&gt;18 autres&lt;/em&gt; — par ex. fréquentation et validations (Martinique Transport, sur demande), comptages routiers (sur demande), données de téléphonie Orange Flux Vision (payantes), Waze for Cities / Strava Metro (partenariat), campagne de comptages piétons (à créer)&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;Cataloguées&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="tourisme-et-croisière"&gt;&lt;a href="#tourisme-et-croisi%c3%a8re" class="header-anchor"&gt;&lt;/a&gt;Tourisme et croisière
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Source&lt;/th&gt;
					&lt;th&gt;Apport&lt;/th&gt;
					&lt;th&gt;Période / fréquence&lt;/th&gt;
					&lt;th&gt;Statut&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.cruisemapper.com/ports/fort-de-france-port-2382" target="_blank" rel="noopener"
 &gt;Calendrier des escales du port de Fort-de-France&lt;/a&gt; — CruiseMapper&lt;/td&gt;
					&lt;td&gt;Escales navire par navire, avec heures d&amp;rsquo;arrivée et de départ&lt;/td&gt;
					&lt;td&gt;Mars 2026 → mars 2029 ; archivage mensuel, les mois passés disparaissant du site&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.cruisemapper.com/ships" target="_blank" rel="noopener"
 &gt;Fiches navires&lt;/a&gt; — CruiseMapper&lt;/td&gt;
					&lt;td&gt;Capacité passagers, équipage, jauge des navires en escale&lt;/td&gt;
					&lt;td&gt;Courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Bilans de saison de croisière — Comité martiniquais du tourisme (CMT), via la presse&lt;/td&gt;
					&lt;td&gt;Croisiéristes et escales par saison, terminaux de croisière&lt;/td&gt;
					&lt;td&gt;Saisons 2024-2025 et 2025-2026&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://data.humdata.org/dataset/martinique-daily-port-activity-data-and-shipment-estimates" target="_blank" rel="noopener"
 &gt;PortWatch&lt;/a&gt; — FMI / HDX&lt;/td&gt;
					&lt;td&gt;Escales quotidiennes issues de l&amp;rsquo;AIS&lt;/td&gt;
					&lt;td&gt;2019–2026, quotidienne&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/64808a5811da153f1439914c" target="_blank" rel="noopener"
 &gt;Trafic aérien commercial mensuel&lt;/a&gt; — DGAC&lt;/td&gt;
					&lt;td&gt;Arrivées à l&amp;rsquo;aéroport Martinique Aimé Césaire (saisonnalité touristique)&lt;/td&gt;
					&lt;td&gt;1990–2025, mensuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/hebergements-touristiques-classes-en-france/" target="_blank" rel="noopener"
 &gt;Hébergements touristiques classés&lt;/a&gt; — Atout France&lt;/td&gt;
					&lt;td&gt;Hôtels et résidences classés, chambres et capacité&lt;/td&gt;
					&lt;td&gt;Stock courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.insee.fr/fr/statistiques/2021703" target="_blank" rel="noopener"
 &gt;Capacité des communes en hébergement touristique&lt;/a&gt; — INSEE&lt;/td&gt;
					&lt;td&gt;Hôtels par catégorie, campings, résidences, villages vacances&lt;/td&gt;
					&lt;td&gt;2015–2026, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;em&gt;7 autres&lt;/em&gt; — par ex. DATAtourisme (ADN Tourisme), enquête de fréquentation hôtelière (INSEE), Inside Airbnb / AirDNA, données d&amp;rsquo;escales du port&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;Cataloguées&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="contexte--météo-air-calendrier-sécurité"&gt;&lt;a href="#contexte--m%c3%a9t%c3%a9o-air-calendrier-s%c3%a9curit%c3%a9" class="header-anchor"&gt;&lt;/a&gt;Contexte : météo, air, calendrier, sécurité
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Source&lt;/th&gt;
					&lt;th&gt;Apport&lt;/th&gt;
					&lt;th&gt;Période / fréquence&lt;/th&gt;
					&lt;th&gt;Statut&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/donnees-climatologiques-de-base-horaires" target="_blank" rel="noopener"
 &gt;Données climatologiques de base&lt;/a&gt; — Météo-France&lt;/td&gt;
					&lt;td&gt;Pluie, température, vent (stations de Fort-de-France Desaix et du Lamentin)&lt;/td&gt;
					&lt;td&gt;2010–2026, horaire / quotidienne&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Qualité de l&amp;rsquo;air — Madininair&lt;/td&gt;
					&lt;td&gt;NO₂ comme indicateur indirect du trafic, ainsi que PM10, PM2,5, O₃ et H₂S des sargasses&lt;/td&gt;
					&lt;td&gt;Horaire ; NO₂ mensuel 2016–2026&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://www.data.gouv.fr/datasets/bases-statistiques-communale-departementale-et-regionale-de-la-delinquance-enregistree-par-la-police-et-la-gendarmerie-nationales" target="_blank" rel="noopener"
 &gt;Base communale de la délinquance enregistrée&lt;/a&gt; — SSMSI&lt;/td&gt;
					&lt;td&gt;Infractions enregistrées&lt;/td&gt;
					&lt;td&gt;2016–2025, annuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Jours fériés en Martinique — DINUM&lt;/td&gt;
					&lt;td&gt;Calendrier, dont le 22 mai&lt;/td&gt;
					&lt;td&gt;2006–2031&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://data.education.gouv.fr/explore/dataset/fr-en-calendrier-scolaire/" target="_blank" rel="noopener"
 &gt;Calendrier scolaire&lt;/a&gt; — MENJ&lt;/td&gt;
					&lt;td&gt;Vacances scolaires, dont celles de Carnaval&lt;/td&gt;
					&lt;td&gt;2017-2018 → 2026-2027&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Pageviews — Wikimedia Foundation&lt;/td&gt;
					&lt;td&gt;Intérêt en ligne pour Fort-de-France, le Carnaval et le patrimoine&lt;/td&gt;
					&lt;td&gt;2016–2026, mensuelle&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;em&gt;4 autres&lt;/em&gt; — par ex. lumières nocturnes NASA Black Marble, Google Trends / GDELT, agenda des événements (à constituer)&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;Cataloguées&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="géographie-et-fonds-de-carte"&gt;&lt;a href="#g%c3%a9ographie-et-fonds-de-carte" class="header-anchor"&gt;&lt;/a&gt;Géographie et fonds de carte
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Source&lt;/th&gt;
					&lt;th&gt;Apport&lt;/th&gt;
					&lt;th&gt;Période / fréquence&lt;/th&gt;
					&lt;th&gt;Statut&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Périmètres d&amp;rsquo;étude — projet&lt;/td&gt;
					&lt;td&gt;Centre-ville et centre élargi (provisoires, voir D1)&lt;/td&gt;
					&lt;td&gt;Version 0.1&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;API Découpage administratif (geo.api.gouv.fr) — DINUM / IGN / INSEE&lt;/td&gt;
					&lt;td&gt;Contour de la commune et population légale&lt;/td&gt;
					&lt;td&gt;Courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Contours IRIS — IGN / INSEE&lt;/td&gt;
					&lt;td&gt;Maille infracommunale du recensement&lt;/td&gt;
					&lt;td&gt;Couche courante&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://cartes.gouv.fr/rechercher-une-donnee/dataset/IGNF_BD-TOPO" target="_blank" rel="noopener"
 &gt;BD TOPO&lt;/a&gt; — IGN&lt;/td&gt;
					&lt;td&gt;Bâtiments (hauteur, usage), voirie, équipements&lt;/td&gt;
					&lt;td&gt;Éditions trimestrielles&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;BD TOPO, bâtiments résidentiels du centre élargi — IGN&lt;/td&gt;
					&lt;td&gt;Usage, hauteur et emprise, pour répartir les ménages dans les bâtiments&lt;/td&gt;
					&lt;td&gt;Édition courante&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Fond de carte vectoriel OpenStreetMap — contributeurs OpenStreetMap&lt;/td&gt;
					&lt;td&gt;Voirie, eau, parcs, littoral dessinés dans l&amp;rsquo;application&lt;/td&gt;
					&lt;td&gt;Courant&lt;/td&gt;
					&lt;td&gt;Intégrée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;em&gt;9 autres&lt;/em&gt; — par ex. cadastre Etalab, Base Adresse Nationale, BD ORTHO (IGN), PLU (Géoportail de l&amp;rsquo;Urbanisme), risques naturels (Géorisques)&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;Cataloguées&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="lapplication--cœur-de-ville-"&gt;&lt;a href="#lapplication--c%c5%93ur-de-ville-" class="header-anchor"&gt;&lt;/a&gt;L&amp;rsquo;application « Cœur de ville »
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;entrepôt s&amp;rsquo;explore dans une application de bureau (Electron, React, ECharts,
Leaflet sur OpenStreetMap, DuckDB lisant une copie de l&amp;rsquo;entrepôt). Elle est organisée
autour de quelques questions — qui est là, quand, qu&amp;rsquo;est-ce qui attire, le
stationnement suffit-il, qui dépend des transports collectifs, le centre gagne-t-il ou
perd-il — avec une carte toujours au même endroit, un sélecteur commun jour × créneau,
et chaque chiffre accompagné de sa source et de son statut.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Écran de synthèse : indicateurs clés, carte de présence en matinée au carreau de 200 m, rythme de la journée par population et flux horaires de voitures" class="gallery-image" data-flex-basis="395px" data-flex-grow="164" height="972" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-synthese.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-synthese_hu_1325b374e6fd7abc.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-synthese.jpg 1600w" width="1600"&gt;
&lt;em&gt;Synthèse — le centre en un coup d&amp;rsquo;œil : rapport jour/nuit, pression de stationnement,
commerces 2016 → 2026, pauvreté, prochaine grosse journée d&amp;rsquo;escale, présence au
carreau de 200 m et rythme de la journée des résidents, salariés, scolaires et touristes.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Écran des flux : carte animée de la présence par créneau et tableau semaine × créneau" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1122" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-flux.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-flux_hu_f9fb52a2d7d7124a.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-flux.jpg 1500w" width="1500"&gt;
&lt;em&gt;Flux et moments de vie — la présence par carreau pour tout jour et tout créneau,
lisible en animation sur la semaine, avec la courbe journalière empilée par population.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Écran des points d’intérêt : des milliers d’établissements par famille, carreaux les plus attractifs et courbes d’ouverture" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1122" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-poles.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-poles_hu_cf9d8514fb9c8d3d.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-poles.jpg 1500w" width="1500"&gt;
&lt;em&gt;Pôles d&amp;rsquo;attractivité — les établissements par famille (répertoire Sirene et
OpenStreetMap), les carreaux les plus attractifs au moment choisi et la part
d&amp;rsquo;établissements ouverts heure par heure.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Zoom à la rue : façade numéro par numéro, carte du secteur et évolution base 100" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1122" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-ilot-perrinon.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-ilot-perrinon_hu_7d284fe42d9fc670.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-ilot-perrinon.jpg 1500w" width="1500"&gt;
&lt;em&gt;Zoom sur un îlot — la façade de la rue numéro par numéro, les établissements actifs et
fermés depuis 2016, et l&amp;rsquo;évolution du secteur comparée à l&amp;rsquo;ensemble du centre.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Écran Évolution : score d’attractivité par carreau avec un curseur d’années 2016–2026 et indicateurs associés" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1122" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-evolution.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-evolution_hu_1eb289eca6678a0e.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-evolution.jpg 1500w" width="1500"&gt;
&lt;em&gt;Évolution 2016–2026 — l&amp;rsquo;attractivité par carreau avec un curseur d&amp;rsquo;années, les
créations et fermetures, les foyers fiscaux et d&amp;rsquo;autres signaux croisés sur la même
grille.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Écran Stationnement : taux d’occupation théorique par carreau avec des hypothèses réglables en direct" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1122" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-stationnement.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-stationnement_hu_8141213c09f19e60.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-stationnement.jpg 1500w" width="1500"&gt;
&lt;em&gt;Stationnement — l&amp;rsquo;offre reconstruite rue par rue et le taux d&amp;rsquo;occupation théorique par
carreau et par créneau ; chaque hypothèse (longueur de place, largeur de voie, part
modale…) est un curseur et le résultat est recalculé en SQL.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Pression de stationnement un matin de semaine : carreaux colorés par le taux d’occupation théorique, hypothèses et tableau semaine × créneau" class="gallery-image" data-flex-basis="425px" data-flex-grow="177" height="846" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-pression-parking.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-pression-parking_hu_48b3b457873b0ba9.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-pression-parking.jpg 1500w" width="1500"&gt;
&lt;em&gt;Pression de stationnement — mardi, 9-12 h : voitures des résidents et des salariés
rapportées aux places publiques à 300 m à pied, carreau par carreau. Le tableau de la
semaine montre un taux d&amp;rsquo;occupation théorique supérieur à 1 les matinées de semaine,
alors que les soirées et le week-end restent nettement en dessous.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Écran Escales et événements : calendrier annuel des escales, navires du jour et croisiéristes à terre par heure" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1122" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-escales.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-escales_hu_712bc4be717471d7.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-escales.jpg 1500w" width="1500"&gt;
&lt;em&gt;Escales et événements — le calendrier annuel des escales avec les jours fériés et les
vacances scolaires, les navires d&amp;rsquo;une journée et l&amp;rsquo;estimation des croisiéristes à terre
heure par heure.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Écran Sources et hypothèses : catalogue des sources consultable avec statut d’intégration, paramètres de modélisation et journal des acquisitions" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1122" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/urban-flows-fort-de-france/app-sources.jpg" srcset="https://borisdupoux.com/research/urban-flows-fort-de-france/app-sources_hu_e0417d4e381ce409.jpg 800w, https://borisdupoux.com/research/urban-flows-fort-de-france/app-sources.jpg 1500w" width="1500"&gt;
&lt;em&gt;Sources et hypothèses — le catalogue derrière chaque chiffre (filtrable par statut),
les paramètres de modélisation avec leur justification et les acquisitions archivées.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="résultats"&gt;&lt;a href="#r%c3%a9sultats" class="header-anchor"&gt;&lt;/a&gt;Résultats
&lt;/h2&gt;&lt;p&gt;Le projet a démarré en octobre 2026 et en est à un &lt;strong&gt;stade précoce, non
calé&lt;/strong&gt; (application v0.6.0). Tous les chiffres relatifs au centre-ville
dépendent d&amp;rsquo;un périmètre provisoire (voir ci-dessous). Chaque résultat
ci-dessous précise les sources qu&amp;rsquo;il croise : aucun ne pourrait être obtenu à
partir d&amp;rsquo;un seul jeu de données.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Catalogue.&lt;/strong&gt; 120 sources sont cataloguées, dont 51 intégrées.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entrepôt (première construction).&lt;/strong&gt; 117 161 entités, environ 25 000
mesures et 1 278 indicateurs, avec les 6 invariants validés.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Déclin commercial et résidents (mesuré, registres × recensement ×
données fiscales).&lt;/strong&gt; Le nombre d&amp;rsquo;établissements actifs d&amp;rsquo;équipement de la
personne (Sirene) est passé de 498 (2016) à 363 (2026), soit une baisse de
27 %, et la part du centre-ville dans la commune pour ce secteur de 75,5 % à
64,7 %. Sur la même période, la population des IRIS du centre-ville
(recensement) est passée de 13 444 (2016) à 12 898 (2022), et la vacance
des logements de 24,9 % à 27,6 %. 47 % des ménages du centre-ville vivent
sous le seuil de pauvreté, contre 30 % pour la commune (Filosofi 2021). Lues
ensemble, ces trois sources montrent un centre qui perd en même temps des
commerces, des habitants et du pouvoir d&amp;rsquo;achat.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rythme jour/nuit (modélisé, six sources croisées).&lt;/strong&gt; Environ 3 700
personnes sont présentes la nuit et 11 200 le matin, soit un rapport de
3,0. Les résidents de nuit viennent de Filosofi carroyé 200 m réparti dans
les bâtiments BD TOPO ; les salariés de jour, des tranches d&amp;rsquo;effectif
Sirene ; les élèves, de l&amp;rsquo;annuaire de l&amp;rsquo;éducation ; les touristes, de la
capacité des hébergements classés. Le créneau du matin est ajusté sur le
profil horaire du NO₂ aux stations trafic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vitesse observée des bus et modèle (GTFS-RT × graphe routier × enquêtes
de mobilité).&lt;/strong&gt; Sur une journée complète, les bus roulaient à 12,7 km/h à
5 h, puis à 7 à 8 km/h en journée et à 10,6 km/h à 19 h. Le modèle
d&amp;rsquo;affectation, construit à partir des routes BD TOPO, des navettes MOBPRO,
des profils de déplacements EMP et des équipements BPE, prévoit un
ralentissement de 20 % aux heures de pointe, alors que les bus en montrent
45 %. La mesure révèle ce que le modèle ne voit pas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contrôle croisière (escales × capacités des navires × effectifs
publiés).&lt;/strong&gt; Les croisiéristes à terre sont modélisés à partir du calendrier
des escales et des capacités des navires (CruiseMapper). Pour la seule
journée d&amp;rsquo;escale documentée (24 avril 2026), les estimations se sont
situées à environ 1 à 2 % des effectifs de passagers publiés dans la presse
(3 075 contre 3 112, et 1 995 contre 1 969). Le taux de remplissage du
modèle a été fixé sur cette même journée : il s&amp;rsquo;agit donc d&amp;rsquo;un contrôle de
cohérence, pas d&amp;rsquo;une validation indépendante.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="limites--suite"&gt;&lt;a href="#limites--suite" class="header-anchor"&gt;&lt;/a&gt;Limites &amp;amp; suite
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;D1 : le périmètre du centre-ville est provisoire.&lt;/strong&gt; Il s&amp;rsquo;agit d&amp;rsquo;un
rectangle autour du noyau historique, complété d&amp;rsquo;une zone élargie de 1 km,
utilisé dans l&amp;rsquo;attente d&amp;rsquo;un périmètre officiel. Tous les chiffres relatifs
au centre-ville en dépendent.&lt;/li&gt;
&lt;li&gt;Aucune donnée de comptage piéton, de fréquentation ou de comptage routier
n&amp;rsquo;est ouverte. Les rythmes horaires, les poids d&amp;rsquo;attractivité et les
hypothèses de stationnement ne sont pas encore calés. Les seuls contrôles
mesurés à ce stade sont le NO₂ horaire aux stations trafic et les vitesses
observées des bus.&lt;/li&gt;
&lt;li&gt;Le stock d&amp;rsquo;établissements 2016–2026 est reconstitué uniquement à partir des
dates de création et de fermeture.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prochaines étapes :&lt;/strong&gt; accumuler plusieurs mois de données GTFS-RT pour
mesurer la congestion, solliciter des données d&amp;rsquo;enquête et de comptage, et
caler la présence sur des comptages de terrain.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="stack-technique"&gt;&lt;a href="#stack-technique" class="header-anchor"&gt;&lt;/a&gt;Stack technique
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; · &lt;code&gt;DuckDB&lt;/code&gt; (spatial, httpfs) · &lt;code&gt;Parquet&lt;/code&gt; · &lt;code&gt;SQL&lt;/code&gt; · &lt;code&gt;GTFS / GTFS-RT&lt;/code&gt; · &lt;code&gt;pytest&lt;/code&gt; · &lt;code&gt;ruff&lt;/code&gt; · &lt;code&gt;Electron&lt;/code&gt; · &lt;code&gt;React&lt;/code&gt; · &lt;code&gt;TypeScript&lt;/code&gt; · &lt;code&gt;ECharts&lt;/code&gt; · &lt;code&gt;Leaflet&lt;/code&gt; · &lt;code&gt;GitHub Actions&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Atomes de traitement explicables pour documents et données</title><link>https://borisdupoux.com/fr/research/processing-atoms/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://borisdupoux.com/fr/research/processing-atoms/</guid><description>&lt;h2 id="contexte"&gt;&lt;a href="#contexte" class="header-anchor"&gt;&lt;/a&gt;Contexte
&lt;/h2&gt;&lt;p&gt;Des systèmes de production pour le rapprochement documentaire et l&amp;rsquo;OCR, développés pour
des clients tels qu&amp;rsquo;un grossiste distributeur et un cabinet d&amp;rsquo;expertise comptable, ont
laissé plusieurs bases de code résolvant chacune les mêmes sous-problèmes (routage des
pages, réglage de l&amp;rsquo;OCR, extraction par LLM, comparaison de champs) avec leurs propres
bogues. La bibliothèque d&amp;rsquo;atomes les consolide en un seul paquet. Sa question centrale est
celle qui sous-tendait les systèmes d&amp;rsquo;origine : &lt;strong&gt;peut-on automatiser un contrôle documentaire
de sorte qu&amp;rsquo;un humain puisse auditer et contester chaque verdict ?&lt;/strong&gt; Extraire un champ ne
suffit pas. Le système doit indiquer si deux documents concordent, pourquoi, et sur la base
de quels éléments.&lt;/p&gt;
&lt;h2 id="approche"&gt;&lt;a href="#approche" class="header-anchor"&gt;&lt;/a&gt;Approche
&lt;/h2&gt;&lt;p&gt;Tout est construit à partir d&amp;rsquo;&lt;strong&gt;atomes&lt;/strong&gt;. Un atome a une seule responsabilité, des
entrées et sorties typées, aucun état global et des dépendances injectées (client LLM,
moteur OCR, stockage). Une chaîne de traitement est une composition d&amp;rsquo;atomes, soit écrite
en code, soit déclarée sous forme de recette YAML validée au chargement, avant toute exécution.&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 A["Documents d'entrée (PDF, numérisations, CSV, courriels)"] --&gt; B{"Routage des pages : texte natif ou OCR ?"}
 B -- "natif" --&gt; C["Texte natif positionné"]
 B -- "numérisation" --&gt; D["PaddleOCR (réglages de production)"]
 C --&gt; E["Segmentation &amp; classification"]
 D --&gt; E
 E --&gt; F["Extraction JSON par LLM + vérification d'ancrage verbatim"]
 F --&gt; G["Rapprochement inter-documents (facture / bon de livraison / commande)"]
 G --&gt; H["Verdict tri-état + motif nommé + trace"]
 H --&gt; I["Rapport / revue humaine"]&lt;/pre&gt;&lt;h2 id="le-catalogue"&gt;&lt;a href="#le-catalogue" class="header-anchor"&gt;&lt;/a&gt;Le catalogue
&lt;/h2&gt;&lt;p&gt;Les 459 atomes sont regroupés en 32 familles, un paquet Python chacune, rangées le long de
la chaîne de traitement : &lt;strong&gt;capter&lt;/strong&gt; le monde, le &lt;strong&gt;comprendre&lt;/strong&gt;, &lt;strong&gt;rapprocher&lt;/strong&gt; et décider,
&lt;strong&gt;restituer&lt;/strong&gt;, puis &lt;strong&gt;exploiter&lt;/strong&gt; en production. Deux paquets supplémentaires les assemblent :
&lt;code&gt;steps&lt;/code&gt; (77 étapes nommées et paramétrées) et &lt;code&gt;recipes&lt;/code&gt; (chargement et validation des recettes YAML).&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Série&lt;/th&gt;
					&lt;th&gt;Famille&lt;/th&gt;
					&lt;th style="text-align: right"&gt;Atomes&lt;/th&gt;
					&lt;th&gt;Rôle&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Socle&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;core&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;25&lt;/td&gt;
					&lt;td&gt;types pivots, chaîne de traitement, configuration, résilience (reprises, limites de débit), fichiers, concurrence&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Capter&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;connect&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;40&lt;/td&gt;
					&lt;td&gt;HTTP résilient, boîtes aux lettres (Graph, IMAP), SFTP, OneDrive, source ERP en lecture seule, données ouvertes, piste d&amp;rsquo;audit&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;google&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;24&lt;/td&gt;
					&lt;td&gt;Gmail, Sheets, Drive, Apps Script, avec exécution résiliente&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;web&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;17&lt;/td&gt;
					&lt;td&gt;robots web indépendants du pilote (Selenium, Playwright) : attentes, squelette à reprise, formulaires&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pdf&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;9&lt;/td&gt;
					&lt;td&gt;texte natif positionné, décision d&amp;rsquo;OCR, rendu, pages, doublons&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ocr&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;9&lt;/td&gt;
					&lt;td&gt;PaddleOCR avec réglages de production, EasyOCR&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;layout&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;3&lt;/td&gt;
					&lt;td&gt;géométrie de page : lignes, colonnes, redressement, rendu monospace&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;audio&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;16&lt;/td&gt;
					&lt;td&gt;transcription par morceaux, post-traitement des segments, recalage micro ↔ écran&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;vision&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;32&lt;/td&gt;
					&lt;td&gt;flux vidéo / RTSP, détection, suivi, profondeur, segmentation, calibration&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;vlm&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;10&lt;/td&gt;
					&lt;td&gt;lecture d&amp;rsquo;écran par modèle de vision-langage : détection de changement, localisation de libellés&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;geo&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;11&lt;/td&gt;
					&lt;td&gt;mesures géodésiques, position combinée de relevés GPS, filtrage par distance aux lignes, SQL spatial&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;calendar&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;4&lt;/td&gt;
					&lt;td&gt;jours fériés, jours et horaires ouvrés&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Comprendre&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;32&lt;/td&gt;
					&lt;td&gt;nombres et montants, dates, normalisation, champs par motifs, identifiants&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;segment&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;7&lt;/td&gt;
					&lt;td&gt;pages → documents logiques, numéros de pièce typés, nature de page&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;classify&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;12&lt;/td&gt;
					&lt;td&gt;classement par nom de fichier, expéditeur, motifs pondérés, TF-IDF, visuel, LLM, cascades&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;llm&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;24&lt;/td&gt;
					&lt;td&gt;contrat indépendant du fournisseur, fournisseurs, pool, prompts, extraction structurée&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;anchor&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;5&lt;/td&gt;
					&lt;td&gt;champs et tableaux situés par rapport aux libellés imprimés, texte natif ou OCR&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;kb&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;8&lt;/td&gt;
					&lt;td&gt;base de connaissances tracée : journal d&amp;rsquo;événements validé, replié en index SQLite&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Rapprocher&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;match&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;25&lt;/td&gt;
					&lt;td&gt;EAN/GTIN, index, score multicritère, affectation optimale, résolution d&amp;rsquo;entités&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;compare&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;9&lt;/td&gt;
					&lt;td&gt;comparateurs tri-états et explicables de champs, d&amp;rsquo;enregistrements et d&amp;rsquo;ensembles&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;check&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;9&lt;/td&gt;
					&lt;td&gt;contrôles génériques tri-états : totaux, TVA, balance, complétude, vraisemblance&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;reconcile&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;12&lt;/td&gt;
					&lt;td&gt;appariement d&amp;rsquo;ensembles, chaînes commande → livraison → facture, N-voies, lettrage, rapprochement bancaire&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;validate&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;14&lt;/td&gt;
					&lt;td&gt;moteur de règles, identifiants, cohérence des montants, verdicts LLM corrigés, décision finale&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;rules&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;8&lt;/td&gt;
					&lt;td&gt;langage de conditions sûr, tables « premier match » explicables, escalade, machines à états&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;events&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;11&lt;/td&gt;
					&lt;td&gt;événements horodatés : fenêtres, veille des événements attendus, sessions, transitions de statut&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;analytics&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;18&lt;/td&gt;
					&lt;td&gt;analyses supply chain sans pandas : demande, ruptures, taux de service, stock de sécurité&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Restituer&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;export&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;8&lt;/td&gt;
					&lt;td&gt;CSV pour Excel FR, classeurs Excel partagés, rapports HTML / Markdown / PDF&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;report&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;6&lt;/td&gt;
					&lt;td&gt;écarts persistables, synthèses, file de revue&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;render&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;12&lt;/td&gt;
					&lt;td&gt;livrables HTML : diagrammes Mermaid pré-rendus, graphiques ECharts, cartes GeoJSON&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;diagram&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;6&lt;/td&gt;
					&lt;td&gt;diagrammes de processus : lecture draw.io / BPMN JSON, rendu Mermaid et BPMN XML&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Exploiter&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ops&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;26&lt;/td&gt;
					&lt;td&gt;haute disponibilité (battements, élection), démon à déclencheurs horaires, surveillance, contrôles préalables&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;qa&lt;/code&gt;&lt;/td&gt;
					&lt;td style="text-align: right"&gt;7&lt;/td&gt;
					&lt;td&gt;non-régression rédactionnelle (fichiers dorés), rejeu de simulations, accord inter-annotateurs&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="recettes-nommées"&gt;&lt;a href="#recettes-nomm%c3%a9es" class="header-anchor"&gt;&lt;/a&gt;Recettes nommées
&lt;/h3&gt;&lt;p&gt;Chacune des 17 recettes est une liste YAML d&amp;rsquo;étapes nommées &lt;code&gt;&amp;lt;famille&amp;gt;.&amp;lt;atome&amp;gt;&lt;/code&gt;. Trois exemples :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;invoice_multi_doc&lt;/code&gt;&lt;/strong&gt; : un lot de PDF multidocuments devient un ensemble de documents
logiques contrôlés. &lt;code&gt;io.collect&lt;/code&gt; → &lt;code&gt;pdf.read&lt;/code&gt; → &lt;code&gt;segment.documents&lt;/code&gt; → &lt;code&gt;classify.documents&lt;/code&gt; →
&lt;code&gt;llm.extract&lt;/code&gt; → &lt;code&gt;validate.ids&lt;/code&gt; → &lt;code&gt;validate.amounts&lt;/code&gt; → &lt;code&gt;validate.decide&lt;/code&gt; → &lt;code&gt;export.csv&lt;/code&gt;
→ &lt;code&gt;google.sheets.upsert&lt;/code&gt; → &lt;code&gt;connect.notify&lt;/code&gt;. Chaque document finit valide, à vérifier ou invalide.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;doc_reconciliation&lt;/code&gt;&lt;/strong&gt; : un dossier de factures, d&amp;rsquo;avoirs et de bons de livraison,
contrôlé par rapport aux commandes. L&amp;rsquo;extraction LLM gardée (&lt;code&gt;llm.extract_docs&lt;/code&gt;) est
recoupée avec une extraction par motifs (&lt;code&gt;extract.regex&lt;/code&gt;, &lt;code&gt;compare.extractions&lt;/code&gt;,
&lt;code&gt;reconcile.fields&lt;/code&gt;), puis viennent &lt;code&gt;check.document&lt;/code&gt; et &lt;code&gt;check.completeness&lt;/code&gt;, les lignes
face à la commande (&lt;code&gt;compare.reference&lt;/code&gt;), la chaîne commande → livraison → facture
(&lt;code&gt;reconcile.nway&lt;/code&gt;), et enfin un fichier d&amp;rsquo;écarts et une file de revue
(&lt;code&gt;report.discrepancies&lt;/code&gt;, &lt;code&gt;report.review&lt;/code&gt;). 17 étapes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;meeting_transcript&lt;/code&gt;&lt;/strong&gt; : un enregistrement de réunion devient une transcription horodatée
avec locuteurs. &lt;code&gt;audio.decode&lt;/code&gt; → &lt;code&gt;audio.vad&lt;/code&gt; → &lt;code&gt;audio.transcribe&lt;/code&gt; → &lt;code&gt;audio.diarize&lt;/code&gt; →
&lt;code&gt;audio.speakers&lt;/code&gt; → &lt;code&gt;audio.segments&lt;/code&gt; → &lt;code&gt;export.csv&lt;/code&gt; → &lt;code&gt;export.transcript&lt;/code&gt; → &lt;code&gt;connect.notify&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les autres sont notamment &lt;code&gt;delivery_vs_order&lt;/code&gt;, &lt;code&gt;ledger_reconciliation&lt;/code&gt;, &lt;code&gt;invoice_dedup&lt;/code&gt;,
&lt;code&gt;article_base_cleaning&lt;/code&gt;, &lt;code&gt;stock_policy&lt;/code&gt;, &lt;code&gt;mail_to_sheet&lt;/code&gt;, &lt;code&gt;draft_mails&lt;/code&gt;,
&lt;code&gt;pdf_text_extract&lt;/code&gt;, &lt;code&gt;rubric_eval&lt;/code&gt;, &lt;code&gt;screen_session&lt;/code&gt;, &lt;code&gt;camera_flow&lt;/code&gt; et
&lt;code&gt;process_from_transcript&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="latlas"&gt;&lt;a href="#latlas" class="header-anchor"&gt;&lt;/a&gt;L&amp;rsquo;Atlas
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;Atlas est une page HTML unique, consultable hors ligne, générée à partir du code lui-même
(arbres syntaxiques et YAML), sans aucune donnée saisie à la main. Il dessine le catalogue
comme un tableau périodique : chaque famille est un élément doté d&amp;rsquo;un symbole, chaque module
un atome, chaque recette une molécule. Il signale aussi les atomes sans documentation, sans
test ou sans exemple d&amp;rsquo;usage.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Atlas, série « Capter » : un élément par famille (connect, google, web, pdf, ocr, layout, audio, vision, vlm, geo, calendar), avec ses atomes en dessous" class="gallery-image" data-flex-basis="367px" data-flex-grow="153" height="920" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/processing-atoms/atlas-capture-series.png" srcset="https://borisdupoux.com/research/processing-atoms/atlas-capture-series_hu_dfcfb778a533826c.png 800w, https://borisdupoux.com/research/processing-atoms/atlas-capture-series.png 1408w" width="1408"&gt;
&lt;em&gt;La série « Capter » du tableau périodique. Chaque case est une famille, avec son symbole, son nombre de modules et sa taille en milliers de lignes ; chaque tuile en dessous est un atome.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Atlas, série « Rapprocher » : match, compare, check, reconcile, validate, rules, events, analytics" class="gallery-image" data-flex-basis="536px" data-flex-grow="223" height="630" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/processing-atoms/atlas-reconcile-series.png" srcset="https://borisdupoux.com/research/processing-atoms/atlas-reconcile-series_hu_872c082d4171f5de.png 800w, https://borisdupoux.com/research/processing-atoms/atlas-reconcile-series.png 1408w" width="1408"&gt;
&lt;em&gt;La série « Rapprocher » : les familles qui apparient, comparent, contrôlent et décident.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Fiche de l’atome compare.fields dans l’Atlas : rôle, règles de dominance et signature complète" class="gallery-image" data-flex-basis="170px" data-flex-grow="71" height="900" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/processing-atoms/atlas-atom-compare-fields.png" width="640"&gt;
&lt;em&gt;La fiche d&amp;rsquo;un atome (&lt;code&gt;compare.fields&lt;/code&gt;) : à quoi il sert, d&amp;rsquo;après sa docstring, puis chaque nom public avec sa signature complète.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="La recette invoice_multi_doc vue comme une molécule : 11 étapes reliées par les clés de contexte qu’elles se transmettent" class="gallery-image" data-flex-basis="590px" data-flex-grow="246" height="572" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/processing-atoms/atlas-recipe-invoice-multi-doc.png" srcset="https://borisdupoux.com/research/processing-atoms/atlas-recipe-invoice-multi-doc_hu_9f54a6aa2766961a.png 800w, https://borisdupoux.com/research/processing-atoms/atlas-recipe-invoice-multi-doc.png 1408w" width="1408"&gt;
&lt;em&gt;La recette &lt;code&gt;invoice_multi_doc&lt;/code&gt; en molécule : 11 étapes, les clés de contexte qui les relient et les services requis (en pointillé lorsqu&amp;rsquo;ils sont facultatifs).&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="méthodes"&gt;&lt;a href="#m%c3%a9thodes" class="header-anchor"&gt;&lt;/a&gt;Méthodes
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Résultats tri-états.&lt;/strong&gt; Chaque comparaison renvoie &lt;code&gt;ok ∈ {True, False, None}&lt;/code&gt;
(conforme / écart / non concluant) avec un code de motif nommé et une trace. Une valeur
manquante ou illisible compte comme non concluante, jamais comme une anomalie. Les
résultats non concluants sont tout de même comptabilisés, et non écartés en silence.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Routage hybride texte natif/OCR.&lt;/strong&gt; Chaque page PDF est classée comme native, OCR ou
vide, selon la quantité de texte natif qu&amp;rsquo;elle contient et la part de ce texte couverte
par des images. L&amp;rsquo;OCR n&amp;rsquo;est exécuté que là où il est nécessaire.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extraction LLM ancrée.&lt;/strong&gt; L&amp;rsquo;extraction JSON structurée est validée par rapport à des
schémas Pydantic. Chaque valeur extraite est ensuite vérifiée mot pour mot dans le texte
source, de sorte que les valeurs altérées ou inventées sont signalées.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rapprochement inter-documents.&lt;/strong&gt; Factures, bons de livraison et commandes sont comparés
ligne à ligne à l&amp;rsquo;aide de tolérances nommées et de règles de dominance. Par exemple, un
montant de ligne concordant peut l&amp;rsquo;emporter sur un écart de prix.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provenance.&lt;/strong&gt; Chaque atome porté comporte un en-tête &lt;code&gt;Provenance:&lt;/code&gt; et une entrée qui le
relie à &lt;code&gt;repo@commit:path:lines&lt;/code&gt; dans le code de production d&amp;rsquo;origine. Les bogues découverts
lors du portage ont été corrigés, et chaque correction est couverte par un test de non-régression.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Architecture contrôlée.&lt;/strong&gt; Le découpage en couches est vérifié par 30 contrats d&amp;rsquo;import :
un atome n&amp;rsquo;importe que le paquet &lt;code&gt;core&lt;/code&gt;. Un typage strict, un seuil de couverture ≥ 80 % et
une vérification de l&amp;rsquo;absence de noms de clients dans le code source sont également imposés.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstraction du matériel.&lt;/strong&gt; Les atomes de vision et d&amp;rsquo;audio ciblent &lt;code&gt;cuda&lt;/code&gt;, &lt;code&gt;mps&lt;/code&gt; ou &lt;code&gt;cpu&lt;/code&gt; via un seul paramètre.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Évaluation de bout en bout.&lt;/strong&gt; Les tests s&amp;rsquo;exécutent avec de vrais moteurs (PaddleOCR, Ollama &lt;code&gt;qwen3:8b&lt;/code&gt;
et &lt;code&gt;qwen3-vl:8b&lt;/code&gt;) sur des données à vérité terrain connue. Chaque métrique est consignée face à un
seuil dans un rapport JSON/HTML. Les métriques qui n&amp;rsquo;atteignent pas leur seuil sont conservées et
affichées comme en échec.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="résultats"&gt;&lt;a href="#r%c3%a9sultats" class="header-anchor"&gt;&lt;/a&gt;Résultats
&lt;/h2&gt;&lt;p&gt;Base de code (arborescence actuelle) : 459 modules d&amp;rsquo;atomes répartis en 32 familles, 77 étapes
paramétrées, 17 recettes YAML, 30 contrats d&amp;rsquo;import. La suite collecte 2 959 tests unitaires et
de recettes, plus 109 tests de bout en bout exécutés séparément. Les 17 recettes disposent toutes
d&amp;rsquo;au moins un test de bout en bout, et 34 des 35 éléments de l&amp;rsquo;Atlas sont testés de bout en bout.&lt;/p&gt;
&lt;p&gt;Scores de bout en bout sélectionnés (documents synthétiques à vérité terrain connue, modèles 8B locaux) :&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tâche&lt;/th&gt;
					&lt;th&gt;Moteur&lt;/th&gt;
					&lt;th&gt;Mesure&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Rapprochement facture + bon de livraison / commande&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;qwen3:8b&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;types de documents et champs 14/14 ; écarts attendus 5/5 ; 0 faux écart sur le cas conforme&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Extraction JSON par LLM (4 factures natives)&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;qwen3:8b&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;JSON valide 4/4 ; champs exacts 28/28 ; toutes les valeurs volontairement altérées détectées par l&amp;rsquo;ancrage&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OCR sur une étiquette photographiée&lt;/td&gt;
					&lt;td&gt;PaddleOCR&lt;/td&gt;
					&lt;td&gt;rappel des mots 0,94 sur la photo brute ; un défaut de rehaussement du contraste (0,65–0,71) a été identifié et corrigé (0,88–0,94)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Reconstruction de tableaux à partir de l&amp;rsquo;OCR&lt;/td&gt;
					&lt;td&gt;PaddleOCR&lt;/td&gt;
					&lt;td&gt;100 % de cellules exactes (police proportionnelle), 95 % (chasse fixe)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="limites--suite"&gt;&lt;a href="#limites--suite" class="header-anchor"&gt;&lt;/a&gt;Limites &amp;amp; suite
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;L&amp;rsquo;ancrage verbatim ne peut pas détecter une valeur présente dans le document mais placée
dans le mauvais champ : un champ absent a été rempli à tort dans 1 cas sur 8.&lt;/li&gt;
&lt;li&gt;Le modèle 8B a jugé un écart de quantité de +50 % comme un écart « mineur », contrairement
à la consigne. Les verdicts du LLM sont donc normalisés et maintenus en aval de règles
déterministes.&lt;/li&gt;
&lt;li&gt;Les scores proviennent principalement de données synthétiques. Un jeu de test sur documents
réels est en cours de constitution en dehors du dépôt, et seuls les cas ayant fait l&amp;rsquo;objet
d&amp;rsquo;une revue sont notés.&lt;/li&gt;
&lt;li&gt;Prochaines étapes : mesurer le taux de rapprochement automatique et le taux de faux positifs
sur des données de production.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="stack-technique"&gt;&lt;a href="#stack-technique" class="header-anchor"&gt;&lt;/a&gt;Stack technique
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; · &lt;code&gt;Pydantic&lt;/code&gt; · &lt;code&gt;PyYAML&lt;/code&gt; · &lt;code&gt;PaddleOCR&lt;/code&gt; · &lt;code&gt;Ollama&lt;/code&gt; (&lt;code&gt;qwen3:8b&lt;/code&gt;, &lt;code&gt;qwen3-vl:8b&lt;/code&gt;) · &lt;code&gt;Mistral / Anthropic / OpenAI APIs&lt;/code&gt; · &lt;code&gt;pytest&lt;/code&gt; · &lt;code&gt;mypy&lt;/code&gt; · &lt;code&gt;import-linter&lt;/code&gt; · &lt;code&gt;ruff&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Codex — archivage physique haute densité de médias sur papier</title><link>https://borisdupoux.com/fr/research/codex-paper-archive/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://borisdupoux.com/fr/research/codex-paper-archive/</guid><description>&lt;h2 id="contexte"&gt;&lt;a href="#contexte" class="header-anchor"&gt;&lt;/a&gt;Contexte
&lt;/h2&gt;&lt;p&gt;Les médias numériques grand public se dégradent à l&amp;rsquo;échelle de quelques années. Les SSD non alimentés perdent leur charge, les disques optiques se délaminent, les formats tombent en désuétude et les comptes sont fermés. Le papier peut durer des siècles, ne nécessite aucune électricité et peut être vérifié à l&amp;rsquo;œil nu. La question est de savoir quelle quantité d&amp;rsquo;information une feuille A4 ordinaire peut contenir si elle doit encore pouvoir être relue de façon fiable avec un scanner à plat standard, sans matériel spécialisé.&lt;/p&gt;
&lt;p&gt;Le problème est difficile car le canal impression-numérisation est bruité de plusieurs manières à la fois. Le toner s&amp;rsquo;étale et forme des amas, la densité varie sur la page, et les scanners introduisent rotation, mise à l&amp;rsquo;échelle anisotrope, entraînement irrégulier du papier, flou, vignettage et gamma. Le papier se déforme aussi de façon non linéaire : à la densité visée, un étirement de 0,2 % décale la grille d&amp;rsquo;environ trois cellules. Les codes 2D courants comme QR et DataMatrix sont conçus pour la robustesse plutôt que pour la densité. Une archive à long terme doit en outre rester décodable lorsque les logiciels actuels auront disparu.&lt;/p&gt;
&lt;h2 id="approche"&gt;&lt;a href="#approche" class="header-anchor"&gt;&lt;/a&gt;Approche
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 A["Médias sources : photo, vidéo, voix, texte"] --&gt; B["Réduction conservatrice des formats&lt;br/&gt;JPEG baseline · AVI MJPEG/PCM · WAV PCM · UTF-8"]
 B --&gt; C["Archive : tar + zlib + SHA-256"]
 C --&gt; D["Code à effacement inter-pages&lt;br/&gt;MDS de Cauchy sur GF(256) : K pages quelconques parmi N"]
 D --&gt; E["Reed–Solomon + CRC-32 par bloc&lt;br/&gt;entrelacement sur la page, en-tête triplé"]
 E --&gt; F["Rendu de cellules multiniveaux&lt;br/&gt;PDF A4 1 bit à 1200 dpi"]
 F --&gt; G["Impression → numérisation&lt;br/&gt;(canal simulé)"]
 G --&gt; H["Repères → homographie → marqueurs d'alignement locaux"]
 H --&gt; I["Calibration des niveaux de gris à partir de la page elle-même"]
 I --&gt; J["Décodage RS/CRC → décodage d'effacement → contrôle SHA-256"]
 J --&gt; K["Fichiers identiques à l'octet près, ou récupération partielle"]
 F -.-&gt; L["Annexe imprimée : spécification du format + source du décodeur en OCR-B avec CRC-16 par ligne"]
 L -.-&gt; J&lt;/pre&gt;&lt;p&gt;&lt;img alt="Une page de données A4 encodée de l’archive photo, à côté d’un agrandissement de son coin supérieur gauche à la résolution de l’imprimante, montrant le repère d’angle, le début du bandeau d’en-tête et les premières cellules en niveaux de gris avec un marqueur d’alignement" class="gallery-image" data-flex-basis="436px" data-flex-grow="181" height="880" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/codex-paper-archive/codex-page-and-macro.png" srcset="https://borisdupoux.com/research/codex-paper-archive/codex-page-and-macro_hu_7e58d21b3fd6152e.png 800w, https://borisdupoux.com/research/codex-paper-archive/codex-page-and-macro.png 1600w" width="1600"&gt;
&lt;em&gt;À gauche : la page 1 sur 10 de l&amp;rsquo;archive photo, telle qu&amp;rsquo;envoyée à l&amp;rsquo;imprimante (A4, 1200 dpi, une grille de 1 145 × 1 576 cellules), réduite. À droite : le coin supérieur gauche encadré, à la résolution de l&amp;rsquo;imprimante (environ 10 × 9 mm, chaque point d&amp;rsquo;imprimante dessiné en 2 × 2 pixels) : le repère d&amp;rsquo;angle plein, le début du bandeau d&amp;rsquo;en-tête et les premières cellules de données. Chaque cellule mesure 8 × 8 points (0,169 mm) et son nombre de points encrés code l&amp;rsquo;un des 4 niveaux. Le carré situé au coin de la grille est un marqueur d&amp;rsquo;alignement.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Une page de l’annexe imprimée : le début du fichier du décodeur cdx_read.py, composé en OCR-B, chaque ligne précédée de son numéro et d’un CRC-16 à quatre chiffres" class="gallery-image" data-flex-basis="339px" data-flex-grow="141" height="778" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/codex-paper-archive/codex-appendix-decoder-page.png" srcset="https://borisdupoux.com/research/codex-paper-archive/codex-appendix-decoder-page_hu_f0b09cea3a0e024f.png 800w, https://borisdupoux.com/research/codex-paper-archive/codex-appendix-decoder-page.png 1100w" width="1100"&gt;
&lt;em&gt;Une page de l&amp;rsquo;annexe imprimée (page 11 sur 30) : le début de &lt;code&gt;cdx_read.py&lt;/code&gt; (360 lignes), composé en OCR-B. Chaque ligne porte son numéro et son CRC-16 : une ligne mal relue par l&amp;rsquo;OCR peut ainsi être repérée et vérifiée à la main.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="méthodes"&gt;&lt;a href="#m%c3%a9thodes" class="header-anchor"&gt;&lt;/a&gt;Méthodes
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cellules multiniveaux plutôt que modules binaires.&lt;/strong&gt; Chaque cellule porte 2 bits. Les cellules sont dessinées sous forme de points groupés à la résolution native de l&amp;rsquo;imprimante, de sorte que le pilote n&amp;rsquo;effectue aucun tramage et ne produit aucun moiré.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Récupération de la géométrie par étapes.&lt;/strong&gt; Quatre repères d&amp;rsquo;angle, dont l&amp;rsquo;un est creux pour fixer l&amp;rsquo;orientation, donnent une homographie globale. Des marqueurs d&amp;rsquo;alignement répartis sur la page absorbent ensuite l&amp;rsquo;étirement local et non linéaire du papier.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lecteur auto-calibré.&lt;/strong&gt; Le décodeur estime les niveaux de gris imprimés et l&amp;rsquo;ombrage spatial à partir de structures de calibration présentes sur chaque page ; il ne dépend donc pas des réglages de points de l&amp;rsquo;imprimante.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contrôle d&amp;rsquo;erreurs à deux niveaux, un code produit.&lt;/strong&gt; Reed–Solomon et CRC-32 à l&amp;rsquo;intérieur de chaque page corrigent les erreurs aléatoires et en rafale, comme les taches et les rayures. Un code à effacement MDS de Cauchy entre les pages, décodé bloc par bloc, permet à K pages quelconques parmi N de reconstruire une archive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dégradation progressive.&lt;/strong&gt; Si le contrôle SHA-256 échoue, le décodeur extrait malgré tout chaque fichier complet situé avant la zone endommagée.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Archive autodescriptive.&lt;/strong&gt; Une annexe imprimée contient la spécification du format, une procédure de lecture et le code source complet du décodeur en OCR-B, avec un numéro de ligne et un CRC-16 sur chaque ligne. Le décodeur ne nécessite que NumPy, Pillow et reedsolo. Le texte utilise DEFLATE (zlib), qui peut être réimplémenté en quelques centaines de lignes, plutôt que LZMA, plus performant.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prototype antérieur (&lt;code&gt;codex_proto/&lt;/code&gt;).&lt;/strong&gt; Cette version explorait plusieurs supports physiques : papier, acier inoxydable gravé au laser, plaques en taille-douce et images de microfilm. Elle utilisait des cellules de 2 à 16 niveaux, des pages de parité de type fontaine, des lecteurs de niveaux de gris à base de MLP, un calculateur optique imprimé pour la lecture des microfilms, ainsi qu&amp;rsquo;une réduction des médias avec pertes (codage paramétrique de la voix, codage des photos par résidus d&amp;rsquo;ondelettes).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="résultats"&gt;&lt;a href="#r%c3%a9sultats" class="header-anchor"&gt;&lt;/a&gt;Résultats
&lt;/h2&gt;&lt;p&gt;Tous les chiffres ci-dessous proviennent &lt;strong&gt;uniquement de simulations&lt;/strong&gt;. Le logiciel modélise les défauts laser (flou du spot, grain du toner, engraissement du point, effet de bandes, densité non uniforme, papier texturé), les défauts du scanner (rotation de ±1,2°, échelle x/y de ±0,3 %, oscillation de l&amp;rsquo;entraînement, flou, vignettage, bruit, gamma 2,2), des taches de café, des rayures et &lt;strong&gt;une page volontairement perdue par archive&lt;/strong&gt;. Aucun essai physique d&amp;rsquo;impression et de numérisation n&amp;rsquo;a encore été réalisé.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Charge utile nette :&lt;/strong&gt; 383 469 octets par page A4, soit environ 59 bits/mm².&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;De bout en bout :&lt;/strong&gt; 46 pages sur 50 ont été numérisées et les &lt;strong&gt;4 archives sur 4 ont été restaurées à l&amp;rsquo;identique, octet pour octet&lt;/strong&gt; (photo, vidéo, voix, texte). Aucun mot de code Reed–Solomon n&amp;rsquo;a échoué et aucun bloc inter-pages n&amp;rsquo;a été perdu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Taux d&amp;rsquo;erreur :&lt;/strong&gt; les pages propres ont nécessité la correction d&amp;rsquo;environ 0,007–0,008 % des octets. Les pages tachées et/ou rayées en ont nécessité au plus 0,90 %.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Taille des archives :&lt;/strong&gt; photo 2,86 Mo → 10 pages (8 de données + 2 de parité) ; vidéo (800×600, 24 s, MJPEG + PCM 16 kHz) 8,30 Mo → 25 pages ; voix 0,91 Mo → 5 pages ; texte 5,58 Mo → 10 pages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Texte :&lt;/strong&gt; les &lt;em&gt;Mémoires d&amp;rsquo;outre-tombe&lt;/em&gt;, dans le domaine public (5,43 millions de caractères), occuperaient 1 357 pages A4 composées. Encodées, elles tiennent sur 6 pages de données, soit un rapport d&amp;rsquo;environ 226. zlib compresse cette prose d&amp;rsquo;un facteur 2,62 et LZMA d&amp;rsquo;un facteur 3,58.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Récupération partielle :&lt;/strong&gt; une archive tronquée au quart de sa longueur a encore restitué 1,42 Mo des 5,58 Mo de texte.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Robustesse du décodeur :&lt;/strong&gt; le décodeur a également fonctionné sur des numérisations tournées de 90° et 180°, sur des numérisations à 600 dpi et sur des numérisations JPEG (q92).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Taille du décodeur :&lt;/strong&gt; 731 lignes de Python pour les modules du décodeur imprimé.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="La même petite zone d’une page de données, à gauche telle qu’encodée, à droite après le canal impression-numérisation simulé, à cheval sur le bord d’une tache de café simulée" class="gallery-image" data-flex-basis="616px" data-flex-grow="256" height="600" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/codex-paper-archive/codex-encoded-vs-scan.png" srcset="https://borisdupoux.com/research/codex-paper-archive/codex-encoded-vs-scan_hu_25056d9200d46d29.png 800w, https://borisdupoux.com/research/codex-paper-archive/codex-encoded-vs-scan.png 1540w" width="1540"&gt;
&lt;em&gt;La même zone de la page photo (380 × 300 points, environ 8 × 6,4 mm), agrandie. À gauche : telle qu&amp;rsquo;encodée. À droite : après le canal impression-numérisation &lt;strong&gt;simulé&lt;/strong&gt;, rééchantillonnée sur la grille de la page grâce à l&amp;rsquo;homographie des repères. L&amp;rsquo;étalement du toner, le flou et le bruit adoucissent les cellules, et le bord d&amp;rsquo;une tache de café simulée assombrit la partie gauche. Le lecteur calibre les niveaux de gris localement et distingue donc encore les quatre niveaux. Dans la simulation présentée ci-dessus, les pages tachées ou rayées ont nécessité la correction d&amp;rsquo;au plus 0,90 % des octets.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Trois images d’une vidéo sous-marine : en haut l’original, en bas les images restituées après encodage, impression-numérisation simulée et décodage" class="gallery-image" data-flex-basis="480px" data-flex-grow="200" height="792" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/codex-paper-archive/codex-video-frames.jpg" srcset="https://borisdupoux.com/research/codex-paper-archive/codex-video-frames_hu_87a931ee2368d927.jpg 800w, https://borisdupoux.com/research/codex-paper-archive/codex-video-frames.jpg 1584w" width="1584"&gt;
&lt;em&gt;L&amp;rsquo;archive vidéo : un plan sous-marin (banc de poissons au-dessus d&amp;rsquo;un récif) servant de séquence de test. En haut : les images originales HEVC 3840 × 2880 à 3,2 s, 12,8 s et 16,0 s, réduites. En bas : les mêmes instants, décodés à partir des numérisations &lt;strong&gt;simulées&lt;/strong&gt; des 25 pages (dont une volontairement perdue). Le canal papier lui-même ne perd rien : l&amp;rsquo;AVI restitué est identique, octet pour octet, à l&amp;rsquo;AVI archivé. Ce qui diffère de l&amp;rsquo;original, c&amp;rsquo;est la réduction faite avant l&amp;rsquo;impression (MJPEG 800 × 600, 12,5 images/s, son mono 16 kHz) pour que 24 s de vidéo tiennent en 8,30 Mo.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Gros plan sur la même zone du récif : vidéo originale à gauche, vidéo restituée à droite, avec effets de blocs JPEG et perte des détails fins dans l’image restituée" class="gallery-image" data-flex-basis="648px" data-flex-grow="270" height="585" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://borisdupoux.com/research/codex-paper-archive/codex-video-detail.jpg" srcset="https://borisdupoux.com/research/codex-paper-archive/codex-video-detail_hu_ef2152090c0bf4cc.jpg 800w, https://borisdupoux.com/research/codex-paper-archive/codex-video-detail.jpg 1580w" width="1580"&gt;
&lt;em&gt;Gros plan sur l&amp;rsquo;image à 12,8 s. À gauche : une zone de 1 152 × 864 pixels de l&amp;rsquo;original, réduite. À droite : la zone correspondante de 240 × 180 pixels de l&amp;rsquo;image restituée, agrandie sans lissage. Les poissons et le récif restent reconnaissables. La texture fine et les nuances de couleur sont perdues, et des blocs MJPEG apparaissent. C&amp;rsquo;est le prix à payer pour faire tenir le plan en 25 pages.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="limites--suite"&gt;&lt;a href="#limites--suite" class="header-anchor"&gt;&lt;/a&gt;Limites &amp;amp; suite
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pas encore d&amp;rsquo;essai physique.&lt;/strong&gt; Les motifs de points des cellules ont été ajustés en simulation. La prochaine étape est une impression réelle à 1200 dpi avec une numérisation à 1200 dpi, afin de les régler et de mesurer la marge d&amp;rsquo;erreur effective.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jeu de test restreint.&lt;/strong&gt; La simulation couvre une seule exécution sur quatre archives. Un balayage en fonction de la sévérité des défauts, de la résolution de numérisation et du type de papier reste nécessaire.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Propriétés physiques non mesurées.&lt;/strong&gt; Le vieillissement à long terme du papier et du toner, ainsi que la faisabilité pratique de la relecture OCR du décodeur depuis le papier, n&amp;rsquo;ont pas été mesurés.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dépendance à une police.&lt;/strong&gt; Le corps de texte de l&amp;rsquo;annexe repose sur une police système.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="stack-technique"&gt;&lt;a href="#stack-technique" class="header-anchor"&gt;&lt;/a&gt;Stack technique
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; · &lt;code&gt;NumPy&lt;/code&gt; · &lt;code&gt;SciPy&lt;/code&gt; · &lt;code&gt;Pillow&lt;/code&gt; · &lt;code&gt;reedsolo&lt;/code&gt; · &lt;code&gt;ReportLab&lt;/code&gt; · &lt;code&gt;soundfile&lt;/code&gt; · &lt;code&gt;ffmpeg&lt;/code&gt; · &lt;code&gt;Tesseract (OCR-B)&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Identification sur le terrain des véhicules concernés par un rappel</title><link>https://borisdupoux.com/fr/research/fleet-management/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://borisdupoux.com/fr/research/fleet-management/</guid><description>&lt;h2 id="contexte"&gt;&lt;a href="#contexte" class="header-anchor"&gt;&lt;/a&gt;Contexte
&lt;/h2&gt;&lt;p&gt;Les campagnes de rappel de sécurité supposent d&amp;rsquo;atteindre chaque véhicule concerné, mais
courriers et appels téléphoniques laissent une population résiduelle de propriétaires qui
ne répondent jamais. Dans les territoires insulaires et ultramarins, le problème est plus
aigu : la couverture réseau est inégale, la logistique de terrain s&amp;rsquo;étend sur plusieurs
territoires et le registre de qui conduit quoi est incomplet. La question pratique devient
alors une question de gestion de flotte : &lt;em&gt;quels véhicules du parc en circulation sont
encore concernés, où sont-ils aperçus, et où en est chacun d&amp;rsquo;eux sur le chemin de la
réparation ?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="approche"&gt;&lt;a href="#approche" class="header-anchor"&gt;&lt;/a&gt;Approche
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 A["Liste de rappel&lt;br/&gt;(récupération planifiée du fichier ou CSV manuel)"] --&gt; B["Serveur central&lt;br/&gt;import · versionnage · décodage des noms de modèles"]
 B --&gt;|"diff incrémental"| C["Unités de terrain (ordinateurs portables dans les véhicules des agents)&lt;br/&gt;copie locale de la liste de rappel"]
 D["Flux caméra"] --&gt; E["Détection de plaques + OCR&lt;br/&gt;(sur l'appareil, hors ligne)"]
 E --&gt; F["Correction tenant compte du format&lt;br/&gt;+ confirmation par double lecture"]
 F --&gt; G{"Correspondance avec&lt;br/&gt;la liste de rappel locale ?"}
 G --&gt;|"non"| H["Écartée — rien n'est stocké"]
 G --&gt;|"oui"| I["Alerte à l'agent&lt;br/&gt;+ file d'attente locale"]
 I --&gt;|"synchronisation au retour du réseau"| B
 B --&gt; J["Tableau de bord&lt;br/&gt;unités · tournées · détections · incidents"]
 J --&gt; K["Processus de contact des propriétaires&lt;br/&gt;identifié → contacté → réparé"]&lt;/pre&gt;&lt;h2 id="méthodes"&gt;&lt;a href="#m%c3%a9thodes" class="header-anchor"&gt;&lt;/a&gt;Méthodes
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Ingestion et versionnage des données.&lt;/strong&gt; La liste de rappel est récupérée automatiquement
selon un calendrier ou importée manuellement. Chaque import est comparé au précédent à
l&amp;rsquo;aide d&amp;rsquo;identifiants stables, versionné par empreinte, et seul le delta est envoyé aux
unités de terrain. Les codes de type constructeur sont traduits en noms de modèles lisibles
lors de l&amp;rsquo;import.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Correspondance malgré le bruit de l&amp;rsquo;OCR.&lt;/strong&gt; La détection des plaques et la reconnaissance
des caractères s&amp;rsquo;exécutent sur l&amp;rsquo;ordinateur portable de terrain avec des modèles ONNX, sans
dépendance au réseau. Deux garde-fous réduisent les fausses correspondances : (i) une étape
de &lt;em&gt;correction positionnelle&lt;/em&gt; exploite la structure connue des formats de plaques
nationaux (actuel et ancien) pour lever les confusions classiques de l&amp;rsquo;OCR (O/0, I/1, S/5,
B/8, Z/2, G/6), en rejetant toute lecture ambiguë ; (ii) une &lt;em&gt;confirmation par double
lecture&lt;/em&gt; ne comptabilise une plaque que si elle est lue deux fois dans une courte fenêtre
de temps. Une page web pour smartphone offre une solution de secours manuelle (photo ou
saisie de la plaque, avec validation de la clé de contrôle du VIN).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Synchronisation pensée pour le hors-ligne.&lt;/strong&gt; Les correspondances sont mises en file d&amp;rsquo;attente
localement et transmises au serveur central à la connexion suivante, de sorte que les
détections survivent à des coupures de plusieurs jours. Les unités envoient un signal de
vie (version du logiciel, version de la liste de rappel, compteurs de lectures).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Opérations de terrain.&lt;/strong&gt; Les superviseurs planifient des tournées sous forme de points de
contrôle ordonnés et géolocalisés sur une carte, les attribuent aux équipes et aux unités,
réutilisent des modèles et suivent l&amp;rsquo;avancement. Les agents signalent les incidents avec un
niveau de gravité. Un processus de contact consigne le résultat de chaque démarche auprès
d&amp;rsquo;un propriétaire, et le tableau de bord en déduit un entonnoir de conversion (identifié →
approché → engagé → réparé) avec les tendances hebdomadaires, le délai médian jusqu&amp;rsquo;à la
réparation et une ventilation par territoire.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Protection des données dès la conception.&lt;/strong&gt; Les plaques qui ne figurent pas sur la liste
de rappel ne sont jamais stockées ni transmises ; les enregistrements conservés ont des
durées de conservation fixes avec purge automatique ; les actions sont consignées dans un
journal d&amp;rsquo;audit ; l&amp;rsquo;accès au tableau de bord repose sur des rôles, y compris des comptes en
lecture seule ; les données au repos sont chiffrées. Un registre des traitements a été
rédigé parallèlement au code.&lt;/p&gt;
&lt;h2 id="déploiement--exploitation-devops"&gt;&lt;a href="#d%c3%a9ploiement--exploitation-devops" class="header-anchor"&gt;&lt;/a&gt;Déploiement &amp;amp; exploitation (DevOps)
&lt;/h2&gt;&lt;p&gt;Le système tourne sur deux types de machines très différents : des ordinateurs
portables Windows dans les véhicules des agents, qui peuvent rester hors ligne
plusieurs jours, et un serveur par instance. Après les premières semaines de
terrain, l&amp;rsquo;essentiel du travail d&amp;rsquo;ingénierie a consisté à rendre les deux côtés
faciles à déployer, à superviser et à remettre en service, par une seule
personne, sans interrompre le travail de terrain.&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR
 subgraph ADM["Poste d'administration"]
 GIT["Dépôt Git&lt;br/&gt;arbre commité uniquement"]
 PROV["Script de provisionnement&lt;br/&gt;un fichier de configuration par unité"]
 BLD["Build terrain&lt;br/&gt;paquet PyInstaller + modèles ONNX"]
 end
 subgraph SRV["Serveur (VPS Ubuntu LTS)"]
 CAD["Caddy&lt;br/&gt;TLS · HSTS · sans journal d'accès"]
 APP["Conteneur Docker&lt;br/&gt;API FastAPI + tableau de bord&lt;br/&gt;port en boucle locale uniquement"]
 VOL[("Volume LUKS2&lt;br/&gt;SQLite · photos · archives")]
 TIM["Timers systemd&lt;br/&gt;supervision · sauvegarde · nettoyage"]
 end
 FLD["Portables de terrain&lt;br/&gt;SQLite local · boucle de synchronisation"]
 OBJ[("Stockage objet externe&lt;br/&gt;sauvegardes chiffrées age")]
 CHAT["Alertes messagerie&lt;br/&gt;changements d'état + bilans quotidiens"]
 GIT --&gt;|"git archive via SSH → script de déploiement"| APP
 PROV --&gt;|"API d'administration"| APP
 PROV --&gt;|"fichier de configuration + LISEZMOI"| FLD
 BLD --&gt;|"archive + installateur en un clic"| FLD
 FLD &lt;--&gt;|"HTTPS : signal de vie · envois · diff des rappels"| CAD
 CAD --&gt; APP
 APP --- VOL
 TIM --&gt; VOL
 TIM --&gt;|"copie chiffrée"| OBJ
 TIM --&gt; CHAT&lt;/pre&gt;&lt;h3 id="portables-de-terrain--empaquetage-installation-et-mises-à-jour"&gt;&lt;a href="#portables-de-terrain--empaquetage-installation-et-mises-%c3%a0-jour" class="header-anchor"&gt;&lt;/a&gt;Portables de terrain : empaquetage, installation et mises à jour
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Empaquetage.&lt;/strong&gt; L&amp;rsquo;application de terrain (backend Python, interface React)
est figée avec PyInstaller en un exécutable Windows « un dossier » qui embarque
les modèles ONNX et la configuration de l&amp;rsquo;OCR : une unité n&amp;rsquo;a besoin ni d&amp;rsquo;une
installation Python ni du réseau pour lire les plaques. Des modes intégrés
&lt;code&gt;--diag&lt;/code&gt; et &lt;code&gt;--selftest&lt;/code&gt; vérifient l&amp;rsquo;environnement d&amp;rsquo;exécution embarqué et
lisent une image de test sans lancer l&amp;rsquo;interface, ce qui a permis de
diagnostiquer les échecs de démarrage directement sur la machine de terrain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Installateur en un clic.&lt;/strong&gt; Le build est livré sous forme d&amp;rsquo;archive avec un
&lt;code&gt;INSTALLER.bat&lt;/code&gt; à lancer d&amp;rsquo;un double-clic. Il s&amp;rsquo;élève lui-même en
administrateur et exécute un script PowerShell qui retire des fichiers la
marque « téléchargé depuis Internet » (sans quoi l&amp;rsquo;environnement embarqué ne
se charge pas), désactive la mise en veille USB pour que le dongle GPS ne soit
pas suspendu, et installe le fichier de configuration de l&amp;rsquo;unité là où
l&amp;rsquo;exécutable le lit. Le script refuse de deviner : si plusieurs fichiers de
configuration &lt;em&gt;différents&lt;/em&gt; sont présents, il les liste et demande lequel est
le nouveau. Une réinitialisation optionnelle efface la base locale lorsqu&amp;rsquo;une
unité change de serveur ; elle affiche le serveur cible avant de demander
confirmation et avertit que les détections non synchronisées seraient perdues.
Le jeton d&amp;rsquo;accès de l&amp;rsquo;unité n&amp;rsquo;est jamais affiché. Une mise à jour suit le même
chemin : nouveau build, nouvelle exécution de l&amp;rsquo;installateur.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Provisionnement.&lt;/strong&gt; Un script Python qui n&amp;rsquo;utilise que la bibliothèque
standard, et tourne donc sur un Windows nu, crée les unités à partir d&amp;rsquo;un
fichier CSV via l&amp;rsquo;API d&amp;rsquo;administration du serveur et génère, pour chacune, son
fichier de configuration (adresse du serveur, code de l&amp;rsquo;unité, nom affiché,
jeton) et un LISEZMOI à remettre avec le portable. La clé d&amp;rsquo;administration est
lue dans une variable d&amp;rsquo;environnement ou saisie de manière masquée, jamais
passée en argument de ligne de commande.&lt;/p&gt;
&lt;h3 id="versionnage--logiciel-et-liste-de-rappel"&gt;&lt;a href="#versionnage--logiciel-et-liste-de-rappel" class="header-anchor"&gt;&lt;/a&gt;Versionnage : logiciel et liste de rappel
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Version du logiciel.&lt;/strong&gt; Chaque unité indique la version de son application
dans son signal de vie. Le tableau de bord la compare à la version attendue et
signale les unités qui restent à mettre à jour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Version de la liste de rappel.&lt;/strong&gt; La liste de rappel est versionnée par
empreinte. À chaque cycle, une unité compare son empreinte locale à celle du
serveur : identique, rien à faire ; pas de copie locale, téléchargement
complet ; sinon, le serveur ne renvoie que les lignes ajoutées et retirées
depuis cette empreinte (et l&amp;rsquo;unité se rabat sur un téléchargement complet si
le serveur ne connaît plus sa version). La modification est appliquée en une
seule transaction, et l&amp;rsquo;empreinte locale n&amp;rsquo;avance que si tout a été appliqué.&lt;/p&gt;
&lt;p&gt;Cette dernière règle vient d&amp;rsquo;un incident de terrain. Une contrainte de la base
de données faisait échouer le diff sur une unité, l&amp;rsquo;erreur était absorbée par
la boucle de synchronisation, et l&amp;rsquo;unité continuait d&amp;rsquo;envoyer ses signaux de
vie alors que sa liste de rappel restait figée pendant plus de deux semaines :
elle alertait donc sur des véhicules déjà réparés. La version 1.4.1 a corrigé
la cause, ajouté un retour arrière explicite et livré une migration de schéma
qui conserve les données existantes. Elle a été testée par une série de 62
tests, qui reproduisait le bug et migrait une base à l&amp;rsquo;ancien schéma. La
supervision lève désormais une alerte « synchronisation des rappels figée »
lorsqu&amp;rsquo;une unité n&amp;rsquo;a pas reçu une liste publiée au-delà d&amp;rsquo;un délai de grâce.&lt;/p&gt;
&lt;h3 id="synchronisation-incrémentale-et-résiliente"&gt;&lt;a href="#synchronisation-incr%c3%a9mentale-et-r%c3%a9siliente" class="header-anchor"&gt;&lt;/a&gt;Synchronisation incrémentale et résiliente
&lt;/h3&gt;&lt;p&gt;Toutes les cinq minutes, ou à la demande, une unité exécute un cycle de
synchronisation composé d&amp;rsquo;étapes indépendantes : signal de vie, envoi des
détections (par lots), trace GPS, incidents, mises à jour des points de
contrôle, puis récupération de la liste de rappel et des tournées. Les envois
passent avant les récupérations, de sorte que les données de terrain partent
en premier. Une étape en échec ne bloque plus les autres : dans une version
antérieure, le cycle était monolithique, et un signal de vie en échec a un
jour retardé les détections de 22 minutes. Les requêtes utilisent des délais
d&amp;rsquo;attente courts, les téléchargements des délais plus longs. Le signal de vie
transmet la version du logiciel, la version de la liste de rappel, le nombre
de détections en attente et les compteurs de lectures, sur lesquels reposent
le tableau de bord et la supervision.&lt;/p&gt;
&lt;h3 id="déploiement-du-serveur"&gt;&lt;a href="#d%c3%a9ploiement-du-serveur" class="header-anchor"&gt;&lt;/a&gt;Déploiement du serveur
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Kit d&amp;rsquo;instance.&lt;/strong&gt; Chaque déploiement est une instance indépendante, décrite
par un court identifiant, sur un serveur virtuel Ubuntu LTS. Un script
d&amp;rsquo;amorçage, interactif et relançable sans risque, installe les paquets
système, Docker et Caddy depuis leurs dépôts officiels. Il active les mises à
jour de sécurité automatiques sans redémarrage automatique, restreint SSH à
l&amp;rsquo;authentification par clé, active un pare-feu en refus par défaut et une
protection contre la force brute, et vérifie que l&amp;rsquo;enregistrement DNS pointe
vers le serveur avant d&amp;rsquo;appliquer la configuration TLS. Les secrets résident
dans des fichiers de configuration réservés à root sur le serveur, jamais dans
le dépôt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conteneur et proxy inverse.&lt;/strong&gt; Un Dockerfile multi-étapes construit le
tableau de bord React avec Node, puis exécute le serveur FastAPI sur une image
Python allégée, sous un utilisateur non privilégié. Son contrôle de santé
prévoit une période de démarrage de trois minutes, car les modèles de plaques
et d&amp;rsquo;OCR sont chargés avant que le serveur n&amp;rsquo;écoute. Le conteneur n&amp;rsquo;est publié
que sur l&amp;rsquo;interface de boucle locale. Caddy est le seul point d&amp;rsquo;entrée public :
certificat Let&amp;rsquo;s Encrypt automatique, HSTS explicite et aucun journal
d&amp;rsquo;accès, car les URL de scan contiennent des plaques. Le journal d&amp;rsquo;accès de
l&amp;rsquo;application elle-même est désactivé pour la même raison.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Déploiement et retour arrière.&lt;/strong&gt; Le code ne quitte le poste
d&amp;rsquo;administration que sous la forme d&amp;rsquo;un &lt;code&gt;git archive&lt;/code&gt; d&amp;rsquo;un arbre commité : les
modifications non commitées sont listées et ne partent pas, et les fins de
ligne sont forcées en LF. Sur le serveur, le nouvel arbre est extrait à côté
de l&amp;rsquo;actuel puis permuté, le précédent est conservé, et le commit déployé est
consigné. Le script de déploiement se détache ensuite de la session SSH : une
connexion coupée n&amp;rsquo;interrompt ni le déploiement ni un retour arrière. Un
verrou empêche les déploiements concurrents. Le script construit l&amp;rsquo;image
(étiquetée avec son commit), conserve l&amp;rsquo;image précédente comme &lt;code&gt;rollback&lt;/code&gt;,
recrée le conteneur et attend qu&amp;rsquo;il se déclare en bonne santé. Il abandonne
au bout de cinq minutes, ou dès que le conteneur a redémarré deux fois. En
cas d&amp;rsquo;échec, il revient automatiquement à l&amp;rsquo;image et à l&amp;rsquo;arbre source
précédents, met de côté le code en échec et envoie une alerte. Revenir à
n&amp;rsquo;importe quelle version antérieure revient à redéployer ce commit. Un retour
arrière d&amp;rsquo;image ne défait pas une migration de schéma : la procédure
documentée consiste donc à faire une sauvegarde avant tout déploiement qui
modifie le schéma.&lt;/p&gt;
&lt;h3 id="volume-chiffré-et-redémarrages-sûrs"&gt;&lt;a href="#volume-chiffr%c3%a9-et-red%c3%a9marrages-s%c3%bbrs" class="header-anchor"&gt;&lt;/a&gt;Volume chiffré et redémarrages sûrs
&lt;/h3&gt;&lt;p&gt;Les données du serveur (base, photos de contact, archives des listes de
rappel) résident dans un conteneur de fichier LUKS2 monté avec des options
restrictives. Sa phrase de passe n&amp;rsquo;est jamais stockée sur la machine : après
un redémarrage, une personne déverrouille le volume. Le conteneur redémarre de
lui-même, mais le serveur refuse de démarrer tant qu&amp;rsquo;un fichier sentinelle
&lt;em&gt;situé sur le volume chiffré&lt;/em&gt; est absent. Sans lui, un redémarrage aurait
laissé un dossier vide à la place du volume, et l&amp;rsquo;application y aurait créé
une base neuve, non chiffrée, et accepté les données de terrain. Cette
protection a été vérifiée dans les deux sens sur un conteneur jetable. Un
script distinct agrandit le volume pendant qu&amp;rsquo;il est monté.&lt;/p&gt;
&lt;h3 id="sauvegardes-et-reprise"&gt;&lt;a href="#sauvegardes-et-reprise" class="header-anchor"&gt;&lt;/a&gt;Sauvegardes et reprise
&lt;/h3&gt;&lt;p&gt;Un timer systemd quotidien prend un instantané cohérent de la base SQLite via
son API de sauvegarde, l&amp;rsquo;archive avec les photos et les archives de rappel, et
chiffre le résultat avec &lt;code&gt;age&lt;/code&gt; vers une clé publique. La clé privée n&amp;rsquo;est
affichée qu&amp;rsquo;une fois, à sa création, et conservée hors du serveur. Les
sauvegardes sont gardées localement et, en option, copiées vers un stockage
objet compatible S3 avec &lt;code&gt;rclone&lt;/code&gt;, configuré uniquement par variables
d&amp;rsquo;environnement. Un mode de &lt;em&gt;test&lt;/em&gt; de restauration déchiffre une sauvegarde
dans un dossier temporaire sur le volume chiffré, lance un contrôle
d&amp;rsquo;intégrité, compte les lignes par table, puis efface tout. Le mode
d&amp;rsquo;&lt;em&gt;application&lt;/em&gt; déplace l&amp;rsquo;état courant de côté au lieu de le supprimer. La
documentation comprend une reconstruction pas à pas après perte totale du
serveur. Le plan de continuité vise un délai de reprise de 4 heures et une
perte de données maximale de 24 heures.&lt;/p&gt;
&lt;h3 id="supervision"&gt;&lt;a href="#supervision" class="header-anchor"&gt;&lt;/a&gt;Supervision
&lt;/h3&gt;&lt;p&gt;Un chien de garde s&amp;rsquo;exécute toutes les 15 minutes et ne publie sur un webhook
de messagerie que lorsqu&amp;rsquo;un état change (problème, puis « rétabli »). Un bilan
plus complet est envoyé deux fois par jour, calé sur les horaires de terrain.
Il vérifie que le volume chiffré est monté, le point de santé de l&amp;rsquo;API (avec
plusieurs essais, car l&amp;rsquo;import quotidien peut le bloquer environ une minute),
l&amp;rsquo;état de santé du conteneur, la lisibilité de la base, l&amp;rsquo;occupation du disque
système et du volume chiffré, la taille du journal d&amp;rsquo;écriture anticipée de
SQLite, l&amp;rsquo;expiration du certificat TLS, l&amp;rsquo;âge et la taille de la dernière
sauvegarde, les unités silencieuses depuis plus de 48 heures (et non 24, car
les unités sont éteintes le week-end) et les unités dont la liste de rappel
est figée. Un guetteur distinct alerte lorsqu&amp;rsquo;aucun import de liste de rappel
n&amp;rsquo;a eu lieu depuis plus de 30 heures. Plusieurs de ces contrôles ont été
ajoutés après des incidents réels : le volume chiffré a un jour atteint 90 %
sans aucune alerte, car seul le disque système était surveillé. Un timer
hebdomadaire nettoie les caches de construction Docker et ne conserve que les
images courante et de &lt;code&gt;rollback&lt;/code&gt;. Un script dédié tronque le journal SQLite
avec une attente de verrou courte, afin que les écritures du terrain ne
soient jamais bloquées longtemps.&lt;/p&gt;
&lt;h3 id="résilience-hors-ligne"&gt;&lt;a href="#r%c3%a9silience-hors-ligne" class="header-anchor"&gt;&lt;/a&gt;Résilience hors ligne
&lt;/h3&gt;&lt;p&gt;Le côté terrain est conçu pour continuer à fonctionner pendant une panne du
serveur : lecture des plaques, correspondance avec la copie locale de la liste
de rappel, alertes, tournées déjà téléchargées et onglet de statistiques local
fonctionnent sans réseau, et la file d&amp;rsquo;attente se vide à la connexion
suivante. Seuls le tableau de bord (et la page pour
smartphone hébergée sur le serveur) sont indisponibles tant que le serveur
est arrêté.&lt;/p&gt;
&lt;h3 id="tests"&gt;&lt;a href="#tests" class="header-anchor"&gt;&lt;/a&gt;Tests
&lt;/h3&gt;&lt;p&gt;Le dépôt ne comporte pas de chaîne d&amp;rsquo;intégration continue. Les versions sont
testées avant leur livraison, et les commits consignent ces exécutions :
12/12 et 6/6 pour les étapes de correction des plaques et de confirmation,
62 tests pour la version 1.4.1. Les comportements qui ne se prêtent pas aux
tests unitaires, comme la protection du volume ou un déploiement réel, ont été
vérifiés sur des conteneurs jetables et sur le point de santé de la
production.&lt;/p&gt;
&lt;h2 id="résultats"&gt;&lt;a href="#r%c3%a9sultats" class="header-anchor"&gt;&lt;/a&gt;Résultats
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Lors des premières opérations de terrain, les agents ont signalé &lt;strong&gt;32 %&lt;/strong&gt; des détections
comme des erreurs de lecture sur environ une semaine. Cette mesure a motivé les étapes de
correction positionnelle et de confirmation par double lecture, et les statistiques du
tableau de bord excluent désormais les détections marquées comme faux positifs.&lt;/li&gt;
&lt;li&gt;Les nouvelles étapes ont été livrées avec des tests unitaires : &lt;strong&gt;12/12&lt;/strong&gt; pour la
correction des plaques et &lt;strong&gt;6/6&lt;/strong&gt; pour la confirmation, les réglages et le journal des
lectures.&lt;/li&gt;
&lt;li&gt;Après l&amp;rsquo;extension de la table de correspondance des noms de modèles, &lt;strong&gt;une seule&lt;/strong&gt; ligne
de la liste de rappel de production restait sans nom de modèle décodé.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aucun taux de reconnaissance de bout en bout n&amp;rsquo;a encore été mesuré.&lt;/p&gt;
&lt;h2 id="limites--suite"&gt;&lt;a href="#limites--suite" class="header-anchor"&gt;&lt;/a&gt;Limites &amp;amp; suite
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;La précision de la reconnaissance n&amp;rsquo;a pas été mesurée sur un banc d&amp;rsquo;essai avec vérité
terrain. Les objectifs du cahier des charges (taux de lecture, latence) sont des
objectifs de conception, non des résultats.&lt;/li&gt;
&lt;li&gt;Aucune lecture de plaque à l&amp;rsquo;ancien format n&amp;rsquo;a été observée au départ. Un compteur dédié
suit désormais ces lectures de bout en bout, mais le correctif doit encore être vérifié
sur le terrain.&lt;/li&gt;
&lt;li&gt;Une fausse correspondance avec une liste volumineuse coûte toujours du temps aux agents.
L&amp;rsquo;étape suivante consiste à calibrer le seuil de confiance et la fenêtre de confirmation
sur des vidéos de terrain annotées.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="stack-technique"&gt;&lt;a href="#stack-technique" class="header-anchor"&gt;&lt;/a&gt;Stack technique
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; · &lt;code&gt;FastAPI&lt;/code&gt; · &lt;code&gt;SQLite&lt;/code&gt; · &lt;code&gt;ONNX Runtime&lt;/code&gt; · &lt;code&gt;fast-alpr&lt;/code&gt; (détecteur de plaques YOLOv9 + OCR) · &lt;code&gt;OpenCV&lt;/code&gt; · &lt;code&gt;PaddleOCR&lt;/code&gt; · &lt;code&gt;React&lt;/code&gt; · &lt;code&gt;TypeScript&lt;/code&gt; · &lt;code&gt;Vite&lt;/code&gt; · &lt;code&gt;Leaflet&lt;/code&gt; · &lt;code&gt;Docker&lt;/code&gt; · &lt;code&gt;Caddy&lt;/code&gt; · &lt;code&gt;LUKS&lt;/code&gt; · &lt;code&gt;systemd&lt;/code&gt; · &lt;code&gt;age&lt;/code&gt; · &lt;code&gt;rclone&lt;/code&gt; · &lt;code&gt;PyInstaller&lt;/code&gt; · &lt;code&gt;PowerShell&lt;/code&gt;&lt;/p&gt;</description></item></channel></rss>