Rechercher dans le blog

Clonage, édition et mise à jour de données (cartes et couches) avec l'API Python d'ArcGIS

Bienvenue dans ce sixième tutoriel de le série de l'été consacrée à la prise en main de l'API Python d'ArcGIS, où nous allons voir ensemble comment automatiser le clonage et la mise à jour de ses données, que ce soit des couches ou des cartes. Dans le tutoriel précédent, nous avons appris à télécharger, préparer et publier des éléments sur son portail de manière automatique. Grâce à ce nouveau tutoriel, vous pourrez insérer ce que vous avez appris dans des workflows de mise à jour. Nous allons ainsi réaccéder au feature layer publié la semaine dernière pour l'actualiser avec des données plus récentes, sans l'écraser ni le republier. Toutes les cartes et applications dans lesquelles ce feature layer est utilisé se verront ainsi également actualisée avec les nouvelles données. En couplant ce que nous aurons vu dans ce tutoriel et le précédent, vous serez capable de faire du pseudo temps réel sur votre plateforme ArcGIS grâce à l'API Python !
 
Comme chaque semaine, vous pouvez suivre le tutoriel ci-dessous pas à pas pour obtenir les explications des différentes étapes, et écrire le code par vous-même ou retrouver le code complet et commenté sur mon Github ou alors le récupérer via cet item ArcGIS
Notez qu'un compte Creator ou supérieur avec des privilèges de publication de contenu sont nécessaires. Vous pouvez exécuter ce Notebook directement dans ArcGIS Notebooks sur ArcGIS Online (disponible par défaut si votre administrateur vous a accordé les droits nécessaires), dans ArcGIS Enterprise (disponible avec le rôle serveur correspondant) ou en le téléchargeant et en l'ouvrant sur ArcGIS Pro (plus d'infos dans la doc). Vous pouvez également l'exécuter dans n'importe quel environnement d'exécution de votre choix, mais veillez dans ce cas à avoir installé les packages nécessaires.

1 - Import des bibliothèques et connexion au GIS

Nous commençons par importer les différentes bibliothèques nécessaires, puis par nous connecter au SIG. Pour cela, nous importons l'objet GIS du module gis, qui représente notre organisation. La connexion est ensuite à adapter selon votre environnement et votre méthode d'authentification. Voir l'aide en ligne pour plus d'informations.
Si vous êtes connectés en tant qu'admin, la cellule va vous renvoyer un message rouge pour vous prévenir qu'il faut faire attention aux opérations que vous utilisez. Cela n'empêche pas votre code de s'exécuter correctement.
Si votre environnement n'est pas directement connecté à votre SIG, vous devrez lui passer vos informations d'authentification via la cellule suivante, que vous devez bien sûr mettre à jour avec vos propres informations : 

2 - Elements basiques de clonage et de mise à jour d'une carte

Nous allons commencer par des éléments très basique de clonage et de mise à jour en travaillant avec une webmap.
 

2a - Accès à une webmap

Je commence par accéder à une webmap de mon portail avec la méthode get() du ContentManager de l'API. De votre côté, vous pouvez faire pareil en accédant à n'importe quelle webmap qui vous appartient sur votre portail, en remplaçant l'id que j'ai utilisé par l'id de votre propre item.

2b - Clonage de la webmap

Nous pourrions effectuer directement les modifications sur notre webmap, mais nous allons plutôt commencer par la cloner pour éviter de créer tout problème dans notre contenu orginel. Pour cela, le ContentManager possède une méthode clone_items() à l'intérieur de laquelle nous transmettons la liste des items à cloner.
En transmettant l'item de la webmap, nous clonons non seulement la webmap mais aussi tous les feature layers qu'elle contient. Vous voyez que le clone retourne une liste contenant pour ma part ma webmap et son feature layer. 
 
La méthode clone_items() supporte un grand nombre d'items pour le clonage, non seulement des cartes et des couches, mais aussi des formulaires Survey123, des applications (StoryMap, Dashboards...), des Notebooks, etc. Vous trouverez la liste complète des items supportés dans la documentation.
Dans ce tutoriel, nous ne verrons qu'un clonage basique d'un item au sein d'un seul portail dans le contenu d'un seul utilisateur. Sachez que clone_items() peut également être utilisée pour cloner des contenus d'un utilisateur à un autre, voire même d'un portail à un autre. C'est une méthode très pratique pour transférer du contenu vers une autre organisation ! 
 
Cela dit, passons à la suite du tutoriel. Dans la liste renvoyée par le clone, je vais accéder à la webmap, qui est pour ma part en deuxième position (donc à l'index 1) :

2c - Mise à jour de la webmap

Dans le tutoriel numéro 4 de la série, nous avons appris à créer une webmap dans l'API Python en construisant la carte de zéro. Sachez qu'il est également possible d'accéder et d'afficher une webmap déjà créée et présente dans le protail. Nous utilisons pour cela, nous utilisons la classe WebMap du module mapping de l'API, et nous passons notre item de webmap en argument (j'utilise ici la webmap clonée).

Cela va créer une MapView qui va afficher votre carte directement dans le Notebook si votre environnement de développement le supporte.
 
Je peux ensuite accéder à tous les paramètres de la MapView comme dans le tuto 4 afin de les mettre à jour.
Je vais par exemple modifier la basemap utilisée :
Si vous retournez plus haut, vous devriez voir votre widget [MapView] se mettre à jour avec le nouveau fond de carte :
Pour information, vous pouvez accéder à la liste des basemaps disponibles en décommentant et en exécutant la cellule ci-dessous : 
Pour l'instant, la modification n'est effective que dans mon instance de MapView, mais ne se répercute pas encore dans ma webmap. Nous allons devoir utiliser la méthode update(). Celle-ci est similaire à la méthode save() que nous avons utilisée dans le tutoriel 4, mais est utilisée sur une webmap existante pour la mettre à jour plutôt que pour la publication d'une nouvelle webmap.
Vous avez peut-être noté que dans votre portail, la webmap clonée possède exactement le même titre que la webmap d'origine. Je profite de la mise à jour de la webmap pour passer un nouveau titre en argument via la propriété item_properties de l'update(), dans laquelle j'attribue une nouvelle valeur à la clé title (ici, je rajoute sobrement "MAJ -" devant le titre de la webmap).
Vous pouvez aller voir que les modifications ont bien été prises en compte, soit directement en réappelant l'item et en allant le consulter, soit en réaffichant la webmap dans une nouvelle MapView :

3 - Mise à jour automatique d'une couche

Dans le tutoriel 5, nous avons appris à télécharger, à préparer et à publier automatiquement des données dans notre portail. Nous avons utilisé les données d'historique journalier du compteur de trafic routier de Bordeaux Métropole. Ces données étant mises à jour quotidiennement, il serait intéressant de pouvoir de notre côté également mettre à jour le feature layer publié pour l'actualiser avec les dernières données en date.
En mettant à jour le feature layer, toutes les cartes et applications l'utilisant verront également leurs données s'actualiser. Cela constitue donc un avantgage très important par rapport à la publication d'un nouveau feature layer.
 
Pour pouvoir suivre et comprendre ce que nous allons faire, je vous conseille fortement d'avoir en amont déjà consulté le tutoriel 5 de la série
 
A l'issue du tutoriel précédent et de la publication des données de comptage en tant que Feature Layer sur mon portail, j'ai fait quelques modification afin de rendre la mise à jour plus évidente dans les captures d'écran du tutoriel et de pouvoir illustrer la mise à jour automatique des applications dans lesquelles le Feature Layer est utilisé. Vous n'êtes pas obligé de faire de même pour pouvoir suivre le tutoriel, mais voici à titre indicatif ce que j'ai fait : J'ai d'abord accédé au Feature Layer via le Map Viewer. J'en ai modifié la symbologie et les étiquettes. J'ai ensuite enregistré les modifications au niveau du Feature Layer, et j'ai enregistré la carte (à laquelle j'ai égalementajouté les données de limites administratives de la commune de Bordeaux) :
Enfin, j'ai inséré cette carte dans un Dashboard, au sein duquel j'affiche plusieurs indicateurs issus des données : 

3a - Accès au feature layer

Afin de mettre à jour le feature layer, nous allons commencer par y accéder. Pour cela, nous utilisons la méthode search() du ContentManager. Si jamais vous aviez modifié le nom du feature layer au moment de la publication dans le tutoriel précédent, changez également le titre dans l'argument de la recherche dans la cellule ci-dessous. Pour rendre la recherche plus précise, nous spécifions également que nous cherchons un élément de type Feature Layer. Pour rappel, search() renvoit une liste. Pour accéder à notre feature layer, nous accédons au premier élément de cette liste.

3b - Création d'un backup des données du Feature Layer

Lors de la mise à jour du Feature Layer, nous allons totalement supprimer les données actuellement contenues dans le feature layer. Ce n'est pas obligatoire, mais nous allons d'abord utiliser une fonction de clonage afin de conserver un historique des anciennes données. Attention cependant, si vous exécutez ce type de script de manière quotidienne en conservant systématiquement l'historique, votre espace de stockage pourrait se remplir relativement vite.

Pour nommer le clone, nous allons récupérer la date des données présentes actuellement dans le feature layer. Pour info, la date est contenue dans le champ 'date' de celui-ci. Si je veux être sûre de la syntaxe du nom du champ, je peux pour rappel accéder à la liste des champs de la couche en accédant à la propriété name des properties de la couche de mon feature layer :
Afin d'accéder facilement aux données contenues dans ma couche, nous allons lire celle-ci en tant que spatially enabled dataframe (sedf) avec la fonction from_layer du GeoAccessor :
Je peux ensuite récupérer la date en accédant à une des valeurs contenues dans la colonne 'date'. Puisque toutes les données contenues ont la même date (car nous avions filtré sur la date au moment de la préparation des données), je peux accéder à la valeur de n'importe quelle ligne. Ici, je prends donc simplement celle de la première ligne (à l'index 0).
Nous pouvons maintenant créer un clone du feature layer avec la méthode clone_items() comme nous l'avions fait au début du tutoriel pour la webmap.
Comme tout à l'heure avec la méthode update(), je mets à jour le titre de mon clone afin qu'il ne possède plus le même nom que mon feature layer d'origine, en y insérant la variable contenant la date des données. La méthode update() renvoyant une liste, je dois accéder à l'élément de la liste contenant le clone du feature layer en en précisant l'index pour pouvoir modifier le titre.
Si nous le souhaitons, nous pouvons appeler le clone fraîchement créé pour le consulter :

3c - Téléchargement et préparation des nouvelles données

Le script de cette partie correspond à ce que nous avions vu en terme de téléchargement et préparation de données dans le tutoriel 5. Je ne le redécrirait pas ici, je vous invite donc à aller consulter le tutoriel précédent si vous voulez plus d'informations sur cette partie.

 

3d - Récupération et suppression de tous les enregistrements du feature layer

Les nouvelles données ayant été récupérées, elles vont pouvoir être ajoutées au Feature Layer pour le mettre à jour. Mais dans un premier temps, nous devons supprimer les données étant actuellement contenues dedans car elles sont obsolètes. Notez que j'accède bien au feature layer d'origine et non pas à son clone, car celui-ci est fait pour contenir les données de backup et ne sera donc pas mis à jour.
Afin de récupérer toutes les entités de ma couches, nous pouvons utiliser la fonction query() sur celle-ci. Si la requête est vide, alors toutes les entités de la couche sont renvoyées.
La deuxième ligne de la cellule permet d'afficher le résultat de la requête sous la forme d'un spatially enabled dataframe afin de vérifier les données renvoyées.
Nous pouvons ensuite appliquer la méthode delete_features sur notre couche en passant le résultat de la requête en argument pour le paramètre deletes.
Cela va supprimer toutes les entités renvoyées par la requête. Dans notre cas, il s'agit de 100% des entités contenues actuellement dans la couche car nous avons laissé la requête vide, mais notez que vous pourriez tirer parti des requêtes pour mettre à jour vos couches en accédant uniquement à certaines entités de celles-ci.

3e - Comparaison des structures des deux sets de données

Maintenant que nous avons supprimé les anciennes données du feature layer, nous sommes à priori prêts à y écrire les données nouvellement récupérées. Nous allons cependant vérifier que le feature layer à mettre à jour et le spatially enabled dataframe contenant les données à écrire ont bien le même format, notamment au niveau du nom des colonnes. J'utilise des fonctions des dataframes afin de comparer les différences de nom de colonnes entre mes deux sets de données :
Je constate que mon feature layer publié a les noms de colonne 'comptage_5' et 'identifian' là où celles de mon sedf contenant les nouvelles données s'appellent 'comptage_5m' et 'identifiant'. Les noms des colonnes ont été tronquées lors de la publication. Elles auraient également pu être modifiées après publication par exemple. Cela empêchera les données de s'écrire correctement à l'intérieur de ces colonnes, alors pensez à vérifier cela si vous constatez que certaines colonnes ne s'écrivent plus lors des mises à jour.
Afin d'éviter les problèmes d'écriture, nous allons renomer les colonnes du sedf exactement de la même manière que celles du feature layer :
Si vous rencontrez d'autres problèmes d'écriture, pensez également à comparer les types de données attendues dans chacune des colonnes avec la propriété la propriété dtypes de vos dataframes :
Ici, normalement, les types de données correspondent (en notant que le type de données object correspond bien à un string, spécifique aux dataframes). Si ça n'est pas le cas, vous pouvez facilement convertir les types de données des colonnes du dataframe contenant les nouvelles données grâce à la méthode astype()
 

3f - Insertion des nouvelles données dans le Feature Layer

Afin de pouvoir insérer les données du sedf dans le feature layer, nous devons commencer par convertir les sedf en Feature Set avec la méthode to_featureset() du GeoAccessor :
Afin d'insérer les données dans la couche, nous utilisons la méthode edit_features() du FeatureLayer. Nous précisons en argument de la fonction que le Feature Set à ajouter aux données est celui créé juste au-dessus.
Nous pouvons maintenant appeler notre Feature Layer, et aller le consulter pour voir les données mises à jour :
Comme je vous le disais, ce workflow met à jour non seulement le feature layer, mais se répercutent également sur toutes les cartes et les applications appelant ce dernier. Par exemple, vous pouvez voir ci-dessous le Dashboard que j'ai créé avec les anciennes données (à gauche), puis après exécution du script ci-dessus et mise à jour des données (à droite) :
Notez que toutes les étiquettes de la carte se sont actualisés automatiquement, et qu'il en va de même pour les indicateurs du Dashboard.

4/ Planifier l'exécution de la mise à jour

Ce genre de script de mise à jour gagne beaucoup de valeur s'il s'exécute automatiquement. Si vous utilisez ArcGIS Notebooks, sachez qu'il est possible de créer une tâche pour planifier l'exécution de ce script de manière très facile. Cela vous permet par exemple de mettre à jour les données et d'obtenir un Dashboard actualisé quotidiennement, sans avoir à aller exécuter le Notebook par vous-même.
Pour cela, créez une version épurée du Notebook contenant uniquement l'import des bibliothèque et la connexion au SIG, puis les codes du chapitre 3 du tutoriel (vous pouvez également supprimer tous les affichages dynamiques afin d'alléger encore d'avantage le Notebook et accélérer son temps d'exécution).
Enregistrez-le dans vos contenus. Vous pourrez ensuite accéder à l'onglet Tâches dans le bandeau supérieur, et créer une Tâche où vous pourrez paramétrer la fréquence d'exécution du Notebook comme illustré dans la vidéo ci-dessous :
Les paramètres utilisés dans la vidéo ont été utilisés lors d'un tutoriel précédent. Ici, vous pouvez adapter des paramètres comme le titre et la fréquence d'exécution.
Notez que l'exécution planifiée de tâches de Notebooks dans ArcGIS Online consomme des crédits de votre organisation. Le nombre de crédits dépend du runtime utilisé par votre Notebook. Ici, avec un runtime standard, l'exécution consomme 1,5 crédits par heure avec un calcul à la minute. Ce type de Notebook de seulement quelques cellules ne prend que quelques minutes à s'exécuter, sa planification ne devrait donc pas avoir de gros impacts sur votre consommation de crédits. Vous pouvez en apprendre plus sur la consommation de crédits selon le runtime du Notebook sur cette page de l'aide en ligne.
 
Ce tutoriel est maintenant fini ! En étant capable d'accéder à les données et les préparer automatiquement puis de mettre à jour des données publiées sur votre portail, vous pouvez maintenant facilement créer des Notebooks et les planifier afin qu'ils s'exécutent avec un certain intervalle de temps pour alimenter vos couche avec de nouvelles données. Cela vous permet de mettre en place du pseudo temps-réel dans vos cartes et vos applications.

Dans le prochain tutoriel, nous attaquerons le dernier volet de capacités de l'API : l'analyse spatiale. Nous apprendrons notamment à utiliser les outils d'analyse spatiale du portail et à accéder aux services de localisation d'ArcGIS.

Aucun commentaire:

Enregistrer un commentaire