ar_redadeg/scripts_v2/phase_3_prepare.py
2021-11-13 15:53:08 +01:00

327 lines
9.1 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Libraries
#
import os
import sys
import datetime
import time
import configparser
import psycopg2
#from logguer import log_verif
# ==============================================================================
# répertoire courant
script_dir = os.path.dirname(os.path.abspath(__file__))
# jour courant
date = datetime.datetime.now()
# lecture du fichier de configuration qui contient les infos de connection
config = configparser.ConfigParser()
config.read( script_dir + '/config.ini')
#fichier_log = str(date.year)+str(date.month)+str(date.day)+"_"+str(date.hour)+str(date.minute)
fichier_log = str(date.year)+str(date.month)+str(date.day)
# ==============================================================================
def initConnRedadegDB():
# connexion à la base postgresql
try:
global db_redadeg_pg_conn
db_redadeg_pg_conn = psycopg2.connect(db_redadeg_conn_str)
db_redadeg_pg_conn.set_session(autocommit=True)
print(" Connexion à la base "+db_redadeg_db+" sur "+db_redadeg_host+" réussie ")
except Exception as err:
print(" Connexion à la base "+db_redadeg_db+" sur "+db_redadeg_host+ " impossible ")
try:
err.pgcode
print(" PostgreSQL error code : " + err.pgcode)
sys.exit()
except:
print(" " + str(err),0)
sys.exit()
# ==============================================================================
def closeConnRedadegDB():
try:
db_redadeg_pg_conn.close()
print(" Fermeture de la connexion à la base "+db_redadeg_db+" sur "+db_redadeg_host)
except:
pass
#
# Functions
#
#
# Start processing
#
startTime = time.perf_counter()
# on récupère les arguments passés
list_of_args = sys.argv
millesime=""
secteur=""
typemaj=""
# et on fait des tests
try:
if len(list_of_args[1]) != 4:
print("Pas de millésime en argument")
sys.exit()
else:
millesime = list_of_args[1]
# millesime ok : on passe au secteur
if len(list_of_args[2]) != 3:
print("Pas d'id secteur en argument")
sys.exit()
else:
secteur = list_of_args[2]
# ok : tout est bon on peut commencer
# sortie des tests
except SystemExit:
print("Erreur dans les arguments --> stop")
sys.exit()
except:
print("oups : vérifiez vos arguments passés au script !")
print("stop")
sys.exit()
print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
print("")
print(" Préparation des données phase 3 du secteur "+str(secteur)+" pour le millésime "+str(millesime))
print("")
print(" Lecture du fichier de configuration ")
print("")
# BD Ar Redadeg
global db_redadeg_host
global db_redadeg_db
db_redadeg_host = config.get('redadeg_database', 'host')
db_redadeg_port = config.get('redadeg_database', 'port')
db_redadeg_db = config.get('redadeg_database', 'db')+"_"+str(millesime)
db_redadeg_user = config.get('redadeg_database', 'user')
db_redadeg_passwd = config.get('redadeg_database', 'passwd')
# chaîne de connection
global db_redadeg_conn_str
db_redadeg_conn_str = "host="+db_redadeg_host+" port="+db_redadeg_port+" dbname="+db_redadeg_db+" user="+db_redadeg_user+" password="+db_redadeg_passwd
initConnRedadegDB()
# le cursor
db_redadeg_cursor = db_redadeg_pg_conn.cursor()
print("")
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
try:
# longueur de découpage des tronçons de la phase 2
longueur_densification = config.get('redadeg', 'longueur_densification')
# ------------------------------------------------------
print(" Suppression des données du secteur "+secteur)
sql_delete = "DELETE FROM phase_3_troncons_pgr WHERE secteur_id = "+secteur +" ;"
db_redadeg_cursor.execute(sql_delete)
print(" fait")
print("")
# ------------------------------------------------------
print(" Chargement de tronçons découpés tous les "+longueur_densification+" m depuis la couche des tronçons phase 2")
# on charge, pour le secteur concerné des tronçons courts découpés tous les x mètres
# (densification avec ST_LineSubstring )
sql_insert = """
INSERT INTO phase_3_troncons_pgr (secteur_id, osm_id, highway, type, oneway, ref, name_fr, name_br, the_geom)
SELECT
secteur_id, osm_id, highway, type, oneway, ref, name_fr, name_br,
ST_LineSubstring(the_geom, """+longueur_densification+"""*n/length,
CASE
WHEN """+longueur_densification+"""*(n+1) < length THEN """+longueur_densification+"""*(n+1)/length
ELSE 1
END) As the_geom
FROM
(
SELECT
secteur_id, osm_id, highway, type, oneway, ref, name_fr, name_br,
ST_Length(the_geom) AS length,
the_geom
FROM phase_2_trace_troncons
WHERE secteur_id = """+secteur+"""
) AS t
CROSS JOIN generate_series(0,10000) AS n
WHERE n*"""+longueur_densification+"""/length < 1;"""
db_redadeg_cursor.execute(sql_insert)
print(" fait")
print("")
print(" Calcul des coûts...")
# calcul des attributs de support du calcul pour PGR
sql_update_costs = """
UPDATE phase_3_troncons_pgr
SET
cost =
CASE
WHEN trunc(st_length(the_geom)::numeric,2) = """ + str( float(longueur_densification) - 0.01 ) + """ THEN """ + longueur_densification + """
ELSE trunc(st_length(the_geom)::numeric,2)
END,
reverse_cost =
CASE
WHEN trunc(st_length(the_geom)::numeric,2) = """ + str( float(longueur_densification) - 0.01 ) + """ THEN """ + longueur_densification + """
ELSE trunc(st_length(the_geom)::numeric,2)
END
WHERE secteur_id = """ + secteur + """ ;"""
db_redadeg_cursor.execute(sql_update_costs)
print(" fait")
print("")
# ------------------------------------------------------
print(" Création / maj de la topologie pgRouting pour les tronçons nouvellement créés")
sql_nb_edges = f"SELECT count(*) FROM phase_3_troncons_pgr WHERE secteur_id = {secteur} ;"
db_redadeg_cursor.execute(sql_nb_edges)
nb_edges = db_redadeg_cursor.fetchone()[0]
# estimation du temps de traitement avec 400 edges / s
temps_sec = round(nb_edges/400)
minutes, seconds = divmod(temps_sec, 60)
print(f" temps de traitement évalué à {minutes} min et {seconds} sec")
now = datetime.datetime.now()
fin_sec = now.second + seconds
fin_min = now.minute + minutes + 1
fin_heure = now.hour
print(f" donc fin estimée à {fin_heure}h{fin_min} maximum")
sql_create_pgr_topology = f"SELECT pgr_createTopology('phase_3_troncons_pgr', 0.001, rows_where:='secteur_id={secteur}', clean:=false);"
db_redadeg_cursor.execute(sql_create_pgr_topology)
print(" fait")
print("")
# optimisation
print(" vacuum")
db_redadeg_cursor.execute("VACUUM FULL phase_3_troncons_pgr ;")
print(" fait")
print("")
# ------------------------------------------------------
print(" Récupération id des nœuds de début et fin du secteur, et la longueur")
# récupération id node début et fin de secteur
secteurs_in_clause = secteur+","+str(int(secteur)+100)
sql_get_nodes = """
SELECT v.id, s.the_geom
FROM phase_2_pk_secteur s, phase_3_troncons_pgr_vertices_pgr v
WHERE s.secteur_id IN ("""+secteurs_in_clause+""") AND ST_INTERSECTS(s.the_geom, v.the_geom)
ORDER BY s.secteur_id;"""
db_redadeg_cursor.execute(sql_get_nodes)
# fetchone() fait passer d'un enregistrement à un autre
# donc : nœud de début du secteur
node_start = db_redadeg_cursor.fetchone()
node_start_id = node_start[0]
node_start_geom = node_start[1]
# nœud de fin du secteur
node_end = db_redadeg_cursor.fetchone()
node_end_id = node_end[0]
node_end_geom = node_end[1]
# la longueur
sql_longueur_secteur = """
SELECT sum(COST) AS longueur
FROM phase_3_troncons_pgr
WHERE secteur_id = """ + secteur + """
GROUP BY secteur_id ;"""
db_redadeg_cursor.execute(sql_longueur_secteur)
longueur_secteur = db_redadeg_cursor.fetchone()[0]
longueur_km_secteur = longueur_secteur / 1000
# on maj les infos dans la table secteurs
sql_update_nodes_infos = "UPDATE secteur SET "
sql_update_nodes_infos += "node_start = " + str(node_start_id) + ", node_stop = " + str(node_end_id) + ", "
sql_update_nodes_infos += "longueur = " + str(longueur_secteur) + ", longueur_km = " + str(longueur_km_secteur) + " "
sql_update_nodes_infos += "WHERE id = " + secteur + " ;"
db_redadeg_cursor.execute(sql_update_nodes_infos)
print(" fait : "+str(node_start_id)+" -> "+str(node_end_id))
print("")
print("")
except Exception as err:
print(" ERREUR : " + str(err))
closeConnRedadegDB()
sys.exit()
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
db_redadeg_cursor.close()
closeConnRedadegDB()
# pour connaître le temps d'exécution
print("")
print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
print("F I N")
print("")
stopTime = time.perf_counter()
# version simple en secondes
#print(f"Exécuté en {stopTime - startTime:0.4f} secondes")
# version en h min s
hours, rem = divmod(stopTime - startTime, 3600)
minutes, seconds = divmod(rem, 60)
print("Exécuté en {:0>2}:{:0>2}:{:05.2f}".format(int(hours),int(minutes),seconds))