L'Atlas nécessite de définir un territoire correspondant à l'emprise géographique des observations stockées dans le module Synthèse de GeoNature.
Dans le cadre du SINP PACA, nous avons gérées la définition du territoire et la suppression des zones géographiques inutiles via un script de gestion des zones géographiques liées à un territoire.
Dans le cadre du SINP AURA, un script basé sur le même principe est aussi disponible mais nous avons préféré utiliser le référentiel géographique construit par Flavia dans leur GeoNature. En effet, les contours des départements et de la région ont été construits à l'aide des contours des communes. Cela offre l'avantage d'avoir une parfaite superposition de ces différentes entités géographiques. De plus, l'intégration de différentes entités géographiques fournit par l'INPN a été réalisé et l'ensemble des entités géographiques hors région AURA supprimées.
Vous pouvez consulter les requêtes initialement exécutées pour créer le territoire et supprimer des zones géographiques dans le cadre du SINP PACA.
ssh geonat@db-<region>-sinp
cd ~/data
vm_observations
avec : psql -h localhost -U geonatadmin -d gnatlas -f ./db-atlas/data/sql/01_update_vm_observations.sql
sudo -u postgres -s psql -d gnatlas -f ./db-atlas/data/sql/03_fix_as_superuser.sql
psql -h localhost -U geonatadmin -d gnatlas -f ./db-atlas/data/sql/04_fix_as_user.sql
100
le passé à 100 000 :ALTER SERVER geonaturedbserver OPTIONS (SET fetch_size '100000');
ALTER SERVER geonaturedbserver OPTIONS (ADD fetch_size '100000');
centroid
de la table ref_geo.l_areas
car elle est utilisé par la vue synthese.syntheseff
de l'Atlas. Or par défaut, cette colonne est vide : UPDATE ref_geo.l_areas SET centroid = ST_Centroid(geom) WHERE centroid IS NULL ;
synthese.syntheseff
car la requête par défaut ne fonctionne pas avec 46 millions de lignes dans la table cor_area_synthese
. C'est la requêtes associant les id_synthese avec les différents types de zone géo qui posent problème. L'affichage dans l'Atlas se faisant sous forme de mailles, nous allons supprimé cette partie le temps de trouver une solution :CREATE OR REPLACE VIEW synthese.syntheseff AS SELECT s.id_synthese, s.id_dataset, s.cd_nom, s.date_min AS dateobs, s.observers AS observateurs, (s.altitude_min + s.altitude_max) / 2 AS altitude_retenue, st_transform(s.the_geom_point, 4326) AS the_geom_point, s.count_min AS effectif_total, c.insee, dl.cd_nomenclature::INTEGER AS diffusion_level FROM synthese.synthese s JOIN atlas.l_communes AS c ON ( st_intersects(s.the_geom_point, c.the_geom) ) LEFT JOIN synthese.t_nomenclatures AS dl ON (s.id_nomenclature_diffusion_level = dl.id_nomenclature) LEFT JOIN synthese.t_nomenclatures AS st ON (s.id_nomenclature_observation_status = st.id_nomenclature) WHERE ( NOT dl.cd_nomenclature::text = '4'::text OR s.id_nomenclature_diffusion_level IS NULL ) AND st.cd_nomenclature::text = 'Pr'::TEXT ;
atlas.vm_communes
se comporte normalement. Elle met toujours un peu de temps à se générer (15mn en local sur disque SSD Nvme). Avant la version 1.5 de l'Atlas, la VM atlas.vm_communes
ne contient pas toutes les communes du territoire. Il semblerait que les communes en bord de mer ne soient pas prise en compte même avec l'utilisation de la fonction Postgis st_buffer()
… Le problème vient peut être des îles des communes côtières. De plus, la génération de son contenu prend énormément de temps, nous pouvons donc utiliser la subdivision du territoire à la place. Au final, nous pouvons utiliser à la place : DROP MATERIALIZED VIEW IF EXISTS atlas.vm_stats ; DROP MATERIALIZED VIEW IF EXISTS atlas.vm_communes ; CREATE MATERIALIZED VIEW atlas.vm_communes TABLESPACE pg_default AS SELECT DISTINCT c.insee, c.commune_maj, c.the_geom, c.commune_geojson FROM atlas.l_communes c JOIN atlas.t_subdivided_territory t ON (st_intersects(t.geom, c.the_geom)) WITH DATA ; -- View indexes: CREATE UNIQUE INDEX vm_communes_insee_idx ON atlas.vm_communes USING btree(insee) ; CREATE INDEX vm_communes_commune_maj_idx ON atlas.vm_communes USING btree(commune_maj) ; CREATE INDEX index_gist_vm_communes_the_geom ON atlas.vm_communes USING gist(the_geom) ; CREATE MATERIALIZED VIEW atlas.vm_stats TABLESPACE pg_default AS SELECT 'observations'::text AS label, COUNT(*) AS RESULT FROM atlas.vm_observations UNION SELECT 'municipalities'::text AS label, COUNT(*) AS RESULT FROM atlas.vm_communes UNION SELECT 'taxons'::text AS label, COUNT(DISTINCT vm_taxons.cd_ref) AS RESULT FROM atlas.vm_taxons UNION SELECT 'pictures'::text AS label, COUNT(DISTINCT m.id_media) AS RESULT FROM atlas.vm_medias m JOIN atlas.vm_taxons t ON t.cd_ref = m.cd_ref WHERE m.id_type = ANY (ARRAY[1, 2]) WITH DATA ; -- View indexes: CREATE UNIQUE INDEX vm_stats_label_idx ON atlas.vm_stats USING btree(label) ; -- Restore permissions GRANT SELECT ON TABLE atlas.vm_communes TO geonatatlas ; GRANT SELECT ON TABLE atlas.vm_stats TO geonatatlas ;
atlas.vm_observations_mailles
avec : CREATE UNIQUE INDEX vm_observations_mailles_id_obs_geojson_idx ON atlas.vm_observations_mailles USING btree (id_observation, geojson_maille) ;
CREATE MATERIALIZED VIEW atlas.cor_synthese_area TABLESPACE pg_default AS SELECT DISTINCT ON (sa.id_synthese, t.type_code) sa.id_synthese, sa.id_area, st_transform(a.centroid, 4326) AS centroid_4326, t.type_code, a.area_code FROM synthese.cor_area_synthese AS sa JOIN ref_geo.l_areas AS a ON (sa.id_area = a.id_area) JOIN ref_geo.bib_areas_types AS t ON (a.id_type = t.id_type) WHERE t.type_code IN ('M10', 'COM', 'DEP') WITH DATA; -- View indexes: CREATE UNIQUE INDEX cas_pk_idx ON atlas.cor_synthese_area USING btree (id_synthese, id_area); CREATE INDEX cas_type_code_idx ON atlas.cor_synthese_area USING btree (type_code); CREATE OR REPLACE FUNCTION atlas.get_blurring_centroid_geom_by_code(code CHARACTER VARYING, idSynthese INTEGER) RETURNS geometry LANGUAGE plpgsql IMMUTABLE AS $function$ -- Function which return the centroid for a sensitivity or diffusion_level code and an id synthese DECLARE centroid geometry; BEGIN SELECT INTO centroid csa.centroid_4326 FROM atlas.cor_synthese_area AS csa WHERE csa.id_synthese = idSynthese AND csa.type_code = (CASE WHEN code = '1' THEN 'COM' WHEN code = '2' THEN 'M10' WHEN code = '3' THEN 'DEP' END) LIMIT 1 ; RETURN centroid ; END; $function$ ; CREATE OR REPLACE VIEW synthese.syntheseff AS SELECT s.id_synthese, s.id_dataset, s.cd_nom, s.date_min AS dateobs, s.observers AS observateurs, (s.altitude_min + s.altitude_max) / 2 AS altitude_retenue, CASE WHEN (sens.cd_nomenclature::INT >= 1 AND sens.cd_nomenclature::INT <= 3 AND dl.cd_nomenclature::INT >= 1 AND dl.cd_nomenclature::INT <= 3) THEN CASE WHEN (sens.cd_nomenclature::INT >= dl.cd_nomenclature::INT) THEN ( atlas.get_blurring_centroid_geom_by_code(sens.cd_nomenclature, s.id_synthese) ) WHEN (sens.cd_nomenclature::INT < dl.cd_nomenclature::INT) THEN ( atlas.get_blurring_centroid_geom_by_code(dl.cd_nomenclature, s.id_synthese) ) END WHEN (sens.cd_nomenclature::INT >= 1 AND sens.cd_nomenclature::INT <= 3) AND (dl.cd_nomenclature::INT < 1 OR dl.cd_nomenclature::INT > 3) THEN ( atlas.get_blurring_centroid_geom_by_code(sens.cd_nomenclature, s.id_synthese) ) WHEN (dl.cd_nomenclature::INT >= 1 AND dl.cd_nomenclature::INT <= 3) AND (sens.cd_nomenclature::INT < 1 OR sens.cd_nomenclature::INT > 3) THEN ( atlas.get_blurring_centroid_geom_by_code(dl.cd_nomenclature, s.id_synthese) ) ELSE st_transform(s.the_geom_point, 4326) END AS the_geom_point, s.count_min AS effectif_total, c.insee, sens.cd_nomenclature AS sensitivity, dl.cd_nomenclature AS diffusion_level FROM synthese.synthese s JOIN atlas.l_communes AS c ON ( st_intersects(s.the_geom_point, c.the_geom) ) LEFT JOIN synthese.t_nomenclatures AS sens ON (s.id_nomenclature_sensitivity = sens.id_nomenclature) LEFT JOIN synthese.t_nomenclatures AS dl ON (s.id_nomenclature_diffusion_level = dl.id_nomenclature) LEFT JOIN synthese.t_nomenclatures AS st ON (s.id_nomenclature_observation_status = st.id_nomenclature) WHERE ( NOT dl.cd_nomenclature = '4' OR s.id_nomenclature_diffusion_level IS NULL ) AND ( NOT sens.cd_nomenclature = '4' OR s.id_nomenclature_sensitivity IS NULL ) AND st.cd_nomenclature = 'Pr' ;
ssh geonat@<sinp-web>
sudo nginx_dissite atlas.conf ; sudo nginx_ensite atlas_maintenance.conf ; sudo service nginx reload
sudo supervisorctl stop atlas
cd ~/dwl/
export GNAV=$(curl -s https://api.github.com/repos/PnX-SI/GeoNature-atlas/releases/latest | grep tag_name | cut -d\" -f4)
echo "${GNAV}"
wget https://github.com/PnX-SI/GeoNature-atlas/archive/${GNAV}.zip -O atlas_v${GNAV}.zip
unzip atlas_v${GNAV}.zip -d ~/www/
cd ~/www/
mv GeoNature-atlas-${GNAV} atlas_v${GNAV}
cd ~/www; rm -f atlas_old; ln -s atlas_v<ancienne-version> atlas_old
cp ~/www/atlas_old/atlas/configuration/settings.ini ~/www/atlas_v${GNAV}/atlas/configuration/settings.ini
cp ~/www/atlas_old/atlas/configuration/config.py ~/www/atlas_v${GNAV}/atlas/configuration/config.py
diff ~/www/atlas_old/atlas/configuration/settings.ini.sample ~/www/atlas_v${GNAV}/atlas/configuration/settings.ini.sample
diff ~/www/atlas_old/atlas/configuration/config.py.sample ~/www/atlas_v${GNAV}/atlas/configuration/config.py.sample
cp -aR ~/www/atlas_old/static/custom/ ~/www/atlas_v${GNAV}/static
cd ~/www; rm -f atlas; ln -s "atlas_v${GNAV}" atlas
rsync -av -e "ssh -p <port-ssh-db>" /home/geonat/www/ geonat@db-<region>-sinp:/home/geonat/www/
ssh geonat@<sinp-db>
psql -h localhost -U geonatadmin -d gnatlas -f ~/www/atlas/data/<mon-fichier-de-mise-a-jour>.sql
cd ~/www/atlas/ ; ./install_app.sh
~/www/atlas/log/errors_atlas.log
avec : tail -f ~/www/atlas/log/errors_atlas.log
sudo systemctl start geonature-atlas
sudo nginx_dissite atlas_maintenance.conf ; sudo nginx_ensite atlas.conf ; sudo service nginx reload
Toutes étapes suivantes se déroulent sur "web-srv" à l'exception des mises à jour de la base à exécuter via psql
sur "db-srv" :
export GNAB="<branche>"
cat VERSION
export GNAV="1.5.2-dev0-04dbbcb"
echo "Branche: ${GNAB} ; GeoNature-Atlas : ${GNAV}"
cd ~/dwl/
wget https://github.com/PnX-SI/GeoNature-atlas/archive/<branche>.zip -O "atlas_${GNAB}_v${GNAV}.zip"
https://github.com/PnX-SI/GeoNature-atlas/archive/<sha1>.zip
unzip atlas_${GNAB}_v${GNAV}.zip -d ~/dwl/
mv GeoNature-atlas-${GNAB} atlas_${GNAB}_v${GNAV}
mv atlas_${GNAB}_v${GNAV} ~/www/
cd ~/www/
cp ~/www/atlas/atlas/configuration/settings.ini ~/www/atlas_${GNAB}_v${GNAV}/atlas/configuration/settings.ini
cp ~/www/atlas/atlas/configuration/config.py ~/www/atlas_${GNAB}_v${GNAV}/atlas/configuration/config.py
diff ~/www/atlas/atlas/configuration/config.py.sample ~/www/atlas_${GNAB}_v${GNAV}/atlas/configuration/config.py.sample
diff ~/www/atlas/atlas/configuration/settings.ini.sample ~/www/atlas_${GNAB}_v${GNAV}/atlas/configuration/settings.ini.sample
vi ~/www/atlas_${GNAB}_v${GNAV}/atlas/configuration/config.py
vi ~/www/atlas_${GNAB}_v${GNAV}/atlas/configuration/settings.ini
cp -aR ~/www/atlas/atlas/static/custom/ ~/www/atlas_${GNAB}_v${GNAV}/atlas/static
cp ~/www/atlas/environ ~/www/atlas_${GNAB}_v${GNAV}/environ
cd ~/www; rm -f atlas; ln -s atlas_${GNAB}_v${GNAV} atlas
cd ~/www; rm -f atlas_old; ln -s atlas_v${GNAV} atlas_old
cd ~/www; rm -f atlas_old; ln -s atlas_${GNAB}_v<ancienne-version> atlas_old
rsync -av -e "ssh -p <port-ssh-db>" /home/geonat/www/ geonat@db-<region>-sinp:/home/geonat/www/
ssh geonat@<sinp-db>
psql -h localhost -U geonatadmin -d gnatlas -f ~/www/atlas/data/<mon-fichier-de-mise-a-jour>.sql
cd ~/www/atlas/ ; ./install_app.sh
sudo systemctl restart geonature-atlas
sudo nginx_dissite atlas_maintenance.conf ; sudo nginx_ensite atlas.conf ; sudo nginx-reload
Surcoucher le service Systemd de GeoNature Atlas :
systemctl edit geonature-atlas
[Unit] StartLimitIntervalSec=6min StartLimitBurst=5 [Service] ExecStart= ExecStart=/home/geonat/www/atlas/venv/bin/gunicorn atlas.wsgi:app \ --statsd-host "localhost:8125" \ --statsd-prefix "atlas" \ --name "${GUNICORN_PROC_NAME}" --workers "${GUNICORN_NUM_WORKERS}" \ --bind "${GUNICORN_HOST}:${GUNICORN_PORT}" --timeout="${GUNICORN_TIMEOUT}" Restart=on-failure RestartSec=1min
vi /etc/systemd/system/geonature-atlas.service.d/override.conf
systemctl daemon-reload
systemctl restart geonature-atlas
Si vous souhaitez utiliser dans l'Atlas les images issues de l'INPN vous pouvez suivre la procédure suivante :
ssh geonat@sinp-<region>-web
screen -S "images-inpn-import"
cd ~/www/taxhub/data/scripts/import_inpn_media
python3 -m venv venv
source venv/bin/activate
sudo chmod o+x /usr/bin/gcc
pip install psycopg2 requests
sudo chmod o-x /usr/bin/gcc
cp config.py.sample config.py
SQLALCHEMY_DATABASE_URI = "postgresql://geonatadmin:<mot-de-passe>@10.0.1.20:5432/geonature2db"
QUERY_SELECT_CDREF = """SELECT DISTINCT cd_ref FROM taxonomie.bib_noms ORDER BY cd_ref LIMIT 100"""
LIMIT 100
une fois un premier test effectuéQUERY_SELECT_CDREF = """ SELECT DISTINCT cd_ref FROM taxonomie.bib_noms AS bn WHERE NOT EXISTS ( SELECT 'X' FROM taxonomie.t_medias tm WHERE tm.cd_ref = bn.cd_ref ) ORDER BY cd_ref """
taxonomie.bib_noms
est vide. Cela peut arrivé si aucun module de saisie n'est actif (cas du SINP). Il est possible de la remplir à partir des données de gn_synthese.synthese
avec la requête suivante :INSERT INTO taxonomie.bib_noms (cd_nom, cd_ref) SELECT DISTINCT s.cd_nom, t.cd_ref FROM gn_synthese.synthese AS s JOIN taxonomie.taxref AS t ON s.cd_nom = t.cd_nom WHERE NOT s.cd_nom IN (SELECT DISTINCT cd_nom FROM taxonomie.bib_noms);
bib_noms
est vide (Temps d’exécution 20s pour 9,3 millions de lignes dans synthese
): psql -h localhost -U geonatadmin -d geonature2db -c "INSERT INTO taxonomie.bib_noms (cd_nom, cd_ref) SELECT DISTINCT s.cd_nom, t.cd_ref FROM gn_synthese.synthese AS s JOIN taxonomie.taxref AS t ON s.cd_nom = t.cd_nom WHERE NOT s.cd_nom IN (SELECT DISTINCT cd_nom FROM taxonomie.bib_noms);
"
python import_inpn_media.py
taxonomie.t_medias
. deactivate
WITH first_media AS ( SELECT MIN(id_media) AS first_id_media_founded, cd_ref FROM taxonomie.t_medias GROUP BY cd_ref ) UPDATE taxonomie.t_medias AS tm SET id_type = 1 FROM first_media AS fm WHERE tm.id_media = fm.first_id_media_founded AND tm.cd_ref = fm.cd_ref ;
WITH first_media AS ( SELECT MIN(id_media) AS first_id_media_founded, cd_ref FROM taxonomie.t_medias WHERE cd_ref NOT IN ( SELECT cd_ref FROM taxonomie.t_medias stm WHERE id_type = 1 ) GROUP BY cd_ref ) UPDATE taxonomie.t_medias AS tm SET id_type = 1 FROM first_media AS fm WHERE tm.id_media = fm.first_id_media_founded AND tm.cd_ref = fm.cd_ref ;
psql -h localhost -U geonatadmin -d geonature2db -c "WITH first_media AS (SELECT MIN(id_media) AS first_id_media_founded, cd_ref FROM taxonomie.t_medias GROUP BY cd_ref) UPDATE taxonomie.t_medias AS tm SET id_type = 1 FROM first_media AS fm WHERE tm.id_media = fm.first_id_media_founded AND tm.cd_ref = fm.cd_ref ;"
UPDATE taxonomie.t_medias AS tm SET id_type = 2 WHERE id_type = 1 ;
WITH exists_first_medias AS ( SELECT cd_ref FROM taxonomie.t_medias AS stm WHERE id_type = 1 ), priority_first_medias AS ( SELECT 1 AS priority, MIN(id_media) AS first_id_media_founded, cd_ref FROM taxonomie.t_medias WHERE cd_ref NOT IN ( SELECT cd_ref FROM exists_first_medias ) AND "source" != 'INPN' AND supprime != TRUE GROUP BY cd_ref UNION SELECT 2 AS priority, MIN(id_media) AS first_id_media_founded, cd_ref FROM taxonomie.t_medias WHERE cd_ref NOT IN ( SELECT cd_ref FROM exists_first_medias ) AND "source" = 'INPN' AND supprime != TRUE GROUP BY cd_ref ), first_medias AS ( SELECT DISTINCT ON (pfm.cd_ref) pfm.cd_ref, pfm.priority, pfm.first_id_media_founded FROM priority_first_medias AS pfm ORDER BY pfm.cd_ref, pfm.priority ) UPDATE taxonomie.t_medias AS tm SET id_type = 1 FROM first_medias AS fm WHERE tm.id_media = fm.first_id_media_founded AND tm.cd_ref = fm.cd_ref ;
REFRESH MATERIALIZED VIEW atlas.vm_medias WITH DATA ; REFRESH MATERIALIZED VIEW atlas.vm_taxons_plus_observes WITH DATA ; REFRESH MATERIALIZED VIEW atlas.vm_stats WITH DATA ; TRUNCATE atlas.t_cache ;
ssh geonat@<sinp-db>
screen -S "update-atlas"
CONCURRENTLY
, il est possible de lancer le rafraîchissement des VMs sur l'installation de production. L'Atlas restera fonctionnel même pendant le rafraîchissement.psql -h localhost -U geonatadmin -d gnatlas -c "SELECT atlas.refresh_materialized_view_data() ;"
psql -h localhost -U geonatadmin -d gnatlas -c "SELECT atlas.refresh_materialized_view_ref_geo() ;"
psql -h localhost -U geonatadmin -d gnatlas -c "SELECT RefreshAllMaterializedViews('atlas') ;"