Like the Plugins, the MapCSS are dedicated to check the tags of one object at the time.
The MapCSS is more easy to understand and write than the Python implementation. The definition of the MapCSS language is from JOSM. The MapCSS code can also be run and shared with the JOSM validator.
For explanation purpose only, we just here make a plugin that report fountains, it is not looking for issue in the data.
Each MapCSS file must begin by a set of general declaration named meta
.
Note 1, We are in a Python Jupyter note book, so we need to quote the MapCSS code into Python String. But it does not have to be so in a plain MapCSS file.
Note 2, the declarations stating with -osmose
are specific to Osmose-QA and ignored by JOSM.
In [1]:
%cd "/opt/osmose-backend/"
mapcss_code = """
meta {
title: "Osmose-QA – Object here";
description: "Nice report.";
author: "Bob";
min-josm-version: 14481;
-osmoseTags: list("tag");
}
meta[lang=en] { /* lang=en, unused, only to use tr() to catch string for translation */
description: tr("Nice report.");
}
meta[lang=fr] {
description: "Chouette rapport.";
}
"""
Rules are written like CSS for HTML, but on OSM Objects. You must select type of objects, one of:
node
,way
,relation
,area
is not support in Osmose-QA implementation),*
.The condition must be applied to filter objects, use as many conditions as required: [amenity=fountain]
.
Once objects are selected, Osmose-QA issues are yield using one throwError
or throwWarning
. throwError
is by default mapped to Osmose-QA level of issue 2, and throwWarning
to level 3. JOSM also define throwOther
, but is ignored by Osmose-QA.
In [2]:
mapcss_code = """
*[amenity=fountain] {
throwError: tr("Fountain here");
}
"""
Osmose-QA specific declaration can be added to match the Osmose-QA issue item, class, level and tags.
In [3]:
mapcss_code = """
*[amenity=fountain] {
throwWarning: tr("Fountain here");
-osmoseItemClassLevel: "4030/40301/2";
-osmoseTags: list("fix:survey"); // The tags are added to the on of the global declaration
}
"""
Unitary tests should be set to validate the behaviors of the rule. Set as many asserts as required.
assertMatch
: should define an object that will match the rule.assertNoMatch
: should define an object that will not match the rule.The rule is run with all objects defined in assertMatch
and assertNoMatch
to ensure the expected behaviors.
In [4]:
mapcss_code = """
*[amenity=fountain] {
throwError: tr("Fountain here");
assertMatch: "way amenity=fountain";
assertMatch: "way amenity=fountain name='Eau Claire'";
assertNoMatch: "node sport=boules";
}
"""
Then we can convert the MapCSS code to Python. Using this command line to produce a Fountain.py
file, from the root directory:
python -m mapcss.mapcss2osmose plugins/Fountain.validator.mapcss
But here, we compile the MapCSS programmatically.
In [5]:
from modules.jupyter import *
# Define the Fountain Python plugin, and it Test class
compiled = compile_mapcss(mapcss_code, 'Fountain')
# Run the test
compiled.Test().test() # Returns nothing where it is OK, else error.
To run the analyze we need a context of execution. Each country or area have a entry in the file osmose_config.py
.
In [6]:
import osmose_config as config
country_conf = config.config['monaco']
country_conf.init()
country_conf.analyser_options
Out[6]:
The plugins are run by the analyzer "sax". The result can be fetched by Jupyter and displayed. By default it is in Osmose-QA XML format. CSV en GeoJson format are for debug only and have partial content.
In [7]:
from analysers.analyser_sax import Analyser_Sax
from modules.jupyter import *
csv = run(country_conf, Analyser_Sax, plugin = compiled.Fountain, format = 'csv')
print_csv(csv)
Out[7]:
In [8]:
geojson = run(country_conf, Analyser_Sax, plugin = compiled.Fountain, format = 'geojson')
print_geojson(geojson)
In [ ]: