Suite

Arcpy/REST : comment enregistrer un jeu de données raster à partir d'une URL

Arcpy/REST : comment enregistrer un jeu de données raster à partir d'une URL


J'ai un script qui télécharge des fonctionnalités à partir d'un ArcGIS MapServer via l'API REST. L'obtention de fonctionnalités vectorielles est relativement triviale car les fonctionnalités peuvent être récupérées au format JSON. Cependant, lors de la récupération d'une carte sous forme d'image, je suis bloqué au point où j'ai récupéré une réponse.

La partie pertinente de mon code, qui me donne une URL d'image valide, est la suivante :

# Exportez la carte en JSON. urlGetImage = '%s/export?bbox=%s&bboxSR=%s&format=png&f=json' % ( theBasicUrl, bbox, bboxSR) urlGetImageResponse = urllib2.urlopen(urlGetImage) jsonImage = json.loads(urlGet.ImageResponse()) l'URL de l'image à partir du JSON et enregistrez l'image. urllib.urlretrieve(jsonImage['href'], os.path.join(tempFolder, 'test.png">

Travaillez-vous avec un ImageService ? D'après ce que je peux dire, c'est que vous travaillez avec un service de carte et si tel est le cas, l'option d'exportation de carte ne renverra qu'une image statique du service de carte ou d'une couche individuelle.

En regardant ce qui est renvoyé dans votre exemple, nous pouvons voir qu'un png est renvoyé. Ce n'est pas un vrai raster mais juste une image de celui-ci. Par conséquent, il ne sera pas géorectifié et il n'aura pas les valeurs de pixels du raster (ce seront simplement des valeurs RVB).

Ceux-ci semblent être des services sur vos propres serveurs ? Si tel est le cas, vous pouvez simplement publier le raster seul en tant que service d'imagerie, puis récupérer l'image en tant que tif, qui contiendra les informations de référence spatiale ainsi que les valeurs des pixels.

ÉDITER

Après une discussion plus approfondie, nous avons déterminé qu'il vous suffisait de géoréférencer l'image de la carte en sortie. J'ai écrit une petite fonction basée sur votre code ci-dessus pour le faire et cela a fonctionné pour moi :

import urllib, urllib2, json, os, arcpy arcpy.env.overwriteOutput = True def exportMap(url, bbox, bboxSR, out_png): # obtient les propriétés du cadre de délimitation (suppose qu'il est délimité par des virgules) xmin, ymin, xmax, ymax = map( float, bbox.split(',')) size = ','.join(map(str, [int(abs(xmin-xmax)), int(abs(ymin-ymax))])) # faire des requêtes urlGetImage = '%s/export?bbox=%s&bboxSR=%s&size=%s&format=png&f=json' %(url, bbox, bboxSR, size) urlGetImageResponse = urllib2.urlopen(urlGetImage) jsonImage = json.loads(urlGetreadImageResponse )) # Lisez l'URL de l'image à partir du JSON et enregistrez l'image. tmp_png = os.path.join(arcpy.env.scratchFolder, 'temp_png.png">

L'image téléchargée ne contient aucune information sur sa situation géographique (du moins pas à ma connaissance), vous devez donc créer un fichier mondial manuellement. Le format est trivial, consultez l'aide d'ArcGIS Desktop sur Fichiers mondiaux pour les jeux de données raster.

De plus, vous devez définir la référence spatiale de l'image, utilisezarcpy.DefineProjection_management()pour ce faire : http://desktop.arcgis.com/en/desktop/latest/tools/data-management-toolbox/define-projection.htm.

ÉDITER

J'ai juste pensé à une alternative : vous pourriez créer un catalogue raster (non) géré, les informations géographiques nécessaires vont ensuite dans un tableau. Veuillez consulter l'aide de la boîte à outils Créer un catalogue raster.


Il s'avère qu'il existe un moyen beaucoup plus pratique, moins manuel et moins sujet aux erreurs. Il s'agissait simplement d'obtenir les données MapServer en tant que KMZ et de les convertir de KML en raster en utilisant tous les paramètres de l'outil. Pour la conversion vectorielle, vous n'avez besoin que de deux paramètres pour l'outil KMLToLayer_conversion, mais pour la conversion raster/image, vous doit précisez les quatre. C'est l'étape cruciale que j'ai manquée plus tôt.

Après quelques ajustements, et avec une refactorisation probablement encore nécessaire, voici une approche de travail (testée avec une carte non carrelée):

## imports : arcpy, os, json, glob, urllib def getMapImage(theBasicUrl, theClipJsonString, theDestinationFolder, theDestinationGDB) : """ Récupérer une image de carte via une URL basée sur une étendue. Paramètres : theBasicUrl : URL vers laquelle les requêtes peuvent être attaché. theDestinationFolder : le répertoire contenant le GDB de destination. theDestinationGDB : l'emplacement de sortie ultime. theClipJsonString : zone à découper (en JSON). Renvoie : outputFeature : l'emplacement de l'entité de sortie sous forme de chaîne. """ # Créer un temp dossier dans lequel travailler. # Remarque : 'now' est une variable globale contenant une chaîne datetime. tempFolder = os.path.join(theDestinationFolder,'temp_%s' % now) os.makedirs(tempFolder) # Définit le format de l'image (peut aussi être un paramètre). imageFormat = 'png' # Crée un fichier JSON à partir de la zone de clip JSON # (requis pour JSONToFeatures_conversion). jsonFile = os.path.join(tempFolder, 'clip.json') avec open(jsonFile, 'w') comme outFile: outFile.write(theClipJsonString) # Transforme la forme du clip en classe d'entités. clipFeatureClass = os.path.join(tempFolder, 'clipFC.shp') arcpy.JSONToFeatures_conversion(jsonFile, clipFeatureClass) # Obtient l'étendue de la classe d'entités de découpage. clipExtents = arcpy.Describe(clipFeatureClass).extent # Construire une chaîne pour le paramètre bbox de l'URL de la requête. bbox = '%s,%s,%s,%s' % ( clipExtents.XMin, clipExtents.YMin, clipExtents.XMax, clipExtents.YMax) bboxSR = json.loads(theClipJsonString)['spatialReference']['wkid' ] # Télécharger en tant que KMZ. urlGetImage = '%s/export?bbox=%s&bboxSR=%s&format=%s&f=kmz' % ( theBasicUrl, bbox, bboxSR, imageFormat) kmzFile = os.path.join(tempFolder, 'test.kmz') urllib.URLopener ().retrieve(urlGetImage, kmzFile)"REMARQUE : une mise en garde s'applique ici concernant le téléchargement possible de rasters sources à toutes les échelles disponibles, comme mentionné dans la documentation de KMLToLayer_conversion."# Convertissez le KMZ en raster. rasterizedKMZ = 'mapLayer' arcpy.KMLToLayer_conversion(kmzFile, tempFolder, rasterizedKMZ, True) # Place le raster dans la GDB. rasterizedKMZFile = glob.glob(os.path.join(tempFolder, '%s.grd' %  rasterizedKMZ, '*.%s' % imageFormat))[0] outRasterName = 'map_export_%s' % now arcpy.CopyRaster_management( rasterizedKMZFile, os.path.join(theDestinationGDB, outRasterName), '#', '#', '256', 'NONE', 'NONE', '#', 'NONE', 'NONE') # Supprimer les intermédiaires arcpy. Delete_management(tempFolder) # cela ne fonctionne pas encore return os.path.join(theDestinationGDB, outRasterName)

Voir la vidéo: Using the ArcGIS REST JS Libraries and the ArcGIS REST APIs