version 20230116
0
doc/docs/about.md
Normal file
76
doc/docs/implementation.md
Normal 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".
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
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
@ -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
|
BIN
doc/docs/raster-dl_bdd_diagram.png
Normal file
After Width: | Height: | Size: 30 KiB |
36
doc/docs/technical.md
Normal 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
@ -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
BIN
doc/~$ster-dl.docx
Normal file
@ -7,6 +7,8 @@ from shapely.geometry import Polygon
|
||||
import matplotlib.pyplot as plt
|
||||
import folium
|
||||
|
||||
gpkg = "../data/raster-dl.gpkg"
|
||||
|
||||
@eel.expose
|
||||
def get_extent_types():
|
||||
"""Return the list of extends of level layer."""
|
||||
@ -36,7 +38,7 @@ def get_extent_types():
|
||||
@eel.expose
|
||||
def get_extents(level='communes'):
|
||||
"""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')
|
||||
|
||||
|
||||
@ -47,7 +49,7 @@ def get_products(code=None, level=None, buffer=0, bbox=False):
|
||||
if not code or not level:
|
||||
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 = 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)
|
||||
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['code'] = products_seleted['code_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:
|
||||
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 = 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)
|
||||
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_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')
|
||||
|
||||
|
||||
|
||||
def get_bbox(layer, buffer=0):
|
||||
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)])
|
0
ui/.gitignore → eel/ui/.gitignore
vendored
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 479 B |
Before Width: | Height: | Size: 511 B After Width: | Height: | Size: 511 B |
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 518 B |
Before Width: | Height: | Size: 585 B After Width: | Height: | Size: 585 B |
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
Before Width: | Height: | Size: 294 B After Width: | Height: | Size: 294 B |
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 870 B After Width: | Height: | Size: 870 B |
Before Width: | Height: | Size: 458 B After Width: | Height: | Size: 458 B |
Before Width: | Height: | Size: 480 B After Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 487 B |
Before Width: | Height: | Size: 569 B After Width: | Height: | Size: 569 B |
Before Width: | Height: | Size: 608 B After Width: | Height: | Size: 608 B |
Before Width: | Height: | Size: 645 B After Width: | Height: | Size: 645 B |
Before Width: | Height: | Size: 637 B After Width: | Height: | Size: 637 B |
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 719 B |
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 391 B |
Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 433 B |
Before Width: | Height: | Size: 440 B After Width: | Height: | Size: 440 B |
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 507 B |
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 496 B |
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 523 B After Width: | Height: | Size: 523 B |
Before Width: | Height: | Size: 605 B After Width: | Height: | Size: 605 B |
Before Width: | Height: | Size: 619 B After Width: | Height: | Size: 619 B |
Before Width: | Height: | Size: 643 B After Width: | Height: | Size: 643 B |
Before Width: | Height: | Size: 665 B After Width: | Height: | Size: 665 B |
Before Width: | Height: | Size: 732 B After Width: | Height: | Size: 732 B |
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 281 B After Width: | Height: | Size: 281 B |
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 288 B |
Before Width: | Height: | Size: 370 B After Width: | Height: | Size: 370 B |
Before Width: | Height: | Size: 694 B After Width: | Height: | Size: 694 B |
Before Width: | Height: | Size: 720 B After Width: | Height: | Size: 720 B |
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 741 B |
Before Width: | Height: | Size: 809 B After Width: | Height: | Size: 809 B |
Before Width: | Height: | Size: 575 B After Width: | Height: | Size: 575 B |
Before Width: | Height: | Size: 600 B After Width: | Height: | Size: 600 B |
Before Width: | Height: | Size: 623 B After Width: | Height: | Size: 623 B |
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 689 B |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 690 B After Width: | Height: | Size: 690 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 493 B After Width: | Height: | Size: 493 B |
Before Width: | Height: | Size: 849 B After Width: | Height: | Size: 849 B |
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 626 B |
Before Width: | Height: | Size: 711 B After Width: | Height: | Size: 711 B |
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 487 B |
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 315 B After Width: | Height: | Size: 315 B |
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 316 B |
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
Before Width: | Height: | Size: 864 B After Width: | Height: | Size: 864 B |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 240 B |
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 438 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 387 B After Width: | Height: | Size: 387 B |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 282 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 359 B |
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 401 B |
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B |
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 349 B |
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B |
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 349 B |
Before Width: | Height: | Size: 375 B After Width: | Height: | Size: 375 B |