Suite

Comment puis-je obtenir les valeurs renvoyées par un objet de limites OpenLayers au format Longitude / Latitude ?

Comment puis-je obtenir les valeurs renvoyées par un objet de limites OpenLayers au format Longitude / Latitude ?


J'ai créé une carte et ajouté une couche à l'aide de la bibliothèque OpenLayers :

map = new OpenLayers.Map('map'); var gphy = new OpenLayers.Layer.Google("Google Physical", {type : G_PHYSICAL_MAP}); map.addLayer(gphy);

La carte se charge et je peux centrer ma carte :

map.setCenter(nouveau OpenLayers.LonLat(-114.922485, 56.400224), 4);

J'ai ensuite créé un gestionnaire de boîte, mais les limites renvoyées ne sont pas au format Longitude / Latitude. Lorsque je dessine une boîte autour du centre de ma carte, mon objet lié renvoie ce qui suit :

en bas à gauche=(278,245) en haut à droite=(304,211)

Comment puis-je convertir ces valeurs en Longitude / Latitude ?

La résolution grâce à unicoletti :

map.getLonLatFromPixel(nouveau OpenLayers.Pixel(bounds.left, bounds.bottom))

En supposant qu'il s'agisse de coordonnées en pixels, vous pouvez utiliser :

map.getLonLatFromPixel

ou l'une des autres fonctions de conversion pixel en latitude/longitude de l'objet cartographique. Consultez la documentation relative à votre version OL pour une explication détaillée.


L'instance OpenLayers.Bounds que vous regardez a 4 propriétés : left, bottom, right et top. La longitude du coin inférieur gauche est bounds.left, la latitude est bounds.bottom.

Notez, cependant, que les coordonnées utilisées par OpenLayers.Bounds et OpenLayers.LonLat ne sont pas nécessairement des latitudes et des longitudes. Ils dépendent de la projection de la couche de base. Pour le web mercator, qui est la projection lorsque vous configurez votre couche de base Google avec sphericalMercator : vrai, les valeurs seraient complètement différentes. Pour obtenir la latitude et la longitude dans ce cas, vous utiliseriez la méthode de transformation, par ex.

bounds.transform(map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));

Comment traiter les données météorologiques GRIB2 pour les applications éoliennes (GeoJSON)

Écrit par
Elliott Wobler
Ingénieur technico-commercial

Aperçu

Ce didacticiel explique comment utiliser les données de prévision mondiales de Spire Weather au format GRIB2 à l'aide de Python.

Si vous n'avez jamais travaillé avec des données GRIB2 auparavant, il est recommandé de commencer par le didacticiel de démarrage, car celui-ci abordera des sujets légèrement plus avancés.

Plus précisément, ce didacticiel montre comment récupérer la vitesse et la direction du vent à différents niveaux verticaux (c'est-à-dire les hauteurs pertinentes pour les éoliennes) dans les limites d'un polygone complexe (par exemple, une frontière nationale).

À la fin de ce tutoriel, vous saurez comment :

  1. Charger des fichiers contenant des messages GRIB2 dans un programme Python
  2. Inspectez les données GRIB2 pour comprendre quelles variables météorologiques sont incluses
  3. Filtrez les données GRIB2 sur les variables météorologiques d'intérêt à différents niveaux verticaux
  4. Calculer la vitesse et la direction du vent à partir des composantes du vent vers l'est et le nord
  5. Recadrer les données GRIB2 à la zone définie par une entrée de fichier GeoJSON
  6. Convertissez les données GRIB2 transformées en un fichier de sortie CSV pour une analyse et une visualisation plus poussées

Téléchargement des données

La première étape consiste à télécharger les données de l'API de fichier de Spire Weather.

Ce didacticiel s'attend à ce que les messages GRIB2 contiennent des données NWP provenant du paquet de données d'énergie renouvelable de Spire.

Pour plus d'informations sur l'utilisation des points de terminaison de l'API de fichier Spire Weather’s, veuillez consulter la documentation de l'API et la FAQ.

La FAQ contient également des exemples détaillés expliquant comment télécharger plusieurs fichiers de prévision à la fois à l'aide de cURL.

Pour les besoins de ce didacticiel, il est supposé que les données GRIB2 ont déjà été téléchargées avec succès, sinon obtenez un échantillon ici.

Comprendre les noms de fichiers

Les fichiers téléchargés à partir des produits API de Spire Weather partagent tous la même convention de dénomination de fichier.

En regardant simplement le nom du fichier, nous pouvons déterminer :

  • la date et l'heure d'émission de la prévision
  • la date et l'heure de validité des données prévisionnelles
  • la résolution horizontale des données de prévision globales
  • les variables de données météorologiques incluses dans le fichier (voir la liste complète des ensembles de données commerciales Spire Weather)

Pour plus d'informations sur ce qui précède, veuillez vous référer à notre FAQ.

Configuration requise pour Python

Les packages Python suivants sont requis pour ce didacticiel.

Bien que l'utilisation de conda ne soit pas strictement requise, c'est la méthode officiellement recommandée pour installer PyNIO (voir le lien ci-dessous).

Une fois qu'un environnement conda a été créé et activé, les commandes suivantes peuvent être exécutées directement :

Inspection des données

Après avoir téléchargé les données et configuré un environnement Python avec les packages requis, l'étape suivante consiste à inspecter le contenu des données afin de déterminer les variables météorologiques auxquelles il est possible d'accéder. L'inspection des données peut être effectuée uniquement avec PyNIO, mais dans ce didacticiel, nous utiliserons plutôt PyNIO comme moteur pour xarray et chargerons les données dans un ensemble de données xarray pour la transformation. Notez qu'une importation explicite de PyNIO n'est pas requise, tant qu'il est correctement installé dans l'environnement Python actif.

Tout d'abord, importez le package xarray :

Ensuite, ouvrez les données GRIB2 avec xarray en utilisant PyNIO comme moteur (notez que les données GRIB2 doivent provenir de Spire’s Énergie renouvelable paquet de données):

ds = xr.open_dataset("path_to_renewable_energy_file.grib2", engine="pynio")

Enfin, pour chacune des variables, imprimez la clé de recherche, le nom lisible par l'homme et les unités de mesure :

La sortie de ce qui précède devrait ressembler à ceci, donnant un aperçu clair des champs de données disponibles :

Étant donné que ce didacticiel couvre l'utilisation des données GRIB2 à différents niveaux verticaux, nous devons également inspecter le champ level_type :

La sortie de ce qui précède devrait ressembler à ceci :

Notez que trois des variables incluses ont la même valeur level_type d'altitude spécifique au-dessus du niveau moyen de la mer (m) .

Cela signifie que la même méthodologie exacte peut être utilisée pour traiter ces variables à différents niveaux verticaux, bien que pour les besoins de ce didacticiel, nous nous limiterons à examiner uniquement les variables des composantes du vent : UGRD_P0_L103_GLL0 et VGRD_P0_L103_GLL0 .

Comprendre les valeurs de hauteur

Pour mieux comprendre les valeurs de profondeur disponibles, nous pouvons commencer par imprimer des métadonnées pour l'une des variables de composante du vent :
imprimer(ds["UGRD_P0_L103_GLL0"])
La sortie de ce qui précède devrait ressembler à ceci :

À la fin de la première ligne, la liste contient non seulement les noms d'index lat_0 et lon_0 auxquels nous nous attendrions après le didacticiel de base, mais aussi un nouveau appelé lv_HTGL0 .
Nous savons d'après notre déclaration d'impression précédente que lv_HTGL0 fait référence au niveau de hauteur spécifié au-dessus du sol (m) , et la quatrième ligne de la dernière sortie d'impression fournit un aperçu des valeurs lv_HTGL0. A partir de ces informations, nous pouvons deviner qu'il existe un troisième index pour ces données appelé lv_HTGL0 qui correspond à la hauteur des données en mètres.
Nous pouvons imprimer des métadonnées sur un index avec la même méthode que celle utilisée pour inspecter les variables :
imprimer(ds["lv_HTGL0"])
La sortie de ce qui précède devrait ressembler à ceci :

La première ligne de la sortie nous indique qu'il existe trois valeurs possibles, exprimées sous la forme (lv_HTGL0: 3) , et la deuxième ligne nous indique quelles sont ces valeurs : [ 80., 100., 120.]
Cela signifie que pour chaque paire unique de coordonnées lat_0 et lon_0, il existe trois valeurs de niveau vertical distinctes (c'est-à-dire la hauteur) qui peuvent être récupérées en spécifiant une valeur lv_HTGL0 de 80 , 100 ou 120 .

Traitement des données

Maintenant que nous savons quelles variables météorologiques et quels niveaux verticaux sont inclus dans les données GRIB2, nous pouvons commencer à traiter notre jeu de données xarray.

Filtrage des données xarray vers une variable spécifique

Avec xarray , le filtrage du contenu de l'ensemble de données sur nos variables d'intérêt s'effectue en spécifiant un tableau de chaînes :

Il est recommandé d'effectuer cette étape avant de convertir le jeu de données xarray en un DataFrame pandas (plutôt que de filtrer le DataFrame ultérieurement), car cela minimise la taille des données à convertir et réduit donc le temps d'exécution global.

Conversion des données xarray en pandas.DataFrame

Pour convertir l'ensemble de données xarray filtré en un DataFrame pandas, exécutez simplement la commande suivante :

Filtrage des pandas.DataFrame à une hauteur spécifique

En utilisant les informations recueillies auprès du Comprendre les valeurs de hauteur section, nous pouvons maintenant filtrer le DataFrame à une hauteur spécifique.

La première chose que nous faisons est de copier les valeurs d'index de hauteur (en mètres) dans une nouvelle colonne DataFrame :

Ensuite, nous créons l'expression que nous utiliserons pour filtrer le DataFrame.

Nous pouvons filtrer les données des composantes du vent jusqu'à une hauteur de 100 mètres avec l'expression suivante :

height_filter = (df["hauteur"] == 100)

Enfin, nous appliquons le filtre au DataFrame :

Notre DataFrame a maintenant été filtré pour n'inclure que les données des composantes du vent à une hauteur de 100 mètres.

Chargement d'un fichier GeoJSON avec le package GDAL Python

Bien que le package que nous avons installé avec conda s'appelle gdal , nous l'importons dans Python sous le nom osgeo . Il s'agit de l'abréviation de l'Open Source Geospatial Foundation, par laquelle GDAL/OGR (un logiciel libre et open source) est concédé sous licence.

Pour charger les données GeoJSON dans GDAL, nous utilisons simplement la fonction CreateGeometryFromJSON de GDAL :

Le format GeoJSON est un standard courant dans le monde des systèmes d'information géographique. De nombreuses régions GeoJSON préexistantes peuvent être téléchargées gratuitement en ligne (par exemple, les frontières nationales, les zones économiques exclusives, etc.) et des formes personnalisées peuvent également être créées dans une variété d'outils logiciels gratuits, tels que geojson.io ou geoman.io. Pour ce didacticiel, nous utilisons le pays de l'Italie comme polygone complexe, mais cela pourrait tout aussi bien être l'étendue d'une ferme ou d'une autre zone sous-régionale.

Lors du chargement de données GeoJSON dans GDAL, seule la section de géométrie de la fonctionnalité est nécessaire. Voici un exemple simple de ce que le fichier d'entrée GeoJSON pourrait contenir :

Le fichier GeoJSON peut être chargé dans Python à l'aide du package json standard, et doit ensuite être converti en une chaîne Python :

Une fois que nous avons chargé notre définition GeoJSON dans une chaîne Python, nous pouvons créer un objet de géométrie GDAL comme celui-ci :

Obtenir le cadre de délimitation qui contient une zone GeoJSON

Finalement, nous recadrerons les données dans la zone précise définie par le fichier GeoJSON, mais il s'agit d'un processus coûteux en calcul, il est donc préférable de limiter d'abord la taille des données. En théorie, nous pourrions sauter complètement l'étape du recadrage dans une simple boîte, mais en pratique, cela vaut la peine de le faire pour réduire le temps d'exécution global.

GDAL facilite le calcul de la boîte englobante grossière qui contient une zone GeoJSON complexe :

Les valeurs de coordonnées sont ensuite accessibles individuellement à partir du tableau résultant :

L'ordre des coordonnées géospatiales est une source courante de confusion, alors prenez soin de noter que la fonction GetEnvelope de GDAL renvoie un tableau où les valeurs de longitude précèdent les valeurs de latitude.

Recadrage du pandas.DataFrame dans un cadre de délimitation géospatial

Maintenant que les données filtrées sont converties en un DataFrame pandas et que nous avons les limites contenant notre zone d'intérêt, nous pouvons recadrer les données dans une simple boîte.

La première étape de ce processus consiste à décompresser les valeurs de latitude et de longitude de l'index DataFrame’s, accessible via les noms d'index lat_0 et lon_0 :

Bien que les valeurs de latitude soient déjà dans la plage standard de -90 dégresser à +90 degrés, les valeurs de longitude sont dans la plage de 0 à +360.

Pour faciliter l'utilisation des données, nous convertissons les valeurs de longitude dans la plage standard de -180 degrés à +180 degrés:

Avec les données de latitude et de longitude maintenant dans les plages de valeurs souhaitées, nous pouvons les stocker en tant que nouvelles colonnes dans notre DataFrame existant :

Ensuite, nous utilisons les valeurs de la zone de délimitation de la section précédente (les composants du tableau bbox) pour construire les expressions de filtre DataFrame :

Enfin, nous appliquons les filtres à notre DataFrame existant :

Le DataFrame résultant a été rogné aux limites de la boîte qui contient la zone GeoJSON complexe.

Recadrage du pandas.DataFrame aux limites précises d'une zone GeoJSON

Afin de recadrer le DataFrame aux limites précises de la zone GeoJSON complexe, nous devrons vérifier chaque paire de coordonnées dans nos données. Semblable à la section précédente où nous avons remappé chaque valeur de longitude, nous effectuerons cette action avec une expression de carte.

Pour passer chaque paire de coordonnées dans la fonction de carte, nous créons une nouvelle colonne DataFrame appelée point où chaque valeur est un tuple contenant à la fois la latitude et la longitude :

Nous pouvons ensuite passer chaque valeur de tuple de paire de coordonnées dans la fonction map, avec la zone GeoJSON précédemment chargée, et les traiter dans une fonction appelée check_point_in_area que nous définirons ci-dessous. La fonction check_point_in_area retournera True ou False pour indiquer si la paire de coordonnées fournie est à l'intérieur de la zone ou non. En conséquence, nous allons nous retrouver avec une nouvelle colonne DataFrame de valeurs booléennes appelée inArea :

Une fois que la colonne inArea est remplie, nous effectuons un filtre simple pour supprimer les lignes où la valeur inArea est False . Cela supprime efficacement les données de tous les emplacements de points qui ne se trouvent pas dans la zone GeoJSON :

Bien sûr, le succès de ce qui précède dépend de la logique à l'intérieur de la fonction check_point_in_area, que nous n'avons pas encore implémentée. Étant donné que la zone GeoJSON a été chargée avec GDAL, nous pouvons tirer parti d'une méthode de géométrie GDAL appelée Contains pour vérifier rapidement si la zone contient un point spécifique. Pour ce faire, la paire de coordonnées doit d'abord être convertie en une géométrie wkbPoint dans GDAL :

Une fois que nous avons notre géométrie wkbPoint, nous la passons simplement dans la méthode area.Contains pour vérifier si la zone contient le point :

En rassemblant les pièces, voici ce que nous obtenons pour notre dernière fonction check_point_in_area :

Comme vous pouvez le voir, la seule variable renvoyée par la fonction check_point_in_area est une valeur booléenne indiquant si le point spécifié est dans la zone ou non. Ces valeurs booléennes remplissent ensuite la nouvelle colonne inArea DataFrame. Cela nous permet d'appliquer le filtre d'en haut et d'obtenir les données recadrées avec précision que nous voulons :

Calcul de la vitesse et de la direction du vent à partir des composantes du vent

Maintenant que les données ont été recadrées dans notre zone d'intérêt, en réduisant la taille totale de nos points de données, nous pouvons calculer la vitesse et la direction du vent à partir des valeurs des composantes du vent vers l'est (U) et le nord (V).

Tout d'abord, nous devons importer certaines fonctions utilitaires du module mathématique de Python :

Ensuite, la vitesse du vent peut être calculée avec les éléments suivants :

La direction du vent peut être calculée comme suit :

Notez que les valeurs renvoyées par la fonction wind_direction_from_u_v se réfèrent à la représentation météorologique de la direction du vent en degrés :

Afin d'appliquer ces fonctions à tous les points de données de notre DataFrame, nous devons utiliser des fonctions lambda :

Une fois les fonctions lambda définies, nous pouvons les appliquer au DataFrame et mapper leur sortie sur de nouvelles colonnes de données :

Nous avons maintenant de nouvelles colonnes de données appelées vitesse et direction du vent qui contiennent les valeurs calculées pour chaque emplacement.

Analyser l'heure de prévision à partir du nom de fichier

Chaque fichier individuel contient des données de prévisions météorologiques mondiales pour le même moment.

En utilisant nos connaissances de la Comprendre les noms de fichiers section de ce didacticiel, et en supposant que l'argument du nom de fichier est dans le format attendu, nous pouvons écrire une fonction pour analyser l'heure de prévision valide à partir du nom de fichier :

Ensuite, nous pouvons créer une nouvelle colonne DataFrame pour le temps qui stocke cette valeur sous forme de chaîne dans chaque ligne :

Bien qu'il puisse sembler inutile de stocker la même valeur d'horodatage exacte dans chaque ligne, il s'agit d'une étape importante si nous voulons éventuellement concaténer notre DataFrame avec des données de prévision pour d'autres moments (démontré ci-dessous dans Traitement de plusieurs fichiers de données).

Enregistrement des données dans un fichier de sortie CSV

Effectuez un filtre final sur notre DataFrame pour sélectionner uniquement les colonnes que nous voulons dans notre sortie :

Enregistrez le DataFrame traité dans un fichier CSV de sortie :

La définition du paramètre index=False garantit que les colonnes d'index DataFrame ne sont pas incluses dans la sortie. De cette façon, nous excluons les valeurs lat_0 , lon_0 et lv_HTGL0 car nous avons déjà des colonnes pour la latitude et la longitude remappées (et toutes les données restantes sont à la même hauteur après notre filtrage).

Veuillez noter que la conversion de GRIB2 en CSV peut entraîner fichiers de très grande taille, en particulier si les données ne sont pas rognées ou filtrées de manière significative.

Traitement de plusieurs fichiers de données

Il est souvent souhaitable de traiter plusieurs fichiers de données à la fois, afin de combiner les résultats en un seul fichier de sortie CSV unifié.

Par exemple, disons que nous venons d'utiliser l'API Spire Weather pour télécharger une prévision complète de données GRIB2 dans un répertoire local appelé Forecast_data/ . Nous pouvons ensuite lire ces noms de fichiers dans une liste et les trier par ordre alphabétique pour faire bonne mesure :

À partir de là, nous pouvons parcourir les noms de fichiers et passer chacun d'eux dans une fonction qui exécute les étapes décrites dans le Traitement des données section de ce tutoriel.

Une fois que tous nos DataFrames finaux sont prêts, nous pouvons utiliser des pandas pour les concaténer comme ceci (où final_dataframes est une liste de DataFrames) :

Nous nous retrouvons avec un DataFrame combiné appelé output_df que nous pouvons enregistrer dans un fichier CSV de sortie comme nous l'avons fait auparavant :

Code complet

Vous trouverez ci-dessous un script Python opérationnel qui utilise les techniques décrites dans ce didacticiel et comprend également des commentaires explicatifs en ligne.

Le script prend trois arguments (les noms des variables des composants du vent sont codés en dur dans le script) :

Le répertoire local où sont stockées les données Météo Energies Renouvelables GRIB2

Le chemin d'accès au fichier GeoJSON définissant la zone d'intérêt

La valeur d'index de hauteur pour filtrer les données à un seul niveau vertical ( 80 , 100 ou 120 )

Par exemple, le script peut être exécuté comme ceci :

python script.py --source-data grib_directory/ --geojson italie.json --height 100

Voici le code complet :

Notes finales

En utilisant la sortie de données CSV de notre script final, nous pouvons maintenant facilement visualiser les données traitées dans un outil gratuit tel que kepler.gl. Nous pouvons également définir des seuils pour les alertes, générer des statistiques ou fusionner avec d'autres ensembles de données.

Spire Weather propose également des visualisations pré-créées via l'API Web Map Service (WMS) dont vous pouvez en savoir plus ici.

Pour des exemples de code supplémentaires, consultez le référentiel GitHub public de Spire Weather.

Vous souhaitez réserver une consultation ?

En savoir plus sur nos API météo et comment Spire Weather peut vous aider à tirer parti de l'avantage des données.


Comment traiter les données météorologiques GRIB2 pour les applications agricoles (GeoJSON)

Écrit par
Elliott Wobler
Ingénieur de solutions techniques

Ce didacticiel explique comment utiliser les données de prévision globales de Spire Weather au format GRIB2 à l'aide de Python.

Ce tutoriel utilise l'entrée GeoJSON.

Aperçu

Ce didacticiel explique comment utiliser les données de prévision mondiales de Spire Weather au format GRIB2 à l'aide de Python.

Si vous n'avez jamais travaillé avec des données GRIB2 auparavant, il est recommandé de commencer par le didacticiel de démarrage, car celui-ci abordera des sujets légèrement plus avancés.

Plus précisément, ce didacticiel montre comment récupérer des données sur l'humidité du sol à différentes profondeurs dans les limites d'un polygone complexe (par exemple, une frontière nationale).

À la fin de ce tutoriel, vous saurez comment :

  1. Charger des fichiers contenant des messages GRIB2 dans un programme Python
  2. Inspectez les données GRIB2 pour comprendre quelles variables météorologiques sont incluses
  3. Filtrez les données GRIB2 sur les variables météorologiques d'intérêt à différentes profondeurs
  4. Recadrer les données GRIB2 à la zone définie par une entrée de fichier GeoJSON
  5. Convertissez les données GRIB2 transformées en un fichier de sortie CSV pour une analyse et une visualisation plus poussées

Téléchargement des données

La première étape consiste à télécharger les données de l'API de fichier de Spire Weather.

Ce didacticiel s'attend à ce que les messages GRIB2 contiennent des données NWP du paquet de données agricoles de Spire.

Pour plus d'informations sur l'utilisation des points de terminaison de l'API de fichier Spire Weather’s, veuillez consulter la documentation de l'API et la FAQ.

La FAQ contient également des exemples détaillés expliquant comment télécharger plusieurs fichiers de prévision à la fois à l'aide de cURL.

Pour les besoins de ce didacticiel, il est supposé que les données GRIB2 ont déjà été téléchargées avec succès, sinon obtenez un échantillon ici.

Comprendre les noms de fichiers

Les fichiers téléchargés à partir des produits API de Spire Weather partagent tous la même convention de dénomination de fichier.

En regardant simplement le nom du fichier, nous pouvons déterminer :

  • la date et l'heure d'émission de la prévision
  • la date et l'heure de validité des données prévisionnelles
  • la résolution horizontale des données de prévision globales
  • les variables de données météorologiques incluses dans le fichier (voir la liste complète des ensembles de données commerciales Spire Weather)

Pour plus d'informations sur ce qui précède, veuillez vous référer à notre FAQ.

Configuration requise pour Python

Les packages Python suivants sont requis pour ce didacticiel.

Bien que l'utilisation de conda ne soit pas strictement requise, c'est la méthode officiellement recommandée pour installer PyNIO (voir le lien ci-dessous).

Une fois qu'un environnement conda a été créé et activé, les commandes suivantes peuvent être exécutées directement :

Inspection des données

Après avoir téléchargé les données et configuré un environnement Python avec les packages requis, l'étape suivante consiste à inspecter le contenu des données afin de déterminer les variables météorologiques auxquelles il est possible d'accéder. L'inspection des données peut être effectuée uniquement avec PyNIO, mais dans ce didacticiel, nous utiliserons plutôt PyNIO comme moteur pour xarray et chargerons les données dans un ensemble de données xarray pour la transformation. Notez qu'une importation explicite de PyNIO n'est pas requise, tant qu'il est correctement installé dans l'environnement Python actif.

Tout d'abord, importez le package xarray :

Ensuite, ouvrez les données GRIB2 avec xarray en utilisant PyNIO comme moteur (notez que les données GRIB2 doivent provenir de Spire’s Agricole paquet de données):

ds = xr.open_dataset("chemin_vers_fichier_agricole.grib2", engine="pynio")

Enfin, pour chacune des variables, imprimez la clé de recherche, le nom lisible par l'homme et les unités de mesure :

La sortie de ce qui précède devrait ressembler à ceci, donnant un aperçu clair des champs de données disponibles :

Étant donné que ce didacticiel couvre l'utilisation des données GRIB2 à différents niveaux verticaux, nous devons également inspecter le champ level_type :

La sortie de ce qui précède devrait ressembler à ceci :

Notez que lv_DBLL0_l0 et lv_DBLL0_l1 sont maintenant absents de la sortie. C'est parce qu'il s'agit de champs spéciaux contenant des données décrivant les plages de profondeur disponibles. Nous reviendrons sur ces deux champs dans la section suivante : Comprendre les valeurs de profondeur.

Une autre chose à souligner ici est que SOILW_P0_2L106_GLL0 et TSOIL_P0_2L106_GLL0 ont la même valeur level_type. Cela signifie que la même méthodologie exacte peut être utilisée pour traiter l'humidité ou la température du sol à différentes profondeurs, bien que pour les besoins de ce didacticiel, nous nous en tiendrons à l'humidité du sol uniquement.

Comprendre les valeurs de profondeur

Pour mieux comprendre les valeurs de profondeur disponibles, nous pouvons commencer par imprimer des métadonnées pour la variable d'humidité du sol :
imprimer(ds["SOILW_P0_2L106_GLL0"])
La sortie de ce qui précède devrait ressembler à ceci :

À la fin de la première ligne, la liste contient non seulement les noms d'index lat_0 et lon_0 auxquels nous nous attendrions après le didacticiel de base, mais aussi un nouveau appelé lv_DBLL0 .
Nous savons d'après notre déclaration d'impression précédente que lv_DBLL0 fait référence à la profondeur sous la surface du sol , et la sixième ligne de la dernière sortie d'impression nous indique que lv_DBLL0 est une dimension sans coordonnées. À partir de ces informations, nous pouvons deviner qu'il existe un troisième indice pour ces données appelé lv_DBLL0 qui indique le niveau de profondeur dans le sol auquel les données d'humidité correspondent.
Nous pouvons imprimer des métadonnées sur un index avec la même méthode que celle utilisée pour inspecter les variables :
print(ds["lv_DBLL0"])
La sortie de ce qui précède devrait ressembler à ceci :

La première ligne de la sortie nous indique qu'il existe quatre valeurs possibles, exprimées sous la forme (lv_DBLL0: 4) , et la deuxième ligne nous indique quelles sont ces valeurs : [0, 1, 2, 3]
Cela signifie que pour chaque paire unique de coordonnées lat_0 et lon_0, il existe quatre valeurs d'humidité du sol distinctes qui peuvent être récupérées en spécifiant une valeur lv_DBLL0 de 0 , 1 , 2 ou 3 .
Afin de déterminer à quelles plages de profondeur ces valeurs d'index correspondent réellement, nous devons approfondir nos recherches en inspectant les variables associées à partir de notre sortie d'impression initiale : lv_DBLL0_l0 et lv_DBLL0_l1
imprimer(ds["lv_DBLL0_l0"])
La sortie de ce qui précède devrait ressembler à ceci :

On peut alors faire de même pour la variable lv_DBLL0_l1 :
imprimer(ds["lv_DBLL0_l1"])
La sortie de ce qui précède devrait ressembler à ceci :

Ce que cela nous dit, c'est que :

une valeur lv_DBLL0 de 0 correspond à une valeur lv_DBLL0_l0 de 0,0 mètre et une valeur lv_DBLL0_l1 de 0,1 mètre

une valeur lv_DBLL0 de 1 correspond à une valeur lv_DBLL0_l0 de 0,1 mètre et une valeur lv_DBLL0_l1 de 0,4 mètre

une valeur lv_DBLL0 de 2 correspond à une valeur lv_DBLL0_l0 de 0,4 mètre et une valeur lv_DBLL0_l1 de 1,0 mètre

une valeur lv_DBLL0 de 3 correspond à une valeur lv_DBLL0_l0 de 1,0 mètre et une valeur lv_DBLL0_l1 de 2,0 mètres

une valeur lv_DBLL0 de 1 correspond à une profondeur de 10 cm à 40 cm

une valeur lv_DBLL0 de 2 correspond à une profondeur de 40 cm à 100 cm

une valeur lv_DBLL0 de 3 correspond à une profondeur de 100 cm à 200 cm

Traitement des données

Maintenant que nous savons quelles variables météorologiques et quels niveaux verticaux sont inclus dans les données GRIB2, nous pouvons commencer à traiter notre jeu de données xarray.

Filtrage des données xarray vers une variable spécifique

Avec xarray , le filtrage du contenu de l'ensemble de données sur une seule variable d'intérêt est très simple :

La sélection de plusieurs variables est également possible en utilisant un tableau de chaînes en entrée : ds = ds.get([var1, var2])

Il est recommandé d'effectuer cette étape avant de convertir le jeu de données xarray en un DataFrame pandas (plutôt que de filtrer le DataFrame ultérieurement), car cela minimise la taille des données à convertir et réduit donc le temps d'exécution global.

Conversion des données xarray en pandas.DataFrame

Pour convertir l'ensemble de données xarray filtré en un DataFrame pandas, exécutez simplement la commande suivante :

Filtrage des pandas.DataFrame à une plage de profondeur spécifique

En utilisant les informations recueillies auprès du Comprendre les valeurs de profondeur section, nous pouvons maintenant filtrer le DataFrame sur une plage de profondeur spécifique.

La première chose que nous faisons est de copier les valeurs d'index de profondeur dans une nouvelle colonne DataFrame :

Ensuite, nous créons l'expression que nous utiliserons pour filtrer le DataFrame.

Nous savons d'après notre analyse précédente qu'une valeur lv_DBLL0 de 0 correspond à une profondeur de 0 cm à 10 cm.

Par conséquent, nous pouvons filtrer les données d'humidité du sol sur une plage de profondeur de 0 à 10 cm avec l'expression suivante :

Enfin, nous appliquons le filtre au DataFrame :

Notre DataFrame a maintenant été filtré pour n'inclure que les données d'humidité du sol à une profondeur de 0 à 10 cm.

Chargement d'un fichier GeoJSON avec le package GDAL Python

Bien que le package que nous avons installé avec conda s'appelle gdal , nous l'importons dans Python sous le nom osgeo . Il s'agit de l'abréviation de l'Open Source Geospatial Foundation, par laquelle GDAL/OGR (un logiciel libre et open source) est concédé sous licence.

Pour charger les données GeoJSON dans GDAL, nous utilisons simplement la fonction CreateGeometryFromJSON de GDAL :

Le format GeoJSON est un standard courant dans le monde des systèmes d'information géographique. De nombreuses régions GeoJSON préexistantes peuvent être téléchargées gratuitement en ligne (par exemple, les frontières nationales, les zones économiques exclusives, etc.) et des formes personnalisées peuvent également être créées dans une variété d'outils logiciels gratuits, tels que geojson.io ou geoman.io. Pour ce didacticiel, nous utilisons le pays de l'Italie comme polygone complexe, mais cela pourrait tout aussi bien être l'étendue d'une ferme ou d'une autre zone sous-régionale.

Lors du chargement de données GeoJSON dans GDAL, seule la section de géométrie de la fonctionnalité est nécessaire. Voici un exemple simple de ce que le fichier d'entrée GeoJSON pourrait contenir :

Le fichier GeoJSON peut être chargé dans Python à l'aide du package json standard, et doit ensuite être converti en une chaîne Python :

Une fois que nous avons chargé notre définition GeoJSON dans une chaîne Python, nous pouvons créer un objet de géométrie GDAL comme celui-ci :

Obtenir le cadre de délimitation qui contient une zone GeoJSON

Finalement, nous recadrerons les données dans la zone précise définie par le fichier GeoJSON, mais il s'agit d'un processus coûteux en calcul, il est donc préférable de limiter d'abord la taille des données. En théorie, nous pourrions sauter complètement l'étape du recadrage dans une simple boîte, mais en pratique, cela vaut la peine de le faire pour réduire le temps d'exécution global.

GDAL facilite le calcul de la boîte englobante grossière qui contient une zone GeoJSON complexe :

Les valeurs de coordonnées sont ensuite accessibles individuellement à partir du tableau résultant :

L'ordre des coordonnées géospatiales est une source courante de confusion, alors prenez soin de noter que la fonction GetEnvelope de GDAL renvoie un tableau où les valeurs de longitude précèdent les valeurs de latitude.

Recadrage du pandas.DataFrame dans un cadre de délimitation géospatial

Maintenant que les données filtrées sont converties en un DataFrame pandas et que nous avons les limites contenant notre zone d'intérêt, nous pouvons recadrer les données dans une simple boîte.

La première étape de ce processus consiste à décompresser les valeurs de latitude et de longitude de l'index DataFrame’s, accessible via les noms d'index lat_0 et lon_0 :

Bien que les valeurs de latitude soient déjà dans la plage standard de -90 dégresser à +90 degrés, les valeurs de longitude sont dans la plage de 0 à +360.

Pour faciliter l'utilisation des données, nous convertissons les valeurs de longitude dans la plage standard de -180 degrés à +180 degrés:

Avec les données de latitude et de longitude maintenant dans les plages de valeurs souhaitées, nous pouvons les stocker en tant que nouvelles colonnes dans notre DataFrame existant :

Ensuite, nous utilisons les valeurs de la zone de délimitation de la section précédente (les composants du tableau bbox) pour construire les expressions de filtre DataFrame :

Enfin, nous appliquons les filtres à notre DataFrame existant :

Le DataFrame résultant a été rogné aux limites de la boîte qui contient la zone GeoJSON complexe.

Recadrage du pandas.DataFrame aux limites précises d'une zone GeoJSON

Afin de recadrer le DataFrame aux limites précises de la zone GeoJSON complexe, nous devrons vérifier chaque paire de coordonnées dans nos données. Semblable à la section précédente où nous avons remappé chaque valeur de longitude, nous effectuerons cette action avec une expression de carte.

Pour transmettre chaque paire de coordonnées à la fonction de carte, nous créons une nouvelle colonne DataFrame appelée point où chaque valeur est un tuple contenant à la fois la latitude et la longitude :

Nous pouvons ensuite passer chaque valeur de tuple de paire de coordonnées dans la fonction map, avec la zone GeoJSON précédemment chargée, et les traiter dans une fonction appelée check_point_in_area que nous définirons ci-dessous. La fonction check_point_in_area retournera True ou False pour indiquer si la paire de coordonnées fournie est à l'intérieur de la zone ou non. En conséquence, nous allons nous retrouver avec une nouvelle colonne DataFrame de valeurs booléennes appelée inArea :

Une fois que la colonne inArea est remplie, nous effectuons un filtre simple pour supprimer les lignes où la valeur inArea est False . Cela supprime efficacement les données de tous les emplacements de points qui ne se trouvent pas dans la zone GeoJSON :

Bien sûr, le succès de ce qui précède dépend de la logique à l'intérieur de la fonction check_point_in_area, que nous n'avons pas encore implémentée. Étant donné que la zone GeoJSON a été chargée avec GDAL, nous pouvons tirer parti d'une méthode de géométrie GDAL appelée Contains pour vérifier rapidement si la zone contient un point spécifique. Pour ce faire, la paire de coordonnées doit d'abord être convertie en une géométrie wkbPoint dans GDAL :

Once we have our wkbPoint geometry, we simply pass it into the area.Contains method to check if the area contains the point:

Putting the pieces together, here is what we get for our final check_point_in_area function:

As you can see, the only variable returned by the check_point_in_area function is a boolean value indicating whether the specified point is in the area or not. These boolean values then populate the new inArea DataFrame column. This allows us to apply the filter from above and end up with the precisely cropped data we want:

Parsing the forecast time from the filename

Each individual file contains global weather forecast data for the same point in time.

Using our knowledge from the Understanding Filenames section of this tutorial, and assuming that the filename argument is in the expected format, we can write a function to parse the valid forecast time from the filename:

Then, we can create a new DataFrame column for time which stores this value as a string in every row:

Although it may seem unnecessary to store the same exact timestamp value in every row, this is an important step if we want to eventually concatenate our DataFrame with forecast data for other times (demonstrated below in Processing Multiple Data Files).

Saving the data to a CSV output file

Perform a final filter on our DataFrame to select only the columns that we want in our output, where variable is a string like "SOILW_P0_2L106_GLL0" :

Save the processed DataFrame to an output CSV file:

Setting the index=False parameter ensures that the DataFrame index columns are not included in the output. This way, we exclude the lat_0 , lon_0 , and lv_DBLL0 values since we already have columns for latitude and remapped longitude (and all remaining data is at the same depth after our filtering).

Please note that converting from GRIB2 to CSV can result in very large file sizes, especially if the data is not significantly cropped or filtered.

Processing Multiple Data Files

It is often desirable to process multiple data files at once, in order to combine the results into a single unified CSV output file.

For example, let’s say that we have just used the Spire Weather API to download a full forecast’s worth of GRIB2 data into a local directory called forecast_data/ . We can then read those filenames into a list and sort them alphabetically for good measure:

From here, we can iterate through the filenames and pass each one into a function that performs the steps outlined in the Processing the Data section of this tutorial.

Once all of our final DataFrames are ready, we can use pandas to concatenate them together like so (where final_dataframes is a list of DataFrames):

We end up with a combined DataFrame called output_df which we can save to an output CSV file like we did before:

Complete Code

Below is an operational Python script which uses the techniques described in this tutorial and also includes explanatory in-line comments.

The script takes four arguments:

The weather data variable of interest ( SOILW_P0_2L106_GLL0 or TSOIL_P0_2L106_GLL0 )

The local directory where the Agricultural Weather GRIB2 data is stored

The path to the GeoJSON file defining the area of interest

The depth range index value for filtering the data to a single vertical level ( 0 , 1 , 2 , or 3 )

For example, the script can be run like this:

python script.py --variable SOILW_P0_2L106_GLL0 --source-data grib_directory/ --geojson italy.json --depth 0

Here is the complete code:

Final Notes

Using the CSV data output from our final script, we can now easily visualize the processed data in a free tool such as kepler.gl. We can also set thresholds for alerts, generate statistics, or fuse with other datasets.

The visualization included below – originally featured in a Spire data story – was created with Kepler using the techniques covered in this tutorial. Spire Weather also offers pre-created visualizations through the Web Map Service (WMS) API which you can read more about here.

For additional code samples, check out Spire Weather’s public GitHub repository.


OpenLayers.Map

Instances of OpenLayers.Map are interactive maps embedded in a web page. Create a new map with the OpenLayers.Map constructor.

On their own maps do not provide much functionality. To extend a map it&rsquos necessary to add controls (OpenLayers.Control) and layers (OpenLayers.Layer) to the map.

OpenLayers.MapInstances of OpenLayers.Map are interactive maps embedded in a web page.
Constants
Z_INDEX_BASE Base z-indexes for different classes of thing
EVENT_TYPES Supported application event types.
Propriétés
events An events object that handles all events on the map
allOverlays Allow the map to function with &ldquooverlays&rdquo only.
div The element that contains the map (or an id for that element).
couches Ordered list of layers in the map
baseLayer The currently selected base layer.
tileSize Set in the map options to override the default tile size for this map.
projection Set in the map options to override the default projection string this map - also set maxExtent, maxResolution, and units if appropriate.
unités The map units.
resolutions A list of map resolutions (map units per pixel) in descending order.
maxResolution Default max is 360 deg / 256 px, which corresponds to zoom level 0 on gmaps.
minResolution
maxEchelle
minÉchelle
maxExtent The maximum extent for the map.
minExtent
restrictedExtent Limit map navigation to this extent where possible.
numZoomLevels Number of zoom levels for the map.
thème Relative path to a CSS file from which to load theme styles.
displayProjection Requires proj4js support.Projection used by several controls to display data to user.
fallThrough Should OpenLayers allow events on the map to fall through to other elements on the page, or should it swallow them?
eventListeners If set as an option at construction, the eventListeners object will be registered with <OpenLayers.Events.on>.
panMethod The Easing function to be used for tweening.
Constructeur
OpenLayers.MapConstructor for a new OpenLayers.Map instance.
Les fonctions
rendreRender the map to a specified container.
détruireDestroy this map
setOptionsChange the map options
getTileSizeGet the tile size for the map
getByGet a list of objects given a property and a match item.
getLayersByGet a list of layers with properties matching the given criteria.
getLayersByNameGet a list of layers with names matching the given name.
getLayersByClassGet a list of layers of a given class (CLASS_NAME).
getControlsByGet a list of controls with properties matching the given criteria.
getControlsByClassGet a list of controls of a given class (CLASS_NAME).
getLayerGet a layer based on its id
addLayer
addLayers
removeLayerRemoves a layer from the map by removing its visual element (the layer.div property), then removing it from the map&rsquos internal list of layers, setting the layer&rsquos map property to null.
getNumLayers The number of layers attached to the map.
getLayerIndex
setLayerIndexMove the given layer to the specified (zero-based) index in the layer list, changing its z-index in the map display.
raiseLayerChange the index of the given layer by delta.
setBaseLayerAllows user to specify one of the currently-loaded layers as the Map&rsquos new base layer.
addControl
getControl
removeControlRemove a control from the map.
addPopup
removePopup
getSize An OpenLayers.Size object that represents the size, in pixels, of the div into which OpenLayers has been loaded.
updateSizeThis function should be called by any external code which dynamically changes the size of the map div (because mozilla wont let us catch the &ldquoonresize&rdquo for an element)
getCenter
getZoom
poêleAllows user to pan by a value of screen pixels
panToAllows user to pan to a new lonlat If the new lonlat is in the current extent the map will slide smoothly
setCenterSet the map center (and optionally, the zoom level).
getProjectionThis method returns a string representing the projection.
getProjectionObjectReturns the projection obect from the baselayer.
getMaxResolution The Map&rsquos Maximum Resolution
getMaxExtent
getNumZoomLevels The total number of zoom levels that can be displayed by the current baseLayer.
getExtent A Bounds object which represents the lon/lat bounds of the current viewPort.
getResolution The current resolution of the map.
getUnits The current units of the map.
getScale The current scale denominator of the map.
getZoomForExtent
getResolutionForZoom
getZoomForResolution
zoomToZoom to a specific zoom level
zoomIn
zoomOut
zoomToExtentZoom to the passed in bounds, recenter
zoomToMaxExtentZoom to the full extent and recenter.
zoomToScaleZoom to a specified scale
getViewPortPxFromLonLat
getLonLatFromPixel
getPixelFromLonLatReturns a pixel location given a map location.
getViewPortPxFromLayerPx
getLayerPxFromViewPortPx
getLayerPxFromLonLat
Constants
TILE_WIDTH 256 Default tile width (unless otherwise specified)
TILE_HEIGHT 256 Default tile height (unless otherwise specified)

Constants

Z_INDEX_BASE

Base z-indexes for different classes of thing

EVENT_TYPES

Supported application event types. Register a listener for a particular event with the following syntax:

Listeners will be called with a reference to an event object. The properties of this event depends on exactly what happened.

All event objects have at least the following properties

  • objetA reference to map.events.object.
  • élémentA reference to map.events.element.

Browser events have the following additional properties

  • xy The pixel location of the event (relative to the the map viewport).
  • other properties that come with browser events

Supported map event types

  • preaddlayer triggered before a layer has been added. The event object will include a couche property that references the layer to be added.
  • addlayer triggered after a layer has been added. The event object will include a couche property that references the added layer.
  • removelayer triggered after a layer has been removed. The event object will include a couche property that references the removed layer.
  • changelayer triggered after a layer name change, order change, opacity change or visibility change (due to resolution thresholds). Listeners will receive an event object with couche et biens Propriétés. Le couche property will be a reference to the changed layer. Le biens property will be a key to the changed property (name, order, opacity or visibility).
  • movestart triggered after the start of a drag, pan, or zoom
  • mouvement triggered after each drag, pan, or zoom
  • déplacer triggered after a drag, pan, or zoom completes
  • zoomer triggered after a zoom completes
  • addmarker triggered after a marker has been added
  • removemarker triggered after a marker has been removed
  • clearmarkers triggered after markers have been cleared
  • survol de la souris triggered after mouseover the map
  • souris triggered after mouseout the map
  • mouvement de la souris triggered after mousemove the map
  • dragstart Does not work. Register for movestart instead.
  • glisser Does not work. Register for move instead.
  • dragend Does not work. Register for moveend instead.
  • changebaselayer triggered after the base layer changes

Propriétés

Events

An events object that handles all events on the map

AllOverlays

Allow the map to function with &ldquooverlays&rdquo only. Defaults to false. If true, the lowest layer in the draw order will act as the base layer. In addition, if set to true, all layers will have isBaseLayer set to false when they are added to the map.

If you set map.allOverlays to true, then you ne peux pas use map.setBaseLayer or layer.setIsBaseLayer. With allOverlays true, the lowest layer in the draw layer is the base layer. So, to change the base layer, use setLayerIndex or raiseLayer to set the layer index to 0.

The element that contains the map (or an id for that element). If the OpenLayers.Map constructor is called with two arguments, this should be provided as the first argument. Alternatively, the map constructor can be called with the options object as the only argument. In this case (one argument), a div property may or may not be provided. If the div property is not provided, the map can be rendered to a container later using the render method.

Note: If you calling render after map construction, do not use maxResolution auto. Instead, divide your maxExtent by your maximum expected dimension.


Grilles

Grid — Visibility of latitude and longitude lines 'on' (default) | on/off logical value

Visibility of latitude and longitude lines on the map, specified as 'on' or 'off' , or as numeric or logical 1 ( true ) or 0 ( false ). A value of 'on' is equivalent to true , and 'off' is equivalent to false . Thus, you can use the value of this property as a logical value. The value is stored as an on/off logical value of type matlab.lang.OnOffSwitchState .

'off' – Do not show grid lines.

Exemple: gx.Grid = 'off'

GridLineStyle — Line style for grid lines '-' (default) | '--' | ':' | '-.' | 'rien'

Line style for grid lines, specified as one of the line styles in this table.

To display the grid lines, use the grid on command or set the Grid property to 'on' .

Exemple: gx.GridLineStyle = '--'

GridColor — Color of grid lines [0.15 0.15 0.15] (default) | RGB triplet | hexadecimal color code | color name | short color name

Background color, specified as an RGB triplet, a hexadecimal color code, a color name, or a short color name.

For a custom color, specify an RGB triplet or a hexadecimal color code.

An RGB triplet is a three-element row vector whose elements specify the intensities of the red, green, and blue components of the color. The intensities must be in the range [0,1] for example, [0.4 0.6 0.7] .

A hexadecimal color code is a character vector or a string scalar that starts with a hash symbol ( # ) followed by three or six hexadecimal digits, which can range from 0 to F . The values are not case sensitive. Thus, the color codes '#FF8800' , '#ff8800' , '#F80' , and '#f80' are equivalent.

Alternatively, you can specify some common colors by name. This table lists the named color options, the equivalent RGB triplets, and hexadecimal color codes.

Here are the RGB triplets and hexadecimal color codes for the default colors MATLAB uses in many types of plots.

For example, create a geographic axis object with red grid lines. Set the GridAlpha property to 0.5 to increase visibility.

Exemple: gx.GridColor = [0 0 1]

Exemple: gx.GridColor = 'b'

Exemple: gx.GridColor = 'blue'

Exemple: gx.GridColor = '#0000FF'

GridColorMode — Property for setting grid color 'auto' (default) | 'manual'

Property for setting the grid color, specified as one of these values:

'auto' — Object automatically selects the color.

'manual' — To set the grid line color for all directions, use GridColor .

GridAlpha — Grid-line transparency 0.15 (default) | value in the range [0,1]

Grid-line transparency, specified as a value in the range [0,1] . A value of 1 means opaque and a value of 0 means completely transparent.

Exemple: gx.GridAlpha = 0.5

GridAlphaMode — Selection mode for GridAlpha 'auto' (default) | 'manual'

Selection mode for the GridAlpha property, specified as one of these values:

'auto' — Object selects the transparency value.

'manual' — To specify the transparency value, use the GridAlpha property.

Exemple: gx.GridAlphaMode = 'auto'


List index out of bounds error

When trying out a proposed solution to my previous question, Displaying multiple names from different objects from a query in VF, while there is no error in the developer console, I am receiving an error when I preview the page. The query without the where portion gets me the data I need (I tested it without the where portion in the query editor), but I believe there is an issue stemming from the portion of the query. The controller is:

How do I make the array index in bounds?

I understand what an array out of bounds error is but what I don't get is the line:

Doesn't the query end after the ] bracket? What is the purpose and meaning of the [0].PartsinProducts__r? I think my issue stems from my lack of understanding of this line of code. Is there nothing in the array? I'm quite sure 0 index of an array indicates the first element in that array.

The controller can be seen in the link but I will put it here anyways:

This is the error message I get from the two huge code blocks above:

The query that I run in the query editor and its results:


The only thing you can do with a class SphericalImage is to project an image onto cube faces. The few functions it has to manipulate the stored image are just there to help with the projection. Instead of using a class , perhaps it is better to just have a single function that takes an image, and splits it into six cube faces. It could look like this:

Basically, you give it an ImageBuf , and you get six ImageBuf s back. You can add additional parameters for your algorithm, like threshold , centerWeighted , possibly with default values. Your main() should then be able to look like:

Note that this doesn't mean you have to put all the functionality inside that function, you can still have helper functions. These should then be made static .


How can I get the values returned by an OpenLayers bounds object in Longitude / Latitude format? - Systèmes d'information géographique

Geocoder is a library which helps you build geo-aware applications. It provides an abstraction layer for geocoding manipulations. The library is split in two parts: HttpAdapter and Provider and is really extensible.

HttpAdapters are responsible to get data from remote APIs.

Currently, there are the following adapters:

  • BuzzHttpAdapter to use Buzz, a lightweight PHP 5.3 library for issuing HTTP requests
  • CurlHttpAdapter to use cURL
  • GuzzleHttpAdapter to use Guzzle, PHP 5.3+ HTTP client and framework for building RESTful web service clients
  • SocketHttpAdapter to use a socket
  • ZendHttpAdapter to use Zend Http Client.

Fournisseurs contain the logic to extract useful information.

Currently, there are many providers for the following APIs:

    as IP-Based geocoding provider as IP-Based geocoding provider as IP-Based geocoding provider (city precision) as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider (based on the Nominatim provider) as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider , the PHP extension, as IP-Based geocoding provider
  • ChainProvider is a special provider that takes a list of providers and iterates over this list to get information as Address-Based geocoding and reverse geocoding provider as very accurate Address-Based geocoding and reverse geocoding provider (exclusively in Denmark) as Address-Based geocoding and reverse geocoding provider (exclusively in USA & Canada) as Address-Based geocoding provider (exclusively in USA) as Address-Based geocoding provider (exclusively in France) as IP-Based geocoding provider or an Address-Based provider (exclusively in USA & Canada) as Address-Based geocoding and reverse geocoding provider as IP-Based geocoding provider as IP-Based geocoding provider as IP-Based geocoding provider (City/ISP/Org and Omni services) as IP-Based geocoding provider as Place-Based geocoding and reverse geocoding provider as IP-Based geocoding provider (very accurate in Russia) as Address-Based geocoding and reverse geocoding provider (exclusively in China) as Address-Based geocoding and reverse geocoding provider as Address-Based geocoding and reverse geocoding provider.

The Geocoder Extra library contains even more providers!

The recommended way to install Geocoder is through composer.

Just create a composer.json file for your project:

Protip: you should browse the willdurand/geocoder page to choose a stable version to use, avoid the @stable meta constraint.

And run these two commands to install it:

Now you can add the autoloader, and you will have access to the library:

If you don't use either Composer ou un ClassLoader in your application, just require the provided autoloader:

First, you need an adapter to query an API:

The BuzzHttpAdapter is tweakable, actually you can pass a Browser object to this adapter:

Now, you have to choose a provider which is closed to what you want to get.

The FreeGeoIpProvider named free_geo_ip is able to geocode IPv4 and IPv6 addresses seulement.

The HostIpProvider named host_ip is able to geocode IPv4 addresses seulement.

The IpInfoDbProvider named ip_info_db is able to geocode IPv4 addresses seulement. A valid api key is required.

The GoogleMapsProvider named google_maps is able to geocode and reverse geocode street addresses.

The GoogleMapsBusinessProvider named google_maps_business is able to geocode and reverse geocode street addresses. A valid Client ID is required. The private key is optional.

The BingMapsProvider named bing_maps is able to geocode and reverse geocode street addresses. A valid api key is required.

The OpenStreetMapProvider named openstreetmap is able to geocode and reverse geocode street addresses.

Avertissement: The OpenStreetMapsProvider is deprecated, and you should rather use the OpenStreetMapProvider . See issue #269.

The NominatimProvider named nominatim is able to geocode and reverse geocode street addresses. Access to a Nominatim server is required. See the Nominatim Wiki Page for more information.

The CloudMadeProvider named cloudmade is able to geocode and reverse geocode street addresses. A valid api key is required.

The GeoipProvider named geoip is able to geocode IPv4 and IPv6 addresses seulement. No need to use an HttpAdapter as it uses a local database. See the MaxMind page for more information.

The ChainProvider named chain is a special provider that takes a list of providers and iterates over this list to get information.

The MapQuestProvider named map_quest is able to geocode and reverse geocode street addresses. A valid api key is required.

The OIORestProvider named oio_rest is able to geocode and reverse geocode street addresses, exclusively in Denmark.

The GeocoderCaProvider named geocoder_ca is able to geocode and reverse geocode street addresses, exclusively in USA & Canada.

The GeocoderUsProvider named geocoder_us is able to geocode street addresses only, exclusively in USA.

The IGNOpenLSProvider named ign_openls is able to geocode street addresses only, exclusively in France. A valid OpenLS api key is required.

The DataScienceToolkitProvider named data_science_toolkit is able to geocode IPv4 addresses et street adresses, exclusively in USA & Canada.

The YandexProvider named yandex is able to geocode and reverse geocode street addresses. The default language-locale is ru-RU , you can choose between uk-UA , be-BY , en-US , en-BR and tr-TR . This provider can also reverse information based on coordinates (latitude, longitude). It's possible to precise the toponym to get more accurate result for reverse geocoding: house , street , metro , district and locality .

The GeoPluginProvider named geo_plugin is able to geocode IPv4 addresses and IPv6 addresses seulement.

The GeoIPsProvider named geo_ips is able to geocode IPv4 addresses seulement. A valid api key is required.

The MaxMindProvider named maxmind is able to geocode IPv4 and IPv6 addresses seulement. A valid City/ISP/Org or Omni service's api key is required. This provider provides two constants CITY_EXTENDED_SERVICE by default and OMNI_SERVICE .

The GeonamesProvider named geonames is able to geocode and reverse geocode places. A valid username is required.

The IpGeoBaseProvider named ip_geo_base is able to geocode IPv4 addresses only, very accurate in Russia.

The BaiduProvider named baidu is able to geocode and reverse geocode street addresses, exclusively in China. A valid api key is required.

The TomTomProvider named tomtom is able to geocode and reverse geocode street addresses. The default langage-locale is en , you can choose between de , es , fr , it , nl , pl , pt and sv . A valid api key is required.

The ArcGISOnlineProvider named arcgis_online is able to geocode and reverse geocode street addresses. It's possible to specify a sourceCountry to restrict result to this specific country thus reducing request time (note that this doesn't work on reverse geocoding). This provider also supports SSL.

You can use one of them or write your own provider. You can also register all providers and decide later. That's we'll do:

  • $locale is available for YandexProvider , BingMapsProvider and TomTomProvider .
  • $region is available for GoogleMapsProvider and GoogleMapsBusinessProvider .
  • $toponym is available for YandexProvider .
  • $service is available for MaxMindProvider .
  • $useSsl is available for GoogleMapsProvider , GoogleMapsBusinessProvider , MaxMindProvider and ArcGISOnlineProvider .
  • $sourceCountry is available for ArcGISOnlineProvider .
  • $rootUrl is available for NominatimProvider .

As said it's a special provider that takes a list of providers and iterates over this list to get information. Note that it s'arrête its iteration when a provider returns a result. The result is returned by GoogleMapsProvider because FreeGeoIpProvider and HostIpProvider cannot geocode street addresses. BingMapsProvider is ignored.

The main method is called geocode() which receives a value to geocode. It can be an IP address or a street address (partial or not).

The geocode() method returns a Geocoded result object with the following API, this object also implements the ArrayAccess interface:

  • getCoordinates() will return an array with latitude and longitude values
  • getLatitude() will return the latitude value
  • getLongitude() will return the longitude value
  • getBounds() will return an array with south , west , north and east values
  • getStreetNumber() will return the street number/house number value
  • getStreetName() will return the street name value
  • getCity() will return the city
  • getZipcode() will return the zipcode
  • getCityDistrict() will return the city district , or sublocality
  • getCounty() will return the county
  • getCountyCode() will return the county code (county short name)
  • getRegion() will return the region
  • getRegionCode() will return the region code (region short name)
  • getCountry() will return the country
  • getCountryCode() will return the ISO country code
  • getTimezone() will return the timezone .

The Geocoder's API is fluent, you can write:

The using() method allows you to choose the provider to use by its name. When you deal with multiple providers, you may want to choose one of them. The default behavior is to use the first one but it can be annoying.

The limit() method allows you to configure the maximum number of results being returned. Depending on the provider you may not get as many results as expected, it is a maximum limit, not the expected number of results.

This library provides a reverse() method to retrieve information from coordinates:

Geocoder provides dumpers that aim to transform a ResultInterface object in standard formats.

Le GPS eXchange format is designed to share geolocated data like point of interests, tracks, ways, but also coordinates. Geocoder provides a dumper to convert a ResultInterface object in an GPX compliant format.

Assuming we got a $result object as seen previously:

GeoJSON is a format for encoding a variety of geographic data structures.

Langage de balisage en trou de serrure (KML)

Keyhole Markup Language is an XML notation for expressing geographic annotation and visualization within Internet-based, two-dimensional maps and three-dimensional Earth browsers.

The Well-Known Binary (WKB) representation for geometric values is defined by the OpenGIS specification.

Well-known text (WKT) is a text markup language for representing vector geometry objects on a map, spatial reference systems of spatial objects and transformations between spatial reference systems.

A common use case is to print geocoded data. Thanks to the Formatter class, it's really easy to format a ResultInterface object as a string:


Visualforce - Apex - Google maps

I have been trying to get something to work with Google maps in combination with Apex and Visualforce pages, but I can't figure out what I'm doing wrong. What I want is to set different icons avec Couleurs différentes in a Google map. More exactly, I want to modify an existing code that was doing the job but only with two icons, one for current location (Account object), and another icon for accounts around the current location.

If I take a look to the Visualforce page that is part of the Account page layout, which contains the Google maps, I can see this section of the code that takes care of the icons and some other stuff:

So I though, ok, I want to add a different icon to each account base on a value of a custom field (Point of Sales), in the Account object. What I did was to created a custom text field in the Account object, Google_marker_URL__c, to assigned a URL to different icons that are in the Documents object, base on the values in the Point of Sales domaine. This was easy and it works! All I needed was to change the icon: '' to icon:'' . The problem is that is picking up the current account Google_marker_URL__c for all the accounts around, which it is obvious. now :( So my question is, how can I change that? How can I use the icon that it is assigned to the accounts that are around the current account?

I have been trying all day different things but it won't work the way I want. I use four different icons with four different colors. Any ideas on how to change this code to do what I want?


Options:

offset — The position, in the input term, of the last character that the service uses to match predictions. For example, if the input is 'Google' and the offset is 3, the service will match on 'Goo'. The string determined by the offset is matched against the first word in the input term only. For example, if the input term is 'Google abc' and the offset is 3, the service will attempt to match against 'Goo abc'. If no offset is supplied, the service will use the whole term. The offset should generally be set to the position of the text caret.

location — The point around which you wish to retrieve place information. Must be specified as latitude,longitude.

radius — The distance (in meters) within which to return place results. Note that setting a radius biases results to the indicated area, but may not fully restrict results to the specified area. See Location Biasing below.

language — The language code, indicating in which language the results should be returned, if possible. Searches are also biased to the selected language results in the selected language may be given a higher ranking. See the list of supported languages and their codes. Note that we often update supported languages so this list may not be exhaustive. If language is not supplied, the Place Autocomplete service will attempt to use the native language of the domain from which the request is sent.

types — The types of place results to return. See Place Types below. If no type is specified, all types will be returned.

components — A grouping of places to which you would like to restrict your results. Currently, you can use components to filter by country. The country must be passed as a two character, ISO 3166-1 Alpha-2 compatible country code. For example: components=country:fr would restrict your results to places within France.


Visualizing the cluster-reduced spatial data

This interactive CartoDB map shows both the full and reduced data sets as separate layers, along with informational pop-ups when you hover over a point. You can turn each layer on or off and zoom in to see how well the reduced set of points represents the full data set:

Now I can save the final reduced data set to CSV and use it in other applications that need a low-overhead spatial data set to render a visualization quickly and responsively. In particular, you might be interested in this notebook that uses this technique to cluster 1.2 million spatial data points and this post about that project. You can also read the paper here.


Voir la vidéo: Google Maps - Coordonnées GPS, latitude et longitude