-- Leo's gemini proxy

-- Connecting to unbon.cafe:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini;

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 :


`id_local` deviendra `ref` ;

`id_osm` est un champ laissé vide. Cela semble plus être utilisé dans le but d’export depuis OpenStreetMap ;

`code_com` peut être utilisé pour le code INSEE de la commune, inutile dans notre cas ;

`coordonneesxy`, explicite mais j’ai tout de même vérifié que c’était dans cet ordre et pas Y,X ;

`capacite` semble être la capacité de stationnement soit `capacity`. Je suis tout de même surpris d’y voir des valeurs nulles (431 éléments avec une capacité de 0) ainsi que de nombres impairs (sachant le nombre d’arceaux). Par précaution je pense essayer de filtrer ces valeurs nulles et ne simplement pas mettre de capacité.

`capacite_cargo` est l’équivalent de `capacity:cargo_bike`, à savoir le nombre de vélo-cargos. Malheureusement laissé vide :

`type_accroche` décrit le type de stationnement proposé, soit `bicycle_parking` en tant que clé. Tous les éléments n’affichent que la valeur « Cadre et roue » ce qui me laisse plus que dubitatif ;

`mobilier` a un usage similaire au champ précédant, au cas où la classification OpenStreetMap ne soit pas assez discriminante. Ici, seule la valeur « Autre » est inscrite ;

`acces` correspond à `access` et permet d’indiquer le mode d’accès à un élément ;

`gratuit` correspond à l’attribut `fee=no` ;

`protection` permet également de préciser le type de stationnement `bicycle_parking` ;

`couverture` indique si l’élément est couvert ou non des intempéries `covered`, les valeurs utilisées sont « vrai » et « faux » ;

`surveillance` précise si l’élément est surveillé d’une manière ou d’une autre ;

`lumiere` indique si l’emplacement est éclairé, `lit`, ou non ;

`url_info` permet de donner un lien internet pour plus d’informations sur l’emplacement. Cela correspondra ainsi à `website`, `operator:website`, ou `contact:website` ;

`d_service` est la date de mise en service, `start_date` ;

`source` fait partie des champs utiles pour les communes, par défaut la valeur doit être OpenStreetMap ;

`proprietaire` est le nom de l’organisation possédant l’emplacement, soit `owner` ;

`gestionnaire` est le nom de l’organisation en charge de l’emplacement, soit `operator`. Les valeurs indiquent si c’est l’Eurométropole qui est en charge ou non ;

`date_maj` est la date de dernière modification sur OpenStreetMap ;

`commentaires` est un champ contenant des renseignement divers, correspondant ainsi aux champs `description`, `note` ou `fixme`.


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

-- Response ended

-- Page fetched on Sun May 19 01:34:06 2024