from pycen import con_sicen, update_to_sql from sqlalchemy import create_engine # pour lecture de la bd Géonature from sqlalchemy.engine import URL from shapely.geometry import Polygon import geopandas as gpd import pandas as pd import json import matplotlib.pyplot as plt PATH = '/home/colas/Documents/9_PROJETS/6_GEONATURE/MIGRATION/RNGL/DUMP/' FILE = 'export_rnngl.txt' usr = 'postgres' pdw = 'postgres' bdd = 'serenadb' host = '172.17.0.2' eng = URL.create('postgresql+psycopg2',username=usr,password=pdw,host=host,database=bdd) conn = create_engine(eng) tax = pd.read_sql_table('rnf_taxo',con=conn,schema='serenarefe') obs = pd.read_sql_table('rnf_obse',con=conn,schema='serenabase') sit = pd.read_sql_table('rnf_site',con=conn,schema='serenabase') exp = pd.read_table(PATH+FILE,sep='\t',encoding='Windows-1252',dtype={'OBSE_NOMBRE':str,'OBSE_ABOND_CHOI':str,'OBSE_DATE':str}) exp.columns = exp.columns.str.lower() exp[['obse_lat','obse_lon','obse_nombre','oglat','oglon']] = exp[['obse_lat','obse_lon','obse_nombre','oglat','oglon']].replace(',','.',regex=True) cols_coord = exp.columns[exp.columns.str.endswith('lat|lon')] year_only = exp.obse_date.str.len() == 4 month_only = exp.obse_date.str.len() == 6 exp.loc[year_only,'obse_date'] = exp.loc[year_only,'obse_date'] + '0101' exp.loc[month_only,'obse_date'] = exp.loc[month_only,'obse_date'] + '01' exp = (gpd.GeoDataFrame( exp,crs=4326, geometry=gpd.points_from_xy(exp.oglon,exp.oglat)) .to_crs(2154)) exp['obse_date'] = pd.to_datetime(exp.obse_date) # Re-création des géométries des sites sit['poly'] = (sit .site_poly.str[9:] .str.split(',')) sit.loc[sit.poly.notna(),'geom'] = (sit.loc[sit.poly.notna(),'poly'] .apply(lambda x: [xx.split(' ') for xx in x if xx]) .apply(lambda x: [[float(xxx) for xxx in xx] for xx in x ]) .apply(lambda x: Polygon(x))) sit = (sit .set_geometry('geom',crs=4326) .to_crs(2154)) # Création des géométries à partir des coordonnées geom_na = obs.geom_obse.isna() idx = obs[geom_na].obse_id.tolist() # Test des données de l'export exp[exp.obse_id.isin(idx)] # Mise à jour des observations-sites obs_sit = (obs[geom_na] .merge(sit[['site_id','geom']],how='left',left_on='obse_site_id',right_on='site_id') .set_geometry('geom',crs=2154)) update_to_sql( obs_sit[['obse_id','geom']].rename_geometry('geom_site'), conn,'rnf_obse','serenabase','obse_id') #### IDENTIFICATION SERENA-GLEMPS ON SICEN #### #### IDENTIFICATION SERENA-GLEMPS ON SICEN #### obs = pd.read_sql_table('rnf_obse',con=conn,schema='serenabase') sic = pd.read_sql_table('saisie_observation',con=con_sicen,schema='saisie') vsi = pd.read_sql_table('v_saisie_observation',con=con_sicen,schema='saisie') # vmsi = pd.read_sql_table('vm_synthese_observations',con=con_sicen,schema='saisie') vmsi = gpd.read_postgis('SELECT * FROM saisie.vm_synthese_observations',con_sicen,crs=2154) vmsi['date_obs'] = pd.to_datetime(vmsi.date_obs) test_obsEXP = exp.obsv_libel.str.contains('BIRON|JUTON|MARRON',na=False) exp[test_obsEXP] id_obsGL = obs.obse_id.astype(str).tolist() t1_obsVM = ~vmsi.observateurs_v2.str.contains('BIRON',na=False) t2_obsVM = vmsi.rmq_localisation.str.contains('GRAND-LEMPS|GRAND LEMPS',na=False,case=False) t3_obsVM = ~vmsi.id_origine.isin(exp[test_obsEXP].obse_id.astype(str)) t4_obsVM = vmsi.date_obs <= '2019-01-01' t5_obsVM = vmsi.etude != 'Import données Pro Faune Isère' t6_obsVM = vmsi.id_origine.isin(id_obsGL) GL = vmsi[t2_obsVM&t1_obsVM].copy() GL['lat'] = GL.to_crs(4326).geometry.y.round(10).astype(str) GL['lon'] = GL.to_crs(4326).geometry.x.round(10).astype(str) while (GL.lat.str.len()==13).all() == False: GL.loc[GL.lat.str.len()<13,'lat'] = GL[GL.lat.str.len()<13].lat + '0' while (GL.lon.str.len()==12).all() == False: GL.loc[GL.lon.str.len()<12,'lon'] = GL[GL.lon.str.len()<12].lon + '0' test = GL[['lat','lon']].eq(exp[['oglat','oglon']]) test = GL.intersects(exp.unary_union) GL[test] # 18819 Données dans Sicen Qui concerne le Grand-Lemps data_gl = vmsi[t6_obsVM] t7 = ~vmsi.id_obs.isin(data_gl.id_obs) GL = vmsi[t1_obsVM&t2_obsVM&t4_obsVM&t5_obsVM&t7].copy() 4259862565 45.4259862565 id_obs = obs.obse_id.astype(str).tolist() vsi[vsi.id_origine.isin(id_obs)].astype({'id_origine':int}).sort_values('id_origine') vsi[vsi.id_origine.isin(id_obs)].date_obs.max() loc_glps = vsi.localisation.str.contains('ETANG DU GRAND-LEMPS',na=False) vsi[loc_glps].observateur.unique() loc_glps = vmsi.rmq_localisation.str.contains('ETANG DU GRAND-LEMPS',na=False) loc_avenir = vmsi.observateurs_v2.str.contains('BIRON|JUTON|MARRON',na=False) vmsi[loc_glps&~loc_avenir].observateurs_v2.unique() (vsi[loc_glps].observateur .astype(list)) ## By OBSV_LIBEL + DATE rnn = exp.copy() rnn.obsv_libel = (rnn.obsv_libel .replace(r'\(.*?\)','',regex=True) .str.strip() .replace({' - ':' '},regex=True) .replace({' ':' '},regex=True) .replace({' et ':' & '},regex=True) .replace({'&':','},regex=True) .replace({' , ':', '},regex=True) .replace({' , ':', '},regex=True) .apply(lambda x: ', '.join(sorted(x.split(', '))))) sieg = vmsi.copy() sieg.observateurs_v2 = (sieg.observateurs_v2 .replace(r'\(.*?\)','',regex=True) .str.strip() .replace({' ':' '},regex=True) .replace({' ,':', '},regex=True) .replace({' ,':', '},regex=True) .apply(lambda x: ', '.join(sorted(x.split(', '))))) sit.set_index('site_id',inplace=True) lst_etude_serena = [ 'Protocole de suivi AVENIR', 'Veille écologique AVENIR', 'Anciennes BD AVENIR', 'BIBLIOGRAPHIE', 'Échange de données - CORA Rhône', 'Veille écologique', 'Échange de données - CBNA', 'Echange de données - GRPLS', # 'Echange de données (partenaires)' ] t1 = sieg.observateurs_v2.isin(rnn.obsv_libel) t2 = sieg.date_obs.isin(rnn.obse_date) t3 = sieg.intersects(sit.iloc[2].geom.buffer(0)) t4 = sieg.etude.isin(lst_etude_serena) t4 = sieg.etude=='Échange de données - CORA Rhône' sieg[t1&t2&t3&t4] # Données à écarter. 15212 données dans Sicen qui concerne le Grand-Lemps # 10404 dans le Grand-Lemps avant le 01-01-2018 date_max = sieg[t1&t2&t3&t4].date_obs.max() rnn[rnn.obse_date <= date_max] t5 = sieg.date_obs==date_max sieg[t1&t2&t3&t4&(~t5)] dat_max2 = sieg[t1&t2&t3&t4&(~t5)].date_obs.max() t6 = sieg.date_obs==dat_max2 sieg[t1&t2&t3&t4&(~t5)&(~t6)] sieg[t1&t2&t3&t4&t6] dict_col = { 'observateurs_v2':'obsv_libel', 'date_obs':'obse_date', # 'lot_donnee':'lot_donnee', 'etude':'relv_nom', 'nom_complet':'taxo_latin_c', # 'geom':'geometry', } fusion = pd.concat( [sieg[t1&t2&t3&t4].rename(columns=dict_col)[[*dict_col.values()]], rnn[[*dict_col.values()]]], ) #### Test equivalence [obse_lat - oglat, obse_lon - oglon] # Columns : # obsv_libel : Observateur # obse_date : date d'Observation test = exp[exp.obse_lat.notna()] tlat = test.obse_lat.eq(test.oglat) tlon = test.obse_lon.eq(test.oglon) test[~tlat].index.equals(test[~tlon].index) test[~tlat] test[~tlon] lst_tax = tax.taxo_id.tolist() test = obs[~obs.obse_taxo_id.isin(lst_tax)] # ERREUR: une instruction insert ou update sur la table « rnf_obse » viole la contrainte de clé # étrangère « rnf_obse_rnf_user_fk » # Détail : La clé (obse_obsv_id)=(6052) n'est pas présente dans la table « rnf_user ». test = ~vmsi.observateurs_v2.str.contains('Isère|Personnel',na=False,case=False) vmsi[test] vmsi[test].observateurs_v2