💾 Archived View for unbon.cafe › lejun › posts › 20230117_osmoseIntegration.gmi captured on 2024-02-05 at 09:56:25. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

Osmose : Intégration

2023-01-17

Osmose, pour OpenStreetMap Oversight Search Engine, est un outil qualité permettant d’interagir avec les données OpenStreetMap. Il permet entre autre de mettre en évidence des erreurs mais également l’intégrations de données OpenData.

Format d’analyse

Les analyses reposent sur du code Ă©crit en Python, SQL et MapCSS.

Cas d’usage : Stationnement vélo

Surprennament, la communauté OpenStreetMap est encore loin d’être mature, et beaucoup de chose reste encore à construire. Il a été porté à mon attention que les données OpenData de Strasbourg n’étaient pas prises en charge par Osmose, de quoi faire mes premiers pas – documentés – avec la structure d’Osmose.

Deux jeux de données sont fournis par l’Eurométropole de Strasbourg, un premier, et un second datant de 2023 qui suit le format de la Base Nationale du Stationnement Cyclable. Apparaît tout de même une différence de 1000 emplacements entre les deux jeux (8000 pour le premier contre 7000 sur le second). Pour éviter tout type de conflit je vais uniquement mettre en place l’intégration du second, je m’occuperai de tirer autant de données que possible du premier via Conflation sous JOSM[1].

Par chance, l’intégration de stationnement – qui plus est vélo – est déjà prise en charge par l’outil sous la référence item 8150, et des exemples ressortent lors d’une recherche dans les tickets pour les villes de Bordeaux et Paris. Je n’ai donc qu’à copier allégrement le format utilisé et m’éviter de devoir lancer des tests (qui me paraissent encore flous). Deux fichiers seront concernées par l’intégration : `osmose_config.py` ainsi qu’un analyser `merge_bicycle_parking_FR_strasbourg` qu’il faudra créer.

Pas de difficulté apparente et il me suffit de calquer ce qui a déjà été fait, je rajoute sur `osmose_config.py` un lien vers l’analyser que je vais créer par la suite.

france_departement("alsace/bas_rhin", 7415, "FR-67"), include=[
    # Strasbourg
    'merge_bicycle_parking_FR_strasbourg',
])

L’analyser est plus complexe à bidouiller que prévu. J’ai rapidement sélectionné à la volée Bordeaux, Paris et Madrid qui intègrent les stationnement cyclables locaux, des trois seul Paris propose également une analyse au format CSV et non SHP, comme Strasbourg. Une sélection des données est proposée, utile dans le cas de données mixtes ce qui n’est pas mon cas, je retire donc la fonction `select` de `Load_XY`. Enfin vient la question des attributs. Il semble que les intégrations soient relativement légères jusque là, qu’à cela ne tienne, Strasbourg peut être pionnière.

Le jeu de données possède 21 champs à intégrer sous forme de clés, pas besoin de réinventer l’eau chaude, le travail a déjà été fait et est disponible sur le site du gouvernement :

Pour transformer les valeurs données au format OSM, j’ai également pris exemple et copié du code sur d’autres types d’éléments – J’ai dis que je maîtrisais absolument pas Python ? – pour obtenir des correspondances 1:1. Par chance, les valeurs sont peu diverses et j’ai pu facilement m’en sortir, mais suivant son développement je vais devoir me retrousser les manches…

#!/usr/bin/env python
#-*- coding: utf-8 -*-

###########################################################################
##                                                                       ##
## Copyrights LeJun 2023                                                 ##
##                                                                       ##
## This program is free software: you can redistribute it and/or modify  ##
## it under the terms of the GNU General Public License as published by  ##
## the Free Software Foundation, either version 3 of the License, or     ##
## (at your option) any later version.                                   ##
##                                                                       ##
## This program is distributed in the hope that it will be useful,       ##
## but WITHOUT ANY WARRANTY; without even the implied warranty of        ##
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         ##
## GNU General Public License for more details.                          ##
##                                                                       ##
## You should have received a copy of the GNU General Public License     ##
## along with this program.  If not, see <http://www.gnu.org/licenses/>. ##
##                                                                       ##
###########################################################################

from modules.OsmoseTranslation import T_
from .Analyser_Merge import Analyser_Merge_Point, SourceOpenDataSoft, CSV, Load_XY, Conflate, Select, Mapping

class Analyser_Merge_Bicycle_Parking_FR_Strasbourg(Analyser_Merge_Point):
    def __init__(self, config, logger = None):
        Analyser_Merge_Point.__init__(self, config, logger)
        self.def_class_missing_official(item = 8150, id = 81, level = 3, tags = ['merge', 'public equipment', 'bicycle', 'fix:survey', 'fix:picture'],
            title = T_('Bicycle parking not integrated'))

        self.init(
            "https://data.strasbourg.eu/explore/dataset/stationnementcyclable_ville_et_eurometropole_de_strasbourg/information/",
            "Stationnement cyclable au format BNSC",
            CSV(SourceOpenDataSoft(
                attribution="Ville et eurométropole de Strasbourg",
                url="https://data.strasbourg.eu/explore/dataset/stationnementcyclable_ville_et_eurometropole_de_strasbourg/",
                encoding="utf-8-sig")),
            Load_XY("coordonneesxy", "coordonneesxy",
                xFunction = lambda x: Load_XY.float_comma(x[1:-1].split(',')[0]),
                yFunction = lambda y: Load_XY.float_comma(y[1:-1].split(',')[1])
            ),
            Conflate(
                select = Select(
                    types = ["nodes", "ways"],
                    tags = {"amenity": "bicycle_parking"}),
                conflationDistance = 20,
                mapping = Mapping(
                    static1 = {"amenity": "bicycle_parking"},
                    static2 = {"source": self.source},
                    mapping1 = {
                        "capacity": lambda res: None if res["capacite"] in (None, "0") else res["capacite"],
                        "capacity:cargo_bike": lambda res: None if res["capacite_cargo"] in (None, "0") else res["capacite_cargo"],
                        # "bicycle_parking": (type_accroche, mobilier, protection),
                    },
                    mapping2 = {
                        "ref": "id_local",
                        # "access": "acces"
                        "fee": lambda res: "no" if res["gratuit"] == "vrai" else None,
                        "covered": lambda res: "yes" if res["couverture"] == "vrai" else None,
                        "surveillance": lambda res: "yes" if res["surveillance"] == "vrai" else None,
                        "lit": lambda res: "yes" if res["lumiere"] == "vrai" else None,
                        "website": "url_info",
                        "start_date": "d_service",
                        "owner": "proprietaire",
                        "operator": lambda res: "Eurométropole de Strasbourg" if res["gestionnaire"] == "eurometropole" else None,
                        "note": "commentaires"} )))

Tous les éléments me paraissant essentiels, j’avais choisi de mettre tous les attributs dans la variable `mapping1` avant qu’on me demande par la suite d’en reléguer au `mapping2` de sorte à alléger la charge sur Osmose. J’ai également laissé en commentaire les clés `bicycle_parking` et `access` faute de savoir quelles valeurs et logique la ville utilisera.

Références

[1] JOSM : Conflation, LeJun 2022