version 20230116

This commit is contained in:
Guillaume RYCKELYNCK 2023-01-16 15:12:03 +01:00
parent 209b8c3b99
commit 68d9b2dd53
2043 changed files with 541 additions and 314 deletions

0
doc/docs/about.md Normal file
View File

View File

@ -0,0 +1,76 @@
# Implémentation
## Structure de la base de données
La base de donnée est organisée afin de faciliter la sélection de dalles à partir d'une emprise géographique. Elle s'appuie sur 3 concepts clés:
- La notion d'emprise administrative
- La notion de produits (base de données spatiale raster)
- La notion de dalles à extraire (unité minimale de diffusion d'un produit raster)
L'application doit donc sélectionner, en fonction d'une emprise et d'un produit les dalles d'intersection.
A noter:
- Une emprise peut être de différents type: Commune, EPCI, PNR, SCOT. Pour faciliter la gestion, une table spatiale a été produite pour chaque type d'emprise.
- Un fichier de dallage peut varier selon le produit considéré. Par exemple, les données IGN sont diffusées selon le cas en dalles de 1 km ou 5 km.
Ainsi, les étapes d'interaction avec la BDD sont les suivantes:
1. l'utiliateur choisit un type d'emprise
2. le système récupère la liste des emprises dans la table correspondante à ce type et la propose à l'utilisateur
3. l'utiliateur choisit une emprise
4. le système:
- croise cette emprise avec la couche spatiale de chaque produit pour voir ceux qui intersectent l'emprise choisie
- propose à l'utilisateur cette liste de produit
5. l'utilisateur sélectionne un produit et lance l'opération de sélection des dallées
6. Le système croise l'emprise sléectionnée avec la couche des dalles du produit sélectionnée
7. Le système propose la liste des dalles à l'utilisateur sous forme:
- de liens de téléchargement
- d'un fichier TXT
- d'un aperçu sous forme d'image
- d'une application Leaflet auto-générée
La structure de la BDD est donc relativement simple:
- 1 table spatiale par type d'emprise (communes, epci, pnr et scot) avec les champs:
- CODE
- NAME
- 1 table spatiale de l'ensemble des produits. Chaque produit est généré par la fusion de l'ensemble des dalles qui le constitue:
- CODE
- NAME: permet d'afficher un nom de produit compéhensible par l'utilisateur (ex.: "ORTHO IGN RVB 2018-2019 (20cm) - Grand Est")
- DATA_TYPE: non utilisé à ce stade
- DATA_EXTENT: non utilisé à ce stade
- DATA_PRODUCT: non utilisé à ce stade
- DATA_DATE: non utilisé à ce stade
- DATA_RESOLUTION: non utilisé à ce stade
- DATA_COMPRESSION: non utilisé à ce stade
- DATA_TYPE: non utilisé à ce stade
- DATA_DIRECTORY
- DATA_URL
- METADATA_URL
- LAYER_TILES: permet le lien avec les couches de dallage du produit en indiquant le nom de la table contenant les dalles du produit (ex.: "dalles_ortho_1km")
- PARENT: permet de préciser l'interdépendance des produits pour les emprises à cheval sur plusieurs territoires. Ainsi pour un PNR est proposé le produit régional issu de l'union des produits départementaux ainsi que les sous-produits correspodant à chaque département. L'utilisateur peut alors choisir de télécharger uniquement les dalles de son territoire sur un département ou sur l'ensemble des départements qui le concernent.
- 1 table pour chaque dallage des produits
Les pricinpaux liens entre tables se font ensuite lors du calcul spatial des intersections via "geopandas".
![test](./raster-dl_bdd_diagram.png)
<!--
For full documentation visit [mkdocs.org](https://www.mkdocs.org).
## Commands
* `mkdocs new [dir-name]` - Create a new project.
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs -h` - Print help message and exit.
## Project layout
mkdocs.yml # The configuration file.
docs/
index.md # The documentation homepage.
... # Other markdown pages, images and other files.
-->

23
doc/docs/index.md Normal file
View File

@ -0,0 +1,23 @@
# Documentation de "Raster DownLoad"
Application permettant de télécharger une donnée raster sous forme de dalles à partir d'une emprise administrative.
## Fonctionnalités:
- Lister les dalles d'une donnée raster intersectant une emprise administrative
- Possibilité d'export de cette liste (format TXT)
- Possibilité de téléchargement des dalles de cette liste (dalle par dalle)
- Possibilité de visualiser l'emprise et les dalles sélectionnées sous forme d'image
- Possibilité de visualiser l'emprise et les dalles sélectionnées sous forme d'une carto dynamique autogénérée (Leaflet)
- Possibilité de définir un buffer autour de l'emprise
- Possibilité d'utiliser la BBOX de l'emprise comme polygone de sélection (extraction de forme rectangulaire)
## Fonctionnement et usage:
- Sélectionner un type d'emprise administrative (commune, EPCI, PNR ou SCOT)
- Sélectionner une emprise (mise à jour de la liste et autocomplétion du nom en fonction du type d'emprise choisi)
- Sélectionner le cas échéant un buffer (pour élargir l'emprise)
- Sélectionner le cas échéant si l'on veut utiliser la BBOX de l'emprise comme base d'extraction
- Sélectionner le "produit" à extraire (liste générée à partir de l'intersection avec l'emprise sélectionnée)
- Cliquer sur "Valider" pour générer la liste des dalles par intersection du produit avec l'emprise
- Le système propose alors de télécharger la liste des dalles au format TXT ou de télécharger toutes les dalles individuellement

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

36
doc/docs/technical.md Normal file
View File

@ -0,0 +1,36 @@
# Choix techniques:
- Base de données: Geopackage
- Serveur: Python + Eel + Geopandas + Plotly + Folium + ...
- Interface utilisateur: HTML + CSS + JS (Eel et Bootstrap)
## Le choix de GeoPackage
Il était initialement prévu d'utiliser un ensemble de fichiers JSON ou une BDD SQLite avec la pré-génération de l'ensemble des appartenances de chaque dalle en fonction des entités administratives, sur le modèle de https://sig.cc-saulnois.fr/ge_ortho.php.
Les premiers tests ont rapidement montré les limites de cette approche, notamment étant donné le volume de données et le nombre de possibilités de croisement entre ces couches d'information. L'utilisation des fonctions spatiales de GeoPackage pour croiser à la volée la couche des emprises administratives avec celle des dalles semblait plus intéressante.
## Le choix du langage Python
Le choix de Python et des bibliothèques mobilisées a notamment été motivé par la volonté:
- De monter en compétence sur des domaines centraux de l'analyse de données
- D'engager une démarche exploratoire autour des bibliothèqes "pandas" et "geopandas" d'une part
- D'utiliser la bibliothèque "eel" sur un projet concrét
**Les bibliothèques Python de traitement et représentation des données**
Différentes bibliothèques Python de traitement et représentation de données sont mobilisées dans ce projet.
On peut citer notamment:
- "pandas" et "geopandas": son usage a été encouragé par l'absence de bibliothèque simple exploitant les capacités spatiales des GeoPackage via le langage SQL, le recours à PostGreSQL/PostGIS étant exclu ici.
- "plotly" pour afficher les résultats sous forme d'image
- "folium" (découvert au court du projet) pour générer une carte leaflet à la volée
**La bibliothèque Python "eel"**
La bibliothèque "eel" (cf. https://github.com/python-eel/Eel) permet initialement de générer des applications bureautiques en python utilisant le langage HTML (+ CSS + JS) pour construire l'interface utilisateur.
Les tests réalisés ont montré qu'il est ainsi possible de construire une application unique avec un double portage: desktop + web.
Le cas présent, même s'il est limité a permis une première approche de cette solution.
Par ailleurs la partie web (UI) a été réalisée en s'appuyant sur Bootstrap et du javascript natif.

91
doc/mkdocs.yml Normal file
View File

@ -0,0 +1,91 @@
site_name: Raster DownLoad
site_url:
nav:
- Accueil: index.md
- Choix techniques: technical.md
- Implémentation: implementation.md
- A propos: about.md
copyright: 'Copyright © 2023 DataGrandEst'
theme:
name: material
highlightjs: true
palette:
primary: 'blue'
accent: 'blue'
language: fr
features:
- navigation.tracking
- navigation.instant
- navigation.tabs
# - navigation.tabs.sticky
# - navigation.sections
# - navigation.expand
# - navigation.indexes
- navigation.top
- toc.integrate
- search.suggest
- search.highlight
custom_dir: 'docs'
#favicon: img/favicon.ico
#logo: img/logo.png
icon:
logo: material/file-document
font:
text: Arial
code: Roboto Mono
plugins:
- search:
lang: fr
# - tags
extra:
social:
- type: 'github'
link: 'https://github.com/datagrandest'
icon: fontawesome/brands/github-alt
markdown_extensions:
- meta
- toc:
permalink: "#"
baselevel: 1
separator: "-"
toc_depth: 2
- admonition
- footnotes
- pymdownx.arithmatex
- pymdownx.betterem:
smart_enable: all
- pymdownx.caret
- attr_list
- pymdownx.critic
- pymdownx.details
- pymdownx.inlinehilite
- pymdownx.magiclink
- pymdownx.mark
- pymdownx.smartsymbols
- pymdownx.highlight:
linenums: true
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_div_format
- pymdownx.tabbed
- def_list
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.tilde
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
- pymdownx.snippets
- pymdownx.progressbar
- codehilite:
linenums: true

0
doc/raster-dl.docx Normal file
View File

BIN
doc/~$ster-dl.docx Normal file

Binary file not shown.

View File

@ -7,6 +7,8 @@ from shapely.geometry import Polygon
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import folium import folium
gpkg = "../data/raster-dl.gpkg"
@eel.expose @eel.expose
def get_extent_types(): def get_extent_types():
"""Return the list of extends of level layer.""" """Return the list of extends of level layer."""
@ -36,7 +38,7 @@ def get_extent_types():
@eel.expose @eel.expose
def get_extents(level='communes'): def get_extents(level='communes'):
"""Return the list of extends of level layer.""" """Return the list of extends of level layer."""
gdf_level = gpd.read_file("../../data/raster-dl.gpkg", layer=level) gdf_level = gpd.read_file(gpkg, layer=level)
return gdf_level[['name', 'code']].to_dict(orient='records') return gdf_level[['name', 'code']].to_dict(orient='records')
@ -47,7 +49,7 @@ def get_products(code=None, level=None, buffer=0, bbox=False):
if not code or not level: if not code or not level:
return [] return []
gdf_level = gpd.read_file("../../data/raster-dl.gpkg", layer=level) gdf_level = gpd.read_file(gpkg, layer=level)
level_feature = gdf_level[gdf_level['code'] == str(code)] level_feature = gdf_level[gdf_level['code'] == str(code)]
level_feature = level_feature[['geometry', 'code', 'name']] level_feature = level_feature[['geometry', 'code', 'name']]
@ -59,7 +61,7 @@ def get_products(code=None, level=None, buffer=0, bbox=False):
bbox_feature = get_bbox(level_feature) bbox_feature = get_bbox(level_feature)
extent = level_feature extent = level_feature
gdf_products = gpd.read_file("../../data/raster-dl.gpkg", layer='products') gdf_products = gpd.read_file(gpkg, layer='products')
products_seleted = gpd.sjoin(gdf_products, extent, how='inner', predicate='intersects') products_seleted = gpd.sjoin(gdf_products, extent, how='inner', predicate='intersects')
products_seleted['code'] = products_seleted['code_left'] products_seleted['code'] = products_seleted['code_left']
products_seleted['name'] = products_seleted['name_left'] products_seleted['name'] = products_seleted['name_left']
@ -75,7 +77,7 @@ def get_map(code=None, level=None, tiles_layer=None, buffer=0, bbox=False):
if not code or not level or not tiles_layer: if not code or not level or not tiles_layer:
return [] return []
gdf_level = gpd.read_file("../../data/raster-dl.gpkg", layer=level) gdf_level = gpd.read_file(gpkg, layer=level)
level_feature = gdf_level[gdf_level['code'] == code] level_feature = gdf_level[gdf_level['code'] == code]
level_feature = level_feature[['geometry', 'code', 'name']] level_feature = level_feature[['geometry', 'code', 'name']]
@ -87,7 +89,7 @@ def get_map(code=None, level=None, tiles_layer=None, buffer=0, bbox=False):
bbox_feature = get_bbox(level_feature) bbox_feature = get_bbox(level_feature)
extent = level_feature extent = level_feature
gdf_dalles = gpd.read_file("../../data/raster-dl.gpkg", layer=tiles_layer) gdf_dalles = gpd.read_file(gpkg, layer=tiles_layer)
dalles = gdf_dalles[['geometry', 'FILE_IMG', 'DALLE']] dalles = gdf_dalles[['geometry', 'FILE_IMG', 'DALLE']]
dalles_seleted = gpd.sjoin(dalles, extent, how='inner', predicate='intersects') dalles_seleted = gpd.sjoin(dalles, extent, how='inner', predicate='intersects')
@ -112,7 +114,6 @@ def get_map(code=None, level=None, tiles_layer=None, buffer=0, bbox=False):
return dalles_seleted[['DALLE', 'FILE_IMG', 'code']].to_dict(orient='records') return dalles_seleted[['DALLE', 'FILE_IMG', 'code']].to_dict(orient='records')
def get_bbox(layer, buffer=0): def get_bbox(layer, buffer=0):
x_min, y_min, x_max, y_max = layer.total_bounds x_min, y_min, x_max, y_max = layer.total_bounds
bbox_polygon = Polygon([(x_min, y_min), (x_max, y_min), (x_max, y_max), (x_min, y_max)]) bbox_polygon = Polygon([(x_min, y_min), (x_max, y_min), (x_max, y_max), (x_min, y_max)])

View File

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 479 B

After

Width:  |  Height:  |  Size: 479 B

View File

Before

Width:  |  Height:  |  Size: 511 B

After

Width:  |  Height:  |  Size: 511 B

View File

Before

Width:  |  Height:  |  Size: 518 B

After

Width:  |  Height:  |  Size: 518 B

View File

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 585 B

View File

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 257 B

View File

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 287 B

View File

Before

Width:  |  Height:  |  Size: 294 B

After

Width:  |  Height:  |  Size: 294 B

View File

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 376 B

View File

Before

Width:  |  Height:  |  Size: 870 B

After

Width:  |  Height:  |  Size: 870 B

View File

Before

Width:  |  Height:  |  Size: 458 B

After

Width:  |  Height:  |  Size: 458 B

View File

Before

Width:  |  Height:  |  Size: 480 B

After

Width:  |  Height:  |  Size: 480 B

View File

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 487 B

View File

Before

Width:  |  Height:  |  Size: 569 B

After

Width:  |  Height:  |  Size: 569 B

View File

Before

Width:  |  Height:  |  Size: 608 B

After

Width:  |  Height:  |  Size: 608 B

View File

Before

Width:  |  Height:  |  Size: 645 B

After

Width:  |  Height:  |  Size: 645 B

View File

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 637 B

View File

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 719 B

View File

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 391 B

View File

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 433 B

View File

Before

Width:  |  Height:  |  Size: 440 B

After

Width:  |  Height:  |  Size: 440 B

View File

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 507 B

View File

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 496 B

View File

Before

Width:  |  Height:  |  Size: 516 B

After

Width:  |  Height:  |  Size: 516 B

View File

Before

Width:  |  Height:  |  Size: 523 B

After

Width:  |  Height:  |  Size: 523 B

View File

Before

Width:  |  Height:  |  Size: 605 B

After

Width:  |  Height:  |  Size: 605 B

View File

Before

Width:  |  Height:  |  Size: 619 B

After

Width:  |  Height:  |  Size: 619 B

View File

Before

Width:  |  Height:  |  Size: 643 B

After

Width:  |  Height:  |  Size: 643 B

View File

Before

Width:  |  Height:  |  Size: 665 B

After

Width:  |  Height:  |  Size: 665 B

View File

Before

Width:  |  Height:  |  Size: 732 B

After

Width:  |  Height:  |  Size: 732 B

View File

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 252 B

View File

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 281 B

View File

Before

Width:  |  Height:  |  Size: 288 B

After

Width:  |  Height:  |  Size: 288 B

View File

Before

Width:  |  Height:  |  Size: 370 B

After

Width:  |  Height:  |  Size: 370 B

View File

Before

Width:  |  Height:  |  Size: 694 B

After

Width:  |  Height:  |  Size: 694 B

View File

Before

Width:  |  Height:  |  Size: 720 B

After

Width:  |  Height:  |  Size: 720 B

View File

Before

Width:  |  Height:  |  Size: 741 B

After

Width:  |  Height:  |  Size: 741 B

View File

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 809 B

View File

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 575 B

View File

Before

Width:  |  Height:  |  Size: 600 B

After

Width:  |  Height:  |  Size: 600 B

View File

Before

Width:  |  Height:  |  Size: 623 B

After

Width:  |  Height:  |  Size: 623 B

View File

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 689 B

View File

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 367 B

View File

Before

Width:  |  Height:  |  Size: 690 B

After

Width:  |  Height:  |  Size: 690 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 493 B

After

Width:  |  Height:  |  Size: 493 B

View File

Before

Width:  |  Height:  |  Size: 849 B

After

Width:  |  Height:  |  Size: 849 B

View File

Before

Width:  |  Height:  |  Size: 626 B

After

Width:  |  Height:  |  Size: 626 B

View File

Before

Width:  |  Height:  |  Size: 711 B

After

Width:  |  Height:  |  Size: 711 B

View File

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 487 B

View File

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 271 B

View File

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 315 B

View File

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 318 B

View File

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 316 B

View File

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 318 B

View File

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 287 B

View File

Before

Width:  |  Height:  |  Size: 864 B

After

Width:  |  Height:  |  Size: 864 B

View File

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 326 B

View File

Before

Width:  |  Height:  |  Size: 240 B

After

Width:  |  Height:  |  Size: 240 B

View File

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 438 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 387 B

View File

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 359 B

View File

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 401 B

View File

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 350 B

View File

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 349 B

View File

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 350 B

View File

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 349 B

View File

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

Some files were not shown because too many files have changed in this diff Show More