Google MapsのAir Quality APIから大気汚染データを取得するためのPythonツール
PythonツールでGoogle MapsのAir Quality APIから大気汚染データを取得しよう
世界中からリッチでリアルタイムな大気の質データを取得する方法を学びましょう
この記事では、Google マップの大気質 API を使用して、Python でリアルタイムの大気汚染データ、時系列データ、地図を取得および探索する方法について詳述しています。フルコードはこちらでご確認いただけます。
1. 背景
2023年8月、Google はマッピング API のリストに大気の質サービスを追加すると発表しました。詳細についてはこちらをご覧ください。この情報は現在、Google マップアプリ内からも利用可能であるようですが、API を通じて取得できるデータの方がよりリッチです。
発表によれば、Google はさまざまなソースからの情報を組み合わせて、地上の汚染センサー、衛星データ、リアルタイムの交通情報、数値モデルの予測を含め、最大500mの解像度で100ヶ国の大気の質をダイナミックに更新されるデータセットとして提供しています。これは非常に興味深く、さまざまなマッピング、ヘルスケア、計画アプリケーションにとって有用なデータセットのようです!
これを初めて読んだとき、私は「データと話す」アプリケーションで試してみる予定でした。このトラベルマッパーツールの構築に関する知識を活用して、お気に入りの都市の大気汚染濃度の時系列プロットや、悪い大気を回避するための地元のハイキング計画を支援するツールなどを作成するかもしれません。
- 「都市部の話題の中心地を特定する」
- 機械学習エンジニアリングチームの炭素排出量’ (Kikai Gakushū Enjiniaringu Chīmu no Tanso Hatsu shutsuryō)
- AIブームがクラウドサービスに与える影響の調査
ここで役立つ “現在の条件” サービス、場所ごとの現在の大気質指数値と汚染物質濃度を提供する「過去の条件」サービス、およびイメージとして特定の地域の現在の条件を提供する「ヒートマップ」サービスの3つの API ツールがあります。
以前は、Python で Google マップの API を呼び出すために素晴らしいgooglemaps
パッケージを使用していましたが、これらの新しい API はまだサポートされていません。驚くべきことに、公式のドキュメント以外では、これらの新しいツールを使用している人々の例や、それらを呼び出すために設計された事前存在の Python パッケージはほとんど見つかりませんでした。もし他に知っている人がいれば、喜んで訂正いたします!
そこで、自分自身の簡単なツールを作成しました。この記事では、それらがどのように機能し、どのように使用するかについて説明します。これが、Python でこれらの新しい API を試してみたい人や、始める場所を探している人に役立つことを願っています。このプロジェクトのすべてのコードはこちらで見つけることができ、時間の経過とともに機能を追加し、大気の質データを使用した何らかのマッピングアプリケーションを作成する予定です。
2. 特定の場所の現在の大気質を取得する
さあ、始めましょう!このセクションでは、Google マップで特定の場所の大気質データを取得する方法について説明します。まず、Google Cloud アカウントを通じて生成できる API キーが必要です。90日間の無料トライアル期間がありますが、それ以降は使用した API サービスに対して料金が発生しますので、コール数を増やす前に価格ポリシーをご確認ください!
私は通常、API キーを.env
ファイルに保存し、このようにdotenv
を使用してそれをロードします。
from dotenv import load_dotenvfrom pathlib import Pathdef load_secets(): load_dotenv() env_path = Path(".") / ".env" load_dotenv(dotenv_path=env_path) google_maps_key = os.getenv("GOOGLE_MAPS_API_KEY") return { "GOOGLE_MAPS_API_KEY": google_maps_key, }
現在の状況を取得するには、詳細はこちらのPOSTリクエストが必要です。私たちは< a href=”https://github.com/googlemaps/google-maps-services-python”>googlemapsパッケージからインスピレーションを受けて、一般化できる方法でこれを行います。最初に、 requests
を使用して呼び出しを行うクライアントクラスを作成します。目標は非常に簡単です-以下のようなURLを構築し、ユーザーのクエリに固有のリクエストオプションをすべて含めたいのです。
https://airquality.googleapis.com/v1/currentConditions:lookup?key=YOUR_API_KEY
Client
クラスは、key
としてAPIキーを受け取り、request_url
をクエリのために構築します。リクエストオプションをparams
辞書として受け入れ、それらをJSONリクエストボディに配置し、これはself.session.post()
呼び出しで処理されます。
import requestsimport ioclass Client(object): DEFAULT_BASE_URL = "https://airquality.googleapis.com" def __init__(self, key): self.session = requests.Session() self.key = key def request_post(self, url, params): request_url = self.compose_url(url) request_header = self.compose_header() request_body = params response = self.session.post( request_url, headers=request_header, json=request_body, ) return self.get_body(response) def compose_url(self, path): return self.DEFAULT_BASE_URL + path + "?" + "key=" + self.key @staticmethod def get_body(response): body = response.json() if "error" in body: return body["error"] return body @staticmethod def compose_header(): return { "Content-Type": "application/json", }
ここで、このClientクラスを使用して現在の状況APIの有効なリクエストオプションをユーザーが組み立て、その後このクライアントクラスを使用してリクエストを行う関数を作成できます。これもgooglemapsパッケージのデザインに触発されています。
def current_conditions( client, location, include_local_AQI=True, include_health_suggestion=False, include_all_pollutants=True, include_additional_pollutant_info=False, include_dominent_pollutant_conc=True, language=None,): """ こちらのAPIのドキュメンテーションを参照してください https://developers.google.com/maps/documentation/air-quality/reference/rest/v1/currentConditions/lookup """ params = {} if isinstance(location, dict): params["location"] = location else: raise ValueError( "Location argument must be a dictionary containing latitude and longitude" ) extra_computations = [] if include_local_AQI: extra_computations.append("LOCAL_AQI") if include_health_suggestion: extra_computations.append("HEALTH_RECOMMENDATIONS") if include_additional_pollutant_info: extra_computations.append("POLLUTANT_ADDITIONAL_INFO") if include_all_pollutants: extra_computations.append("POLLUTANT_CONCENTRATION") if include_dominent_pollutant_conc: extra_computations.append("DOMINANT_POLLUTANT_CONCENTRATION") if language: params["language"] = language params["extraComputations"] = extra_computations return client.request_post("/v1/currentConditions:lookup", params)
このAPIのオプションは比較的簡単です。調査したいポイントの経度と緯度を含む辞書が必要であり、返される情報の量を制御するさまざまな他の引数をオプションで取ることができます。すべての引数がTrue
に設定された状態での動作を見てみましょう
#クライアントの設定client = Client(key=GOOGLE_MAPS_API_KEY)# Los Angeles, CAの場所location = {"longitude":-118.3,"latitude":34.1}# JSONでのレスポンスcurrent_conditions_data = current_conditions( client, location, include_health_suggestion=True, include_additional_pollutant_info=True)
興味深い情報がたくさん返されます! Universalおよび米国のAQI指数からのエアクオリティインデックスの値だけでなく、主な汚染物質の濃度、それぞれの説明、現在の空気の品質に対する総合的な健康推奨事項もあります。
{'dateTime': '2023-10-12T05:00:00Z', 'regionCode': 'us', 'indexes': [{'code': 'uaqi', 'displayName': 'Universal AQI', 'aqi': 60, 'aqiDisplay': '60', 'color': {'red': 0.75686276, 'green': 0.90588236, 'blue': 0.09803922}, 'category': 'Good air quality', 'dominantPollutant': 'pm10'}, {'code': 'usa_epa', 'displayName': 'AQI (US)', 'aqi': 39, 'aqiDisplay': '39', 'color': {'green': 0.89411765}, 'category': 'Good air quality', 'dominantPollutant': 'pm10'}], 'pollutants': [{'code': 'co', 'displayName': 'CO', 'fullName': 'Carbon monoxide', 'concentration': {'value': 292.61, 'units': 'PARTS_PER_BILLION'}, 'additionalInfo': {'sources': 'Typically originates from incomplete combustion of carbon fuels, such as that which occurs in car engines and power plants.', 'effects': 'When inhaled, carbon monoxide can prevent the blood from carrying oxygen. Exposure may cause dizziness, nausea and headaches. Exposure to extreme concentrations can lead to loss of consciousness.'}}, {'code': 'no2', 'displayName': 'NO2', 'fullName': 'Nitrogen dioxide', 'concentration': {'value': 22.3, 'units': 'PARTS_PER_BILLION'}, 'additionalInfo': {'sources': 'Main sources are fuel burning processes, such as those used in industry and transportation.', 'effects': 'Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with Chronic Obstructive Pulmonary Disease
3. ある場所の大気の品質の時系列を取得する
特定の場所でAQIと汚染物質の値の時系列を取得できると便利ですよね?これによって、汚染物質間の相関関係や、交通や天候による日常の変動などの興味深いパターンが明らかになるかもしれません。
これは、歴史的な条件APIに対する別のPOSTリクエストで実現できます。これにより、時間毎の履歴が得られます。現在の条件と同様に機能しますが、結果が非常に長くなる場合があるため、複数の
pages
として返されます。これに対応するために、少し追加の論理処理が必要です。まず、
Client
のrequest_post
メソッドを以下のように修正しましょう。def request_post(self,url,params): request_url = self.compose_url(url) request_header = self.compose_header() request_body = params response = self.session.post( request_url, headers=request_header, json=request_body, ) response_body = self.get_body(response) # まず最初のページをレスポンスの辞書に入れます page = 1 final_response = { "page_{}".format(page) : response_body } # 必要に応じてすべてのページを取得します while "nextPageToken" in response_body: # 次のページのトークンを使って再度呼び出します request_body.update({ "pageToken":response_body["nextPageToken"] }) response = self.session.post( request_url, headers=request_header, json=request_body, ) response_body = self.get_body(response) page += 1 final_response["page_{}".format(page)] = response_body return final_response
この修正では、
response_body
にnextPageToken
というフィールドが含まれる場合に対応しています。これは、生成された次のデータのページのIDであり、取得可能な状態になっています。この情報が存在する場合は、pageToken
という新しいパラメータを使用してAPIを再度呼び出すだけです。これをページがなくなるまで繰り返すwhileループで行います。したがって、final_response
の辞書には、ページ番号で示される別のレイヤーが追加されます。current_conditions
への呼び出しでは、通常1つのページしかないのですが、historical_conditions
への呼び出しでは複数のページが存在する場合があります。これで準備が整ったので、
current_conditions
と非常に似たスタイルでhistorical_conditions
関数を記述できます。def historical_conditions( client, location, specific_time=None, lag_time=None, specific_period=None, include_local_AQI=True, include_health_suggestion=False, include_all_pollutants=True, include_additional_pollutant_info=False, include_dominant_pollutant_conc=True, language=None,): """ このAPIのドキュメントはこちらを参照してください https://developers.google.com/maps/documentation/air-quality/reference/rest/v1/history/lookup """ params = {} if isinstance(location, dict): params["location"] = location else: raise ValueError( "Location argument must be a dictionary containing latitude and longitude" ) if isinstance(specific_period, dict) and not specific_time and not lag_time: assert "startTime" in specific_period assert "endTime" in specific_period params["period"] = specific_period elif specific_time and not lag_time and not isinstance(specific_period, dict): # 注意:時刻は「ズール」形式である必要があります。 # 例:datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%SZ") params["dateTime"] = specific_time # 時間のラグ期間(時間単位) elif lag_time and not specific_time and not isinstance(specific_period, dict): params["hours"] = lag_time else: raise ValueError( "Must provide specific_time, specific_period or lag_time arguments" ) extra_computations = [] if include_local_AQI: extra_computations.append("LOCAL_AQI") if include_health_suggestion: extra_computations.append("HEALTH_RECOMMENDATIONS") if include_additional_pollutant_info: extra_computations.append("POLLUTANT_ADDITIONAL_INFO") if include_all_pollutants: extra_computations.append("POLLUTANT_CONCENTRATION") if include_dominant_pollutant_conc: extra_computations.append("DOMINANT_POLLUTANT_CONCENTRATION") if language: params["language"] = language params["extraComputations"] = extra_computations # ページサイズはここでデフォルト値100に設定されています params["pageSize"] = 100 # page tokenは必要に応じてrequest_postメソッドで埋められます params["pageToken"] = "" return client.request_post("/v1/history:lookup", params)
APIを使用して、歴史的な期間を定義するために、最大720時間(30日)までの
lag_time
を受け入れることができます。また、specific_period
辞書を受け入れることもできます。これは、上記のコメントで説明されている形式で開始時間と終了時間を定義します。最後に、単一のデータの1時間を取得するために、specific_time
によって提供される単一のタイムスタンプを受け入れることができます。また、pageSize
パラメータの使用にも注意してください。これは、APIへの各呼び出しで返される時間ポイントの数を制御します。デフォルトは100です。試してみましょう。
# クライアントのセットアップclient = Client(key=GOOGLE_MAPS_API_KEY)# ロサンゼルス、カリフォルニアの場所location = {"longitude":-118.3,"latitude":34.1}# JSONレスポンスhistory_conditions_data = historical_conditions( client, location, lag_time=720)
過去720時間の1時間ごとのAQIインデックス値と特定の汚染物値が含まれる、長い入れ子のJSONレスポンスを取得するはずです。これを視覚化や分析に適した構造に整形するためには、さまざまな方法がありますが、以下の関数では、これを「長い」フォーマットのパンダのデータフレームに変換し、プロットに適しています。
from itertools import chainimport pandas as pddef historical_conditions_to_df(response_dict): chained_pages = list(chain(*[response_dict[p]["hoursInfo"] for p in [*response_dict]])) all_indexes = [] all_pollutants = [] for i in range(len(chained_pages)): # タイムスタンプのいずれかがデータが欠落している場合に必要なこのチェックがあります。これは時々起こります。 if "indexes" in chained_pages[i]: this_element = chained_pages[i] # 時間を取得 time = this_element["dateTime"] # すべてのインデックス値を取得してメタデータを追加 all_indexes += [(time , x["code"],x["displayName"],"index",x["aqi"],None) for x in this_element['indexes']] # すべての汚染物値を取得してメタデータを追加 all_pollutants += [(time , x["code"],x["fullName"],"pollutant",x["concentration"]["value"],x["concentration"]["units"]) for x in this_element['pollutants']] all_results = all_indexes + all_pollutants # "長いフォーマット"のデータフレームを生成 res = pd.DataFrame(all_results,columns=["time","code","name","type","value","unit"]) res["time"]=pd.to_datetime(res["time"]) return res
historical_conditions
の出力に対してこれを実行すると、簡単な分析のためにフォーマットされたデータフレームが生成されます。df = historical_conditions_to_df(history_conditions_data)
そして、結果を
seaborn
や他の可視化ツールでプロットすることができます。import seaborn as snsg = sns.relplot( x="time", y="value", data=df[df["code"].isin(["uaqi","usa_epa","pm25","pm10"])], kind="line", col="name", col_wrap=4, hue="type", height=4, facet_kws={'sharey': False, 'sharex': False})g.set_xticklabels(rotation=90)
これは既に非常に興味深いです!汚染物の時系列には明らかにいくつかの周期性があり、US AQIは、pm25やpm10の濃度と密接に関連していることがわかります。Googleがここで提供しているユニバーサルAQIについてはあまり詳しくないため、なぜpm25とp10と逆相関しているのかは分かりません。UAQIが小さいほど空気の質が良いのでしょうか?いくつかの検索を行っても、良い答えを見つけることができませんでした。
4. エアクオリティヒートマップタイルを取得する
Google Maps Air Quality APIの最終的なユースケースであるヒートマップタイルの生成に入りましょう。これらのタイルは現在の空気のクオリティを視覚化するための強力なツールであり、特に
Folium
マップと組み合わせると効果的です。ただし、これに関するドキュメントは少なく、残念なことです。GETリクエストを使用してこれらのタイルを取得します。URLの形式は以下のようになります。
zoom
、x
、y
によってタイルの場所が指定されます。GET https://airquality.googleapis.com/v1/mapTypes/{mapType}/heatmapTiles/{zoom}/{x}/{y}
zoom
、x
、y
は何を意味するのでしょうか?これについては、Google Mapsが緯度と経度の座標を「タイル座標」に変換する方法について学ぶことで理解できます。詳細はこちらで説明されています。基本的に、Google Mapsは各セルが256x256ピクセルであるグリッドにイメージを格納しており、セルの実際の大きさはズームレベルの関数です。APIに対して呼び出しを行う際、どのグリッドから描画するか(ズームレベルによって決まる)と、グリッド上のどこから描画するか(x
とy
のタイル座標によって決まる)を指定する必要があります。APIから返されるのはPython Imaging Library(PIL)や同様のイメージ処理パッケージで読み取ることができるバイト配列です。上記の形式で
url
を作成した後、対応する画像を取得するためにClient
クラスにいくつかのメソッドを追加できます。def request_get(self,url): request_url = self.compose_url(url) response = self.session.get(request_url) # ヒートマップタイルサービスからの画像の場合 return self.get_image(response) @staticmethod def get_image(response): if response.status_code == 200: image_content = response.content # PILのImageを使用していることに注意 # PILからImageをインポートする必要があります image = Image.open(io.BytesIO(image_content)) return image else: print("画像のGETリクエストがエラーを返しました") return None
これは良いですが、本当に必要なのは経度と緯度の一連の座標をタイル座標に変換する能力です。ドキュメントはこれを説明しており、まず座標をメルカトル投影に変換し、指定されたズームレベルで「ピクセル座標」に変換します。最後に、それをタイル座標に変換します。これらの変換をすべて処理するには、以下の
TileHelper
クラスを使用できます。import mathimport numpy as npclass TileHelper(object): def __init__(self, tile_size=256): self.tile_size = tile_size def location_to_tile_xy(self,location,zoom_level=4): # ここでの関数に基づいています # https://developers.google.com/maps/documentation/javascript/examples/map-coordinates#maps_map_coordinates-javascript lat = location["latitude"] lon = location["longitude"] world_coordinate = self._project(lat,lon) scale = 1 << zoom_level pixel_coord = (math.floor(world_coordinate[0]*scale), math.floor(world_coordinate[1]*scale)) tile_coord = (math.floor(world_coordinate[0]*scale/self.tile_size),math.floor(world_coordinate[1]*scale/self.tile_size)) return world_coordinate, pixel_coord, tile_coord def tile_to_bounding_box(self,tx,ty,zoom_level): # 詳細はこちらを参照 # https://developers.google.com/maps/documentation/javascript/coordinates box_north = self._tiletolat(ty,zoom_level) # タイル番号は南に進む box_south = self._tiletolat(ty+1,zoom_level) box_west = self._tiletolon(tx,zoom_level) # タイル番号は東に進む box_east = self._tiletolon(tx+1,zoom_level) # (latmin, latmax, lonmin, lonmax) return (box_south, box_north, box_west, box_east) @staticmethod def _tiletolon(x,zoom): return x / math.pow(2.0,zoom) * 360.0 - 180.0 @staticmethod def _tiletolat(y,zoom): n = math.pi - (2.0 * math.pi * y)/math.pow(2.0,zoom) return math.atan(math.sinh(n))*(180.0/math.pi) def _project(self,lat,lon): siny = math.sin(lat*math.pi/180.0) siny = min(max(siny,-0.9999), 0.9999) return (self.tile_size*(0.5 + lon/360), self.tile_size*(0.5 - math.log((1 + siny) / (1 - siny)) / (4 * math.pi))) @staticmethod def find_nearest_corner(location,bounds): corner_lat_idx = np.argmin([ np.abs(bounds[0]-location["latitude"]), np.abs(bounds[1]-location["latitude"]) ]) corner_lon_idx = np.argmin([ np.abs(bounds[2]-location["longitude"]), np.abs(bounds[3]-location["longitude"]) ]) if (corner_lat_idx == 0) and (corner_lon_idx == 0): # 最も近いのはlatmin, lonmin direction = "southwest" elif (corner_lat_idx == 0) and (corner_lon_idx == 1): direction = "southeast" elif (corner_lat_idx == 1) and (corner_lon_idx == 0): direction = "northwest" else: direction = "northeast" corner_coords = (bounds[corner_lat_idx],bounds[corner_lon_idx+2]) return corner_coords, direction @staticmethod def get_ajoining_tiles(tx,ty,direction): if direction == "southwest": return [(tx-1,ty),(tx-1,ty+1),(tx,ty+1)] elif direction == "southeast": return [(tx+1,ty),(tx+1,ty-1),(tx,ty-1)] elif direction == "northwest": return [(tx-1,ty-1),(tx-1,ty),(tx,ty-1)] else: return [(tx+1,ty-1),(tx+1,ty),(tx,ty-1)]
location_to_tile_xy
関数は、位置の辞書とズームレベルを受け取り、その点が含まれるタイルを返します。もう一つ便利な関数はtile_to_bounding_box
です。これは指定したグリッドセルの境界座標を見つけます。この関数は、セルを地理位置に関連付けて地図上にプロットするために必要です。では、以下の
air_quality_tile
関数の内部でこれがどのように機能するか見てみましょう。この関数は、client
、location
、および取得するタイルの種類を示す文字列を受け取ります。また、最初に選択するのが難しいズームレベルを指定する必要があり、いくつかの試行とエラーが必要です。後でget_adjoining_tiles
引数について説明します。def air_quality_tile( client, location, pollutant="UAQI_INDIGO_PERSIAN", zoom=4, get_adjoining_tiles = True): # see https://developers.google.com/maps/documentation/air-quality/reference/rest/v1/mapTypes.heatmapTiles/lookupHeatmapTile assert pollutant in [ "UAQI_INDIGO_PERSIAN", "UAQI_RED_GREEN", "PM25_INDIGO_PERSIAN", "GBR_DEFRA", "DEU_UBA", "CAN_EC", "FRA_ATMO", "US_AQI" ] # contains useful methods for dealing the tile coordinates helper = TileHelper() # get the tile that the location is in world_coordinate, pixel_coord, tile_coord = helper.location_to_tile_xy(location,zoom_level=zoom) # get the bounding box of the tile bounding_box = helper.tile_to_bounding_box(tx=tile_coord[0],ty=tile_coord[1],zoom_level=zoom) if get_adjoining_tiles: nearest_corner, nearest_corner_direction = helper.find_nearest_corner(location, bounding_box) adjoining_tiles = helper.get_ajoining_tiles(tile_coord[0],tile_coord[1],nearest_corner_direction) else: adjoining_tiles = [] tiles = [] #get all the adjoining tiles, plus the one in question for tile in adjoining_tiles + [tile_coord]: bounding_box = helper.tile_to_bounding_box(tx=tile[0],ty=tile[1],zoom_level=zoom) image_response = client.request_get( "/v1/mapTypes/" + pollutant + "/heatmapTiles/" + str(zoom) + '/' + str(tile[0]) + '/' + str(tile[1]) ) # convert the PIL image to numpy try: image_response = np.array(image_response) except: image_response = None tiles.append({ "bounds":bounding_box, "image":image_response }) return tiles
コードを読むことから、以下のワークフローがわかります。まず、興味のある位置のタイル座標を見つけます。これは取得したいグリッドセルを指定します。そして、このグリッドセルの境界座標を見つけます。周囲のタイルを取得したい場合は、境界ボックスの最も近い隅を見つけて、その隅を使用して隣接する3つのグリッドセルのタイル座標を計算します。それからAPIを呼び出し、各タイルを対応する境界ボックスとともに画像として返します。
このコードは以下のように通常の方法で実行できます:
client = Client(key=GOOGLE_MAPS_API_KEY)location = {"longitude":-118.3,"latitude":34.1}zoom = 7tiles = air_quality_tile( client, location, pollutant="UAQI_INDIGO_PERSIAN", zoom=zoom, get_adjoining_tiles=False)
そしてズーム可能なマップをfoliumでプロットします!ここでleafmapを使用していることに注意してください。なぜなら、このパッケージはgradioと互換性のあるFoliumマップを生成できるからです。gradioは、Pythonアプリケーションのシンプルなユーザーインターフェースを生成するための強力なツールです。例については、この記事をご覧ください。
import leafmap.foliumap as leafmapimport foliumlat = location["latitude"]lon = location["longitude"]map = leafmap.Map(location=[lat, lon], tiles="OpenStreetMap", zoom_start=zoom)for tile in tiles: latmin, latmax, lonmin, lonmax = tile["bounds"] AQ_image = tile["image"] folium.raster_layers.ImageOverlay( image=AQ_image, bounds=[[latmin, lonmin], [latmax, lonmax]], opacity=0.7 ).add_to(map)
残念なことに、このズームレベルで私たちの場所を含むタイルはほとんど海ですが、詳細な地図の上に大気汚染がプロットされているのを見ることはまだ素晴らしいです。ズームインすると、都市部の大気品質のシグナルに道路交通情報が使用されていることがわかります。
get_adjoining_tiles=True
を設定すると、そのズームレベルで最も近い3つの重複しないタイルを取得するため、より素敵な地図が表示されます。私たちの場合、それは地図をより見栄え良くするために非常に役立ちます。個人的には、
pollutant=US_AQI
の場合に生成される画像が好きですが、いくつかの異なるオプションがあります。残念ながらAPIはカラースケールを返さないため、画像のピクセル値と色の意味を知ることでカラースケールを生成することができます。We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles