add filter cd_typo_sdage is null

This commit is contained in:
Colas Geier 2026-02-04 15:22:26 +01:00
parent ba5ef578d0
commit eec8bdea08

View File

@ -1,4 +1,6 @@
from csv import list_dialects #!/usr/bin/env python3
# -*- coding: UTF-8 -*-.
import geopandas as gpd import geopandas as gpd
from uuid import uuid4 from uuid import uuid4
import json,urllib.request import json,urllib.request
@ -10,14 +12,38 @@ dict_columns = {
'code_zh': 'code', 'code_zh': 'code',
'nom_zh': 'main_name', 'nom_zh': 'main_name',
'date_visite':'create_date', 'date_visite':'create_date',
'remark_activity': 'global_remark_activity'
} }
dict_type_milieux = {
'FU':'Fourré humide',
'BFH':'Boisement feuillu humide',
'BCH':'Boisement de conifères humide',
'AL':'Végétation herbacée pionnière des alluvions',
'GH':'Communauté de grands hélophytes',
'RB':'Communauté de petits hélophytes',
'MC':'Magnocariçaie',
'BM':'Bas-marais et marais de transition',
'MG':'Mégaphorbiaie',
'AQ':'Végétation aquatique',
'FO':'Végétation fontinale (sources, mouillères)',
'EC':"Végétation amphibie des bordure d'eaux courantes",
'PH':'Prairie humide (et pelouse humide)',
}
def normalize_connexion(con): def normalize_connexion(con):
if gpd.pd.__version__>'2.1.2': if gpd.pd.__version__>'2.1.2':
return con.raw_connection() return con.raw_connection()
else: else:
return con return con
def get_cor_impact_types(con):
res = gpd.pd.read_sql_table('cor_impact_types',con,'pr_zh')
return dict(zip(res.id_impact,res.id_cor_impact_types))
def get_nomenclature_id(con,cd,typ): def get_nomenclature_id(con,cd,typ):
""" """
Get the id_nomenclature for a given cd and typ. Get the id_nomenclature for a given cd and typ.
@ -45,7 +71,7 @@ def get_nomenclature_id(con,cd,typ):
return res.one()[0] if res else None return res.one()[0] if res else None
def _cor_zh_area(tzh_code,typ,cover=False): def _cor_zh_area(tzh_code,con,typ,cover=False):
""" """
@tzh : pd.Serie. Série de valeurs @tzh : pd.Serie. Série de valeurs
correspondants à la colonne pr_zh.t_zh."code". correspondants à la colonne pr_zh.t_zh."code".
@ -58,7 +84,7 @@ def _cor_zh_area(tzh_code,typ,cover=False):
sqltzh = """ sqltzh = """
SELECT zh.id_zh, zh.geom FROM pr_zh.t_zh zh WHERE zh."code" in {tzh_code} SELECT zh.id_zh, zh.geom FROM pr_zh.t_zh zh WHERE zh."code" in {tzh_code}
""".format(tzh_code=tuple(tzh_code)) """.format(tzh_code=tuple(tzh_code))
tzh = gpd.read_postgis(sqltzh,con_gn,crs=4326) tzh = gpd.read_postgis(sqltzh,con,crs=4326)
if tzh.crs.srs.lower()=='epsg:4326': if tzh.crs.srs.lower()=='epsg:4326':
tzh.to_crs(2154,inplace=True) tzh.to_crs(2154,inplace=True)
@ -68,7 +94,7 @@ def _cor_zh_area(tzh_code,typ,cover=False):
JOIN ref_geo.bib_areas_types bib USING (id_type) JOIN ref_geo.bib_areas_types bib USING (id_type)
WHERE bib.type_code='{typ}' and l."enable" WHERE bib.type_code='{typ}' and l."enable"
""".format(typ=typ) """.format(typ=typ)
larea = gpd.read_postgis(sqllarea,con_gn,crs=2154) larea = gpd.read_postgis(sqllarea,con,crs=2154)
df = _calc_recouvrmt(larea,tzh).rename(columns={'perc_rcvmt':'cover'}) df = _calc_recouvrmt(larea,tzh).rename(columns={'perc_rcvmt':'cover'})
@ -80,7 +106,7 @@ def _cor_zh_area(tzh_code,typ,cover=False):
# return df # return df
if not df.empty: if not df.empty:
df.to_sql( df.to_sql(
name=table, con=con_gn, schema='pr_zh', name=table, con=con, schema='pr_zh',
if_exists='append', index=False if_exists='append', index=False
) )
print('INSERT %i correspondances'%df.shape[0]) print('INSERT %i correspondances'%df.shape[0])
@ -133,32 +159,7 @@ def _calc_recouvrmt(df1,df2,how='inner'):
return tmp[[iddf1,iddf2,'perc_rcvmt']] return tmp[[iddf1,iddf2,'perc_rcvmt']]
def _cor_zh_hydro(tzh_code): def _cor_zh_(tzh_code,con,typ):
"""
@tzh : pd.Serie. Série de valeurs
correspondants à la colonne pr_zh.t_zh."code".
"""
table = 'cor_zh_hydro'
sql = '''
SELECT h.id_hydro,zh.id_zh
FROM pr_zh.t_hydro_area h, pr_zh.t_zh zh
WHERE zh."code" in {tzh_code}
AND ST_INTERSECTS( ST_SetSRID(h.geom,4326),ST_MakeValid(ST_SetSRID(zh.geom,4326)))
AND (h.id_hydro,zh.id_zh) NOT IN (SELECT id_hydro,id_zh FROM pr_zh.cor_zh_hydro)
'''.format(tzh_code=tuple(tzh_code))
df = gpd.pd.read_sql_query(sql,con_gn)
if not df.empty:
df.to_sql(
name=table, con=con_gn, schema='pr_zh',
if_exists='append', index=False
)
print('INSERT %i correspondances'%df.shape[0])
else:
print('AUCUNE nouvelles correspondances identifiées')
def _cor_zh_(tzh_code,typ):
""" """
@tzh : pd.Serie. Série de valeurs @tzh : pd.Serie. Série de valeurs
correspondants à la colonne pr_zh.t_zh."code". correspondants à la colonne pr_zh.t_zh."code".
@ -179,11 +180,11 @@ def _cor_zh_(tzh_code,typ):
id_typ = id_typ, id_typ = id_typ,
tab_typ = tab_typ, tab_typ = tab_typ,
tab_to = table) tab_to = table)
df = gpd.pd.read_sql_query(sql,con_gn) df = gpd.pd.read_sql_query(sql,con)
if not df.empty: if not df.empty:
df.to_sql( df.to_sql(
name=table, con=con_gn, schema='pr_zh', name=table, con=con, schema='pr_zh',
if_exists='append', index=False if_exists='append', index=False
) )
print('INSERT %i correspondances'%df.shape[0]) print('INSERT %i correspondances'%df.shape[0])
@ -236,13 +237,12 @@ def to_tzh(df,con,lst_area):
res_df = gpd.pd.DataFrame(res) res_df = gpd.pd.DataFrame(res)
for area in lst_area: for area in lst_area:
cov = True if area == 'COM' else False cov = True if area == 'COM' else False
_cor_zh_area(tzh_code=res_df.code,typ=area,cover=cov) _cor_zh_area(tzh_code=res_df.code,con=con,typ=area,cover=cov)
print('INSERT cor_zh_area %s OK !'%area) print('INSERT cor_zh_area %s OK !'%area)
# _cor_zh_hydro(tzh_code=res_df.code) _cor_zh_(tzh_code=res_df.code,con=con,typ='hydro')
_cor_zh_(tzh_code=res_df.code,typ='hydro')
print('INSERT cor_zh_hydro OK !') print('INSERT cor_zh_hydro OK !')
_cor_zh_(tzh_code=res_df.code,typ='rb') _cor_zh_(tzh_code=res_df.code,con=con,typ='rb')
print('INSERT cor_zh_rb OK !') print('INSERT cor_zh_rb OK !')
print("INSERT data TO t_zh OK !") print("INSERT data TO t_zh OK !")
@ -313,6 +313,7 @@ def to_cor_zh_cb(id_zh,df,con):
------- -------
None None
""" """
cor_zh_cb = (df cor_zh_cb = (df
.merge(id_zh,how='left',on='code') .merge(id_zh,how='left',on='code')
.set_index('id_zh') .set_index('id_zh')
@ -337,11 +338,13 @@ def to_cor_zh_cb(id_zh,df,con):
finally: finally:
print("INSERT habitats to cor_zh_cb OK !") print("INSERT habitats to cor_zh_cb OK !")
def check_cd_nomenclature_impact(cd): def check_cd_nomenclature_impact(cd):
dizaine = range(0,100,10) dizaine = range(0,100,10)
_cd = [x+'.0' if float(x) not in dizaine and not x.endswith('.0') else x for x in cd] _cd = [x+'.0' if float(x) not in dizaine and not x.endswith('.0') else x for x in cd]
return _cd return _cd
def to_t_activity(id_zh,actv,con): def to_t_activity(id_zh,actv,con):
_activ = (actv _activ = (actv
.merge(id_zh,how='left',on='code') .merge(id_zh,how='left',on='code')
@ -370,7 +373,10 @@ def to_t_activity(id_zh,actv,con):
.reset_index() .reset_index()
) )
impact_list['_cd_impact'] = check_cd_nomenclature_impact(impact_list.cd_impact) impact_list['_cd_impact'] = check_cd_nomenclature_impact(impact_list.cd_impact)
impact_list['id_impact'] = [get_nomenclature_id(con,x,'IMPACTS') for x in impact_list._cd_impact] impact_list['id_cor_impact_types'] = [get_nomenclature_id(con,x,'IMPACTS') for x in impact_list._cd_impact]
cor_imp_typ = get_cor_impact_types(con)
impact_list.replace({'id_cor_impact_types':cor_imp_typ}, inplace=True)
t_activ.drop(['cd_activite_humaine','localisation','impact'],axis=1,inplace=True) t_activ.drop(['cd_activite_humaine','localisation','impact'],axis=1,inplace=True)
impact_list.drop(['cd_impact','_cd_impact'],axis=1,inplace=True) impact_list.drop(['cd_impact','_cd_impact'],axis=1,inplace=True)
@ -395,7 +401,7 @@ def to_t_activity(id_zh,actv,con):
name='cor_impact_list', name='cor_impact_list',
con=con, con=con,
schema='pr_zh', schema='pr_zh',
index=True, index=False,
if_exists='append', if_exists='append',
method='multi' method='multi'
) )
@ -569,7 +575,9 @@ def filter_zh(code,con):
res = gpd.pd.read_sql(sql,con) res = gpd.pd.read_sql(sql,con)
return res return res
def insert_zh_fromapi(url,con,dep_filter,orga,lst_area=['DEP','COM'],prefix_hab_rq=''): def insert_zh_fromapi(
url,con,dep_filter,orga,lst_area=['DEP','COM'],
prefix_hab_rq='',code_rename={}):
""" """
Insert data from API into geonature database Insert data from API into geonature database
@ -583,21 +591,59 @@ def insert_zh_fromapi(url,con,dep_filter,orga,lst_area=['DEP','COM'],prefix_hab_
filter code_zh by this department code filter code_zh by this department code
prefix_hab_rq : str prefix_hab_rq : str
prefix to add to remark_pres field for habitats not in geonature database prefix to add to remark_pres field for habitats not in geonature database
code_rename : dict
Dictionnary of zh code
Returns Returns
------- -------
None None
""" """
api = gpd.read_file(url)
api = gpd.read_file(url, engine='fiona')
if api.empty: if api.empty:
print("Aucun zone humide trouvée") print("Aucune zone humide trouvée")
print("Arrêt du script !")
return None return None
df = (api[api.action=='Créer'] api.rename(columns=dict_columns, inplace=True)
.rename(columns=dict_columns) if code_rename :
.rename_geometry('geom') api.replace({'code':code_rename},inplace=True)
zh_filter = filter_zh(
tuple(api.code.dropna()),
con
)
nzh_tobdd = api[
(api.action=='Créer')&
(~api.code.isin(zh_filter.code.tolist()))&
(~api.cd_typo_sdage.isna())
].shape[0]
print("L'api contient %s zones .."%api.shape[0])
print("%s zones sont taguée `Problème` .."%api[api.action=='Problème'].shape[0])
print("%s zones dont la typologie SDAGE est inconnue et sont écartées"%api[api.cd_typo_sdage.isna()].shape[0])
print("%s zones taguée `Créer` existent déjà .."%zh_filter.shape[0])
print("%s zones taguée `Créer` sont à intégrer .."%nzh_tobdd)
if nzh_tobdd == 0 :
print("\nAucune nouvelles zones humides sont à intégrée ..")
print("Arrêt du script !")
return None
Q = input('Souhaitez-vous continuer ? (Y/n) : ')
if Q.lower() != 'y':
print('Arrêt du code ..')
return None
df = (api[
(api.action=='Créer')&
(~api.code.isin(zh_filter.code.tolist()))&
(~api.cd_typo_sdage.isna())
].rename_geometry('geom')
# .merge(load_missing_propertie(url,'cd_nomenclature_delimitation',dep_filter), on='pk') # .merge(load_missing_propertie(url,'cd_nomenclature_delimitation',dep_filter), on='pk')
) )
df.observateur = normalize_observers(df.observateur) df.observateur = normalize_observers(df.observateur)
users, id_org = insert_users_missing(df.observateur,orga,con) users, id_org = insert_users_missing(df.observateur,orga,con)
df['id_org'] = id_org df['id_org'] = id_org
@ -606,12 +652,12 @@ def insert_zh_fromapi(url,con,dep_filter,orga,lst_area=['DEP','COM'],prefix_hab_
.rename(columns={'ids_observers':'id_role'}) .rename(columns={'ids_observers':'id_role'})
) )
df['zh_uuid'] = [uuid4() for _ in range(len(df))] df['zh_uuid'] = [uuid4() for _ in range(len(df))]
df['id_lim_list'] = [uuid4() for _ in range(len(df))] df['id_lim_list'] = [uuid4() for _ in range(len(df))]
df['id_sdage'] = [get_nomenclature_id(con,x,'SDAGE') for x in df.cd_typo_sdage] df['id_sdage'] = [get_nomenclature_id(con,x,'SDAGE') for x in df.cd_typo_sdage]
df['create_author'] = df.id_role.copy() df['create_author'] = df.id_role.copy()
df['update_author'] = df.id_role.copy() df['update_author'] = df.id_role.copy()
df['area'] = df.to_crs(2154).area/10000
cd_hab = (df cd_hab = (df
.set_index('code') .set_index('code')
@ -622,16 +668,33 @@ def insert_zh_fromapi(url,con,dep_filter,orga,lst_area=['DEP','COM'],prefix_hab_
hab_zh,hab_notzh = filter_habitat(cd_hab,con) hab_zh,hab_notzh = filter_habitat(cd_hab,con)
_df = (df _df = (df
.drop('habitat_corine_biotope',axis=1) .drop('habitat_corine_biotope',axis=1)
.merge(hab_zh,how='left',right_index=True,left_on='code')) .merge(hab_zh,how='left',right_index=True,left_on='code')
_df = _df.merge( .sort_values('code'))
prefix_hab_rq + hab_notzh.rename('remark_pres'),
how='left',right_index=True,left_on='code' # Si pas de champs remark_pres dans le tableau
) if 'remark_pres' not in _df.columns:
_df = _df.merge(
prefix_hab_rq + hab_notzh.rename('remark_pres'),
how='left',right_index=True,left_on='code'
)
else :
_df.remark_pres = (_df.remark_pres
.str.split('_',expand=True)[0]
.replace(dict_type_milieux)
)
_df.set_index('code',inplace=True)
_df.loc[_df.index.isin(hab_notzh.index),'remark_pres'] = (
_df[_df.index.isin(hab_notzh.index.tolist())]
.remark_pres
+ '\n' + prefix_hab_rq + hab_notzh
)
_df.reset_index(drop=False,inplace=True)
c = _df[_df.action=="Créer"].copy() c = _df[_df.action=="Créer"].copy()
u = _df[_df.action=="Modifier"].copy() u = _df[_df.action=="Modifier"].copy()
if not c.empty: if not c.empty:
# retrun c
id_zh = to_tzh(c,con,lst_area) id_zh = to_tzh(c,con,lst_area)
to_cor_zh_cb(id_zh,c,con) to_cor_zh_cb(id_zh,c,con)
to_cor_lim_list(c[['id_lim_list','cd_nomenclature_delimitation']],con) to_cor_lim_list(c[['id_lim_list','cd_nomenclature_delimitation']],con)
@ -677,24 +740,35 @@ if __name__ == "__main__":
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.engine import URL from sqlalchemy.engine import URL
# Parametres bdd # Parametres bdd
user = 'geonatadmin' user = 'xxxxxxx'
pwd = "prep!!Ge0naT38*aDm1n" pwd = "xxxxxxx"
adr = 'localhost' adr = 'xxxxxxx'
base = 'geonature2db' base = 'xxxxxxx'
url = URL.create("postgresql+psycopg2", username=user, password=pwd, host=adr, database=base) url = URL.create("postgresql+psycopg2", username=user, password=pwd, host=adr, database=base)
con_gn = create_engine(url) con_gn = create_engine(url)
from pycen import con_gn
# from pycen import con_gn
# Numéro de département permettant d'identifier les zones humides concernées par le territoire # Numéro de département permettant d'identifier les zones humides concernées par le territoire
# ['38', '05'], default : 38 # ['38', '05'], default : 38
dep_filter = '38' dep_filter = '05'
# Préfixe ajouté dans le champs remark_pres lorsque des habitats décrits ne sont pas des habitats dit "humides" # Préfixe ajouté dans le champs remark_pres lorsque des habitats décrits ne sont pas des habitats dit "humides" dans la listes des habitats humides définis en bdd (table bib_cb)
prefix_hab_rmk = 'Autre(s) habitat(s) décrit(s) :\n' prefix_hab_rmk = 'Autre(s) habitat(s) décrit(s) :\n'
# [Nom de l'organisme, Abbreviation] # [Nom de l'organisme, Abbreviation]
organisme = ['Parc national des Écrins','PNE'] organisme = ['Parc national des Écrins','PNE']
# Liste des type_area à intersecter pour remplir la table cor_zh_area # Liste des type_area à intersecter pour remplir la table cor_zh_area
listAreaCover = ['DEP','COM','APB','ZPS','SIC','ZNIEFF1','ZNIEFF2','ENS_ZI'] listAreaCover = ['DEP','COM','APB','ZPS','SIC','ZNIEFF1','ZNIEFF2']
# Code zh de l'api à renomer si souhaité. Défaut = {}
code_rename = {}
api = 'https://geonature.ecrins-parcnational.fr/api/exports/api/21?departement=%s'%dep_filter api = 'https://geonature.ecrins-parcnational.fr/api/exports/api/21?departement=%s'%dep_filter
insert_zh_fromapi(api,con_gn,dep_filter,organisme,lst_area=listAreaCover,prefix_hab_rq=prefix_hab_rmk) res = insert_zh_fromapi(
url=api,
con=con_gn,
dep_filter=dep_filter,
orga=organisme,
lst_area=listAreaCover,
prefix_hab_rq=prefix_hab_rmk,
code_rename=code_rename
)