Commit 8e07c77a authored by Commandre Benjamin's avatar Commandre Benjamin
Browse files

Merge branch 'develop' into 'master'

Develop

See merge request benjamin.commandre/sentinel-3a!3
1 merge request!3Develop
Showing with 325 additions and 471 deletions
+325 -471
This diff is collapsed.
#!/bin/env python3
# -*- coding: utf-8 -*-
import sys
import argparse
import logging
from logging.handlers import RotatingFileHandler
......@@ -9,6 +10,10 @@ from contextlib import contextmanager
import inspect
from osgeo import gdal
import app.Constantes as Constantes
import configparser
import ast
from datetime import datetime
import app.Satellites as Satellites
class Fusion(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
......@@ -77,25 +82,25 @@ class TimeoutException(Exception): pass
@contextmanager
def limitation_temporelle(secondes):
def signal_handler(signum, frame):
raise TimeoutException
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(secondes)
def signal_handler(signum, frame):
raise TimeoutException
try:
yield
finally:
signal.alarm(0)
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(secondes)
try:
yield
finally:
signal.alarm(0)
# Utilisation :
#
# try:
# with limitation_temporelle(temps_en_seconde):
# appel_fonction()
# with limitation_temporelle(temps_en_seconde):
# appel_fonction()
# except TimeoutException:
# pass
# pass
def clip(image, cut, form="Mem", dst="", type_sortie=gdal.GDT_Float32, nodata="NaN"):
"""
......@@ -118,4 +123,126 @@ def clip(image, cut, form="Mem", dst="", type_sortie=gdal.GDT_Float32, nodata="N
option_clip = gdal.WarpOptions(cropToCutline=True,\
cutlineDSName=cut, outputType=type_sortie , format=form, dstNodata=nodata)
return gdal.Warp(dst, image, options=option_clip)
\ No newline at end of file
return gdal.Warp(dst, image, options=option_clip)
def str2bool(v):
return v.lower() in (["false"])
def checkDate(date):
d = date.split('-')
try:
if not date :
annee = datetime.now().year
if datetime.now().month < 10 :
mois = "0{}".format(datetime.now().month)
else :
mois = datetime.now().month
if datetime.now().day < 10 :
jour = "0{}".format(datetime.now().day)
else :
jour = datetime.now().day
elif len(d) == 1 :
annee = d[0]
mois = "01"
jour = "01"
elif len(d) == 2 :
annee = d[0]
mois = d[1]
jour = "01"
elif len(d) == 3 :
annee = d[0]
mois = d[1]
jour = d[2]
datetime(int(annee), int(mois), int(jour))
return "{annee}-{mois}-{jour}".format(annee=annee, mois=mois, jour=jour)
except ValueError:
print("Format invalide")
sys.exit(1)
except IndexError:
print("La date doit être au format 'AAAA-MM-JJ', 'AAAA-MM' ou 'AAAA'")
sys.exit(1)
def get_variable(self, config):
"""
Récupération des variables dans le fichier de configuration
"""
configfile = configparser.ConfigParser()
configfile.read(config)
self.requete = dict()
self.requete["lang"] = "fr"
self.requete["_pretty"] = "true"
self.requete["maxRecord"] = 500
# Capteur utilisé
self.capteur = configfile["satellite"]["capteur"]
self.bandes = configfile["satellite"]["bandes"]
self.requete["processingLevel"] = configfile["satellite"]["processingLevel"]
# Dossier contenant les résultats
self.dossier_sortie = configfile["sortie"]["chemin"]
try:
if str2bool(configfile["sortie"]["extraction"]):
self.extraction = False
else :
self.extraction = True
except :
self.extraction = True
self.groupe = configfile["sortie"]["groupe"]
# Date de début et de fin de la recherche
try:
# self.date_debut = configfile["donnees"]["date_debut"]
self.requete["startDate"] = checkDate(configfile["donnees"]["date_debut"])
except Exception as e:
raise "L'année de départ est requise."
self.requete["completionDate"] = checkDate(configfile["donnees"]["date_fin"])
self.seuil_nuage = float(configfile["donnees"]["seuil_nuage"])/100.0 if configfile["donnees"]["seuil_nuage"] else 0.0
# Emprise et zone de l'étude
self.emprise = configfile["donnees"]["chemin_emprise"]
if self.emprise :
self.zone_etude = configfile["donnees"]["chemin_zone_etude"]
if not self.zone_etude :
self.zone_etude = self.emprise
else :
try:
self.liste_tuiles = list(ast.literal_eval(configfile["donnees"]["liste_tuiles"]))
except Exception as e:
raise "Aucune emprise ni aucune tuile n'a été renseigné."
self.nombre_image = configfile["donnees"]["nombre_image"]
# Identifiant, mot de passe et proxy pour le téléchargement des images Théia
self.id = configfile["theia"]["identifiant"]
self.mdp = configfile["theia"]["mdp"]
self.proxy = configfile["theia"]["proxy"]
if self.bandes == "RGB" :
self.extent_img = Satellites.SATELLITE[self.capteur][self.requete["processingLevel"]][:-1]
else :
self.extent_img = Satellites.SATELLITE[self.capteur][self.requete["processingLevel"]]
if self.requete["processingLevel"] == "LEVEL2A" :
self.nuage = Satellites.SATELLITE[self.capteur]["NUAGE"]
else :
self.nuage = None
self.serveur = Satellites.SATELLITE[self.capteur]["serveur"]
self.resto = Satellites.SATELLITE[self.capteur]["resto"]
self.token_type = Satellites.SATELLITE[self.capteur]["token_type"]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import configparser
import datetime
import glob
from osgeo import gdal
import otbApplication as otb
from app import Archive
def str2bool(v):
return v.lower() in ("true")
class Processing(object):
def __init__(self):
pass
def i_download(self):
"""
Méthode pour télécharger les images sur le site Theia Land.
"""
if not self.annee_fin :
self.annee_fin = datetime.datetime.now().year
self.check_download = Archive.Archive(self.capteur, self.bandes, self.niveau, self.emprise, self.zone_etude,\
self.resultats, self.annee_debut, int(self.annee_fin), self.seuil_nuage)
self.check_download.listing()
self.check_download.download_auto(self.id, self.mdp, self.proxy, extraction=self.extraction, groupe=self.groupe)
self.liste_dossier = dict()
for annee in os.listdir(self.resultats):
with open("{}/{}/dates.txt".format(self.resultats, annee), "w") as fichier :
for image in sorted(glob.glob("{}/{}/Images/*".format(self.resultats, annee))) :
fichier.write("{}\n".format(os.path.basename(image)[:-4]))
self.liste_dossier[annee] = sorted([x for x in glob.glob("{}/{}/Images/*".format(self.resultats, annee)) if x.endswith(".tif")])
def otbPhenologie(self):
"""
Appel le module OTB : 'SigmoFitting' sur l'image composée de l'empilement des NDVI
"""
otb_Phenologie = otb.Registry.CreateApplication("SigmoFitting")
otb_Phenologie.SetParameterString("mode", "metrics")
for annee in self.liste_dossier :
otb_Phenologie.SetParameterString("in", "{}/{}/NDVI/stack_ndvi.tif".format(self.resultats, annee))
otb_Phenologie.SetParameterString("dates", "{}/{}/dates.txt".format(self.resultats, annee))
otb_Phenologie.SetParameterString("out", "{}/{}/metrics.tif".format(self.resultats, annee))
otb_Phenologie.ExecuteAndWriteOutput()
def calcul_ndvi(self):
"""
Méthode effectuant le calcul du NDVI via le module OTB : 'RadiometricIndices'
"""
options_vrt = gdal.ParseCommandLine('-resolution highest -separate')
otb_NDVI = otb.Registry.CreateApplication("RadiometricIndices")
otb_NDVI.SetParameterInt("channels.blue", 1)
otb_NDVI.SetParameterInt("channels.green", 2)
otb_NDVI.SetParameterInt("channels.red", 3)
otb_NDVI.SetParameterInt("channels.nir", 4)
otb_NDVI.SetParameterStringList("list", ["Vegetation:NDVI"])
sauvegarde = configparser.ConfigParser()
for annee in self.liste_dossier :
sauvegarde.read("{}/{}/sauvegarde.ini".format(self.resultats, annee))
dossier_NDVI = "{}/{}/NDVI".format(self.resultats, annee)
if not os.path.exists(dossier_NDVI) :
os.makedirs(dossier_NDVI)
for img in self.liste_dossier[annee] :
chemin_ndvi = "{}/ndvi_{}".format(dossier_NDVI, os.path.basename(img))
if not str2bool(sauvegarde[os.path.basename(img)[:-4]]["NDVI"]):
otb_NDVI.SetParameterString("in", img)
otb_NDVI.SetParameterString("out", chemin_ndvi)
otb_NDVI.ExecuteAndWriteOutput()
sauvegarde[os.path.basename(img)[:-4]]["NDVI"] = "True"
liste_ndvi = sorted([x for x in glob.glob("{}/*".format(dossier_NDVI)) if x.endswith(".tif") and "stack" not in x])
vrt = gdal.BuildVRT("", liste_ndvi, options=options_vrt)
gdal.Translate("{}/{}/NDVI/stack_ndvi.tif".format(self.resultats, annee), vrt)
with open("{}/{}/sauvegarde.ini".format(self.resultats, annee), 'w') as configfile:
sauvegarde.write(configfile)
def i_images_processing(self):
"""
Calul le ndvi, fusionnne en une seule image puis lance le module OTBPhenology
"""
self.calcul_ndvi()
self.otbPhenologie()
......@@ -6,27 +6,38 @@ chemin_emprise =
# Si vide, zone d'étude = emprise
chemin_zone_etude =
# Année à partir de laquelle les images ont été prises
annee_debut =
# Liste des tuiles Sentinel2 à télécharger
# Si une emprise est spécifiée, celle-ci est privilégié
# Ex : ["T30ABC", "T31ABC", "T30DEF"]
liste_tuiles =
# Année limite d'acquisition des images
# Si vide, l'année de fin correspond à l'année actuelle
annee_fin =
# Nombre d'images à télécharger par tuile
# Si vide, télécharge toutes les images disponibles
nombre_image =
# Date à partir de laquelle les images ont été prises
# La date doit être au format AAAA-MM-JJ, AAAA-MM ou AAAA
date_debut =
# Date limite d'acquisition des images
# La date doit être au format AAAA-MM-JJ, AAAA-MM ou AAAA
# Si vide, la date de fin correspond au jour actuel
date_fin =
# Pourcentage maximal d'ennuagement
seuil_nuage = 5.0
[sortie]
# chemin/dossier/resultats
chemin =
chemin =
# Manière de regrouper les images/archives
# Possibilités :- Date (Regroupe les images selon leurs date d'acquisition)
# - Tuile (Regroupe les images en fonction de la tuile sentinel2 auquelle elles correspondent )
groupe = Date
groupe = Tuile
# Vrai si extraction des images des archives, faux si téléchagement de celles-ci
extraction = True
extraction = False
[theia]
# Identifiant Theia-land
......@@ -47,7 +58,7 @@ capteur = SENTINEL2
# Niveau de traitement des images satellites
# Possibilités :- LEVEL2A (Acquisition standard)
# - LEVEL3A (Synthèse mensuelle)
processingLevel= LEVEL2A
processingLevel= LEVEL3A
# Bandes d'intêrets
# Possibilités :- RGB (Bandes Rouge, Verte, Bleue)
......
#!/bin/bash
# =========================================
# Script d'installation
# =========================================
function erreur {
echo "Usage : $0 [--libs --maj --compil --all]"
echo "--libs : Installation des bibliothèques python"
echo "--maj : Téléchargement des fichiers sources pour OTB"
echo "--compil : Compilation d'OTB"
echo "--all : Téléchargement des sources et des bibliothèques python puis compilation d'OTB"
exit
}
function confirme {
read -r -p "${1}Êtes-vous sûr de vouloir continuer ? [O/N] " response
if [[ $response == "o" || $response = "O" || $response == "y" || $response = "Y" ]]; then
echo -e "${ROUGE}\e[1mLauching generation in $prefix_dir\e[0m"
else
exit
fi
}
set -e
#Couleur 'Rouge' pour le terminal
ROUGE='\033[0;31m'
# Dossier courant du script
CMD="$(readlink -e "${BASH_SOURCE[0]}")"
SH_DIR="$(dirname "$CMD")"
prefix_dir=$SH_DIR
if [ ! -z $CXX ]; then
echo "Version du compilateur : $CXX"
else
CXX=`type -p g++`
fi
CXXVersion=`${CXX} -dumpversion`
version_compilateur="5.0.0"
if [ "$(printf '%s\n' "$version_compilateur" "$CXXVersion" | sort -V | head -n1)" = "$CXXVersion" ]; then
echo "Gcc version too old"
echo "Actual: ${CXXVersion}"
echo "Needed: ${version_compilateur}"
exit
fi
# Erreur si manque ou mauvais argument
if [[ "$#" != "1" ]]; then
erreur
fi
if [[ "$1" != "--libs" ]] && [[ "$1" != "--maj" ]] && [[ "$1" != "--compil" ]] && [[ "$1" != "--all" ]]; then
erreur
fi
if [[ "$1" == "--libs" ]]; then
echo "Installation des bibliothèques python3"
sudo apt-get update
sudo apt-get install aptitude -y
sudo aptitude install python3-pip -y
sudo pip3 install -r "dépendances.txt"
fi
echo $prefix_dir/OTB
if [[ "$1" != "--libs" ]]; then
echo "Installation de la bibliothèque OTB dans : ${prefix_dir}"
confirme
#----------------------------------------
# Récupération des sources
if [[ "$1" == "--maj" ]] || [[ "$1" == "--all" ]]; then
# Clonage du repertoire OTB
if [ -d "OTB" ]; then
echo "Le répertoire OTB existe déjà."
else
echo "Clonage OTB ..."
mkdir -p $prefix_dir/OTB
cd $prefix_dir/OTB
git clone https://gitlab.orfeo-toolbox.org/orfeotoolbox/otb.git
fi
fi
#----------------------------------------
# Compilation
if [[ "$1" != "--compil" ]] || [[ "$1" == "--all" ]] ; then
sudo aptitude install make cmake-curses-gui build-essential libtool automake git libbz2-dev python-dev libboost-dev libboost-filesystem-dev libboost-serialization-dev libboost-system-dev zlib1g-dev libcurl4-gnutls-dev swig libgdal-dev
echo "Compilation d'OTB ..."
cd $prefix_dir/
mkdir -p build
mkdir -p build
cd build
# Compilation d'OTB
cmake -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_CXX_FLAGS:STRING=-std=c++14 -DUSE_SYSTEM_BOOST=ON -DUSE_SYSTEM_CURL=ON -DUSE_SYSTEM_ZLIB=ON -DUSE_SYSTEM_GDAL=ON -DCMAKE_BUILD_TYPE=Release -DOTB_WRAP_PYTHON3:BOOL=ON -DGDAL_SB_EXTRA_OPTIONS:STRING="--with-python" -DCMAKE_INSTALL_PREFIX=$prefix_dir/OTB/install/ -DOTB_USE_QWT=OFF -DOTB_USE_GLEW=OFF -DOTB_USE_GLFW=OFF -DOTB_USE_GLUT=OFF -DOTB_USE_OPENGL=OFF -DOTB_USE_QT=OFF -DOTB_USE_QWT=OFF $prefix_dir/OTB/otb/SuperBuild/
make --jobs=12
# Compilation des modules
cd $prefix_dir/OTB/build/OTB/build
cmake -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_CXX_FLAGS:STRING=-std=c++14 -DModule_OTBPhenology:BOOL=ON -DModule_OTBTemporalGapFilling:BOOL=ON $prefix_dir/OTB/otb
make --jobs=12
make install
fi
echo "Installation terminée."
fi
......@@ -2,73 +2,21 @@
# -*- coding: utf-8 -*-
import sys, time
from osgeo import ogr
import configparser
from app.Processing import Processing
import app.Constantes as Constantes
import app.Outils as Outils
def str2bool(v):
return v.lower() in (["false"])
class Telechargement(Processing):
import argparse
def __init__(self, parent=None):
super(Processing, self).__init__()
Processing.__init__(self)
self.logger = Outils.Log("log", "Téléchargement")
self.get_variable()
def get_variable(self):
"""
Récupération des variables dans le fichier de configuration
"""
configfile = configparser.ConfigParser()
configfile.read("config.ini")
# Capteur utilisé
self.capteur = configfile["satellite"]["capteur"]
self.niveau = configfile["satellite"]["processingLevel"]
self.bandes = configfile["satellite"]["bandes"]
# Dossier contenant les résultats
self.resultats = configfile["sortie"]["chemin"]
try:
if str2bool(configfile["sortie"]["extraction"]):
self.extraction = False
else :
self.extraction = True
except :
self.extraction = True
self.groupe = configfile["sortie"]["groupe"]
# Date de début et de fin de la recherche
try:
self.annee_debut = int(configfile["donnees"]["annee_debut"])
except Exception as e:
raise "L'année de départ est requise."
from app.Archive import Archive
import app.Constantes as Constantes
self.annee_fin = configfile["donnees"]["annee_fin"]
self.seuil_nuage = float(configfile["donnees"]["seuil_nuage"])/100.0 if configfile["donnees"]["seuil_nuage"] else 0.0
from app.Outils import Log
# Emprise et zone de l'étude
self.emprise = configfile["donnees"]["chemin_emprise"]
self.zone_etude = configfile["donnees"]["chemin_zone_etude"]
class Telechargement(object):
if not self.zone_etude :
self.zone_etude = self.emprise
def __init__(self, config):
super(Telechargement, self).__init__()
# Identifiant, mot de passe et proxy pour le téléchargement des images Théia
self.id = configfile["theia"]["identifiant"]
self.mdp = configfile["theia"]["mdp"]
self.proxy = configfile["theia"]["proxy"]
self.logger = Log("log", "Téléchargement")
self.config = config
def run(self):
"""
......@@ -77,11 +25,9 @@ class Telechargement(Processing):
# Début du processus
debut = time.time()
# Recherche de nouvelles images non traitées et téléchargement de celles-ci le cas échéant
self.i_download()
# Traitement des images
self.i_images_processing()
prog = Archive(self.config)
prog.listing()
prog.download_auto()
# Fin du processus
fin = time.time()
......@@ -92,5 +38,9 @@ class Telechargement(Processing):
if __name__ == "__main__":
app = Telechargement()
parser = argparse.ArgumentParser()
parser.add_argument("-config", dest="config", help="Chemin du fichier de config", required=True)
args = parser.parse_args()
app = Telechargement(args.config)
sys.exit(app.run())
#!/bin/bash
# Dossier courant du script.
CMD="$(readlink -e "${BASH_SOURCE[0]}")"
SH_DIR="$(dirname "$CMD")"
prefix_dir=$SH_DIR
export PATH=$PATH:$prefix_dir/OTB/install/bin
export PYTHONPATH=$prefix_dir/OTB/install/lib/otb/python3
export ITK_AUTOLOAD_PATH=$prefix_dir/OTB/install/lib/otb/applications
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment