Visualisation de données en Flask§

Avec Matplotlib§

Rappel sur Matplotlib§

from matplotlib.figure import Figure

bins = ["A", "B", "C", "D", "E", "F"]
values = [3,  5,  8,  4,  2,  1]
cumul  = [3,  8, 16, 20, 22, 23]

fig = Figure()
ax1, ax2 = fig.subplots(2, 1)
fig.suptitle("Répartition par appréciation")
ax1.bar(bins, values)
ax2.bar(bins, cumul)
../_images/rappel_matplotlib.png

Sauvegarder dans un fichier§

fig.savefig("/tmp/test.png", format="png")

ou

with open("/tmp/test.png", 'wb') as f:
    fig.savefig(f, format="png")

Formats supportés : png (défaut), pdf, svg...

BytesIO§

La classe io.BytesIO permet de créer un fichier virtuel, dont le contenu est stocké en mémoire, et accessible à l’aide de la méthode getvalue.

from io import BytesIO

b = BytesIO()
b.write(b"hello")
b.write(b" world")
print(b.getvalue())

# affiche b'hello world'

Générer un graphique dans Flask§

@app.route("/foo/<bar>/baz.png")
def example_matplotlib(bar):
    data = make_data_from(bar) # requête SQL ou autre...

    fig = Figure()
    # ... création du graphique à partir de data ...

    b = BytesIO()
    fig.savefig(b, format="png")

    resp = make_response(b.getvalue())
    resp.headers['content-type'] = 'image/png'
    return resp

Initiation à SVG§

Qu’est-ce que SVG ?§

  • SVG signifie Scalable Vector Graphics.
  • C’est un langage à balise, similaire à HTML, pour décrire des objets graphiques.
  • Il peut être utlisé à l’intérieur d’un document HTML.

Indice

Contrairement aux images raster comme PNG, qui sont discrétisées en pixels, les images vectorielles décrivent des formes mathématiques, qui peuvent donc être redimensionnées à volonté, sans perte de qualité.

Exemple§

<svg viewBox="-50 -50 100 100">
    <circle cx="0" cy="0" r="40" style="fill:red" />
    <rect x="-27.5" y="-7.5" width="55" height="15"
          style="fill:white" />
</svg>

La balise svg§

  • Elle contient tous les autres éléments SVG.

  • L’attribut viewBox définit la zone affichable :

    • x minimum (bord gauche)
    • y minimum (bord haut)
    • largeur
    • hauteur
  • La taille réelle est fixée

    • soit par CSS,
    • soit par des attributs «idth et height directement dans la balise svg.

La balise circle§

  • Elle décrit un cercle.

  • Elle utilise les attributs suivants :

    • cx: abscisse du centre
    • cy: ordonnée du centre
    • r: rayon

Important

En SVG, les balises sans contenue doivent être explicitement fermée, en les terminant par />.

La balise rect§

  • Elle décrit un rectangle.

  • Elle utilise les attributs suivants :

    • x: abscisse du coin supérieur gauche
    • y: ordonnée du coin supérieur gauche
    • width: largeur
    • height: hauteur
  • Attributs optionnels:

    • rx: rayon horizontal des coins
    • ry: rayon vertical des coins (si différent de rx)

Exemples de rect§

<svg viewBox="0 0 100 100">
    <rect x="10" y="10" width="80" height="40" rx="10"
          style="fill:teal"/>
    <rect x="10" y="55" width="80" height="40" rx="20" ry="10"
          style="fill:orange"/>
</svg>

La balise line§

  • Elle décrit une ligne.

  • Elle utilise les attributs suivants :

    • x1: abscisse du premier point
    • y1: ordonnée du premier point
    • x2: abscisse du second point
    • y2: ordonnée du second point

Exemples de rect§

<svg viewBox="0 0 100 100">
    <line x1="10" y1="10" x2="50" y2="10" style="stroke:black"/>
    <line x1="10" y1="20" x2="60" y2="30" style="stroke:black"/>
    <line x1="10" y1="30" x2="80" y2="50" style="stroke:black"/>
</svg>

Attributs CSS pour SVG§

  • stroke : couleur du trait/contour
  • fill : couleur de remplissage
  • stroke-width : largeur du trait
  • stroke-dasharray : largeurs des pointillés

Cette liste n’est pas exhaustive.

Ces attributs peuvent être spécifiés

  • directement dans l’attribut style, ou
  • via une feuille de style,
  • y compris via une classe.

Exemple CSS§

circle { stroke-width: 5 }
.foo { stroke: blue; fill: red }
.bar { stroke: green; fill: yellow }
<svg viewBow="0 0 200 100">
    <circle cx="50" cy="50" r="45" class="foo" />
    <circle cx="150" cy="50" r="45" class="bar" />
</svg>

CSS et interactivité§

CSS permet de plus d’ajouter un peu d’interactivité, notamment avec la pseudo-classe CSS :hover (documentation).

Liens en SVG§

<svg viewBox="0 0 100 100">
  <a href="http://champin.net/">
    <rect x="10" y="10" width="80" height="40" rx="10"
          style="fill:teal"/></a>
  <a href="http://www.univ-lyon1.fr/">
    <rect x="10" y="55" width="80" height="40" rx="20" ry="10"
          style="fill:orange"/></a>
</svg>

Autres balises SVG§

Visualisation de données en SVG§

SVG et matplotlib§

  • matplotlib permet de générer facilement des graphiques complexes.
  • Il génère du SVG “auto-suffisant” qu’on peut insérer dans une balise img mais pas directement dans le HTML,
  • ce qui limite les possibilités d’interaction.

SVG et template§

Les templates Jinja2 peuvent être utilisés pour générer du SVG.

Il sera cependant nécessaire de leur fournir des données « pré-traitées », dans lesquels les calculs géométriques compliqués ont été fait au préalable en Python.

Note

Les boucles {% for ... %} peuvent être utilisée autour d’un ensemble de balise, mais également à l’intérieur d’un attribut (utile pour polyline ou path).

Exemple d’histogramme en SVG§

<svg viewBox="-10 -10 130 110">
  <polyline points="0,90 0,0 110,0"/>
  <path d="M 25,0 V -3 M 50,0 V -3 M 75,0 V -3 M 100,0 V -3"/>
  <a href="#A">
    <rect x="0" y="5" width="40" height="20"/>
    <text x="0" y="5" dx="5" dy="12" text-anchor="middle">A</text></a>
  <a href="#B">
    <rect x="0" y="35" width="73" height="20" fill="teal"/>
    <text x="0" y="35" dx="5" dy="12" text-anchor="middle">B</text></a>
  <a href="#C">
    <rect x="0" y="65" width="42" height="20" fill="teal"/>
    <text x="0" y="65" dx="5" dy="12">C</text></a>
</svg>
A B C