diff --git a/.gitignore b/.gitignore index 7963fe03..c69c16d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,120 +1,120 @@ -# data -*.gpkg -*.gpkg-shm -*.graphml -analysis/images/* -process/configuration/*.json -!process/configuration/resources.json -process/data/input/* -validation/edge/data -validation/destination/data -validation/data -process/data - - -.DS_Store - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ +# data +*.gpkg +*.gpkg-shm +*.graphml +analysis/images/* +process/configuration/*.json +!process/configuration/resources.json +process/data/input/* +validation/edge/data +validation/destination/data +validation/data +process/data + + +.DS_Store + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/LICENSE b/LICENSE index 10c7d730..c205f931 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2019 Jonathan Arundel, Geoff Boeing, Carl Higgs, Shiqin Liu - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2019 Jonathan Arundel, Geoff Boeing, Carl Higgs, Shiqin Liu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/analysis/analysis-between-cities.ipynb b/analysis/analysis-between-cities.ipynb index ae9c2828..aaa383b3 100644 --- a/analysis/analysis-between-cities.ipynb +++ b/analysis/analysis-between-cities.ipynb @@ -1,342 +1,342 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Visualization and data analysis of output indicators \n", - "\n", - "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", - "The analyses consist of two major components: \n", - " 1. Within-city variations\n", - " - Show maps of walkability indicators for all cities and do a visual sanity check to see if any issue occurs\n", - " - Interpret the within-city variation patterns\n", - " - Pick one or two cities as examples, plot different indicators and compare, interprete the within-city variations and how that may or may not represent the real-world situation\n", - "\n", - " 2. Between-city analysis\n", - " - Show tables for measurements and raw indicator number, rank cities from the highest to the lowest, and interprete the results\n", - " - Plot in a world map using graduated symbol or color to visualize and compare indicators across cities\n", - " - Create box plot to compare median statistics across cities\n", - " - We could may be do similar analyses like policy indicators analyses to color code cities based on the lancet study threshold?\n", - " \n", - "\n", - "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**\n", - " \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import geopandas as gpd\n", - "import os\n", - "import pandas as pd\n", - "import json\n", - "import matplotlib.pyplot as plt\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "image_path = './images'\n", - "dpi = 300\n", - "\n", - "process_folder = '../process'\n", - "process_config_path = '../process/configuration/cities.json'" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "with open(process_config_path) as json_file:\n", - " config = json.load(json_file)\n", - "\n", - "output_folder = os.path.join(process_folder, config['folder'])\n", - "input_folder = os.path.join(process_folder, config['input_folder'])\n", - "\n", - "# the path of \"global_indicators_hex_250m.gpkg\"\n", - "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", - "\n", - "# create the path of \"global_indicators_city.gpkg\"\n", - "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "cities = ['adelaide',\n", - " 'auckland',\n", - " 'baltimore',\n", - " 'bangkok',\n", - " 'barcelona',\n", - " 'belfast',\n", - " 'bern',\n", - " 'chennai',\n", - " 'mexico_city',\n", - " 'cologne',\n", - " 'ghent',\n", - " 'graz',\n", - " 'hanoi',\n", - " 'hong_kong',\n", - " 'lisbon',\n", - " 'melbourne',\n", - " 'odense',\n", - " 'olomouc',\n", - " 'sao_paulo',\n", - " 'phoenix',\n", - " 'seattle',\n", - " 'sydney',\n", - " 'valencia',\n", - " 'vic']" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "cities_ind = gpd.GeoDataFrame()\n", - "for city in cities:\n", - " #read file\n", - " city_ind = gpd.read_file(gpkgOutput_cities, layer=city)\n", - " cities_ind = cities_ind.append(city_ind, ignore_index=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Index(['Study region', 'urban_sample_point_count',\n", - " 'pop_pct_access_500m_fresh_food_market_binary',\n", - " 'pop_pct_access_500m_convenience_binary',\n", - " 'pop_pct_access_500m_pt_osm_any_binary',\n", - " 'pop_pct_access_500m_public_open_space_any_binary',\n", - " 'pop_pct_access_500m_public_open_space_large_binary',\n", - " 'pop_pct_access_500m_pt_gtfs_any_binary',\n", - " 'pop_pct_access_500m_pt_gtfs_freq_30_binary',\n", - " 'pop_pct_access_500m_pt_gtfs_freq_20_binary',\n", - " 'pop_pct_access_500m_pt_any_binary', 'pop_nh_pop_density',\n", - " 'pop_nh_intersection_density', 'pop_daily_living', 'pop_walkability',\n", - " 'all_cities_pop_z_nh_population_density',\n", - " 'all_cities_pop_z_nh_intersection_density',\n", - " 'all_cities_pop_z_daily_living', 'all_cities_walkability', 'geometry',\n", - " 'db', 'area_sqkm'],\n", - " dtype='object')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#correct vic study region column\n", - "cities_ind['Study region'] = cities_ind['Study region'].fillna('Vic')\n", - "cities_ind.columns" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "ename": "KeyError", - "evalue": "\"['all_cities_pop_walkability'] not in index\"", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# show pop-weighted walkability score ranking relative to all cities\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m cities_ind[['Study region', 'all_cities_walkability', 'all_cities_pop_walkability'\n\u001b[0m\u001b[1;32m 3\u001b[0m ]].sort_values('all_cities_pop_walkability').reset_index().drop(columns=['index'])\n", - "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/geopandas/geodataframe.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 574\u001b[0m \u001b[0mGeoDataFrame\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 575\u001b[0m \"\"\"\n\u001b[0;32m--> 576\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mGeoDataFrame\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__getitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 577\u001b[0m \u001b[0mgeo_col\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_geometry_column_name\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 578\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mgeo_col\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 2804\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_iterator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2805\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2806\u001b[0;31m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_listlike_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraise_missing\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2807\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2808\u001b[0m \u001b[0;31m# take() does not accept boolean indexers\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/pandas/core/indexing.py\u001b[0m in \u001b[0;36m_get_listlike_indexer\u001b[0;34m(self, key, axis, raise_missing)\u001b[0m\n\u001b[1;32m 1551\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1552\u001b[0m self._validate_read_indexer(\n\u001b[0;32m-> 1553\u001b[0;31m \u001b[0mkeyarr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindexer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_axis_number\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maxis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraise_missing\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mraise_missing\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1554\u001b[0m )\n\u001b[1;32m 1555\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mkeyarr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindexer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/pandas/core/indexing.py\u001b[0m in \u001b[0;36m_validate_read_indexer\u001b[0;34m(self, key, indexer, axis, raise_missing)\u001b[0m\n\u001b[1;32m 1644\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"loc\"\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mraise_missing\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1645\u001b[0m \u001b[0mnot_found\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0max\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1646\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"{not_found} not in index\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1647\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1648\u001b[0m \u001b[0;31m# we skip the warning on Categorical/Interval\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyError\u001b[0m: \"['all_cities_pop_walkability'] not in index\"" - ] - } - ], - "source": [ - "# show pop-weighted walkability score ranking relative to all cities\n", - "cities_ind[['Study region', 'all_cities_walkability', 'all_cities_pop_walkability'\n", - " ]].sort_values('all_cities_pop_walkability').reset_index().drop(columns=['index'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# save these indicators in csv file\n", - "cities_ind[['Study region', 'all_cities_pop_walkability',\n", - " 'all_cities_pop_z_daily_living',\n", - " 'all_cities_pop_z_nh_intersection_density',\n", - " 'all_cities_pop_z_nh_population_density', \n", - " 'pop_daily_living', 'pop_walkability',\n", - " 'pop_nh_intersection_density', 'pop_nh_pop_density',\n", - " 'pop_pct_access_500m_convenience_binary',\n", - " 'pop_pct_access_500m_fresh_food_market_binary',\n", - " 'pop_pct_access_500m_pt_any_binary',\n", - " 'pop_pct_access_500m_pt_gtfs_any_binary',\n", - " 'pop_pct_access_500m_pt_gtfs_freq_20_binary',\n", - " 'pop_pct_access_500m_pt_gtfs_freq_30_binary',\n", - " 'pop_pct_access_500m_pt_osm_any_binary',\n", - " 'pop_pct_access_500m_public_open_space_any_binary',\n", - " 'pop_pct_access_500m_public_open_space_large_binary', \n", - " 'all_cities_walkability', 'all_cities_z_daily_living', \n", - " 'all_cities_z_nh_intersection_density',\n", - " 'all_cities_z_nh_population_density',\n", - " 'local_daily_living', 'local_nh_intersection_density',\n", - " 'local_nh_population_density', 'local_walkability', \n", - " 'urban_sample_point_count']].to_csv('images/globe_cities_results_Sept2020.csv')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Other visualization to consider (work-in-progress):\n", - "1. global mapping to plot indicators: [this site](https://geopandas.org/mapping.html)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "continents = pd.read_csv('cities_continents.csv')\n", - "cities_point = pd.merge(cities_ind, continents, left_on='Study region', right_on='City', how='outer')\n", - "cities_point.columns" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# creat point geometry to plot in the map\n", - "list_lat = [] # create empty lists\n", - "list_long = []\n", - "\n", - "for index, row in cities_point.iterrows(): # iterate over rows in dataframe\n", - " City = row['City']\n", - " Country = row['Country']\n", - " query = str(City) +','+str(Country)\n", - "\n", - " results = ox.geocode(query) \n", - " lat = results[1]\n", - " long = results[0]\n", - "\n", - " list_lat.append(lat)\n", - " list_long.append(long)\n", - "\n", - "# create new columns from lists \n", - "cities_point['lat'] = list_lat \n", - "cities_point['lon'] = list_long" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# generate point geometry columns \n", - "cities_point = cities_point.rename(columns={'geometry':'poly_geometry'})\n", - "\n", - "from shapely.geometry import Point\n", - "cities_point['geometry'] = cities_point.apply(lambda row: Point(row['lat'], row['lon']), axis=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import mpl_toolkits\n", - "import matplotlib\n", - "\n", - "# use cartopy not basemap (which was deprecated years ago)\n", - "from mpl_toolkits.basemap import Basemap\n", - "\n", - "# Set the dimension of the figure\n", - "my_dpi=96\n", - "plt.figure(figsize=(2600/my_dpi, 1800/my_dpi), dpi=my_dpi)\n", - "\n", - "# Make the background map\n", - "m=Basemap(llcrnrlon=-150, llcrnrlat=-65,urcrnrlon=180,urcrnrlat=80)\n", - "m.drawmapboundary(fill_color='#A6CAE0', linewidth=0)\n", - "m.fillcontinents(color='grey', alpha=0.3)\n", - "m.drawcoastlines(linewidth=0.1, color=\"white\")\n", - " \n", - "# prepare a color for each point depending on the continent.\n", - "cities_point['labels_enc'] = pd.factorize(cities_point['Continents'])[0]\n", - "\n", - "m.scatter(cities_point['lat'], cities_point['lon'], marker='^', s=200,\n", - " c=cities_point['labels_enc'], cmap=\"Set1\", alpha=0.9)\n", - " \n", - "# copyright and source data info\n", - "#plt.text( -170, -58,'walkability', ha='left', va='bottom', size=9, color='#555555' )\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note: Cannot plot the negative z score bubble maps: If a variable takes negative values, then it cannot be directly assigned to point size as an encoding: after all, how can a shape have a negative area? Additional information needs to be encoded into shape size in order to indicate negative values. For example, you might have filled circles indicate positive values and unfilled circles indicate negative values. As another alternative, you might have positive points in one color, and negative points in a distinct, different color." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualization and data analysis of output indicators \n", + "\n", + "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", + "The analyses consist of two major components: \n", + " 1. Within-city variations\n", + " - Show maps of walkability indicators for all cities and do a visual sanity check to see if any issue occurs\n", + " - Interpret the within-city variation patterns\n", + " - Pick one or two cities as examples, plot different indicators and compare, interprete the within-city variations and how that may or may not represent the real-world situation\n", + "\n", + " 2. Between-city analysis\n", + " - Show tables for measurements and raw indicator number, rank cities from the highest to the lowest, and interprete the results\n", + " - Plot in a world map using graduated symbol or color to visualize and compare indicators across cities\n", + " - Create box plot to compare median statistics across cities\n", + " - We could may be do similar analyses like policy indicators analyses to color code cities based on the lancet study threshold?\n", + " \n", + "\n", + "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import geopandas as gpd\n", + "import os\n", + "import pandas as pd\n", + "import json\n", + "import matplotlib.pyplot as plt\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "image_path = './images'\n", + "dpi = 300\n", + "\n", + "process_folder = '../process'\n", + "process_config_path = '../process/configuration/cities.json'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "with open(process_config_path) as json_file:\n", + " config = json.load(json_file)\n", + "\n", + "output_folder = os.path.join(process_folder, config['folder'])\n", + "input_folder = os.path.join(process_folder, config['input_folder'])\n", + "\n", + "# the path of \"global_indicators_hex_250m.gpkg\"\n", + "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", + "\n", + "# create the path of \"global_indicators_city.gpkg\"\n", + "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "cities = ['adelaide',\n", + " 'auckland',\n", + " 'baltimore',\n", + " 'bangkok',\n", + " 'barcelona',\n", + " 'belfast',\n", + " 'bern',\n", + " 'chennai',\n", + " 'mexico_city',\n", + " 'cologne',\n", + " 'ghent',\n", + " 'graz',\n", + " 'hanoi',\n", + " 'hong_kong',\n", + " 'lisbon',\n", + " 'melbourne',\n", + " 'odense',\n", + " 'olomouc',\n", + " 'sao_paulo',\n", + " 'phoenix',\n", + " 'seattle',\n", + " 'sydney',\n", + " 'valencia',\n", + " 'vic']" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "cities_ind = gpd.GeoDataFrame()\n", + "for city in cities:\n", + " #read file\n", + " city_ind = gpd.read_file(gpkgOutput_cities, layer=city)\n", + " cities_ind = cities_ind.append(city_ind, ignore_index=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['Study region', 'urban_sample_point_count',\n", + " 'pop_pct_access_500m_fresh_food_market_binary',\n", + " 'pop_pct_access_500m_convenience_binary',\n", + " 'pop_pct_access_500m_pt_osm_any_binary',\n", + " 'pop_pct_access_500m_public_open_space_any_binary',\n", + " 'pop_pct_access_500m_public_open_space_large_binary',\n", + " 'pop_pct_access_500m_pt_gtfs_any_binary',\n", + " 'pop_pct_access_500m_pt_gtfs_freq_30_binary',\n", + " 'pop_pct_access_500m_pt_gtfs_freq_20_binary',\n", + " 'pop_pct_access_500m_pt_any_binary', 'pop_nh_pop_density',\n", + " 'pop_nh_intersection_density', 'pop_daily_living', 'pop_walkability',\n", + " 'all_cities_pop_z_nh_population_density',\n", + " 'all_cities_pop_z_nh_intersection_density',\n", + " 'all_cities_pop_z_daily_living', 'all_cities_walkability', 'geometry',\n", + " 'db', 'area_sqkm'],\n", + " dtype='object')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#correct vic study region column\n", + "cities_ind['Study region'] = cities_ind['Study region'].fillna('Vic')\n", + "cities_ind.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "ename": "KeyError", + "evalue": "\"['all_cities_pop_walkability'] not in index\"", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# show pop-weighted walkability score ranking relative to all cities\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m cities_ind[['Study region', 'all_cities_walkability', 'all_cities_pop_walkability'\n\u001b[0m\u001b[1;32m 3\u001b[0m ]].sort_values('all_cities_pop_walkability').reset_index().drop(columns=['index'])\n", + "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/geopandas/geodataframe.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 574\u001b[0m \u001b[0mGeoDataFrame\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 575\u001b[0m \"\"\"\n\u001b[0;32m--> 576\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mGeoDataFrame\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__getitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 577\u001b[0m \u001b[0mgeo_col\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_geometry_column_name\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 578\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mgeo_col\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 2804\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_iterator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2805\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2806\u001b[0;31m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_listlike_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraise_missing\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2807\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2808\u001b[0m \u001b[0;31m# take() does not accept boolean indexers\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/pandas/core/indexing.py\u001b[0m in \u001b[0;36m_get_listlike_indexer\u001b[0;34m(self, key, axis, raise_missing)\u001b[0m\n\u001b[1;32m 1551\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1552\u001b[0m self._validate_read_indexer(\n\u001b[0;32m-> 1553\u001b[0;31m \u001b[0mkeyarr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindexer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_axis_number\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maxis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraise_missing\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mraise_missing\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1554\u001b[0m )\n\u001b[1;32m 1555\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mkeyarr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindexer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/conda/lib/python3.7/site-packages/pandas/core/indexing.py\u001b[0m in \u001b[0;36m_validate_read_indexer\u001b[0;34m(self, key, indexer, axis, raise_missing)\u001b[0m\n\u001b[1;32m 1644\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"loc\"\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mraise_missing\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1645\u001b[0m \u001b[0mnot_found\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0max\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1646\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"{not_found} not in index\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1647\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1648\u001b[0m \u001b[0;31m# we skip the warning on Categorical/Interval\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyError\u001b[0m: \"['all_cities_pop_walkability'] not in index\"" + ] + } + ], + "source": [ + "# show pop-weighted walkability score ranking relative to all cities\n", + "cities_ind[['Study region', 'all_cities_walkability', 'all_cities_pop_walkability'\n", + " ]].sort_values('all_cities_pop_walkability').reset_index().drop(columns=['index'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# save these indicators in csv file\n", + "cities_ind[['Study region', 'all_cities_pop_walkability',\n", + " 'all_cities_pop_z_daily_living',\n", + " 'all_cities_pop_z_nh_intersection_density',\n", + " 'all_cities_pop_z_nh_population_density', \n", + " 'pop_daily_living', 'pop_walkability',\n", + " 'pop_nh_intersection_density', 'pop_nh_pop_density',\n", + " 'pop_pct_access_500m_convenience_binary',\n", + " 'pop_pct_access_500m_fresh_food_market_binary',\n", + " 'pop_pct_access_500m_pt_any_binary',\n", + " 'pop_pct_access_500m_pt_gtfs_any_binary',\n", + " 'pop_pct_access_500m_pt_gtfs_freq_20_binary',\n", + " 'pop_pct_access_500m_pt_gtfs_freq_30_binary',\n", + " 'pop_pct_access_500m_pt_osm_any_binary',\n", + " 'pop_pct_access_500m_public_open_space_any_binary',\n", + " 'pop_pct_access_500m_public_open_space_large_binary', \n", + " 'all_cities_walkability', 'all_cities_z_daily_living', \n", + " 'all_cities_z_nh_intersection_density',\n", + " 'all_cities_z_nh_population_density',\n", + " 'local_daily_living', 'local_nh_intersection_density',\n", + " 'local_nh_population_density', 'local_walkability', \n", + " 'urban_sample_point_count']].to_csv('images/globe_cities_results_Sept2020.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Other visualization to consider (work-in-progress):\n", + "1. global mapping to plot indicators: [this site](https://geopandas.org/mapping.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "continents = pd.read_csv('cities_continents.csv')\n", + "cities_point = pd.merge(cities_ind, continents, left_on='Study region', right_on='City', how='outer')\n", + "cities_point.columns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# creat point geometry to plot in the map\n", + "list_lat = [] # create empty lists\n", + "list_long = []\n", + "\n", + "for index, row in cities_point.iterrows(): # iterate over rows in dataframe\n", + " City = row['City']\n", + " Country = row['Country']\n", + " query = str(City) +','+str(Country)\n", + "\n", + " results = ox.geocode(query) \n", + " lat = results[1]\n", + " long = results[0]\n", + "\n", + " list_lat.append(lat)\n", + " list_long.append(long)\n", + "\n", + "# create new columns from lists \n", + "cities_point['lat'] = list_lat \n", + "cities_point['lon'] = list_long" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# generate point geometry columns \n", + "cities_point = cities_point.rename(columns={'geometry':'poly_geometry'})\n", + "\n", + "from shapely.geometry import Point\n", + "cities_point['geometry'] = cities_point.apply(lambda row: Point(row['lat'], row['lon']), axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import mpl_toolkits\n", + "import matplotlib\n", + "\n", + "# use cartopy not basemap (which was deprecated years ago)\n", + "from mpl_toolkits.basemap import Basemap\n", + "\n", + "# Set the dimension of the figure\n", + "my_dpi=96\n", + "plt.figure(figsize=(2600/my_dpi, 1800/my_dpi), dpi=my_dpi)\n", + "\n", + "# Make the background map\n", + "m=Basemap(llcrnrlon=-150, llcrnrlat=-65,urcrnrlon=180,urcrnrlat=80)\n", + "m.drawmapboundary(fill_color='#A6CAE0', linewidth=0)\n", + "m.fillcontinents(color='grey', alpha=0.3)\n", + "m.drawcoastlines(linewidth=0.1, color=\"white\")\n", + " \n", + "# prepare a color for each point depending on the continent.\n", + "cities_point['labels_enc'] = pd.factorize(cities_point['Continents'])[0]\n", + "\n", + "m.scatter(cities_point['lat'], cities_point['lon'], marker='^', s=200,\n", + " c=cities_point['labels_enc'], cmap=\"Set1\", alpha=0.9)\n", + " \n", + "# copyright and source data info\n", + "#plt.text( -170, -58,'walkability', ha='left', va='bottom', size=9, color='#555555' )\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note: Cannot plot the negative z score bubble maps: If a variable takes negative values, then it cannot be directly assigned to point size as an encoding: after all, how can a shape have a negative area? Additional information needs to be encoded into shape size in order to indicate negative values. For example, you might have filled circles indicate positive values and unfilled circles indicate negative values. As another alternative, you might have positive points in one color, and negative points in a distinct, different color." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/analysis/analysis-within-city-boxplots.ipynb b/analysis/analysis-within-city-boxplots.ipynb index 15210681..eb8a289b 100644 --- a/analysis/analysis-within-city-boxplots.ipynb +++ b/analysis/analysis-within-city-boxplots.ipynb @@ -1,412 +1,412 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Visualization and data analysis of output indicators \n", - "\n", - "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", - "The analyses consist of two major components: \n", - " 1. Within-city variations\n", - " - Show maps of walkability indicators for all cities and do a visual sanity check to see if any issue occurs\n", - " - Interpret the within-city variation patterns\n", - " - Pick one or two cities as examples, plot different indicators and compare, interprete the within-city variations and how that may or may not represent the real-world situation\n", - "\n", - " 2. Between-city analysis\n", - " - Show tables for measurements and raw indicator number, rank cities from the highest to the lowest, and interprete the results\n", - " - Plot in a world map using graduated symbol or color to visualize and compare indicators across cities\n", - " - Create box plot to compare median statistics across cities\n", - " - We could may be do similar analyses like policy indicators analyses to color code cities based on the lancet study threshold?\n", - " \n", - "\n", - "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**\n", - " \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import geopandas as gpd\n", - "import pandas as pd\n", - "import os\n", - "import json\n", - "import matplotlib.pyplot as plt\n", - "import seaborn as sns\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "image_path = './images'\n", - "dpi = 300\n", - "\n", - "process_folder = '../process'\n", - "process_config_path = '../process/configuration/cities.json'" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "with open(process_config_path) as json_file:\n", - " config = json.load(json_file)\n", - "\n", - "output_folder = os.path.join(process_folder, config['folder'])\n", - "input_folder = os.path.join(process_folder, config['input_folder'])\n", - "\n", - "# the path of \"global_indicators_hex_250m.gpkg\"\n", - "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", - "\n", - "# create the path of \"global_indicators_city.gpkg\"\n", - "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "cities = ['adelaide',\n", - " 'auckland',\n", - " 'baltimore',\n", - " 'bangkok',\n", - " 'barcelona',\n", - " 'belfast',\n", - " 'bern',\n", - " 'chennai',\n", - " 'mexico_city',\n", - " 'cologne',\n", - " 'ghent',\n", - " 'graz',\n", - " 'hanoi',\n", - " 'hong_kong',\n", - " 'lisbon',\n", - " 'melbourne',\n", - " 'odense',\n", - " 'olomouc',\n", - " 'sao_paulo',\n", - " 'phoenix',\n", - " 'seattle',\n", - " 'sydney',\n", - " 'valencia',\n", - " 'vic']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## All cities hex-level indicators boxplot" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "334003" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# concat all hexes for all cities in one big dataframe\n", - "all_hexes=pd.DataFrame()\n", - "\n", - "for city in cities:\n", - " #read file\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " hex250['city'] = city\n", - " # append all hexes into one dataframe for analysis\n", - " all_hexes = pd.concat([all_hexes, hex250], ignore_index=True)\n", - "\n", - "len(all_hexes)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Index(['index', 'study_region', 'urban_sample_point_count',\n", - " 'pct_access_500m_fresh_food_market_binary',\n", - " 'pct_access_500m_convenience_binary',\n", - " 'pct_access_500m_pt_osm_any_binary',\n", - " 'pct_access_500m_public_open_space_any_binary',\n", - " 'pct_access_500m_public_open_space_large_binary',\n", - " 'pct_access_500m_pt_gtfs_any_binary',\n", - " 'pct_access_500m_pt_gtfs_freq_30_binary',\n", - " 'pct_access_500m_pt_gtfs_freq_20_binary',\n", - " 'pct_access_500m_pt_any_binary', 'local_nh_population_density',\n", - " 'local_nh_intersection_density', 'local_daily_living',\n", - " 'local_walkability', 'all_cities_z_nh_population_density',\n", - " 'all_cities_z_nh_intersection_density', 'all_cities_z_daily_living',\n", - " 'all_cities_walkability', 'geometry', 'city'],\n", - " dtype='object')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "all_hexes.columns" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "figs = {'all_cities_walkability': {'note': 'Sum z-scores of pop density + intersect density + daily living, hex-level',\n", - " 'title': 'Walkability Index (place-based, not pop weighted)',\n", - " 'filename': 'boxplot-walkability_unweighted.png'},\n", - " 'local_daily_living': {'note': 'Sum of binary accessibility to all daily living destinations',\n", - " 'title': 'Daily Living Scores',\n", - " 'filename': 'boxplot-daily_living.png'},\n", - " 'local_nh_population_density': {'note': 'Population per km2, hex-level',\n", - " 'title': 'Local Population Density',\n", - " 'filename': 'boxplot-pop_density.png'},\n", - " 'local_nh_intersection_density': {'note': 'Intersections per km2, hex-level',\n", - " 'title': 'Local Intersection Density',\n", - " 'filename': 'boxplot-intersect_density.png'}\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "sns.set_style('whitegrid') #visual styles\n", - "sns.set_context('paper') #presets for scaling figure element sizes" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "for col, details in figs.items():\n", - "\n", - " #order by median\n", - " median_order = all_hexes.groupby(by=['study_region'])[col].median().sort_values().index\n", - "\n", - " fig, ax = plt.subplots(figsize=(8, 6))\n", - "\n", - " # switch x and y\n", - " ax=sns.boxplot(ax=ax, y=all_hexes['study_region'], x=all_hexes[col],\n", - " order=median_order, palette='Blues', width=0.6,\n", - " fliersize=0.05, boxprops={'alpha':0.7})\n", - " ax.tick_params(axis='both', which='major')\n", - " ax.set_xlabel(details['note'])\n", - " ax.set_ylabel('')\n", - "\n", - " # add a title to the figure\n", - " ax.set_title(details['title'], fontsize=16)\n", - " fig.tight_layout()\n", - "\n", - " save_path = os.path.join(image_path, details['filename'])\n", - " fig.savefig(save_path, dpi=300, bbox_inches='tight')\n", - " plt.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## All cities pop-weighted hex-level indicators boxplot (work-in-progress)\n", - "\n", - "Pop-weighted hex-level indicators are not currently in our processing scripts but we may want to include this for consistency with the city-level indicators" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "def aggregation_hexes_pop_weighted(input_gdf, out_gdf, fieldNames):\n", - " \"\"\"\n", - " Aggregating hexagon level indicators by weighted population\n", - " Parameters\n", - "\n", - " \"\"\"\n", - " # loop over each indicators field names of input and output gdf\n", - " for field in fieldNames:\n", - " # calculate the population weighted indicators based on input hexagon layer\n", - " # sum to aggregate up to the city level\n", - " out_gdf[field[1]] = (input_gdf[sc.cities_parameters[\"pop_est\"]] * input_gdf[field[0]]) / (\n", - " input_gdf[sc.cities_parameters[\"pop_est\"]].sum())\n", - " return out_gdf\n", - "\n", - "\n", - "def calc_hexes_pop_pct_indicators(gpkg_hex_250m, city, gpkg_input, gpkg_output):\n", - " \"\"\"\n", - " Calculate population-weighted hex-level indicators,\n", - " and save to output geopackage\n", - " \"\"\"\n", - " gdf_hex = gpd.read_file(gpkg_hex_250m, layer=city)\n", - "\n", - " gdf_hex_origin = gpd.read_file(gpkg_input, layer=sc.cities_parameters[\"hex250\"])\n", - " # join pop_est from original hex to processed hex\n", - " gdf_hex = gdf_hex.join(gdf_hex_origin.set_index(\"index\"), on=\"index\", how=\"left\", rsuffix=\"_origin\")\n", - "\n", - " # hex-level field names from city-specific hex indicators gpkg\n", - " fieldNames = sc.hex_fieldNames[3:-1]\n", - " \n", - " # new file names for population-weighted city-level indicators\n", - " fieldNames_new = sc.city_fieldNames[2:-1]\n", - " \n", - " # calculate the population weighted city-level indicators\n", - " gdf_hexes = aggregation_hexes_pop_weighted(gdf_hex, gdf_hex, list(zip(fieldNames, fieldNames_new)))\n", - " \n", - " #gdf_hexes.to_file(gpkg_output, layer=city, driver=\"GPKG\")\n", - " return gdf_hexes" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'dirname' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mgpkgInput_ori\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mgpkg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"gpkgNames\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mgpkgInput_ori\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdirname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minput_folder\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgpkg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mNameError\u001b[0m: name 'dirname' is not defined" - ] - } - ], - "source": [ - "# read pre-prepared sample point stats of each city from disk\n", - "gpkgInput_ori = []\n", - "for gpkg in list(config[\"gpkgNames\"].values()):\n", - " gpkgInput_ori.append(os.path.join(dirname, input_folder, gpkg))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "all_hexes1=pd.DataFrame()\n", - "cities = list(config[\"gpkgNames\"].keys())\n", - "\n", - "for index, gpkgInput in enumerate(gpkgInput_ori):\n", - " #print(index, gpkgInput)\n", - " gdf_hexes = calc_hexes_pop_pct_indicators(gpkgOutput_hex250, cities[index], \n", - " gpkgInput, gpkgOutput_hex250) \n", - " # append all hexes into one dataframe for analysis\n", - " all_hexes1 = pd.concat([all_hexes1, gdf_hexes], ignore_index=True)\n", - "\n", - "all_hexes1.columns" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# check if the results are the same as city-level outputs\n", - "all_hexes1[['study_region', 'all_cities_pop_walkability', 'all_cities_pop_z_daily_living',\n", - " 'all_cities_pop_z_nh_intersection_density',\n", - " 'all_cities_pop_z_nh_population_density']].groupby('study_region').sum()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# library & dataset\n", - "import seaborn as sns\n", - "\n", - "col ='all_cities_pop_walkability'\n", - "\n", - "#order by median\n", - "median_order = all_hexes1.groupby(by=['study_region'])[col].median().sort_values().index\n", - "\n", - "fig, ax = plt.subplots(figsize=(20, 10))\n", - "\n", - "# Just switch x and y\n", - "ax=sns.boxplot(ax=ax, y=all_hexes1['study_region'], x=all_hexes1[col], order=median_order, palette=\"Blues\", width=0.6)\n", - "ax.tick_params(axis='both', which='major', labelsize=14)\n", - "ax.set_xlabel('Walkability index (Z Scores)', fontsize=16)\n", - "ax.set_ylabel('Study region', fontsize=16)\n", - "ax.set(xlim=(-0.005, 0.008))\n", - "\n", - "# add a title to the figure\n", - "fig.suptitle('Walkability Index \\n ( weighted by population)', y=0.95, fontsize=20, weight='bold')\n", - "\n", - "fig.text(0.1, 0, 'Note: Population-weighted walkability index relative to all cities - sum of the population-weighted z-scores of pop and intersection density, and daily living generated at the hex level; ranked by median \\n', \n", - " fontsize=12, color='#555555')\n", - "\n", - "#fig.savefig('figure/walkability_popweighted.png', dpi=600)\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualization and data analysis of output indicators \n", + "\n", + "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", + "The analyses consist of two major components: \n", + " 1. Within-city variations\n", + " - Show maps of walkability indicators for all cities and do a visual sanity check to see if any issue occurs\n", + " - Interpret the within-city variation patterns\n", + " - Pick one or two cities as examples, plot different indicators and compare, interprete the within-city variations and how that may or may not represent the real-world situation\n", + "\n", + " 2. Between-city analysis\n", + " - Show tables for measurements and raw indicator number, rank cities from the highest to the lowest, and interprete the results\n", + " - Plot in a world map using graduated symbol or color to visualize and compare indicators across cities\n", + " - Create box plot to compare median statistics across cities\n", + " - We could may be do similar analyses like policy indicators analyses to color code cities based on the lancet study threshold?\n", + " \n", + "\n", + "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import geopandas as gpd\n", + "import pandas as pd\n", + "import os\n", + "import json\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "image_path = './images'\n", + "dpi = 300\n", + "\n", + "process_folder = '../process'\n", + "process_config_path = '../process/configuration/cities.json'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "with open(process_config_path) as json_file:\n", + " config = json.load(json_file)\n", + "\n", + "output_folder = os.path.join(process_folder, config['folder'])\n", + "input_folder = os.path.join(process_folder, config['input_folder'])\n", + "\n", + "# the path of \"global_indicators_hex_250m.gpkg\"\n", + "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", + "\n", + "# create the path of \"global_indicators_city.gpkg\"\n", + "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "cities = ['adelaide',\n", + " 'auckland',\n", + " 'baltimore',\n", + " 'bangkok',\n", + " 'barcelona',\n", + " 'belfast',\n", + " 'bern',\n", + " 'chennai',\n", + " 'mexico_city',\n", + " 'cologne',\n", + " 'ghent',\n", + " 'graz',\n", + " 'hanoi',\n", + " 'hong_kong',\n", + " 'lisbon',\n", + " 'melbourne',\n", + " 'odense',\n", + " 'olomouc',\n", + " 'sao_paulo',\n", + " 'phoenix',\n", + " 'seattle',\n", + " 'sydney',\n", + " 'valencia',\n", + " 'vic']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## All cities hex-level indicators boxplot" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "334003" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# concat all hexes for all cities in one big dataframe\n", + "all_hexes=pd.DataFrame()\n", + "\n", + "for city in cities:\n", + " #read file\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " hex250['city'] = city\n", + " # append all hexes into one dataframe for analysis\n", + " all_hexes = pd.concat([all_hexes, hex250], ignore_index=True)\n", + "\n", + "len(all_hexes)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['index', 'study_region', 'urban_sample_point_count',\n", + " 'pct_access_500m_fresh_food_market_binary',\n", + " 'pct_access_500m_convenience_binary',\n", + " 'pct_access_500m_pt_osm_any_binary',\n", + " 'pct_access_500m_public_open_space_any_binary',\n", + " 'pct_access_500m_public_open_space_large_binary',\n", + " 'pct_access_500m_pt_gtfs_any_binary',\n", + " 'pct_access_500m_pt_gtfs_freq_30_binary',\n", + " 'pct_access_500m_pt_gtfs_freq_20_binary',\n", + " 'pct_access_500m_pt_any_binary', 'local_nh_population_density',\n", + " 'local_nh_intersection_density', 'local_daily_living',\n", + " 'local_walkability', 'all_cities_z_nh_population_density',\n", + " 'all_cities_z_nh_intersection_density', 'all_cities_z_daily_living',\n", + " 'all_cities_walkability', 'geometry', 'city'],\n", + " dtype='object')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "all_hexes.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "figs = {'all_cities_walkability': {'note': 'Sum z-scores of pop density + intersect density + daily living, hex-level',\n", + " 'title': 'Walkability Index (place-based, not pop weighted)',\n", + " 'filename': 'boxplot-walkability_unweighted.png'},\n", + " 'local_daily_living': {'note': 'Sum of binary accessibility to all daily living destinations',\n", + " 'title': 'Daily Living Scores',\n", + " 'filename': 'boxplot-daily_living.png'},\n", + " 'local_nh_population_density': {'note': 'Population per km2, hex-level',\n", + " 'title': 'Local Population Density',\n", + " 'filename': 'boxplot-pop_density.png'},\n", + " 'local_nh_intersection_density': {'note': 'Intersections per km2, hex-level',\n", + " 'title': 'Local Intersection Density',\n", + " 'filename': 'boxplot-intersect_density.png'}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "sns.set_style('whitegrid') #visual styles\n", + "sns.set_context('paper') #presets for scaling figure element sizes" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "for col, details in figs.items():\n", + "\n", + " #order by median\n", + " median_order = all_hexes.groupby(by=['study_region'])[col].median().sort_values().index\n", + "\n", + " fig, ax = plt.subplots(figsize=(8, 6))\n", + "\n", + " # switch x and y\n", + " ax=sns.boxplot(ax=ax, y=all_hexes['study_region'], x=all_hexes[col],\n", + " order=median_order, palette='Blues', width=0.6,\n", + " fliersize=0.05, boxprops={'alpha':0.7})\n", + " ax.tick_params(axis='both', which='major')\n", + " ax.set_xlabel(details['note'])\n", + " ax.set_ylabel('')\n", + "\n", + " # add a title to the figure\n", + " ax.set_title(details['title'], fontsize=16)\n", + " fig.tight_layout()\n", + "\n", + " save_path = os.path.join(image_path, details['filename'])\n", + " fig.savefig(save_path, dpi=300, bbox_inches='tight')\n", + " plt.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## All cities pop-weighted hex-level indicators boxplot (work-in-progress)\n", + "\n", + "Pop-weighted hex-level indicators are not currently in our processing scripts but we may want to include this for consistency with the city-level indicators" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def aggregation_hexes_pop_weighted(input_gdf, out_gdf, fieldNames):\n", + " \"\"\"\n", + " Aggregating hexagon level indicators by weighted population\n", + " Parameters\n", + "\n", + " \"\"\"\n", + " # loop over each indicators field names of input and output gdf\n", + " for field in fieldNames:\n", + " # calculate the population weighted indicators based on input hexagon layer\n", + " # sum to aggregate up to the city level\n", + " out_gdf[field[1]] = (input_gdf[sc.cities_parameters[\"pop_est\"]] * input_gdf[field[0]]) / (\n", + " input_gdf[sc.cities_parameters[\"pop_est\"]].sum())\n", + " return out_gdf\n", + "\n", + "\n", + "def calc_hexes_pop_pct_indicators(gpkg_hex_250m, city, gpkg_input, gpkg_output):\n", + " \"\"\"\n", + " Calculate population-weighted hex-level indicators,\n", + " and save to output geopackage\n", + " \"\"\"\n", + " gdf_hex = gpd.read_file(gpkg_hex_250m, layer=city)\n", + "\n", + " gdf_hex_origin = gpd.read_file(gpkg_input, layer=sc.cities_parameters[\"hex250\"])\n", + " # join pop_est from original hex to processed hex\n", + " gdf_hex = gdf_hex.join(gdf_hex_origin.set_index(\"index\"), on=\"index\", how=\"left\", rsuffix=\"_origin\")\n", + "\n", + " # hex-level field names from city-specific hex indicators gpkg\n", + " fieldNames = sc.hex_fieldNames[3:-1]\n", + " \n", + " # new file names for population-weighted city-level indicators\n", + " fieldNames_new = sc.city_fieldNames[2:-1]\n", + " \n", + " # calculate the population weighted city-level indicators\n", + " gdf_hexes = aggregation_hexes_pop_weighted(gdf_hex, gdf_hex, list(zip(fieldNames, fieldNames_new)))\n", + " \n", + " #gdf_hexes.to_file(gpkg_output, layer=city, driver=\"GPKG\")\n", + " return gdf_hexes" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'dirname' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mgpkgInput_ori\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mgpkg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"gpkgNames\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mgpkgInput_ori\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdirname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minput_folder\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgpkg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'dirname' is not defined" + ] + } + ], + "source": [ + "# read pre-prepared sample point stats of each city from disk\n", + "gpkgInput_ori = []\n", + "for gpkg in list(config[\"gpkgNames\"].values()):\n", + " gpkgInput_ori.append(os.path.join(dirname, input_folder, gpkg))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "all_hexes1=pd.DataFrame()\n", + "cities = list(config[\"gpkgNames\"].keys())\n", + "\n", + "for index, gpkgInput in enumerate(gpkgInput_ori):\n", + " #print(index, gpkgInput)\n", + " gdf_hexes = calc_hexes_pop_pct_indicators(gpkgOutput_hex250, cities[index], \n", + " gpkgInput, gpkgOutput_hex250) \n", + " # append all hexes into one dataframe for analysis\n", + " all_hexes1 = pd.concat([all_hexes1, gdf_hexes], ignore_index=True)\n", + "\n", + "all_hexes1.columns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# check if the results are the same as city-level outputs\n", + "all_hexes1[['study_region', 'all_cities_pop_walkability', 'all_cities_pop_z_daily_living',\n", + " 'all_cities_pop_z_nh_intersection_density',\n", + " 'all_cities_pop_z_nh_population_density']].groupby('study_region').sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# library & dataset\n", + "import seaborn as sns\n", + "\n", + "col ='all_cities_pop_walkability'\n", + "\n", + "#order by median\n", + "median_order = all_hexes1.groupby(by=['study_region'])[col].median().sort_values().index\n", + "\n", + "fig, ax = plt.subplots(figsize=(20, 10))\n", + "\n", + "# Just switch x and y\n", + "ax=sns.boxplot(ax=ax, y=all_hexes1['study_region'], x=all_hexes1[col], order=median_order, palette=\"Blues\", width=0.6)\n", + "ax.tick_params(axis='both', which='major', labelsize=14)\n", + "ax.set_xlabel('Walkability index (Z Scores)', fontsize=16)\n", + "ax.set_ylabel('Study region', fontsize=16)\n", + "ax.set(xlim=(-0.005, 0.008))\n", + "\n", + "# add a title to the figure\n", + "fig.suptitle('Walkability Index \\n ( weighted by population)', y=0.95, fontsize=20, weight='bold')\n", + "\n", + "fig.text(0.1, 0, 'Note: Population-weighted walkability index relative to all cities - sum of the population-weighted z-scores of pop and intersection density, and daily living generated at the hex level; ranked by median \\n', \n", + " fontsize=12, color='#555555')\n", + "\n", + "#fig.savefig('figure/walkability_popweighted.png', dpi=600)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/analysis/analysis-within-city-casestudies.ipynb b/analysis/analysis-within-city-casestudies.ipynb index 33363830..d94d9889 100644 --- a/analysis/analysis-within-city-casestudies.ipynb +++ b/analysis/analysis-within-city-casestudies.ipynb @@ -1,663 +1,663 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Visualization and data analysis of output indicators \n", - "\n", - "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", - " - Uses 4 sample cities, plots different indicators and compare, interpret the within-city variations and how that may or may not represent the real-world situation\n", - "\n", - "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import geopandas as gpd\n", - "import json\n", - "import os\n", - "import matplotlib.pyplot as plt\n", - "import osmnx as ox\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "image_path = './images'\n", - "dpi = 300\n", - "\n", - "process_folder = '../process'\n", - "process_config_path = '../process/configuration/cities.json'" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "with open(process_config_path) as json_file:\n", - " config = json.load(json_file)\n", - "\n", - "output_folder = os.path.join(process_folder, config['folder'])\n", - "input_folder = os.path.join(process_folder, config['input_folder'])\n", - "\n", - "# the path of \"global_indicators_hex_250m.gpkg\"\n", - "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", - "\n", - "# create the path of \"global_indicators_city.gpkg\"\n", - "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "cities = ['adelaide',\n", - " 'auckland',\n", - " 'baltimore',\n", - " 'bangkok',\n", - " 'barcelona',\n", - " 'belfast',\n", - " 'bern',\n", - " 'chennai',\n", - " 'mexico_city',\n", - " 'cologne',\n", - " 'ghent',\n", - " 'graz',\n", - " 'hanoi',\n", - " 'hong_kong',\n", - " 'lisbon',\n", - " 'melbourne',\n", - " 'odense',\n", - " 'olomouc',\n", - " 'sao_paulo',\n", - " 'phoenix',\n", - " 'seattle',\n", - " 'sydney',\n", - " 'valencia',\n", - " 'vic']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plot Example Cities" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "scheme = 'NaturalBreaks'\n", - "k = 5\n", - "cmap = 'plasma'\n", - "edgecolor = 'none'\n", - "city_color = 'none'\n", - "city_edge = 'w'\n", - "city_edge_lw = 0.2\n", - "title_y = 1.02\n", - "title_fontsize = 16\n", - "title_weight = 'bold'\n", - "\n", - "fontcolor = 'w'\n", - "params = {\"text.color\" : fontcolor,\n", - " \"ytick.color\" : fontcolor,\n", - " \"xtick.color\" : fontcolor}\n", - "plt.rcParams.update(params)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def plot_within(gpkgOutput_hex250, gpkgOutput_cities, filepath, figsize=(14, 8), facecolor=\"k\", nrows=2, ncols=3, projected=True):\n", - "\n", - " cols=['all_cities_walkability', \n", - " 'pct_access_500m_public_open_space_any_binary',\n", - " 'pct_access_500m_public_open_space_large_binary',\n", - " 'pct_access_500m_pt_gtfs_any_binary',\n", - " 'pct_access_500m_pt_gtfs_freq_20_binary',\n", - " 'pct_access_500m_pt_gtfs_freq_30_binary']\n", - "\n", - " fig, axes = plt.subplots(figsize=figsize, facecolor=facecolor, nrows=nrows, ncols=ncols,)\n", - "\n", - " for ax, col in zip(axes.flatten(), cols):\n", - " # the path of \"global_indicators_hex_250m.gpkg\"\n", - " gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", - "\n", - " # create the path of \"global_indicators_city.gpkg\"\n", - " gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])\n", - " \n", - " # from filepaths, extract city-level data\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", - " \n", - " # plot hexplot and city boundaries\n", - " _ = hex250.plot(ax=ax, column=col, scheme=scheme, k=k, cmap=cmap, edgecolor=edgecolor,\n", - " label=city, legend=False, legend_kwds=None)\n", - " _ = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - "\n", - " # add titles\n", - " fig.suptitle(f\"{city} Within-city Indicators\", color=fontcolor, fontsize=20, weight='bold')\n", - " ax.set_title(col, color=fontcolor, fontsize=10)\n", - " ax.set_axis_off()\n", - "\n", - " # save to disk\n", - " save_path = os.path.join(image_path, f\"{city}-within-maps.png\")\n", - " fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", - " plt.close()\n", - " \n", - " print(ox.ts(), f'figures saved to disk at \"{filepath}\"')\n", - "\n", - " return fig, axes" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 06:57:54 begin mapping adelaide\n", - "2020-10-05 06:58:07 figures saved to disk at \"./images\"\n", - "2020-10-05 06:58:17 figures saved to disk at \"./images\"\n", - "2020-10-05 06:58:27 figures saved to disk at \"./images\"\n", - "2020-10-05 06:58:37 figures saved to disk at \"./images\"\n", - "2020-10-05 06:58:47 figures saved to disk at \"./images\"\n", - "2020-10-05 06:58:57 figures saved to disk at \"./images\"\n", - "2020-10-05 06:58:57 begin mapping auckland\n", - "2020-10-05 06:59:06 figures saved to disk at \"./images\"\n", - "2020-10-05 06:59:17 figures saved to disk at \"./images\"\n", - "2020-10-05 06:59:27 figures saved to disk at \"./images\"\n", - "2020-10-05 06:59:37 figures saved to disk at \"./images\"\n", - "2020-10-05 06:59:48 figures saved to disk at \"./images\"\n", - "2020-10-05 06:59:58 figures saved to disk at \"./images\"\n", - "2020-10-05 06:59:58 begin mapping baltimore\n", - "2020-10-05 07:00:11 figures saved to disk at \"./images\"\n", - "2020-10-05 07:00:24 figures saved to disk at \"./images\"\n", - "2020-10-05 07:00:36 figures saved to disk at \"./images\"\n", - "2020-10-05 07:00:48 figures saved to disk at \"./images\"\n", - "2020-10-05 07:01:02 figures saved to disk at \"./images\"\n", - "2020-10-05 07:01:16 figures saved to disk at \"./images\"\n", - "2020-10-05 07:01:16 begin mapping bangkok\n", - "2020-10-05 07:01:37 figures saved to disk at \"./images\"\n", - "2020-10-05 07:01:58 figures saved to disk at \"./images\"\n", - "2020-10-05 07:02:21 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:02:43 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:03:06 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:03:26 figures saved to disk at \"./images\"\n", - "2020-10-05 07:03:27 begin mapping barcelona\n", - "2020-10-05 07:03:38 figures saved to disk at \"./images\"\n", - "2020-10-05 07:03:48 figures saved to disk at \"./images\"\n", - "2020-10-05 07:03:58 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:08 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:16 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:27 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:27 begin mapping belfast\n", - "2020-10-05 07:04:32 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:36 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:40 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:43 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:47 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:51 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:51 begin mapping bern\n", - "2020-10-05 07:04:55 figures saved to disk at \"./images\"\n", - "2020-10-05 07:04:57 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:00 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:02 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:05 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:07 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:07 begin mapping chennai\n", - "2020-10-05 07:05:17 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:27 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:35 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:46 figures saved to disk at \"./images\"\n", - "2020-10-05 07:05:55 figures saved to disk at \"./images\"\n", - "2020-10-05 07:06:05 figures saved to disk at \"./images\"\n", - "2020-10-05 07:06:05 begin mapping mexico_city\n", - "2020-10-05 07:06:56 figures saved to disk at \"./images\"\n", - "2020-10-05 07:07:46 figures saved to disk at \"./images\"\n", - "2020-10-05 07:08:40 figures saved to disk at \"./images\"\n", - "2020-10-05 07:09:27 figures saved to disk at \"./images\"\n", - "2020-10-05 07:10:16 figures saved to disk at \"./images\"\n", - "2020-10-05 07:10:57 figures saved to disk at \"./images\"\n", - "2020-10-05 07:10:57 begin mapping cologne\n", - "2020-10-05 07:11:07 figures saved to disk at \"./images\"\n", - "2020-10-05 07:11:17 figures saved to disk at \"./images\"\n", - "2020-10-05 07:11:26 figures saved to disk at \"./images\"\n", - "2020-10-05 07:11:35 figures saved to disk at \"./images\"\n", - "2020-10-05 07:11:43 figures saved to disk at \"./images\"\n", - "2020-10-05 07:11:54 figures saved to disk at \"./images\"\n", - "2020-10-05 07:11:54 begin mapping ghent\n", - "2020-10-05 07:11:59 figures saved to disk at \"./images\"\n", - "2020-10-05 07:12:03 figures saved to disk at \"./images\"\n", - "2020-10-05 07:12:06 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:12:10 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:12:13 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:12:17 figures saved to disk at \"./images\"\n", - "2020-10-05 07:12:17 begin mapping graz\n", - "2020-10-05 07:12:21 figures saved to disk at \"./images\"\n", - "2020-10-05 07:12:25 figures saved to disk at \"./images\"\n", - "2020-10-05 07:12:31 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:12:35 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:12:38 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:12:41 figures saved to disk at \"./images\"\n", - "2020-10-05 07:12:41 begin mapping hanoi\n", - "2020-10-05 07:13:01 figures saved to disk at \"./images\"\n", - "2020-10-05 07:13:24 figures saved to disk at \"./images\"\n", - "2020-10-05 07:13:51 figures saved to disk at \"./images\"\n", - "2020-10-05 07:14:10 figures saved to disk at \"./images\"\n", - "2020-10-05 07:14:27 figures saved to disk at \"./images\"\n", - "2020-10-05 07:14:42 figures saved to disk at \"./images\"\n", - "2020-10-05 07:14:42 begin mapping hong_kong\n", - "2020-10-05 07:14:52 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:02 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:09 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:18 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:27 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:35 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:35 begin mapping lisbon\n", - "2020-10-05 07:15:40 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:43 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:48 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:51 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:55 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:58 figures saved to disk at \"./images\"\n", - "2020-10-05 07:15:58 begin mapping melbourne\n", - "2020-10-05 07:16:40 figures saved to disk at \"./images\"\n", - "2020-10-05 07:17:17 figures saved to disk at \"./images\"\n", - "2020-10-05 07:17:54 figures saved to disk at \"./images\"\n", - "2020-10-05 07:18:27 figures saved to disk at \"./images\"\n", - "2020-10-05 07:19:02 figures saved to disk at \"./images\"\n", - "2020-10-05 07:19:37 figures saved to disk at \"./images\"\n", - "2020-10-05 07:19:37 begin mapping odense\n", - "2020-10-05 07:19:41 figures saved to disk at \"./images\"\n", - "2020-10-05 07:19:44 figures saved to disk at \"./images\"\n", - "2020-10-05 07:19:49 figures saved to disk at \"./images\"\n", - "2020-10-05 07:19:53 figures saved to disk at \"./images\"\n", - "2020-10-05 07:19:58 figures saved to disk at \"./images\"\n", - "2020-10-05 07:20:03 figures saved to disk at \"./images\"\n", - "2020-10-05 07:20:03 begin mapping olomouc\n", - "2020-10-05 07:20:07 figures saved to disk at \"./images\"\n", - "2020-10-05 07:20:09 figures saved to disk at \"./images\"\n", - "2020-10-05 07:20:12 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:20:15 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:20:17 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:20:19 figures saved to disk at \"./images\"\n", - "2020-10-05 07:20:19 begin mapping sao_paulo\n", - "2020-10-05 07:20:45 figures saved to disk at \"./images\"\n", - "2020-10-05 07:21:06 figures saved to disk at \"./images\"\n", - "2020-10-05 07:21:29 figures saved to disk at \"./images\"\n", - "2020-10-05 07:22:04 figures saved to disk at \"./images\"\n", - "2020-10-05 07:22:32 figures saved to disk at \"./images\"\n", - "2020-10-05 07:22:59 figures saved to disk at \"./images\"\n", - "2020-10-05 07:22:59 begin mapping phoenix\n", - "2020-10-05 07:23:20 figures saved to disk at \"./images\"\n", - "2020-10-05 07:23:36 figures saved to disk at \"./images\"\n", - "2020-10-05 07:23:55 figures saved to disk at \"./images\"\n", - "2020-10-05 07:24:11 figures saved to disk at \"./images\"\n", - "2020-10-05 07:24:28 figures saved to disk at \"./images\"\n", - "2020-10-05 07:24:52 figures saved to disk at \"./images\"\n", - "2020-10-05 07:24:52 begin mapping seattle\n", - "2020-10-05 07:26:35 figures saved to disk at \"./images\"\n", - "2020-10-05 07:27:47 figures saved to disk at \"./images\"\n", - "2020-10-05 07:28:47 figures saved to disk at \"./images\"\n", - "2020-10-05 07:29:31 figures saved to disk at \"./images\"\n", - "2020-10-05 07:30:17 figures saved to disk at \"./images\"\n", - "2020-10-05 07:31:09 figures saved to disk at \"./images\"\n", - "2020-10-05 07:31:09 begin mapping sydney\n", - "2020-10-05 07:31:52 figures saved to disk at \"./images\"\n", - "2020-10-05 07:32:41 figures saved to disk at \"./images\"\n", - "2020-10-05 07:33:57 figures saved to disk at \"./images\"\n", - "2020-10-05 07:34:42 figures saved to disk at \"./images\"\n", - "2020-10-05 07:35:20 figures saved to disk at \"./images\"\n", - "2020-10-05 07:35:55 figures saved to disk at \"./images\"\n", - "2020-10-05 07:35:55 begin mapping valencia\n", - "2020-10-05 07:36:03 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:09 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:19 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:25 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:30 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:35 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:35 begin mapping vic\n", - "2020-10-05 07:36:38 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:41 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:43 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:36:46 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:36:48 figures saved to disk at \"./images\"\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", - " Warn(ms, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", - " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", - "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", - " gadf = 1 - self.adcm / adam\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-05 07:36:50 figures saved to disk at \"./images\"\n", - "2020-10-05 07:36:50 all done, saved figures\"\n" - ] - } - ], - "source": [ - "for city in cities:\n", - " print(ox.ts(), f\"begin mapping {city}\")\n", - " fp = image_path.format(city=city)\n", - " fig, axes = plot_within(gpkgOutput_hex250, gpkgOutput_cities, fp)\n", - "\n", - "print(ox.ts(), f'all done, saved figures\"')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python (GlobalInd)", - "language": "python", - "name": "globalind" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualization and data analysis of output indicators \n", + "\n", + "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", + " - Uses 4 sample cities, plots different indicators and compare, interpret the within-city variations and how that may or may not represent the real-world situation\n", + "\n", + "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import geopandas as gpd\n", + "import json\n", + "import os\n", + "import matplotlib.pyplot as plt\n", + "import osmnx as ox\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "image_path = './images'\n", + "dpi = 300\n", + "\n", + "process_folder = '../process'\n", + "process_config_path = '../process/configuration/cities.json'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "with open(process_config_path) as json_file:\n", + " config = json.load(json_file)\n", + "\n", + "output_folder = os.path.join(process_folder, config['folder'])\n", + "input_folder = os.path.join(process_folder, config['input_folder'])\n", + "\n", + "# the path of \"global_indicators_hex_250m.gpkg\"\n", + "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", + "\n", + "# create the path of \"global_indicators_city.gpkg\"\n", + "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "cities = ['adelaide',\n", + " 'auckland',\n", + " 'baltimore',\n", + " 'bangkok',\n", + " 'barcelona',\n", + " 'belfast',\n", + " 'bern',\n", + " 'chennai',\n", + " 'mexico_city',\n", + " 'cologne',\n", + " 'ghent',\n", + " 'graz',\n", + " 'hanoi',\n", + " 'hong_kong',\n", + " 'lisbon',\n", + " 'melbourne',\n", + " 'odense',\n", + " 'olomouc',\n", + " 'sao_paulo',\n", + " 'phoenix',\n", + " 'seattle',\n", + " 'sydney',\n", + " 'valencia',\n", + " 'vic']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot Example Cities" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "scheme = 'NaturalBreaks'\n", + "k = 5\n", + "cmap = 'plasma'\n", + "edgecolor = 'none'\n", + "city_color = 'none'\n", + "city_edge = 'w'\n", + "city_edge_lw = 0.2\n", + "title_y = 1.02\n", + "title_fontsize = 16\n", + "title_weight = 'bold'\n", + "\n", + "fontcolor = 'w'\n", + "params = {\"text.color\" : fontcolor,\n", + " \"ytick.color\" : fontcolor,\n", + " \"xtick.color\" : fontcolor}\n", + "plt.rcParams.update(params)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_within(gpkgOutput_hex250, gpkgOutput_cities, filepath, figsize=(14, 8), facecolor=\"k\", nrows=2, ncols=3, projected=True):\n", + "\n", + " cols=['all_cities_walkability', \n", + " 'pct_access_500m_public_open_space_any_binary',\n", + " 'pct_access_500m_public_open_space_large_binary',\n", + " 'pct_access_500m_pt_gtfs_any_binary',\n", + " 'pct_access_500m_pt_gtfs_freq_20_binary',\n", + " 'pct_access_500m_pt_gtfs_freq_30_binary']\n", + "\n", + " fig, axes = plt.subplots(figsize=figsize, facecolor=facecolor, nrows=nrows, ncols=ncols,)\n", + "\n", + " for ax, col in zip(axes.flatten(), cols):\n", + " # the path of \"global_indicators_hex_250m.gpkg\"\n", + " gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", + "\n", + " # create the path of \"global_indicators_city.gpkg\"\n", + " gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])\n", + " \n", + " # from filepaths, extract city-level data\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", + " \n", + " # plot hexplot and city boundaries\n", + " _ = hex250.plot(ax=ax, column=col, scheme=scheme, k=k, cmap=cmap, edgecolor=edgecolor,\n", + " label=city, legend=False, legend_kwds=None)\n", + " _ = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + "\n", + " # add titles\n", + " fig.suptitle(f\"{city} Within-city Indicators\", color=fontcolor, fontsize=20, weight='bold')\n", + " ax.set_title(col, color=fontcolor, fontsize=10)\n", + " ax.set_axis_off()\n", + "\n", + " # save to disk\n", + " save_path = os.path.join(image_path, f\"{city}-within-maps.png\")\n", + " fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", + " plt.close()\n", + " \n", + " print(ox.ts(), f'figures saved to disk at \"{filepath}\"')\n", + "\n", + " return fig, axes" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 06:57:54 begin mapping adelaide\n", + "2020-10-05 06:58:07 figures saved to disk at \"./images\"\n", + "2020-10-05 06:58:17 figures saved to disk at \"./images\"\n", + "2020-10-05 06:58:27 figures saved to disk at \"./images\"\n", + "2020-10-05 06:58:37 figures saved to disk at \"./images\"\n", + "2020-10-05 06:58:47 figures saved to disk at \"./images\"\n", + "2020-10-05 06:58:57 figures saved to disk at \"./images\"\n", + "2020-10-05 06:58:57 begin mapping auckland\n", + "2020-10-05 06:59:06 figures saved to disk at \"./images\"\n", + "2020-10-05 06:59:17 figures saved to disk at \"./images\"\n", + "2020-10-05 06:59:27 figures saved to disk at \"./images\"\n", + "2020-10-05 06:59:37 figures saved to disk at \"./images\"\n", + "2020-10-05 06:59:48 figures saved to disk at \"./images\"\n", + "2020-10-05 06:59:58 figures saved to disk at \"./images\"\n", + "2020-10-05 06:59:58 begin mapping baltimore\n", + "2020-10-05 07:00:11 figures saved to disk at \"./images\"\n", + "2020-10-05 07:00:24 figures saved to disk at \"./images\"\n", + "2020-10-05 07:00:36 figures saved to disk at \"./images\"\n", + "2020-10-05 07:00:48 figures saved to disk at \"./images\"\n", + "2020-10-05 07:01:02 figures saved to disk at \"./images\"\n", + "2020-10-05 07:01:16 figures saved to disk at \"./images\"\n", + "2020-10-05 07:01:16 begin mapping bangkok\n", + "2020-10-05 07:01:37 figures saved to disk at \"./images\"\n", + "2020-10-05 07:01:58 figures saved to disk at \"./images\"\n", + "2020-10-05 07:02:21 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:02:43 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:03:06 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:03:26 figures saved to disk at \"./images\"\n", + "2020-10-05 07:03:27 begin mapping barcelona\n", + "2020-10-05 07:03:38 figures saved to disk at \"./images\"\n", + "2020-10-05 07:03:48 figures saved to disk at \"./images\"\n", + "2020-10-05 07:03:58 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:08 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:16 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:27 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:27 begin mapping belfast\n", + "2020-10-05 07:04:32 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:36 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:40 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:43 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:47 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:51 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:51 begin mapping bern\n", + "2020-10-05 07:04:55 figures saved to disk at \"./images\"\n", + "2020-10-05 07:04:57 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:00 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:02 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:05 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:07 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:07 begin mapping chennai\n", + "2020-10-05 07:05:17 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:27 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:35 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:46 figures saved to disk at \"./images\"\n", + "2020-10-05 07:05:55 figures saved to disk at \"./images\"\n", + "2020-10-05 07:06:05 figures saved to disk at \"./images\"\n", + "2020-10-05 07:06:05 begin mapping mexico_city\n", + "2020-10-05 07:06:56 figures saved to disk at \"./images\"\n", + "2020-10-05 07:07:46 figures saved to disk at \"./images\"\n", + "2020-10-05 07:08:40 figures saved to disk at \"./images\"\n", + "2020-10-05 07:09:27 figures saved to disk at \"./images\"\n", + "2020-10-05 07:10:16 figures saved to disk at \"./images\"\n", + "2020-10-05 07:10:57 figures saved to disk at \"./images\"\n", + "2020-10-05 07:10:57 begin mapping cologne\n", + "2020-10-05 07:11:07 figures saved to disk at \"./images\"\n", + "2020-10-05 07:11:17 figures saved to disk at \"./images\"\n", + "2020-10-05 07:11:26 figures saved to disk at \"./images\"\n", + "2020-10-05 07:11:35 figures saved to disk at \"./images\"\n", + "2020-10-05 07:11:43 figures saved to disk at \"./images\"\n", + "2020-10-05 07:11:54 figures saved to disk at \"./images\"\n", + "2020-10-05 07:11:54 begin mapping ghent\n", + "2020-10-05 07:11:59 figures saved to disk at \"./images\"\n", + "2020-10-05 07:12:03 figures saved to disk at \"./images\"\n", + "2020-10-05 07:12:06 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:12:10 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:12:13 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:12:17 figures saved to disk at \"./images\"\n", + "2020-10-05 07:12:17 begin mapping graz\n", + "2020-10-05 07:12:21 figures saved to disk at \"./images\"\n", + "2020-10-05 07:12:25 figures saved to disk at \"./images\"\n", + "2020-10-05 07:12:31 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:12:35 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:12:38 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:12:41 figures saved to disk at \"./images\"\n", + "2020-10-05 07:12:41 begin mapping hanoi\n", + "2020-10-05 07:13:01 figures saved to disk at \"./images\"\n", + "2020-10-05 07:13:24 figures saved to disk at \"./images\"\n", + "2020-10-05 07:13:51 figures saved to disk at \"./images\"\n", + "2020-10-05 07:14:10 figures saved to disk at \"./images\"\n", + "2020-10-05 07:14:27 figures saved to disk at \"./images\"\n", + "2020-10-05 07:14:42 figures saved to disk at \"./images\"\n", + "2020-10-05 07:14:42 begin mapping hong_kong\n", + "2020-10-05 07:14:52 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:02 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:09 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:18 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:27 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:35 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:35 begin mapping lisbon\n", + "2020-10-05 07:15:40 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:43 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:48 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:51 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:55 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:58 figures saved to disk at \"./images\"\n", + "2020-10-05 07:15:58 begin mapping melbourne\n", + "2020-10-05 07:16:40 figures saved to disk at \"./images\"\n", + "2020-10-05 07:17:17 figures saved to disk at \"./images\"\n", + "2020-10-05 07:17:54 figures saved to disk at \"./images\"\n", + "2020-10-05 07:18:27 figures saved to disk at \"./images\"\n", + "2020-10-05 07:19:02 figures saved to disk at \"./images\"\n", + "2020-10-05 07:19:37 figures saved to disk at \"./images\"\n", + "2020-10-05 07:19:37 begin mapping odense\n", + "2020-10-05 07:19:41 figures saved to disk at \"./images\"\n", + "2020-10-05 07:19:44 figures saved to disk at \"./images\"\n", + "2020-10-05 07:19:49 figures saved to disk at \"./images\"\n", + "2020-10-05 07:19:53 figures saved to disk at \"./images\"\n", + "2020-10-05 07:19:58 figures saved to disk at \"./images\"\n", + "2020-10-05 07:20:03 figures saved to disk at \"./images\"\n", + "2020-10-05 07:20:03 begin mapping olomouc\n", + "2020-10-05 07:20:07 figures saved to disk at \"./images\"\n", + "2020-10-05 07:20:09 figures saved to disk at \"./images\"\n", + "2020-10-05 07:20:12 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:20:15 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:20:17 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:20:19 figures saved to disk at \"./images\"\n", + "2020-10-05 07:20:19 begin mapping sao_paulo\n", + "2020-10-05 07:20:45 figures saved to disk at \"./images\"\n", + "2020-10-05 07:21:06 figures saved to disk at \"./images\"\n", + "2020-10-05 07:21:29 figures saved to disk at \"./images\"\n", + "2020-10-05 07:22:04 figures saved to disk at \"./images\"\n", + "2020-10-05 07:22:32 figures saved to disk at \"./images\"\n", + "2020-10-05 07:22:59 figures saved to disk at \"./images\"\n", + "2020-10-05 07:22:59 begin mapping phoenix\n", + "2020-10-05 07:23:20 figures saved to disk at \"./images\"\n", + "2020-10-05 07:23:36 figures saved to disk at \"./images\"\n", + "2020-10-05 07:23:55 figures saved to disk at \"./images\"\n", + "2020-10-05 07:24:11 figures saved to disk at \"./images\"\n", + "2020-10-05 07:24:28 figures saved to disk at \"./images\"\n", + "2020-10-05 07:24:52 figures saved to disk at \"./images\"\n", + "2020-10-05 07:24:52 begin mapping seattle\n", + "2020-10-05 07:26:35 figures saved to disk at \"./images\"\n", + "2020-10-05 07:27:47 figures saved to disk at \"./images\"\n", + "2020-10-05 07:28:47 figures saved to disk at \"./images\"\n", + "2020-10-05 07:29:31 figures saved to disk at \"./images\"\n", + "2020-10-05 07:30:17 figures saved to disk at \"./images\"\n", + "2020-10-05 07:31:09 figures saved to disk at \"./images\"\n", + "2020-10-05 07:31:09 begin mapping sydney\n", + "2020-10-05 07:31:52 figures saved to disk at \"./images\"\n", + "2020-10-05 07:32:41 figures saved to disk at \"./images\"\n", + "2020-10-05 07:33:57 figures saved to disk at \"./images\"\n", + "2020-10-05 07:34:42 figures saved to disk at \"./images\"\n", + "2020-10-05 07:35:20 figures saved to disk at \"./images\"\n", + "2020-10-05 07:35:55 figures saved to disk at \"./images\"\n", + "2020-10-05 07:35:55 begin mapping valencia\n", + "2020-10-05 07:36:03 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:09 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:19 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:25 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:30 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:35 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:35 begin mapping vic\n", + "2020-10-05 07:36:38 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:41 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:43 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:36:46 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:36:48 figures saved to disk at \"./images\"\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1718: UserWarning: Warning: Not enough unique values in array to form k classes\n", + " Warn(ms, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:1719: UserWarning: Warning: setting k to 1\n", + " Warn(\"Warning: setting k to %d\" % uvk, UserWarning)\n", + "/opt/conda/lib/python3.7/site-packages/mapclassify/classifiers.py:890: RuntimeWarning: invalid value encountered in double_scalars\n", + " gadf = 1 - self.adcm / adam\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2020-10-05 07:36:50 figures saved to disk at \"./images\"\n", + "2020-10-05 07:36:50 all done, saved figures\"\n" + ] + } + ], + "source": [ + "for city in cities:\n", + " print(ox.ts(), f\"begin mapping {city}\")\n", + " fp = image_path.format(city=city)\n", + " fig, axes = plot_within(gpkgOutput_hex250, gpkgOutput_cities, fp)\n", + "\n", + "print(ox.ts(), f'all done, saved figures\"')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (GlobalInd)", + "language": "python", + "name": "globalind" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/analysis/analysis-within-city-maps.ipynb b/analysis/analysis-within-city-maps.ipynb index 67424883..a0b9866b 100644 --- a/analysis/analysis-within-city-maps.ipynb +++ b/analysis/analysis-within-city-maps.ipynb @@ -1,529 +1,529 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Visualization and data analysis of output indicators \n", - "\n", - "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", - "The analyses consist of two major components: \n", - " 1. Within-city variations\n", - " - Show maps of walkability indicators for all cities and do a visual sanity check to see if any issue occurs\n", - " - Interpret the within-city variation patterns\n", - " - Pick one or two cities as examples, plot different indicators and compare, interprete the within-city variations and how that may or may not represent the real-world situation\n", - "\n", - " 2. Between-city analysis\n", - " - Show tables for measurements and raw indicator number, rank cities from the highest to the lowest, and interprete the results\n", - " - Plot in a world map using graduated symbol or color to visualize and compare indicators across cities\n", - " - Create box plot to compare median statistics across cities\n", - " - We could may be do similar analyses like policy indicators analyses to color code cities based on the lancet study threshold?\n", - " \n", - "\n", - "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**\n", - " \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import geopandas as gpd\n", - "import os\n", - "import json\n", - "import matplotlib.pyplot as plt\n", - "import pandas as pd\n", - "import numpy as np\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "image_path = './images'\n", - "dpi = 300\n", - "\n", - "process_folder = '../process'\n", - "process_config_path = '../process/configuration/cities.json'" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "with open(process_config_path) as json_file:\n", - " config = json.load(json_file)\n", - "\n", - "output_folder = os.path.join(process_folder, config['folder'])\n", - "input_folder = os.path.join(process_folder, config['input_folder'])\n", - "\n", - "# the path of \"global_indicators_hex_250m.gpkg\"\n", - "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", - "\n", - "# create the path of \"global_indicators_city.gpkg\"\n", - "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "cities = ['adelaide',\n", - " 'auckland',\n", - " 'baltimore',\n", - " 'bangkok',\n", - " 'barcelona',\n", - " 'belfast',\n", - " 'bern',\n", - " 'chennai',\n", - " 'mexico_city',\n", - " 'cologne',\n", - " 'ghent',\n", - " 'graz',\n", - " 'hanoi',\n", - " 'hong_kong',\n", - " 'lisbon',\n", - " 'melbourne',\n", - " 'odense',\n", - " 'olomouc',\n", - " 'sao_paulo',\n", - " 'phoenix',\n", - " 'seattle',\n", - " 'sydney',\n", - " 'valencia',\n", - " 'vic']" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "scheme = 'NaturalBreaks'\n", - "scheme2 = 'UserDefined'\n", - "k = 5\n", - "cmap = 'plasma'\n", - "edgecolor = 'none'\n", - "city_color = 'none'\n", - "city_edge = 'w'\n", - "city_edge_lw = 0.2\n", - "title_y = 1.02\n", - "title_fontsize = 16\n", - "title_weight = 'bold'\n", - "\n", - "fontcolor = 'w'\n", - "params = {\"text.color\" : fontcolor,\n", - " \"ytick.color\" : fontcolor,\n", - " \"xtick.color\" : fontcolor}\n", - "plt.rcParams.update(params)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Master Dataframe" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "hex250_adelaide = gpd.read_file(gpkgOutput_hex250,layer='adelaide')\n", - "hex250_auckland = gpd.read_file(gpkgOutput_hex250,layer='auckland')\n", - "hex250_baltimore = gpd.read_file(gpkgOutput_hex250,layer='baltimore')\n", - "hex250_bangkok = gpd.read_file(gpkgOutput_hex250,layer='bangkok')\n", - "hex250_barcelona = gpd.read_file(gpkgOutput_hex250,layer='barcelona')\n", - "hex250_belfast = gpd.read_file(gpkgOutput_hex250,layer='belfast')\n", - "hex250_bern = gpd.read_file(gpkgOutput_hex250,layer='bern')\n", - "hex250_chennai = gpd.read_file(gpkgOutput_hex250,layer='chennai')\n", - "hex250_mexico_city = gpd.read_file(gpkgOutput_hex250,layer='mexico_city')\n", - "hex250_cologne = gpd.read_file(gpkgOutput_hex250,layer='cologne')\n", - "hex250_ghent = gpd.read_file(gpkgOutput_hex250,layer='ghent')\n", - "hex250_graz = gpd.read_file(gpkgOutput_hex250,layer='graz')\n", - "hex250_hanoi = gpd.read_file(gpkgOutput_hex250,layer='hanoi')\n", - "hex250_hong_kong = gpd.read_file(gpkgOutput_hex250,layer='hong_kong')\n", - "hex250_lisbon = gpd.read_file(gpkgOutput_hex250,layer='lisbon')\n", - "hex250_melbourne = gpd.read_file(gpkgOutput_hex250,layer='melbourne')\n", - "hex250_odense = gpd.read_file(gpkgOutput_hex250,layer='odense')\n", - "hex250_olomouc = gpd.read_file(gpkgOutput_hex250,layer='olomouc')\n", - "hex250_sao_paulo = gpd.read_file(gpkgOutput_hex250,layer='sao_paulo')\n", - "hex250_phoenix = gpd.read_file(gpkgOutput_hex250,layer='phoenix')\n", - "hex250_seattle = gpd.read_file(gpkgOutput_hex250,layer='seattle')\n", - "hex250_sydney = gpd.read_file(gpkgOutput_hex250,layer='sydney')\n", - "hex250_valencia = gpd.read_file(gpkgOutput_hex250,layer='valencia')\n", - "hex250_vic = gpd.read_file(gpkgOutput_hex250,layer='vic')" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "hex250_bangkok = hex250_bangkok.drop(['pct_access_500m_pt_gtfs_any_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", - "hex250_ghent = hex250_ghent.drop(['pct_access_500m_pt_gtfs_any_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", - "hex250_graz = hex250_graz.drop(['pct_access_500m_pt_gtfs_any_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", - "hex250_olomouc = hex250_olomouc.drop(['pct_access_500m_pt_gtfs_any_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", - "hex250_vic = hex250_vic.drop(['pct_access_500m_pt_gtfs_any_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", - " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "city_data_list = [hex250_adelaide, hex250_auckland, hex250_baltimore, hex250_bangkok,\n", - " hex250_barcelona, hex250_belfast, hex250_bern, hex250_chennai,\n", - " hex250_mexico_city, hex250_cologne, hex250_ghent, hex250_graz,\n", - " hex250_hanoi, hex250_hong_kong, hex250_lisbon, hex250_melbourne,\n", - " hex250_odense, hex250_olomouc, hex250_sao_paulo, hex250_phoenix, \n", - " hex250_seattle, hex250_sydney, hex250_valencia, hex250_vic]" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "city_data = pd.concat(city_data_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Within-city hex-level walkability maps (weighted by natural breaks)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 5min 44s, sys: 7.91 s, total: 5min 52s\n", - "Wall time: 5min 52s\n" - ] - } - ], - "source": [ - "%%time\n", - "col = 'all_cities_walkability'\n", - "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", - "\n", - "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", - " print(count, city, end=' ')\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", - "\n", - " #plot indicators\n", - " if hex250[col].sum() == 0:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " else:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " ax = hex250.plot(ax=ax, column=col, scheme=scheme2, \n", - " classification_kwds={'bins':[-4.34, -2, -1, 1, 4]},\n", - " k=k, cmap=cmap, edgecolor=edgecolor, label=city, legend=False, legend_kwds=None)\n", - "\n", - " ax.set_title(city, color=fontcolor, fontsize=10)\n", - " ax.set_axis_off()\n", - "\n", - "# add a title to the figure\n", - "fig.suptitle('Within-City Walkability Index', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", - "fig.tight_layout()\n", - "\n", - "save_path = os.path.join(image_path, 'map-walkability.png')\n", - "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", - "plt.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 50s, sys: 1.85 s, total: 3min 52s\n", - "Wall time: 3min 49s\n" - ] - } - ], - "source": [ - "%%time\n", - "col = 'pct_access_500m_public_open_space_any_binary'\n", - "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", - "\n", - "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", - " print(count, city, end=' ')\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", - " \n", - " #plot indicators\n", - " if hex250[col].sum() == 0:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " else:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", - " classification_kwds={'bins':[0.00, 13.51, 40.62, 67.06, 89.47]}, \n", - " k=k, cmap=cmap, edgecolor=edgecolor,\n", - " label=city, legend=False, legend_kwds=None)\n", - "\n", - " ax.set_title(city, color=fontcolor, fontsize=10)\n", - " ax.set_axis_off()\n", - "\n", - "# add a title to the figure\n", - "fig.suptitle('Access to Any Public Open Space', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", - "fig.tight_layout()\n", - "\n", - "save_path = os.path.join(image_path, 'map-openspace-any.png')\n", - "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", - "plt.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 41s, sys: 1.65 s, total: 3min 43s\n", - "Wall time: 3min 40s\n" - ] - } - ], - "source": [ - "%%time\n", - "col = 'pct_access_500m_public_open_space_large_binary'\n", - "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", - "\n", - "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", - " print(count, city, end=' ')\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", - " \n", - " #plot indicators\n", - " if hex250[col].sum() == 0:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " else:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", - " classification_kwds={'bins':[0.00, 12.31, 37.50, 63.48, 87.62]}, \n", - " k=k, cmap=cmap, edgecolor=edgecolor,\n", - " label=city, legend=False, legend_kwds=None)\n", - "\n", - " ax.set_title(city, color=fontcolor, fontsize=10)\n", - " ax.set_axis_off()\n", - "\n", - "# add a title to the figure\n", - "fig.suptitle('Access to Large Public Open Space', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", - "fig.tight_layout()\n", - "\n", - "save_path = os.path.join(image_path, 'map-openspace-large.png')\n", - "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", - "plt.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 19s, sys: 1.63 s, total: 3min 21s\n", - "Wall time: 3min 18s\n" - ] - } - ], - "source": [ - "%%time\n", - "col = 'pct_access_500m_pt_gtfs_any_binary'\n", - "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", - "\n", - "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", - " print(count, city, end=' ')\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", - " \n", - " #plot indicators\n", - " if hex250[col].sum() == 0:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " else:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", - " classification_kwds={'bins':[0.00, 13.64, 40.48, 66.00, 88.79]}, \n", - " k=k, cmap=cmap, edgecolor=edgecolor,\n", - " label=city, legend=False, legend_kwds=None)\n", - "\n", - " ax.set_title(city, color=fontcolor, fontsize=10)\n", - " ax.set_axis_off()\n", - "\n", - "# add a title to the figure\n", - "fig.suptitle('Access to Any Transit', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", - "fig.tight_layout()\n", - "\n", - "save_path = os.path.join(image_path, 'map-transit-any.png')\n", - "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", - "plt.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 19s, sys: 1.68 s, total: 3min 20s\n", - "Wall time: 3min 18s\n" - ] - } - ], - "source": [ - "%%time\n", - "col = 'pct_access_500m_pt_gtfs_freq_20_binary'\n", - "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", - "\n", - "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", - " print(count, city, end=' ')\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", - " \n", - " #plot indicators\n", - " if hex250[col].sum() == 0:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " else:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", - " classification_kwds={'bins':[0.00, 13.04, 39.53, 65.45, 88.57]}, \n", - " k=k, cmap=cmap, edgecolor=edgecolor,\n", - " label=city, legend=False, legend_kwds=None)\n", - " \n", - " ax.set_title(city, color=fontcolor, fontsize=10)\n", - " ax.set_axis_off()\n", - "\n", - "# add a title to the figure\n", - "fig.suptitle('Access to Transit at 20 Minute Frequency', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", - "fig.tight_layout()\n", - "\n", - "save_path = os.path.join(image_path, 'map-transit-20.png')\n", - "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", - "plt.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 4min 23s, sys: 3.55 s, total: 4min 27s\n", - "Wall time: 23min 50s\n" - ] - } - ], - "source": [ - "%%time\n", - "col = 'pct_access_500m_pt_gtfs_freq_30_binary'\n", - "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", - "\n", - "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", - " print(count, city, end=' ')\n", - " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", - " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", - " \n", - " #plot indicators\n", - " if hex250[col].sum() == 0:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " else:\n", - " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", - " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", - " classification_kwds={'bins':[0.00, 13.64, 41.18, 67.50, 89.58]}, \n", - " k=k, cmap=cmap, edgecolor=edgecolor,\n", - " label=city, legend=False, legend_kwds=None)\n", - "\n", - " ax.set_title(city, color=fontcolor, fontsize=10)\n", - " ax.set_axis_off()\n", - "\n", - "# add a title to the figure\n", - "fig.suptitle('Access to Transit at 30 Minute Frequency', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", - "fig.tight_layout()\n", - "\n", - "save_path = os.path.join(image_path, 'map-transit-30.png')\n", - "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", - "plt.close()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualization and data analysis of output indicators \n", + "\n", + "This notebook presents data visualization and analysis for output indicators from the Global indicator project. \n", + "The analyses consist of two major components: \n", + " 1. Within-city variations\n", + " - Show maps of walkability indicators for all cities and do a visual sanity check to see if any issue occurs\n", + " - Interpret the within-city variation patterns\n", + " - Pick one or two cities as examples, plot different indicators and compare, interprete the within-city variations and how that may or may not represent the real-world situation\n", + "\n", + " 2. Between-city analysis\n", + " - Show tables for measurements and raw indicator number, rank cities from the highest to the lowest, and interprete the results\n", + " - Plot in a world map using graduated symbol or color to visualize and compare indicators across cities\n", + " - Create box plot to compare median statistics across cities\n", + " - We could may be do similar analyses like policy indicators analyses to color code cities based on the lancet study threshold?\n", + " \n", + "\n", + "**Note: Refer to the [workflow documentation](https://github.com/gboeing/global-indicators/blob/master/documentation/workflow.md) for indicators tables and description**\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import geopandas as gpd\n", + "import os\n", + "import json\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "image_path = './images'\n", + "dpi = 300\n", + "\n", + "process_folder = '../process'\n", + "process_config_path = '../process/configuration/cities.json'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "with open(process_config_path) as json_file:\n", + " config = json.load(json_file)\n", + "\n", + "output_folder = os.path.join(process_folder, config['folder'])\n", + "input_folder = os.path.join(process_folder, config['input_folder'])\n", + "\n", + "# the path of \"global_indicators_hex_250m.gpkg\"\n", + "gpkgOutput_hex250 = os.path.join(output_folder, config['output_hex_250m'])\n", + "\n", + "# create the path of \"global_indicators_city.gpkg\"\n", + "gpkgOutput_cities = os.path.join(output_folder, config['global_indicators_city'])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "cities = ['adelaide',\n", + " 'auckland',\n", + " 'baltimore',\n", + " 'bangkok',\n", + " 'barcelona',\n", + " 'belfast',\n", + " 'bern',\n", + " 'chennai',\n", + " 'mexico_city',\n", + " 'cologne',\n", + " 'ghent',\n", + " 'graz',\n", + " 'hanoi',\n", + " 'hong_kong',\n", + " 'lisbon',\n", + " 'melbourne',\n", + " 'odense',\n", + " 'olomouc',\n", + " 'sao_paulo',\n", + " 'phoenix',\n", + " 'seattle',\n", + " 'sydney',\n", + " 'valencia',\n", + " 'vic']" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "scheme = 'NaturalBreaks'\n", + "scheme2 = 'UserDefined'\n", + "k = 5\n", + "cmap = 'plasma'\n", + "edgecolor = 'none'\n", + "city_color = 'none'\n", + "city_edge = 'w'\n", + "city_edge_lw = 0.2\n", + "title_y = 1.02\n", + "title_fontsize = 16\n", + "title_weight = 'bold'\n", + "\n", + "fontcolor = 'w'\n", + "params = {\"text.color\" : fontcolor,\n", + " \"ytick.color\" : fontcolor,\n", + " \"xtick.color\" : fontcolor}\n", + "plt.rcParams.update(params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Master Dataframe" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "hex250_adelaide = gpd.read_file(gpkgOutput_hex250,layer='adelaide')\n", + "hex250_auckland = gpd.read_file(gpkgOutput_hex250,layer='auckland')\n", + "hex250_baltimore = gpd.read_file(gpkgOutput_hex250,layer='baltimore')\n", + "hex250_bangkok = gpd.read_file(gpkgOutput_hex250,layer='bangkok')\n", + "hex250_barcelona = gpd.read_file(gpkgOutput_hex250,layer='barcelona')\n", + "hex250_belfast = gpd.read_file(gpkgOutput_hex250,layer='belfast')\n", + "hex250_bern = gpd.read_file(gpkgOutput_hex250,layer='bern')\n", + "hex250_chennai = gpd.read_file(gpkgOutput_hex250,layer='chennai')\n", + "hex250_mexico_city = gpd.read_file(gpkgOutput_hex250,layer='mexico_city')\n", + "hex250_cologne = gpd.read_file(gpkgOutput_hex250,layer='cologne')\n", + "hex250_ghent = gpd.read_file(gpkgOutput_hex250,layer='ghent')\n", + "hex250_graz = gpd.read_file(gpkgOutput_hex250,layer='graz')\n", + "hex250_hanoi = gpd.read_file(gpkgOutput_hex250,layer='hanoi')\n", + "hex250_hong_kong = gpd.read_file(gpkgOutput_hex250,layer='hong_kong')\n", + "hex250_lisbon = gpd.read_file(gpkgOutput_hex250,layer='lisbon')\n", + "hex250_melbourne = gpd.read_file(gpkgOutput_hex250,layer='melbourne')\n", + "hex250_odense = gpd.read_file(gpkgOutput_hex250,layer='odense')\n", + "hex250_olomouc = gpd.read_file(gpkgOutput_hex250,layer='olomouc')\n", + "hex250_sao_paulo = gpd.read_file(gpkgOutput_hex250,layer='sao_paulo')\n", + "hex250_phoenix = gpd.read_file(gpkgOutput_hex250,layer='phoenix')\n", + "hex250_seattle = gpd.read_file(gpkgOutput_hex250,layer='seattle')\n", + "hex250_sydney = gpd.read_file(gpkgOutput_hex250,layer='sydney')\n", + "hex250_valencia = gpd.read_file(gpkgOutput_hex250,layer='valencia')\n", + "hex250_vic = gpd.read_file(gpkgOutput_hex250,layer='vic')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "hex250_bangkok = hex250_bangkok.drop(['pct_access_500m_pt_gtfs_any_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", + "hex250_ghent = hex250_ghent.drop(['pct_access_500m_pt_gtfs_any_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", + "hex250_graz = hex250_graz.drop(['pct_access_500m_pt_gtfs_any_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", + "hex250_olomouc = hex250_olomouc.drop(['pct_access_500m_pt_gtfs_any_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)\n", + "hex250_vic = hex250_vic.drop(['pct_access_500m_pt_gtfs_any_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_20_binary', \n", + " 'pct_access_500m_pt_gtfs_freq_30_binary'], axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "city_data_list = [hex250_adelaide, hex250_auckland, hex250_baltimore, hex250_bangkok,\n", + " hex250_barcelona, hex250_belfast, hex250_bern, hex250_chennai,\n", + " hex250_mexico_city, hex250_cologne, hex250_ghent, hex250_graz,\n", + " hex250_hanoi, hex250_hong_kong, hex250_lisbon, hex250_melbourne,\n", + " hex250_odense, hex250_olomouc, hex250_sao_paulo, hex250_phoenix, \n", + " hex250_seattle, hex250_sydney, hex250_valencia, hex250_vic]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "city_data = pd.concat(city_data_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Within-city hex-level walkability maps (weighted by natural breaks)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 5min 44s, sys: 7.91 s, total: 5min 52s\n", + "Wall time: 5min 52s\n" + ] + } + ], + "source": [ + "%%time\n", + "col = 'all_cities_walkability'\n", + "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", + "\n", + "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", + " print(count, city, end=' ')\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", + "\n", + " #plot indicators\n", + " if hex250[col].sum() == 0:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " else:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " ax = hex250.plot(ax=ax, column=col, scheme=scheme2, \n", + " classification_kwds={'bins':[-4.34, -2, -1, 1, 4]},\n", + " k=k, cmap=cmap, edgecolor=edgecolor, label=city, legend=False, legend_kwds=None)\n", + "\n", + " ax.set_title(city, color=fontcolor, fontsize=10)\n", + " ax.set_axis_off()\n", + "\n", + "# add a title to the figure\n", + "fig.suptitle('Within-City Walkability Index', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", + "fig.tight_layout()\n", + "\n", + "save_path = os.path.join(image_path, 'map-walkability.png')\n", + "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", + "plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 50s, sys: 1.85 s, total: 3min 52s\n", + "Wall time: 3min 49s\n" + ] + } + ], + "source": [ + "%%time\n", + "col = 'pct_access_500m_public_open_space_any_binary'\n", + "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", + "\n", + "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", + " print(count, city, end=' ')\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", + " \n", + " #plot indicators\n", + " if hex250[col].sum() == 0:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " else:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", + " classification_kwds={'bins':[0.00, 13.51, 40.62, 67.06, 89.47]}, \n", + " k=k, cmap=cmap, edgecolor=edgecolor,\n", + " label=city, legend=False, legend_kwds=None)\n", + "\n", + " ax.set_title(city, color=fontcolor, fontsize=10)\n", + " ax.set_axis_off()\n", + "\n", + "# add a title to the figure\n", + "fig.suptitle('Access to Any Public Open Space', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", + "fig.tight_layout()\n", + "\n", + "save_path = os.path.join(image_path, 'map-openspace-any.png')\n", + "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", + "plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 41s, sys: 1.65 s, total: 3min 43s\n", + "Wall time: 3min 40s\n" + ] + } + ], + "source": [ + "%%time\n", + "col = 'pct_access_500m_public_open_space_large_binary'\n", + "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", + "\n", + "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", + " print(count, city, end=' ')\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", + " \n", + " #plot indicators\n", + " if hex250[col].sum() == 0:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " else:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", + " classification_kwds={'bins':[0.00, 12.31, 37.50, 63.48, 87.62]}, \n", + " k=k, cmap=cmap, edgecolor=edgecolor,\n", + " label=city, legend=False, legend_kwds=None)\n", + "\n", + " ax.set_title(city, color=fontcolor, fontsize=10)\n", + " ax.set_axis_off()\n", + "\n", + "# add a title to the figure\n", + "fig.suptitle('Access to Large Public Open Space', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", + "fig.tight_layout()\n", + "\n", + "save_path = os.path.join(image_path, 'map-openspace-large.png')\n", + "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", + "plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 19s, sys: 1.63 s, total: 3min 21s\n", + "Wall time: 3min 18s\n" + ] + } + ], + "source": [ + "%%time\n", + "col = 'pct_access_500m_pt_gtfs_any_binary'\n", + "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", + "\n", + "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", + " print(count, city, end=' ')\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", + " \n", + " #plot indicators\n", + " if hex250[col].sum() == 0:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " else:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", + " classification_kwds={'bins':[0.00, 13.64, 40.48, 66.00, 88.79]}, \n", + " k=k, cmap=cmap, edgecolor=edgecolor,\n", + " label=city, legend=False, legend_kwds=None)\n", + "\n", + " ax.set_title(city, color=fontcolor, fontsize=10)\n", + " ax.set_axis_off()\n", + "\n", + "# add a title to the figure\n", + "fig.suptitle('Access to Any Transit', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", + "fig.tight_layout()\n", + "\n", + "save_path = os.path.join(image_path, 'map-transit-any.png')\n", + "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", + "plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 3min 19s, sys: 1.68 s, total: 3min 20s\n", + "Wall time: 3min 18s\n" + ] + } + ], + "source": [ + "%%time\n", + "col = 'pct_access_500m_pt_gtfs_freq_20_binary'\n", + "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", + "\n", + "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", + " print(count, city, end=' ')\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", + " \n", + " #plot indicators\n", + " if hex250[col].sum() == 0:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " else:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", + " classification_kwds={'bins':[0.00, 13.04, 39.53, 65.45, 88.57]}, \n", + " k=k, cmap=cmap, edgecolor=edgecolor,\n", + " label=city, legend=False, legend_kwds=None)\n", + " \n", + " ax.set_title(city, color=fontcolor, fontsize=10)\n", + " ax.set_axis_off()\n", + "\n", + "# add a title to the figure\n", + "fig.suptitle('Access to Transit at 20 Minute Frequency', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", + "fig.tight_layout()\n", + "\n", + "save_path = os.path.join(image_path, 'map-transit-20.png')\n", + "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", + "plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 adelaide 1 auckland 2 baltimore 3 bangkok 4 barcelona 5 belfast 6 bern 7 chennai 8 mexico_city 9 cologne 10 ghent 11 graz 12 hanoi 13 hong_kong 14 lisbon 15 melbourne 16 odense 17 olomouc 18 sao_paulo 19 phoenix 20 seattle 21 sydney 22 valencia 23 vic CPU times: user 4min 23s, sys: 3.55 s, total: 4min 27s\n", + "Wall time: 23min 50s\n" + ] + } + ], + "source": [ + "%%time\n", + "col = 'pct_access_500m_pt_gtfs_freq_30_binary'\n", + "fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(8, 8), facecolor='k')\n", + "\n", + "for count, (ax, city) in enumerate(zip(axes.flatten(), cities)):\n", + " print(count, city, end=' ')\n", + " hex250 = gpd.read_file(gpkgOutput_hex250, layer=city)\n", + " city_bound = gpd.read_file(gpkgOutput_cities, layer=city)\n", + " \n", + " #plot indicators\n", + " if hex250[col].sum() == 0:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " else:\n", + " ax = city_bound.plot(ax=ax, color=city_color, edgecolor=city_edge, linewidth=city_edge_lw)\n", + " ax = hex250.plot(ax=ax, column=col, scheme=scheme2,\n", + " classification_kwds={'bins':[0.00, 13.64, 41.18, 67.50, 89.58]}, \n", + " k=k, cmap=cmap, edgecolor=edgecolor,\n", + " label=city, legend=False, legend_kwds=None)\n", + "\n", + " ax.set_title(city, color=fontcolor, fontsize=10)\n", + " ax.set_axis_off()\n", + "\n", + "# add a title to the figure\n", + "fig.suptitle('Access to Transit at 30 Minute Frequency', y=title_y, fontsize=title_fontsize, weight=title_weight)\n", + "fig.tight_layout()\n", + "\n", + "save_path = os.path.join(image_path, 'map-transit-30.png')\n", + "fig.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor=fig.get_facecolor())\n", + "plt.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/analysis/data/cities_continents.csv b/analysis/data/cities_continents.csv index 79f4b987..4dde725a 100644 --- a/analysis/data/cities_continents.csv +++ b/analysis/data/cities_continents.csv @@ -1,25 +1,25 @@ -City,Country,Continents -Auckland,New Zealand,Zealandia -Hong Kong,China,Asia -Hanoi,Vietnam,Asia -Cologne,Germany,Europe -Adelaide,Australia,Australia -Phoenix,United States of America,"America, North" -Sydney,Australia,Australia -Melbourne,Australia,Australia -Mexico City,Mexico,"America, North" -Baltimore,United States of America,"America, North" -Bangkok,Thailand,Asia -Sao Paulo,Brazil,"America, South" -Seattle,United States of America,"America, North" -Vic,Spain,Europe -Olomouc,Czechia,Europe -Lisbon,Portugal,Europe -Valencia,Spain,Europe -Odense,Denmark,Europe -Graz,Austria,Europe -Ghent,Belgium,Europe -Belfast,Northern Ireland,Europe -Bern,Switzerland,Europe -Chennai,India,Asia +City,Country,Continents +Auckland,New Zealand,Zealandia +Hong Kong,China,Asia +Hanoi,Vietnam,Asia +Cologne,Germany,Europe +Adelaide,Australia,Australia +Phoenix,United States of America,"America, North" +Sydney,Australia,Australia +Melbourne,Australia,Australia +Mexico City,Mexico,"America, North" +Baltimore,United States of America,"America, North" +Bangkok,Thailand,Asia +Sao Paulo,Brazil,"America, South" +Seattle,United States of America,"America, North" +Vic,Spain,Europe +Olomouc,Czechia,Europe +Lisbon,Portugal,Europe +Valencia,Spain,Europe +Odense,Denmark,Europe +Graz,Austria,Europe +Ghent,Belgium,Europe +Belfast,Northern Ireland,Europe +Bern,Switzerland,Europe +Chennai,India,Asia Barcelona,Spain,Europe \ No newline at end of file diff --git a/analysis/readme.md b/analysis/readme.md index 785ea649..c71fc87d 100644 --- a/analysis/readme.md +++ b/analysis/readme.md @@ -1,28 +1,28 @@ -# Indicators Analysis - -This folder contains notebooks to generate visualizations and calculate descriptive stats of the global livability indicators calculated in the process folder. These analyses include within-city and between-city analyses. - -## Instructions - -To run the notebooks: - - 1. Download all the indicators data output GeoPackages from [Cloudstor](https://cloudstor.aarnet.edu.au/plus/s/nYtHf1UqN9AAZX1). These include: - - Hex-level output: global_indicators_hex_250m.gpkg. - - City-level output: global_indicators_city.gpkg. - - City-specific output: studyregion_country_yyyy_1600m_outputyyyymmdd.gpkg (e.g. phoenix_us_2020_1600m_buffer_output20200820.gpkg). - 2. Place the hex- and city-level indicators output data in the process/data/output folder, and the city-specific output in the process/data/input folder - 3. Run the notebooks. - -## Development Guidelines - -### Image/Mapping Guidelines - - - Generated figures should not exceed 8-inches in their largest dimension or 600 DPI when saving - - Maps should have a black background, title, and scalebar - - Maps should use the plasma colormap - - Maps' data should range from "worst" values (eg, low walkability) in a dark color to "best" values in a light color (eg, high walkability) - -### Commit Guidelines - - - Make sure no images appear inline in notebooks. - - Do not commit any image files. +# Indicators Analysis + +This folder contains notebooks to generate visualizations and calculate descriptive stats of the global livability indicators calculated in the process folder. These analyses include within-city and between-city analyses. + +## Instructions + +To run the notebooks: + + 1. Download all the indicators data output GeoPackages from [Cloudstor](https://cloudstor.aarnet.edu.au/plus/s/nYtHf1UqN9AAZX1). These include: + - Hex-level output: global_indicators_hex_250m.gpkg. + - City-level output: global_indicators_city.gpkg. + - City-specific output: studyregion_country_yyyy_1600m_outputyyyymmdd.gpkg (e.g. phoenix_us_2020_1600m_buffer_output20200820.gpkg). + 2. Place the hex- and city-level indicators output data in the process/data/output folder, and the city-specific output in the process/data/input folder + 3. Run the notebooks. + +## Development Guidelines + +### Image/Mapping Guidelines + + - Generated figures should not exceed 8-inches in their largest dimension or 600 DPI when saving + - Maps should have a black background, title, and scalebar + - Maps should use the plasma colormap + - Maps' data should range from "worst" values (eg, low walkability) in a dark color to "best" values in a light color (eg, high walkability) + +### Commit Guidelines + + - Make sure no images appear inline in notebooks. + - Do not commit any image files. diff --git a/docker-bash.sh b/docker-bash.sh index 27676146..25191423 100644 --- a/docker-bash.sh +++ b/docker-bash.sh @@ -1,3 +1,3 @@ -docker pull gboeing/global-indicators:latest -git pull -docker run --rm -it --shm-size=2g --net=host -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash +docker pull gboeing/global-indicators:latest +git pull +docker run --rm -it --shm-size=2g --net=host -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash diff --git a/docker-jupyter.sh b/docker-jupyter.sh index 29ac26aa..846f6b1d 100644 --- a/docker-jupyter.sh +++ b/docker-jupyter.sh @@ -1,3 +1,3 @@ -docker pull gboeing/global-indicators:latest -git pull -docker run --rm -it -p 8888:8888 -v "$PWD":/home/jovyan/work gboeing/global-indicators +docker pull gboeing/global-indicators:latest +git pull +docker run --rm -it -p 8888:8888 -v "$PWD":/home/jovyan/work gboeing/global-indicators diff --git a/docker/Dockerfile b/docker/Dockerfile index ff16e18c..f9618b11 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,74 +1,74 @@ -######################################################################## -# -# Build an image from the dockerfile: -# >>> docker build -t gboeing/global-indicators . -# -# Run bash in this container and export final conda environment to a yml file: -# >>> docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash -# >>> conda env export -n base > /home/jovyan/work/environment.yml -# -# Push to docker hub -# docker login -# docker tag gboeing/global-indicators gboeing/global-indicators:v0 -# docker push gboeing/global-indicators -# -# Run jupyter lab in this container: -# >>> docker run --rm -it -p 8888:8888 -v "%cd%":/home/jovyan/work gboeing/global-indicators -# -# Stop/delete all local docker containers/images: -# >>> docker stop $(docker ps -aq) -# >>> docker rm $(docker ps -aq) -# >>> docker rmi $(docker images -q) --force -######################################################################## - -FROM continuumio/miniconda3 -LABEL maintainer="Geoff Boeing " -LABEL url="https://github.com/gboeing/global-indicators" - -COPY requirements.txt /tmp/ - -# configure conda and install packages in one RUN to keep image tidy -RUN conda config --set show_channel_urls true && \ - conda config --set channel_priority strict && \ - conda config --prepend channels conda-forge && \ - conda update --yes -n base conda && \ - conda install --update-all --force-reinstall --yes --file /tmp/requirements.txt && \ - conda clean --all --yes && \ - conda info --all && \ - conda list && \ - # install tools for using OpenStreetMap - apt-get update && apt-get install -y osm2pgsql osmctools && \ - # Install tinytex, a minimal TeX distribution for making pdf documentation - apt-get update && apt-get install -y perl wget libfontconfig1 && \ - wget -qO- "https://yihui.org/tinytex/install-bin-unix.sh" | sh && \ - apt-get clean && \ - # Install LaTeX packages - /root/bin/tlmgr install xetex xcolor pgf fancyhdr parskip babel-english \ - units lastpage mdwtools comment fontawesome times \ - fncychap titlesec tabulary varwidth wrapfig capt-of needspace \ - polyglossia fontspec cmap gnu-freefont upquote oberdiek latexmk \ - caption makecell multirow changepage \ - --repository=http://mirror.ctan.org/systems/texlive/tlnet \ - && /root/bin/fmtutil-sys --all && \ - # Install additional LaTeX packages - # installing seperately to avoid error associated with multirow && \ - # install the make build tools, for compiling sphinx documentation - apt-get update && apt-get install -y make && \ - # install the contextily package using pip, required for validation report basemaps - pip install contextily - - -# add root/bin to path so that tex commands can be run from container -ENV PATH=$PATH:/root/bin - -# launch jupyter in the local working directory that we mount -WORKDIR /home/jovyan/work - -RUN python -m ipykernel install --name GlobalInd --display-name "Python (GlobalInd)" - -# set default command to launch when container is run -CMD ["jupyter", "lab", "--ip='0.0.0.0'", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.token=''", "--NotebookApp.password=''"] - -# to test, import OSMnx and print its version -RUN ipython -c "import osmnx; print(osmnx.__version__)" - +######################################################################## +# +# Build an image from the dockerfile: +# >>> docker build -t gboeing/global-indicators . +# +# Run bash in this container and export final conda environment to a yml file: +# >>> docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash +# >>> conda env export -n base > /home/jovyan/work/environment.yml +# +# Push to docker hub +# docker login +# docker tag gboeing/global-indicators gboeing/global-indicators:v0 +# docker push gboeing/global-indicators +# +# Run jupyter lab in this container: +# >>> docker run --rm -it -p 8888:8888 -v "%cd%":/home/jovyan/work gboeing/global-indicators +# +# Stop/delete all local docker containers/images: +# >>> docker stop $(docker ps -aq) +# >>> docker rm $(docker ps -aq) +# >>> docker rmi $(docker images -q) --force +######################################################################## + +FROM continuumio/miniconda3 +LABEL maintainer="Geoff Boeing " +LABEL url="https://github.com/gboeing/global-indicators" + +COPY requirements.txt /tmp/ + +# configure conda and install packages in one RUN to keep image tidy +RUN conda config --set show_channel_urls true && \ + conda config --set channel_priority strict && \ + conda config --prepend channels conda-forge && \ + conda update --yes -n base conda && \ + conda install --update-all --force-reinstall --yes --file /tmp/requirements.txt && \ + conda clean --all --yes && \ + conda info --all && \ + conda list && \ + # install tools for using OpenStreetMap + apt-get update && apt-get install -y osm2pgsql osmctools && \ + # Install tinytex, a minimal TeX distribution for making pdf documentation + apt-get update && apt-get install -y perl wget libfontconfig1 && \ + wget -qO- "https://yihui.org/tinytex/install-bin-unix.sh" | sh && \ + apt-get clean && \ + # Install LaTeX packages + /root/bin/tlmgr install xetex xcolor pgf fancyhdr parskip babel-english \ + units lastpage mdwtools comment fontawesome times \ + fncychap titlesec tabulary varwidth wrapfig capt-of needspace \ + polyglossia fontspec cmap gnu-freefont upquote oberdiek latexmk \ + caption makecell multirow changepage \ + --repository=http://mirror.ctan.org/systems/texlive/tlnet \ + && /root/bin/fmtutil-sys --all && \ + # Install additional LaTeX packages + # installing seperately to avoid error associated with multirow && \ + # install the make build tools, for compiling sphinx documentation + apt-get update && apt-get install -y make && \ + # install the contextily package using pip, required for validation report basemaps + pip install contextily + + +# add root/bin to path so that tex commands can be run from container +ENV PATH=$PATH:/root/bin + +# launch jupyter in the local working directory that we mount +WORKDIR /home/jovyan/work + +RUN python -m ipykernel install --name GlobalInd --display-name "Python (GlobalInd)" + +# set default command to launch when container is run +CMD ["jupyter", "lab", "--ip='0.0.0.0'", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.token=''", "--NotebookApp.password=''"] + +# to test, import OSMnx and print its version +RUN ipython -c "import osmnx; print(osmnx.__version__)" + diff --git a/docker/environment.yml b/docker/environment.yml index f68c6694..7ca8de6d 100644 --- a/docker/environment.yml +++ b/docker/environment.yml @@ -1,269 +1,269 @@ -name: base -channels: - - conda-forge - - defaults -dependencies: - - _libgcc_mutex=0.1=conda_forge - - _openmp_mutex=4.5=1_llvm - - affine=2.3.0=py_0 - - astroid=2.4.2=py37hc8dfbb8_0 - - attrs=19.3.0=py_0 - - backcall=0.1.0=py_0 - - beautifulsoup4=4.9.1=py37hc8dfbb8_0 - - bleach=3.1.5=pyh9f0ad1d_0 - - blosc=1.19.0=he1b5a44_0 - - bokeh=2.0.1=py37hc8dfbb8_0 - - boost-cpp=1.72.0=h8e57a91_0 - - bottleneck=1.3.2=py37h03ebfcd_1 - - branca=0.4.1=py_0 - - bzip2=1.0.8=h516909a_2 - - ca-certificates=2020.4.5.2=hecda079_0 - - cairo=1.16.0=hcf35c78_1003 - - cartopy=0.18.0=py37h4b180d9_0 - - certifi=2020.4.5.2=py37hc8dfbb8_0 - - cffi=1.14.0=py37hd463f26_0 - - cfitsio=3.470=h3eac812_5 - - chardet=3.0.4=py37hc8dfbb8_1006 - - click=7.1.2=pyh9f0ad1d_0 - - click-plugins=1.1.1=py_0 - - cligj=0.5.0=py_0 - - conda=4.8.3=py37hc8dfbb8_1 - - conda-package-handling=1.6.0=py37h8f50634_2 - - cryptography=2.9.2=py37hb09aad4_0 - - curl=7.69.1=h33f0ec9_0 - - cycler=0.10.0=py_2 - - cython=0.29.20=py37h3340039_0 - - decorator=4.4.2=py_0 - - defusedxml=0.6.0=py_0 - - deprecated=1.2.10=pyh9f0ad1d_0 - - descartes=1.1.0=py_4 - - entrypoints=0.3=py37hc8dfbb8_1001 - - esda=2.2.1=py_0 - - expat=2.2.9=he1b5a44_2 - - fastcache=1.1.0=py37h8f50634_1 - - fiona=1.8.13=py37h0492a4a_1 - - flake8=3.8.3=pyh9f0ad1d_0 - - folium=0.11.0=py_0 - - fontconfig=2.13.1=h86ecdb6_1001 - - freetype=2.10.2=he06d7ca_0 - - freexl=1.0.5=h14c3975_1002 - - gdal=3.0.4=py37h4b180d9_10 - - geoalchemy2=0.6.3=py_0 - - geographiclib=1.50=py_0 - - geopandas=0.7.0=py_1 - - geopy=1.22.0=pyh9f0ad1d_0 - - geos=3.8.1=he1b5a44_0 - - geotiff=1.6.0=h05acad5_0 - - gettext=0.19.8.1=hc5be6a0_1002 - - giddy=2.3.3=py_0 - - giflib=5.2.1=h516909a_2 - - glib=2.64.3=h6f030ca_0 - - gmp=6.2.0=he1b5a44_2 - - gmpy2=2.1.0b1=py37h04dde30_0 - - hdf4=4.2.13=hf30be14_1003 - - hdf5=1.10.6=nompi_h3c11f04_100 - - icu=64.2=he1b5a44_1 - - idna=2.9=py_1 - - importlib-metadata=1.6.1=py37hc8dfbb8_0 - - importlib_metadata=1.6.1=0 - - inequality=1.0.0=py_0 - - ipykernel=5.3.0=py37h43977f1_0 - - ipython=7.15.0=py37hc8dfbb8_0 - - ipython_genutils=0.2.0=py_1 - - ipywidgets=7.5.1=py_0 - - isort=4.3.21=py37hc8dfbb8_1 - - jedi=0.17.0=py37hc8dfbb8_0 - - jinja2=2.11.2=pyh9f0ad1d_0 - - joblib=0.15.1=py_0 - - jpeg=9d=h516909a_0 - - json-c=0.13.1=hbfbb72e_1002 - - json5=0.9.4=pyh9f0ad1d_0 - - jsonschema=3.2.0=py37hc8dfbb8_1 - - jupyter_client=6.1.3=py_0 - - jupyter_core=4.6.3=py37hc8dfbb8_1 - - jupyterlab=2.1.4=py_0 - - jupyterlab_server=1.1.5=py_0 - - kealib=1.4.13=h33137a7_1 - - kiwisolver=1.2.0=py37h99015e2_0 - - krb5=1.17.1=h2fd8d38_0 - - lazy-object-proxy=1.4.3=py37h8f50634_2 - - ld_impl_linux-64=2.34=h53a641e_5 - - libblas=3.8.0=16_openblas - - libcblas=3.8.0=16_openblas - - libcurl=7.69.1=hf7181ac_0 - - libdap4=3.20.6=h1d1bd15_0 - - libedit=3.1.20191231=h46ee950_0 - - libffi=3.2.1=he1b5a44_1007 - - libgcc=7.2.0=h69d50b8_2 - - libgcc-ng=9.2.0=h24d8f2e_2 - - libgdal=3.0.4=he6a97d6_10 - - libgfortran-ng=7.5.0=hdf63c60_6 - - libiconv=1.15=h516909a_1006 - - libkml=1.3.0=hb574062_1011 - - liblapack=3.8.0=16_openblas - - libllvm8=8.0.1=hc9558a2_0 - - libnetcdf=4.7.4=nompi_h84807e1_104 - - libopenblas=0.3.9=h5ec1e0e_0 - - libpng=1.6.37=hed695b0_1 - - libpq=12.2=h5513abc_1 - - libpysal=4.2.2=py_0 - - libsodium=1.0.17=h516909a_0 - - libspatialindex=1.9.3=he1b5a44_3 - - libspatialite=4.3.0a=h2482549_1038 - - libssh2=1.9.0=hab1572f_2 - - libstdcxx-ng=9.2.0=hdf63c60_2 - - libtiff=4.1.0=hc7e4089_6 - - libuuid=2.32.1=h14c3975_1000 - - libwebp-base=1.1.0=h516909a_3 - - libxcb=1.13=h14c3975_1002 - - libxml2=2.9.10=hee79883_0 - - llvm-openmp=10.0.0=hc9558a2_0 - - llvmlite=0.32.1=py37h5202443_0 - - lz4-c=1.9.2=he1b5a44_1 - - lzo=2.10=h14c3975_1000 - - mapclassify=2.2.0=py_0 - - markupsafe=1.1.1=py37h8f50634_1 - - matplotlib-base=3.2.1=py37h30547a4_0 - - mccabe=0.6.1=py_1 - - memory_profiler=0.57.0=py_0 - - mgwr=2.1.1=py_0 - - mistune=0.8.4=py37h8f50634_1001 - - mock=4.0.2=py37hc8dfbb8_0 - - mpc=1.1.0=h04dde30_1007 - - mpfr=4.0.2=he80fd80_1 - - mpmath=1.1.0=py_0 - - munch=2.5.0=py_0 - - nbconvert=5.6.1=py37hc8dfbb8_1 - - nbformat=5.0.6=py_0 - - ncurses=6.1=hf484d3e_1002 - - networkx=2.4=py_1 - - nodejs=6.13.1=0 - - nose=1.3.7=py37hc8dfbb8_1004 - - notebook=6.0.3=py37hc8dfbb8_0 - - numba=0.49.1=py37h0da4684_0 - - numexpr=2.7.1=py37h0da4684_1 - - numpy=1.17.5=py37h95a1406_0 - - olefile=0.46=py_0 - - openjpeg=2.3.1=h981e76c_3 - - openssl=1.1.1g=h516909a_0 - - osmnet=0.1.5=py_3 - - osmnx=0.14.1=pyh9f0ad1d_0 - - owslib=0.20.0=py_0 - - packaging=20.4=pyh9f0ad1d_0 - - pandana=0.4.4=py37hb3f55d8_1 - - pandas=1.0.4=py37h0da4684_0 - - pandoc=2.9.2.1=0 - - pandocfilters=1.4.2=py_1 - - parso=0.7.0=pyh9f0ad1d_0 - - patsy=0.5.1=py_0 - - pcre=8.44=he1b5a44_0 - - pexpect=4.8.0=py37hc8dfbb8_1 - - pickleshare=0.7.5=py37hc8dfbb8_1001 - - pillow=7.1.2=py37h718be6c_0 - - pip=20.1.1=py_1 - - pixman=0.38.0=h516909a_1003 - - pointpats=2.1.0=py_1 - - poppler=0.87.0=h4190859_1 - - poppler-data=0.4.9=1 - - postgresql=12.2=h8573dbc_1 - - proj=7.0.0=h966b41f_4 - - prometheus_client=0.8.0=pyh9f0ad1d_0 - - prompt-toolkit=3.0.5=py_0 - - psutil=5.7.0=py37h8f50634_1 - - psycopg2=2.8.5=py37hb09aad4_1 - - pthread-stubs=0.4=h14c3975_1001 - - ptyprocess=0.6.0=py_1001 - - pycodestyle=2.6.0=pyh9f0ad1d_0 - - pycosat=0.6.3=py37h8f50634_1004 - - pycparser=2.20=py_0 - - pyepsg=0.4.0=py_0 - - pyflakes=2.2.0=pyh9f0ad1d_0 - - pygments=2.6.1=py_0 - - pylint=2.5.2=py37hc8dfbb8_0 - - pyopenssl=19.1.0=py_1 - - pyparsing=2.4.7=pyh9f0ad1d_0 - - pyproj=2.6.1.post1=py37h34dd122_0 - - pyrsistent=0.16.0=py37h8f50634_0 - - pysal=2.2.0=py_0 - - pyshp=2.1.0=py_0 - - pysocks=1.7.1=py37hc8dfbb8_1 - - pytables=3.6.1=py37h56451d4_2 - - python=3.7.6=cpython_h8356626_6 - - python-dateutil=2.8.0=py_0 - - python_abi=3.7=1_cp37m - - pytz=2020.1=pyh9f0ad1d_0 - - pyyaml=5.3.1=py37h8f50634_0 - - pyzmq=19.0.1=py37hac76be4_0 - - quantecon=0.4.7=py37hc8dfbb8_0 - - rasterio=1.1.5=py37h0492a4a_0 - - rasterstats=0.14.0=py_0 - - readline=8.0=hf8c457e_0 - - requests=2.23.0=pyh8c360ce_2 - - rtree=0.9.4=py37h8526d28_1 - - ruamel_yaml=0.15.80=py37h8f50634_1001 - - scikit-learn=0.23.1=py37h8a51577_0 - - scipy=1.4.1=py37ha3d9a3c_3 - - seaborn=0.10.1=1 - - seaborn-base=0.10.1=py_1 - - segregation=1.2.0=py_1 - - send2trash=1.5.0=py_0 - - setuptools=47.1.1=py37hc8dfbb8_0 - - shapely=1.7.0=py37hc88ce51_3 - - simplejson=3.17.0=py37h8f50634_1 - - six=1.15.0=pyh9f0ad1d_0 - - snuggs=1.4.7=py_0 - - soupsieve=2.0.1=py37hc8dfbb8_0 - - spaghetti=1.5.0=py_0 - - spglm=1.0.7=py_0 - - spint=1.0.6=py_0 - - splot=1.1.3=py_0 - - spreg=1.1.1=py_0 - - spvcm=0.3.0=py_0 - - sqlalchemy=1.3.17=py37h8f50634_0 - - sqlite=3.30.1=hcee41ef_0 - - statsmodels=0.11.1=py37h8f50634_2 - - sympy=1.6=py37hc8dfbb8_0 - - tbb=2020.1=hc9558a2_0 - - terminado=0.8.3=py37hc8dfbb8_1 - - testpath=0.4.4=py_0 - - threadpoolctl=2.1.0=pyh5ca1d4c_0 - - tiledb=1.7.7=h8efa9f0_3 - - tk=8.6.10=hed695b0_0 - - tobler=0.3.0=py_0 - - toml=0.10.1=pyh9f0ad1d_0 - - tornado=6.0.4=py37h8f50634_1 - - tqdm=4.46.1=pyh9f0ad1d_0 - - traitlets=4.3.3=py37hc8dfbb8_1 - - typed-ast=1.4.1=py37h516909a_0 - - typing_extensions=3.7.4.2=py_0 - - tzcode=2020a=h516909a_0 - - urbanaccess=0.2.0=py_1 - - urllib3=1.24.3=py37_0 - - wcwidth=0.2.4=pyh9f0ad1d_0 - - webencodings=0.5.1=py_1 - - wheel=0.34.2=py_1 - - widgetsnbextension=3.5.1=py37_0 - - wrapt=1.11.2=py37h8f50634_0 - - xerces-c=3.2.2=h8412b87_1004 - - xlrd=1.2.0=py_0 - - xlwt=1.3.0=py_1 - - xorg-kbproto=1.0.7=h14c3975_1002 - - xorg-libice=1.0.10=h516909a_0 - - xorg-libsm=1.2.3=h84519dc_1000 - - xorg-libx11=1.6.9=h516909a_0 - - xorg-libxau=1.0.9=h14c3975_0 - - xorg-libxdmcp=1.1.3=h516909a_0 - - xorg-libxext=1.3.4=h516909a_0 - - xorg-libxrender=0.9.10=h516909a_1002 - - xorg-renderproto=0.11.1=h14c3975_1002 - - xorg-xextproto=7.3.0=h14c3975_1002 - - xorg-xproto=7.0.31=h14c3975_1007 - - xz=5.2.5=h516909a_0 - - yaml=0.2.5=h516909a_0 - - yapf=0.29.0=py_0 - - zeromq=4.3.2=he1b5a44_2 - - zipp=3.1.0=py_0 - - zlib=1.2.11=h516909a_1006 - - zstd=1.4.4=h6597ccf_3 -prefix: /opt/conda - +name: base +channels: + - conda-forge + - defaults +dependencies: + - _libgcc_mutex=0.1=conda_forge + - _openmp_mutex=4.5=1_llvm + - affine=2.3.0=py_0 + - astroid=2.4.2=py37hc8dfbb8_0 + - attrs=19.3.0=py_0 + - backcall=0.1.0=py_0 + - beautifulsoup4=4.9.1=py37hc8dfbb8_0 + - bleach=3.1.5=pyh9f0ad1d_0 + - blosc=1.19.0=he1b5a44_0 + - bokeh=2.0.1=py37hc8dfbb8_0 + - boost-cpp=1.72.0=h8e57a91_0 + - bottleneck=1.3.2=py37h03ebfcd_1 + - branca=0.4.1=py_0 + - bzip2=1.0.8=h516909a_2 + - ca-certificates=2020.4.5.2=hecda079_0 + - cairo=1.16.0=hcf35c78_1003 + - cartopy=0.18.0=py37h4b180d9_0 + - certifi=2020.4.5.2=py37hc8dfbb8_0 + - cffi=1.14.0=py37hd463f26_0 + - cfitsio=3.470=h3eac812_5 + - chardet=3.0.4=py37hc8dfbb8_1006 + - click=7.1.2=pyh9f0ad1d_0 + - click-plugins=1.1.1=py_0 + - cligj=0.5.0=py_0 + - conda=4.8.3=py37hc8dfbb8_1 + - conda-package-handling=1.6.0=py37h8f50634_2 + - cryptography=2.9.2=py37hb09aad4_0 + - curl=7.69.1=h33f0ec9_0 + - cycler=0.10.0=py_2 + - cython=0.29.20=py37h3340039_0 + - decorator=4.4.2=py_0 + - defusedxml=0.6.0=py_0 + - deprecated=1.2.10=pyh9f0ad1d_0 + - descartes=1.1.0=py_4 + - entrypoints=0.3=py37hc8dfbb8_1001 + - esda=2.2.1=py_0 + - expat=2.2.9=he1b5a44_2 + - fastcache=1.1.0=py37h8f50634_1 + - fiona=1.8.13=py37h0492a4a_1 + - flake8=3.8.3=pyh9f0ad1d_0 + - folium=0.11.0=py_0 + - fontconfig=2.13.1=h86ecdb6_1001 + - freetype=2.10.2=he06d7ca_0 + - freexl=1.0.5=h14c3975_1002 + - gdal=3.0.4=py37h4b180d9_10 + - geoalchemy2=0.6.3=py_0 + - geographiclib=1.50=py_0 + - geopandas=0.7.0=py_1 + - geopy=1.22.0=pyh9f0ad1d_0 + - geos=3.8.1=he1b5a44_0 + - geotiff=1.6.0=h05acad5_0 + - gettext=0.19.8.1=hc5be6a0_1002 + - giddy=2.3.3=py_0 + - giflib=5.2.1=h516909a_2 + - glib=2.64.3=h6f030ca_0 + - gmp=6.2.0=he1b5a44_2 + - gmpy2=2.1.0b1=py37h04dde30_0 + - hdf4=4.2.13=hf30be14_1003 + - hdf5=1.10.6=nompi_h3c11f04_100 + - icu=64.2=he1b5a44_1 + - idna=2.9=py_1 + - importlib-metadata=1.6.1=py37hc8dfbb8_0 + - importlib_metadata=1.6.1=0 + - inequality=1.0.0=py_0 + - ipykernel=5.3.0=py37h43977f1_0 + - ipython=7.15.0=py37hc8dfbb8_0 + - ipython_genutils=0.2.0=py_1 + - ipywidgets=7.5.1=py_0 + - isort=4.3.21=py37hc8dfbb8_1 + - jedi=0.17.0=py37hc8dfbb8_0 + - jinja2=2.11.2=pyh9f0ad1d_0 + - joblib=0.15.1=py_0 + - jpeg=9d=h516909a_0 + - json-c=0.13.1=hbfbb72e_1002 + - json5=0.9.4=pyh9f0ad1d_0 + - jsonschema=3.2.0=py37hc8dfbb8_1 + - jupyter_client=6.1.3=py_0 + - jupyter_core=4.6.3=py37hc8dfbb8_1 + - jupyterlab=2.1.4=py_0 + - jupyterlab_server=1.1.5=py_0 + - kealib=1.4.13=h33137a7_1 + - kiwisolver=1.2.0=py37h99015e2_0 + - krb5=1.17.1=h2fd8d38_0 + - lazy-object-proxy=1.4.3=py37h8f50634_2 + - ld_impl_linux-64=2.34=h53a641e_5 + - libblas=3.8.0=16_openblas + - libcblas=3.8.0=16_openblas + - libcurl=7.69.1=hf7181ac_0 + - libdap4=3.20.6=h1d1bd15_0 + - libedit=3.1.20191231=h46ee950_0 + - libffi=3.2.1=he1b5a44_1007 + - libgcc=7.2.0=h69d50b8_2 + - libgcc-ng=9.2.0=h24d8f2e_2 + - libgdal=3.0.4=he6a97d6_10 + - libgfortran-ng=7.5.0=hdf63c60_6 + - libiconv=1.15=h516909a_1006 + - libkml=1.3.0=hb574062_1011 + - liblapack=3.8.0=16_openblas + - libllvm8=8.0.1=hc9558a2_0 + - libnetcdf=4.7.4=nompi_h84807e1_104 + - libopenblas=0.3.9=h5ec1e0e_0 + - libpng=1.6.37=hed695b0_1 + - libpq=12.2=h5513abc_1 + - libpysal=4.2.2=py_0 + - libsodium=1.0.17=h516909a_0 + - libspatialindex=1.9.3=he1b5a44_3 + - libspatialite=4.3.0a=h2482549_1038 + - libssh2=1.9.0=hab1572f_2 + - libstdcxx-ng=9.2.0=hdf63c60_2 + - libtiff=4.1.0=hc7e4089_6 + - libuuid=2.32.1=h14c3975_1000 + - libwebp-base=1.1.0=h516909a_3 + - libxcb=1.13=h14c3975_1002 + - libxml2=2.9.10=hee79883_0 + - llvm-openmp=10.0.0=hc9558a2_0 + - llvmlite=0.32.1=py37h5202443_0 + - lz4-c=1.9.2=he1b5a44_1 + - lzo=2.10=h14c3975_1000 + - mapclassify=2.2.0=py_0 + - markupsafe=1.1.1=py37h8f50634_1 + - matplotlib-base=3.2.1=py37h30547a4_0 + - mccabe=0.6.1=py_1 + - memory_profiler=0.57.0=py_0 + - mgwr=2.1.1=py_0 + - mistune=0.8.4=py37h8f50634_1001 + - mock=4.0.2=py37hc8dfbb8_0 + - mpc=1.1.0=h04dde30_1007 + - mpfr=4.0.2=he80fd80_1 + - mpmath=1.1.0=py_0 + - munch=2.5.0=py_0 + - nbconvert=5.6.1=py37hc8dfbb8_1 + - nbformat=5.0.6=py_0 + - ncurses=6.1=hf484d3e_1002 + - networkx=2.4=py_1 + - nodejs=6.13.1=0 + - nose=1.3.7=py37hc8dfbb8_1004 + - notebook=6.0.3=py37hc8dfbb8_0 + - numba=0.49.1=py37h0da4684_0 + - numexpr=2.7.1=py37h0da4684_1 + - numpy=1.17.5=py37h95a1406_0 + - olefile=0.46=py_0 + - openjpeg=2.3.1=h981e76c_3 + - openssl=1.1.1g=h516909a_0 + - osmnet=0.1.5=py_3 + - osmnx=0.14.1=pyh9f0ad1d_0 + - owslib=0.20.0=py_0 + - packaging=20.4=pyh9f0ad1d_0 + - pandana=0.4.4=py37hb3f55d8_1 + - pandas=1.0.4=py37h0da4684_0 + - pandoc=2.9.2.1=0 + - pandocfilters=1.4.2=py_1 + - parso=0.7.0=pyh9f0ad1d_0 + - patsy=0.5.1=py_0 + - pcre=8.44=he1b5a44_0 + - pexpect=4.8.0=py37hc8dfbb8_1 + - pickleshare=0.7.5=py37hc8dfbb8_1001 + - pillow=7.1.2=py37h718be6c_0 + - pip=20.1.1=py_1 + - pixman=0.38.0=h516909a_1003 + - pointpats=2.1.0=py_1 + - poppler=0.87.0=h4190859_1 + - poppler-data=0.4.9=1 + - postgresql=12.2=h8573dbc_1 + - proj=7.0.0=h966b41f_4 + - prometheus_client=0.8.0=pyh9f0ad1d_0 + - prompt-toolkit=3.0.5=py_0 + - psutil=5.7.0=py37h8f50634_1 + - psycopg2=2.8.5=py37hb09aad4_1 + - pthread-stubs=0.4=h14c3975_1001 + - ptyprocess=0.6.0=py_1001 + - pycodestyle=2.6.0=pyh9f0ad1d_0 + - pycosat=0.6.3=py37h8f50634_1004 + - pycparser=2.20=py_0 + - pyepsg=0.4.0=py_0 + - pyflakes=2.2.0=pyh9f0ad1d_0 + - pygments=2.6.1=py_0 + - pylint=2.5.2=py37hc8dfbb8_0 + - pyopenssl=19.1.0=py_1 + - pyparsing=2.4.7=pyh9f0ad1d_0 + - pyproj=2.6.1.post1=py37h34dd122_0 + - pyrsistent=0.16.0=py37h8f50634_0 + - pysal=2.2.0=py_0 + - pyshp=2.1.0=py_0 + - pysocks=1.7.1=py37hc8dfbb8_1 + - pytables=3.6.1=py37h56451d4_2 + - python=3.7.6=cpython_h8356626_6 + - python-dateutil=2.8.0=py_0 + - python_abi=3.7=1_cp37m + - pytz=2020.1=pyh9f0ad1d_0 + - pyyaml=5.3.1=py37h8f50634_0 + - pyzmq=19.0.1=py37hac76be4_0 + - quantecon=0.4.7=py37hc8dfbb8_0 + - rasterio=1.1.5=py37h0492a4a_0 + - rasterstats=0.14.0=py_0 + - readline=8.0=hf8c457e_0 + - requests=2.23.0=pyh8c360ce_2 + - rtree=0.9.4=py37h8526d28_1 + - ruamel_yaml=0.15.80=py37h8f50634_1001 + - scikit-learn=0.23.1=py37h8a51577_0 + - scipy=1.4.1=py37ha3d9a3c_3 + - seaborn=0.10.1=1 + - seaborn-base=0.10.1=py_1 + - segregation=1.2.0=py_1 + - send2trash=1.5.0=py_0 + - setuptools=47.1.1=py37hc8dfbb8_0 + - shapely=1.7.0=py37hc88ce51_3 + - simplejson=3.17.0=py37h8f50634_1 + - six=1.15.0=pyh9f0ad1d_0 + - snuggs=1.4.7=py_0 + - soupsieve=2.0.1=py37hc8dfbb8_0 + - spaghetti=1.5.0=py_0 + - spglm=1.0.7=py_0 + - spint=1.0.6=py_0 + - splot=1.1.3=py_0 + - spreg=1.1.1=py_0 + - spvcm=0.3.0=py_0 + - sqlalchemy=1.3.17=py37h8f50634_0 + - sqlite=3.30.1=hcee41ef_0 + - statsmodels=0.11.1=py37h8f50634_2 + - sympy=1.6=py37hc8dfbb8_0 + - tbb=2020.1=hc9558a2_0 + - terminado=0.8.3=py37hc8dfbb8_1 + - testpath=0.4.4=py_0 + - threadpoolctl=2.1.0=pyh5ca1d4c_0 + - tiledb=1.7.7=h8efa9f0_3 + - tk=8.6.10=hed695b0_0 + - tobler=0.3.0=py_0 + - toml=0.10.1=pyh9f0ad1d_0 + - tornado=6.0.4=py37h8f50634_1 + - tqdm=4.46.1=pyh9f0ad1d_0 + - traitlets=4.3.3=py37hc8dfbb8_1 + - typed-ast=1.4.1=py37h516909a_0 + - typing_extensions=3.7.4.2=py_0 + - tzcode=2020a=h516909a_0 + - urbanaccess=0.2.0=py_1 + - urllib3=1.24.3=py37_0 + - wcwidth=0.2.4=pyh9f0ad1d_0 + - webencodings=0.5.1=py_1 + - wheel=0.34.2=py_1 + - widgetsnbextension=3.5.1=py37_0 + - wrapt=1.11.2=py37h8f50634_0 + - xerces-c=3.2.2=h8412b87_1004 + - xlrd=1.2.0=py_0 + - xlwt=1.3.0=py_1 + - xorg-kbproto=1.0.7=h14c3975_1002 + - xorg-libice=1.0.10=h516909a_0 + - xorg-libsm=1.2.3=h84519dc_1000 + - xorg-libx11=1.6.9=h516909a_0 + - xorg-libxau=1.0.9=h14c3975_0 + - xorg-libxdmcp=1.1.3=h516909a_0 + - xorg-libxext=1.3.4=h516909a_0 + - xorg-libxrender=0.9.10=h516909a_1002 + - xorg-renderproto=0.11.1=h14c3975_1002 + - xorg-xextproto=7.3.0=h14c3975_1002 + - xorg-xproto=7.0.31=h14c3975_1007 + - xz=5.2.5=h516909a_0 + - yaml=0.2.5=h516909a_0 + - yapf=0.29.0=py_0 + - zeromq=4.3.2=he1b5a44_2 + - zipp=3.1.0=py_0 + - zlib=1.2.11=h516909a_1006 + - zstd=1.4.4=h6597ccf_3 +prefix: /opt/conda + diff --git a/docker/readme.md b/docker/readme.md index 1b7d948e..a64cba06 100644 --- a/docker/readme.md +++ b/docker/readme.md @@ -1,18 +1,18 @@ -# Project docker image - -## Pull this image from docker hub -``` -docker pull gboeing/global-indicators -``` - -## Run bash in this container - -*On Windows* open a command prompt and run: -``` -docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash -``` - -*On Mac/Linux* open a terminal window and run: -``` -docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash -``` +# Project docker image + +## Pull this image from docker hub +``` +docker pull gboeing/global-indicators +``` + +## Run bash in this container + +*On Windows* open a command prompt and run: +``` +docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash +``` + +*On Mac/Linux* open a terminal window and run: +``` +docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash +``` diff --git a/docker/requirements.txt b/docker/requirements.txt index e5982da1..84fac0f3 100644 --- a/docker/requirements.txt +++ b/docker/requirements.txt @@ -1,35 +1,35 @@ -beautifulsoup4 -bokeh -bottleneck -cartopy -contextily -cython -flake8 -folium -geoalchemy2 -geopandas -jupyterlab -memory_profiler -networkx -nodejs -numexpr -numpy -osmnx -pandana -pillow -pip -psycopg2 -pylint -pysal -python == 3.* -rasterio -scikit-learn -scipy -seaborn -sphinx -sphinxcontrib-bibtex -sphinx_rtd_theme -urbanaccess -xlrd -xlwt -yapf +beautifulsoup4 +bokeh +bottleneck +cartopy +contextily +cython +flake8 +folium +geoalchemy2 +geopandas +jupyterlab +memory_profiler +networkx +nodejs +numexpr +numpy +osmnx +pandana +pillow +pip +psycopg2 +pylint +pysal +python == 3.* +rasterio +scikit-learn +scipy +seaborn +sphinx +sphinxcontrib-bibtex +sphinx_rtd_theme +urbanaccess +xlrd +xlwt +yapf diff --git a/documentation/readme.md b/documentation/readme.md index 3042bc2f..02c9185a 100644 --- a/documentation/readme.md +++ b/documentation/readme.md @@ -1,147 +1,147 @@ -# Understanding the Github Repository: -The Github Repository (henceforth the repo) is named **global-indicators**, and the master branch is managed by **Geoff Boeing**. -This section will describe what is information can be found in each part of the repo in a summarized form. For more detailed instruction on to run different parts of the code, please look within folders the code exists within. If you are unfamiliar with Github, we recommend that you read the [Github Guides](https://guides.github.com/). - -There are **three work folders** and a **documentation folder** in the repo. -- **The process folder** holds the code and results of the main analysis for this project. -- **The validation folder** holds the codes, results, and analysis for Phase II validation of the project. -- **The analysis folder** for storing output indicator visualization and analysis. - -In this readme, you will find a summary of what occurs in aspect of the repo. - -## Main Directory -### Readme -The repo's readme gives a brief overview of the project and the indicators that are collected for analysis. - -### Misc Documents -There are various documents that are accessible from the main repo. These include: -- **.gitignore**: A list of files for the repo to ignore. This keeps irrelevant files away from the main folders of the repo -- **LICENSE**: Legal information concerning the repo and its contents -- **Win-docker-bash.bat**: A file to smooth out the process of running Docker on a windows device - -### Docker Folder -The docker folder gives you the relevant information to pull the docker image onto your machine and run bash in this container. -- On **Windows** open a command prompt and run: - ```docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash``` -- On **Mac/Linux** open a terminal window and run: -```docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash``` - -### Documentation Folder -The documentation folder contains this readme. The purpose of the documentation folder is to help you understand what the project does and how it does it. - -## Process Folder -The process folder runs through the process of loading in the data and calculating the indicators. The readme goes step-by-step on the code to run. The configuration folder has the specific configuration json file for each study city. The data folder is empty before any code is run. The process folder also has five python scripts (henceforth scripts). This section will explain what each script and notebook does. This serves as basic understanding of what exists in the Process folder. To understand what steps to follow to run the process, please read the Process Folder’s readme. - -### Preprocess Folder -The preprocess folder runs through the process of preparing input datasets. Currently, it contains a configuration file (_project_configuration.xlsx) for the study regions defines both the project- and region-specific parameters, and the series of pre-processing scripts. The pre-processing procedure creates the geopackage and graphml files that are required for the subsequent steps of analysis. It is being coordinated by Carl. Please read the pre_process folder for more detail. - -### Collaborator_report folder -This folder contains scripts to create a PDF validation report that was distributed to collaborators for feedback. Then, preprocessing will be revised as required by the collaborators feedback in an iterative process to ensure that data corroborated with the expectations of local experts. This is part of the effort for Phase I validation. - -### Configuration Folder -The configuration folder contain configuration files for each of the 25 analyzed cities. The configuration files make it easier to organize and analyze the different study cities by providing file paths for the input and output of each city. This configuration of file paths allows you to simply write the city name and allow the code to pull in all the city-specific data itself. For example, each city has a different geopackage that is labled with 'geopackagePath' in the configuration file. The process code is able to extract the correct geopackage by using the configuration file. In Adelaide's case, 'adelaide_au_2019_1600m_buffer.gpkg' will be called whenever the code retreives 'geopackagePath' for Adelaide. The configuration files allow the project to be more flexible by creating an easy way to add, delete, or alter study city data. - -### Data Folder -On the repo, the data folder is empty. You are able to download the data for the process and place the data in this folder. Instructions for obtaining the data are below. - -### setup_aggr.py and setup_sp.py -These are modules that do not need to be run. Instead they work in the background and set up the definitions for different functions needed to run the Sample Points script (sp.py) and Aggregation script (aggr.py). In essence, they work as packages for the main process running scripts. For information on the difference of Scripts and Modules, you can look [HERE](https://realpython.com/run-python-scripts/). - -### setup_config.py -Run this script first. This script sets the configuration files for each city study region. Before running this script, the configuration folder will be empty. - -### sp.py -Run this script second. After projecting the data into the applicable crs, this script calculates data for the sample points. -1. First, intersection and population density are calculated for each sample point’s local walkable neighborhood. The script works for either the multiprocessing or single thread methods. -1. It then creates the pandana network for each sample point. -1. Next, the proximity of a sample point to each destination type is calculated within a certain distance (x). The distance is converted to a binary 0 or 1. 0 meaning the destination is not within the predetermined distance x, and 1 meaning that the destination is within the preset distance x. -1. Finally, a z-score for the variables is calculated -This script must be run first for each sample city before running the aggregation script. - -### process_regions.sh -This is a shell script wrapper to run all study regions at once to process sample point estimates (sp.py) in sequence, and can be run using ```bash process_region.sh``` followed by a list of region names. - -### aggr.py -Run this script third. This is the last script needed to be run. This script converts the data from sample points into hex data. This allows for within city analysis. It also concatenates each city so that the indicators are calculated for between city comparisons. The concatenation is why the sample points script must be run for every city before running this script. After running the script, Two indicators' geopackages will be created in the data/output folder. - - -## Validation Folder -The project’s validation phase aims to verify the accuracy of the indicators processed from the data used in the process folder i.e. the global human settlement layer and OSM data (henceforth global dataset). In order to do this, we have three phases of validation. - -Phase I validation is a qualitative assessment on how the global dataset matches with reality. For this step, collaborators from each city review the global dataset’s determined study region boundaries, population density, open space networks, and destination types, names, and categories for accuracy. Phase I validation is getting completed on an ongoing basis, and it is being coordinated by Carl. - -Phase II validation compares the global dataset with a second dataset. The second dataset (henceforth official dataset) has been collected by local partners, so it will be individual for each city. The official dataset reflects what exists in public records. At the moment, the project has official datasets for four cities: Belfast, Olomouc, Hong Kong, and Sao Paulo. These four cities serve as case studies for the rest of the project by comparing the street networks and destinations in their official datasets with the global dataset. - -Phase III validation is a comparison of the indicators that are derived from the global dataset and the official datasets. It will be difficult to run the process folder for the official datasets because of their inconsistent formats, so it may never be possible to run Phase III validation measures. - -As of Summer 2020, the validation folder is dedicated to Phase II validation. - -### Initial Readme -The Validation Folder’s readme explains how to run the official datasets for both street networks (edges) and destinations. - -### Configuration Folder -The validation configuration folder serves a similar purpose to the configuration folder in the process folder. The configuration files exists for each city for which the project has official data. Note, some cities have only edge data, only destination data, or edge and destination data. - -### Data Folder -On the repo, the data folder is empty. You are able to download the data for validation and place the data in this folder. Instructions for obtaining the data are below. - -### Edge and Destination Folders -Both the edge folder and the destination folder start with a readme file and a python script. The readme file explains the results of the validation work. Run the python script to conduct Phase II validation. After running the python script, each folder will populate with a csv file containing relevant indicators and a fig folder for the created figures. - -### Edge -The edge folder compares the OSM derived street network with the official street network. - -### Destination -The destination folder compares fresh food destinations between the OSM derived data and the official data. This includes supermarkets, markets, and shops like bakeries. - -## Data -Retrieve the data from the links found in the following google doc: -https://docs.google.com/document/d/1NnV3g8uj0OnOQFkFIR5IbT60HO2PiF3SLoZpUUTL3B0/edit?ts=5ecc5e75 - -## Key Terms -Indicators- -Indicators will be produced based on network analysis of sample points in urban areas of cities, with two output scales: a 250 meter hexagonal grid (for plotting the within city spatial distribution of measures); and city level summary. -The set of indicators chosen for calculation include: -- A walkability index (within city, and between city versions) -- Percent of population with access to frequent* public transport within 500 meters (* where frequency data is available) -- Percent of population with access to public open space -Walkability is calculated as a composite score using local neighborhood measures of population density, street connectivity, and land use mix. We use a score for proximal access to daily living amenities (fresh food, convenience, and public transport) as proxy measure for land use mix, which would otherwise be a challenge to calculate on a global scale. - -##### Indicators- -Indicators will be produced based on network analysis of sample points in urban areas of cities, with two output scales: a 250 meter hexagonal grid (for plotting the within city spatial distribution of measures); and city level summary. -The set of indicators chosen for calculation include are included in the following chart -Population per square kilometre -- Street connectivity per square kilometre -- Access to supermarkets within 500 metres -- Access to convenience stores within 500 metres -- Access to a public transport stop (any mode) within 500 metres -- Access to public open space (e.g. parks) within 500 metres -- Access to a frequent public transport stop (any mode) within 500 metres -- Daily Living Score within 500 metres (within and across cities) - - The Daily Living Score is a composite of the different land use indicators. We use a score for proximal access to daily living amenities (fresh food, convenience, and public transport) as proxy measure for land use mix, which would otherwise be a challenge to calculate on a global scale. -- Walkability scores (within and across cities) - - Walkability is calculated as a composite score using local neighborhood measures of population density, street connectivity, and land use mix. - -##### Study Regions- -The analysis area for each city included in the Global Livability Indicators project was constructed using the inter- section of a city administrative boundary (supplied by collaborators via a Google Form survey or acquired by the researchers independently) and urban centers identified by the Global Human Settlements project. - -The use of an independent, global data source for urban centers helps to ensure that the analysis focus on exposure for urban populations across all cities, and not for example for lower density rural settings on the urban fringe, which may otherwise fall within an administrative boundary. - -A large buffer (10 kilometers) was created around each study region, which defined the broader area of analysis for access to amenities. Built environment data — the network of roads and paths accessible by the public, and a series of destinations — were acquired for each city within the respective buffered study region boundaries. - -The use of a buffer such as this ensures that the population who may live on the edge of the identified urban study region can still have access to nearby amenities evaluated, even if located outside the identified urban bounds. Access will only be analyzed up to 500 meters network distance for the present set of indicators, however the broader buffer area allows us flexibility for expanding analysis in the future. - -##### Destinations- -- Supermarkets (commonly used in built environment analysis as a primary source of fresh food) -- Markets (which may be a major source of fresh food in some locations of some cities) -- Shops, in general (which may include bakeries, or other specific locations selling fresh food) -- Convenience stores (where basic and non-essential items may be acquired) -- Public transport (which might include bus, tram/light rail, train/metro/rail, ferry, etc) -- Public open space, including ‘green space’, ‘squares’, or other kind of public area for pedestrians - -##### OSMNX- -Learn more about OSMNX by going through Geoff Boeing’s Github repository. -https://github.com/gboeing/osmnx - -##### Pandana Network- -A network analysis library in python that calculates the accessibility of different destinations. It does this by taking nodes and attaching an amenity to each node. For every node in the network, it calculates how many amenities are in the node. This information informs on the landscape of accessibility across the entire network. +# Understanding the Github Repository: +The Github Repository (henceforth the repo) is named **global-indicators**, and the master branch is managed by **Geoff Boeing**. +This section will describe what is information can be found in each part of the repo in a summarized form. For more detailed instruction on to run different parts of the code, please look within folders the code exists within. If you are unfamiliar with Github, we recommend that you read the [Github Guides](https://guides.github.com/). + +There are **three work folders** and a **documentation folder** in the repo. +- **The process folder** holds the code and results of the main analysis for this project. +- **The validation folder** holds the codes, results, and analysis for Phase II validation of the project. +- **The analysis folder** for storing output indicator visualization and analysis. + +In this readme, you will find a summary of what occurs in aspect of the repo. + +## Main Directory +### Readme +The repo's readme gives a brief overview of the project and the indicators that are collected for analysis. + +### Misc Documents +There are various documents that are accessible from the main repo. These include: +- **.gitignore**: A list of files for the repo to ignore. This keeps irrelevant files away from the main folders of the repo +- **LICENSE**: Legal information concerning the repo and its contents +- **Win-docker-bash.bat**: A file to smooth out the process of running Docker on a windows device + +### Docker Folder +The docker folder gives you the relevant information to pull the docker image onto your machine and run bash in this container. +- On **Windows** open a command prompt and run: + ```docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash``` +- On **Mac/Linux** open a terminal window and run: +```docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash``` + +### Documentation Folder +The documentation folder contains this readme. The purpose of the documentation folder is to help you understand what the project does and how it does it. + +## Process Folder +The process folder runs through the process of loading in the data and calculating the indicators. The readme goes step-by-step on the code to run. The configuration folder has the specific configuration json file for each study city. The data folder is empty before any code is run. The process folder also has five python scripts (henceforth scripts). This section will explain what each script and notebook does. This serves as basic understanding of what exists in the Process folder. To understand what steps to follow to run the process, please read the Process Folder’s readme. + +### Preprocess Folder +The preprocess folder runs through the process of preparing input datasets. Currently, it contains a configuration file (_project_configuration.xlsx) for the study regions defines both the project- and region-specific parameters, and the series of pre-processing scripts. The pre-processing procedure creates the geopackage and graphml files that are required for the subsequent steps of analysis. It is being coordinated by Carl. Please read the pre_process folder for more detail. + +### Collaborator_report folder +This folder contains scripts to create a PDF validation report that was distributed to collaborators for feedback. Then, preprocessing will be revised as required by the collaborators feedback in an iterative process to ensure that data corroborated with the expectations of local experts. This is part of the effort for Phase I validation. + +### Configuration Folder +The configuration folder contain configuration files for each of the 25 analyzed cities. The configuration files make it easier to organize and analyze the different study cities by providing file paths for the input and output of each city. This configuration of file paths allows you to simply write the city name and allow the code to pull in all the city-specific data itself. For example, each city has a different geopackage that is labled with 'geopackagePath' in the configuration file. The process code is able to extract the correct geopackage by using the configuration file. In Adelaide's case, 'adelaide_au_2019_1600m_buffer.gpkg' will be called whenever the code retreives 'geopackagePath' for Adelaide. The configuration files allow the project to be more flexible by creating an easy way to add, delete, or alter study city data. + +### Data Folder +On the repo, the data folder is empty. You are able to download the data for the process and place the data in this folder. Instructions for obtaining the data are below. + +### setup_aggr.py and setup_sp.py +These are modules that do not need to be run. Instead they work in the background and set up the definitions for different functions needed to run the Sample Points script (sp.py) and Aggregation script (aggr.py). In essence, they work as packages for the main process running scripts. For information on the difference of Scripts and Modules, you can look [HERE](https://realpython.com/run-python-scripts/). + +### setup_config.py +Run this script first. This script sets the configuration files for each city study region. Before running this script, the configuration folder will be empty. + +### sp.py +Run this script second. After projecting the data into the applicable crs, this script calculates data for the sample points. +1. First, intersection and population density are calculated for each sample point’s local walkable neighborhood. The script works for either the multiprocessing or single thread methods. +1. It then creates the pandana network for each sample point. +1. Next, the proximity of a sample point to each destination type is calculated within a certain distance (x). The distance is converted to a binary 0 or 1. 0 meaning the destination is not within the predetermined distance x, and 1 meaning that the destination is within the preset distance x. +1. Finally, a z-score for the variables is calculated +This script must be run first for each sample city before running the aggregation script. + +### process_regions.sh +This is a shell script wrapper to run all study regions at once to process sample point estimates (sp.py) in sequence, and can be run using ```bash process_region.sh``` followed by a list of region names. + +### aggr.py +Run this script third. This is the last script needed to be run. This script converts the data from sample points into hex data. This allows for within city analysis. It also concatenates each city so that the indicators are calculated for between city comparisons. The concatenation is why the sample points script must be run for every city before running this script. After running the script, Two indicators' geopackages will be created in the data/output folder. + + +## Validation Folder +The project’s validation phase aims to verify the accuracy of the indicators processed from the data used in the process folder i.e. the global human settlement layer and OSM data (henceforth global dataset). In order to do this, we have three phases of validation. + +Phase I validation is a qualitative assessment on how the global dataset matches with reality. For this step, collaborators from each city review the global dataset’s determined study region boundaries, population density, open space networks, and destination types, names, and categories for accuracy. Phase I validation is getting completed on an ongoing basis, and it is being coordinated by Carl. + +Phase II validation compares the global dataset with a second dataset. The second dataset (henceforth official dataset) has been collected by local partners, so it will be individual for each city. The official dataset reflects what exists in public records. At the moment, the project has official datasets for four cities: Belfast, Olomouc, Hong Kong, and Sao Paulo. These four cities serve as case studies for the rest of the project by comparing the street networks and destinations in their official datasets with the global dataset. + +Phase III validation is a comparison of the indicators that are derived from the global dataset and the official datasets. It will be difficult to run the process folder for the official datasets because of their inconsistent formats, so it may never be possible to run Phase III validation measures. + +As of Summer 2020, the validation folder is dedicated to Phase II validation. + +### Initial Readme +The Validation Folder’s readme explains how to run the official datasets for both street networks (edges) and destinations. + +### Configuration Folder +The validation configuration folder serves a similar purpose to the configuration folder in the process folder. The configuration files exists for each city for which the project has official data. Note, some cities have only edge data, only destination data, or edge and destination data. + +### Data Folder +On the repo, the data folder is empty. You are able to download the data for validation and place the data in this folder. Instructions for obtaining the data are below. + +### Edge and Destination Folders +Both the edge folder and the destination folder start with a readme file and a python script. The readme file explains the results of the validation work. Run the python script to conduct Phase II validation. After running the python script, each folder will populate with a csv file containing relevant indicators and a fig folder for the created figures. + +### Edge +The edge folder compares the OSM derived street network with the official street network. + +### Destination +The destination folder compares fresh food destinations between the OSM derived data and the official data. This includes supermarkets, markets, and shops like bakeries. + +## Data +Retrieve the data from the links found in the following google doc: +https://docs.google.com/document/d/1NnV3g8uj0OnOQFkFIR5IbT60HO2PiF3SLoZpUUTL3B0/edit?ts=5ecc5e75 + +## Key Terms +Indicators- +Indicators will be produced based on network analysis of sample points in urban areas of cities, with two output scales: a 250 meter hexagonal grid (for plotting the within city spatial distribution of measures); and city level summary. +The set of indicators chosen for calculation include: +- A walkability index (within city, and between city versions) +- Percent of population with access to frequent* public transport within 500 meters (* where frequency data is available) +- Percent of population with access to public open space +Walkability is calculated as a composite score using local neighborhood measures of population density, street connectivity, and land use mix. We use a score for proximal access to daily living amenities (fresh food, convenience, and public transport) as proxy measure for land use mix, which would otherwise be a challenge to calculate on a global scale. + +##### Indicators- +Indicators will be produced based on network analysis of sample points in urban areas of cities, with two output scales: a 250 meter hexagonal grid (for plotting the within city spatial distribution of measures); and city level summary. +The set of indicators chosen for calculation include are included in the following chart +Population per square kilometre +- Street connectivity per square kilometre +- Access to supermarkets within 500 metres +- Access to convenience stores within 500 metres +- Access to a public transport stop (any mode) within 500 metres +- Access to public open space (e.g. parks) within 500 metres +- Access to a frequent public transport stop (any mode) within 500 metres +- Daily Living Score within 500 metres (within and across cities) + - The Daily Living Score is a composite of the different land use indicators. We use a score for proximal access to daily living amenities (fresh food, convenience, and public transport) as proxy measure for land use mix, which would otherwise be a challenge to calculate on a global scale. +- Walkability scores (within and across cities) + - Walkability is calculated as a composite score using local neighborhood measures of population density, street connectivity, and land use mix. + +##### Study Regions- +The analysis area for each city included in the Global Livability Indicators project was constructed using the inter- section of a city administrative boundary (supplied by collaborators via a Google Form survey or acquired by the researchers independently) and urban centers identified by the Global Human Settlements project. + +The use of an independent, global data source for urban centers helps to ensure that the analysis focus on exposure for urban populations across all cities, and not for example for lower density rural settings on the urban fringe, which may otherwise fall within an administrative boundary. + +A large buffer (10 kilometers) was created around each study region, which defined the broader area of analysis for access to amenities. Built environment data — the network of roads and paths accessible by the public, and a series of destinations — were acquired for each city within the respective buffered study region boundaries. + +The use of a buffer such as this ensures that the population who may live on the edge of the identified urban study region can still have access to nearby amenities evaluated, even if located outside the identified urban bounds. Access will only be analyzed up to 500 meters network distance for the present set of indicators, however the broader buffer area allows us flexibility for expanding analysis in the future. + +##### Destinations- +- Supermarkets (commonly used in built environment analysis as a primary source of fresh food) +- Markets (which may be a major source of fresh food in some locations of some cities) +- Shops, in general (which may include bakeries, or other specific locations selling fresh food) +- Convenience stores (where basic and non-essential items may be acquired) +- Public transport (which might include bus, tram/light rail, train/metro/rail, ferry, etc) +- Public open space, including ‘green space’, ‘squares’, or other kind of public area for pedestrians + +##### OSMNX- +Learn more about OSMNX by going through Geoff Boeing’s Github repository. +https://github.com/gboeing/osmnx + +##### Pandana Network- +A network analysis library in python that calculates the accessibility of different destinations. It does this by taking nodes and attaching an amenity to each node. For every node in the network, it calculates how many amenities are in the node. This information informs on the landscape of accessibility across the entire network. diff --git a/process/aggr.py b/process/aggr.py index 3a2a6fce..0882a677 100644 --- a/process/aggr.py +++ b/process/aggr.py @@ -1,98 +1,98 @@ -################################################################################ -# Script: aggr.py -# Description: This script is for preparing all within and across city indicators -# This script should be run after when the sample point stats are prepared for all cities (sp.py) -# use this is script to get all the final output for both within-city and across-city indicator - -# Two outputs: -# 1. global_indicators_hex_250m.gpkg -# 2. global_indicators_city.gpkg - -################################################################################ - -import json -import os -import sys -import time -from tqdm import tqdm - -import setup_aggr as sa # module for all aggregation functions used in this notebook - -if __name__ == "__main__": - # use the script from command line, like 'python aggr.py' - # the script will read pre-prepared sample point indicators from geopackage of each city - - startTime = time.time() - print("Process aggregation for hex-level indicators.") - - # Establish key configuration parameters - folder_path = os.path.abspath("") - config = sa.cities_config - output_folder = config["output_folder"] - cities = list(config["gpkgNames"].keys()) - cities_count = len(cities) - gpkg_output_hex = config["output_hex_250m"].replace('.gpkg',f'_{time.strftime("%Y-%m-%d")}.gpkg') - gpkg_output_cities = config["global_indicators_city"].replace('.gpkg',f'_{time.strftime("%Y-%m-%d")}.gpkg') - - print(f"\nCities: {cities}\n") - - # Create the path of 'global_indicators_hex_250m.gpkg' - # This is the geopackage to store the hexagon-level spatial indicators for each city - # The date of output processing is appended to the output file to differentiate from - # previous results, if any (yyyy-mm-dd format) - gpkg_output_hex = os.path.join(folder_path, output_folder, gpkg_output_hex) - - if not os.path.exists(os.path.dirname(gpkg_output_hex)): - os.makedirs(os.path.dirname(gpkg_output_hex)) - - # read pre-prepared sample point stats of each city from disk - gpkg_inputs = [] - for gpkg in list(config["gpkgNames"].values()): - gpkg_inputs.append(os.path.join(folder_path, output_folder, gpkg)) - - # calculate within-city indicators weighted by sample points for each city - # calc_hexes_pct_sp_indicators take sample point stats within each city as - # input and aggregate up to hex-level indicators by calculating the mean of - # sample points stats within each hex - print("\nCalculate hex-level indicators weighted by sample points within each city") - for i, gpkg_input in enumerate(tqdm(gpkg_inputs)): - sa.calc_hexes_pct_sp_indicators(gpkg_input, gpkg_output_hex, - cities[i], config["samplepointResult"], config["hex250"]) - - # calculate within-city zscores indicators for each city - # calc_hexes_zscore_walk take the zsocres of the hex-level indicators - # generated using calc_hexes_pct_sp_indicators function to create daily - # living and walkability scores - print("\nCalculate hex-level indicators zscores relative to all cities.") - sa.calc_hexes_zscore_walk(gpkg_output_hex, cities) - - print("\nCreate combined layer of all cities hex grids, to facilitate grouped analyses and mapping") - sa.combined_city_hexes(gpkg_inputs, gpkg_output_hex, cities) - - # calculate city-level indicators weighted by population - # calc_cities_pop_pct_indicators function take hex-level indicators and - # pop estimates of each city as input then aggregate hex-level to city-level - # indicator by summing all the population weighted hex-level indicators - print("Calculate city-level indicators weighted by city population:") - gpkg_output_cities = os.path.join(folder_path, output_folder, gpkg_output_cities) - # in addition to the population weighted averages, unweighted averages are also included to reflect - # the spatial distribution of key walkability measures (regardless of population distribution) - # as per discussion here: https://3.basecamp.com/3662734/buckets/11779922/messages/2465025799 - extra_unweighted_vars = ['local_nh_population_density','local_nh_intersection_density','local_daily_living', - 'local_walkability', - 'all_cities_z_nh_population_density','all_cities_z_nh_intersection_density','all_cities_z_daily_living', - 'all_cities_walkability'] - for i, gpkg_input in enumerate(tqdm(gpkg_inputs)): - if i==0: - all_cities_combined = sa.calc_cities_pop_pct_indicators(gpkg_output_hex, cities[i], - gpkg_input, gpkg_output_cities,extra_unweighted_vars) - else: - all_cities_combined = all_cities_combined.append(sa.calc_cities_pop_pct_indicators(gpkg_output_hex, - cities[i], gpkg_input, gpkg_output_cities,extra_unweighted_vars)) - - all_cities_combined = all_cities_combined.sort_values(['Continent', 'Country','City']) - all_cities_combined.to_file(gpkg_output_cities, layer='all_cities_combined', driver="GPKG") - all_cities_combined[[x for x in all_cities_combined.columns if x!='geometry']]\ - .to_csv(gpkg_output_cities.replace('gpkg','csv'),index=False) - print(f"Time is: {(time.time() - startTime)/60.0:.02f} mins") - print("finished.") +################################################################################ +# Script: aggr.py +# Description: This script is for preparing all within and across city indicators +# This script should be run after when the sample point stats are prepared for all cities (sp.py) +# use this is script to get all the final output for both within-city and across-city indicator + +# Two outputs: +# 1. global_indicators_hex_250m.gpkg +# 2. global_indicators_city.gpkg + +################################################################################ + +import json +import os +import sys +import time +from tqdm import tqdm + +import setup_aggr as sa # module for all aggregation functions used in this notebook + +if __name__ == "__main__": + # use the script from command line, like 'python aggr.py' + # the script will read pre-prepared sample point indicators from geopackage of each city + + startTime = time.time() + print("Process aggregation for hex-level indicators.") + + # Establish key configuration parameters + folder_path = os.path.abspath("") + config = sa.cities_config + output_folder = config["output_folder"] + cities = list(config["gpkgNames"].keys()) + cities_count = len(cities) + gpkg_output_hex = config["output_hex_250m"].replace('.gpkg',f'_{time.strftime("%Y-%m-%d")}.gpkg') + gpkg_output_cities = config["global_indicators_city"].replace('.gpkg',f'_{time.strftime("%Y-%m-%d")}.gpkg') + + print(f"\nCities: {cities}\n") + + # Create the path of 'global_indicators_hex_250m.gpkg' + # This is the geopackage to store the hexagon-level spatial indicators for each city + # The date of output processing is appended to the output file to differentiate from + # previous results, if any (yyyy-mm-dd format) + gpkg_output_hex = os.path.join(folder_path, output_folder, gpkg_output_hex) + + if not os.path.exists(os.path.dirname(gpkg_output_hex)): + os.makedirs(os.path.dirname(gpkg_output_hex)) + + # read pre-prepared sample point stats of each city from disk + gpkg_inputs = [] + for gpkg in list(config["gpkgNames"].values()): + gpkg_inputs.append(os.path.join(folder_path, output_folder, gpkg)) + + # calculate within-city indicators weighted by sample points for each city + # calc_hexes_pct_sp_indicators take sample point stats within each city as + # input and aggregate up to hex-level indicators by calculating the mean of + # sample points stats within each hex + print("\nCalculate hex-level indicators weighted by sample points within each city") + for i, gpkg_input in enumerate(tqdm(gpkg_inputs)): + sa.calc_hexes_pct_sp_indicators(gpkg_input, gpkg_output_hex, + cities[i], config["samplepointResult"], config["hex250"]) + + # calculate within-city zscores indicators for each city + # calc_hexes_zscore_walk take the zsocres of the hex-level indicators + # generated using calc_hexes_pct_sp_indicators function to create daily + # living and walkability scores + print("\nCalculate hex-level indicators zscores relative to all cities.") + sa.calc_hexes_zscore_walk(gpkg_output_hex, cities) + + print("\nCreate combined layer of all cities hex grids, to facilitate grouped analyses and mapping") + sa.combined_city_hexes(gpkg_inputs, gpkg_output_hex, cities) + + # calculate city-level indicators weighted by population + # calc_cities_pop_pct_indicators function take hex-level indicators and + # pop estimates of each city as input then aggregate hex-level to city-level + # indicator by summing all the population weighted hex-level indicators + print("Calculate city-level indicators weighted by city population:") + gpkg_output_cities = os.path.join(folder_path, output_folder, gpkg_output_cities) + # in addition to the population weighted averages, unweighted averages are also included to reflect + # the spatial distribution of key walkability measures (regardless of population distribution) + # as per discussion here: https://3.basecamp.com/3662734/buckets/11779922/messages/2465025799 + extra_unweighted_vars = ['local_nh_population_density','local_nh_intersection_density','local_daily_living', + 'local_walkability', + 'all_cities_z_nh_population_density','all_cities_z_nh_intersection_density','all_cities_z_daily_living', + 'all_cities_walkability'] + for i, gpkg_input in enumerate(tqdm(gpkg_inputs)): + if i==0: + all_cities_combined = sa.calc_cities_pop_pct_indicators(gpkg_output_hex, cities[i], + gpkg_input, gpkg_output_cities,extra_unweighted_vars) + else: + all_cities_combined = all_cities_combined.append(sa.calc_cities_pop_pct_indicators(gpkg_output_hex, + cities[i], gpkg_input, gpkg_output_cities,extra_unweighted_vars)) + + all_cities_combined = all_cities_combined.sort_values(['Continent', 'Country','City']) + all_cities_combined.to_file(gpkg_output_cities, layer='all_cities_combined', driver="GPKG") + all_cities_combined[[x for x in all_cities_combined.columns if x!='geometry']]\ + .to_csv(gpkg_output_cities.replace('gpkg','csv'),index=False) + print(f"Time is: {(time.time() - startTime)/60.0:.02f} mins") + print("finished.") diff --git a/process/collaborator_report/Makefile b/process/collaborator_report/Makefile index d4bb2cbb..73a28c71 100644 --- a/process/collaborator_report/Makefile +++ b/process/collaborator_report/Makefile @@ -1,20 +1,20 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/process/collaborator_report/_render.sh b/process/collaborator_report/_render.sh index bc30f2ac..cc8bb5e6 100644 --- a/process/collaborator_report/_render.sh +++ b/process/collaborator_report/_render.sh @@ -1,5 +1,5 @@ -make clean -make html -cp -rT _build/html ../maps/ -make latexpdf - +make clean +make html +cp -rT _build/html ../maps/ +make latexpdf + diff --git a/process/collaborator_report/_static/osm_definitions.csv b/process/collaborator_report/_static/osm_definitions.csv index c6110b93..453add2f 100644 --- a/process/collaborator_report/_static/osm_definitions.csv +++ b/process/collaborator_report/_static/osm_definitions.csv @@ -1,39 +1,39 @@ -dest_name,dest_full_name,detail_name,detail_name_full,key,value,global_freq_2018_nov,pre-condition,description,domain,note, -fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,shop,supermarket,"343,085",,A large store for groceries and other goods.,Food,, -fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,supermarket,,95,,,Food,if not null then is a supermarket, -fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,amenity,supermarket,37,,,Food,, -fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,building,supermarket,"8,251",,A building built as a supermarket,Food,, -fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,shop,grocery,"1,137",,,Food,, -fresh_food_market,Fresh Food / Market,bakery_osm,Bakery,shop,bakery,"154,061",,A shop selling bread,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -fresh_food_market,Fresh Food / Market,bakery_osm,Bakery,shop,pastry,"6,436",,A shop where sweet bakery products are produced and sold,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -fresh_food_market,Fresh Food / Market,bakery_osm,Bakery,name,Tortillera,,,,,, -fresh_food_market,Fresh Food / Market,meat_seafood_osm,Meat / Seafood,shop,butcher,"60,510",,A shop selling meat or meat products.,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -fresh_food_market,Fresh Food / Market,meat_seafood_osm,Meat / Seafood,shop,seafood,"11,651",,A shop selling fish/seafood.,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -fresh_food_market,Fresh Food / Market,meat_seafood_osm,Meat / Seafood,shop,fishmonger,"1,029",,,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,greengrocer,"33,791",,A shop which sells fruits and vegetables,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,fruit,50,,,Food,, -fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,fruits,22,,,Food,, -fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,vegetables,10,,,Food,, -fresh_food_market,Fresh Food / Market,deli_osm,Deli,shop,deli,"12,735",,A delicatessen store,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -fresh_food_market,Fresh Food / Market,deli_osm,Deli,shop,cheese,"2,415",,A shop mainly selling cheese.,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", -convenience,Convenience,convenience_osm,Convenience,shop,convenience,"457,453",,A small local shop carrying a small subset of the items you would find in a supermarket.,Convenience,, -convenience,Convenience,petrolstation_osm,Convenience,amenity,fuel,"398,945",,A retail facility for refueling cars,Convenience,"<<< not sure if we should include this, some international reviewers questioned inclusion of petrol stations as convenience.", -convenience,Convenience,newsagent_osm,Convenience,shop,kiosk,"72,391",,"A small shop on the pavement that sells magazines, tobacco, newspapers, sweets and stamps.",Convenience,, -convenience,Convenience,newsagent_osm,Convenience,shop,newsagent,"19,245",,A shop selling newspapers and magazines.,Convenience,, -convenience,Convenience,newsagent_osm,Convenience,shop,newsagency,10,,,Convenience,, -convenience,Convenience,newsagent_osm,Convenience,amenity,newsagency,3,,,Convenience,, -fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,marketplace,52267,,A marketplace where trade is regulated.,"Convenience; Community, Culture and Leisure","Perhaps safest to consider as 'convenience' (although potentially distinct from, or more than this)", -fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,market,206,,,"Convenience; Community, Culture and Leisure",included for completeness, -fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,market_place,41,,,"Convenience; Community, Culture and Leisure",included for completeness, -fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,public_market,22,,,"Convenience; Community, Culture and Leisure",included for completeness, -fresh_food_market,Fresh Food / Market,market_osm,Market,shop,marketplace,248,,,"Convenience; Community, Culture and Leisure",, -fresh_food_market,Fresh Food / Market,market_osm,Market,shop,market,246,,,"Convenience; Community, Culture and Leisure",, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),public_transport,platform,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),public_transport,stop_position,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),highway,bus_stop,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),highway,platform,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),railway,platform,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),public_transport,station,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),amenity,ferry_terminal,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),railway,tram_stop,,,,,, -pt_any,Public transport stop (any),pt_any,Public transport stop (any),railway,stop,,,,,, +dest_name,dest_full_name,detail_name,detail_name_full,key,value,global_freq_2018_nov,pre-condition,description,domain,note, +fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,shop,supermarket,"343,085",,A large store for groceries and other goods.,Food,, +fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,supermarket,,95,,,Food,if not null then is a supermarket, +fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,amenity,supermarket,37,,,Food,, +fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,building,supermarket,"8,251",,A building built as a supermarket,Food,, +fresh_food_market,Fresh Food / Market,supermarket_osm,Supermarket,shop,grocery,"1,137",,,Food,, +fresh_food_market,Fresh Food / Market,bakery_osm,Bakery,shop,bakery,"154,061",,A shop selling bread,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +fresh_food_market,Fresh Food / Market,bakery_osm,Bakery,shop,pastry,"6,436",,A shop where sweet bakery products are produced and sold,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +fresh_food_market,Fresh Food / Market,bakery_osm,Bakery,name,Tortillera,,,,,, +fresh_food_market,Fresh Food / Market,meat_seafood_osm,Meat / Seafood,shop,butcher,"60,510",,A shop selling meat or meat products.,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +fresh_food_market,Fresh Food / Market,meat_seafood_osm,Meat / Seafood,shop,seafood,"11,651",,A shop selling fish/seafood.,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +fresh_food_market,Fresh Food / Market,meat_seafood_osm,Meat / Seafood,shop,fishmonger,"1,029",,,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,greengrocer,"33,791",,A shop which sells fruits and vegetables,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,fruit,50,,,Food,, +fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,fruits,22,,,Food,, +fresh_food_market,Fresh Food / Market,fruit_veg_osm,Fruit and Veg,shop,vegetables,10,,,Food,, +fresh_food_market,Fresh Food / Market,deli_osm,Deli,shop,deli,"12,735",,A delicatessen store,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +fresh_food_market,Fresh Food / Market,deli_osm,Deli,shop,cheese,"2,415",,A shop mainly selling cheese.,Food,"Clusters of fresh food proprieters might indicate historical village hubs (or shopping centres, idk)", +convenience,Convenience,convenience_osm,Convenience,shop,convenience,"457,453",,A small local shop carrying a small subset of the items you would find in a supermarket.,Convenience,, +convenience,Convenience,petrolstation_osm,Convenience,amenity,fuel,"398,945",,A retail facility for refueling cars,Convenience,"<<< not sure if we should include this, some international reviewers questioned inclusion of petrol stations as convenience.", +convenience,Convenience,newsagent_osm,Convenience,shop,kiosk,"72,391",,"A small shop on the pavement that sells magazines, tobacco, newspapers, sweets and stamps.",Convenience,, +convenience,Convenience,newsagent_osm,Convenience,shop,newsagent,"19,245",,A shop selling newspapers and magazines.,Convenience,, +convenience,Convenience,newsagent_osm,Convenience,shop,newsagency,10,,,Convenience,, +convenience,Convenience,newsagent_osm,Convenience,amenity,newsagency,3,,,Convenience,, +fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,marketplace,52267,,A marketplace where trade is regulated.,"Convenience; Community, Culture and Leisure","Perhaps safest to consider as 'convenience' (although potentially distinct from, or more than this)", +fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,market,206,,,"Convenience; Community, Culture and Leisure",included for completeness, +fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,market_place,41,,,"Convenience; Community, Culture and Leisure",included for completeness, +fresh_food_market,Fresh Food / Market,market_osm,Market,amenity,public_market,22,,,"Convenience; Community, Culture and Leisure",included for completeness, +fresh_food_market,Fresh Food / Market,market_osm,Market,shop,marketplace,248,,,"Convenience; Community, Culture and Leisure",, +fresh_food_market,Fresh Food / Market,market_osm,Market,shop,market,246,,,"Convenience; Community, Culture and Leisure",, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),public_transport,platform,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),public_transport,stop_position,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),highway,bus_stop,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),highway,platform,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),railway,platform,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),public_transport,station,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),amenity,ferry_terminal,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),railway,tram_stop,,,,,, +pt_any,Public transport stop (any),pt_any,Public transport stop (any),railway,stop,,,,,, diff --git a/process/collaborator_report/_static/style.css b/process/collaborator_report/_static/style.css index 6b38039a..0dafebc1 100644 --- a/process/collaborator_report/_static/style.css +++ b/process/collaborator_report/_static/style.css @@ -1,35 +1,35 @@ -@import "theme.css"; - -.wy-side-nav-search, .wy-nav-top { - background: #2ca25f; -} - - -.wy-nav-content { - max-width: none; -} - -.wy-table-responsive { - height: 500px; -} - -div.body { - background-image: url("watermark-draft.png") !important; - background-repeat: repeat-y !important; - background-position: center top !important; - background-attachment: scroll !important; -} - -figcaption { - font-style: italic; - font-size: smaller; - padding: 0.5em; -} - -figure { - text-indent: 0; - border: thin silver solid; - margin: 0.5em; - padding: 0.5em; - max-width: 1000px; -} +@import "theme.css"; + +.wy-side-nav-search, .wy-nav-top { + background: #2ca25f; +} + + +.wy-nav-content { + max-width: none; +} + +.wy-table-responsive { + height: 500px; +} + +div.body { + background-image: url("watermark-draft.png") !important; + background-repeat: repeat-y !important; + background-position: center top !important; + background-attachment: scroll !important; +} + +figcaption { + font-style: italic; + font-size: smaller; + padding: 0.5em; +} + +figure { + text-indent: 0; + border: thin silver solid; + margin: 0.5em; + padding: 0.5em; + max-width: 1000px; +} diff --git a/process/collaborator_report/_templates/layout.html b/process/collaborator_report/_templates/layout.html index b0a44806..7488ec4a 100644 --- a/process/collaborator_report/_templates/layout.html +++ b/process/collaborator_report/_templates/layout.html @@ -1,4 +1,4 @@ -{% extends "!layout.html" %} -{% block extrahead %} - +{% extends "!layout.html" %} +{% block extrahead %} + {% endblock %} \ No newline at end of file diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/__init__.py b/process/collaborator_report/_themes/sphinx_rtd_theme/__init__.py index 32c87c38..4c973337 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/__init__.py +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/__init__.py @@ -1,30 +1,30 @@ -""" -Sphinx Read the Docs theme. - -From https://github.com/ryan-roemer/sphinx-bootstrap-theme. -""" - -from os import path - -import sphinx - - -__version__ = '0.4.3.dev0' -__version_full__ = __version__ - - -def get_html_theme_path(): - """Return list of HTML theme paths.""" - cur_dir = path.abspath(path.dirname(path.dirname(__file__))) - return cur_dir - - -# See http://www.sphinx-doc.org/en/stable/theming.html#distribute-your-theme-as-a-python-package -def setup(app): - app.add_html_theme('sphinx_rtd_theme', path.abspath(path.dirname(__file__))) - - if sphinx.version_info >= (1, 8, 0): - # Add Sphinx message catalog for newer versions of Sphinx - # See http://www.sphinx-doc.org/en/master/extdev/appapi.html#sphinx.application.Sphinx.add_message_catalog - rtd_locale_path = path.join(path.abspath(path.dirname(__file__)), 'locale') - app.add_message_catalog('sphinx', rtd_locale_path) +""" +Sphinx Read the Docs theme. + +From https://github.com/ryan-roemer/sphinx-bootstrap-theme. +""" + +from os import path + +import sphinx + + +__version__ = '0.4.3.dev0' +__version_full__ = __version__ + + +def get_html_theme_path(): + """Return list of HTML theme paths.""" + cur_dir = path.abspath(path.dirname(path.dirname(__file__))) + return cur_dir + + +# See http://www.sphinx-doc.org/en/stable/theming.html#distribute-your-theme-as-a-python-package +def setup(app): + app.add_html_theme('sphinx_rtd_theme', path.abspath(path.dirname(__file__))) + + if sphinx.version_info >= (1, 8, 0): + # Add Sphinx message catalog for newer versions of Sphinx + # See http://www.sphinx-doc.org/en/master/extdev/appapi.html#sphinx.application.Sphinx.add_message_catalog + rtd_locale_path = path.join(path.abspath(path.dirname(__file__)), 'locale') + app.add_message_catalog('sphinx', rtd_locale_path) diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/breadcrumbs.html b/process/collaborator_report/_themes/sphinx_rtd_theme/breadcrumbs.html index 90cb0ff8..9af5b2ad 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/breadcrumbs.html +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/breadcrumbs.html @@ -1,82 +1,82 @@ -{# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #} - -{% if page_source_suffix %} -{% set suffix = page_source_suffix %} -{% else %} -{% set suffix = source_suffix %} -{% endif %} - -{% if meta is defined and meta is not none %} -{% set check_meta = True %} -{% else %} -{% set check_meta = False %} -{% endif %} - -{% if check_meta and 'github_url' in meta %} -{% set display_github = True %} -{% endif %} - -{% if check_meta and 'bitbucket_url' in meta %} -{% set display_bitbucket = True %} -{% endif %} - -{% if check_meta and 'gitlab_url' in meta %} -{% set display_gitlab = True %} -{% endif %} - -
- - - - {% if (theme_prev_next_buttons_location == 'top' or theme_prev_next_buttons_location == 'both') and (next or prev) %} - - {% endif %} -
-
+{# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #} + +{% if page_source_suffix %} +{% set suffix = page_source_suffix %} +{% else %} +{% set suffix = source_suffix %} +{% endif %} + +{% if meta is defined and meta is not none %} +{% set check_meta = True %} +{% else %} +{% set check_meta = False %} +{% endif %} + +{% if check_meta and 'github_url' in meta %} +{% set display_github = True %} +{% endif %} + +{% if check_meta and 'bitbucket_url' in meta %} +{% set display_bitbucket = True %} +{% endif %} + +{% if check_meta and 'gitlab_url' in meta %} +{% set display_gitlab = True %} +{% endif %} + +
+ + + + {% if (theme_prev_next_buttons_location == 'top' or theme_prev_next_buttons_location == 'both') and (next or prev) %} + + {% endif %} +
+
diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/footer.html b/process/collaborator_report/_themes/sphinx_rtd_theme/footer.html index 3b9bcb01..bba82b49 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/footer.html +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/footer.html @@ -1,56 +1,56 @@ -
- {% if (theme_prev_next_buttons_location == 'bottom' or theme_prev_next_buttons_location == 'both') and (next or prev) %} - - {% endif %} - -
- -
-

- {%- if show_copyright %} - {%- if hasdoc('copyright') %} - {% set path = pathto('copyright') %} - {% set copyright = copyright|e %} - © {% trans %}Copyright{% endtrans %} {{ copyright }} - {%- else %} - {% set copyright = copyright|e %} - © {% trans %}Copyright{% endtrans %} {{ copyright }} - {%- endif %} - {%- endif %} - - {%- if build_id and build_url %} - - {# Translators: Build is a noun, not a verb #} - {% trans %}Build{% endtrans %} - {{ build_id }}. - - {%- elif commit %} - - {% trans %}Revision{% endtrans %} {{ commit }}. - - {%- elif last_updated %} - - {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} - - {%- endif %} - -

-
- - {%- if show_sphinx %} - {% set sphinx_web = 'Sphinx' %} - {% set readthedocs_web = 'Read the Docs' %} - {% trans sphinx_web=sphinx_web, readthedocs_web=readthedocs_web %}Built with {{ sphinx_web }} using a{% endtrans %} {% trans %}theme{% endtrans %} {% trans %}provided by {{ readthedocs_web }}{% endtrans %}. - {%- endif %} - - {%- block extrafooter %} {% endblock %} - -
- +
+ {% if (theme_prev_next_buttons_location == 'bottom' or theme_prev_next_buttons_location == 'both') and (next or prev) %} + + {% endif %} + +
+ +
+

+ {%- if show_copyright %} + {%- if hasdoc('copyright') %} + {% set path = pathto('copyright') %} + {% set copyright = copyright|e %} + © {% trans %}Copyright{% endtrans %} {{ copyright }} + {%- else %} + {% set copyright = copyright|e %} + © {% trans %}Copyright{% endtrans %} {{ copyright }} + {%- endif %} + {%- endif %} + + {%- if build_id and build_url %} + + {# Translators: Build is a noun, not a verb #} + {% trans %}Build{% endtrans %} + {{ build_id }}. + + {%- elif commit %} + + {% trans %}Revision{% endtrans %} {{ commit }}. + + {%- elif last_updated %} + + {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} + + {%- endif %} + +

+
+ + {%- if show_sphinx %} + {% set sphinx_web = 'Sphinx' %} + {% set readthedocs_web = 'Read the Docs' %} + {% trans sphinx_web=sphinx_web, readthedocs_web=readthedocs_web %}Built with {{ sphinx_web }} using a{% endtrans %} {% trans %}theme{% endtrans %} {% trans %}provided by {{ readthedocs_web }}{% endtrans %}. + {%- endif %} + + {%- block extrafooter %} {% endblock %} + +
+ diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/layout.html b/process/collaborator_report/_themes/sphinx_rtd_theme/layout.html index c575f516..89bde5a2 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/layout.html +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/layout.html @@ -1,239 +1,239 @@ -{# TEMPLATE VAR SETTINGS #} -{%- set url_root = pathto('', 1) %} -{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} -{%- if not embedded and docstitle %} - {%- set titlesuffix = " — "|safe + docstitle|e %} -{%- else %} - {%- set titlesuffix = "" %} -{%- endif %} -{%- set lang_attr = 'en' if language == None else (language | replace('_', '-')) %} - - - - - - - {{ metatags }} - - {% block htmltitle %} - {{ title|striptags|e }}{{ titlesuffix }} - {% endblock %} - - {# FAVICON #} - {% if favicon %} - - {% endif %} - {# CANONICAL URL #} - {% if theme_canonical_url %} - - {% endif %} - - {# JAVASCRIPTS #} - {%- block scripts %} - - {%- if not embedded %} - {# XXX Sphinx 1.8.0 made this an external js-file, quick fix until we refactor the template to inherert more blocks directly from sphinx #} - {% if sphinx_version >= "1.8.0" %} - - {%- for scriptfile in script_files %} - {{ js_tag(scriptfile) }} - {%- endfor %} - {% else %} - - {%- for scriptfile in script_files %} - - {%- endfor %} - {% endif %} - - - {# OPENSEARCH #} - {%- if use_opensearch %} - - {%- endif %} - {%- endif %} - {%- endblock %} - - {# CSS #} - - - {%- for css in css_files %} - {%- if css|attr("rel") %} - - {%- else %} - - {%- endif %} - {%- endfor %} - - {%- for cssfile in extra_css_files %} - - {%- endfor %} - - {%- block linktags %} - {%- if hasdoc('about') %} - - {%- endif %} - {%- if hasdoc('genindex') %} - - {%- endif %} - {%- if hasdoc('search') %} - - {%- endif %} - {%- if hasdoc('copyright') %} - - {%- endif %} - {%- if next %} - - {%- endif %} - {%- if prev %} - - {%- endif %} - {%- endblock %} - {%- block extrahead %} {% endblock %} - - - - - {% block extrabody %} {% endblock %} -
- {# SIDE NAV, TOGGLES ON MOBILE #} - - -
- - {# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #} - - - -
- {%- block content %} - {% if theme_style_external_links|tobool %} - - -
- -
- {% include "versions.html" %} - - - - {# Do not conflict with RTD insertion of analytics script #} - {% if not READTHEDOCS %} - {% if theme_analytics_id %} - - - - {% endif %} - {% endif %} - - {%- block footer %} {% endblock %} - - - +{# TEMPLATE VAR SETTINGS #} +{%- set url_root = pathto('', 1) %} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} +{%- set lang_attr = 'en' if language == None else (language | replace('_', '-')) %} + + + + + + + {{ metatags }} + + {% block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {% endblock %} + + {# FAVICON #} + {% if favicon %} + + {% endif %} + {# CANONICAL URL #} + {% if theme_canonical_url %} + + {% endif %} + + {# JAVASCRIPTS #} + {%- block scripts %} + + {%- if not embedded %} + {# XXX Sphinx 1.8.0 made this an external js-file, quick fix until we refactor the template to inherert more blocks directly from sphinx #} + {% if sphinx_version >= "1.8.0" %} + + {%- for scriptfile in script_files %} + {{ js_tag(scriptfile) }} + {%- endfor %} + {% else %} + + {%- for scriptfile in script_files %} + + {%- endfor %} + {% endif %} + + + {# OPENSEARCH #} + {%- if use_opensearch %} + + {%- endif %} + {%- endif %} + {%- endblock %} + + {# CSS #} + + + {%- for css in css_files %} + {%- if css|attr("rel") %} + + {%- else %} + + {%- endif %} + {%- endfor %} + + {%- for cssfile in extra_css_files %} + + {%- endfor %} + + {%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} + {%- endblock %} + {%- block extrahead %} {% endblock %} + + + + + {% block extrabody %} {% endblock %} +
+ {# SIDE NAV, TOGGLES ON MOBILE #} + + +
+ + {# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #} + + + +
+ {%- block content %} + {% if theme_style_external_links|tobool %} + + +
+ +
+ {% include "versions.html" %} + + + + {# Do not conflict with RTD insertion of analytics script #} + {% if not READTHEDOCS %} + {% if theme_analytics_id %} + + + + {% endif %} + {% endif %} + + {%- block footer %} {% endblock %} + + + diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/en/LC_MESSAGES/sphinx.po b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/en/LC_MESSAGES/sphinx.po index d1d89b74..7fb4700e 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/en/LC_MESSAGES/sphinx.po +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/en/LC_MESSAGES/sphinx.po @@ -1,147 +1,147 @@ -# English translations for sphinx_rtd_theme. -# Copyright (C) 2019 ORGANIZATION -# This file is distributed under the same license as the sphinx_rtd_theme -# project. -# FIRST AUTHOR , 2019. -# -msgid "" -msgstr "" -"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-07-24 23:51-0600\n" -"PO-Revision-Date: 2019-07-16 15:43-0600\n" -"Last-Translator: FULL NAME \n" -"Language: en\n" -"Language-Team: en \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.7.0\n" - -#: sphinx_rtd_theme/breadcrumbs.html:31 -msgid "Docs" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 -msgid "Edit on GitHub" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 -msgid "Edit on Bitbucket" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 -msgid "Edit on GitLab" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 -msgid "View page source" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 -msgid "Next" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 -msgid "Previous" -msgstr "" - -#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 -#: sphinx_rtd_theme/layout.html:92 -msgid "Copyright" -msgstr "" - -#. Build is a noun, not a verb -#: sphinx_rtd_theme/footer.html:31 -msgid "Build" -msgstr "" - -#: sphinx_rtd_theme/footer.html:36 -msgid "Revision" -msgstr "" - -#: sphinx_rtd_theme/footer.html:40 -#, python-format -msgid "Last updated on %(last_updated)s." -msgstr "" - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "Built with %(sphinx_web)s using a" -msgstr "" - -#: sphinx_rtd_theme/footer.html:50 -msgid "theme" -msgstr "" - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "provided by %(readthedocs_web)s" -msgstr "" - -#: sphinx_rtd_theme/layout.html:61 -#, python-format -msgid "Search within %(docstitle)s" -msgstr "" - -#: sphinx_rtd_theme/layout.html:83 -msgid "About these documents" -msgstr "" - -#: sphinx_rtd_theme/layout.html:86 -msgid "Index" -msgstr "" - -#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 -msgid "Search" -msgstr "" - -#: sphinx_rtd_theme/layout.html:124 -msgid "Logo" -msgstr "" - -#: sphinx_rtd_theme/search.html:26 -msgid "Please activate JavaScript to enable the search functionality." -msgstr "" - -#. Search is a noun, not a verb -#: sphinx_rtd_theme/search.html:34 -msgid "Search Results" -msgstr "" - -#: sphinx_rtd_theme/search.html:36 -msgid "" -"Your search did not match any documents. Please make sure that all words " -"are spelled correctly and that you've selected enough categories." -msgstr "" - -#: sphinx_rtd_theme/searchbox.html:4 -msgid "Search docs" -msgstr "" - -#: sphinx_rtd_theme/versions.html:11 -msgid "Versions" -msgstr "" - -#: sphinx_rtd_theme/versions.html:17 -msgid "Downloads" -msgstr "" - -#. The phrase "Read the Docs" is not translated -#: sphinx_rtd_theme/versions.html:24 -msgid "On Read the Docs" -msgstr "" - -#: sphinx_rtd_theme/versions.html:26 -msgid "Project Home" -msgstr "" - -#: sphinx_rtd_theme/versions.html:29 -msgid "Builds" -msgstr "" - -#: sphinx_rtd_theme/versions.html:33 -msgid "Free document hosting provided by" -msgstr "" - +# English translations for sphinx_rtd_theme. +# Copyright (C) 2019 ORGANIZATION +# This file is distributed under the same license as the sphinx_rtd_theme +# project. +# FIRST AUTHOR , 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2019-07-24 23:51-0600\n" +"PO-Revision-Date: 2019-07-16 15:43-0600\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.7.0\n" + +#: sphinx_rtd_theme/breadcrumbs.html:31 +msgid "Docs" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 +msgid "Edit on GitHub" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 +msgid "Edit on Bitbucket" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 +msgid "Edit on GitLab" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 +msgid "View page source" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 +msgid "Next" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 +msgid "Previous" +msgstr "" + +#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 +#: sphinx_rtd_theme/layout.html:92 +msgid "Copyright" +msgstr "" + +#. Build is a noun, not a verb +#: sphinx_rtd_theme/footer.html:31 +msgid "Build" +msgstr "" + +#: sphinx_rtd_theme/footer.html:36 +msgid "Revision" +msgstr "" + +#: sphinx_rtd_theme/footer.html:40 +#, python-format +msgid "Last updated on %(last_updated)s." +msgstr "" + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "Built with %(sphinx_web)s using a" +msgstr "" + +#: sphinx_rtd_theme/footer.html:50 +msgid "theme" +msgstr "" + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "provided by %(readthedocs_web)s" +msgstr "" + +#: sphinx_rtd_theme/layout.html:61 +#, python-format +msgid "Search within %(docstitle)s" +msgstr "" + +#: sphinx_rtd_theme/layout.html:83 +msgid "About these documents" +msgstr "" + +#: sphinx_rtd_theme/layout.html:86 +msgid "Index" +msgstr "" + +#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 +msgid "Search" +msgstr "" + +#: sphinx_rtd_theme/layout.html:124 +msgid "Logo" +msgstr "" + +#: sphinx_rtd_theme/search.html:26 +msgid "Please activate JavaScript to enable the search functionality." +msgstr "" + +#. Search is a noun, not a verb +#: sphinx_rtd_theme/search.html:34 +msgid "Search Results" +msgstr "" + +#: sphinx_rtd_theme/search.html:36 +msgid "" +"Your search did not match any documents. Please make sure that all words " +"are spelled correctly and that you've selected enough categories." +msgstr "" + +#: sphinx_rtd_theme/searchbox.html:4 +msgid "Search docs" +msgstr "" + +#: sphinx_rtd_theme/versions.html:11 +msgid "Versions" +msgstr "" + +#: sphinx_rtd_theme/versions.html:17 +msgid "Downloads" +msgstr "" + +#. The phrase "Read the Docs" is not translated +#: sphinx_rtd_theme/versions.html:24 +msgid "On Read the Docs" +msgstr "" + +#: sphinx_rtd_theme/versions.html:26 +msgid "Project Home" +msgstr "" + +#: sphinx_rtd_theme/versions.html:29 +msgid "Builds" +msgstr "" + +#: sphinx_rtd_theme/versions.html:33 +msgid "Free document hosting provided by" +msgstr "" + diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/es/LC_MESSAGES/sphinx.po b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/es/LC_MESSAGES/sphinx.po index b5b8b74d..443936fd 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/es/LC_MESSAGES/sphinx.po +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/es/LC_MESSAGES/sphinx.po @@ -1,149 +1,149 @@ -# Spanish translations for sphinx_rtd_theme. -# Copyright (C) 2019 Read the Docs, Inc -# This file is distributed under the same license as the sphinx_rtd_theme -# project. -msgid "" -msgstr "" -"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" -"Report-Msgid-Bugs-To: support@readthedocs.org\n" -"POT-Creation-Date: 2019-07-24 23:51-0600\n" -"PO-Revision-Date: 2019-07-16 21:44+0000\n" -"Last-Translator: Anthony , 2019\n" -"Language: es\n" -"Language-Team: Spanish " -"(https://www.transifex.com/readthedocs/teams/101354/es/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.7.0\n" - -#: sphinx_rtd_theme/breadcrumbs.html:31 -msgid "Docs" -msgstr "Documentos" - -#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 -msgid "Edit on GitHub" -msgstr "Editar en GitHub" - -#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 -msgid "Edit on Bitbucket" -msgstr "Editar en Bitbucket" - -#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 -msgid "Edit on GitLab" -msgstr "Editar en GitLab" - -#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 -msgid "View page source" -msgstr "Ver código fuente de la página" - -#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 -msgid "Next" -msgstr "Siguiente" - -#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 -msgid "Previous" -msgstr "Anterior" - -#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 -#: sphinx_rtd_theme/layout.html:92 -msgid "Copyright" -msgstr "Derechos de autor" - -#. Build is a noun, not a verb -#: sphinx_rtd_theme/footer.html:31 -msgid "Build" -msgstr "Construido" - -#: sphinx_rtd_theme/footer.html:36 -msgid "Revision" -msgstr "Revisión" - -#: sphinx_rtd_theme/footer.html:40 -#, python-format -msgid "Last updated on %(last_updated)s." -msgstr "Actualizado por última vez en %(last_updated)s." - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "Built with %(sphinx_web)s using a" -msgstr "Construido con %(sphinx_web)s usando un" - -#: sphinx_rtd_theme/footer.html:50 -msgid "theme" -msgstr "tema" - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "provided by %(readthedocs_web)s" -msgstr "proporcionado por %(readthedocs_web)s" - -#: sphinx_rtd_theme/layout.html:61 -#, python-format -msgid "Search within %(docstitle)s" -msgstr "Buscar en %(docstitle)s" - -#: sphinx_rtd_theme/layout.html:83 -msgid "About these documents" -msgstr "Sobre esta documentación" - -#: sphinx_rtd_theme/layout.html:86 -msgid "Index" -msgstr "Índice" - -#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 -msgid "Search" -msgstr "Búsqueda" - -#: sphinx_rtd_theme/layout.html:124 -msgid "Logo" -msgstr "Logotipo" - -#: sphinx_rtd_theme/search.html:26 -msgid "Please activate JavaScript to enable the search functionality." -msgstr "Por favor, active JavaScript para habilitar la funcionalidad de búsqueda." - -#. Search is a noun, not a verb -#: sphinx_rtd_theme/search.html:34 -msgid "Search Results" -msgstr "Resultados de la búsqueda" - -#: sphinx_rtd_theme/search.html:36 -msgid "" -"Your search did not match any documents. Please make sure that all words " -"are spelled correctly and that you've selected enough categories." -msgstr "" -"Su búsqueda no coincide con ningún documento. Por favor, asegúrese de que" -" todas las palabras estén correctamente escritas y que usted haya " -"seleccionado las suficientes categorías." - -#: sphinx_rtd_theme/searchbox.html:4 -msgid "Search docs" -msgstr "Buscar documentos" - -#: sphinx_rtd_theme/versions.html:11 -msgid "Versions" -msgstr "Versiones" - -#: sphinx_rtd_theme/versions.html:17 -msgid "Downloads" -msgstr "Descargas" - -#. The phrase "Read the Docs" is not translated -#: sphinx_rtd_theme/versions.html:24 -msgid "On Read the Docs" -msgstr "En Read the Docs" - -#: sphinx_rtd_theme/versions.html:26 -msgid "Project Home" -msgstr "Página de Proyecto" - -#: sphinx_rtd_theme/versions.html:29 -msgid "Builds" -msgstr "Construcciones" - -#: sphinx_rtd_theme/versions.html:33 -msgid "Free document hosting provided by" -msgstr "Alojamiento gratuito de documentos proporcionado por" - +# Spanish translations for sphinx_rtd_theme. +# Copyright (C) 2019 Read the Docs, Inc +# This file is distributed under the same license as the sphinx_rtd_theme +# project. +msgid "" +msgstr "" +"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" +"Report-Msgid-Bugs-To: support@readthedocs.org\n" +"POT-Creation-Date: 2019-07-24 23:51-0600\n" +"PO-Revision-Date: 2019-07-16 21:44+0000\n" +"Last-Translator: Anthony , 2019\n" +"Language: es\n" +"Language-Team: Spanish " +"(https://www.transifex.com/readthedocs/teams/101354/es/)\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.7.0\n" + +#: sphinx_rtd_theme/breadcrumbs.html:31 +msgid "Docs" +msgstr "Documentos" + +#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 +msgid "Edit on GitHub" +msgstr "Editar en GitHub" + +#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 +msgid "Edit on Bitbucket" +msgstr "Editar en Bitbucket" + +#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 +msgid "Edit on GitLab" +msgstr "Editar en GitLab" + +#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 +msgid "View page source" +msgstr "Ver código fuente de la página" + +#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 +msgid "Next" +msgstr "Siguiente" + +#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 +msgid "Previous" +msgstr "Anterior" + +#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 +#: sphinx_rtd_theme/layout.html:92 +msgid "Copyright" +msgstr "Derechos de autor" + +#. Build is a noun, not a verb +#: sphinx_rtd_theme/footer.html:31 +msgid "Build" +msgstr "Construido" + +#: sphinx_rtd_theme/footer.html:36 +msgid "Revision" +msgstr "Revisión" + +#: sphinx_rtd_theme/footer.html:40 +#, python-format +msgid "Last updated on %(last_updated)s." +msgstr "Actualizado por última vez en %(last_updated)s." + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "Built with %(sphinx_web)s using a" +msgstr "Construido con %(sphinx_web)s usando un" + +#: sphinx_rtd_theme/footer.html:50 +msgid "theme" +msgstr "tema" + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "provided by %(readthedocs_web)s" +msgstr "proporcionado por %(readthedocs_web)s" + +#: sphinx_rtd_theme/layout.html:61 +#, python-format +msgid "Search within %(docstitle)s" +msgstr "Buscar en %(docstitle)s" + +#: sphinx_rtd_theme/layout.html:83 +msgid "About these documents" +msgstr "Sobre esta documentación" + +#: sphinx_rtd_theme/layout.html:86 +msgid "Index" +msgstr "Índice" + +#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 +msgid "Search" +msgstr "Búsqueda" + +#: sphinx_rtd_theme/layout.html:124 +msgid "Logo" +msgstr "Logotipo" + +#: sphinx_rtd_theme/search.html:26 +msgid "Please activate JavaScript to enable the search functionality." +msgstr "Por favor, active JavaScript para habilitar la funcionalidad de búsqueda." + +#. Search is a noun, not a verb +#: sphinx_rtd_theme/search.html:34 +msgid "Search Results" +msgstr "Resultados de la búsqueda" + +#: sphinx_rtd_theme/search.html:36 +msgid "" +"Your search did not match any documents. Please make sure that all words " +"are spelled correctly and that you've selected enough categories." +msgstr "" +"Su búsqueda no coincide con ningún documento. Por favor, asegúrese de que" +" todas las palabras estén correctamente escritas y que usted haya " +"seleccionado las suficientes categorías." + +#: sphinx_rtd_theme/searchbox.html:4 +msgid "Search docs" +msgstr "Buscar documentos" + +#: sphinx_rtd_theme/versions.html:11 +msgid "Versions" +msgstr "Versiones" + +#: sphinx_rtd_theme/versions.html:17 +msgid "Downloads" +msgstr "Descargas" + +#. The phrase "Read the Docs" is not translated +#: sphinx_rtd_theme/versions.html:24 +msgid "On Read the Docs" +msgstr "En Read the Docs" + +#: sphinx_rtd_theme/versions.html:26 +msgid "Project Home" +msgstr "Página de Proyecto" + +#: sphinx_rtd_theme/versions.html:29 +msgid "Builds" +msgstr "Construcciones" + +#: sphinx_rtd_theme/versions.html:33 +msgid "Free document hosting provided by" +msgstr "Alojamiento gratuito de documentos proporcionado por" + diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/nl/LC_MESSAGES/sphinx.po b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/nl/LC_MESSAGES/sphinx.po index f398ae75..a7d0cb3a 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/nl/LC_MESSAGES/sphinx.po +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/nl/LC_MESSAGES/sphinx.po @@ -1,152 +1,152 @@ -# English translations for sphinx_rtd_theme. -# Copyright (C) 2019 ORGANIZATION -# This file is distributed under the same license as the sphinx_rtd_theme -# project. -# FIRST AUTHOR , 2019. -# -# Translators: -# Jesse Tan, 2019 -msgid "" -msgstr "" -"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-07-24 23:51-0600\n" -"PO-Revision-Date: 2019-07-16 21:44+0000\n" -"Last-Translator: Jesse Tan, 2019\n" -"Language: nl\n" -"Language-Team: Dutch " -"(https://www.transifex.com/readthedocs/teams/101354/nl/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.7.0\n" - -#: sphinx_rtd_theme/breadcrumbs.html:31 -msgid "Docs" -msgstr "Documentatie" - -#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 -msgid "Edit on GitHub" -msgstr "Bewerk op GitHub" - -#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 -msgid "Edit on Bitbucket" -msgstr "Bewerk op BitBucket" - -#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 -msgid "Edit on GitLab" -msgstr "Bewerk op GitLab" - -#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 -msgid "View page source" -msgstr "Bekijk paginabron" - -#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 -msgid "Next" -msgstr "Volgende" - -#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 -msgid "Previous" -msgstr "Vorige" - -#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 -#: sphinx_rtd_theme/layout.html:92 -msgid "Copyright" -msgstr "Copyright" - -#. Build is a noun, not a verb -#: sphinx_rtd_theme/footer.html:31 -msgid "Build" -msgstr "Bouwsel" - -#: sphinx_rtd_theme/footer.html:36 -msgid "Revision" -msgstr "Revisie" - -#: sphinx_rtd_theme/footer.html:40 -#, python-format -msgid "Last updated on %(last_updated)s." -msgstr "Laatste update op %(last_updated)s." - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "Built with %(sphinx_web)s using a" -msgstr "Gebouwd met %(sphinx_web)s met een" - -#: sphinx_rtd_theme/footer.html:50 -msgid "theme" -msgstr "thema" - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "provided by %(readthedocs_web)s" -msgstr "geleverd door %(readthedocs_web)s" - -#: sphinx_rtd_theme/layout.html:61 -#, python-format -msgid "Search within %(docstitle)s" -msgstr "Zoek binnen %(docstitle)s" - -#: sphinx_rtd_theme/layout.html:83 -msgid "About these documents" -msgstr "Over deze documenten" - -#: sphinx_rtd_theme/layout.html:86 -msgid "Index" -msgstr "Index" - -#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 -msgid "Search" -msgstr "Zoek" - -#: sphinx_rtd_theme/layout.html:124 -msgid "Logo" -msgstr "Logo" - -#: sphinx_rtd_theme/search.html:26 -msgid "Please activate JavaScript to enable the search functionality." -msgstr "Zet JavaScript aan om de zoekfunctie mogelijk te maken." - -#. Search is a noun, not a verb -#: sphinx_rtd_theme/search.html:34 -msgid "Search Results" -msgstr "Zoekresultaten" - -#: sphinx_rtd_theme/search.html:36 -msgid "" -"Your search did not match any documents. Please make sure that all words " -"are spelled correctly and that you've selected enough categories." -msgstr "" -"Zoekpoging vond geen documenten. Zorg ervoor dat alle woorden correct " -"zijn gespeld en dat voldoende categorieën zijn geselecteerd." - -#: sphinx_rtd_theme/searchbox.html:4 -msgid "Search docs" -msgstr "Zoek in documentatie" - -#: sphinx_rtd_theme/versions.html:11 -msgid "Versions" -msgstr "Versies" - -#: sphinx_rtd_theme/versions.html:17 -msgid "Downloads" -msgstr "Downloads" - -#. The phrase "Read the Docs" is not translated -#: sphinx_rtd_theme/versions.html:24 -msgid "On Read the Docs" -msgstr "Op Read the Docs" - -#: sphinx_rtd_theme/versions.html:26 -msgid "Project Home" -msgstr "Project Home" - -#: sphinx_rtd_theme/versions.html:29 -msgid "Builds" -msgstr "Bouwsels" - -#: sphinx_rtd_theme/versions.html:33 -msgid "Free document hosting provided by" -msgstr "Gratis hosting voor documentatie verzorgd door" - +# English translations for sphinx_rtd_theme. +# Copyright (C) 2019 ORGANIZATION +# This file is distributed under the same license as the sphinx_rtd_theme +# project. +# FIRST AUTHOR , 2019. +# +# Translators: +# Jesse Tan, 2019 +msgid "" +msgstr "" +"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2019-07-24 23:51-0600\n" +"PO-Revision-Date: 2019-07-16 21:44+0000\n" +"Last-Translator: Jesse Tan, 2019\n" +"Language: nl\n" +"Language-Team: Dutch " +"(https://www.transifex.com/readthedocs/teams/101354/nl/)\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.7.0\n" + +#: sphinx_rtd_theme/breadcrumbs.html:31 +msgid "Docs" +msgstr "Documentatie" + +#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 +msgid "Edit on GitHub" +msgstr "Bewerk op GitHub" + +#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 +msgid "Edit on Bitbucket" +msgstr "Bewerk op BitBucket" + +#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 +msgid "Edit on GitLab" +msgstr "Bewerk op GitLab" + +#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 +msgid "View page source" +msgstr "Bekijk paginabron" + +#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 +msgid "Next" +msgstr "Volgende" + +#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 +msgid "Previous" +msgstr "Vorige" + +#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 +#: sphinx_rtd_theme/layout.html:92 +msgid "Copyright" +msgstr "Copyright" + +#. Build is a noun, not a verb +#: sphinx_rtd_theme/footer.html:31 +msgid "Build" +msgstr "Bouwsel" + +#: sphinx_rtd_theme/footer.html:36 +msgid "Revision" +msgstr "Revisie" + +#: sphinx_rtd_theme/footer.html:40 +#, python-format +msgid "Last updated on %(last_updated)s." +msgstr "Laatste update op %(last_updated)s." + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "Built with %(sphinx_web)s using a" +msgstr "Gebouwd met %(sphinx_web)s met een" + +#: sphinx_rtd_theme/footer.html:50 +msgid "theme" +msgstr "thema" + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "provided by %(readthedocs_web)s" +msgstr "geleverd door %(readthedocs_web)s" + +#: sphinx_rtd_theme/layout.html:61 +#, python-format +msgid "Search within %(docstitle)s" +msgstr "Zoek binnen %(docstitle)s" + +#: sphinx_rtd_theme/layout.html:83 +msgid "About these documents" +msgstr "Over deze documenten" + +#: sphinx_rtd_theme/layout.html:86 +msgid "Index" +msgstr "Index" + +#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 +msgid "Search" +msgstr "Zoek" + +#: sphinx_rtd_theme/layout.html:124 +msgid "Logo" +msgstr "Logo" + +#: sphinx_rtd_theme/search.html:26 +msgid "Please activate JavaScript to enable the search functionality." +msgstr "Zet JavaScript aan om de zoekfunctie mogelijk te maken." + +#. Search is a noun, not a verb +#: sphinx_rtd_theme/search.html:34 +msgid "Search Results" +msgstr "Zoekresultaten" + +#: sphinx_rtd_theme/search.html:36 +msgid "" +"Your search did not match any documents. Please make sure that all words " +"are spelled correctly and that you've selected enough categories." +msgstr "" +"Zoekpoging vond geen documenten. Zorg ervoor dat alle woorden correct " +"zijn gespeld en dat voldoende categorieën zijn geselecteerd." + +#: sphinx_rtd_theme/searchbox.html:4 +msgid "Search docs" +msgstr "Zoek in documentatie" + +#: sphinx_rtd_theme/versions.html:11 +msgid "Versions" +msgstr "Versies" + +#: sphinx_rtd_theme/versions.html:17 +msgid "Downloads" +msgstr "Downloads" + +#. The phrase "Read the Docs" is not translated +#: sphinx_rtd_theme/versions.html:24 +msgid "On Read the Docs" +msgstr "Op Read the Docs" + +#: sphinx_rtd_theme/versions.html:26 +msgid "Project Home" +msgstr "Project Home" + +#: sphinx_rtd_theme/versions.html:29 +msgid "Builds" +msgstr "Bouwsels" + +#: sphinx_rtd_theme/versions.html:33 +msgid "Free document hosting provided by" +msgstr "Gratis hosting voor documentatie verzorgd door" + diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/ru/LC_MESSAGES/sphinx.po b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/ru/LC_MESSAGES/sphinx.po index 01c960ae..f644d579 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/locale/ru/LC_MESSAGES/sphinx.po +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/locale/ru/LC_MESSAGES/sphinx.po @@ -1,148 +1,148 @@ -# Russian translations for sphinx_rtd_theme. -# Copyright (C) 2019 Read the Docs, Inc -# This file is distributed under the same license as the sphinx_rtd_theme -# project. -msgid "" -msgstr "" -"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" -"Report-Msgid-Bugs-To: support@readthedocs.org\n" -"POT-Creation-Date: 2019-07-24 23:51-0600\n" -"PO-Revision-Date: 2019-07-16 21:44+0000\n" -"Last-Translator: FULL NAME \n" -"Language: ru\n" -"Language-Team: Russian " -"(https://www.transifex.com/readthedocs/teams/101354/ru/)\n" -"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " -"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) " -"|| (n%100>=11 && n%100<=14)? 2 : 3)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.7.0\n" - -#: sphinx_rtd_theme/breadcrumbs.html:31 -msgid "Docs" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 -msgid "Edit on GitHub" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 -msgid "Edit on Bitbucket" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 -msgid "Edit on GitLab" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 -msgid "View page source" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 -msgid "Next" -msgstr "" - -#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 -msgid "Previous" -msgstr "" - -#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 -#: sphinx_rtd_theme/layout.html:92 -msgid "Copyright" -msgstr "" - -#. Build is a noun, not a verb -#: sphinx_rtd_theme/footer.html:31 -msgid "Build" -msgstr "" - -#: sphinx_rtd_theme/footer.html:36 -msgid "Revision" -msgstr "" - -#: sphinx_rtd_theme/footer.html:40 -#, python-format -msgid "Last updated on %(last_updated)s." -msgstr "" - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "Built with %(sphinx_web)s using a" -msgstr "" - -#: sphinx_rtd_theme/footer.html:50 -msgid "theme" -msgstr "" - -#: sphinx_rtd_theme/footer.html:50 -#, python-format -msgid "provided by %(readthedocs_web)s" -msgstr "" - -#: sphinx_rtd_theme/layout.html:61 -#, python-format -msgid "Search within %(docstitle)s" -msgstr "" - -#: sphinx_rtd_theme/layout.html:83 -msgid "About these documents" -msgstr "" - -#: sphinx_rtd_theme/layout.html:86 -msgid "Index" -msgstr "" - -#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 -msgid "Search" -msgstr "" - -#: sphinx_rtd_theme/layout.html:124 -msgid "Logo" -msgstr "" - -#: sphinx_rtd_theme/search.html:26 -msgid "Please activate JavaScript to enable the search functionality." -msgstr "" - -#. Search is a noun, not a verb -#: sphinx_rtd_theme/search.html:34 -msgid "Search Results" -msgstr "" - -#: sphinx_rtd_theme/search.html:36 -msgid "" -"Your search did not match any documents. Please make sure that all words " -"are spelled correctly and that you've selected enough categories." -msgstr "" - -#: sphinx_rtd_theme/searchbox.html:4 -msgid "Search docs" -msgstr "" - -#: sphinx_rtd_theme/versions.html:11 -msgid "Versions" -msgstr "" - -#: sphinx_rtd_theme/versions.html:17 -msgid "Downloads" -msgstr "" - -#. The phrase "Read the Docs" is not translated -#: sphinx_rtd_theme/versions.html:24 -msgid "On Read the Docs" -msgstr "" - -#: sphinx_rtd_theme/versions.html:26 -msgid "Project Home" -msgstr "" - -#: sphinx_rtd_theme/versions.html:29 -msgid "Builds" -msgstr "" - -#: sphinx_rtd_theme/versions.html:33 -msgid "Free document hosting provided by" -msgstr "" - +# Russian translations for sphinx_rtd_theme. +# Copyright (C) 2019 Read the Docs, Inc +# This file is distributed under the same license as the sphinx_rtd_theme +# project. +msgid "" +msgstr "" +"Project-Id-Version: sphinx_rtd_theme 0.4.3.dev0\n" +"Report-Msgid-Bugs-To: support@readthedocs.org\n" +"POT-Creation-Date: 2019-07-24 23:51-0600\n" +"PO-Revision-Date: 2019-07-16 21:44+0000\n" +"Last-Translator: FULL NAME \n" +"Language: ru\n" +"Language-Team: Russian " +"(https://www.transifex.com/readthedocs/teams/101354/ru/)\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) " +"|| (n%100>=11 && n%100<=14)? 2 : 3)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.7.0\n" + +#: sphinx_rtd_theme/breadcrumbs.html:31 +msgid "Docs" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:43 sphinx_rtd_theme/breadcrumbs.html:45 +msgid "Edit on GitHub" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:50 sphinx_rtd_theme/breadcrumbs.html:52 +msgid "Edit on Bitbucket" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:57 sphinx_rtd_theme/breadcrumbs.html:59 +msgid "Edit on GitLab" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:62 sphinx_rtd_theme/breadcrumbs.html:64 +msgid "View page source" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:74 sphinx_rtd_theme/footer.html:5 +msgid "Next" +msgstr "" + +#: sphinx_rtd_theme/breadcrumbs.html:77 sphinx_rtd_theme/footer.html:8 +msgid "Previous" +msgstr "" + +#: sphinx_rtd_theme/footer.html:21 sphinx_rtd_theme/footer.html:24 +#: sphinx_rtd_theme/layout.html:92 +msgid "Copyright" +msgstr "" + +#. Build is a noun, not a verb +#: sphinx_rtd_theme/footer.html:31 +msgid "Build" +msgstr "" + +#: sphinx_rtd_theme/footer.html:36 +msgid "Revision" +msgstr "" + +#: sphinx_rtd_theme/footer.html:40 +#, python-format +msgid "Last updated on %(last_updated)s." +msgstr "" + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "Built with %(sphinx_web)s using a" +msgstr "" + +#: sphinx_rtd_theme/footer.html:50 +msgid "theme" +msgstr "" + +#: sphinx_rtd_theme/footer.html:50 +#, python-format +msgid "provided by %(readthedocs_web)s" +msgstr "" + +#: sphinx_rtd_theme/layout.html:61 +#, python-format +msgid "Search within %(docstitle)s" +msgstr "" + +#: sphinx_rtd_theme/layout.html:83 +msgid "About these documents" +msgstr "" + +#: sphinx_rtd_theme/layout.html:86 +msgid "Index" +msgstr "" + +#: sphinx_rtd_theme/layout.html:89 sphinx_rtd_theme/search.html:11 +msgid "Search" +msgstr "" + +#: sphinx_rtd_theme/layout.html:124 +msgid "Logo" +msgstr "" + +#: sphinx_rtd_theme/search.html:26 +msgid "Please activate JavaScript to enable the search functionality." +msgstr "" + +#. Search is a noun, not a verb +#: sphinx_rtd_theme/search.html:34 +msgid "Search Results" +msgstr "" + +#: sphinx_rtd_theme/search.html:36 +msgid "" +"Your search did not match any documents. Please make sure that all words " +"are spelled correctly and that you've selected enough categories." +msgstr "" + +#: sphinx_rtd_theme/searchbox.html:4 +msgid "Search docs" +msgstr "" + +#: sphinx_rtd_theme/versions.html:11 +msgid "Versions" +msgstr "" + +#: sphinx_rtd_theme/versions.html:17 +msgid "Downloads" +msgstr "" + +#. The phrase "Read the Docs" is not translated +#: sphinx_rtd_theme/versions.html:24 +msgid "On Read the Docs" +msgstr "" + +#: sphinx_rtd_theme/versions.html:26 +msgid "Project Home" +msgstr "" + +#: sphinx_rtd_theme/versions.html:29 +msgid "Builds" +msgstr "" + +#: sphinx_rtd_theme/versions.html:33 +msgid "Free document hosting provided by" +msgstr "" + diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/search.html b/process/collaborator_report/_themes/sphinx_rtd_theme/search.html index 10ac568c..075b7e29 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/search.html +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/search.html @@ -1,54 +1,54 @@ -{# - basic/search.html - ~~~~~~~~~~~~~~~~~ - - Template for the search page. - - :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -#} -{%- extends "layout.html" %} -{% set title = _('Search') %} -{%- block scripts %} - {{ super() }} - -{%- endblock %} -{% block footer %} - - {# this is used when loading the search index using $.ajax fails, - such as on Chrome for documents on localhost #} - - {{ super() }} -{% endblock %} -{% block body %} - - - {% if search_performed %} - {# Translators: Search is a noun, not a verb #} -

{{ _('Search Results') }}

- {% if not search_results %} -

{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

- {% endif %} - {% endif %} -
- {% if search_results %} -
    - {% for href, caption, context in search_results %} -
  • - {{ caption }} -

    {{ context|e }}

    -
  • - {% endfor %} -
- {% endif %} -
-{% endblock %} +{# + basic/search.html + ~~~~~~~~~~~~~~~~~ + + Template for the search page. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- extends "layout.html" %} +{% set title = _('Search') %} +{%- block scripts %} + {{ super() }} + +{%- endblock %} +{% block footer %} + + {# this is used when loading the search index using $.ajax fails, + such as on Chrome for documents on localhost #} + + {{ super() }} +{% endblock %} +{% block body %} + + + {% if search_performed %} + {# Translators: Search is a noun, not a verb #} +

{{ _('Search Results') }}

+ {% if not search_results %} +

{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

+ {% endif %} + {% endif %} +
+ {% if search_results %} +
    + {% for href, caption, context in search_results %} +
  • + {{ caption }} +

    {{ context|e }}

    +
  • + {% endfor %} +
+ {% endif %} +
+{% endblock %} diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/searchbox.html b/process/collaborator_report/_themes/sphinx_rtd_theme/searchbox.html index 606f5c8c..59c2295d 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/searchbox.html +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/searchbox.html @@ -1,9 +1,9 @@ -{%- if builder != 'singlehtml' %} -
-
- - - -
-
-{%- endif %} +{%- if builder != 'singlehtml' %} +
+
+ + + +
+
+{%- endif %} diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/badge_only.css b/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/badge_only.css index 3c33cef5..a877e5ee 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/badge_only.css +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/badge_only.css @@ -1 +1 @@ -.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} +.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/theme.css b/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/theme.css index 9f0837a7..53ddacb0 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/theme.css +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/static/css/theme.css @@ -1,6 +1,6 @@ -@charset "UTF-8";html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li span.toctree-expand:before,.wy-nav-top a,.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased} - -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) +@charset "UTF-8";html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li span.toctree-expand:before,.wy-nav-top a,.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased} + +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(../fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(../fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(../fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(../fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(../fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li span.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p.caption .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a span.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-left.toctree-expand,.wy-menu-vertical li span.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p.caption .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a span.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-right.toctree-expand,.wy-menu-vertical li span.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li span.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li span.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li span.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li span.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li span.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p.caption .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.btn .wy-menu-vertical li span.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p.caption .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.nav .wy-menu-vertical li span.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p.caption .btn .headerlink,.rst-content p.caption .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li span.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol li,.rst-content ol.arabic li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content ol.arabic li p:last-child,.rst-content ol.arabic li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.rst-content .wy-breadcrumbs li tt,.wy-breadcrumbs li .rst-content tt,.wy-breadcrumbs li code{padding:5px;border:none;background:none}.rst-content .wy-breadcrumbs li tt.literal,.wy-breadcrumbs li .rst-content tt.literal,.wy-breadcrumbs li code.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover span.toctree-expand,.wy-menu-vertical li.on a:hover span.toctree-expand{color:grey}.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand{display:block;font-size:.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a{color:#404040}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{width:300px;z-index:200;background-color:#2980b9;text-align:center;padding:.809em;display:block;color:#fcfcfc;margin-bottom:.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions .rst-current-version{*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .note .last,.rst-content .seealso .last,.rst-content .tip .last,.rst-content .warning .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .section ol p:last-child,.rst-content .section ul p:last-child{margin-bottom:24px}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink{visibility:hidden;font-size:14px}.rst-content .code-block-caption .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after{content:"\f0c1";font-family:FontAwesome}.rst-content .code-block-caption:hover .headerlink:after,.rst-content .toctree-wrapper p.caption:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;display:inline-block;font-weight:700;padding:0 6px}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:grey}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.docutils.citation code,.rst-content table.docutils.citation tt,.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}.rst-content table.docutils td .last,.rst-content table.docutils td .last :last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{font-size:inherit;line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px!important}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100%!important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100%!important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) code,.rst-content dl:not(.docutils) tt{font-weight:700}.rst-content dl:not(.docutils) code.descclassname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descname{font-weight:700}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(../fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(../fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:Lato;src:url(../fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(../fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:swap}@font-face{font-family:Lato;src:url(../fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(../fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:swap}@font-face{font-family:Lato;src:url(../fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(../fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:swap}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(../fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(../fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:swap}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(../fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(../fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:swap}.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(../fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(../fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(../fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(../fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(../fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg b/process/collaborator_report/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg index 855c845e..d7534c97 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg @@ -1,2671 +1,2671 @@ - - - - -Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 - By ,,, -Copyright Dave Gandy 2016. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/process/collaborator_report/_themes/sphinx_rtd_theme/static/js/modernizr.min.js b/process/collaborator_report/_themes/sphinx_rtd_theme/static/js/modernizr.min.js index f65d4797..d5787b6a 100644 --- a/process/collaborator_report/_themes/sphinx_rtd_theme/static/js/modernizr.min.js +++ b/process/collaborator_report/_themes/sphinx_rtd_theme/static/js/modernizr.min.js @@ -1,4 +1,4 @@ -/* Modernizr 2.6.2 (Custom Build) | MIT & BSD - * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load - */ -;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f"),e("table.docutils.footnote").wrap("
"),e("table.docutils.citation").wrap("
"),e(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var n=e(this);expand=e(''),expand.on("click",function(e){return t.toggleCurrent(n),e.stopPropagation(),!1}),n.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),n=t.find('[href="'+e+'"]');if(0===n.length){var r=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(n=t.find('[href="#'+r.attr("id")+'"]')).length&&(n=t.find('[href="#"]'))}n.length>0&&($(".wy-menu-vertical .current").removeClass("current"),n.addClass("current"),n.closest("li.toctree-l1").addClass("current"),n.closest("li.toctree-l1").parent().addClass("current"),n.closest("li.toctree-l1").addClass("current"),n.closest("li.toctree-l2").addClass("current"),n.closest("li.toctree-l3").addClass("current"),n.closest("li.toctree-l4").addClass("current"),n[0].scrollIntoView())}catch(e){console.log("Error expanding nav for anchor",e)}},onScroll:function(){this.winScroll=!1;var e=this.win.scrollTop(),t=e+this.winHeight,n=this.navBar.scrollTop()+(e-this.winPosition);e<0||t>this.docHeight||(this.navBar.scrollTop(n),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var e=0,t=["ms","moz","webkit","o"],n=0;n0&&t-1 in e)}C.fn=C.prototype={jquery:"3.4.1",constructor:C,length:0,toArray:function(){return u.call(this)},get:function(e){return null==e?u.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=C.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return C.each(this,e)},map:function(e){return this.pushStack(C.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(u.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n"),e("table.docutils.footnote").wrap("
"),e("table.docutils.citation").wrap("
"),e(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var n=e(this);expand=e(''),expand.on("click",function(e){return t.toggleCurrent(n),e.stopPropagation(),!1}),n.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t=$(".wy-menu-vertical"),n=t.find('[href="'+e+'"]');if(0===n.length){var r=$('.document [id="'+e.substring(1)+'"]').closest("div.section");0===(n=t.find('[href="#'+r.attr("id")+'"]')).length&&(n=t.find('[href="#"]'))}n.length>0&&($(".wy-menu-vertical .current").removeClass("current"),n.addClass("current"),n.closest("li.toctree-l1").addClass("current"),n.closest("li.toctree-l1").parent().addClass("current"),n.closest("li.toctree-l1").addClass("current"),n.closest("li.toctree-l2").addClass("current"),n.closest("li.toctree-l3").addClass("current"),n.closest("li.toctree-l4").addClass("current"),n[0].scrollIntoView())}catch(e){console.log("Error expanding nav for anchor",e)}},onScroll:function(){this.winScroll=!1;var e=this.win.scrollTop(),t=e+this.winHeight,n=this.navBar.scrollTop()+(e-this.winPosition);e<0||t>this.docHeight||(this.navBar.scrollTop(n),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){var t=e.closest("li");t.siblings("li.current").removeClass("current"),t.siblings().find("li.current").removeClass("current"),t.find("> ul li.current").removeClass("current"),t.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var e=0,t=["ms","moz","webkit","o"],n=0;n0&&t-1 in e)}C.fn=C.prototype={jquery:"3.4.1",constructor:C,length:0,toArray:function(){return u.call(this)},get:function(e){return null==e?u.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=C.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return C.each(this,e)},map:function(e){return this.pushStack(C.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(u.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+F),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){p()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(D=O.call(w.childNodes),w.childNodes),D[w.childNodes.length].nodeType}catch(e){H={apply:D.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function se(e,t,r,i){var o,s,l,c,f,h,m,y=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=Z.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(y&&(l=y.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return H.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return H.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!A[e+" "]&&(!v||!v.test(e))&&(1!==T||"object"!==t.nodeName.toLowerCase())){if(m=e,y=t,1===T&&U.test(e)){for((c=t.getAttribute("id"))?c=c.replace(re,ie):t.setAttribute("id",c=b),s=(h=a(e)).length;s--;)h[s]="#"+c+" "+xe(h[s]);m=h.join(","),y=ee.test(e)&&me(t.parentNode)||t}try{return H.apply(r,y.querySelectorAll(m)),r}catch(t){A(e,!0)}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ue(){var e=[];return function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}}function le(e){return e[b]=!0,e}function ce(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){for(var n=e.split("|"),i=n.length;i--;)r.attrHandle[n[i]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function de(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function he(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ge(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ae(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function ve(e){return le(function(t){return t=+t,le(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function me(e){return e&&void 0!==e.getElementsByTagName&&e}for(t in n=se.support={},o=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},p=se.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(h=(d=a).documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",oe,!1):i.attachEvent&&i.attachEvent("onunload",oe)),n.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ce(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=K.test(d.getElementsByClassName),n.getById=ce(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(te,ne);return function(e){var n=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&g)return t.getElementsByClassName(e)},m=[],v=[],(n.qsa=K.test(d.querySelectorAll))&&(ce(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(n.matchesSelector=K.test(y=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ce(function(e){n.disconnectedMatch=y.call(e,"*"),y.call(e,"[s!='']:x"),m.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),m=m.length&&new RegExp(m.join("|")),t=K.test(h.compareDocumentPosition),x=t||K.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},N=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?R(c,e)-R(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?R(c,e)-R(c,t):0;if(i===o)return pe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?pe(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),n.matchesSelector&&g&&!A[t+" "]&&(!m||!m.test(t))&&(!v||!v.test(t)))try{var r=y.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){A(t,!0)}return se(t,d,null,[e]).length>0},se.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&j.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(N),f){for(;t=e[o++];)t===e[o]&&(i=r.push(o));for(;i--;)e.splice(r[i],1)}return c=null,e},i=se.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r++];)n+=i(t);return n},(r=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=S[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&S(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=se.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace(W," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",v=t.parentNode,m=s&&t.nodeName.toLowerCase(),y=!u&&!s,x=!1;if(v){if(o){for(;g;){for(p=t;p=p[g];)if(s?p.nodeName.toLowerCase()===m:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?v.firstChild:v.lastChild],a&&y){for(x=(d=(l=(c=(f=(p=v)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&v.childNodes[d];p=++d&&p&&p[g]||(x=d=0)||h.pop();)if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(y&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)for(;(p=++d&&p&&p[g]||(x=d=0)||h.pop())&&((s?p.nodeName.toLowerCase()!==m:1!==p.nodeType)||!++x||(y&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p!==t)););return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,n){for(var r,o=i(e,t),a=o.length;a--;)e[r=R(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:le(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?le(function(e,t,n,i){for(var o,a=r(e,null,i,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:le(function(e){return function(t){return se(e,t).length>0}}),contains:le(function(e){return e=e.replace(te,ne),function(t){return(t.textContent||i(t)).indexOf(e)>-1}}),lang:le(function(e){return V.test(e||"")||se.error("unsupported lang: "+e),e=e.replace(te,ne).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;nt?t:n;--r>=0;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s-1&&(o[l]=!(a[l]=f))}}else m=Te(m===a?m.splice(h,m.length):m),i?i(null,a,m,u):H.apply(a,m)})}function Se(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=be(function(e){return e===t},s,!0),f=be(function(e){return R(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&we(p),u>1&&xe(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,v,m=0,y="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),S=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);y!==k&&null!=(f=C[y]);y++){if(i&&f){for(h=0,a||f.ownerDocument===d||(p(f),s=!g);v=e[h++];)if(v(f,a||d,s)){u.push(f);break}c&&(T=S)}n&&((f=!v&&f)&&m--,o&&x.push(f))}if(m+=y,n&&y!==m){for(h=0;v=t[h++];)v(x,b,a,s);if(o){if(m>0)for(;y--;)x[y]||b[y]||(b[y]=q.call(u));b=Te(b)}H.apply(u,b),c&&!o&&b.length>0&&m+t.length>1&&se.uniqueSort(u)}return c&&(T=S,l=w),x};return n?le(o):o}(o,i))).selector=e}return s},u=se.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(te,ne),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}for(o=G.needsContext.test(e)?0:u.length;o--&&(l=u[o],!r.relative[c=l.type]);)if((f=r.find[c])&&(i=f(l.matches[0].replace(te,ne),ee.test(u[0].type)&&me(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&xe(u)))return H.apply(n,i),n;break}}return(p||s(e,d))(i,t,!g,n,!t||ee.test(e)&&me(t.parentNode)||t),n},n.sortStable=b.split("").sort(N).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ce(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ce(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(n);C.find=E,C.expr=E.selectors,C.expr[":"]=C.expr.pseudos,C.uniqueSort=C.unique=E.uniqueSort,C.text=E.getText,C.isXMLDoc=E.isXML,C.contains=E.contains,C.escapeSelector=E.escape;var A=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&C(e).is(n))break;r.push(e)}return r},N=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},j=C.expr.match.needsContext;function D(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var q=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function L(e,t,n){return y(t)?C.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?C.grep(e,function(e){return e===t!==n}):"string"!=typeof t?C.grep(e,function(e){return f.call(t,e)>-1!==n}):C.filter(t,e,n)}C.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?C.find.matchesSelector(r,e)?[r]:[]:C.find.matches(e,C.grep(t,function(e){return 1===e.nodeType}))},C.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(C(e).filter(function(){for(t=0;t1?C.uniqueSort(n):n},filter:function(e){return this.pushStack(L(this,e||[],!1))},not:function(e){return this.pushStack(L(this,e||[],!0))},is:function(e){return!!L(this,"string"==typeof e&&j.test(e)?C(e):e||[],!1).length}});var H,O=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(C.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||H,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:O.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof C?t[0]:t,C.merge(this,C.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:a,!0)),q.test(r[1])&&C.isPlainObject(t))for(r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=a.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(C):C.makeArray(e,this)}).prototype=C.fn,H=C(a);var R=/^(?:parents|prev(?:Until|All))/,P={children:!0,contents:!0,next:!0,prev:!0};function M(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}C.fn.extend({has:function(e){var t=C(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&C.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?C.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?f.call(C(e),this[0]):f.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(C.uniqueSort(C.merge(this.get(),C(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),C.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return A(e,"parentNode")},parentsUntil:function(e,t,n){return A(e,"parentNode",n)},next:function(e){return M(e,"nextSibling")},prev:function(e){return M(e,"previousSibling")},nextAll:function(e){return A(e,"nextSibling")},prevAll:function(e){return A(e,"previousSibling")},nextUntil:function(e,t,n){return A(e,"nextSibling",n)},prevUntil:function(e,t,n){return A(e,"previousSibling",n)},siblings:function(e){return N((e.parentNode||{}).firstChild,e)},children:function(e){return N(e.firstChild)},contents:function(e){return void 0!==e.contentDocument?e.contentDocument:(D(e,"template")&&(e=e.content||e),C.merge([],e.childNodes))}},function(e,t){C.fn[e]=function(n,r){var i=C.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=C.filter(r,i)),this.length>1&&(P[e]||C.uniqueSort(i),R.test(e)&&i.reverse()),this.pushStack(i)}});var I=/[^\x20\t\r\n\f]+/g;function F(e){return e}function $(e){throw e}function W(e,t,n,r){var i;try{e&&y(i=e.promise)?i.call(e).done(t).fail(n):e&&y(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}C.Callbacks=function(e){e="string"==typeof e?function(e){var t={};return C.each(e.match(I)||[],function(e,n){t[n]=!0}),t}(e):C.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1)for(n=a.shift();++s-1;)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?C.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l},C.extend({Deferred:function(e){var t=[["notify","progress",C.Callbacks("memory"),C.Callbacks("memory"),2],["resolve","done",C.Callbacks("once memory"),C.Callbacks("once memory"),0,"resolved"],["reject","fail",C.Callbacks("once memory"),C.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},catch:function(e){return i.then(null,e)},pipe:function(){var e=arguments;return C.Deferred(function(n){C.each(t,function(t,r){var i=y(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&y(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(e,r,i){var o=0;function a(e,t,r,i){return function(){var s=this,u=arguments,l=function(){var n,l;if(!(e=o&&(r!==$&&(s=void 0,u=[n]),t.rejectWith(s,u))}};e?c():(C.Deferred.getStackHook&&(c.stackTrace=C.Deferred.getStackHook()),n.setTimeout(c))}}return C.Deferred(function(n){t[0][3].add(a(0,n,y(i)?i:F,n.notifyWith)),t[1][3].add(a(0,n,y(e)?e:F)),t[2][3].add(a(0,n,y(r)?r:$))}).promise()},promise:function(e){return null!=e?C.extend(e,i):i}},o={};return C.each(t,function(e,n){var a=n[2],s=n[5];i[n[1]]=a.add,s&&a.add(function(){r=s},t[3-e][2].disable,t[3-e][3].disable,t[0][2].lock,t[0][3].lock),a.add(n[3].fire),o[n[0]]=function(){return o[n[0]+"With"](this===o?void 0:this,arguments),this},o[n[0]+"With"]=a.fireWith}),i.promise(o),e&&e.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=u.call(arguments),o=C.Deferred(),a=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?u.call(arguments):n,--t||o.resolveWith(r,i)}};if(t<=1&&(W(e,o.done(a(n)).resolve,o.reject,!t),"pending"===o.state()||y(i[n]&&i[n].then)))return o.then();for(;n--;)W(i[n],a(n),o.reject);return o.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;C.Deferred.exceptionHook=function(e,t){n.console&&n.console.warn&&e&&B.test(e.name)&&n.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},C.readyException=function(e){n.setTimeout(function(){throw e})};var _=C.Deferred();function z(){a.removeEventListener("DOMContentLoaded",z),n.removeEventListener("load",z),C.ready()}C.fn.ready=function(e){return _.then(e).catch(function(e){C.readyException(e)}),this},C.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--C.readyWait:C.isReady)||(C.isReady=!0,!0!==e&&--C.readyWait>0||_.resolveWith(a,[C]))}}),C.ready.then=_.then,"complete"===a.readyState||"loading"!==a.readyState&&!a.documentElement.doScroll?n.setTimeout(C.ready):(a.addEventListener("DOMContentLoaded",z),n.addEventListener("load",z));var U=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===T(n))for(s in i=!0,n)U(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,y(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(C(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){Z.remove(this,e)})}}),C.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=K.get(e,t),n&&(!r||Array.isArray(n)?r=K.access(e,t,C.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=C.queue(e,t),r=n.length,i=n.shift(),o=C._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){C.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return K.get(e,n)||K.access(e,n,{empty:C.Callbacks("once memory").add(function(){K.remove(e,[t+"queue",n])})})}}),C.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]*)/i,me=/^$|^module$|\/(?:java|ecma)script/i,ye={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function xe(e,t){var n;return n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&D(e,t)?C.merge([e],n):n}function be(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=se(o),a=xe(f.appendChild(o),"script"),l&&be(a),n)for(c=0;o=a[c++];)me.test(o.type||"")&&n.push(o);return f}we=a.createDocumentFragment().appendChild(a.createElement("div")),(Te=a.createElement("input")).setAttribute("type","radio"),Te.setAttribute("checked","checked"),Te.setAttribute("name","t"),we.appendChild(Te),m.checkClone=we.cloneNode(!0).cloneNode(!0).lastChild.checked,we.innerHTML="",m.noCloneChecked=!!we.cloneNode(!0).lastChild.defaultValue;var ke=/^key/,Ee=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ae=/^([^.]*)(?:\.(.+)|)/;function Ne(){return!0}function je(){return!1}function De(e,t){return e===function(){try{return a.activeElement}catch(e){}}()==("focus"===t)}function qe(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)qe(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=je;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return C().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=C.guid++)),e.each(function(){C.event.add(this,t,i,r,n)})}function Le(e,t,n){n?(K.set(e,t,!1),C.event.add(e,t,{namespace:!1,handler:function(e){var r,i,o=K.get(this,t);if(1&e.isTrigger&&this[t]){if(o.length)(C.event.special[t]||{}).delegateType&&e.stopPropagation();else if(o=u.call(arguments),K.set(this,t,o),r=n(this,t),this[t](),o!==(i=K.get(this,t))||r?K.set(this,t,!1):i={},o!==i)return e.stopImmediatePropagation(),e.preventDefault(),i.value}else o.length&&(K.set(this,t,{value:C.event.trigger(C.extend(o[0],C.Event.prototype),o.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===K.get(e,t)&&C.event.add(e,t,Ne)}C.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=K.get(e);if(v)for(n.handler&&(n=(o=n).handler,i=o.selector),i&&C.find.matchesSelector(ae,i),n.guid||(n.guid=C.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(t){return void 0!==C&&C.event.triggered!==t.type?C.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(I)||[""]).length;l--;)d=g=(s=Ae.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=C.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=C.event.special[d]||{},c=C.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&C.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),C.event.global[d]=!0)},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=K.hasData(e)&&K.get(e);if(v&&(u=v.events)){for(l=(t=(t||"").match(I)||[""]).length;l--;)if(d=g=(s=Ae.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){for(f=C.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||C.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)C.event.remove(e,d+t[l],n,r,!0);C.isEmptyObject(u)&&K.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=C.event.fix(e),u=new Array(arguments.length),l=(K.get(this,"events")||{})[s.type]||[],c=C.event.special[s.type]||{};for(u[0]=s,t=1;t=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:C.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Oe=/\s*$/g;function Me(e,t){return D(e,"table")&&D(11!==t.nodeType?t:t.firstChild,"tr")&&C(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Fe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function $e(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(K.hasData(e)&&(o=K.access(e),a=K.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n1&&"string"==typeof h&&!m.checkClone&&Re.test(h))return e.each(function(i){var o=e.eq(i);g&&(t[0]=h.call(this,i,o.html())),Be(o,t,n,r)});if(p&&(o=(i=Se(t,e[0].ownerDocument,!1,e,r)).firstChild,1===i.childNodes.length&&(i=o),o||r)){for(s=(a=C.map(xe(i,"script"),Ie)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=se(e);if(!(m.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||C.isXMLDoc(e)))for(a=xe(s),r=0,i=(o=xe(e)).length;r0&&be(a,!u&&xe(e,"script")),s},cleanData:function(e){for(var t,n,r,i=C.event.special,o=0;void 0!==(n=e[o]);o++)if(Q(n)){if(t=n[K.expando]){if(t.events)for(r in t.events)i[r]?C.event.remove(n,r):C.removeEvent(n,r,t.handle);n[K.expando]=void 0}n[Z.expando]&&(n[Z.expando]=void 0)}}}),C.fn.extend({detach:function(e){return _e(this,e,!0)},remove:function(e){return _e(this,e)},text:function(e){return U(this,function(e){return void 0===e?C.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Be(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Me(this,e).appendChild(e)})},prepend:function(){return Be(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Me(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Be(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Be(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(C.cleanData(xe(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return C.clone(this,e,t)})},html:function(e){return U(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Oe.test(e)&&!ye[(ve.exec(e)||["",""])[1].toLowerCase()]){e=C.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function ot(e,t,n){var r=Ue(e),i=(!m.boxSizingReliable()||n)&&"border-box"===C.css(e,"boxSizing",!1,r),o=i,a=Ve(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(ze.test(a)){if(!n)return a;a="auto"}return(!m.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===C.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===C.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+it(e,t,n||(i?"border":"content"),o,r,a)+"px"}function at(e,t,n,r,i){return new at.prototype.init(e,t,n,r,i)}C.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Ve(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=Y(t),u=et.test(t),l=e.style;if(u||(t=Ke(s)),a=C.cssHooks[t]||C.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=fe(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(C.cssNumber[s]?"":"px")),m.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=Y(t);return et.test(t)||(t=Ke(s)),(a=C.cssHooks[t]||C.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Ve(e,t,r)),"normal"===i&&t in nt&&(i=nt[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),C.each(["height","width"],function(e,t){C.cssHooks[t]={get:function(e,n,r){if(n)return!Ze.test(C.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?ot(e,t,r):ce(e,tt,function(){return ot(e,t,r)})},set:function(e,n,r){var i,o=Ue(e),a=!m.scrollboxSize()&&"absolute"===o.position,s=(a||r)&&"border-box"===C.css(e,"boxSizing",!1,o),u=r?it(e,t,r,s,o):0;return s&&a&&(u-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-it(e,t,"border",!1,o)-.5)),u&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=C.css(e,t)),rt(0,n,u)}}}),C.cssHooks.marginLeft=Ge(m.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Ve(e,"marginLeft"))||e.getBoundingClientRect().left-ce(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),C.each({margin:"",padding:"",border:"Width"},function(e,t){C.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(C.cssHooks[e+t].set=rt)}),C.fn.extend({css:function(e,t){return U(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Ue(e),i=t.length;a1)}}),C.Tween=at,at.prototype={constructor:at,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||C.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(C.cssNumber[n]?"":"px")},cur:function(){var e=at.propHooks[this.prop];return e&&e.get?e.get(this):at.propHooks._default.get(this)},run:function(e){var t,n=at.propHooks[this.prop];return this.options.duration?this.pos=t=C.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):at.propHooks._default.set(this),this}},at.prototype.init.prototype=at.prototype,at.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=C.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){C.fx.step[e.prop]?C.fx.step[e.prop](e):1!==e.elem.nodeType||!C.cssHooks[e.prop]&&null==e.elem.style[Ke(e.prop)]?e.elem[e.prop]=e.now:C.style(e.elem,e.prop,e.now+e.unit)}}},at.propHooks.scrollTop=at.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},C.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},C.fx=at.prototype.init,C.fx.step={};var st,ut,lt=/^(?:toggle|show|hide)$/,ct=/queueHooks$/;function ft(){ut&&(!1===a.hidden&&n.requestAnimationFrame?n.requestAnimationFrame(ft):n.setTimeout(ft,C.fx.interval),C.fx.tick())}function pt(){return n.setTimeout(function(){st=void 0}),st=Date.now()}function dt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function ht(e,t,n){for(var r,i=(gt.tweeners[t]||[]).concat(gt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){C.removeAttr(this,e)})}}),C.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return void 0===e.getAttribute?C.prop(e,t,n):(1===o&&C.isXMLDoc(e)||(i=C.attrHooks[t.toLowerCase()]||(C.expr.match.bool.test(t)?vt:void 0)),void 0!==n?null===n?void C.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=C.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!m.radioValue&&"radio"===t&&D(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(I);if(i&&1===e.nodeType)for(;n=i[r++];)e.removeAttribute(n)}}),vt={set:function(e,t,n){return!1===t?C.removeAttr(e,n):e.setAttribute(n,n),n}},C.each(C.expr.match.bool.source.match(/\w+/g),function(e,t){var n=mt[t]||C.find.attr;mt[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=mt[a],mt[a]=i,i=null!=n(e,t,r)?a:null,mt[a]=o),i}});var yt=/^(?:input|select|textarea|button)$/i,xt=/^(?:a|area)$/i;function bt(e){return(e.match(I)||[]).join(" ")}function wt(e){return e.getAttribute&&e.getAttribute("class")||""}function Tt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(I)||[]}C.fn.extend({prop:function(e,t){return U(this,C.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[C.propFix[e]||e]})}}),C.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&C.isXMLDoc(e)||(t=C.propFix[t]||t,i=C.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=C.find.attr(e,"tabindex");return t?parseInt(t,10):yt.test(e.nodeName)||xt.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),m.optSelected||(C.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),C.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){C.propFix[this.toLowerCase()]=this}),C.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(y(e))return this.each(function(t){C(this).addClass(e.call(this,t,wt(this)))});if((t=Tt(e)).length)for(;n=this[u++];)if(i=wt(n),r=1===n.nodeType&&" "+bt(i)+" "){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=bt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(y(e))return this.each(function(t){C(this).removeClass(e.call(this,t,wt(this)))});if(!arguments.length)return this.attr("class","");if((t=Tt(e)).length)for(;n=this[u++];)if(i=wt(n),r=1===n.nodeType&&" "+bt(i)+" "){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");i!==(s=bt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):y(e)?this.each(function(n){C(this).toggleClass(e.call(this,n,wt(this),t),t)}):this.each(function(){var t,i,o,a;if(r)for(i=0,o=C(this),a=Tt(e);t=a[i++];)o.hasClass(t)?o.removeClass(t):o.addClass(t);else void 0!==e&&"boolean"!==n||((t=wt(this))&&K.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":K.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+bt(wt(n))+" ").indexOf(t)>-1)return!0;return!1}});var Ct=/\r/g;C.fn.extend({val:function(e){var t,n,r,i=this[0];return arguments.length?(r=y(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,C(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=C.map(i,function(e){return null==e?"":e+""})),(t=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))})):i?(t=C.valHooks[i.type]||C.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(Ct,""):null==n?"":n:void 0}}),C.extend({valHooks:{option:{get:function(e){var t=C.find.attr(e,"value");return null!=t?t:bt(C.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),C.each(["radio","checkbox"],function(){C.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=C.inArray(C(e).val(),t)>-1}},m.checkOn||(C.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),m.focusin="onfocusin"in n;var St=/^(?:focusinfocus|focusoutblur)$/,kt=function(e){e.stopPropagation()};C.extend(C.event,{trigger:function(e,t,r,i){var o,s,u,l,c,f,p,d,g=[r||a],v=h.call(e,"type")?e.type:e,m=h.call(e,"namespace")?e.namespace.split("."):[];if(s=d=u=r=r||a,3!==r.nodeType&&8!==r.nodeType&&!St.test(v+C.event.triggered)&&(v.indexOf(".")>-1&&(m=v.split("."),v=m.shift(),m.sort()),c=v.indexOf(":")<0&&"on"+v,(e=e[C.expando]?e:new C.Event(v,"object"==typeof e&&e)).isTrigger=i?2:3,e.namespace=m.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=r),t=null==t?[e]:C.makeArray(t,[e]),p=C.event.special[v]||{},i||!p.trigger||!1!==p.trigger.apply(r,t))){if(!i&&!p.noBubble&&!x(r)){for(l=p.delegateType||v,St.test(l+v)||(s=s.parentNode);s;s=s.parentNode)g.push(s),u=s;u===(r.ownerDocument||a)&&g.push(u.defaultView||u.parentWindow||n)}for(o=0;(s=g[o++])&&!e.isPropagationStopped();)d=s,e.type=o>1?l:p.bindType||v,(f=(K.get(s,"events")||{})[e.type]&&K.get(s,"handle"))&&f.apply(s,t),(f=c&&s[c])&&f.apply&&Q(s)&&(e.result=f.apply(s,t),!1===e.result&&e.preventDefault());return e.type=v,i||e.isDefaultPrevented()||p._default&&!1!==p._default.apply(g.pop(),t)||!Q(r)||c&&y(r[v])&&!x(r)&&((u=r[c])&&(r[c]=null),C.event.triggered=v,e.isPropagationStopped()&&d.addEventListener(v,kt),r[v](),e.isPropagationStopped()&&d.removeEventListener(v,kt),C.event.triggered=void 0,u&&(r[c]=u)),e.result}},simulate:function(e,t,n){var r=C.extend(new C.Event,n,{type:e,isSimulated:!0});C.event.trigger(r,null,t)}}),C.fn.extend({trigger:function(e,t){return this.each(function(){C.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return C.event.trigger(e,t,n,!0)}}),m.focusin||C.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){C.event.simulate(t,e.target,C.event.fix(e))};C.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=K.access(r,t);i||r.addEventListener(e,n,!0),K.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=K.access(r,t)-1;i?K.access(r,t,i):(r.removeEventListener(e,n,!0),K.remove(r,t))}}});var Et=n.location,At=Date.now(),Nt=/\?/;C.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new n.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||C.error("Invalid XML: "+e),t};var jt=/\[\]$/,Dt=/\r?\n/g,qt=/^(?:submit|button|image|reset|file)$/i,Lt=/^(?:input|select|textarea|keygen)/i;function Ht(e,t,n,r){var i;if(Array.isArray(t))C.each(t,function(t,i){n||jt.test(e)?r(e,i):Ht(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==T(t))r(e,t);else for(i in t)Ht(e+"["+i+"]",t[i],n,r)}C.param=function(e,t){var n,r=[],i=function(e,t){var n=y(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!C.isPlainObject(e))C.each(e,function(){i(this.name,this.value)});else for(n in e)Ht(n,e[n],t,i);return r.join("&")},C.fn.extend({serialize:function(){return C.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=C.prop(this,"elements");return e?C.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!C(this).is(":disabled")&&Lt.test(this.nodeName)&&!qt.test(e)&&(this.checked||!ge.test(e))}).map(function(e,t){var n=C(this).val();return null==n?null:Array.isArray(n)?C.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var Ot=/%20/g,Rt=/#.*$/,Pt=/([?&])_=[^&]*/,Mt=/^(.*?):[ \t]*([^\r\n]*)$/gm,It=/^(?:GET|HEAD)$/,Ft=/^\/\//,$t={},Wt={},Bt="*/".concat("*"),_t=a.createElement("a");function zt(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(I)||[];if(y(n))for(;r=o[i++];)"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function Ut(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,C.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function Xt(e,t){var n,r,i=C.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&C.extend(!0,e,r),e}_t.href=Et.href,C.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Bt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":C.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Xt(Xt(e,C.ajaxSettings),t):Xt(C.ajaxSettings,e)},ajaxPrefilter:zt($t),ajaxTransport:zt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var r,i,o,s,u,l,c,f,p,d,h=C.ajaxSetup({},t),g=h.context||h,v=h.context&&(g.nodeType||g.jquery)?C(g):C.event,m=C.Deferred(),y=C.Callbacks("once memory"),x=h.statusCode||{},b={},w={},T="canceled",S={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s)for(s={};t=Mt.exec(o);)s[t[1].toLowerCase()+" "]=(s[t[1].toLowerCase()+" "]||[]).concat(t[2]);t=s[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return c?o:null},setRequestHeader:function(e,t){return null==c&&(e=w[e.toLowerCase()]=w[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)S.always(e[S.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||T;return r&&r.abort(t),k(0,t),this}};if(m.promise(S),h.url=((e||h.url||Et.href)+"").replace(Ft,Et.protocol+"//"),h.type=t.method||t.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(I)||[""],null==h.crossDomain){l=a.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=_t.protocol+"//"+_t.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=C.param(h.data,h.traditional)),Ut($t,h,t,S),c)return S;for(p in(f=C.event&&h.global)&&0==C.active++&&C.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!It.test(h.type),i=h.url.replace(Rt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(Ot,"+")):(d=h.url.slice(i.length),h.data&&(h.processData||"string"==typeof h.data)&&(i+=(Nt.test(i)?"&":"?")+h.data,delete h.data),!1===h.cache&&(i=i.replace(Pt,"$1"),d=(Nt.test(i)?"&":"?")+"_="+At+++d),h.url=i+d),h.ifModified&&(C.lastModified[i]&&S.setRequestHeader("If-Modified-Since",C.lastModified[i]),C.etag[i]&&S.setRequestHeader("If-None-Match",C.etag[i])),(h.data&&h.hasContent&&!1!==h.contentType||t.contentType)&&S.setRequestHeader("Content-Type",h.contentType),S.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+Bt+"; q=0.01":""):h.accepts["*"]),h.headers)S.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,S,h)||c))return S.abort();if(T="abort",y.add(h.complete),S.done(h.success),S.fail(h.error),r=Ut(Wt,h,t,S)){if(S.readyState=1,f&&v.trigger("ajaxSend",[S,h]),c)return S;h.async&&h.timeout>0&&(u=n.setTimeout(function(){S.abort("timeout")},h.timeout));try{c=!1,r.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(e,t,a,s){var l,p,d,b,w,T=t;c||(c=!0,u&&n.clearTimeout(u),r=void 0,o=s||"",S.readyState=e>0?4:0,l=e>=200&&e<300||304===e,a&&(b=function(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;"*"===u[0];)u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(h,S,a)),b=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e.throws)t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(h,b,S,l),l?(h.ifModified&&((w=S.getResponseHeader("Last-Modified"))&&(C.lastModified[i]=w),(w=S.getResponseHeader("etag"))&&(C.etag[i]=w)),204===e||"HEAD"===h.type?T="nocontent":304===e?T="notmodified":(T=b.state,p=b.data,l=!(d=b.error))):(d=T,!e&&T||(T="error",e<0&&(e=0))),S.status=e,S.statusText=(t||T)+"",l?m.resolveWith(g,[p,T,S]):m.rejectWith(g,[S,T,d]),S.statusCode(x),x=void 0,f&&v.trigger(l?"ajaxSuccess":"ajaxError",[S,h,l?p:d]),y.fireWith(g,[S,T]),f&&(v.trigger("ajaxComplete",[S,h]),--C.active||C.event.trigger("ajaxStop")))}return S},getJSON:function(e,t,n){return C.get(e,t,n,"json")},getScript:function(e,t){return C.get(e,void 0,t,"script")}}),C.each(["get","post"],function(e,t){C[t]=function(e,n,r,i){return y(n)&&(i=i||r,r=n,n=void 0),C.ajax(C.extend({url:e,type:t,dataType:i,data:n,success:r},C.isPlainObject(e)&&e))}}),C._evalUrl=function(e,t){return C.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){C.globalEval(e,t)}})},C.fn.extend({wrapAll:function(e){var t;return this[0]&&(y(e)&&(e=e.call(this[0])),t=C(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return y(e)?this.each(function(t){C(this).wrapInner(e.call(this,t))}):this.each(function(){var t=C(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=y(e);return this.each(function(n){C(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){C(this).replaceWith(this.childNodes)}),this}}),C.expr.pseudos.hidden=function(e){return!C.expr.pseudos.visible(e)},C.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},C.ajaxSettings.xhr=function(){try{return new n.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=C.ajaxSettings.xhr();m.cors=!!Gt&&"withCredentials"in Gt,m.ajax=Gt=!!Gt,C.ajaxTransport(function(e){var t,r;if(m.cors||Gt&&!e.crossDomain)return{send:function(i,o){var a,s=e.xhr();if(s.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(a in e.xhrFields)s[a]=e.xhrFields[a];for(a in e.mimeType&&s.overrideMimeType&&s.overrideMimeType(e.mimeType),e.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest"),i)s.setRequestHeader(a,i[a]);t=function(e){return function(){t&&(t=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=t(),r=s.onerror=s.ontimeout=t("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&n.setTimeout(function(){t&&r()})},t=t("abort");try{s.send(e.hasContent&&e.data||null)}catch(e){if(t)throw e}},abort:function(){t&&t()}}}),C.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),C.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return C.globalEval(e),e}}}),C.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),C.ajaxTransport("script",function(e){var t,n;if(e.crossDomain||e.scriptAttrs)return{send:function(r,i){t=C(" -''' - -# specify that the above modules and all variables below are imported on 'from config.py import *' -__all__ = [x for x in dir() if x not in ['__file__','__all__', '__builtins__', '__doc__', '__name__', '__package__']] - +# Script: _project_setup.py +# Version: 2020-08-12 +# Author: Carl Higgs +# +# All scripts within the process folder draw on the sources, parameters and modules +# specified in the file _project_configuration.xlsx to source and output +# resources. +# +# If you are starting a new project, you can set up the global parameters which +# (pending overrides) should be applied for each study region in the +# detailed_explanation' folder. +# +# If you are adding a new study region to an existing project, this study region +# will be entered as a column within the 'Parameters' worksheet; the corresponding +# row entries must be completed as required. + +# import modules +import os +import sys +import time +import pandas +import numpy as np +import subprocess as sp +import math +import re + +# import custom utility functions +from _utils import * + +current_script = sys.argv[0] + +# Set up locale (ie. defined at command line, or else testing) +if len(sys.argv) >= 2: + locale = sys.argv[1] +else: + locale = 'adelaide' + # sys.exit('Please supply a locale argument (see region_settings tab in config file)') +if __name__ == '__main__': + print(f"\nProcessing script {current_script} for locale {locale}...\n") + +# cwd = os.path.join(os.getcwd(),'../process') +cwd = os.getcwd() +folder_path = os.path.abspath('../data') + +# Load settings from _project_configuration.xlsx +xls = pandas.ExcelFile(os.path.join(cwd,'_project_configuration.xlsx')) +df_global = pandas.read_excel(xls, 'project_settings',index_col=0) +df_local = pandas.read_excel(xls, 'region_settings',index_col=0) +# df_osm = pandas.read_excel(xls, 'osm_and_open_space_defs') +df_os = pandas.read_excel(xls, 'osm_open_space').set_index('variable') +df_osm_dest = pandas.read_excel(xls, 'osm_dest_definitions') +df_datasets = pandas.read_excel(xls, 'datasets') +df_destinations = pandas.read_excel(xls, 'destinations') + +# prepare and clean configuration entries +for var in [x for x in df_global.index.values]: + globals()[var] = df_global.loc[var]['parameters'] + +df_local[locale] = df_local[locale].fillna('') +for var in [x for x in df_local.index.values]: + globals()[var] = df_local.loc[var][locale] +# full_locale = df_parameters.loc['full_locale'][locale] +df_datasets.name_s = df_datasets.name_s.fillna('') +df_datasets = df_datasets.query(f' purpose == "{population_data}" | purpose == "{urban_data}"') +df_datasets.set_index('name_s',inplace=True) + +# derived study region name (no need to change!) +study_region = f'{locale}_{region}_{year}'.lower() +db = f'li_{locale}_{year}'.lower() + +print(f'\n{full_locale}\n') + +# define areas for global indicators project (not undertaken at multiple administrative scales; filling in some fixed parameters) +analysis_scale = 'city' +area = analysis_scale +area_ids = '' +area_display_bracket = '' + +# region specific output locations +locale_dir = os.path.join(folder_path,'study_region',study_region) +locale_maps = os.path.join('../../maps/',study_region) + +# Study region buffer +buffered_study_region = f'{study_region}_{study_buffer}{units}' + +# sample points +points = f'{points}_{point_sampling_interval}m' +urban_region = str(df_datasets.loc[urban_data,'data_dir']) +if urban_region not in ['','nan']: + urban_region = os.path.join('..',urban_region) + +try: + areas = {} + areas[area] = {} + # areas[area]['data'] = df_datasets[df_datasets.index== area_meta['area_datasets'][idx]].data_dir.values[0] + areas[area]['data'] = area_data + areas[area]['name'] = area.title() + areas[area]['table'] = re.sub('[^\s\w]+', '', areas[area]['name']).lower().strip().replace(' ','_') + areas[area]['display_main'] = areas[area]['name'] + licence = str(area_data_licence) + if licence not in ['none specified','nan','']: + licence_url = area_data_licence_url + licence_attrib = f' under {licence}' + else: + licence_attrib = '' + source_url = area_data_source_url + provider = area_data_source + areas[area]['attribution'] = f'Boundary data: {provider}{licence_attrib}' +except: + print('Please check area data in project configuration: not all required areas of interest parameters appear to have been defined...(error:{})'.format(sys.exc_info())) + +analysis_field = areas[area]['name'] + +# Derived hex settings +hex_grid = f'{study_region}_hex_{hex_diag}{units}_diag' +hex_grid_buffer = f'{study_region}_hex_{hex_diag}{units}_diag_{hex_buffer}{units}_buffer' +hex_side = float(hex_diag)*0.5 +hex_area_km2 = ((3*math.sqrt(3.0)/2)*(hex_side)**2)*10.0**-6 + +hex_grid_100m = f'{study_region}_hex_100{units}_diag' +hex_side_100 = float(100)*0.5 +hex_area_km2_100_diag = ((3*math.sqrt(3.0)/2)*(hex_side_100)**2)*10.0**-6 + +hex_grid_250m = f'{study_region}_hex_250{units}_diag' +hex_side_250 = float(250)*0.5 +hex_area_km2_250_diag = ((3*math.sqrt(3.0)/2)*(hex_side_250)**2)*10.0**-6 + +# Database names -- derived from above parameters; (no need to change!) +dbComment = f'Liveability indicator data for {locale} {year}.' + +# Environment settings for SQL +os.environ['PGHOST'] = db_host +os.environ['PGPORT'] = str(db_port) +os.environ['PGUSER'] = db_user +os.environ['PGPASSWORD'] = db_pwd +os.environ['PGDATABASE'] = db + +# OSM settings +osm_data = os.path.join(folder_path,osm_data) +osm_date = str(osm_date) +osm_prefix = f'osm_{osm_date}' +osm_region = f'{locale}_{osm_prefix}.osm' + +osm_source = os.path.join(folder_path,'study_region',locale,f'{buffered_study_region}_{osm_prefix}.osm') + +# define pedestrian network custom filter (based on OSMnx 'walk' network type, without the cycling exclusion) +pedestrian = ( + '["highway"]' + '["area"!~"yes"]' + '["highway"!~"motor|proposed|construction|abandoned|platform|raceway"]' + '["foot"!~"no"]' + '["service"!~"private"]' + '["access"!~"private"]' + ) + +grant_query = f'''GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO {db_user}; + GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO {db_user};''' + +# roads +# Define network data name structures +# road_data = df_parameters.loc['road_data'][locale] # the folder where road data is kept +network_folder = f'osm_{buffered_study_region}_epsg{srid}_pedestrian_{osm_prefix}' +network_source = os.path.join(locale_dir,network_folder) +intersections_table = f"clean_intersections_{intersection_tolerance}m" + +# Sausage buffer run parameters +# If you experience 'no forward edges' issues, change this value to 1 +# this means that for *subsequently processed* buffers, it will use +# an ST_SnapToGrid parameter of 0.01 instead of 0.001 +## The first pass should use 0.001, however. +snap_to_grid = 0.001 +if no_forward_edge_issues == 1: + snap_to_grid = 0.01 + +# Destinations data directory +# dest_dir = os.path.join(folder_path,dest_dir) +study_destinations = 'study_destinations' + +# array / list of destinations +# IMPORTANT -- These are specified in the 'destinations' worksheet of the _project_configuration.xlsx file +# - specify: destination, domain, cutoff and count distances as required +# +# -- If new destinations are added, they should be appended to end of list +# to ensure this order is respected across time. +# +# The table 'dest_type' will be created in Postgresql to keep track of destinations + +df_destinations = df_destinations.replace(np.nan, 'NULL', regex=True) +destination_list = [x for x in df_destinations.destination.tolist()] # the destinations + +df_osm_dest = df_osm_dest.replace(np.nan, 'NULL', regex=True) + +# Colours for presenting maps +colours = {} +# http://colorbrewer2.org/#type=qualitative&scheme=Dark2&n=8 +colours['qualitative'] = ['#1b9e77','#d95f02','#7570b3','#e7298a','#66a61e','#e6ab02','#a6761d','#666666'] +# http://colorbrewer2.org/#type=diverging&scheme=PuOr&n=8 +colours['diverging'] = ['#8c510a','#bf812d','#dfc27d','#f6e8c3','#c7eae5','#80cdc1','#35978f','#01665e'] + +map_style = ''' + + +''' + +# specify that the above modules and all variables below are imported on 'from config.py import *' +__all__ = [x for x in dir() if x not in ['__file__','__all__', '__builtins__', '__doc__', '__name__', '__package__']] + diff --git a/process/pre_process/_utils.py b/process/pre_process/_utils.py index 4e81ccee..ffcdb2f1 100644 --- a/process/pre_process/_utils.py +++ b/process/pre_process/_utils.py @@ -1,491 +1,491 @@ -""" - -Utility functions -~~~~~~~~~~~~~~~~~ - -:: - - Script: _utils.py - Purpose: These functions may be used in other scripts to undertake specific tasks. - Authors: Carl Higgs - Context: Liveability indicator calculation (general tools for data wrangling) - -Todo: - * further refactor and abstract code as functions for autodoc purposes - -""" - -import os - -# function for printing dictionaries in 'pretty' format to screen -def pretty(d, indent=0): - """Print dictionary data structure in 'pretty' format to screen - - Args: - d (dict): a python dictionary - """ - for key, value in d.items(): - depth = 0 - print('\t' * indent + str(key)+':'), - if isinstance(value, dict): - if depth == 0: - print(" ") - depth+=1 - pretty(value, indent+1) - else: - print(' ' + str(value)) - -def table_exists(name): - """Check if a database table already exists - - Args: - name (str): a table which may or may not exist - - Outputs: - ret (bool): a logical indication of existance (True or False) - """ - ret = engine.dialect.has_table(engine, name) - print('Table "{}" exists: {}'.format(name, ret)) - return ret - -# function for returning a pandas type given a string value representing that type -def valid_type(str_of_type): - """Function for returning a pandas type given a string value representing that type - - Args: - str_of_type (str): a python type in string form - - Outputs: - the Pandas term for that type - """ - if str_of_type in ['int','integer']: - return('Int64') - elif str_of_type in ['float','double precision']: - return('float64') - elif str_of_type in ['str','string','text','object']: - return('object') - else: - return('object') - -def style_dict_fcn(type = 'qualitative',colour=0): - """Return a set of colours for use in maps - - Rationale: - Make use of colourbrewer colour scheme readily accessible and swappable - - Args: - type (str): Either 'qualitative or 'diverging' for preset schemas - colour (int): index number of colour to return - - Outputs: - A png file in the specified output directory - - Todo: - * re-think the purpose of this -- perhaps could use an existing colorbrewer library? - * or just include the standard colorbrewer options (pgrn etc) - """ - # Colours for presenting maps - colours = {} - # http://colorbrewer2.org/#type=qualitative&scheme=Dark2&n=8 - colours['qualitative'] = ['#1b9e77','#d95f02','#7570b3','#e7298a','#66a61e','#e6ab02','#a6761d','#666666'] - # http://colorbrewer2.org/#type=diverging&scheme=PuOr&n=8 - colours['diverging'] = ['#8c510a','#bf812d','#dfc27d','#f6e8c3','#c7eae5','#80cdc1','#35978f','#01665e'] - - if type not in ['qualitative','diverging']: - print("Specified type unknown; assuming 'qualitative'.") - type = 'qualitative' - return { - 'fillOpacity': 0.5, - 'line_opacity': 0.2, - 'fillColor': colours[type][colour], - 'lineColor': colours[type][colour] - } - -def folium_to_image(input_dir='',output_dir='',map_name='',formats=['png'],width=1000,height=800,pause=3,strip_elements=["leaflet-control-zoom","leaflet-control-layers"]): - """This function converts an input html page to a png image - - Rationale: - Leaflet is useful for creating interactive maps; this function is used to - re-purpose these as static maps too. - - Args: - input_dir (str): the input directory for an html file - output_dir (str): the output directory for a png file - map_name (str): the file basename - formats (str): the desired output format - width (int): width in pixels (default = 1000) - height (int): height in pixels (default = 800) - pause (int): a delay time to allow the web page to fully load (e.g. online basemaps) - strip_elements (str array): A list of div tags to remove (e.g. interactive legend, zoom controls) - - Outputs: - A png file in the specified output directory - - Todo: - * input should be path not seperate dir and file; can get base path from the single file path - * modify this to also allow to pdf -- perhaps using pdfkit - * https://stackoverflow.com/questions/54390417/how-to-download-a-web-page-as-a-pdf-using-python - * I think in future should use puppeteer with headless chrome (or pyppeteer) - """ - import selenium.webdriver - import time - try: - if (input_dir=='' or map_name==''): - raise Exception(('This function requires specification of an input directory.\n' - 'Please specify the function in the following form:\n' - 'folium_to_png(input_dir,output_dir,map_name,[["format","format"]],[width],[height],[pause])' - )) - return - if output_dir=='': - output_dir = input_dir - options=selenium.webdriver.firefox.options.Options() - options.add_argument('--headless') - driver = selenium.webdriver.Firefox(options=options) - driver.set_window_size(width, height) # choose a resolution - driver.get('file:///{}/{}/{}.html'.format(os.getcwd(),input_dir,map_name)) - # You may need to add time.sleep(seconds) here - time.sleep(pause) - # Remove zoom controls from snapshot - for leaflet_class in strip_elements: - element = driver.find_element_by_class_name(leaflet_class) - driver.execute_script(""" - var element = arguments[0]; - element.parentNode.removeChild(element); - """, element) - if 'png' in formats: - driver.save_screenshot('{}/{}.png'.format(output_dir,map_name)) - # if 'pdf' in formats: - # import pdfkit - # with open("{}/__folium_temp.html".format(output_dir), "w") as f: - # f.write(driver.page_source) - # pdfkit.from_file("{}/__folium_temp.html".format(output_dir), - # '{}/{}.pdf'.format(output_dir,map_name)) - # os.remove("{}/__folium_temp.html".format(output_dir)) - driver.close() - except Exception as error: - print("Export of {} failed.".format('{}/{}.png: {}'.format(output_dir,map_name,error))) - -def define_geojson_coordinates(i,coords=['lat','long']): - """Updates json coordinates for display as geojson. - - This function takes a json feature collection feature which has been - set up as though it were a geojson (ie. with correct structure and - tags) and replaces the template null geometry tags with the actual - coordinates recorded for that feature. - - Rationale: - The `Air4Thai`_ data can be saved as json. - This records measurements for various pollutants at stations across - Thailand, as well as metadata for each station including its coordi- - nates in latitude and longitude. - - However some manipulation is required to reformat this json data for - correct display as a geojson, retaining all the included attributes. - - Example input: - - :: - - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - 0, - 0 - ] - }, - "properties": { - ... - "lat": "13.666183", - "long": "100.605742", - ... - } - } - - Example output: - - :: - - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - 100.605742, - 13.666183 - ] - }, - "properties": { - ... - "lat": "13.666183", - "long": "100.605742", - ... - } - } - - Args: - i (geojson feature): This is a geojson feature, containing incorrect - coords (2-tuple of strings): a 2-item list of - string names for the latitude and longitude coordinates - - Returns: - geojson feature: Geojson feature with coordinates replaced as per the specified - coordinates in the input feature's properties record. - - .. _Air4Thai: - http://air4thai.pcd.go.th - - """ - i['geometry']['coordinates'][0] = float(i['properties'][coords[1]]) - i['geometry']['coordinates'][1] = float(i['properties'][coords[0]]) - return i - -def unnest_json_property(i,nested_property): - """This function takes each item of the nested list and returns as a - property in its own right, prefixed by an underscore '_' to mitigate - risk of name clash. For any nested items, the nested list name is - taken as a prefix and append to any child items. - - Rationale: - The `Air4Thai`_ data can be saved as json. - This records measurements for various pollutants at stations across - Thailand. However, this is recorded as a nested list, which without - further processing (un-nesting) cannot be mapped or analysed directly. - - Args: - i (geojson feature): This is a geojson feature, containing incorrect - nested_property (string): a string identifying a nested property - - Returns: - geojson feature: Geojson feature with its nested property un-nested. - - .. _Air4Thai: - http://air4thai.pcd.go.th - """ - for x in i['properties'][nested_property]: - if type(i['properties'][nested_property][x]) is not dict: - i['properties']['_{}'.format(x)] = i['properties'][nested_property][x] - else: - for n in i['properties'][nested_property][x]: - i['properties']['_{}_{}'.format(x,n)] = i['properties'][nested_property][x][n] - return i - -def recast_json_properties(i,na=[]): - """This function iterates over properties and recasts to integer or float - values as appropriate. Any "N/A" values are replaced as numpy nan values. - - Rationale: - The `Air4Thai`_ data can be saved as json. - This records measurements for various pollutants at stations across - Thailand. However, numeric values are presented as strings, and - have hard-coded text "N/A" values for not applicable data. - - Args: - i (json feature): This is a json feature - na (string array): a list of strings representing values which should be - interpreted as nan - - Returns: - geojson feature: Geojson feature with recast properties - - .. _Air4Thai: - http://air4thai.pcd.go.th - """ - import numpy as np - for p in i['properties']: - # print(i['properties'][p]) - if type(i['properties'][p]) is not dict: - # if appears to be integer, cast to int - if '{}'.format(i['properties'][p]).isdigit(): - i['properties'][p] = int(i['properties'][p]) - # if appears to be float, cast as float - elif '{}'.format(i['properties'][p]).replace('.','',1).isdigit(): - i['properties'][p] = float(i['properties'][p]) - # if appears to be na, cast as np.nan - elif '{}'.format(i['properties'][p]) in na: - i['properties'][p] = np.nan - # otherwise, let it be - probably a string - - return i - -def add_json_datetime_property(i,date='_date',time='_time',format= '{d}T{t}:00',datetime_field='time'): - """Format datetime field based on given date, time, and format. - - Rationale: - Some applications require a joint date-time variable in a specific format. - Given an input json feature with properties and the names of fields - representing 'date' and 'time', a 'datetime' field is returned. - - Args: - i (geojson feature): This is a geojson feature, containing incorrect - date (string): Property name of date string - time (string): Property name of time string - format (string): A parameterised format for combining these two fields - datetime_field : A new field to contain the formatted datetime variable - - Returns: - geojson feature: Geojson feature with date time variable - """ - t = i['properties']['_time'] - d = i['properties']['_date'] - i['properties'][datetime_field] = format.format(d=d,t=t) - return i - -def reproject_raster(inpath, outpath, new_crs): - import rasterio - from rasterio.warp import calculate_default_transform, reproject, Resampling - dst_crs = new_crs # CRS for web meractor - with rasterio.open(inpath) as src: - transform, width, height = calculate_default_transform( - src.crs, dst_crs, src.width, src.height, *src.bounds) - kwargs = src.meta.copy() - kwargs.update({ - 'crs': dst_crs, - 'transform': transform, - 'width': width, - 'height': height - }) - with rasterio.open(outpath, 'w', **kwargs) as dst: - for i in range(1, src.count + 1): - reproject( - source=rasterio.band(src, i), - destination=rasterio.band(dst, i), - src_transform=src.transform, - src_crs=src.crs, - dst_transform=transform, - dst_crs=dst_crs, - resampling=Resampling.nearest) - - -hex_function = ''' - -------------------------------------------------------------------------------------------------------------------------------- - -- HEX GRID - Create function - -------------------------------------------------------------------------------------------------------------------------------- - -- - -- Hugh Saalmans (@minus34) - -- 2015/04/10 - -- - -- DESCRIPTION: - -- - -- Function returns a grid of mathmatically correct hexagonal polygons. - -- Useful for hexbinning (the art of mapping clusters of information unbiased by political/historical/statistical boundaries). - -- - -- INPUT - -- - -- areakm2 : area of each hexagon in square km. - -- - note: hexagon size can be off slightly due to coordinate rounding in the calcs. - -- - -- xmin, ymin : min coords of the grid extents. - -- - -- xmax, ymax : max coords of the grid extents. - -- - -- inputsrid : the coordinate system (SRID) of the input min/max coords. - -- - -- workingsrid : the SRID used to process the polygons. - -- - SRID must be a projected coord sys (i.e. in metres) as the calcs require ints. Degrees are out. - -- - should be an equal area SRID such as Albers or Lambert Azimuthal (e.g. Australia = 3577, US = 2163). - -- - using Mercator will NOT return hexagons of equal area due to its distortions (don't try it in Greenland). - -- - -- ouputsrid : the SRID of the output polygons. - -- - -- NOTES - -- - -- Hexagon height & width are rounded up & down to the nearest metre, hence the area may be off slightly. - -- This is due to the Postgres generate_series function which doesn't support floats. - -- - -- Why are my areas wrong in QGIS, MapInfo, etc...? - -- Let's assume you created WGS84 lat/long hexagons, you may have noticed the areas differ by almost half in a desktop GIS - -- like QGIS or MapInfo Pro. This is due to the way those tools display geographic coordinate systems like WGS84 lat/long. - -- Running the following query in PostGIS will confirm the min & max sizes of your hexagons (in km2): - -- - -- SELECT (SELECT (MIN(ST_Area(geom::geography, FALSE)) / 1000000.0)::numeric(10,3) From my_hex_grid) AS minarea, - -- (SELECT (MAX(ST_Area(geom::geography, FALSE)) / 1000000.0)::numeric(10,3) From my_hex_grid) AS maxarea; - -- - -- Hey, why doesn't the grid cover the area I defined using my min/max extents? - -- Assuming you used lat/long extents and processed the grid with an equal area projection, the projection caused your - -- min/max coords to describe a conical shape, not a rectangular one - and the conical area didn't cover everything you - -- wanted to include. See au-hex-grid.png as an example of this. - -- If you're bored - learn why projections distort maps here: http://www.icsm.gov.au/mapping/about_projections.html - -- - -- This code is based on this PostGIS Wiki article: https://trac.osgeo.org/postgis/wiki/UsersWikiGenerateHexagonalGrid - -- - -- Dimension calcs are based on formulae from: http://hexnet.org/content/hexagonal-geometry - -- - -- LICENSE - -- - -- This work is licensed under the Apache License, Version 2: https://www.apache.org/licenses/LICENSE-2.0 - -- - -------------------------------------------------------------------------------------------------------------------------------- - - --DROP FUNCTION IF EXISTS hex_grid(areakm2 FLOAT, xmin FLOAT, ymin FLOAT, xmax FLOAT, ymax FLOAT, inputsrid INTEGER, - -- workingsrid INTEGER, ouputsrid INTEGER); - CREATE OR REPLACE FUNCTION hex_grid(areakm2 FLOAT, xmin FLOAT, ymin FLOAT, xmax FLOAT, ymax FLOAT, inputsrid INTEGER, - workingsrid INTEGER, ouputsrid INTEGER) - RETURNS SETOF geometry AS - $BODY$ - - DECLARE - minpnt GEOMETRY; - maxpnt GEOMETRY; - x1 INTEGER; - y1 INTEGER; - x2 INTEGER; - y2 INTEGER; - aream2 FLOAT; - qtrwidthfloat FLOAT; - qtrwidth INTEGER; - halfheight INTEGER; - - BEGIN - - -- Convert input coords to points in the working SRID - minpnt = ST_Transform(ST_SetSRID(ST_MakePoint(xmin, ymin), inputsrid), workingsrid); - maxpnt = ST_Transform(ST_SetSRID(ST_MakePoint(xmax, ymax), inputsrid), workingsrid); - - -- Get grid extents in working SRID coords - x1 = ST_X(minpnt)::INTEGER; - y1 = ST_Y(minpnt)::INTEGER; - x2 = ST_X(maxpnt)::INTEGER; - y2 = ST_Y(maxpnt)::INTEGER; - - -- Get height and width of hexagon - FLOOR and CEILING are used to get the hexagon size closer to the requested input area - aream2 := areakm2 * 1000000.0; - qtrwidthfloat := sqrt(aream2/(sqrt(3.0) * (3.0/2.0))) / 2.0; - - qtrwidth := FLOOR(qtrwidthfloat); - halfheight := CEILING(qtrwidthfloat * sqrt(3.0)); - - -- Return the hexagons - done in pairs, with one offset from the other - RETURN QUERY ( - SELECT ST_Transform(ST_SetSRID(ST_Translate(geom, x_series::FLOAT, y_series::FLOAT), workingsrid), ouputsrid) AS geom - FROM generate_series(x1, x2, (qtrwidth * 6)) AS x_series, - generate_series(y1, y2, (halfheight * 2)) AS y_series, - ( - SELECT ST_GeomFromText( - format('POLYGON((0 0, %s %s, %s %s, %s %s, %s %s, %s %s, 0 0))', - qtrwidth, halfheight, - qtrwidth * 3, halfheight, - qtrwidth * 4, 0, - qtrwidth * 3, halfheight * -1, - qtrwidth, halfheight * -1 - ) - ) AS geom - UNION - SELECT ST_Translate( - ST_GeomFromText( - format('POLYGON((0 0, %s %s, %s %s, %s %s, %s %s, %s %s, 0 0))', - qtrwidth, halfheight, - qtrwidth * 3, halfheight, - qtrwidth * 4, 0, - qtrwidth * 3, halfheight * -1, - qtrwidth, halfheight * -1 - ) - ) - , qtrwidth * 3, halfheight) as geom - ) AS two_hex); - - END$BODY$ - LANGUAGE plpgsql VOLATILE - COST 100; +""" + +Utility functions +~~~~~~~~~~~~~~~~~ + +:: + + Script: _utils.py + Purpose: These functions may be used in other scripts to undertake specific tasks. + Authors: Carl Higgs + Context: Liveability indicator calculation (general tools for data wrangling) + +Todo: + * further refactor and abstract code as functions for autodoc purposes + +""" + +import os + +# function for printing dictionaries in 'pretty' format to screen +def pretty(d, indent=0): + """Print dictionary data structure in 'pretty' format to screen + + Args: + d (dict): a python dictionary + """ + for key, value in d.items(): + depth = 0 + print('\t' * indent + str(key)+':'), + if isinstance(value, dict): + if depth == 0: + print(" ") + depth+=1 + pretty(value, indent+1) + else: + print(' ' + str(value)) + +def table_exists(name): + """Check if a database table already exists + + Args: + name (str): a table which may or may not exist + + Outputs: + ret (bool): a logical indication of existance (True or False) + """ + ret = engine.dialect.has_table(engine, name) + print('Table "{}" exists: {}'.format(name, ret)) + return ret + +# function for returning a pandas type given a string value representing that type +def valid_type(str_of_type): + """Function for returning a pandas type given a string value representing that type + + Args: + str_of_type (str): a python type in string form + + Outputs: + the Pandas term for that type + """ + if str_of_type in ['int','integer']: + return('Int64') + elif str_of_type in ['float','double precision']: + return('float64') + elif str_of_type in ['str','string','text','object']: + return('object') + else: + return('object') + +def style_dict_fcn(type = 'qualitative',colour=0): + """Return a set of colours for use in maps + + Rationale: + Make use of colourbrewer colour scheme readily accessible and swappable + + Args: + type (str): Either 'qualitative or 'diverging' for preset schemas + colour (int): index number of colour to return + + Outputs: + A png file in the specified output directory + + Todo: + * re-think the purpose of this -- perhaps could use an existing colorbrewer library? + * or just include the standard colorbrewer options (pgrn etc) + """ + # Colours for presenting maps + colours = {} + # http://colorbrewer2.org/#type=qualitative&scheme=Dark2&n=8 + colours['qualitative'] = ['#1b9e77','#d95f02','#7570b3','#e7298a','#66a61e','#e6ab02','#a6761d','#666666'] + # http://colorbrewer2.org/#type=diverging&scheme=PuOr&n=8 + colours['diverging'] = ['#8c510a','#bf812d','#dfc27d','#f6e8c3','#c7eae5','#80cdc1','#35978f','#01665e'] + + if type not in ['qualitative','diverging']: + print("Specified type unknown; assuming 'qualitative'.") + type = 'qualitative' + return { + 'fillOpacity': 0.5, + 'line_opacity': 0.2, + 'fillColor': colours[type][colour], + 'lineColor': colours[type][colour] + } + +def folium_to_image(input_dir='',output_dir='',map_name='',formats=['png'],width=1000,height=800,pause=3,strip_elements=["leaflet-control-zoom","leaflet-control-layers"]): + """This function converts an input html page to a png image + + Rationale: + Leaflet is useful for creating interactive maps; this function is used to + re-purpose these as static maps too. + + Args: + input_dir (str): the input directory for an html file + output_dir (str): the output directory for a png file + map_name (str): the file basename + formats (str): the desired output format + width (int): width in pixels (default = 1000) + height (int): height in pixels (default = 800) + pause (int): a delay time to allow the web page to fully load (e.g. online basemaps) + strip_elements (str array): A list of div tags to remove (e.g. interactive legend, zoom controls) + + Outputs: + A png file in the specified output directory + + Todo: + * input should be path not seperate dir and file; can get base path from the single file path + * modify this to also allow to pdf -- perhaps using pdfkit + * https://stackoverflow.com/questions/54390417/how-to-download-a-web-page-as-a-pdf-using-python + * I think in future should use puppeteer with headless chrome (or pyppeteer) + """ + import selenium.webdriver + import time + try: + if (input_dir=='' or map_name==''): + raise Exception(('This function requires specification of an input directory.\n' + 'Please specify the function in the following form:\n' + 'folium_to_png(input_dir,output_dir,map_name,[["format","format"]],[width],[height],[pause])' + )) + return + if output_dir=='': + output_dir = input_dir + options=selenium.webdriver.firefox.options.Options() + options.add_argument('--headless') + driver = selenium.webdriver.Firefox(options=options) + driver.set_window_size(width, height) # choose a resolution + driver.get('file:///{}/{}/{}.html'.format(os.getcwd(),input_dir,map_name)) + # You may need to add time.sleep(seconds) here + time.sleep(pause) + # Remove zoom controls from snapshot + for leaflet_class in strip_elements: + element = driver.find_element_by_class_name(leaflet_class) + driver.execute_script(""" + var element = arguments[0]; + element.parentNode.removeChild(element); + """, element) + if 'png' in formats: + driver.save_screenshot('{}/{}.png'.format(output_dir,map_name)) + # if 'pdf' in formats: + # import pdfkit + # with open("{}/__folium_temp.html".format(output_dir), "w") as f: + # f.write(driver.page_source) + # pdfkit.from_file("{}/__folium_temp.html".format(output_dir), + # '{}/{}.pdf'.format(output_dir,map_name)) + # os.remove("{}/__folium_temp.html".format(output_dir)) + driver.close() + except Exception as error: + print("Export of {} failed.".format('{}/{}.png: {}'.format(output_dir,map_name,error))) + +def define_geojson_coordinates(i,coords=['lat','long']): + """Updates json coordinates for display as geojson. + + This function takes a json feature collection feature which has been + set up as though it were a geojson (ie. with correct structure and + tags) and replaces the template null geometry tags with the actual + coordinates recorded for that feature. + + Rationale: + The `Air4Thai`_ data can be saved as json. + This records measurements for various pollutants at stations across + Thailand, as well as metadata for each station including its coordi- + nates in latitude and longitude. + + However some manipulation is required to reformat this json data for + correct display as a geojson, retaining all the included attributes. + + Example input: + + :: + + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 0, + 0 + ] + }, + "properties": { + ... + "lat": "13.666183", + "long": "100.605742", + ... + } + } + + Example output: + + :: + + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 100.605742, + 13.666183 + ] + }, + "properties": { + ... + "lat": "13.666183", + "long": "100.605742", + ... + } + } + + Args: + i (geojson feature): This is a geojson feature, containing incorrect + coords (2-tuple of strings): a 2-item list of + string names for the latitude and longitude coordinates + + Returns: + geojson feature: Geojson feature with coordinates replaced as per the specified + coordinates in the input feature's properties record. + + .. _Air4Thai: + http://air4thai.pcd.go.th + + """ + i['geometry']['coordinates'][0] = float(i['properties'][coords[1]]) + i['geometry']['coordinates'][1] = float(i['properties'][coords[0]]) + return i + +def unnest_json_property(i,nested_property): + """This function takes each item of the nested list and returns as a + property in its own right, prefixed by an underscore '_' to mitigate + risk of name clash. For any nested items, the nested list name is + taken as a prefix and append to any child items. + + Rationale: + The `Air4Thai`_ data can be saved as json. + This records measurements for various pollutants at stations across + Thailand. However, this is recorded as a nested list, which without + further processing (un-nesting) cannot be mapped or analysed directly. + + Args: + i (geojson feature): This is a geojson feature, containing incorrect + nested_property (string): a string identifying a nested property + + Returns: + geojson feature: Geojson feature with its nested property un-nested. + + .. _Air4Thai: + http://air4thai.pcd.go.th + """ + for x in i['properties'][nested_property]: + if type(i['properties'][nested_property][x]) is not dict: + i['properties']['_{}'.format(x)] = i['properties'][nested_property][x] + else: + for n in i['properties'][nested_property][x]: + i['properties']['_{}_{}'.format(x,n)] = i['properties'][nested_property][x][n] + return i + +def recast_json_properties(i,na=[]): + """This function iterates over properties and recasts to integer or float + values as appropriate. Any "N/A" values are replaced as numpy nan values. + + Rationale: + The `Air4Thai`_ data can be saved as json. + This records measurements for various pollutants at stations across + Thailand. However, numeric values are presented as strings, and + have hard-coded text "N/A" values for not applicable data. + + Args: + i (json feature): This is a json feature + na (string array): a list of strings representing values which should be + interpreted as nan + + Returns: + geojson feature: Geojson feature with recast properties + + .. _Air4Thai: + http://air4thai.pcd.go.th + """ + import numpy as np + for p in i['properties']: + # print(i['properties'][p]) + if type(i['properties'][p]) is not dict: + # if appears to be integer, cast to int + if '{}'.format(i['properties'][p]).isdigit(): + i['properties'][p] = int(i['properties'][p]) + # if appears to be float, cast as float + elif '{}'.format(i['properties'][p]).replace('.','',1).isdigit(): + i['properties'][p] = float(i['properties'][p]) + # if appears to be na, cast as np.nan + elif '{}'.format(i['properties'][p]) in na: + i['properties'][p] = np.nan + # otherwise, let it be - probably a string + + return i + +def add_json_datetime_property(i,date='_date',time='_time',format= '{d}T{t}:00',datetime_field='time'): + """Format datetime field based on given date, time, and format. + + Rationale: + Some applications require a joint date-time variable in a specific format. + Given an input json feature with properties and the names of fields + representing 'date' and 'time', a 'datetime' field is returned. + + Args: + i (geojson feature): This is a geojson feature, containing incorrect + date (string): Property name of date string + time (string): Property name of time string + format (string): A parameterised format for combining these two fields + datetime_field : A new field to contain the formatted datetime variable + + Returns: + geojson feature: Geojson feature with date time variable + """ + t = i['properties']['_time'] + d = i['properties']['_date'] + i['properties'][datetime_field] = format.format(d=d,t=t) + return i + +def reproject_raster(inpath, outpath, new_crs): + import rasterio + from rasterio.warp import calculate_default_transform, reproject, Resampling + dst_crs = new_crs # CRS for web meractor + with rasterio.open(inpath) as src: + transform, width, height = calculate_default_transform( + src.crs, dst_crs, src.width, src.height, *src.bounds) + kwargs = src.meta.copy() + kwargs.update({ + 'crs': dst_crs, + 'transform': transform, + 'width': width, + 'height': height + }) + with rasterio.open(outpath, 'w', **kwargs) as dst: + for i in range(1, src.count + 1): + reproject( + source=rasterio.band(src, i), + destination=rasterio.band(dst, i), + src_transform=src.transform, + src_crs=src.crs, + dst_transform=transform, + dst_crs=dst_crs, + resampling=Resampling.nearest) + + +hex_function = ''' + -------------------------------------------------------------------------------------------------------------------------------- + -- HEX GRID - Create function + -------------------------------------------------------------------------------------------------------------------------------- + -- + -- Hugh Saalmans (@minus34) + -- 2015/04/10 + -- + -- DESCRIPTION: + -- + -- Function returns a grid of mathmatically correct hexagonal polygons. + -- Useful for hexbinning (the art of mapping clusters of information unbiased by political/historical/statistical boundaries). + -- + -- INPUT + -- + -- areakm2 : area of each hexagon in square km. + -- - note: hexagon size can be off slightly due to coordinate rounding in the calcs. + -- + -- xmin, ymin : min coords of the grid extents. + -- + -- xmax, ymax : max coords of the grid extents. + -- + -- inputsrid : the coordinate system (SRID) of the input min/max coords. + -- + -- workingsrid : the SRID used to process the polygons. + -- - SRID must be a projected coord sys (i.e. in metres) as the calcs require ints. Degrees are out. + -- - should be an equal area SRID such as Albers or Lambert Azimuthal (e.g. Australia = 3577, US = 2163). + -- - using Mercator will NOT return hexagons of equal area due to its distortions (don't try it in Greenland). + -- + -- ouputsrid : the SRID of the output polygons. + -- + -- NOTES + -- + -- Hexagon height & width are rounded up & down to the nearest metre, hence the area may be off slightly. + -- This is due to the Postgres generate_series function which doesn't support floats. + -- + -- Why are my areas wrong in QGIS, MapInfo, etc...? + -- Let's assume you created WGS84 lat/long hexagons, you may have noticed the areas differ by almost half in a desktop GIS + -- like QGIS or MapInfo Pro. This is due to the way those tools display geographic coordinate systems like WGS84 lat/long. + -- Running the following query in PostGIS will confirm the min & max sizes of your hexagons (in km2): + -- + -- SELECT (SELECT (MIN(ST_Area(geom::geography, FALSE)) / 1000000.0)::numeric(10,3) From my_hex_grid) AS minarea, + -- (SELECT (MAX(ST_Area(geom::geography, FALSE)) / 1000000.0)::numeric(10,3) From my_hex_grid) AS maxarea; + -- + -- Hey, why doesn't the grid cover the area I defined using my min/max extents? + -- Assuming you used lat/long extents and processed the grid with an equal area projection, the projection caused your + -- min/max coords to describe a conical shape, not a rectangular one - and the conical area didn't cover everything you + -- wanted to include. See au-hex-grid.png as an example of this. + -- If you're bored - learn why projections distort maps here: http://www.icsm.gov.au/mapping/about_projections.html + -- + -- This code is based on this PostGIS Wiki article: https://trac.osgeo.org/postgis/wiki/UsersWikiGenerateHexagonalGrid + -- + -- Dimension calcs are based on formulae from: http://hexnet.org/content/hexagonal-geometry + -- + -- LICENSE + -- + -- This work is licensed under the Apache License, Version 2: https://www.apache.org/licenses/LICENSE-2.0 + -- + -------------------------------------------------------------------------------------------------------------------------------- + + --DROP FUNCTION IF EXISTS hex_grid(areakm2 FLOAT, xmin FLOAT, ymin FLOAT, xmax FLOAT, ymax FLOAT, inputsrid INTEGER, + -- workingsrid INTEGER, ouputsrid INTEGER); + CREATE OR REPLACE FUNCTION hex_grid(areakm2 FLOAT, xmin FLOAT, ymin FLOAT, xmax FLOAT, ymax FLOAT, inputsrid INTEGER, + workingsrid INTEGER, ouputsrid INTEGER) + RETURNS SETOF geometry AS + $BODY$ + + DECLARE + minpnt GEOMETRY; + maxpnt GEOMETRY; + x1 INTEGER; + y1 INTEGER; + x2 INTEGER; + y2 INTEGER; + aream2 FLOAT; + qtrwidthfloat FLOAT; + qtrwidth INTEGER; + halfheight INTEGER; + + BEGIN + + -- Convert input coords to points in the working SRID + minpnt = ST_Transform(ST_SetSRID(ST_MakePoint(xmin, ymin), inputsrid), workingsrid); + maxpnt = ST_Transform(ST_SetSRID(ST_MakePoint(xmax, ymax), inputsrid), workingsrid); + + -- Get grid extents in working SRID coords + x1 = ST_X(minpnt)::INTEGER; + y1 = ST_Y(minpnt)::INTEGER; + x2 = ST_X(maxpnt)::INTEGER; + y2 = ST_Y(maxpnt)::INTEGER; + + -- Get height and width of hexagon - FLOOR and CEILING are used to get the hexagon size closer to the requested input area + aream2 := areakm2 * 1000000.0; + qtrwidthfloat := sqrt(aream2/(sqrt(3.0) * (3.0/2.0))) / 2.0; + + qtrwidth := FLOOR(qtrwidthfloat); + halfheight := CEILING(qtrwidthfloat * sqrt(3.0)); + + -- Return the hexagons - done in pairs, with one offset from the other + RETURN QUERY ( + SELECT ST_Transform(ST_SetSRID(ST_Translate(geom, x_series::FLOAT, y_series::FLOAT), workingsrid), ouputsrid) AS geom + FROM generate_series(x1, x2, (qtrwidth * 6)) AS x_series, + generate_series(y1, y2, (halfheight * 2)) AS y_series, + ( + SELECT ST_GeomFromText( + format('POLYGON((0 0, %s %s, %s %s, %s %s, %s %s, %s %s, 0 0))', + qtrwidth, halfheight, + qtrwidth * 3, halfheight, + qtrwidth * 4, 0, + qtrwidth * 3, halfheight * -1, + qtrwidth, halfheight * -1 + ) + ) AS geom + UNION + SELECT ST_Translate( + ST_GeomFromText( + format('POLYGON((0 0, %s %s, %s %s, %s %s, %s %s, %s %s, 0 0))', + qtrwidth, halfheight, + qtrwidth * 3, halfheight, + qtrwidth * 4, 0, + qtrwidth * 3, halfheight * -1, + qtrwidth, halfheight * -1 + ) + ) + , qtrwidth * 3, halfheight) as geom + ) AS two_hex); + + END$BODY$ + LANGUAGE plpgsql VOLATILE + COST 100; ''' \ No newline at end of file diff --git a/process/pre_process/bulk_gdal_merge.py b/process/pre_process/bulk_gdal_merge.py index ebaa66bd..8601286b 100644 --- a/process/pre_process/bulk_gdal_merge.py +++ b/process/pre_process/bulk_gdal_merge.py @@ -1,49 +1,49 @@ -import os -import sys -import datetime -import argparse -import subprocess as sp - -cwd = os.path.dirname(sys.argv[0]) -print(cwd) - -def valid_path(arg): - if not os.path.exists(arg): - msg = "The path %s does not exist!" % arg - raise argparse.ArgumentTypeError(msg) - else: - return arg - -# Parse input arguments -parser = argparse.ArgumentParser(description='Generate origin destination matrix') -parser.add_argument('-dir', - help='parent directory', - default=cwd, - type=valid_path) -parser.add_argument('-outfile', - help='outfile name', - default='gdal_merged.tif', - type=str) -parser.add_argument('-gdal_loc', - help='location of the gdal_merge.py script', - default='C:/OSGeo4W64/bin/gdal_merge.py', - type=str) -args = parser.parse_args() - -# initialise tif list file -tif_list_name = 'tif_list_{date:%Y-%m-%d}.txt'.format( date=datetime.datetime.now() ) -tif_list_path = os.path.join(args.dir,tif_list_name) -tif_list = open(tif_list_path, "w") - -# iterate of files within root or otherwise specified directory, noting all tifs -count = 0 -for root, dirs, files in os.walk(args.dir): - for file in files: - if file.endswith(".tif"): - tif_list.write('{}\n'.format(os.path.join(root, file))) - count += 1 -tif_list.close() -print('Compiled a list of {} tifs.'.format(count)) -# merge tifs -command = 'python {gm} -v -o {outfile} --optfile {tif_list}'.format(gm = args.gdal_loc, outfile = args.outfile, tif_list =tif_list_name) -sp.call(command, shell=True, cwd=cwd) +import os +import sys +import datetime +import argparse +import subprocess as sp + +cwd = os.path.dirname(sys.argv[0]) +print(cwd) + +def valid_path(arg): + if not os.path.exists(arg): + msg = "The path %s does not exist!" % arg + raise argparse.ArgumentTypeError(msg) + else: + return arg + +# Parse input arguments +parser = argparse.ArgumentParser(description='Generate origin destination matrix') +parser.add_argument('-dir', + help='parent directory', + default=cwd, + type=valid_path) +parser.add_argument('-outfile', + help='outfile name', + default='gdal_merged.tif', + type=str) +parser.add_argument('-gdal_loc', + help='location of the gdal_merge.py script', + default='C:/OSGeo4W64/bin/gdal_merge.py', + type=str) +args = parser.parse_args() + +# initialise tif list file +tif_list_name = 'tif_list_{date:%Y-%m-%d}.txt'.format( date=datetime.datetime.now() ) +tif_list_path = os.path.join(args.dir,tif_list_name) +tif_list = open(tif_list_path, "w") + +# iterate of files within root or otherwise specified directory, noting all tifs +count = 0 +for root, dirs, files in os.walk(args.dir): + for file in files: + if file.endswith(".tif"): + tif_list.write('{}\n'.format(os.path.join(root, file))) + count += 1 +tif_list.close() +print('Compiled a list of {} tifs.'.format(count)) +# merge tifs +command = 'python {gm} -v -o {outfile} --optfile {tif_list}'.format(gm = args.gdal_loc, outfile = args.outfile, tif_list =tif_list_name) +sp.call(command, shell=True, cwd=cwd) diff --git a/process/pre_process/grant_query.py b/process/pre_process/grant_query.py index 8e7accee..2fc4ddbd 100644 --- a/process/pre_process/grant_query.py +++ b/process/pre_process/grant_query.py @@ -1,42 +1,42 @@ -# Script: grant_query.py -# Purpose: -- If no argument is given, this script prints out a grant query -# which may be run manually ( -# ie. to allow python and arc_sde users to modify tables created by -# the admin user. -# -- If a study region is specified, admin connection details are -# requested and an admin connection is made to that database -# in order to execute the query -# Author: Carl Higgs -# Date: 20190208 - -# Import custom variables for National Liveability indicator process -import sys - -grant_query = ''' -GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO arc_sde; -GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO arc_sde; -GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO python; -GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO python; -''' -if len(sys.argv) < 2: - print(grant_query) -else: - import psycopg2 - import time - import getpass - import os - print("Please enter PostgreSQL admin details to grant all privileges to python and arc_sde users") - admin_db = raw_input("Database: ") - admin_user_name = raw_input("Username: ") - admin_pwd = getpass.getpass("Password for user {} on database {}: ".format(admin_user_name, admin_db)) - print("Executing grant query and ensuring tablefunc extension is created...") - for region in sys.argv[1:]: - print(" - {}".format(region)) - db = "li_{}_2018".format(region) - conn = psycopg2.connect(dbname=db, user=admin_user_name, password=admin_pwd) - curs = conn.cursor() - curs.execute('''CREATE EXTENSION IF NOT EXISTS tablefunc;''') - conn.commit() - curs.execute(grant_query) - conn.commit() +# Script: grant_query.py +# Purpose: -- If no argument is given, this script prints out a grant query +# which may be run manually ( +# ie. to allow python and arc_sde users to modify tables created by +# the admin user. +# -- If a study region is specified, admin connection details are +# requested and an admin connection is made to that database +# in order to execute the query +# Author: Carl Higgs +# Date: 20190208 + +# Import custom variables for National Liveability indicator process +import sys + +grant_query = ''' +GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO arc_sde; +GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO arc_sde; +GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO python; +GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO python; +''' +if len(sys.argv) < 2: + print(grant_query) +else: + import psycopg2 + import time + import getpass + import os + print("Please enter PostgreSQL admin details to grant all privileges to python and arc_sde users") + admin_db = raw_input("Database: ") + admin_user_name = raw_input("Username: ") + admin_pwd = getpass.getpass("Password for user {} on database {}: ".format(admin_user_name, admin_db)) + print("Executing grant query and ensuring tablefunc extension is created...") + for region in sys.argv[1:]: + print(" - {}".format(region)) + db = "li_{}_2018".format(region) + conn = psycopg2.connect(dbname=db, user=admin_user_name, password=admin_pwd) + curs = conn.cursor() + curs.execute('''CREATE EXTENSION IF NOT EXISTS tablefunc;''') + conn.commit() + curs.execute(grant_query) + conn.commit() print("Done.") \ No newline at end of file diff --git a/process/pre_process/ogr2poly.py b/process/pre_process/ogr2poly.py index ca1db207..2f91956b 100644 --- a/process/pre_process/ogr2poly.py +++ b/process/pre_process/ogr2poly.py @@ -1,229 +1,229 @@ -#!/usr/bin/env python - -# Sourced from https://trac.openstreetmap.org/export/HEAD/subversion/applications/utils/osm-extract/polygons/ogr2poly.py -# NOTE: modified by Carl Higgs 20190226 to work with Python 3 -# Specifically 'print >> f, string' syntax was replaced with 'f.write(string)' syntax - -# Usage: ogr2poly.py [options] src_datasource [layer] - -# options: -# -p --prefix Text to Prepend to Output Poly File Name -# -b --buffer-distance Set buffer distance in meters (default: 0). -# -s --simplify-distance Set simplify tolerance in meters (default: 0). -# -f --field-name Field name to use to name files. (Field name in source file I presume) -# -v --verbose true/false Print detailed status messages. - -# [layer] layer=0 layer number in datasource to use (default=0) - -# This converts OGR supported files (Shapefile, GPX, etc.) to the polygon -# filter file format [1] supported by Osmosis and other tools. If there is -# more than one feature, it will create one POLY file for each feature, -# either using an incrementing filename or based on a field value. It also -# includes buffering and simplifying. This allows point or line features -# to be used when creating POLY files, but in this case buffering must -# be used. -# -# Requires GDAL/OGR compiled with GEOS -# -# [1] http://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format -# -# written by Josh Doe and licensed under the LGPL -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . - -from optparse import OptionParser -import logging -import os -import sys - -from osgeo import ogr -from osgeo import osr - -# TODO: -# check if file exists, make sure field is unique (increment) -# likely doesn't handle areas spanning the antimeridian (+/-180 deg lon) -# sometimes an empty poly is created, so pay attention to warnings -# this can usually be fixed by decreasing the simplify distance - - -def createPolys(inOgr, options): - logging.info("Opening datasource '%s'" % inOgr) - ds = ogr.Open(inOgr) - lyr = ds.GetLayer(options.layer) - - # create SRS transformations - mercSRS = osr.SpatialReference() - mercSRS.ImportFromEPSG(3857) # TODO: make this an option - wgsSRS = osr.SpatialReference() - wgsSRS.ImportFromEPSG(4326) - nativeSRS2bufferSRS = osr.CoordinateTransformation(lyr.GetSpatialRef(), - mercSRS) - bufferSRS2wgsSRS = osr.CoordinateTransformation(mercSRS, wgsSRS) - nativeSRS2wgsSRS = osr.CoordinateTransformation(lyr.GetSpatialRef(), - wgsSRS) - - # if no field name is provided, use incrementing number - # (padded with just enough zeros) - inc = 0 - incFmt = '%0' + str(len(str(lyr.GetFeatureCount() - 1))) + 'd' - - logging.info('Found %d features, will create one POLY file for each one' - % lyr.GetFeatureCount()) - - # create POLYs - for feat in lyr: - if options.fieldName != None: - fieldVal = feat.GetFieldAsString(options.fieldName) - if fieldVal is None: - return False - polyName = options.outPrefix + fieldVal.replace(' ', '_') - else: - polyName = options.outPrefix + incFmt % inc - inc += 1 - - logging.info('Creating ' + polyName + '.poly') - f = open(polyName + '.poly', 'wt') - f.write(polyName) - - # this will be a polygon, TODO: handle linestrings (must be buffered) - geom = feat.GetGeometryRef() - geomType = geom.GetGeometryType() - - subGeom = [] - - nonAreaTypes = [ogr.wkbPoint, ogr.wkbLineString, ogr.wkbMultiPoint, - ogr.wkbMultiLineString] - if geomType in nonAreaTypes and options.bufferDistance == 0: - logging.warn("Ignoring non-area type. " + - "To include you must set a buffer distance.") - continue - if geomType in [ogr.wkbUnknown, ogr.wkbNone]: - logging.warn("Ignoring unknown geometry type.") - continue - - # transform to WGS84, buffering/simplifying along the way - if options.bufferDistance > 0 or options.simplifyDistance > 0: - geom.Transform(nativeSRS2bufferSRS) - - if options.bufferDistance > 0: - geom = geom.Buffer(float(options.bufferDistance)) - if options.simplifyDistance > 0: - geom = geom.Simplify(float(options.simplifyDistance)) - - geom.Transform(bufferSRS2wgsSRS) - else: - geom.Transform(nativeSRS2wgsSRS) - - # handle multi-polygons - subgeom = [] - geomtype = geom.GetGeometryType() - if geomtype == ogr.wkbPolygon: - subgeom = [geom] - elif geomtype == ogr.wkbMultiPolygon: - for k in range(geom.GetGeometryCount()): - subgeom.append(geom.GetGeometryRef(k)) - - logging.debug("# of polygons: " + str(len(subgeom))) - for g in subgeom: - # loop over all rings in the polygon - logging.debug('# of rings: ' + str(g.GetGeometryCount())) - for i in range(0, g.GetGeometryCount()): - if i == 0: - # outer ring - f.write('\n{}'.format(i + 1)) - else: - # inner ring - f.write('\n!{}'.format(i + 1)) - ring = g.GetGeometryRef(i) - - if ring.GetPointCount() > 0: - logging.debug('# of points: ' + str(ring.GetPointCount())) - else: - logging.warn('Ring with no points') - - # output all points in the ring - for j in range(0, ring.GetPointCount()): - (x, y, z) = ring.GetPoint(j) - # f.write('\n %.6E %.6E' % (x, y)) - f.write(f'\n {y} {x}') - f.write('\nEND') - f.write('\nEND\n') - f.close() - return True - -if __name__ == '__main__': - # Setup program usage - usage = "Usage: %prog [options] src_datasource_name [layer]" - parser = OptionParser(usage=usage) - parser.add_option("-p", "--prefix", dest="outPrefix", - help="Text to prepend to POLY filenames.") - parser.add_option("-b", "--buffer-distance", dest="bufferDistance", - type="float", - help="Set buffer distance in meters (default: 0).") - parser.add_option("-s", "--simplify-distance", dest="simplifyDistance", - type="float", - help="Set simplify tolerance in meters (default: 0).") - parser.add_option("-f", "--field-name", dest="fieldName", - help="Field name to use to name files.") - parser.add_option("-v", "--verbose", dest="verbose", action="store_true", - help="Print detailed status messages.") - - parser.set_defaults(bufferDistance=0, fieldName=None, outPrefix=None, - simplifyDistance=0, layer=0, verbose=False) - - # Parse and process arguments - (options, args) = parser.parse_args() - - if options.verbose: - logging.basicConfig(format='%(asctime)s:%(levelname)s: %(message)s', - level=logging.DEBUG) - else: - logging.basicConfig(format='%(levelname)s: %(message)s', - level=logging.WARNING) - - if len(args) < 1: - parser.print_help() - parser.error("You must specify an OGR source") - sys.exit(1) - elif len(args) > 2: - parser.error("You have specified too many arguments") - - # note that this may be a file (e.g. .shp) or a database connection string - src_datasource = args[0] - if len(args) == 2: - options.layer = args[1] - - # check options - if options.outPrefix == None: - if os.path.exists(src_datasource): - # put in current dir, TODO: allow user to specify output dir? - (options.outPrefix, ext) = os.path.splitext( - os.path.basename(src_datasource)) - options.outPrefix += '_' - else: - # file doesn't exist, so possibly a DB connection string - options.outPrefix = 'poly_' - if options.bufferDistance < 0: - parser.error("Buffer distance must be greater than zero.") - if options.simplifyDistance < 0: - parser.error("Simplify tolerance must be greater than zero.") - if options.simplifyDistance > options.bufferDistance: - logging.warn("Simplify distance greater than buffer distance") - - if createPolys(src_datasource, options): - logging.info('Finished!') - sys.exit(0) - else: - logging.info('Failed!') - sys.exit(1) +#!/usr/bin/env python + +# Sourced from https://trac.openstreetmap.org/export/HEAD/subversion/applications/utils/osm-extract/polygons/ogr2poly.py +# NOTE: modified by Carl Higgs 20190226 to work with Python 3 +# Specifically 'print >> f, string' syntax was replaced with 'f.write(string)' syntax + +# Usage: ogr2poly.py [options] src_datasource [layer] + +# options: +# -p --prefix Text to Prepend to Output Poly File Name +# -b --buffer-distance Set buffer distance in meters (default: 0). +# -s --simplify-distance Set simplify tolerance in meters (default: 0). +# -f --field-name Field name to use to name files. (Field name in source file I presume) +# -v --verbose true/false Print detailed status messages. + +# [layer] layer=0 layer number in datasource to use (default=0) + +# This converts OGR supported files (Shapefile, GPX, etc.) to the polygon +# filter file format [1] supported by Osmosis and other tools. If there is +# more than one feature, it will create one POLY file for each feature, +# either using an incrementing filename or based on a field value. It also +# includes buffering and simplifying. This allows point or line features +# to be used when creating POLY files, but in this case buffering must +# be used. +# +# Requires GDAL/OGR compiled with GEOS +# +# [1] http://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format +# +# written by Josh Doe and licensed under the LGPL +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +from optparse import OptionParser +import logging +import os +import sys + +from osgeo import ogr +from osgeo import osr + +# TODO: +# check if file exists, make sure field is unique (increment) +# likely doesn't handle areas spanning the antimeridian (+/-180 deg lon) +# sometimes an empty poly is created, so pay attention to warnings +# this can usually be fixed by decreasing the simplify distance + + +def createPolys(inOgr, options): + logging.info("Opening datasource '%s'" % inOgr) + ds = ogr.Open(inOgr) + lyr = ds.GetLayer(options.layer) + + # create SRS transformations + mercSRS = osr.SpatialReference() + mercSRS.ImportFromEPSG(3857) # TODO: make this an option + wgsSRS = osr.SpatialReference() + wgsSRS.ImportFromEPSG(4326) + nativeSRS2bufferSRS = osr.CoordinateTransformation(lyr.GetSpatialRef(), + mercSRS) + bufferSRS2wgsSRS = osr.CoordinateTransformation(mercSRS, wgsSRS) + nativeSRS2wgsSRS = osr.CoordinateTransformation(lyr.GetSpatialRef(), + wgsSRS) + + # if no field name is provided, use incrementing number + # (padded with just enough zeros) + inc = 0 + incFmt = '%0' + str(len(str(lyr.GetFeatureCount() - 1))) + 'd' + + logging.info('Found %d features, will create one POLY file for each one' + % lyr.GetFeatureCount()) + + # create POLYs + for feat in lyr: + if options.fieldName != None: + fieldVal = feat.GetFieldAsString(options.fieldName) + if fieldVal is None: + return False + polyName = options.outPrefix + fieldVal.replace(' ', '_') + else: + polyName = options.outPrefix + incFmt % inc + inc += 1 + + logging.info('Creating ' + polyName + '.poly') + f = open(polyName + '.poly', 'wt') + f.write(polyName) + + # this will be a polygon, TODO: handle linestrings (must be buffered) + geom = feat.GetGeometryRef() + geomType = geom.GetGeometryType() + + subGeom = [] + + nonAreaTypes = [ogr.wkbPoint, ogr.wkbLineString, ogr.wkbMultiPoint, + ogr.wkbMultiLineString] + if geomType in nonAreaTypes and options.bufferDistance == 0: + logging.warn("Ignoring non-area type. " + + "To include you must set a buffer distance.") + continue + if geomType in [ogr.wkbUnknown, ogr.wkbNone]: + logging.warn("Ignoring unknown geometry type.") + continue + + # transform to WGS84, buffering/simplifying along the way + if options.bufferDistance > 0 or options.simplifyDistance > 0: + geom.Transform(nativeSRS2bufferSRS) + + if options.bufferDistance > 0: + geom = geom.Buffer(float(options.bufferDistance)) + if options.simplifyDistance > 0: + geom = geom.Simplify(float(options.simplifyDistance)) + + geom.Transform(bufferSRS2wgsSRS) + else: + geom.Transform(nativeSRS2wgsSRS) + + # handle multi-polygons + subgeom = [] + geomtype = geom.GetGeometryType() + if geomtype == ogr.wkbPolygon: + subgeom = [geom] + elif geomtype == ogr.wkbMultiPolygon: + for k in range(geom.GetGeometryCount()): + subgeom.append(geom.GetGeometryRef(k)) + + logging.debug("# of polygons: " + str(len(subgeom))) + for g in subgeom: + # loop over all rings in the polygon + logging.debug('# of rings: ' + str(g.GetGeometryCount())) + for i in range(0, g.GetGeometryCount()): + if i == 0: + # outer ring + f.write('\n{}'.format(i + 1)) + else: + # inner ring + f.write('\n!{}'.format(i + 1)) + ring = g.GetGeometryRef(i) + + if ring.GetPointCount() > 0: + logging.debug('# of points: ' + str(ring.GetPointCount())) + else: + logging.warn('Ring with no points') + + # output all points in the ring + for j in range(0, ring.GetPointCount()): + (x, y, z) = ring.GetPoint(j) + # f.write('\n %.6E %.6E' % (x, y)) + f.write(f'\n {y} {x}') + f.write('\nEND') + f.write('\nEND\n') + f.close() + return True + +if __name__ == '__main__': + # Setup program usage + usage = "Usage: %prog [options] src_datasource_name [layer]" + parser = OptionParser(usage=usage) + parser.add_option("-p", "--prefix", dest="outPrefix", + help="Text to prepend to POLY filenames.") + parser.add_option("-b", "--buffer-distance", dest="bufferDistance", + type="float", + help="Set buffer distance in meters (default: 0).") + parser.add_option("-s", "--simplify-distance", dest="simplifyDistance", + type="float", + help="Set simplify tolerance in meters (default: 0).") + parser.add_option("-f", "--field-name", dest="fieldName", + help="Field name to use to name files.") + parser.add_option("-v", "--verbose", dest="verbose", action="store_true", + help="Print detailed status messages.") + + parser.set_defaults(bufferDistance=0, fieldName=None, outPrefix=None, + simplifyDistance=0, layer=0, verbose=False) + + # Parse and process arguments + (options, args) = parser.parse_args() + + if options.verbose: + logging.basicConfig(format='%(asctime)s:%(levelname)s: %(message)s', + level=logging.DEBUG) + else: + logging.basicConfig(format='%(levelname)s: %(message)s', + level=logging.WARNING) + + if len(args) < 1: + parser.print_help() + parser.error("You must specify an OGR source") + sys.exit(1) + elif len(args) > 2: + parser.error("You have specified too many arguments") + + # note that this may be a file (e.g. .shp) or a database connection string + src_datasource = args[0] + if len(args) == 2: + options.layer = args[1] + + # check options + if options.outPrefix == None: + if os.path.exists(src_datasource): + # put in current dir, TODO: allow user to specify output dir? + (options.outPrefix, ext) = os.path.splitext( + os.path.basename(src_datasource)) + options.outPrefix += '_' + else: + # file doesn't exist, so possibly a DB connection string + options.outPrefix = 'poly_' + if options.bufferDistance < 0: + parser.error("Buffer distance must be greater than zero.") + if options.simplifyDistance < 0: + parser.error("Simplify tolerance must be greater than zero.") + if options.simplifyDistance > options.bufferDistance: + logging.warn("Simplify distance greater than buffer distance") + + if createPolys(src_datasource, options): + logging.info('Finished!') + sys.exit(0) + else: + logging.info('Failed!') + sys.exit(1) diff --git a/process/pre_process/process_region.sh b/process/pre_process/process_region.sh index 6dd05a1c..b2ae3ad7 100644 --- a/process/pre_process/process_region.sh +++ b/process/pre_process/process_region.sh @@ -1,18 +1,18 @@ -# Process study region resources for Global Indicators project - -for i -do - python 00_create_database.py $i - python 01_create_study_region.py $i - python 02_create_osm_resources.py $i - python 03_create_network_resources.py $i - python 04_create_hex_grid.py $i - python 05_create_population_grid.py $i - python 06_compile_destinations.py $i - python 07_open_space_areas_setup.py $i - python 08_locate_origins_destinations.py $i - python 09_hex_destination_summary.py $i - python 10_destination_audit.py $i - python 11_urban_covariates.py $i - python _export_gpkg.py $i -done +# Process study region resources for Global Indicators project + +for i +do + python 00_create_database.py $i + python 01_create_study_region.py $i + python 02_create_osm_resources.py $i + python 03_create_network_resources.py $i + python 04_create_hex_grid.py $i + python 05_create_population_grid.py $i + python 06_compile_destinations.py $i + python 07_open_space_areas_setup.py $i + python 08_locate_origins_destinations.py $i + python 09_hex_destination_summary.py $i + python 10_destination_audit.py $i + python 11_urban_covariates.py $i + python _export_gpkg.py $i +done diff --git a/process/pre_process/progressor.py b/process/pre_process/progressor.py index c5b95bc5..c7b75ee4 100644 --- a/process/pre_process/progressor.py +++ b/process/pre_process/progressor.py @@ -1,82 +1,82 @@ -# Script: progressor.py -# Purpose: a progress percent timer function -# -- place in a loop -# -- initialises with numerator of zero -# -- completes with numerator of 100% or greater -# -- suggests a problem may have occurred if -# numerator is greater than 100% -# -- optionally provide a start time to tally HMS -# and provide ETA based on linear completion rate. -# -- define 'startClock = time.time()' outside of loop -# and provide startClock as start parameter -# -- optionally define a task name to be printed -# Author: Carl Higgs -# Date: 29/12/2016 - - -def progressor(num = 0, denom = 100, start = None, task = ''): - import time - - if (num < 0): - print("Possible error: numerator is negative - is this right?") - - if num >= 0: - pct = (float(num)/denom)*100 - HMS = '' - eta = '' - mult = 9 + len(task) - if type(start) in (int,float): - secs = (time.time()-start) - etaT = start+((secs/(num+0.001))*denom) - HMS = ' {} '.format(time.strftime("%H:%M:%S", time.gmtime(secs))) - eta = ' (ETA: {}) '.format(time.strftime("%Y%m%d_%H%M",time.localtime(etaT))) - mult += len(HMS)+len(eta) - if num == 0: - todayhour = time.strftime("%Y%m%d_%H%M") - print("Start: {} ".format(todayhour)) - print("{:5.2f}% {}{}".format(0,task,' '*(mult-len(task)-9))), - print("\b"*mult), - print("{:5.2f}%{}{} {}".format(pct,HMS,eta,task)), - if num >= denom: - todayhour = time.strftime("%Y%m%d_%H%M") - print("\nComplete: {}".format(todayhour)) - if num > denom: - print("\nPossible error: numerator is greater than denominator. Is this right?") - -if __name__ == '__main__': - import time - - print("Example usage of progressor function") - print(''' - progressor(num,denom) - ''') - - denom = 3 - start = time.time() - for num in range(0,denom+1): - progressor(num,denom) - time.sleep(1) - print("Task duration = {:9.2f}".format((time.time()-start)/60)) - - - print(''' - progressor(num,denom,task = taskName) - ''') - denom = 3 - start = time.time() - taskName = 'Display task progress with task name' - for num in range(0,denom+1): - progressor(num,denom,task = taskName) - time.sleep(1) - print("Task duration = {:9.2f}".format((time.time()-start)/60)) - - print(''' - progressor(num,denom,start,taskName) - ''') - denom = 12 - start = time.time() - taskName = 'Display task progress with task name' - for num in range(0,denom+1): - progressor(num,denom,start,taskName) - time.sleep(1) - print("Task duration = {:9.2f} minutes".format((time.time()-start)/60)) +# Script: progressor.py +# Purpose: a progress percent timer function +# -- place in a loop +# -- initialises with numerator of zero +# -- completes with numerator of 100% or greater +# -- suggests a problem may have occurred if +# numerator is greater than 100% +# -- optionally provide a start time to tally HMS +# and provide ETA based on linear completion rate. +# -- define 'startClock = time.time()' outside of loop +# and provide startClock as start parameter +# -- optionally define a task name to be printed +# Author: Carl Higgs +# Date: 29/12/2016 + + +def progressor(num = 0, denom = 100, start = None, task = ''): + import time + + if (num < 0): + print("Possible error: numerator is negative - is this right?") + + if num >= 0: + pct = (float(num)/denom)*100 + HMS = '' + eta = '' + mult = 9 + len(task) + if type(start) in (int,float): + secs = (time.time()-start) + etaT = start+((secs/(num+0.001))*denom) + HMS = ' {} '.format(time.strftime("%H:%M:%S", time.gmtime(secs))) + eta = ' (ETA: {}) '.format(time.strftime("%Y%m%d_%H%M",time.localtime(etaT))) + mult += len(HMS)+len(eta) + if num == 0: + todayhour = time.strftime("%Y%m%d_%H%M") + print("Start: {} ".format(todayhour)) + print("{:5.2f}% {}{}".format(0,task,' '*(mult-len(task)-9))), + print("\b"*mult), + print("{:5.2f}%{}{} {}".format(pct,HMS,eta,task)), + if num >= denom: + todayhour = time.strftime("%Y%m%d_%H%M") + print("\nComplete: {}".format(todayhour)) + if num > denom: + print("\nPossible error: numerator is greater than denominator. Is this right?") + +if __name__ == '__main__': + import time + + print("Example usage of progressor function") + print(''' + progressor(num,denom) + ''') + + denom = 3 + start = time.time() + for num in range(0,denom+1): + progressor(num,denom) + time.sleep(1) + print("Task duration = {:9.2f}".format((time.time()-start)/60)) + + + print(''' + progressor(num,denom,task = taskName) + ''') + denom = 3 + start = time.time() + taskName = 'Display task progress with task name' + for num in range(0,denom+1): + progressor(num,denom,task = taskName) + time.sleep(1) + print("Task duration = {:9.2f}".format((time.time()-start)/60)) + + print(''' + progressor(num,denom,start,taskName) + ''') + denom = 12 + start = time.time() + taskName = 'Display task progress with task name' + for num in range(0,denom+1): + progressor(num,denom,start,taskName) + time.sleep(1) + print("Task duration = {:9.2f} minutes".format((time.time()-start)/60)) diff --git a/process/pre_process/script_running_log.py b/process/pre_process/script_running_log.py index 967988bb..ede93d8c 100644 --- a/process/pre_process/script_running_log.py +++ b/process/pre_process/script_running_log.py @@ -1,42 +1,42 @@ -# Script: script_running_log.py -# Purpose: log completion to sql -# Author: Carl Higgs -# Date: 20181009 - -# Note: This script assumes the specified postgresql database has already been created. -import os -import sys -import time -import psycopg2 -# Import custom variables for National Liveability indicator process -from _project_setup import db,db_user,db_pwd,db_host,db_port - -# Define script logging to study region database function -def script_running_log(script = '', task = '', start = '', prefix = ''): - # Initialise postgresql connection - conn = psycopg2.connect(dbname=db, user=db_user, password=db_pwd, host = db_host, port = db_port) - curs = conn.cursor() - date_time = time.strftime("%Y%m%d-%H%M%S") - duration = (time.time() - start)/60 - - log_table = ''' - -- If log table doesn't exist, its created - CREATE TABLE IF NOT EXISTS script_log - ( - script varchar, - task varchar, - datetime_completed varchar, - duration_mins numeric - ); - -- Insert completed script details - INSERT INTO script_log VALUES ($${}$$,$${}$$,$${}$$,{}); - '''.format(script,task,date_time,duration) - try: - curs.execute(log_table) - conn.commit() - print('''Processing completed at {}\n- Task: {}\n- Duration: {:04.2f} minutes'''.format(date_time,task,duration)) - except: - print("Error withoutput to script running log. Has the database for this study region been created?") - raise - finally: +# Script: script_running_log.py +# Purpose: log completion to sql +# Author: Carl Higgs +# Date: 20181009 + +# Note: This script assumes the specified postgresql database has already been created. +import os +import sys +import time +import psycopg2 +# Import custom variables for National Liveability indicator process +from _project_setup import db,db_user,db_pwd,db_host,db_port + +# Define script logging to study region database function +def script_running_log(script = '', task = '', start = '', prefix = ''): + # Initialise postgresql connection + conn = psycopg2.connect(dbname=db, user=db_user, password=db_pwd, host = db_host, port = db_port) + curs = conn.cursor() + date_time = time.strftime("%Y%m%d-%H%M%S") + duration = (time.time() - start)/60 + + log_table = ''' + -- If log table doesn't exist, its created + CREATE TABLE IF NOT EXISTS script_log + ( + script varchar, + task varchar, + datetime_completed varchar, + duration_mins numeric + ); + -- Insert completed script details + INSERT INTO script_log VALUES ($${}$$,$${}$$,$${}$$,{}); + '''.format(script,task,date_time,duration) + try: + curs.execute(log_table) + conn.commit() + print('''Processing completed at {}\n- Task: {}\n- Duration: {:04.2f} minutes'''.format(date_time,task,duration)) + except: + print("Error withoutput to script running log. Has the database for this study region been created?") + raise + finally: conn.close() \ No newline at end of file diff --git a/process/process_regions.sh b/process/process_regions.sh index 19e40e77..fd04654c 100644 --- a/process/process_regions.sh +++ b/process/process_regions.sh @@ -1,6 +1,6 @@ -# Process study regions for Global Indicators project - -for i -do - python sp.py $i true -done +# Process study regions for Global Indicators project + +for i +do + python sp.py $i true +done diff --git a/process/readme.md b/process/readme.md index bb0b87a8..a63e3e89 100644 --- a/process/readme.md +++ b/process/readme.md @@ -1,60 +1,60 @@ -# Running the Process -Please follow the instructions below to run the process. - -## Run the Python Scripts - -### 1. Fork the Repo -- Make sure that you have forked the repo onto your own GitHub account and that the repository is cloned onto your machine. -- Additionally, to make sure that your branch is up to date run the following in your command prompt / terminal window - 1. Change directory to the **global-indicators** folder on your machine - 1. Type the following: - ``` - git pull upstream master - ``` - -### 2. Download and Organize the Data -1. Download the global input data from the cloudstor data folder. You can find the links to this data [HERE](https://docs.google.com/document/d/1NnV3g8uj0OnOQFkFIR5IbT60HO2PiF3SLoZpUUTL3B0/edit?ts=5ecc5e75). -1. Rename the folder to **input** and place the folder of data in **global-indicators/process/data**. -1. Create a second subfolder (this will be empty initially) named **output** in **global-indicators/process/data**. - -### 3. Run Docker -1. In the command prompt / terminal window, change your directory to the **global-indicators** folder. Then type the following - ``` - Docker pull gboeing/global-indicators:latest - ``` -1. Start running docker in your machine - - On Windows: - ``` - docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash - ``` - - On Mac/Linux: - ``` - docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash - ``` -1. Change directory to **global-indicators/process** - -### 4. Run the Python Scripts -1. Run scripts using the following code - 1. ```python setup_config.py``` - 1. Make sure to check on the list of cities within the ``setup_config.py``, it should include cities that you plan to analyze - 1. You could either delete or add a pound sign (#) before each city you would NOT include in your analysis - 1. ```python sp.py [SPECIFIC CITY NAME]``` - 1. Use the file name that can be found under the **process/configuration** folder for each city. Example: For Adelaide, type ```python sp.py Adelaide``` - 1. Alternatively, a shell script wrapper **process_region.sh** exists to run all study regions at once in sequence, and can be run using ```bash process_region.sh``` followed by a list of region names. For example, ```bash process_region.sh Adelaide Auckland Baltimore``` - 1. Make sure to run this line of code for each and every city before running ``aggr.py`` script - 1. ```python aggr.py``` - 1. Notice that you will get the final indicator geopackadge in **global-indicators/process/data/output** only after you run this ``aggr.py`` script - -Note that it will take several hours to several days to run these scripts, depending on the size of the study city. - - -## Run the Jupyter Notebooks (TODO) - -1. Follow steps 1 and 2 from the instructions above -1. Run docker: - 1. In the command prompt / terminal window, change your directory to the global-indicators folder. Then type the following - ``` - docker run --rm -it --name global-indicators -p 8888:8888 -v "$PWD":/home/jovyan/work gboeing/global-indicators - ``` -2. Open a web browser and visit http://localhost:8888 -3. Run the Jupyter Notebooks +# Running the Process +Please follow the instructions below to run the process. + +## Run the Python Scripts + +### 1. Fork the Repo +- Make sure that you have forked the repo onto your own GitHub account and that the repository is cloned onto your machine. +- Additionally, to make sure that your branch is up to date run the following in your command prompt / terminal window + 1. Change directory to the **global-indicators** folder on your machine + 1. Type the following: + ``` + git pull upstream master + ``` + +### 2. Download and Organize the Data +1. Download the global input data from the cloudstor data folder. You can find the links to this data [HERE](https://docs.google.com/document/d/1NnV3g8uj0OnOQFkFIR5IbT60HO2PiF3SLoZpUUTL3B0/edit?ts=5ecc5e75). +1. Rename the folder to **input** and place the folder of data in **global-indicators/process/data**. +1. Create a second subfolder (this will be empty initially) named **output** in **global-indicators/process/data**. + +### 3. Run Docker +1. In the command prompt / terminal window, change your directory to the **global-indicators** folder. Then type the following + ``` + Docker pull gboeing/global-indicators:latest + ``` +1. Start running docker in your machine + - On Windows: + ``` + docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash + ``` + - On Mac/Linux: + ``` + docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash + ``` +1. Change directory to **global-indicators/process** + +### 4. Run the Python Scripts +1. Run scripts using the following code + 1. ```python setup_config.py``` + 1. Make sure to check on the list of cities within the ``setup_config.py``, it should include cities that you plan to analyze + 1. You could either delete or add a pound sign (#) before each city you would NOT include in your analysis + 1. ```python sp.py [SPECIFIC CITY NAME]``` + 1. Use the file name that can be found under the **process/configuration** folder for each city. Example: For Adelaide, type ```python sp.py Adelaide``` + 1. Alternatively, a shell script wrapper **process_region.sh** exists to run all study regions at once in sequence, and can be run using ```bash process_region.sh``` followed by a list of region names. For example, ```bash process_region.sh Adelaide Auckland Baltimore``` + 1. Make sure to run this line of code for each and every city before running ``aggr.py`` script + 1. ```python aggr.py``` + 1. Notice that you will get the final indicator geopackadge in **global-indicators/process/data/output** only after you run this ``aggr.py`` script + +Note that it will take several hours to several days to run these scripts, depending on the size of the study city. + + +## Run the Jupyter Notebooks (TODO) + +1. Follow steps 1 and 2 from the instructions above +1. Run docker: + 1. In the command prompt / terminal window, change your directory to the global-indicators folder. Then type the following + ``` + docker run --rm -it --name global-indicators -p 8888:8888 -v "$PWD":/home/jovyan/work gboeing/global-indicators + ``` +2. Open a web browser and visit http://localhost:8888 +3. Run the Jupyter Notebooks diff --git a/process/setup_aggr.py b/process/setup_aggr.py index 9a4ced39..c14da471 100644 --- a/process/setup_aggr.py +++ b/process/setup_aggr.py @@ -1,223 +1,223 @@ -################################################################################ -# Module: setup_aggr.py -# Description: this module contains functions to set up within and across city indicators - -################################################################################ - -import geopandas as gpd -import pandas as pd -import setup_config as sc -from tqdm import tqdm - -cities_config = sc.cities_config - -def calc_hexes_pct_sp_indicators(gpkg_input, gpkg_output, city, layer_samplepoint, layer_hex): - """ - Caculate sample point weighted hexagon-level indicators within each city, - and save to output geopackage - - Parameters - ---------- - gpkg_input: str - file path of sample point input geopackage - gpkg_output: str - file path of hex grid output geopackage - city: str - the name of a city - layer_samplepoint: str - the name of sample point layer in input geopackage - layer_hex: str - the name of hex layer in input geopackage - - Returns - ------- - list, list of GeoDataFrame - """ - # read input geopackage with processed sample point and hex layer - gdf_samplepoint = gpd.read_file(gpkg_input, layer=layer_samplepoint) - gdf_samplepoint = gdf_samplepoint[['hex_id']+sc.fieldNames_from_samplePoint] - gdf_samplepoint.columns = ['hex_id']+sc.fieldNames2hex - - gdf_hex = gpd.read_file(gpkg_input, layer=layer_hex) - - # join urban sample point count for each hex to gdf_hex - samplepoint_count = gdf_samplepoint["hex_id"].value_counts() - samplepoint_count.name = "urban_sample_point_count" - gdf_hex = gdf_hex.join(samplepoint_count, how="inner", on="index") - - # perform aggregation functions to calculate sample point weighted hex level indicators - gdf_samplepoint = gdf_samplepoint.groupby("hex_id").mean() - gdf_hex = gdf_hex.join(gdf_samplepoint, how="left", on="index") - - # scale percentages from proportions - pct_fields = [x for x in gdf_hex if x.startswith('pct_access')] - gdf_hex[pct_fields] = gdf_hex[pct_fields] * 100 - - if "study_region" not in gdf_hex.columns: - gdf_hex["study_region"] = city.title().replace('_',' ') - - gdf_hex = gdf_hex[[x for x in sc.hex_fieldNames if x in gdf_hex.columns]] - # save the gdf_hex to geopackage - gdf_hex.to_file(gpkg_output, layer=city, driver="GPKG") - - -def calc_hexes_zscore_walk(gpkg_output_hex, cities): - """ - Calculate zscore of hexagon-level indicators and walkability relative to all city, and save to output geopackage - - These indicators include (z-score of population weighted indicators relative to all cities): - "all_cities_z_nh_population_density", - "all_cities_z_nh_intersection_density", - "all_cities_z_daily_living", - "all_cities_walkability" - - Parameters - ---------- - gpkg_output_hex: str - file path of output geopackage - cities: list - all the city names - - Returns - ------- - none - """ - print(" - read and append all cities hex layer from the output geopackage") - gdf_layers = [] - for i in tqdm(cities): - try: - gdf = gpd.read_file(gpkg_output_hex, layer=i) - gdf = gdf.reindex(columns=sorted(gdf.columns)) - gdf_layers.append(gdf) - except ValueError as e: - print(e) - - # concatenate all cities hex layers into one a dataframe - all_cities_hex_df = pd.concat(gdf_layers, ignore_index=True) - # zip field names in hex layer that are needed to calculate z scores with new field names for the z score indicators - fieldNames_hex = [sc.field_lookup[x]['hex'] for x in sc.field_lookup if '_z_' in sc.field_lookup[x]['all']] - fieldNames_new = [sc.field_lookup[x]['all'] for x in sc.field_lookup if '_z_' in sc.field_lookup[x]['all']] - print(" - calculate the zscores of indicators accross cities") - for index, layer in enumerate(tqdm(gdf_layers)): - for old,new in list(zip(fieldNames_hex,fieldNames_new)): - mean = all_cities_hex_df[old].mean() - std = all_cities_hex_df[old].std() - layer[new] = (layer[old] - mean) / std - # calculate the accross-city walkability index by summing all zscore indicators - layer["all_cities_walkability"] = layer[fieldNames_new].sum(axis=1) - # save the indicators to out the output geopackage - field_order = sc.hex_fieldNames + [x for x in layer.columns if x not in sc.hex_fieldNames] - layer[field_order].to_file(gpkg_output_hex, layer=cities[index], driver="GPKG") - - -def combined_city_hexes(gpkg_inputs, gpkg_output_hex, cities): - """ - Create a combined layer of all city hexes to facilitate later grouped analyses and plotting. - - This is ordered by Continent, Country, City, and hex index. - - Parameters - ---------- - gpkg_inputs: list - list of sample point input geopackages - gpkg_output_hex: str - file path of output geopackage - cities: list - list of city study region names - - Returns - ------- - none - """ - print(" - combining city hex and basic covariate data") - for i, city in enumerate(tqdm(cities)): - if i==0: - all_city_hexes_combined = gpd.read_file(gpkg_output_hex, layer=city).to_crs(4326) - urban_covariates_combined = gpd.read_file(gpkg_inputs[i], layer='urban_covariates') - else: - all_city_hexes_combined = all_city_hexes_combined.append(gpd.read_file(gpkg_output_hex, - layer=city).to_crs(4326)) - urban_covariates_combined = urban_covariates_combined.append(gpd.read_file(gpkg_inputs[i], - layer='urban_covariates')) - - print(" - saving to geopackage, ordered by Continent, Country, City, and hex index") - urban_covariate_fields = ['Continent','Country','ISO 3166-1 alpha-2','City'] - all_city_hexes_combined = all_city_hexes_combined.set_index('study_region')\ - .join(urban_covariates_combined[urban_covariate_fields]\ - .set_index('City'))\ - .rename_axis('City').reset_index()\ - .sort_values(['Continent','Country','City','index']).reset_index(drop=True) - all_city_hexes_combined = all_city_hexes_combined[urban_covariate_fields + - [x for x in all_city_hexes_combined if x not in urban_covariate_fields]] - all_city_hexes_combined.to_file(gpkg_output_hex, layer='all_city_hexes_combined', driver="GPKG") - - -def calc_cities_pop_pct_indicators(gpkg_output_hex, city, gpkg_input, gpkg_output_cities,extra_unweighted_vars = []): - """ - Calculate population-weighted city-level indicators, - and save to output geopackage - - These indicators include: - 'pop_pct_access_500m_fresh_food_markets', - 'pop_pct_access_500m_convenience', - 'pop_pct_access_500m_pt_any', - 'pop_pct_access_500m_public_open_space', - 'pop_nh_pop_density', - 'pop_nh_intersection_density', - 'pop_daily_living', - 'pop_walkability', - 'all_cities_pop_z_daily_living', - 'all_cities_walkability' - - - Parameters - ---------- - gpkg_output_hex: str - file path of accross-ctiy hexagon-level indicators - city: str - the name of a city - gpkg_input: str - file path of input geopackage - gpkg_output_cities: str - file path of output geopackage - extra_unweighted_vars: list - an optional list of variables to also calculate mean (unweighted) for - - Returns - ------- - list, list of GeoDataFrame - """ - gdf_hex = gpd.read_file(gpkg_output_hex, layer=city) - - gdf_hex_origin = gpd.read_file(gpkg_input, layer=sc.cities_parameters["hex250"]) - gdf_study_region = gpd.read_file(gpkg_input, layer=sc.cities_parameters["urban_study_region"]) - urban_covariates = gpd.read_file(gpkg_input, layer="urban_covariates") - # join pop_est from original hex to processed hex - gdf_hex = gdf_hex.join(gdf_hex_origin.set_index("index"), on="index", how="left", rsuffix="_origin") - # calculate the sum of urban sample point counts for city - urban_covariates['urban_sample_point_count'] = gdf_hex["urban_sample_point_count"].sum() - urban_covariates['geometry'] = gdf_study_region["geometry"] - urban_covariates.crs = gdf_study_region.crs - - # hex-level field names from city-specific hex indicators gpkg - fieldNames = [x for x in sc.hex_fieldNames if x not in sc.basic_attributes+['geometry']] - - # new file names for population-weighted city-level indicators - fieldNames_new = [x for x in sc.city_fieldNames if x not in sc.basic_attributes+['geometry']] - - # calculate the population weighted city-level indicators - for i,o in zip(fieldNames,fieldNames_new): - # calculate the population weighted indicators based on input hexagon layer - # sum to aggregate up to the city level - N = gdf_hex[sc.cities_parameters["pop_est"]].sum() - urban_covariates[o] = (gdf_hex[sc.cities_parameters["pop_est"]] * gdf_hex[i]).sum()/N - - # append any requested unweighted indicator averages - urban_covariates = urban_covariates.join(pd.DataFrame(gdf_hex[extra_unweighted_vars].mean()).transpose()) - # order geometry as final column - urban_covariates = urban_covariates[[x for x in urban_covariates.columns if x!='geometry']+['geometry']] - urban_covariates.to_file(gpkg_output_cities, layer=city, driver="GPKG") - # transform to WGS84 EPSG 4326, for combined all cities layer - urban_covariates = urban_covariates.to_crs(4326) - return(urban_covariates) - +################################################################################ +# Module: setup_aggr.py +# Description: this module contains functions to set up within and across city indicators + +################################################################################ + +import geopandas as gpd +import pandas as pd +import setup_config as sc +from tqdm import tqdm + +cities_config = sc.cities_config + +def calc_hexes_pct_sp_indicators(gpkg_input, gpkg_output, city, layer_samplepoint, layer_hex): + """ + Caculate sample point weighted hexagon-level indicators within each city, + and save to output geopackage + + Parameters + ---------- + gpkg_input: str + file path of sample point input geopackage + gpkg_output: str + file path of hex grid output geopackage + city: str + the name of a city + layer_samplepoint: str + the name of sample point layer in input geopackage + layer_hex: str + the name of hex layer in input geopackage + + Returns + ------- + list, list of GeoDataFrame + """ + # read input geopackage with processed sample point and hex layer + gdf_samplepoint = gpd.read_file(gpkg_input, layer=layer_samplepoint) + gdf_samplepoint = gdf_samplepoint[['hex_id']+sc.fieldNames_from_samplePoint] + gdf_samplepoint.columns = ['hex_id']+sc.fieldNames2hex + + gdf_hex = gpd.read_file(gpkg_input, layer=layer_hex) + + # join urban sample point count for each hex to gdf_hex + samplepoint_count = gdf_samplepoint["hex_id"].value_counts() + samplepoint_count.name = "urban_sample_point_count" + gdf_hex = gdf_hex.join(samplepoint_count, how="inner", on="index") + + # perform aggregation functions to calculate sample point weighted hex level indicators + gdf_samplepoint = gdf_samplepoint.groupby("hex_id").mean() + gdf_hex = gdf_hex.join(gdf_samplepoint, how="left", on="index") + + # scale percentages from proportions + pct_fields = [x for x in gdf_hex if x.startswith('pct_access')] + gdf_hex[pct_fields] = gdf_hex[pct_fields] * 100 + + if "study_region" not in gdf_hex.columns: + gdf_hex["study_region"] = city.title().replace('_',' ') + + gdf_hex = gdf_hex[[x for x in sc.hex_fieldNames if x in gdf_hex.columns]] + # save the gdf_hex to geopackage + gdf_hex.to_file(gpkg_output, layer=city, driver="GPKG") + + +def calc_hexes_zscore_walk(gpkg_output_hex, cities): + """ + Calculate zscore of hexagon-level indicators and walkability relative to all city, and save to output geopackage + + These indicators include (z-score of population weighted indicators relative to all cities): + "all_cities_z_nh_population_density", + "all_cities_z_nh_intersection_density", + "all_cities_z_daily_living", + "all_cities_walkability" + + Parameters + ---------- + gpkg_output_hex: str + file path of output geopackage + cities: list + all the city names + + Returns + ------- + none + """ + print(" - read and append all cities hex layer from the output geopackage") + gdf_layers = [] + for i in tqdm(cities): + try: + gdf = gpd.read_file(gpkg_output_hex, layer=i) + gdf = gdf.reindex(columns=sorted(gdf.columns)) + gdf_layers.append(gdf) + except ValueError as e: + print(e) + + # concatenate all cities hex layers into one a dataframe + all_cities_hex_df = pd.concat(gdf_layers, ignore_index=True) + # zip field names in hex layer that are needed to calculate z scores with new field names for the z score indicators + fieldNames_hex = [sc.field_lookup[x]['hex'] for x in sc.field_lookup if '_z_' in sc.field_lookup[x]['all']] + fieldNames_new = [sc.field_lookup[x]['all'] for x in sc.field_lookup if '_z_' in sc.field_lookup[x]['all']] + print(" - calculate the zscores of indicators accross cities") + for index, layer in enumerate(tqdm(gdf_layers)): + for old,new in list(zip(fieldNames_hex,fieldNames_new)): + mean = all_cities_hex_df[old].mean() + std = all_cities_hex_df[old].std() + layer[new] = (layer[old] - mean) / std + # calculate the accross-city walkability index by summing all zscore indicators + layer["all_cities_walkability"] = layer[fieldNames_new].sum(axis=1) + # save the indicators to out the output geopackage + field_order = sc.hex_fieldNames + [x for x in layer.columns if x not in sc.hex_fieldNames] + layer[field_order].to_file(gpkg_output_hex, layer=cities[index], driver="GPKG") + + +def combined_city_hexes(gpkg_inputs, gpkg_output_hex, cities): + """ + Create a combined layer of all city hexes to facilitate later grouped analyses and plotting. + + This is ordered by Continent, Country, City, and hex index. + + Parameters + ---------- + gpkg_inputs: list + list of sample point input geopackages + gpkg_output_hex: str + file path of output geopackage + cities: list + list of city study region names + + Returns + ------- + none + """ + print(" - combining city hex and basic covariate data") + for i, city in enumerate(tqdm(cities)): + if i==0: + all_city_hexes_combined = gpd.read_file(gpkg_output_hex, layer=city).to_crs(4326) + urban_covariates_combined = gpd.read_file(gpkg_inputs[i], layer='urban_covariates') + else: + all_city_hexes_combined = all_city_hexes_combined.append(gpd.read_file(gpkg_output_hex, + layer=city).to_crs(4326)) + urban_covariates_combined = urban_covariates_combined.append(gpd.read_file(gpkg_inputs[i], + layer='urban_covariates')) + + print(" - saving to geopackage, ordered by Continent, Country, City, and hex index") + urban_covariate_fields = ['Continent','Country','ISO 3166-1 alpha-2','City'] + all_city_hexes_combined = all_city_hexes_combined.set_index('study_region')\ + .join(urban_covariates_combined[urban_covariate_fields]\ + .set_index('City'))\ + .rename_axis('City').reset_index()\ + .sort_values(['Continent','Country','City','index']).reset_index(drop=True) + all_city_hexes_combined = all_city_hexes_combined[urban_covariate_fields + + [x for x in all_city_hexes_combined if x not in urban_covariate_fields]] + all_city_hexes_combined.to_file(gpkg_output_hex, layer='all_city_hexes_combined', driver="GPKG") + + +def calc_cities_pop_pct_indicators(gpkg_output_hex, city, gpkg_input, gpkg_output_cities,extra_unweighted_vars = []): + """ + Calculate population-weighted city-level indicators, + and save to output geopackage + + These indicators include: + 'pop_pct_access_500m_fresh_food_markets', + 'pop_pct_access_500m_convenience', + 'pop_pct_access_500m_pt_any', + 'pop_pct_access_500m_public_open_space', + 'pop_nh_pop_density', + 'pop_nh_intersection_density', + 'pop_daily_living', + 'pop_walkability', + 'all_cities_pop_z_daily_living', + 'all_cities_walkability' + + + Parameters + ---------- + gpkg_output_hex: str + file path of accross-ctiy hexagon-level indicators + city: str + the name of a city + gpkg_input: str + file path of input geopackage + gpkg_output_cities: str + file path of output geopackage + extra_unweighted_vars: list + an optional list of variables to also calculate mean (unweighted) for + + Returns + ------- + list, list of GeoDataFrame + """ + gdf_hex = gpd.read_file(gpkg_output_hex, layer=city) + + gdf_hex_origin = gpd.read_file(gpkg_input, layer=sc.cities_parameters["hex250"]) + gdf_study_region = gpd.read_file(gpkg_input, layer=sc.cities_parameters["urban_study_region"]) + urban_covariates = gpd.read_file(gpkg_input, layer="urban_covariates") + # join pop_est from original hex to processed hex + gdf_hex = gdf_hex.join(gdf_hex_origin.set_index("index"), on="index", how="left", rsuffix="_origin") + # calculate the sum of urban sample point counts for city + urban_covariates['urban_sample_point_count'] = gdf_hex["urban_sample_point_count"].sum() + urban_covariates['geometry'] = gdf_study_region["geometry"] + urban_covariates.crs = gdf_study_region.crs + + # hex-level field names from city-specific hex indicators gpkg + fieldNames = [x for x in sc.hex_fieldNames if x not in sc.basic_attributes+['geometry']] + + # new file names for population-weighted city-level indicators + fieldNames_new = [x for x in sc.city_fieldNames if x not in sc.basic_attributes+['geometry']] + + # calculate the population weighted city-level indicators + for i,o in zip(fieldNames,fieldNames_new): + # calculate the population weighted indicators based on input hexagon layer + # sum to aggregate up to the city level + N = gdf_hex[sc.cities_parameters["pop_est"]].sum() + urban_covariates[o] = (gdf_hex[sc.cities_parameters["pop_est"]] * gdf_hex[i]).sum()/N + + # append any requested unweighted indicator averages + urban_covariates = urban_covariates.join(pd.DataFrame(gdf_hex[extra_unweighted_vars].mean()).transpose()) + # order geometry as final column + urban_covariates = urban_covariates[[x for x in urban_covariates.columns if x!='geometry']+['geometry']] + urban_covariates.to_file(gpkg_output_cities, layer=city, driver="GPKG") + # transform to WGS84 EPSG 4326, for combined all cities layer + urban_covariates = urban_covariates.to_crs(4326) + return(urban_covariates) + diff --git a/process/setup_config.py b/process/setup_config.py index c758a04f..2e07dcb4 100644 --- a/process/setup_config.py +++ b/process/setup_config.py @@ -1,287 +1,287 @@ -################################################################################ -# Script: setup_config.py -# Description: This script defines project parameters and prepare configuration file for all study regions -# All the cities should run this script first to create configuration file in json -# before running the sample point and aggregation scripts. - -# Two major outputs: -# 1. study region configuration json (e.g. odense.json; phoenix.json) -# 2. cities.json - -################################################################################ -import json -import time -import sys - -# define project parameters -project_year = 2020 # Year that the current indicators are targetting -osm_input_date = 20200813 # Date at which OSM download was current -gtfs_analysis_date = 20200827 # Date on which the GTFS data were analysed and output; yyyy-mm-dd string -output_date = 20200820 # Date at which the output data are (or were recorded as) prepared -study_buffer = 1600 # Study region buffer, to account for edge effects, in meters -neighbourhood_distance = 1000 # sausage buffer network size, in meters -accessibility_distance = 500 # distance within which to evaluate access -# minimum sampling threshold for each hexagons grid cell -# (sample points in hex grid cells with population less than this will be excluded -pop_min_threshold = 5 - -# list of cities that are needed to be set up (filtered based on input city command line arguments -cities = [ - {"cityname": "adelaide", "region": "au", "crs": "epsg:7845"}, - {"cityname": "auckland", "region": "nz", "crs": "epsg:2193"}, - {"cityname": "baltimore", "region": "us", "crs": "epsg:32618"}, - {"cityname": "bangkok", "region": "th", "crs": "epsg:32647"}, - {"cityname": "barcelona", "region": "es", "crs": "epsg:25831"}, - {"cityname": "belfast", "region": "gb", "crs": "epsg:29902"}, - {"cityname": "bern", "region": "ch", "crs": "epsg:32633"}, - {"cityname": "chennai", "region": "in", "crs": "epsg:32644"}, - {"cityname": "cologne", "region": "de", "crs": "epsg:32631"}, - {"cityname": "ghent", "region": "be", "crs": "epsg:32631"}, - {"cityname": "graz", "region": "at", "crs": "epsg:32633"}, - {"cityname": "hanoi", "region": "vn", "crs": "epsg:32648"}, - {"cityname": "hong_kong", "region": "hk", "crs": "epsg:32650","no_graphml_buffer":True}, - {"cityname": "lisbon", "region": "pt", "crs": "epsg:3763"}, - {"cityname": "maiduguri", "region": "ng", "crs": "epsg:32633"}, - {"cityname": "melbourne", "region": "au", "crs": "epsg:7845"}, - {"cityname": "mexico_city", "region": "mx", "crs": "epsg:32614"}, - {"cityname": "odense", "region": "dk", "crs": "epsg:32632"}, - {"cityname": "olomouc", "region": "cz", "crs": "epsg:32633"}, - {"cityname": "phoenix", "region": "us", "crs": "epsg:32612"}, - {"cityname": "sao_paulo", "region": "br", "crs": "epsg:32723"}, - {"cityname": "seattle", "region": "us", "crs": "epsg:32610"}, - {"cityname": "sydney", "region": "au", "crs": "epsg:7845"}, - {"cityname": "valencia", "region": "es", "crs": "epsg:25830"}, - {"cityname": "vic", "region": "es", "crs": "epsg:25831"}, -] - -if len(sys.argv) > 1: - input_cities = sys.argv[1:] - cities = [x for x in cities if x['cityname'] in input_cities] -else: - input_cities = [x['cityname'] for x in cities] - -# read in GTFS config -exec(open('./data/GTFS/gtfs_config.py').read()) -# filter GTFS to input city list -for city in [c for c in GTFS.keys() if c not in input_cities]: - del(GTFS[city]) - -# format GTFS date to yyyy-mm-dd format string -gtfs_analysis_date = f'{str(gtfs_analysis_date)[0:4]}-{str(gtfs_analysis_date)[4:6]}-{str(gtfs_analysis_date)[6:]}' -gtfs_gpkg = f'GTFS/gtfs_frequent_transit_headway_{gtfs_analysis_date}_python.gpkg' -# add GTFS layer for each city -for city in cities: - if len(GTFS[city['cityname']])>0: - cities[cities.index(city)]['gtfs_layer'] = f"{city['cityname']}_stops_headway_{GTFS[city['cityname']][-1]['start_date_mmdd']}_{GTFS[city['cityname']][-1]['end_date_mmdd']}" - else: - cities[cities.index(city)]['gtfs_layer'] = None - -field_lookup = { - 'point_id' :{'hex': '','all':''}, - 'hex_id' :{'hex': '','all':''}, - 'egd_ogc_fid' :{'hex': '','all':''}, - 'sp_nearest_node_fresh_food_market' :{'hex': '','all':''}, - 'sp_nearest_node_convenience' :{'hex': '','all':''}, - 'sp_nearest_node_pt_osm_any' :{'hex': '','all':''}, - 'sp_nearest_node_public_open_space_any' :{'hex': '','all':''}, - 'sp_nearest_node_public_open_space_large' :{'hex': '','all':''}, - 'sp_nearest_node_pt_gtfs_any' :{'hex': '','all':''}, - 'sp_nearest_node_pt_gtfs_freq_30' :{'hex': '','all':''}, - 'sp_nearest_node_pt_gtfs_freq_20' :{'hex': '','all':''}, - 'sp_access_fresh_food_market_binary' :{'hex':f'pct_access_{accessibility_distance}m_fresh_food_market_binary','all':''}, - 'sp_access_convenience_binary' :{'hex':f'pct_access_{accessibility_distance}m_convenience_binary','all':''}, - 'sp_access_pt_osm_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_osm_any_binary','all':''}, - 'sp_access_public_open_space_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_public_open_space_any_binary' ,'all':''}, - 'sp_access_public_open_space_large_binary':{'hex':f'pct_access_{accessibility_distance}m_public_open_space_large_binary','all':''}, - 'sp_access_pt_gtfs_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_gtfs_any_binary','all':''}, - 'sp_access_pt_gtfs_freq_30_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_gtfs_freq_30_binary','all':''}, - 'sp_access_pt_gtfs_freq_20_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_gtfs_freq_20_binary','all':''}, - 'sp_access_pt_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_any_binary','all':''}, - 'sp_local_nh_avg_pop_density' :{'hex': 'local_nh_population_density' ,'all':"all_cities_z_nh_population_density"}, - 'sp_local_nh_avg_intersection_density' :{'hex': 'local_nh_intersection_density' ,'all':"all_cities_z_nh_intersection_density"}, - 'sp_daily_living_score' :{'hex': 'local_daily_living' ,'all':"all_cities_z_daily_living"}, - 'sp_walkability_index' :{'hex': 'local_walkability' ,'all':"all_cities_walkability"} -} - -fieldNames_from_samplePoint = [x for x in field_lookup if field_lookup[x]['hex']!=''] -fieldNames2hex = [field_lookup[x]['hex'] for x in fieldNames_from_samplePoint] - -# cities aggregation data parameters -# these are parameters for all cities needed to generated output gpkg -cities_parameters = { - "output_folder": "data/output", - "input_folder": "data/input", - "samplepointResult": "samplePointsData", - "hex250": "pop_ghs_2015", - "urban_study_region": "urban_study_region", - "pop_est": "pop_est", - "output_hex_250m": "global_indicators_hex_250m.gpkg", - "global_indicators_city": "global_indicators_city.gpkg", -} - -# specify study region hex-level output indicators field name -# these are within-city variable names in global_indicators_hex_250m.gpkg -# ?? All identical keys and values --- this data structure may be redundant given code implementation? -basic_attributes = ["index","study_region","area_sqkm","pop_est","pop_per_sqkm","intersection_count","intersections_per_sqkm","urban_sample_point_count"] -hex_fieldNames = basic_attributes \ - + fieldNames2hex \ - + [field_lookup[x]['all'] for x in field_lookup if field_lookup[x]['all']!=''] \ - + ['geometry'] - -# specify between cities city-level output indicators field name -# these are between-city varaibles names in global_indicators_city.gpkg -city_fieldNames = basic_attributes[1:] \ - + [x.replace('local_nh_population','pop_nh_pop') \ - .replace('pct','pop_pct') \ - .replace('local','pop') \ - .replace('_z_','_pop_z_') \ - .replace('all_cities_walkability','all_cities_pop_walkability') \ - for x in hex_fieldNames if x not in basic_attributes] - -gpkgNames = {} -cities_config = {} - -for i in range(len(cities)): - city = cities[i]["cityname"] - region = cities[i]["region"] - - gpkgName = {city: f"{city}_{region}_{project_year}_{study_buffer}m_buffer_output{output_date}.gpkg"} - gpkgNames.update(gpkgName) - -cities_config = {"gpkgNames": gpkgNames} -cities_config.update(cities_parameters) -cities_config.update({"basic_attributes": basic_attributes}) -cities_config.update({"hex_fieldNames": hex_fieldNames}) -cities_config.update({"city_fieldNames": city_fieldNames}) - -if __name__ == "__main__": - # Generate study region configuration files - for i in range(len(cities)): - # generate dict of study region input datasource parameters - city = cities[i]["cityname"] - region = cities[i]["region"] - to_crs = cities[i]["crs"] - gpkg = f"input/{city}_{region}_{project_year}_{study_buffer}m_buffer.gpkg" - gpkg_out = f"output/{city}_{region}_{project_year}_{study_buffer}m_buffer_output{output_date}.gpkg" - if 'no_graphml_buffer' in cities[i] and cities[i]['no_graphml_buffer']: - # a city can be parameterised to not buffer graphml in exceptional circumstances --- e.g. Hong Kong - graphmlName = f"{city}_{region}_{project_year}_pedestrian_osm_{osm_input_date}.graphml" - graphmlProj_name = f"{city}_{region}_{project_year}_pedestrian_osm_{osm_input_date}_proj.graphml" - else: - graphmlName = f"{city}_{region}_{project_year}_{study_buffer}m_pedestrian_osm_{osm_input_date}.graphml" - graphmlProj_name = f"{city}_{region}_{project_year}_{study_buffer}m_pedestrian_osm_{osm_input_date}_proj.graphml" - city_config = f"""# Global Indicators project - -# Generated configuration file for {city.title()} -# {time.strftime("%Y-%m-%d")} - -config={{ - "study_region": "{city}", - "study_region_full": "{city}_{region}_{project_year}", - "region":"{region}", - "year":"{project_year}", - "to_crs": "{to_crs}", - "geopackagePath": '{gpkg}', - "geopackagePath_output": '{gpkg_out}', - "graphmlName": 'input/{graphmlName}', - "graphmlProj_name": 'input/{graphmlProj_name}', - "folder": "data", - "nodes_pop_intersect_density": "output/nodes_pop_intersect_density_{city}.csv", - "nearest_node_analyses":{{ - 'Open street map destinations':{{ - 'geopackage': "{gpkg_out}", # path relative to data directory - 'layers':['destinations'], - 'category_field':'dest_name', - 'categories': ['fresh_food_market','convenience','pt_any'], - 'filter_field': None, - 'filter_iterations': None, - 'output_names': ['fresh_food_market','convenience','pt_osm_any'], - 'notes': "The initial value for pt_any will be based on analysis using OSM data; this will later be copied to a seperate pt_any_osm result, and the final pt_any variable will be based on the 'best result' out of analysis using GTFS data (where available) and OSM data" - }}, - 'Public open space':{{ - 'geopackage': "{gpkg_out}", - 'layers':['aos_public_any_nodes_30m_line','aos_public_large_nodes_30m_line'], - 'category_field':None, - 'categories': [], - 'filter_field': None, - 'filter_iterations': None, - 'output_names':["public_open_space_any","public_open_space_large"], - 'notes':None - }}, - 'Public transport (GTFS)':{{ - 'geopackage': '{gtfs_gpkg}', - 'layers':{[cities[i]["gtfs_layer"]]}, - 'category_field':[], - 'categories': None, - 'filter_field': 'headway', - 'filter_iterations': [">=0","<=30","<=20"], - 'output_names':["pt_gtfs_any","pt_gtfs_freq_30","pt_gtfs_freq_20"], - 'notes':None - }} - }}, - "sample_point_analyses":{{ - # evaluate final PT access measure considered across both OSM or GTFS (which may be null) - 'Best PT (any) access score':{{ - 'sp_access_pt_any_binary':{{ - 'columns':['sp_access_pt_osm_any_binary', - 'sp_access_pt_gtfs_any_binary'], - 'formula':"max", - 'axis':1 - }} - }}, - # evaluate sum of binary scores, ignoring nulls - 'Daily living score':{{ - 'sp_daily_living_score':{{ - 'columns':['sp_access_fresh_food_market_binary', - 'sp_access_convenience_binary', - 'sp_access_pt_any_binary'], - 'formula':"sum", - 'axis':1 - }} - }}, - # evaluate sum of binary scores, ignoring nulls - 'Walkability index':{{ - 'sp_walkability_index':{{ - 'columns':['sp_daily_living_score', - 'sp_local_nh_avg_pop_density', - 'sp_local_nh_avg_intersection_density'], - 'formula':"sum_of_z_scores", - 'axis':0 - }} - }}, - }} - }} - - -parameters={{ - "samplePointsData_withoutNan": "samplePointsData_withoutNan", - "samplePoints": "urban_sample_points", - "destinations": "destinations", - "fresh_food_market": "Fresh Food / Market", - "convenience": "Convenience", - "PT": "Public transport stop (any)", # Note - this is OSM; GTFS and combination measures accuonted for elsewhere - "hex250": "pop_ghs_2015", - "urban_study_region": "urban_study_region", - "pos": "aos_public_any_nodes_30m_line", - "nodes": "nodes", - "edges": "edges", - "accessibility_distance": {accessibility_distance}, - "neighbourhood_distance": {neighbourhood_distance}, - "dropNan": "samplePointsData_droped_nan", - "tempLayer": "samplePointsData_pop_intersect_density", - "samplepointResult": "samplePointsData", - "population_density":"sp_local_nh_avg_pop_density", - "intersection_density":"sp_local_nh_avg_intersection_density", - "pop_min_threshold": {pop_min_threshold} -}}""" - - # Generate city-specific dated configuration script, - # including config and parameter dictionaries - with open(f"configuration/{city}.py", "w") as file: - file.write(city_config) - - # prepare cities configuration json file for aggregation - with open("configuration/cities.json", "w") as write_file: - json.dump(cities_config, write_file, indent=4) - - print(f"\nStudy region and all cities configuration files were generated for {len(input_cities)} regions: {', '.join(input_cities)}\n") +################################################################################ +# Script: setup_config.py +# Description: This script defines project parameters and prepare configuration file for all study regions +# All the cities should run this script first to create configuration file in json +# before running the sample point and aggregation scripts. + +# Two major outputs: +# 1. study region configuration json (e.g. odense.json; phoenix.json) +# 2. cities.json + +################################################################################ +import json +import time +import sys + +# define project parameters +project_year = 2020 # Year that the current indicators are targetting +osm_input_date = 20200813 # Date at which OSM download was current +gtfs_analysis_date = 20200827 # Date on which the GTFS data were analysed and output; yyyy-mm-dd string +output_date = 20200820 # Date at which the output data are (or were recorded as) prepared +study_buffer = 1600 # Study region buffer, to account for edge effects, in meters +neighbourhood_distance = 1000 # sausage buffer network size, in meters +accessibility_distance = 500 # distance within which to evaluate access +# minimum sampling threshold for each hexagons grid cell +# (sample points in hex grid cells with population less than this will be excluded +pop_min_threshold = 5 + +# list of cities that are needed to be set up (filtered based on input city command line arguments +cities = [ + {"cityname": "adelaide", "region": "au", "crs": "epsg:7845"}, + {"cityname": "auckland", "region": "nz", "crs": "epsg:2193"}, + {"cityname": "baltimore", "region": "us", "crs": "epsg:32618"}, + {"cityname": "bangkok", "region": "th", "crs": "epsg:32647"}, + {"cityname": "barcelona", "region": "es", "crs": "epsg:25831"}, + {"cityname": "belfast", "region": "gb", "crs": "epsg:29902"}, + {"cityname": "bern", "region": "ch", "crs": "epsg:32633"}, + {"cityname": "chennai", "region": "in", "crs": "epsg:32644"}, + {"cityname": "cologne", "region": "de", "crs": "epsg:32631"}, + {"cityname": "ghent", "region": "be", "crs": "epsg:32631"}, + {"cityname": "graz", "region": "at", "crs": "epsg:32633"}, + {"cityname": "hanoi", "region": "vn", "crs": "epsg:32648"}, + {"cityname": "hong_kong", "region": "hk", "crs": "epsg:32650","no_graphml_buffer":True}, + {"cityname": "lisbon", "region": "pt", "crs": "epsg:3763"}, + {"cityname": "maiduguri", "region": "ng", "crs": "epsg:32633"}, + {"cityname": "melbourne", "region": "au", "crs": "epsg:7845"}, + {"cityname": "mexico_city", "region": "mx", "crs": "epsg:32614"}, + {"cityname": "odense", "region": "dk", "crs": "epsg:32632"}, + {"cityname": "olomouc", "region": "cz", "crs": "epsg:32633"}, + {"cityname": "phoenix", "region": "us", "crs": "epsg:32612"}, + {"cityname": "sao_paulo", "region": "br", "crs": "epsg:32723"}, + {"cityname": "seattle", "region": "us", "crs": "epsg:32610"}, + {"cityname": "sydney", "region": "au", "crs": "epsg:7845"}, + {"cityname": "valencia", "region": "es", "crs": "epsg:25830"}, + {"cityname": "vic", "region": "es", "crs": "epsg:25831"}, +] + +if len(sys.argv) > 1: + input_cities = sys.argv[1:] + cities = [x for x in cities if x['cityname'] in input_cities] +else: + input_cities = [x['cityname'] for x in cities] + +# read in GTFS config +exec(open('./data/GTFS/gtfs_config.py').read()) +# filter GTFS to input city list +for city in [c for c in GTFS.keys() if c not in input_cities]: + del(GTFS[city]) + +# format GTFS date to yyyy-mm-dd format string +gtfs_analysis_date = f'{str(gtfs_analysis_date)[0:4]}-{str(gtfs_analysis_date)[4:6]}-{str(gtfs_analysis_date)[6:]}' +gtfs_gpkg = f'GTFS/gtfs_frequent_transit_headway_{gtfs_analysis_date}_python.gpkg' +# add GTFS layer for each city +for city in cities: + if len(GTFS[city['cityname']])>0: + cities[cities.index(city)]['gtfs_layer'] = f"{city['cityname']}_stops_headway_{GTFS[city['cityname']][-1]['start_date_mmdd']}_{GTFS[city['cityname']][-1]['end_date_mmdd']}" + else: + cities[cities.index(city)]['gtfs_layer'] = None + +field_lookup = { + 'point_id' :{'hex': '','all':''}, + 'hex_id' :{'hex': '','all':''}, + 'egd_ogc_fid' :{'hex': '','all':''}, + 'sp_nearest_node_fresh_food_market' :{'hex': '','all':''}, + 'sp_nearest_node_convenience' :{'hex': '','all':''}, + 'sp_nearest_node_pt_osm_any' :{'hex': '','all':''}, + 'sp_nearest_node_public_open_space_any' :{'hex': '','all':''}, + 'sp_nearest_node_public_open_space_large' :{'hex': '','all':''}, + 'sp_nearest_node_pt_gtfs_any' :{'hex': '','all':''}, + 'sp_nearest_node_pt_gtfs_freq_30' :{'hex': '','all':''}, + 'sp_nearest_node_pt_gtfs_freq_20' :{'hex': '','all':''}, + 'sp_access_fresh_food_market_binary' :{'hex':f'pct_access_{accessibility_distance}m_fresh_food_market_binary','all':''}, + 'sp_access_convenience_binary' :{'hex':f'pct_access_{accessibility_distance}m_convenience_binary','all':''}, + 'sp_access_pt_osm_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_osm_any_binary','all':''}, + 'sp_access_public_open_space_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_public_open_space_any_binary' ,'all':''}, + 'sp_access_public_open_space_large_binary':{'hex':f'pct_access_{accessibility_distance}m_public_open_space_large_binary','all':''}, + 'sp_access_pt_gtfs_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_gtfs_any_binary','all':''}, + 'sp_access_pt_gtfs_freq_30_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_gtfs_freq_30_binary','all':''}, + 'sp_access_pt_gtfs_freq_20_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_gtfs_freq_20_binary','all':''}, + 'sp_access_pt_any_binary' :{'hex':f'pct_access_{accessibility_distance}m_pt_any_binary','all':''}, + 'sp_local_nh_avg_pop_density' :{'hex': 'local_nh_population_density' ,'all':"all_cities_z_nh_population_density"}, + 'sp_local_nh_avg_intersection_density' :{'hex': 'local_nh_intersection_density' ,'all':"all_cities_z_nh_intersection_density"}, + 'sp_daily_living_score' :{'hex': 'local_daily_living' ,'all':"all_cities_z_daily_living"}, + 'sp_walkability_index' :{'hex': 'local_walkability' ,'all':"all_cities_walkability"} +} + +fieldNames_from_samplePoint = [x for x in field_lookup if field_lookup[x]['hex']!=''] +fieldNames2hex = [field_lookup[x]['hex'] for x in fieldNames_from_samplePoint] + +# cities aggregation data parameters +# these are parameters for all cities needed to generated output gpkg +cities_parameters = { + "output_folder": "data/output", + "input_folder": "data/input", + "samplepointResult": "samplePointsData", + "hex250": "pop_ghs_2015", + "urban_study_region": "urban_study_region", + "pop_est": "pop_est", + "output_hex_250m": "global_indicators_hex_250m.gpkg", + "global_indicators_city": "global_indicators_city.gpkg", +} + +# specify study region hex-level output indicators field name +# these are within-city variable names in global_indicators_hex_250m.gpkg +# ?? All identical keys and values --- this data structure may be redundant given code implementation? +basic_attributes = ["index","study_region","area_sqkm","pop_est","pop_per_sqkm","intersection_count","intersections_per_sqkm","urban_sample_point_count"] +hex_fieldNames = basic_attributes \ + + fieldNames2hex \ + + [field_lookup[x]['all'] for x in field_lookup if field_lookup[x]['all']!=''] \ + + ['geometry'] + +# specify between cities city-level output indicators field name +# these are between-city varaibles names in global_indicators_city.gpkg +city_fieldNames = basic_attributes[1:] \ + + [x.replace('local_nh_population','pop_nh_pop') \ + .replace('pct','pop_pct') \ + .replace('local','pop') \ + .replace('_z_','_pop_z_') \ + .replace('all_cities_walkability','all_cities_pop_walkability') \ + for x in hex_fieldNames if x not in basic_attributes] + +gpkgNames = {} +cities_config = {} + +for i in range(len(cities)): + city = cities[i]["cityname"] + region = cities[i]["region"] + + gpkgName = {city: f"{city}_{region}_{project_year}_{study_buffer}m_buffer_output{output_date}.gpkg"} + gpkgNames.update(gpkgName) + +cities_config = {"gpkgNames": gpkgNames} +cities_config.update(cities_parameters) +cities_config.update({"basic_attributes": basic_attributes}) +cities_config.update({"hex_fieldNames": hex_fieldNames}) +cities_config.update({"city_fieldNames": city_fieldNames}) + +if __name__ == "__main__": + # Generate study region configuration files + for i in range(len(cities)): + # generate dict of study region input datasource parameters + city = cities[i]["cityname"] + region = cities[i]["region"] + to_crs = cities[i]["crs"] + gpkg = f"input/{city}_{region}_{project_year}_{study_buffer}m_buffer.gpkg" + gpkg_out = f"output/{city}_{region}_{project_year}_{study_buffer}m_buffer_output{output_date}.gpkg" + if 'no_graphml_buffer' in cities[i] and cities[i]['no_graphml_buffer']: + # a city can be parameterised to not buffer graphml in exceptional circumstances --- e.g. Hong Kong + graphmlName = f"{city}_{region}_{project_year}_pedestrian_osm_{osm_input_date}.graphml" + graphmlProj_name = f"{city}_{region}_{project_year}_pedestrian_osm_{osm_input_date}_proj.graphml" + else: + graphmlName = f"{city}_{region}_{project_year}_{study_buffer}m_pedestrian_osm_{osm_input_date}.graphml" + graphmlProj_name = f"{city}_{region}_{project_year}_{study_buffer}m_pedestrian_osm_{osm_input_date}_proj.graphml" + city_config = f"""# Global Indicators project + +# Generated configuration file for {city.title()} +# {time.strftime("%Y-%m-%d")} + +config={{ + "study_region": "{city}", + "study_region_full": "{city}_{region}_{project_year}", + "region":"{region}", + "year":"{project_year}", + "to_crs": "{to_crs}", + "geopackagePath": '{gpkg}', + "geopackagePath_output": '{gpkg_out}', + "graphmlName": 'input/{graphmlName}', + "graphmlProj_name": 'input/{graphmlProj_name}', + "folder": "data", + "nodes_pop_intersect_density": "output/nodes_pop_intersect_density_{city}.csv", + "nearest_node_analyses":{{ + 'Open street map destinations':{{ + 'geopackage': "{gpkg_out}", # path relative to data directory + 'layers':['destinations'], + 'category_field':'dest_name', + 'categories': ['fresh_food_market','convenience','pt_any'], + 'filter_field': None, + 'filter_iterations': None, + 'output_names': ['fresh_food_market','convenience','pt_osm_any'], + 'notes': "The initial value for pt_any will be based on analysis using OSM data; this will later be copied to a seperate pt_any_osm result, and the final pt_any variable will be based on the 'best result' out of analysis using GTFS data (where available) and OSM data" + }}, + 'Public open space':{{ + 'geopackage': "{gpkg_out}", + 'layers':['aos_public_any_nodes_30m_line','aos_public_large_nodes_30m_line'], + 'category_field':None, + 'categories': [], + 'filter_field': None, + 'filter_iterations': None, + 'output_names':["public_open_space_any","public_open_space_large"], + 'notes':None + }}, + 'Public transport (GTFS)':{{ + 'geopackage': '{gtfs_gpkg}', + 'layers':{[cities[i]["gtfs_layer"]]}, + 'category_field':[], + 'categories': None, + 'filter_field': 'headway', + 'filter_iterations': [">=0","<=30","<=20"], + 'output_names':["pt_gtfs_any","pt_gtfs_freq_30","pt_gtfs_freq_20"], + 'notes':None + }} + }}, + "sample_point_analyses":{{ + # evaluate final PT access measure considered across both OSM or GTFS (which may be null) + 'Best PT (any) access score':{{ + 'sp_access_pt_any_binary':{{ + 'columns':['sp_access_pt_osm_any_binary', + 'sp_access_pt_gtfs_any_binary'], + 'formula':"max", + 'axis':1 + }} + }}, + # evaluate sum of binary scores, ignoring nulls + 'Daily living score':{{ + 'sp_daily_living_score':{{ + 'columns':['sp_access_fresh_food_market_binary', + 'sp_access_convenience_binary', + 'sp_access_pt_any_binary'], + 'formula':"sum", + 'axis':1 + }} + }}, + # evaluate sum of binary scores, ignoring nulls + 'Walkability index':{{ + 'sp_walkability_index':{{ + 'columns':['sp_daily_living_score', + 'sp_local_nh_avg_pop_density', + 'sp_local_nh_avg_intersection_density'], + 'formula':"sum_of_z_scores", + 'axis':0 + }} + }}, + }} + }} + + +parameters={{ + "samplePointsData_withoutNan": "samplePointsData_withoutNan", + "samplePoints": "urban_sample_points", + "destinations": "destinations", + "fresh_food_market": "Fresh Food / Market", + "convenience": "Convenience", + "PT": "Public transport stop (any)", # Note - this is OSM; GTFS and combination measures accuonted for elsewhere + "hex250": "pop_ghs_2015", + "urban_study_region": "urban_study_region", + "pos": "aos_public_any_nodes_30m_line", + "nodes": "nodes", + "edges": "edges", + "accessibility_distance": {accessibility_distance}, + "neighbourhood_distance": {neighbourhood_distance}, + "dropNan": "samplePointsData_droped_nan", + "tempLayer": "samplePointsData_pop_intersect_density", + "samplepointResult": "samplePointsData", + "population_density":"sp_local_nh_avg_pop_density", + "intersection_density":"sp_local_nh_avg_intersection_density", + "pop_min_threshold": {pop_min_threshold} +}}""" + + # Generate city-specific dated configuration script, + # including config and parameter dictionaries + with open(f"configuration/{city}.py", "w") as file: + file.write(city_config) + + # prepare cities configuration json file for aggregation + with open("configuration/cities.json", "w") as write_file: + json.dump(cities_config, write_file, indent=4) + + print(f"\nStudy region and all cities configuration files were generated for {len(input_cities)} regions: {', '.join(input_cities)}\n") diff --git a/process/setup_sp.py b/process/setup_sp.py index 87d3cef8..5c9cb461 100644 --- a/process/setup_sp.py +++ b/process/setup_sp.py @@ -1,393 +1,393 @@ -################################################################################ -# Module: setup_sp.py -# Description: this module contains functions to set up sample points stats within study regions - -################################################################################ - -import os - -import geopandas as gpd -import networkx as nx -import numpy as np -import pandana as pdna -import pandas as pd -from tqdm import tqdm -import osmnx as ox - -def read_proj_graphml(proj_graphml_filepath, ori_graphml_filepath, to_crs,undirected=True, retain_fields=None): - """ - Read a projected graph from local disk if exist, - otherwise, reproject origional graphml to the CRS appropriate for its geographic location, - and save the projected graph to local disk - - Parameters - ---------- - proj_graphml_filepath: string - the projected graphml filepath - ori_graphml_filepath: string - the original graphml filepath - to_crs: dict or string or pyproj.CRS - project to this CRS - undirected: bool (default: True) - make graph undirected - retain_edge_attributes = list (default: None) - explicitly retain only a subset of edge attributes, else keep all (default) - - Returns - ------- - networkx multidigraph - """ - # if the projected graphml file already exist in disk, then load it from the path - if os.path.isfile(proj_graphml_filepath): - print("Read network from disk.") - G_proj=ox.load_graphml(proj_graphml_filepath,int) - if undirected: - print(" - Ensure graph is undirected.") - if G_proj.is_directed(): - G_proj = G_proj.to_undirected() - return(G_proj) - - # else, read original study region graphml and reproject it - else: - print("Prepare network resources...") - print(" - Read network from disk.") - # load and project origional graphml from disk - G = ox.load_graphml(ori_graphml_filepath,int) - if retain_fields is not None: - print(" - Remove unnecessary key data from edges") - att_list = set([k for n in G.edges for k in G.edges[n].keys() if k not in ['osmid','length']]) - capture_output = [[d.pop(att, None) for att in att_list] - for n1, n2, d in tqdm(G.edges(data=True),desc=' '*18)] - del(capture_output) - print(" - Project graph") - G_proj = ox.project_graph(G, to_crs=to_crs) - if undirected: - print(" - Ensure graph is undirected.") - if G_proj.is_directed(): - G_proj = G_proj.to_undirected() - print(" - Save projected graphml to disk") - ox.save_graphml(G_proj, proj_graphml_filepath) - return(G_proj) - -def spatial_join_index_to_gdf(gdf, join_gdf, right_index_name,join_type='within'): - """ - Append to a geodataframe the named index of another using spatial join - - Parameters - ---------- - gdf: GeoDataFrame - join_gdf: GeoDataFrame - right_index_name: str (default: None) - join_tyoe: str (default 'within') - - Returns - ------- - GeoDataFrame - """ - gdf_columns = list(gdf.columns) - gdf = gpd.sjoin(gdf, join_gdf, how="left", op=join_type) - if right_index_name is not None: - gdf = gdf[gdf_columns+['index_right']] - gdf.columns = gdf_columns+[right_index_name] - return(gdf) - -def create_pdna_net(gdf_nodes, gdf_edges, predistance=500): - """ - Create pandana network to prepare for calculating the accessibility to destinations - The network is comprised of a set of nodes and edges. - - Parameters - ---------- - gdf_nodes: GeoDataFrame - gdf_edges: GeoDataFrame - predistance: int - the distance of search (in meters), default is 500 meters - - Returns - ------- - pandana network - """ - # Defines the x attribute for nodes in the network - gdf_nodes["x"] = gdf_nodes["geometry"].apply(lambda x: x.x) - # Defines the y attribute for nodes in the network (e.g. latitude) - gdf_nodes["y"] = gdf_nodes["geometry"].apply(lambda x: x.y) - # Defines the node id that begins an edge - gdf_edges["from"] = gdf_edges["u"].astype(np.int64) - # Defines the node id that ends an edge - gdf_edges["to"] = gdf_edges["v"].astype(np.int64) - # Define the distance based on OpenStreetMap edges - gdf_edges["length"] = gdf_edges["length"].astype(float) - - gdf_nodes["id"] = gdf_nodes["osmid"].astype(np.int64) - gdf_nodes.set_index("id", inplace=True, drop=False) - # Create the transportation network in the city - # Typical data would be distance based from OSM or travel time from GTFS transit data - net = pdna.Network(gdf_nodes["x"], gdf_nodes["y"], gdf_edges["from"], gdf_edges["to"], gdf_edges[["length"]]) - # Precomputes the range queries (the reachable nodes within this maximum distance) - # so that aggregations don’t perform the network queries unnecessarily - net.precompute(predistance + 10) - return net - - -def cal_dist_node_to_nearest_pois(gdf_poi, distance, network, category_field = None, categories = None, filter_field = None, filter_iterations = None,output_names=None,output_prefix=''): - """ - Calculate the distance from each node to the first nearest destination - within a given maximum search distance threshold - If the nearest destination is not within the distance threshold, then it will be coded as -999 - - Parameters - ---------- - gdf_poi: GeoDataFrame - GeoDataFrame of destination point-of-interest - distance: int - the maximum search distance - network: pandana network - category_field: str - a field which if supplied will be iterated over using values from 'categories' list (default: None) - categories : list - list of field names of categories found in category_field (default: None) - filter_field: str - a field which if supplied will be iterated over to filter the POI dataframe using a query informed by an expression found in the filter iteration list. Filters are only applied if a category has not been supplied (ie. use one or the other) (default: None) - filter_iterations : list - list of expressions to query using the filter_field (default: None) - output_names : list - list of names which are used to rename the outputs; entries must have corresponding order to categories or filter iterations if these are supplied (default: None) - output_prefix: str - option prefix to append to supplied output_names list (default: '') - - Returns - ------- - GeoDataFrame - """ - gdf_poi["x"] = gdf_poi["geometry"].apply(lambda x: x.x) - gdf_poi["y"] = gdf_poi["geometry"].apply(lambda x: x.y) - if category_field is not None and categories is not None: - # Calculate distances iterating over categories - appended_data = [] - # establish output names - if output_names is None: - output_names = categories - - output_names = [f'{output_prefix}{x}' for x in output_names] - # iterate over each destination category - for x in categories: - iteration = categories.index(x) - # initialize the destination point-of-interest category - # the positions are specified by the x and y columns (which are Pandas Series) - # at a max search distance for up to the first nearest points-of-interest - gdf_poi_filtered = gdf_poi.query(f"{category_field}=='{x}'") - if len(gdf_poi_filtered) > 0: - network.set_pois( - x, - distance, - 1, - gdf_poi_filtered["x"], - gdf_poi_filtered["y"], - ) - # return the distance to the first nearest destination category - # if zero destination is within the max search distance, then coded as -999 - dist = network.nearest_pois(distance, x, 1, -999) - - # change the index name corresponding to each destination name - dist.columns = dist.columns.astype(str) - dist.rename(columns={"1": output_names[categories.index(x)]}, inplace=True) - else: - dist == pd.DataFrame(index=network.node_ids, columns=output_names[categories.index(x)]) - - appended_data.append(dist) - # return a GeoDataFrame with distance to the nearest destination from each source node - gdf_poi_dist = pd.concat(appended_data, axis=1) - elif filter_field is not None and filter_iterations is not None: - # Calculate distances across filtered iterations - appended_data = [] - # establish output names - if output_names is None: - output_names = filter_iterations - - output_names = [f'{output_prefix}{x}' for x in output_names] - # iterate over each destination category - for x in filter_iterations: - # initialize the destination point-of-interest category - # the positions are specified by the x and y columns (which are Pandas Series) - # at a max search distance for up to the first nearest points-of-interest - gdf_poi_filtered = gdf_poi.query(f"{filter_field}{x}") - if len(gdf_poi_filtered) > 0: - network.set_pois( - x, - distance, - 1, - gdf_poi_filtered["x"], - gdf_poi_filtered["y"], - ) - # return the distance to the first nearest destination category - # if zero destination is within the max search distance, then coded as -999 - dist = network.nearest_pois(distance, x, 1, -999) - - # change the index name to match desired or default output - dist.columns = dist.columns.astype(str) - dist.rename(columns={"1": output_names[filter_iterations.index(x)]}, inplace=True) - else: - dist == pd.DataFrame(index=network.node_ids, columns=output_names[categories.index(x)]) - - appended_data.append(dist) - # return a GeoDataFrame with distance to the nearest destination from each source node - gdf_poi_dist = pd.concat(appended_data, axis=1) - else: - if output_names is None: - output_names = ['POI'] - - output_names = [f'{output_prefix}{x}' for x in output_names] - network.set_pois(output_names[0], distance, 1, gdf_poi["x"], gdf_poi["y"]) - gdf_poi_dist = network.nearest_pois(distance,output_names[0], 1, -999) - # change the index name to match desired or default output - gdf_poi_dist.columns = gdf_poi_dist.columns.astype(str) - gdf_poi_dist.rename(columns={"1": output_names[0]}, inplace=True) - - return gdf_poi_dist - - -def create_full_nodes( - samplePointsData, - gdf_nodes_simple, - gdf_nodes_poi_dist, - distance_names, - population_density, - intersection_density, -): - """ - Create long form working dataset of sample points to evaluate respective node distances and densities. - - This is achieved by first allocating sample points coincident with nodes their direct estimates, and then - through a sub-function process_distant_nodes() deriving estimates for sample points based on terminal nodes - of the edge segments on which they are located, accounting for respective distances. - - Parameters - ---------- - samplePointsData: GeoDataFrame - GeoDataFrame of sample points - gdf_nodes_simple: GeoDataFrame - GeoDataFrame with density records - gdf_nodes_poi_dist: GeoDataFrame - GeoDataFrame of distances to points of interest - distance_names: list - List of original distance field names - population_density: str - population density variable name - intersection_density: str - intersection density variable name - - Returns - ------- - GeoDataFrame - """ - print("Derive sample point estimates for accessibility and densities based on node distance relations") - simple_nodes = gdf_nodes_poi_dist.join(gdf_nodes_simple) - print("\t - match sample points whose locations coincide with intersections directly with intersection record data") - coincident_nodes = samplePointsData.query('n1_distance==0')[['n1']]\ - .rename({'n1':'node'},axis='columns')\ - .append(samplePointsData.query('n1_distance!=0 and n2_distance==0')[['n2']]\ - .rename({'n2':'node'},axis='columns'))\ - .join(simple_nodes, on="node", how="left")\ - [[x for x in simple_nodes.columns if x not in ['hex_id','geometry']]].copy() - distant_nodes = process_distant_nodes(samplePointsData,gdf_nodes_simple,gdf_nodes_poi_dist,distance_names,population_density,intersection_density) - full_nodes = coincident_nodes.append(distant_nodes).sort_index() - return full_nodes - -def process_distant_nodes( - samplePointsData, - gdf_nodes_simple, - gdf_nodes_poi_dist, - distance_names, - population_density, - intersection_density, -): - """ - Create long form working dataset of sample points to evaluate respective node distances and densities - - Parameters - ---------- - samplePointsData: GeoDataFrame - GeoDataFrame of sample points - gdf_nodes_simple: GeoDataFrame - GeoDataFrame with density records - gdf_nodes_poi_dist: GeoDataFrame - GeoDataFrame of distances to points of interest - distance_names: list - List of original distance field names - population_density: str - population density variable name - intersection_density: str - intersection density variable name - - Returns - ------- - GeoDataFrame - """ - print("\t - for sample points not co-located with intersections, derive estimates by:") - print("\t\t - accounting for distances") - distant_nodes = samplePointsData.query('n1_distance!=0 and n2_distance!=0')\ - [["n1", "n2", "n1_distance", "n2_distance"]].copy() - distant_nodes["nodes"] = distant_nodes.apply(lambda x: [[int(x.n1), x.n1_distance], [int(x.n2), x.n2_distance]], axis=1) - distant_nodes = distant_nodes[["nodes"]].explode("nodes") - distant_nodes[["node", "node_distance_m"]] = pd.DataFrame(distant_nodes.nodes.values.tolist(), index=distant_nodes.index) - distant_nodes = distant_nodes[["node", "node_distance_m"]].join(gdf_nodes_poi_dist, on="node", how="left") - distance_fields = [] - for d in distance_names: - distant_nodes[d] = distant_nodes[d] + distant_nodes["node_distance_m"] - distance_fields.append(d) - - distance_names = [x for x in distance_names if x in gdf_nodes_poi_dist.columns] - print("\t\t - calculating proximity-weighted average of density statistics for each sample point") - # define aggregation functions for per sample point estimates - # ie. we take - # - minimum of full distances - # - and weighted mean of densities - # The latter is so that if distance from two nodes for a point are 10m and 30m - # the weight of 10m is 0.75 and the weight of 30m is 0.25. - # ie. 1 - (10/(10+30)) = 0.75 , and 1 - (30/(10+30)) = 0.25 - # ie. the more proximal node is the dominant source of the density estimate, but the distal one still has - # some contribution to ensure smooth interpolation across sample points (ie. a 'best guess' at true value). - # This is not perfect; ideally the densities would be calculated for the sample points directly. - # But it is better than just assigning the value of the nearest node (which may be hundreds of metres away). - # - # An important exceptional case which needs to be accounted for is a sample point co-located with a node - # intersection which is the beginning and end of a cul-de-sac loop. In such a case, n1 and n2 are identical, - # and the distance to each is zero, which therefore results in a division by zero error. To resolve this issue, - # and a general rule of efficiency, if distance to any node is zero that nodes esimates shall be employed directly. - # This is why the weighting and full distance calculation is only considered for sample points with "distant nodes", - # and not those with "coincident nodes". - - node_weight_denominator = distant_nodes["node_distance_m"].groupby(distant_nodes.index).sum() - distant_nodes = distant_nodes[["node", "node_distance_m"] + distance_fields].join(node_weight_denominator, - how="left", rsuffix="_denominator") - distant_nodes["density_weight"] = 1 - (distant_nodes["node_distance_m"] / distant_nodes["node_distance_m_denominator"]) - # join up full nodes with density fields - distant_nodes = distant_nodes.join(gdf_nodes_simple[[population_density, intersection_density]], on="node", how="left") - distant_nodes[population_density] = distant_nodes[population_density] * distant_nodes.density_weight - distant_nodes[intersection_density] = distant_nodes[intersection_density] * distant_nodes.density_weight - new_densities = [population_density, intersection_density] - agg_functions = dict( - zip(distance_fields + new_densities, ["min"] * len(distance_fields) + ["sum"] * len(new_densities)) - ) - distant_nodes = distant_nodes.groupby(distant_nodes.index).agg(agg_functions) - return(distant_nodes) - - -def split_list(alist, wanted_parts=1): - """ - split list - - Parameters - ---------- - alist: list - the split list - wanted_parts: int - the number of parts (default: {1}) - - Returns - ------- - list - """ - length = len(alist) - # return all parts in a list, like [[],[],[]] - return [alist[i * length // wanted_parts : (i + 1) * length // wanted_parts] for i in range(wanted_parts)] +################################################################################ +# Module: setup_sp.py +# Description: this module contains functions to set up sample points stats within study regions + +################################################################################ + +import os + +import geopandas as gpd +import networkx as nx +import numpy as np +import pandana as pdna +import pandas as pd +from tqdm import tqdm +import osmnx as ox + +def read_proj_graphml(proj_graphml_filepath, ori_graphml_filepath, to_crs,undirected=True, retain_fields=None): + """ + Read a projected graph from local disk if exist, + otherwise, reproject origional graphml to the CRS appropriate for its geographic location, + and save the projected graph to local disk + + Parameters + ---------- + proj_graphml_filepath: string + the projected graphml filepath + ori_graphml_filepath: string + the original graphml filepath + to_crs: dict or string or pyproj.CRS + project to this CRS + undirected: bool (default: True) + make graph undirected + retain_edge_attributes = list (default: None) + explicitly retain only a subset of edge attributes, else keep all (default) + + Returns + ------- + networkx multidigraph + """ + # if the projected graphml file already exist in disk, then load it from the path + if os.path.isfile(proj_graphml_filepath): + print("Read network from disk.") + G_proj=ox.load_graphml(proj_graphml_filepath,int) + if undirected: + print(" - Ensure graph is undirected.") + if G_proj.is_directed(): + G_proj = G_proj.to_undirected() + return(G_proj) + + # else, read original study region graphml and reproject it + else: + print("Prepare network resources...") + print(" - Read network from disk.") + # load and project origional graphml from disk + G = ox.load_graphml(ori_graphml_filepath,int) + if retain_fields is not None: + print(" - Remove unnecessary key data from edges") + att_list = set([k for n in G.edges for k in G.edges[n].keys() if k not in ['osmid','length']]) + capture_output = [[d.pop(att, None) for att in att_list] + for n1, n2, d in tqdm(G.edges(data=True),desc=' '*18)] + del(capture_output) + print(" - Project graph") + G_proj = ox.project_graph(G, to_crs=to_crs) + if undirected: + print(" - Ensure graph is undirected.") + if G_proj.is_directed(): + G_proj = G_proj.to_undirected() + print(" - Save projected graphml to disk") + ox.save_graphml(G_proj, proj_graphml_filepath) + return(G_proj) + +def spatial_join_index_to_gdf(gdf, join_gdf, right_index_name,join_type='within'): + """ + Append to a geodataframe the named index of another using spatial join + + Parameters + ---------- + gdf: GeoDataFrame + join_gdf: GeoDataFrame + right_index_name: str (default: None) + join_tyoe: str (default 'within') + + Returns + ------- + GeoDataFrame + """ + gdf_columns = list(gdf.columns) + gdf = gpd.sjoin(gdf, join_gdf, how="left", op=join_type) + if right_index_name is not None: + gdf = gdf[gdf_columns+['index_right']] + gdf.columns = gdf_columns+[right_index_name] + return(gdf) + +def create_pdna_net(gdf_nodes, gdf_edges, predistance=500): + """ + Create pandana network to prepare for calculating the accessibility to destinations + The network is comprised of a set of nodes and edges. + + Parameters + ---------- + gdf_nodes: GeoDataFrame + gdf_edges: GeoDataFrame + predistance: int + the distance of search (in meters), default is 500 meters + + Returns + ------- + pandana network + """ + # Defines the x attribute for nodes in the network + gdf_nodes["x"] = gdf_nodes["geometry"].apply(lambda x: x.x) + # Defines the y attribute for nodes in the network (e.g. latitude) + gdf_nodes["y"] = gdf_nodes["geometry"].apply(lambda x: x.y) + # Defines the node id that begins an edge + gdf_edges["from"] = gdf_edges["u"].astype(np.int64) + # Defines the node id that ends an edge + gdf_edges["to"] = gdf_edges["v"].astype(np.int64) + # Define the distance based on OpenStreetMap edges + gdf_edges["length"] = gdf_edges["length"].astype(float) + + gdf_nodes["id"] = gdf_nodes["osmid"].astype(np.int64) + gdf_nodes.set_index("id", inplace=True, drop=False) + # Create the transportation network in the city + # Typical data would be distance based from OSM or travel time from GTFS transit data + net = pdna.Network(gdf_nodes["x"], gdf_nodes["y"], gdf_edges["from"], gdf_edges["to"], gdf_edges[["length"]]) + # Precomputes the range queries (the reachable nodes within this maximum distance) + # so that aggregations don’t perform the network queries unnecessarily + net.precompute(predistance + 10) + return net + + +def cal_dist_node_to_nearest_pois(gdf_poi, distance, network, category_field = None, categories = None, filter_field = None, filter_iterations = None,output_names=None,output_prefix=''): + """ + Calculate the distance from each node to the first nearest destination + within a given maximum search distance threshold + If the nearest destination is not within the distance threshold, then it will be coded as -999 + + Parameters + ---------- + gdf_poi: GeoDataFrame + GeoDataFrame of destination point-of-interest + distance: int + the maximum search distance + network: pandana network + category_field: str + a field which if supplied will be iterated over using values from 'categories' list (default: None) + categories : list + list of field names of categories found in category_field (default: None) + filter_field: str + a field which if supplied will be iterated over to filter the POI dataframe using a query informed by an expression found in the filter iteration list. Filters are only applied if a category has not been supplied (ie. use one or the other) (default: None) + filter_iterations : list + list of expressions to query using the filter_field (default: None) + output_names : list + list of names which are used to rename the outputs; entries must have corresponding order to categories or filter iterations if these are supplied (default: None) + output_prefix: str + option prefix to append to supplied output_names list (default: '') + + Returns + ------- + GeoDataFrame + """ + gdf_poi["x"] = gdf_poi["geometry"].apply(lambda x: x.x) + gdf_poi["y"] = gdf_poi["geometry"].apply(lambda x: x.y) + if category_field is not None and categories is not None: + # Calculate distances iterating over categories + appended_data = [] + # establish output names + if output_names is None: + output_names = categories + + output_names = [f'{output_prefix}{x}' for x in output_names] + # iterate over each destination category + for x in categories: + iteration = categories.index(x) + # initialize the destination point-of-interest category + # the positions are specified by the x and y columns (which are Pandas Series) + # at a max search distance for up to the first nearest points-of-interest + gdf_poi_filtered = gdf_poi.query(f"{category_field}=='{x}'") + if len(gdf_poi_filtered) > 0: + network.set_pois( + x, + distance, + 1, + gdf_poi_filtered["x"], + gdf_poi_filtered["y"], + ) + # return the distance to the first nearest destination category + # if zero destination is within the max search distance, then coded as -999 + dist = network.nearest_pois(distance, x, 1, -999) + + # change the index name corresponding to each destination name + dist.columns = dist.columns.astype(str) + dist.rename(columns={"1": output_names[categories.index(x)]}, inplace=True) + else: + dist == pd.DataFrame(index=network.node_ids, columns=output_names[categories.index(x)]) + + appended_data.append(dist) + # return a GeoDataFrame with distance to the nearest destination from each source node + gdf_poi_dist = pd.concat(appended_data, axis=1) + elif filter_field is not None and filter_iterations is not None: + # Calculate distances across filtered iterations + appended_data = [] + # establish output names + if output_names is None: + output_names = filter_iterations + + output_names = [f'{output_prefix}{x}' for x in output_names] + # iterate over each destination category + for x in filter_iterations: + # initialize the destination point-of-interest category + # the positions are specified by the x and y columns (which are Pandas Series) + # at a max search distance for up to the first nearest points-of-interest + gdf_poi_filtered = gdf_poi.query(f"{filter_field}{x}") + if len(gdf_poi_filtered) > 0: + network.set_pois( + x, + distance, + 1, + gdf_poi_filtered["x"], + gdf_poi_filtered["y"], + ) + # return the distance to the first nearest destination category + # if zero destination is within the max search distance, then coded as -999 + dist = network.nearest_pois(distance, x, 1, -999) + + # change the index name to match desired or default output + dist.columns = dist.columns.astype(str) + dist.rename(columns={"1": output_names[filter_iterations.index(x)]}, inplace=True) + else: + dist == pd.DataFrame(index=network.node_ids, columns=output_names[categories.index(x)]) + + appended_data.append(dist) + # return a GeoDataFrame with distance to the nearest destination from each source node + gdf_poi_dist = pd.concat(appended_data, axis=1) + else: + if output_names is None: + output_names = ['POI'] + + output_names = [f'{output_prefix}{x}' for x in output_names] + network.set_pois(output_names[0], distance, 1, gdf_poi["x"], gdf_poi["y"]) + gdf_poi_dist = network.nearest_pois(distance,output_names[0], 1, -999) + # change the index name to match desired or default output + gdf_poi_dist.columns = gdf_poi_dist.columns.astype(str) + gdf_poi_dist.rename(columns={"1": output_names[0]}, inplace=True) + + return gdf_poi_dist + + +def create_full_nodes( + samplePointsData, + gdf_nodes_simple, + gdf_nodes_poi_dist, + distance_names, + population_density, + intersection_density, +): + """ + Create long form working dataset of sample points to evaluate respective node distances and densities. + + This is achieved by first allocating sample points coincident with nodes their direct estimates, and then + through a sub-function process_distant_nodes() deriving estimates for sample points based on terminal nodes + of the edge segments on which they are located, accounting for respective distances. + + Parameters + ---------- + samplePointsData: GeoDataFrame + GeoDataFrame of sample points + gdf_nodes_simple: GeoDataFrame + GeoDataFrame with density records + gdf_nodes_poi_dist: GeoDataFrame + GeoDataFrame of distances to points of interest + distance_names: list + List of original distance field names + population_density: str + population density variable name + intersection_density: str + intersection density variable name + + Returns + ------- + GeoDataFrame + """ + print("Derive sample point estimates for accessibility and densities based on node distance relations") + simple_nodes = gdf_nodes_poi_dist.join(gdf_nodes_simple) + print("\t - match sample points whose locations coincide with intersections directly with intersection record data") + coincident_nodes = samplePointsData.query('n1_distance==0')[['n1']]\ + .rename({'n1':'node'},axis='columns')\ + .append(samplePointsData.query('n1_distance!=0 and n2_distance==0')[['n2']]\ + .rename({'n2':'node'},axis='columns'))\ + .join(simple_nodes, on="node", how="left")\ + [[x for x in simple_nodes.columns if x not in ['hex_id','geometry']]].copy() + distant_nodes = process_distant_nodes(samplePointsData,gdf_nodes_simple,gdf_nodes_poi_dist,distance_names,population_density,intersection_density) + full_nodes = coincident_nodes.append(distant_nodes).sort_index() + return full_nodes + +def process_distant_nodes( + samplePointsData, + gdf_nodes_simple, + gdf_nodes_poi_dist, + distance_names, + population_density, + intersection_density, +): + """ + Create long form working dataset of sample points to evaluate respective node distances and densities + + Parameters + ---------- + samplePointsData: GeoDataFrame + GeoDataFrame of sample points + gdf_nodes_simple: GeoDataFrame + GeoDataFrame with density records + gdf_nodes_poi_dist: GeoDataFrame + GeoDataFrame of distances to points of interest + distance_names: list + List of original distance field names + population_density: str + population density variable name + intersection_density: str + intersection density variable name + + Returns + ------- + GeoDataFrame + """ + print("\t - for sample points not co-located with intersections, derive estimates by:") + print("\t\t - accounting for distances") + distant_nodes = samplePointsData.query('n1_distance!=0 and n2_distance!=0')\ + [["n1", "n2", "n1_distance", "n2_distance"]].copy() + distant_nodes["nodes"] = distant_nodes.apply(lambda x: [[int(x.n1), x.n1_distance], [int(x.n2), x.n2_distance]], axis=1) + distant_nodes = distant_nodes[["nodes"]].explode("nodes") + distant_nodes[["node", "node_distance_m"]] = pd.DataFrame(distant_nodes.nodes.values.tolist(), index=distant_nodes.index) + distant_nodes = distant_nodes[["node", "node_distance_m"]].join(gdf_nodes_poi_dist, on="node", how="left") + distance_fields = [] + for d in distance_names: + distant_nodes[d] = distant_nodes[d] + distant_nodes["node_distance_m"] + distance_fields.append(d) + + distance_names = [x for x in distance_names if x in gdf_nodes_poi_dist.columns] + print("\t\t - calculating proximity-weighted average of density statistics for each sample point") + # define aggregation functions for per sample point estimates + # ie. we take + # - minimum of full distances + # - and weighted mean of densities + # The latter is so that if distance from two nodes for a point are 10m and 30m + # the weight of 10m is 0.75 and the weight of 30m is 0.25. + # ie. 1 - (10/(10+30)) = 0.75 , and 1 - (30/(10+30)) = 0.25 + # ie. the more proximal node is the dominant source of the density estimate, but the distal one still has + # some contribution to ensure smooth interpolation across sample points (ie. a 'best guess' at true value). + # This is not perfect; ideally the densities would be calculated for the sample points directly. + # But it is better than just assigning the value of the nearest node (which may be hundreds of metres away). + # + # An important exceptional case which needs to be accounted for is a sample point co-located with a node + # intersection which is the beginning and end of a cul-de-sac loop. In such a case, n1 and n2 are identical, + # and the distance to each is zero, which therefore results in a division by zero error. To resolve this issue, + # and a general rule of efficiency, if distance to any node is zero that nodes esimates shall be employed directly. + # This is why the weighting and full distance calculation is only considered for sample points with "distant nodes", + # and not those with "coincident nodes". + + node_weight_denominator = distant_nodes["node_distance_m"].groupby(distant_nodes.index).sum() + distant_nodes = distant_nodes[["node", "node_distance_m"] + distance_fields].join(node_weight_denominator, + how="left", rsuffix="_denominator") + distant_nodes["density_weight"] = 1 - (distant_nodes["node_distance_m"] / distant_nodes["node_distance_m_denominator"]) + # join up full nodes with density fields + distant_nodes = distant_nodes.join(gdf_nodes_simple[[population_density, intersection_density]], on="node", how="left") + distant_nodes[population_density] = distant_nodes[population_density] * distant_nodes.density_weight + distant_nodes[intersection_density] = distant_nodes[intersection_density] * distant_nodes.density_weight + new_densities = [population_density, intersection_density] + agg_functions = dict( + zip(distance_fields + new_densities, ["min"] * len(distance_fields) + ["sum"] * len(new_densities)) + ) + distant_nodes = distant_nodes.groupby(distant_nodes.index).agg(agg_functions) + return(distant_nodes) + + +def split_list(alist, wanted_parts=1): + """ + split list + + Parameters + ---------- + alist: list + the split list + wanted_parts: int + the number of parts (default: {1}) + + Returns + ------- + list + """ + length = len(alist) + # return all parts in a list, like [[],[],[]] + return [alist[i * length // wanted_parts : (i + 1) * length // wanted_parts] for i in range(wanted_parts)] diff --git a/process/sp.py b/process/sp.py index 41fc1dfe..d32e35c1 100644 --- a/process/sp.py +++ b/process/sp.py @@ -1,314 +1,314 @@ -################################################################################ -# Script: sp.py -# Description: This script is for preparing all the fields for sample points -# All the cities should run this script first to get the pre-prepared sample points -# before running the aggregation. - -# Two major outputs: -# 1. average population and intersection density per sample sample point -# 2. accessibility, dailyliving and walkability score per sample point - -import os -import sys -import time -from tqdm import tqdm -import networkx as nx -import fiona -import geopandas as gpd -import numpy as np -import pandas as pd - -import osmnx as ox -import setup_sp as ssp - -if __name__ == "__main__": - # use the script from command line, change directory to '/process' folder - # then 'python sp.py [city]' to process city-specific indicators - startTime = time.time() - today = time.strftime("%Y-%m-%d") - # get the work directory - dirname = os.path.abspath("") - - assumptions = """ - This code assumes the name of a known city to be passed as an argument, however none was provided. - - Configuration python files containing the dictionaries 'config' and 'parameters' are written - to the ./configuration directory for cities through use of the set up configuration script setup_config.py, - like so: - python setup_config.py auckland - - or, to generate set up scripts for all cities - python setup_config.py - """ - - # load city-specific configuration file - if len(sys.argv) < 2: - print(assumptions) - sys.exit() - - city = sys.argv[1] - configuration_file = f'{dirname}/configuration/{city}.py' - try: - exec(open(configuration_file).read()) - except Exception as e: - print(f"Failed to read configuration file {configuration_file}.\n\n{assumptions}") - print(e) - - # output the processing city name to users - print(f"\nGlobal indicators project {today}\n\nProcess city: {config['study_region'].title()}\n") - - # geopackage path where to read all the required layers - gpkgPath = os.path.join(dirname, config["folder"], config["geopackagePath"]) - - # define original graphml filepath - ori_graphml_filepath = os.path.join(dirname, config["folder"], config["graphmlName"]) - - if not os.path.exists(gpkgPath): - # check if these files are located in the study region folder (ie. output location for pre-processing) - alt_dir = f"./data/study_region/{config['study_region_full']}" - alt_sources = (f"{alt_dir}/{os.path.basename(gpkgPath)}", - f"{alt_dir}/{os.path.basename(ori_graphml_filepath)}") - if sum([os.path.exists(x) for x in alt_sources])==2: - gpkgPath,ori_graphml_filepath = alt_sources - else: - sys.exit(f"\nThe required input files ({os.path.basename(gpkgPath)} and {os.path.basename(gpkgPath)}) " - f"do not appear to exist in either the ./data/input folder or {alt_dir} folder. " - "Please ensure both of these file exist in one of these locations, or that the input " - "configuration is correctly re-parameterised to recognise an alternative location.") - - # geopackage path where to save processing layers - gpkgPath_output = os.path.join(dirname, config["folder"], config["geopackagePath_output"]) - - # Check if geopackage has a -wal file associated with it - # if so it is likely open and locked for use by another software package (e.g. QGIS) - # and will be unable to be used - for required_gpkg in [gpkgPath,gpkgPath_output]: - if os.path.exists(f'{required_gpkg}-wal'): - sys.exit( - f"\nIt appears that the required geopackage {required_gpkg} may be open in another software package, " - "due to the presence of a Write Ahead Logging (WAL) file associated with it. Please ensure that the input " - "geopackage is not being used in any other software before continuing, and that the file " - f"'{required_gpkg}-wal' is not present before continuing." - ) - - # read projected graphml filepath - proj_graphml_filepath = os.path.join(dirname, config["folder"], config["graphmlProj_name"]) - - G_proj = ssp.read_proj_graphml(proj_graphml_filepath, - ori_graphml_filepath, - config["to_crs"], - undirected=True, - retain_fields=['osmid','length']) - - # copy input geopackage to output geopackage, if not already exist - input_layers = fiona.listlayers(gpkgPath) - if not os.path.isfile(gpkgPath_output): - print("Initialise sample point output geopackage as a copy of input geopackage") - os.system(f'cp {gpkgPath} {gpkgPath_output}') - output_layers = input_layers - else: - output_layers = fiona.listlayers(gpkgPath_output) - print("Sample point geopackage exists.") - for layer in [x for x in input_layers if x not in output_layers]: - print(f" - updating output geopackage to contain the layer '{layer}'") - gpkgPath_input = gpd.read_file(gpkgPath, layer=layer) - gpkgPath_input.to_file(gpkgPath_output, layer=layer, driver="GPKG") - - # read hexagon layer of the city from disk, the hexagon layer is 250m*250m - # it should contain population estimates and intersection information - hexes = gpd.read_file(gpkgPath_output, layer=parameters["hex250"]) - hexes.set_index('index',inplace=True) - - print("\nFirst pass node-level neighbourhood analysis (Calculate average population and intersection density " - "for each intersection node in study regions, taking mean values from distinct hexes within " - "neighbourhood buffer distance)") - nh_startTime = time.time() - population_density = parameters["population_density"] - intersection_density = parameters["intersection_density"] - nh_fields_points = [population_density,intersection_density] - # read from disk if exist - if 'nodes_pop_intersect_density' in output_layers: - print(" - Read population and intersection density from local file.") - gdf_nodes_simple = gpd.read_file(gpkgPath_output, layer='nodes_pop_intersect_density') - gdf_nodes_simple.set_index('osmid', inplace=True) - else: - print(" - Set up simple nodes") - gdf_nodes = ox.graph_to_gdfs(G_proj, nodes=True, edges=False) - gdf_nodes.osmid = gdf_nodes.osmid.astype(int) - gdf_nodes = gdf_nodes.drop_duplicates(subset="osmid") - gdf_nodes.set_index('osmid', inplace=True) - # associate nodes with hex_id - gdf_nodes = ssp.spatial_join_index_to_gdf(gdf_nodes, hexes, right_index_name='hex_id',join_type='within') - # keep only the unique node id column - gdf_nodes = gdf_nodes[["hex_id","geometry"]] - # drop any nodes which are na (they are outside the buffered study region and not of interest) - gdf_nodes_simple = gdf_nodes[~gdf_nodes.hex_id.isna()].copy() - gdf_nodes = gdf_nodes[["hex_id"]] - - if len([x for x in nh_fields_points if x not in gdf_nodes_simple.columns]) > 0: - # Calculate average population and intersection density for each intersection node in study regions - # taking mean values from distinct hexes within neighbourhood buffer distance - nh_fields_hex = ['pop_per_sqkm','intersections_per_sqkm'] - # Create a dictionary of edge index and integer values of length - # The length attribute was saved as string, so must be recast to use as weight - # The units are meters, so the decimal precision is unnecessary (error is larger than this; meter is adequate) - weight = dict(zip([k for k in G_proj.edges],[int(float(G_proj.edges[k]['length'])) for k in G_proj.edges])) - - # Add a new edge attribute using the integer weights - nx.set_edge_attributes(G_proj, weight, 'weight') - - # run all pairs analysis - total_nodes = len(gdf_nodes_simple) - nh_distance = parameters["neighbourhood_distance"] - print(f' - Generate {nh_distance}m neighbourhoods for nodes (All pairs Dijkstra shortest path analysis)') - all_pairs_d = pd.DataFrame([(k,v.keys()) for k,v in tqdm(nx.all_pairs_dijkstra_path_length(G_proj,1000,'weight'), - total=total_nodes,unit='nodes',desc=' '*18)], - columns = ['osmid','nodes']).set_index('osmid') - # extract results - print(' - Summarise attributes (average value from unique associated hexes within nh buffer distance)...') - - result = pd.DataFrame([tuple(hexes.loc[gdf_nodes.loc[all_pairs_d.loc[n].nodes,'hex_id'].dropna().unique(), - nh_fields_hex].mean().values) for index,n in - tqdm(np.ndenumerate(gdf_nodes_simple.index.values),total=total_nodes,desc=' '*18)], - columns = nh_fields_points, - index=gdf_nodes_simple.index.values) - gdf_nodes_simple = gdf_nodes_simple.join(result) - - # save in geopackage (so output files are all kept together) - gdf_nodes_simple.to_file(gpkgPath_output, layer='nodes_pop_intersect_density', driver="GPKG") - - print(f"Time taken to calculate or load city local neighbourhood statistics: {(time.time() - nh_startTime)/60:02g} mins") - - # Calculate accessibility to POI (fresh_food_market,convenience,pt,pso) and - # walkability for sample points steps as follow: - # 1. using pandana packadge to calculate distance to access from sample - # points to destinations (daily living destinations, public open space) - # 2. calculate accessibiity score per sample point: transform accessibility - # distance to binary measure: 1 if access <= 500m, 0 otherwise - # 3. calculate daily living score by summing the accessibiity scores to all - # POIs (excluding pos) - # 4. calculate walkability score per sample point: get zscores for daily - # living accessibility, populaiton density and intersections population_density; - # sum these three zscores at sample point level - - print("\nCalculate assessbility to POIs.") - # read accessibility distance from configuration file, which is 500m - - # create the pandana network, use network nodes and edges - gdf_nodes, gdf_edges = ox.graph_to_gdfs(G_proj) - network = ssp.create_pdna_net(gdf_nodes, gdf_edges, predistance=parameters["accessibility_distance"]) - - distance_results = {} - print("\nCalculating nearest node analyses ...") - for analysis_key in config['nearest_node_analyses']: - print(f'\n\t- {analysis_key}') - analysis = config['nearest_node_analyses'][analysis_key] - layer_analysis_count = len(analysis['layers']) - for layer in analysis['layers']: - if layer is not None: - output_names = analysis['output_names'].copy() - if layer_analysis_count > 1 and layer_analysis_count==len(analysis['output_names']): - # assume that output names correspond to layers, and refresh per analysis - output_names = [output_names[analysis['layers'].index(layer)]] - - print(f'\t\t{output_names}') - gdf_poi = gpd.read_file(f"data/{analysis['geopackage']}", layer = layer) - distance_results[f'{analysis}_{layer}'] = ssp.cal_dist_node_to_nearest_pois(gdf_poi, - parameters["accessibility_distance"], - network, - category_field = analysis['category_field'], - categories = analysis['categories'], - filter_field = analysis['filter_field'], - filter_iterations = analysis['filter_iterations'], - output_names = output_names, - output_prefix = 'sp_nearest_node_') - else: - # create null results --- e.g. for GTFS analyses where no layer exists - distance_results[f'{analysis_key}_{layer}'] = pd.DataFrame(index=gdf_nodes.index, - columns=[f'sp_nearest_node_{x}' for x in analysis['output_names']]) - - # concatenate analysis dataframes into one - gdf_nodes_poi_dist = pd.concat([gdf_nodes]+[distance_results[x] for x in distance_results], axis=1) - - # set index of gdf_nodes_poi_dist, using 'osmid' as the index, and remove other unnecessary columns - gdf_nodes_poi_dist.set_index("osmid",inplace=True) - unnecessary_columns = [x for x in - ["geometry", "id", "lat", "lon", "y", "x", "highway", "ref"] - if x in gdf_nodes_poi_dist.columns] - gdf_nodes_poi_dist.drop(unnecessary_columns,axis=1, inplace=True, errors="ignore") - - # replace -999 values (meaning no destination reached in less than 500 metres) as nan - gdf_nodes_poi_dist = round(gdf_nodes_poi_dist, 0).replace(-999, np.nan).astype("Int64") - - # read sample points from disk (in city-specific geopackage) - samplePointsData = gpd.read_file(gpkgPath_output, layer=parameters["samplePoints"]) - - # create 'hex_id' for sample point, if it not exists - if "hex_id" not in samplePointsData.columns: - samplePointsData = ssp.spatial_join_index_to_gdf(samplePointsData, hexes, right_index_name='hex_id',join_type='within') - - print("Restrict sample points to those not located in hexagons with a population below " - f"the minimum threshold value ({parameters['pop_min_threshold']})..."), - below_minimum_pop_hex_ids = list(hexes.query(f'pop_est < {parameters["pop_min_threshold"]}').index.values) - sample_point_length_pre_discard = len(samplePointsData) - samplePointsData = samplePointsData[~samplePointsData.hex_id.isin(below_minimum_pop_hex_ids)] - sample_point_length_post_discard = len(samplePointsData) - print(f" {sample_point_length_pre_discard - sample_point_length_post_discard} sample points discarded, " - f"leaving {sample_point_length_post_discard} remaining.") - - print("Restrict sample points to those with two associated sample nodes..."), - sample_point_length_pre_discard = len(samplePointsData) - samplePointsData = samplePointsData.query(f"n1 in {list(gdf_nodes_simple.index.values)} " - f"and n2 in {list(gdf_nodes_simple.index.values)}") - sample_point_length_post_discard = len(samplePointsData) - print(f" {sample_point_length_pre_discard - sample_point_length_post_discard} sample points discarded, " - f"leaving {sample_point_length_post_discard} remaining.") - - samplePointsData.set_index("point_id", inplace=True) - - distance_names = list(gdf_nodes_poi_dist.columns) - - # Estimate full distance to destinations for sample points - full_nodes = ssp.create_full_nodes( - samplePointsData, - gdf_nodes_simple, - gdf_nodes_poi_dist, - distance_names, - population_density, - intersection_density, - ) - - samplePointsData = samplePointsData[["hex_id", "edge_ogc_fid", "geometry"]].join(full_nodes, how="left") - - # create binary distances evaluated against accessibility distance - binary_names = [f"{x.replace('nearest_node','access')}_binary" for x in distance_names] - samplePointsData[binary_names] = (samplePointsData[distance_names] <= parameters['accessibility_distance']) \ - .astype("Int64").fillna(0) - - print("Calculating sample point specific analyses ...") - # Defined in generated config file, e.g. daily living score, walkability index, etc - for analysis in config['sample_point_analyses']: - print(f"\t - {analysis}") - for var in config['sample_point_analyses'][analysis]: - columns = config['sample_point_analyses'][analysis][var]['columns'] - formula = config['sample_point_analyses'][analysis][var]['formula'] - axis = config['sample_point_analyses'][analysis][var]['axis'] - if formula == "sum": - samplePointsData[var] = samplePointsData[columns].sum(axis=axis) - if formula == "max": - samplePointsData[var] = samplePointsData[columns].max(axis=axis) - if formula == "sum_of_z_scores": - samplePointsData[var] = ((samplePointsData[columns] - samplePointsData[columns].mean()) \ - / samplePointsData[columns].std()).sum(axis=1) - - # hex_id and edge_ogc_fid are integers - samplePointsData[samplePointsData.columns[0:2]] = samplePointsData[samplePointsData.columns[0:2]].astype(int) - # remaining non-geometry fields are float - samplePointsData[samplePointsData.columns[3:]] = samplePointsData[samplePointsData.columns[3:]].astype(float) - print("Save to geopackage...") - # save the sample points with all the desired results to a new layer in geopackage - samplePointsData = samplePointsData.reset_index() - samplePointsData.to_file(gpkgPath_output, layer=parameters["samplepointResult"], driver="GPKG") - - endTime = time.time() - startTime - print("Total time is : {:.2f} minutes".format(endTime / 60)) +################################################################################ +# Script: sp.py +# Description: This script is for preparing all the fields for sample points +# All the cities should run this script first to get the pre-prepared sample points +# before running the aggregation. + +# Two major outputs: +# 1. average population and intersection density per sample sample point +# 2. accessibility, dailyliving and walkability score per sample point + +import os +import sys +import time +from tqdm import tqdm +import networkx as nx +import fiona +import geopandas as gpd +import numpy as np +import pandas as pd + +import osmnx as ox +import setup_sp as ssp + +if __name__ == "__main__": + # use the script from command line, change directory to '/process' folder + # then 'python sp.py [city]' to process city-specific indicators + startTime = time.time() + today = time.strftime("%Y-%m-%d") + # get the work directory + dirname = os.path.abspath("") + + assumptions = """ + This code assumes the name of a known city to be passed as an argument, however none was provided. + + Configuration python files containing the dictionaries 'config' and 'parameters' are written + to the ./configuration directory for cities through use of the set up configuration script setup_config.py, + like so: + python setup_config.py auckland + + or, to generate set up scripts for all cities + python setup_config.py + """ + + # load city-specific configuration file + if len(sys.argv) < 2: + print(assumptions) + sys.exit() + + city = sys.argv[1] + configuration_file = f'{dirname}/configuration/{city}.py' + try: + exec(open(configuration_file).read()) + except Exception as e: + print(f"Failed to read configuration file {configuration_file}.\n\n{assumptions}") + print(e) + + # output the processing city name to users + print(f"\nGlobal indicators project {today}\n\nProcess city: {config['study_region'].title()}\n") + + # geopackage path where to read all the required layers + gpkgPath = os.path.join(dirname, config["folder"], config["geopackagePath"]) + + # define original graphml filepath + ori_graphml_filepath = os.path.join(dirname, config["folder"], config["graphmlName"]) + + if not os.path.exists(gpkgPath): + # check if these files are located in the study region folder (ie. output location for pre-processing) + alt_dir = f"./data/study_region/{config['study_region_full']}" + alt_sources = (f"{alt_dir}/{os.path.basename(gpkgPath)}", + f"{alt_dir}/{os.path.basename(ori_graphml_filepath)}") + if sum([os.path.exists(x) for x in alt_sources])==2: + gpkgPath,ori_graphml_filepath = alt_sources + else: + sys.exit(f"\nThe required input files ({os.path.basename(gpkgPath)} and {os.path.basename(gpkgPath)}) " + f"do not appear to exist in either the ./data/input folder or {alt_dir} folder. " + "Please ensure both of these file exist in one of these locations, or that the input " + "configuration is correctly re-parameterised to recognise an alternative location.") + + # geopackage path where to save processing layers + gpkgPath_output = os.path.join(dirname, config["folder"], config["geopackagePath_output"]) + + # Check if geopackage has a -wal file associated with it + # if so it is likely open and locked for use by another software package (e.g. QGIS) + # and will be unable to be used + for required_gpkg in [gpkgPath,gpkgPath_output]: + if os.path.exists(f'{required_gpkg}-wal'): + sys.exit( + f"\nIt appears that the required geopackage {required_gpkg} may be open in another software package, " + "due to the presence of a Write Ahead Logging (WAL) file associated with it. Please ensure that the input " + "geopackage is not being used in any other software before continuing, and that the file " + f"'{required_gpkg}-wal' is not present before continuing." + ) + + # read projected graphml filepath + proj_graphml_filepath = os.path.join(dirname, config["folder"], config["graphmlProj_name"]) + + G_proj = ssp.read_proj_graphml(proj_graphml_filepath, + ori_graphml_filepath, + config["to_crs"], + undirected=True, + retain_fields=['osmid','length']) + + # copy input geopackage to output geopackage, if not already exist + input_layers = fiona.listlayers(gpkgPath) + if not os.path.isfile(gpkgPath_output): + print("Initialise sample point output geopackage as a copy of input geopackage") + os.system(f'cp {gpkgPath} {gpkgPath_output}') + output_layers = input_layers + else: + output_layers = fiona.listlayers(gpkgPath_output) + print("Sample point geopackage exists.") + for layer in [x for x in input_layers if x not in output_layers]: + print(f" - updating output geopackage to contain the layer '{layer}'") + gpkgPath_input = gpd.read_file(gpkgPath, layer=layer) + gpkgPath_input.to_file(gpkgPath_output, layer=layer, driver="GPKG") + + # read hexagon layer of the city from disk, the hexagon layer is 250m*250m + # it should contain population estimates and intersection information + hexes = gpd.read_file(gpkgPath_output, layer=parameters["hex250"]) + hexes.set_index('index',inplace=True) + + print("\nFirst pass node-level neighbourhood analysis (Calculate average population and intersection density " + "for each intersection node in study regions, taking mean values from distinct hexes within " + "neighbourhood buffer distance)") + nh_startTime = time.time() + population_density = parameters["population_density"] + intersection_density = parameters["intersection_density"] + nh_fields_points = [population_density,intersection_density] + # read from disk if exist + if 'nodes_pop_intersect_density' in output_layers: + print(" - Read population and intersection density from local file.") + gdf_nodes_simple = gpd.read_file(gpkgPath_output, layer='nodes_pop_intersect_density') + gdf_nodes_simple.set_index('osmid', inplace=True) + else: + print(" - Set up simple nodes") + gdf_nodes = ox.graph_to_gdfs(G_proj, nodes=True, edges=False) + gdf_nodes.osmid = gdf_nodes.osmid.astype(int) + gdf_nodes = gdf_nodes.drop_duplicates(subset="osmid") + gdf_nodes.set_index('osmid', inplace=True) + # associate nodes with hex_id + gdf_nodes = ssp.spatial_join_index_to_gdf(gdf_nodes, hexes, right_index_name='hex_id',join_type='within') + # keep only the unique node id column + gdf_nodes = gdf_nodes[["hex_id","geometry"]] + # drop any nodes which are na (they are outside the buffered study region and not of interest) + gdf_nodes_simple = gdf_nodes[~gdf_nodes.hex_id.isna()].copy() + gdf_nodes = gdf_nodes[["hex_id"]] + + if len([x for x in nh_fields_points if x not in gdf_nodes_simple.columns]) > 0: + # Calculate average population and intersection density for each intersection node in study regions + # taking mean values from distinct hexes within neighbourhood buffer distance + nh_fields_hex = ['pop_per_sqkm','intersections_per_sqkm'] + # Create a dictionary of edge index and integer values of length + # The length attribute was saved as string, so must be recast to use as weight + # The units are meters, so the decimal precision is unnecessary (error is larger than this; meter is adequate) + weight = dict(zip([k for k in G_proj.edges],[int(float(G_proj.edges[k]['length'])) for k in G_proj.edges])) + + # Add a new edge attribute using the integer weights + nx.set_edge_attributes(G_proj, weight, 'weight') + + # run all pairs analysis + total_nodes = len(gdf_nodes_simple) + nh_distance = parameters["neighbourhood_distance"] + print(f' - Generate {nh_distance}m neighbourhoods for nodes (All pairs Dijkstra shortest path analysis)') + all_pairs_d = pd.DataFrame([(k,v.keys()) for k,v in tqdm(nx.all_pairs_dijkstra_path_length(G_proj,1000,'weight'), + total=total_nodes,unit='nodes',desc=' '*18)], + columns = ['osmid','nodes']).set_index('osmid') + # extract results + print(' - Summarise attributes (average value from unique associated hexes within nh buffer distance)...') + + result = pd.DataFrame([tuple(hexes.loc[gdf_nodes.loc[all_pairs_d.loc[n].nodes,'hex_id'].dropna().unique(), + nh_fields_hex].mean().values) for index,n in + tqdm(np.ndenumerate(gdf_nodes_simple.index.values),total=total_nodes,desc=' '*18)], + columns = nh_fields_points, + index=gdf_nodes_simple.index.values) + gdf_nodes_simple = gdf_nodes_simple.join(result) + + # save in geopackage (so output files are all kept together) + gdf_nodes_simple.to_file(gpkgPath_output, layer='nodes_pop_intersect_density', driver="GPKG") + + print(f"Time taken to calculate or load city local neighbourhood statistics: {(time.time() - nh_startTime)/60:02g} mins") + + # Calculate accessibility to POI (fresh_food_market,convenience,pt,pso) and + # walkability for sample points steps as follow: + # 1. using pandana packadge to calculate distance to access from sample + # points to destinations (daily living destinations, public open space) + # 2. calculate accessibiity score per sample point: transform accessibility + # distance to binary measure: 1 if access <= 500m, 0 otherwise + # 3. calculate daily living score by summing the accessibiity scores to all + # POIs (excluding pos) + # 4. calculate walkability score per sample point: get zscores for daily + # living accessibility, populaiton density and intersections population_density; + # sum these three zscores at sample point level + + print("\nCalculate assessbility to POIs.") + # read accessibility distance from configuration file, which is 500m + + # create the pandana network, use network nodes and edges + gdf_nodes, gdf_edges = ox.graph_to_gdfs(G_proj) + network = ssp.create_pdna_net(gdf_nodes, gdf_edges, predistance=parameters["accessibility_distance"]) + + distance_results = {} + print("\nCalculating nearest node analyses ...") + for analysis_key in config['nearest_node_analyses']: + print(f'\n\t- {analysis_key}') + analysis = config['nearest_node_analyses'][analysis_key] + layer_analysis_count = len(analysis['layers']) + for layer in analysis['layers']: + if layer is not None: + output_names = analysis['output_names'].copy() + if layer_analysis_count > 1 and layer_analysis_count==len(analysis['output_names']): + # assume that output names correspond to layers, and refresh per analysis + output_names = [output_names[analysis['layers'].index(layer)]] + + print(f'\t\t{output_names}') + gdf_poi = gpd.read_file(f"data/{analysis['geopackage']}", layer = layer) + distance_results[f'{analysis}_{layer}'] = ssp.cal_dist_node_to_nearest_pois(gdf_poi, + parameters["accessibility_distance"], + network, + category_field = analysis['category_field'], + categories = analysis['categories'], + filter_field = analysis['filter_field'], + filter_iterations = analysis['filter_iterations'], + output_names = output_names, + output_prefix = 'sp_nearest_node_') + else: + # create null results --- e.g. for GTFS analyses where no layer exists + distance_results[f'{analysis_key}_{layer}'] = pd.DataFrame(index=gdf_nodes.index, + columns=[f'sp_nearest_node_{x}' for x in analysis['output_names']]) + + # concatenate analysis dataframes into one + gdf_nodes_poi_dist = pd.concat([gdf_nodes]+[distance_results[x] for x in distance_results], axis=1) + + # set index of gdf_nodes_poi_dist, using 'osmid' as the index, and remove other unnecessary columns + gdf_nodes_poi_dist.set_index("osmid",inplace=True) + unnecessary_columns = [x for x in + ["geometry", "id", "lat", "lon", "y", "x", "highway", "ref"] + if x in gdf_nodes_poi_dist.columns] + gdf_nodes_poi_dist.drop(unnecessary_columns,axis=1, inplace=True, errors="ignore") + + # replace -999 values (meaning no destination reached in less than 500 metres) as nan + gdf_nodes_poi_dist = round(gdf_nodes_poi_dist, 0).replace(-999, np.nan).astype("Int64") + + # read sample points from disk (in city-specific geopackage) + samplePointsData = gpd.read_file(gpkgPath_output, layer=parameters["samplePoints"]) + + # create 'hex_id' for sample point, if it not exists + if "hex_id" not in samplePointsData.columns: + samplePointsData = ssp.spatial_join_index_to_gdf(samplePointsData, hexes, right_index_name='hex_id',join_type='within') + + print("Restrict sample points to those not located in hexagons with a population below " + f"the minimum threshold value ({parameters['pop_min_threshold']})..."), + below_minimum_pop_hex_ids = list(hexes.query(f'pop_est < {parameters["pop_min_threshold"]}').index.values) + sample_point_length_pre_discard = len(samplePointsData) + samplePointsData = samplePointsData[~samplePointsData.hex_id.isin(below_minimum_pop_hex_ids)] + sample_point_length_post_discard = len(samplePointsData) + print(f" {sample_point_length_pre_discard - sample_point_length_post_discard} sample points discarded, " + f"leaving {sample_point_length_post_discard} remaining.") + + print("Restrict sample points to those with two associated sample nodes..."), + sample_point_length_pre_discard = len(samplePointsData) + samplePointsData = samplePointsData.query(f"n1 in {list(gdf_nodes_simple.index.values)} " + f"and n2 in {list(gdf_nodes_simple.index.values)}") + sample_point_length_post_discard = len(samplePointsData) + print(f" {sample_point_length_pre_discard - sample_point_length_post_discard} sample points discarded, " + f"leaving {sample_point_length_post_discard} remaining.") + + samplePointsData.set_index("point_id", inplace=True) + + distance_names = list(gdf_nodes_poi_dist.columns) + + # Estimate full distance to destinations for sample points + full_nodes = ssp.create_full_nodes( + samplePointsData, + gdf_nodes_simple, + gdf_nodes_poi_dist, + distance_names, + population_density, + intersection_density, + ) + + samplePointsData = samplePointsData[["hex_id", "edge_ogc_fid", "geometry"]].join(full_nodes, how="left") + + # create binary distances evaluated against accessibility distance + binary_names = [f"{x.replace('nearest_node','access')}_binary" for x in distance_names] + samplePointsData[binary_names] = (samplePointsData[distance_names] <= parameters['accessibility_distance']) \ + .astype("Int64").fillna(0) + + print("Calculating sample point specific analyses ...") + # Defined in generated config file, e.g. daily living score, walkability index, etc + for analysis in config['sample_point_analyses']: + print(f"\t - {analysis}") + for var in config['sample_point_analyses'][analysis]: + columns = config['sample_point_analyses'][analysis][var]['columns'] + formula = config['sample_point_analyses'][analysis][var]['formula'] + axis = config['sample_point_analyses'][analysis][var]['axis'] + if formula == "sum": + samplePointsData[var] = samplePointsData[columns].sum(axis=axis) + if formula == "max": + samplePointsData[var] = samplePointsData[columns].max(axis=axis) + if formula == "sum_of_z_scores": + samplePointsData[var] = ((samplePointsData[columns] - samplePointsData[columns].mean()) \ + / samplePointsData[columns].std()).sum(axis=1) + + # hex_id and edge_ogc_fid are integers + samplePointsData[samplePointsData.columns[0:2]] = samplePointsData[samplePointsData.columns[0:2]].astype(int) + # remaining non-geometry fields are float + samplePointsData[samplePointsData.columns[3:]] = samplePointsData[samplePointsData.columns[3:]].astype(float) + print("Save to geopackage...") + # save the sample points with all the desired results to a new layer in geopackage + samplePointsData = samplePointsData.reset_index() + samplePointsData.to_file(gpkgPath_output, layer=parameters["samplepointResult"], driver="GPKG") + + endTime = time.time() - startTime + print("Total time is : {:.2f} minutes".format(endTime / 60)) diff --git a/readme.md b/readme.md index 7873367f..84ea39d2 100644 --- a/readme.md +++ b/readme.md @@ -1,50 +1,50 @@ -# global-indicators - -A open-source tool in python to compute pedestrian accessibility indicators for cities worldwide using open data, such as OpenStreetMap (OSM), the Global Human Settlement Layer (GHSL), and GTFS feeds (where available). - -This tool presents a generalized method to measure pedestrian accessibility indicators within- and between-city at both city scale and high-resolution grid level. The methodology and the open data approach developed in this research can be expanded to many cities worldwide to support local policy making towards healthy and sustainable living environments. - -The process scripts enable computation of the following indicators of pedestrian accessibility: -1. Urban area in square kilometers -2. Population size and population density -3. Street connectivity: intersections per square kilometer -4. Access to destinations: population access within 500 meters walking distance to: - - a supermarkets - - a convenience store - - any public open space (e.g. parks) - - any public transport stop (any mode) -5. Daily living score (within and across cities) -6. Walkability index (within and across cities) - -## Documentation -Please refer to the documentation folder readme for more information about this repository. - -# How to set up and get started? - -1. Install [Git](https://git-scm.com/downloads) and [Docker](https://www.docker.com/products/docker-desktop) -1. Git clone https://github.com/gboeing/global-indicators.git, or fork the repo and then git clone a local copy to your machine. For help on this, please refer to the [GitHub Guides](https://guides.github.com/). -1. In your command prompt / terminal window, change directory to the **global-indicators** folder. Pull new updates from the upstream repository, run: - ``` - git pull upstream master - ``` -1. Set up analysis environment container, run: - ``` - docker pull gboeing/global-indicators:latest - ``` -2. Then, check **process** folder for more detail script running process - -# How to contribute - -#### If you want to contribute to a feature: - - - post your proposal on the [issue tracker](https://github.com/gboeing/global-indicators/issues) - - fork the repo, make your change (adhering to existing coding, commenting, and docstring styles) - - Create your feature branch: `git checkout -b my-new-feature` - - Commit your changes: `git commit -am 'Add some feature'` - - Push to the branch: `git push origin my-new-feature` - - Submit a pull request. - -#### If you've found an error: - - - check the [issues](https://github.com/gboeing/global-indicators/issues) first - - open an new issue in the [issue tracker](https://github.com/gboeing/global-indicators/issues) filling out all sections of the template, including a minimal working example or screenshots so others can independently and completely reproduce the problem +# global-indicators + +A open-source tool in python to compute pedestrian accessibility indicators for cities worldwide using open data, such as OpenStreetMap (OSM), the Global Human Settlement Layer (GHSL), and GTFS feeds (where available). + +This tool presents a generalized method to measure pedestrian accessibility indicators within- and between-city at both city scale and high-resolution grid level. The methodology and the open data approach developed in this research can be expanded to many cities worldwide to support local policy making towards healthy and sustainable living environments. + +The process scripts enable computation of the following indicators of pedestrian accessibility: +1. Urban area in square kilometers +2. Population size and population density +3. Street connectivity: intersections per square kilometer +4. Access to destinations: population access within 500 meters walking distance to: + - a supermarkets + - a convenience store + - any public open space (e.g. parks) + - any public transport stop (any mode) +5. Daily living score (within and across cities) +6. Walkability index (within and across cities) + +## Documentation +Please refer to the documentation folder readme for more information about this repository. + +# How to set up and get started? + +1. Install [Git](https://git-scm.com/downloads) and [Docker](https://www.docker.com/products/docker-desktop) +1. Git clone https://github.com/gboeing/global-indicators.git, or fork the repo and then git clone a local copy to your machine. For help on this, please refer to the [GitHub Guides](https://guides.github.com/). +1. In your command prompt / terminal window, change directory to the **global-indicators** folder. Pull new updates from the upstream repository, run: + ``` + git pull upstream master + ``` +1. Set up analysis environment container, run: + ``` + docker pull gboeing/global-indicators:latest + ``` +2. Then, check **process** folder for more detail script running process + +# How to contribute + +#### If you want to contribute to a feature: + + - post your proposal on the [issue tracker](https://github.com/gboeing/global-indicators/issues) + - fork the repo, make your change (adhering to existing coding, commenting, and docstring styles) + - Create your feature branch: `git checkout -b my-new-feature` + - Commit your changes: `git commit -am 'Add some feature'` + - Push to the branch: `git push origin my-new-feature` + - Submit a pull request. + +#### If you've found an error: + + - check the [issues](https://github.com/gboeing/global-indicators/issues) first + - open an new issue in the [issue tracker](https://github.com/gboeing/global-indicators/issues) filling out all sections of the template, including a minimal working example or screenshots so others can independently and completely reproduce the problem diff --git a/validation/configuration/belfast.json b/validation/configuration/belfast.json index fbccbdb0..07feeadc 100644 --- a/validation/configuration/belfast.json +++ b/validation/configuration/belfast.json @@ -1,9 +1,9 @@ -{ - "study_region" : "belfast", - "osm_graphml_path" : "../data/belfast/belfast_gb_2019_10000m_all_osm_20190902.graphml", - "osm_buffer_gpkg_path" : "../data/belfast/belfast_gb_2019_1600m_buffer.gpkg", - "official_streets_gpkg_path": "../data/belfast/Belfast_City_Council_Area_Street_Network/", - "official_dests_filepath" : "../data/belfast/Restaurant_and_Food_Related/", - "destinations_column" : "", - "destinations_values" : [""] -} +{ + "study_region" : "belfast", + "osm_graphml_path" : "../data/belfast/belfast_gb_2019_10000m_all_osm_20190902.graphml", + "osm_buffer_gpkg_path" : "../data/belfast/belfast_gb_2019_1600m_buffer.gpkg", + "official_streets_gpkg_path": "../data/belfast/Belfast_City_Council_Area_Street_Network/", + "official_dests_filepath" : "../data/belfast/Restaurant_and_Food_Related/", + "destinations_column" : "", + "destinations_values" : [""] +} diff --git a/validation/configuration/hong_kong.json b/validation/configuration/hong_kong.json index 42296de3..5a161357 100644 --- a/validation/configuration/hong_kong.json +++ b/validation/configuration/hong_kong.json @@ -1,9 +1,9 @@ -{ - "study_region" : "hong_kong", - "osm_graphml_path" : "../data/hong_kong/hong_kong_hk_2019_10000m_all_osm_20190902.graphml", - "osm_buffer_gpkg_path" : "../data/hong_kong/hong_kong_hk_2019_1600m_buffer.gpkg", - "official_streets_gpkg_path": "../data/hong_kong/hk_centerline/", - "official_dests_filepath" : "", - "destinations_column" : "", - "destinations_values" : [""] -} +{ + "study_region" : "hong_kong", + "osm_graphml_path" : "../data/hong_kong/hong_kong_hk_2019_10000m_all_osm_20190902.graphml", + "osm_buffer_gpkg_path" : "../data/hong_kong/hong_kong_hk_2019_1600m_buffer.gpkg", + "official_streets_gpkg_path": "../data/hong_kong/hk_centerline/", + "official_dests_filepath" : "", + "destinations_column" : "", + "destinations_values" : [""] +} diff --git a/validation/configuration/olomouc.json b/validation/configuration/olomouc.json index d338d6e7..e0bee475 100644 --- a/validation/configuration/olomouc.json +++ b/validation/configuration/olomouc.json @@ -1,9 +1,9 @@ -{ - "study_region" : "olomouc", - "osm_graphml_path" : "../data/olomouc/olomouc_cz_2019_10000m_pedestrian_osm_20190902.graphml", - "osm_buffer_gpkg_path" : "../data/olomouc/olomouc_cz_2019_1600m_buffer.gpkg", - "official_streets_gpkg_path": "../data/olomouc/olomouc_street_network_epsg5514.gpkg", - "official_dests_filepath" : "../data/olomouc/olomouc_supermarkets_2018/", - "destinations_column" : "OBJECTID", - "destinations_values" : ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63"] -} +{ + "study_region" : "olomouc", + "osm_graphml_path" : "../data/olomouc/olomouc_cz_2019_10000m_pedestrian_osm_20190902.graphml", + "osm_buffer_gpkg_path" : "../data/olomouc/olomouc_cz_2019_1600m_buffer.gpkg", + "official_streets_gpkg_path": "../data/olomouc/olomouc_street_network_epsg5514.gpkg", + "official_dests_filepath" : "../data/olomouc/olomouc_supermarkets_2018/", + "destinations_column" : "OBJECTID", + "destinations_values" : ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63"] +} diff --git a/validation/configuration/sao_paulo.json b/validation/configuration/sao_paulo.json index a5e484cb..f03a3d54 100644 --- a/validation/configuration/sao_paulo.json +++ b/validation/configuration/sao_paulo.json @@ -1,9 +1,9 @@ -{ - "study_region" : "sao_paulo", - "osm_graphml_path" : "", - "osm_buffer_gpkg_path" : "../data/sao_paulo/sao_paulo_br_2019_1600m_buffer.gpkg", - "official_streets_gpkg_path": "", - "official_dests_filepath" : "../data/sao_paulo/SP_Freshfood_merged/", - "destinations_column" : "eq_classe", - "destinations_values" : ["MERCADOS MUNICIPAIS", "SACOLÃO"] -} +{ + "study_region" : "sao_paulo", + "osm_graphml_path" : "", + "osm_buffer_gpkg_path" : "../data/sao_paulo/sao_paulo_br_2019_1600m_buffer.gpkg", + "official_streets_gpkg_path": "", + "official_dests_filepath" : "../data/sao_paulo/SP_Freshfood_merged/", + "destinations_column" : "eq_classe", + "destinations_values" : ["MERCADOS MUNICIPAIS", "SACOLÃO"] +} diff --git a/validation/destination/destination_validation.py b/validation/destination/destination_validation.py index a486e654..2395a9f5 100644 --- a/validation/destination/destination_validation.py +++ b/validation/destination/destination_validation.py @@ -1,340 +1,340 @@ -import json -import os - -import geopandas as gpd -import matplotlib.pyplot as plt -import pandas as pd - -import osmnx as ox - -# configure script -cities = ["olomouc", "sao_paulo"] -dest_buffer_dists = [10, 50] -indicators_filepath = "./indicators.csv" -figure_filepath_city = "./fig/city_destination-comparison-{city}.png" -figure_filepath_core = "./fig/core_destination-comparison-{city}.png" - -if not os.path.exists("./fig/"): - os.makedirs("./fig/") - - -def load_data(osm_buffer_gpkg_path, official_dests_filepath, destinations_column, destinations_values): - """ - Load the city destinations and study boundary. - - Parameters - ---------- - osm_buffer_gpkg_path : str - path to the buffered study area geopackage - official_dests_filepath : str - path to the official destinations shapefile - destinations_column : str - column name containing categories of food-related destinations - destinations_values : str - acceptable values for categories of food-related destinations - - Returns - ------- - study_area, geopackage, gdf_osm_destinations, gdf_official_destinations : tuple - the polygon composed of square kilometers that is the city's study area, - the OSM derived dataset - the destinations sourced from OSM, - the destinations from the official data sources - """ - - # load the study area boundary as a shapely (multi)polygon - gdf_study_area = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") - study_area = gdf_study_area["geometry"].iloc[0] - print(ox.ts(), "loaded study area boundary") - - # load the entire geopackage - geopackage = gpd.read_file(osm_buffer_gpkg_path) - - # load the official destinations shapefile - # retain only rows with desired values in the destinations column - gdf_official_destinations = gpd.read_file(official_dests_filepath) - mask = gdf_official_destinations[destinations_column].isin(destinations_values) - gdf_official_destinations = gdf_official_destinations[mask] - print(ox.ts(), "loaded and filtered official destinations shapefile") - - # load the osm destinations shapefile - gdf_osm = gpd.read_file(osm_buffer_gpkg_path, layer="destinations") - gdf_osm_destinations = gdf_osm[gdf_osm["dest_name"] == "fresh_food_market"] - print(ox.ts(), "loaded osm destinations shapefile") - - # project the data to a common crs - crs = gdf_study_area.crs - if geopackage.crs != crs: - geopackage = geopackage.to_crs(crs) - print(ox.ts(), "projected geopackage") - if gdf_official_destinations.crs != crs: - gdf_official_destinations = gdf_official_destinations.to_crs(crs) - print(ox.ts(), "projected official destinations") - if gdf_osm_destinations.crs != crs: - gdf_osm_destinations = gdf_osm_destinations.to_crs(crs) - print(ox.ts(), "projected osm destinations") - - # spatially clip the destinationss to the study area boundary - import warnings - - warnings.filterwarnings("ignore", "GeoSeries.notna", UserWarning) # temp warning suppression - gdf_osm_destinations_clipped = gpd.clip(gdf_osm_destinations, study_area) - gdf_official_destinations_clipped = gpd.clip(gdf_official_destinations, study_area) - print(ox.ts(), "clipped osm/official destinations to study area boundary") - - # double-check everything has same CRS, then return - assert ( - gdf_study_area.crs - == geopackage.crs - == gdf_osm_destinations_clipped.crs - == gdf_official_destinations_clipped.crs - ) - return study_area, geopackage, gdf_osm_destinations_clipped, gdf_official_destinations_clipped - - -def get_core_dests(geopackage, buff, study_area, dests): - """ - Create a negative buffered convex hull of destinations. This will get to the core of the destination data. - - Parameters - ---------- - geopackage : geopandas.GeoDataFrame - the osm derived spatial data - buff : int - the what to multiply the smaller direction by to find urban core - study_area : shapely.Polygon or shapely.MultiPolygon - the study area boundary to negative-buffer - dests : geopandas.GeoDataFrame - the osm destinations or official destinations - - Returns - ------- - dests_core - destinations that fall within the core (negative-buffered) study area - """ - - # Define the extents of the study area - xmin, ymin, xmax, ymax = geopackage["geometry"].total_bounds - x = xmax - xmin - y = ymax - ymin - - if x < y: - buffer_dist = buff * x - else: - buffer_dist = buff * y - - study_area_core = study_area.buffer(-buffer_dist) - mask = dests.within(study_area_core) - dests_core = dests[mask] - return dests_core - - -def plot_city_data(gdf_osm, gdf_official, study_area, filepath, figsize=(10, 10), bgcolor="#333333", projected=True): - """ - Plot the OSM vs official destinations and save to disk. - - Parameters - ---------- - gdf_osm : geopandas.GeoDataFrame - the osm destinations - gdf_official : geopandas.GeoDataFrame - the official destinations - study_area : shapely.Polygon or shapely.MultiPolygon - the study area boundary - filepath : str - path to save figure as file - figsize : tuple - size of plotting figure - bgcolor : str - background color of plot - projected : bool - True if gdfs are projected rather than lat-lng - - Returns - ------- - fig, ax : tuple - """ - - fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) - ax.set_facecolor(bgcolor) - - # turn study_area polygon into gdf with correct CRS - gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm_destinations_clipped.crs) - - # plot study area, then official destinations, then osm destinations as layers - _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") - _ = gdf_official_destinations_clipped.plot(ax=ax, color="r", lw=1, label="Official Data") - _ = gdf_osm_destinations_clipped.plot(ax=ax, color="y", lw=1, label="OSM Data") - - ax.axis("off") - if projected: - # only make x/y equal-aspect if data are projected - ax.set_aspect("equal") - - # create legend - ax.legend() - - # save to disk - fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) - print(ox.ts(), f'figure saved to disk at "{filepath}"') - - plt.close() - return fig, ax - - -def plot_core_data(gdf_osm, gdf_official, study_area, filepath, figsize=(10, 10), bgcolor="#333333", projected=True): - """ - Plot the OSM vs official destinations and save to disk. - - Parameters - ---------- - gdf_osm : geopandas.GeoDataFrame - the osm destinations - gdf_official : geopandas.GeoDataFrame - the official destinations - study_area : shapely.Polygon or shapely.MultiPolygon - the study area boundary - filepath : str - path to save figure as file - figsize : tuple - size of plotting figure - bgcolor : str - background color of plot - projected : bool - True if gdfs are projected rather than lat-lng - - Returns - ------- - fig, ax : tuple - """ - - fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) - ax.set_facecolor(bgcolor) - - # turn study_area polygon into gdf with correct CRS - gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm_destinations_clipped.crs) - - # plot study area, then official destinations, then osm destinations as layers - _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") - _ = official_core_dests.plot(ax=ax, color="r", lw=1, label="Official Data") - _ = osm_core_dests.plot(ax=ax, color="y", lw=1, label="OSM Data") - - ax.axis("off") - if projected: - # only make x/y equal-aspect if data are projected - ax.set_aspect("equal") - - # create legend - ax.legend() - - # save to disk - fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) - print(ox.ts(), f'figure saved to disk at "{filepath}"') - - plt.close() - return fig, ax - - -def calculate_intersect(a, b, dist): - """ - Calculate the count of destinations from the official and the OSM dataset that intersect with different buffer. - - Parameters - ---------- - a : geopandas.GeoDataFrame - the osm or offical destinations - b : geopandas.GeoDataFrame - the osm or offical destinations - dist : int - buffer distance in meters - - Returns - ------- - a_buff_prop, b_buff_prop - the proportion of buffered a destinations that intersect with a buffered b destinations, - the proportion of buffered b destinations that intersect with a buffered a destinations - """ - - # focus on the geography of each gdf - a_geography = a["geometry"] - b_geography = b["geometry"] - - # buffer each by the current distance - a_buff = a_geography.buffer(dist) - b_buff = b_geography.buffer(dist) - - # take the unary union of each's buffered geometry - a_buff_unary = a_buff.unary_union - b_buff_unary = b_buff.unary_union - - # create a list of the destinations that intersect between datasets - a_buff_overlap = [] - for dest in a_buff: - if dest.intersects(b_buff_unary): - a_buff_overlap.append(dest) - - b_buff_overlap = [] - for dest in b_buff: - if dest.intersects(a_buff_unary): - b_buff_overlap.append(dest) - - # find the proportion of destinations that intersect between datasets out of total destination - a_buff_prop = len(a_buff_overlap) / len(a_geography) - b_buff_prop = len(b_buff_overlap) / len(a_geography) - - return a_buff_prop, b_buff_prop - - -# RUN THE SCRIPT -indicators = {} -for city in cities: - - print(ox.ts(), f"begin processing {city}") - indicators[city] = {} - - # load this city's configs - with open(f"../configuration/{city}.json") as f: - config = json.load(f) - - # load destination gdfs from osm graph and official shapefile - study_area, geopackage, gdf_osm_destinations_clipped, gdf_official_destinations_clipped = load_data( - config["osm_buffer_gpkg_path"], - config["official_dests_filepath"], - config["destinations_column"], - config["destinations_values"], - ) - # plot map of study area + osm and official destinations, save to disk - fp_city = figure_filepath_city.format(city=city) - fig, ax = plot_city_data(gdf_osm_destinations_clipped, gdf_official_destinations_clipped, study_area, fp_city) - - # calculate the convex hull to get city core - osm_core_dests = get_core_dests(geopackage, 0.1, study_area, gdf_osm_destinations_clipped) - official_core_dests = get_core_dests(geopackage, 0.1, study_area, gdf_official_destinations_clipped) - indicators[city]["osm_core_dests_count"] = len(osm_core_dests) - indicators[city]["official_core_dests_count"] = len(official_core_dests) - print(ox.ts(), "created core for osm/official destinations") - - # plot map of study area and core destinations - fp_core = figure_filepath_core.format(city=city) - fig, ax = plot_core_data(osm_core_dests, official_core_dests, study_area, fp_core) - - # calculate total destination count in each dataset, then add to indicators - osm_dest_count = len(gdf_osm_destinations_clipped) - official_dest_count = len(gdf_official_destinations_clipped) - indicators[city]["osm_dest_count"] = osm_dest_count - indicators[city]["official_dest_count"] = official_dest_count - print(ox.ts(), "calculated destination counts") - - # calculate the % overlaps of areas and lengths between osm and official destinations with different buffer distances - for dist in dest_buffer_dists: - osm_buff_prop, official_buff_prop = calculate_intersect( - gdf_osm_destinations_clipped, gdf_official_destinations_clipped, dist - ) - indicators[city][f"osm_buff_overlap_count_{dist}"] = osm_buff_prop - indicators[city][f"official_buff_overlap_count_{dist}"] = official_buff_prop - print(ox.ts(), f"calculated destination overlaps for buffer {dist}") - -# turn indicators into a dataframe and save to disk -df_ind = pd.DataFrame(indicators).T -df_ind.to_csv(indicators_filepath, index=True, encoding="utf-8") -print(ox.ts(), f'all done, saved indicators to disk at "{indicators_filepath}"') +import json +import os + +import geopandas as gpd +import matplotlib.pyplot as plt +import pandas as pd + +import osmnx as ox + +# configure script +cities = ["olomouc", "sao_paulo"] +dest_buffer_dists = [10, 50] +indicators_filepath = "./indicators.csv" +figure_filepath_city = "./fig/city_destination-comparison-{city}.png" +figure_filepath_core = "./fig/core_destination-comparison-{city}.png" + +if not os.path.exists("./fig/"): + os.makedirs("./fig/") + + +def load_data(osm_buffer_gpkg_path, official_dests_filepath, destinations_column, destinations_values): + """ + Load the city destinations and study boundary. + + Parameters + ---------- + osm_buffer_gpkg_path : str + path to the buffered study area geopackage + official_dests_filepath : str + path to the official destinations shapefile + destinations_column : str + column name containing categories of food-related destinations + destinations_values : str + acceptable values for categories of food-related destinations + + Returns + ------- + study_area, geopackage, gdf_osm_destinations, gdf_official_destinations : tuple + the polygon composed of square kilometers that is the city's study area, + the OSM derived dataset + the destinations sourced from OSM, + the destinations from the official data sources + """ + + # load the study area boundary as a shapely (multi)polygon + gdf_study_area = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") + study_area = gdf_study_area["geometry"].iloc[0] + print(ox.ts(), "loaded study area boundary") + + # load the entire geopackage + geopackage = gpd.read_file(osm_buffer_gpkg_path) + + # load the official destinations shapefile + # retain only rows with desired values in the destinations column + gdf_official_destinations = gpd.read_file(official_dests_filepath) + mask = gdf_official_destinations[destinations_column].isin(destinations_values) + gdf_official_destinations = gdf_official_destinations[mask] + print(ox.ts(), "loaded and filtered official destinations shapefile") + + # load the osm destinations shapefile + gdf_osm = gpd.read_file(osm_buffer_gpkg_path, layer="destinations") + gdf_osm_destinations = gdf_osm[gdf_osm["dest_name"] == "fresh_food_market"] + print(ox.ts(), "loaded osm destinations shapefile") + + # project the data to a common crs + crs = gdf_study_area.crs + if geopackage.crs != crs: + geopackage = geopackage.to_crs(crs) + print(ox.ts(), "projected geopackage") + if gdf_official_destinations.crs != crs: + gdf_official_destinations = gdf_official_destinations.to_crs(crs) + print(ox.ts(), "projected official destinations") + if gdf_osm_destinations.crs != crs: + gdf_osm_destinations = gdf_osm_destinations.to_crs(crs) + print(ox.ts(), "projected osm destinations") + + # spatially clip the destinationss to the study area boundary + import warnings + + warnings.filterwarnings("ignore", "GeoSeries.notna", UserWarning) # temp warning suppression + gdf_osm_destinations_clipped = gpd.clip(gdf_osm_destinations, study_area) + gdf_official_destinations_clipped = gpd.clip(gdf_official_destinations, study_area) + print(ox.ts(), "clipped osm/official destinations to study area boundary") + + # double-check everything has same CRS, then return + assert ( + gdf_study_area.crs + == geopackage.crs + == gdf_osm_destinations_clipped.crs + == gdf_official_destinations_clipped.crs + ) + return study_area, geopackage, gdf_osm_destinations_clipped, gdf_official_destinations_clipped + + +def get_core_dests(geopackage, buff, study_area, dests): + """ + Create a negative buffered convex hull of destinations. This will get to the core of the destination data. + + Parameters + ---------- + geopackage : geopandas.GeoDataFrame + the osm derived spatial data + buff : int + the what to multiply the smaller direction by to find urban core + study_area : shapely.Polygon or shapely.MultiPolygon + the study area boundary to negative-buffer + dests : geopandas.GeoDataFrame + the osm destinations or official destinations + + Returns + ------- + dests_core + destinations that fall within the core (negative-buffered) study area + """ + + # Define the extents of the study area + xmin, ymin, xmax, ymax = geopackage["geometry"].total_bounds + x = xmax - xmin + y = ymax - ymin + + if x < y: + buffer_dist = buff * x + else: + buffer_dist = buff * y + + study_area_core = study_area.buffer(-buffer_dist) + mask = dests.within(study_area_core) + dests_core = dests[mask] + return dests_core + + +def plot_city_data(gdf_osm, gdf_official, study_area, filepath, figsize=(10, 10), bgcolor="#333333", projected=True): + """ + Plot the OSM vs official destinations and save to disk. + + Parameters + ---------- + gdf_osm : geopandas.GeoDataFrame + the osm destinations + gdf_official : geopandas.GeoDataFrame + the official destinations + study_area : shapely.Polygon or shapely.MultiPolygon + the study area boundary + filepath : str + path to save figure as file + figsize : tuple + size of plotting figure + bgcolor : str + background color of plot + projected : bool + True if gdfs are projected rather than lat-lng + + Returns + ------- + fig, ax : tuple + """ + + fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) + ax.set_facecolor(bgcolor) + + # turn study_area polygon into gdf with correct CRS + gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm_destinations_clipped.crs) + + # plot study area, then official destinations, then osm destinations as layers + _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") + _ = gdf_official_destinations_clipped.plot(ax=ax, color="r", lw=1, label="Official Data") + _ = gdf_osm_destinations_clipped.plot(ax=ax, color="y", lw=1, label="OSM Data") + + ax.axis("off") + if projected: + # only make x/y equal-aspect if data are projected + ax.set_aspect("equal") + + # create legend + ax.legend() + + # save to disk + fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) + print(ox.ts(), f'figure saved to disk at "{filepath}"') + + plt.close() + return fig, ax + + +def plot_core_data(gdf_osm, gdf_official, study_area, filepath, figsize=(10, 10), bgcolor="#333333", projected=True): + """ + Plot the OSM vs official destinations and save to disk. + + Parameters + ---------- + gdf_osm : geopandas.GeoDataFrame + the osm destinations + gdf_official : geopandas.GeoDataFrame + the official destinations + study_area : shapely.Polygon or shapely.MultiPolygon + the study area boundary + filepath : str + path to save figure as file + figsize : tuple + size of plotting figure + bgcolor : str + background color of plot + projected : bool + True if gdfs are projected rather than lat-lng + + Returns + ------- + fig, ax : tuple + """ + + fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) + ax.set_facecolor(bgcolor) + + # turn study_area polygon into gdf with correct CRS + gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm_destinations_clipped.crs) + + # plot study area, then official destinations, then osm destinations as layers + _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") + _ = official_core_dests.plot(ax=ax, color="r", lw=1, label="Official Data") + _ = osm_core_dests.plot(ax=ax, color="y", lw=1, label="OSM Data") + + ax.axis("off") + if projected: + # only make x/y equal-aspect if data are projected + ax.set_aspect("equal") + + # create legend + ax.legend() + + # save to disk + fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) + print(ox.ts(), f'figure saved to disk at "{filepath}"') + + plt.close() + return fig, ax + + +def calculate_intersect(a, b, dist): + """ + Calculate the count of destinations from the official and the OSM dataset that intersect with different buffer. + + Parameters + ---------- + a : geopandas.GeoDataFrame + the osm or offical destinations + b : geopandas.GeoDataFrame + the osm or offical destinations + dist : int + buffer distance in meters + + Returns + ------- + a_buff_prop, b_buff_prop + the proportion of buffered a destinations that intersect with a buffered b destinations, + the proportion of buffered b destinations that intersect with a buffered a destinations + """ + + # focus on the geography of each gdf + a_geography = a["geometry"] + b_geography = b["geometry"] + + # buffer each by the current distance + a_buff = a_geography.buffer(dist) + b_buff = b_geography.buffer(dist) + + # take the unary union of each's buffered geometry + a_buff_unary = a_buff.unary_union + b_buff_unary = b_buff.unary_union + + # create a list of the destinations that intersect between datasets + a_buff_overlap = [] + for dest in a_buff: + if dest.intersects(b_buff_unary): + a_buff_overlap.append(dest) + + b_buff_overlap = [] + for dest in b_buff: + if dest.intersects(a_buff_unary): + b_buff_overlap.append(dest) + + # find the proportion of destinations that intersect between datasets out of total destination + a_buff_prop = len(a_buff_overlap) / len(a_geography) + b_buff_prop = len(b_buff_overlap) / len(a_geography) + + return a_buff_prop, b_buff_prop + + +# RUN THE SCRIPT +indicators = {} +for city in cities: + + print(ox.ts(), f"begin processing {city}") + indicators[city] = {} + + # load this city's configs + with open(f"../configuration/{city}.json") as f: + config = json.load(f) + + # load destination gdfs from osm graph and official shapefile + study_area, geopackage, gdf_osm_destinations_clipped, gdf_official_destinations_clipped = load_data( + config["osm_buffer_gpkg_path"], + config["official_dests_filepath"], + config["destinations_column"], + config["destinations_values"], + ) + # plot map of study area + osm and official destinations, save to disk + fp_city = figure_filepath_city.format(city=city) + fig, ax = plot_city_data(gdf_osm_destinations_clipped, gdf_official_destinations_clipped, study_area, fp_city) + + # calculate the convex hull to get city core + osm_core_dests = get_core_dests(geopackage, 0.1, study_area, gdf_osm_destinations_clipped) + official_core_dests = get_core_dests(geopackage, 0.1, study_area, gdf_official_destinations_clipped) + indicators[city]["osm_core_dests_count"] = len(osm_core_dests) + indicators[city]["official_core_dests_count"] = len(official_core_dests) + print(ox.ts(), "created core for osm/official destinations") + + # plot map of study area and core destinations + fp_core = figure_filepath_core.format(city=city) + fig, ax = plot_core_data(osm_core_dests, official_core_dests, study_area, fp_core) + + # calculate total destination count in each dataset, then add to indicators + osm_dest_count = len(gdf_osm_destinations_clipped) + official_dest_count = len(gdf_official_destinations_clipped) + indicators[city]["osm_dest_count"] = osm_dest_count + indicators[city]["official_dest_count"] = official_dest_count + print(ox.ts(), "calculated destination counts") + + # calculate the % overlaps of areas and lengths between osm and official destinations with different buffer distances + for dist in dest_buffer_dists: + osm_buff_prop, official_buff_prop = calculate_intersect( + gdf_osm_destinations_clipped, gdf_official_destinations_clipped, dist + ) + indicators[city][f"osm_buff_overlap_count_{dist}"] = osm_buff_prop + indicators[city][f"official_buff_overlap_count_{dist}"] = official_buff_prop + print(ox.ts(), f"calculated destination overlaps for buffer {dist}") + +# turn indicators into a dataframe and save to disk +df_ind = pd.DataFrame(indicators).T +df_ind.to_csv(indicators_filepath, index=True, encoding="utf-8") +print(ox.ts(), f'all done, saved indicators to disk at "{indicators_filepath}"') diff --git a/validation/destination/hex_indicators.csv b/validation/destination/hex_indicators.csv index 15c5abc2..9d408f12 100644 --- a/validation/destination/hex_indicators.csv +++ b/validation/destination/hex_indicators.csv @@ -1,3 +1,3 @@ -,weight_percentage,osm_mean,official_mean,osm_true_mean,official_true_meann -olomouc,0.896969696969697,0.10097643097643098,0.10508417508417509,0.2972972972972973,0.25 -sao_paulo,0.8368905423927943,0.16283005226612043,0.003999789128044464,0.05264389330837623,0.004679457182966776 +,weight_percentage,osm_mean,official_mean,osm_true_mean,official_true_meann +olomouc,0.896969696969697,0.10097643097643098,0.10508417508417509,0.2972972972972973,0.25 +sao_paulo,0.8368905423927943,0.16283005226612043,0.003999789128044464,0.05264389330837623,0.004679457182966776 diff --git a/validation/destination/hexagon_points.py b/validation/destination/hexagon_points.py index 499753f5..5b5b54b8 100644 --- a/validation/destination/hexagon_points.py +++ b/validation/destination/hexagon_points.py @@ -1,240 +1,240 @@ -import json -import os - -import geopandas as gpd -import matplotlib.pyplot as plt -import numpy as np -import pandas as pd -from matplotlib.patches import RegularPolygon -from shapely.geometry import Polygon - -import osmnx as ox - -# configure script -cities = ["olomouc", "sao_paulo"] -indicators_filepath = "./hex_indicators.csv" -figure_filepath = "./fig/hexbins-{city}.png" - -if not os.path.exists("./fig/"): - os.makedirs("./fig/") - - -def load_data(osm_buffer_gpkg_path, official_dests_filepath, destinations_column, destinations_values): - - # load the study area boundary as a shapely (multi)polygon - gdf_study_area = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") - study_area = gdf_study_area["geometry"].iloc[0] - print(ox.ts(), "loaded study area boundary") - - # load the official destinations shapefile - # retain only rows with desired values in the destinations column - gdf_official_destinations = gpd.read_file(official_dests_filepath) - mask = gdf_official_destinations[destinations_column].isin(destinations_values) - gdf_official_destinations = gdf_official_destinations[mask] - print(ox.ts(), "loaded and filtered official destinations shapefile") - - # load the osm destinations shapefile - gdf_osm = gpd.read_file(osm_buffer_gpkg_path, layer="destinations") - gdf_osm_destinations = gdf_osm[gdf_osm["dest_name"] == "fresh_food_market"] - print(ox.ts(), "loaded osm destinations shapefile") - - # project the data to a common crs - crs = gdf_study_area.crs - if gdf_official_destinations.crs != crs: - gdf_official_destinations = gdf_official_destinations.to_crs(crs) - print(ox.ts(), "projected official destinations") - if gdf_osm_destinations.crs != crs: - gdf_osm_destinations = gdf_osm_destinations.to_crs(crs) - print(ox.ts(), "projected osm destinations") - - # spatially clip the destinationss to the study area boundary - import warnings - - warnings.filterwarnings("ignore", "GeoSeries.notna", UserWarning) # temp warning suppression - gdf_osm_destinations_clipped = gpd.clip(gdf_osm_destinations, study_area) - gdf_official_destinations_clipped = gpd.clip(gdf_official_destinations, study_area) - print(ox.ts(), "clipped osm/official destinations to study area boundary") - - # double-check everything has same CRS, then return - assert gdf_study_area.crs == gdf_osm_destinations_clipped.crs == gdf_official_destinations_clipped.crs - return study_area, gdf_osm_destinations_clipped, gdf_official_destinations_clipped - - -def hex_bins(osm_buffer_gpkg_path, study_area, gdf_osm_destinations_clipped): - - boundary = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") - gdf_boundary = boundary["geometry"] - - xmin, ymin, xmax, ymax = gdf_boundary.total_bounds # lat-long of 2 corners - xmin -= 500 - xmax += 500 - ymin -= 500 - ymax += 500 - # East-West extent of urban_study_region - EW = xmax - xmin - # North-South extent of urban_study_region - NS = ymax - ymin - # Hexagon bins diameter should equal 500 meters - d = 500 - # horizontal width of hexagon = w = d* sin(60) - w = d * np.sin(np.pi / 3) - # Approximate number of hexagons per row = EW/w - n_cols = int(EW / d) + 1 - # Approximate number of hexagons per column = NS/d - n_rows = int(NS / w) + 1 - - w = (xmax - xmin) / n_cols # width of hexagon - d = w / np.sin(np.pi / 3) # diameter of hexagon 500 meters - array_of_hexes = [] - - # +1 added to n_rows since the range function runs from 0 through (n-1), and the number of rows of hexgons plotted - # was one less than the expcted number of rows. - for rows in range(0, n_rows + 1): - hcoord = np.arange(xmin, xmax, w) + (rows % 2) * w / 2 - vcoord = [ymax - rows * d * 0.75] * n_cols - for x, y in zip(hcoord, vcoord): - hexes = RegularPolygon((x, y), numVertices=6, radius=d / 2, alpha=0.2, edgecolor="k") - verts = hexes.get_path().vertices - trans = hexes.get_patch_transform() - points = trans.transform(verts) - array_of_hexes.append(Polygon(points)) - - # turn study_area polygon into gdf with correct CRS - gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm_destinations_clipped.crs) - gdf_boundary = gpd.GeoDataFrame(gdf_boundary) - - hex_grid = gpd.GeoDataFrame({"geometry": array_of_hexes}) - hex_grid_clipped = gpd.overlay(hex_grid, gdf_boundary) - hex_grid_clipped = gpd.GeoDataFrame(hex_grid_clipped, geometry="geometry") - - return gdf_boundary, hex_grid_clipped - - -def plot_hex_bins( - gdf_boundary, - hex_grid_clipped, - gdf_official_destinations_clipped, - gdf_osm_destinations_clipped, - filepath, - figsize=(10, 10), - bgcolor="#333333", - projected=True, -): - - fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) - ax.set_facecolor(bgcolor) - - # plot study area, then official destinations, then osm destinations as layers - _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") - _ = hex_grid_clipped.plot(ax=ax, facecolor="k", edgecolor="w", lw=2, label="Hex Bins") - _ = gdf_official_destinations_clipped.plot(ax=ax, color="r", lw=1, label="Official Data") - _ = gdf_osm_destinations_clipped.plot(ax=ax, color="y", lw=1, label="OSM Data") - - ax.axis("off") - if projected: - # only make x/y equal-aspect if data are projected - ax.set_aspect("equal") - - # create legend - ax.legend() - - # save to disk - fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) - print(ox.ts(), f'figure saved to disk at "{filepath}"') - - plt.close() - return fig, ax - - -def calc_hex_indicators(hex_grid_clipped, gdf_osm_destinations, gdf_official_destinations): - osm_true = [] - official_true = [] - osm_percentages = [] - official_percentages = [] - weight_count = 0 - osm_layer_df = gpd.GeoDataFrame(gdf_osm_destinations) - official_layer_df = gpd.GeoDataFrame(gdf_official_destinations) - # Loop through hexagon bins - for _, hexagon in enumerate(hex_grid_clipped["geometry"]): - osm_count = 0 - official_count = 0 - total_count = 0 - # Loop through OSM Points - for row in osm_layer_df.iterrows(): - layer_point = row[1]["geometry"] - if hexagon.contains(layer_point): - osm_count += 1 - total_count += 1 - # Loop through Official Points - for row in official_layer_df.iterrows(): - layer_point = row[1]["geometry"] - if hexagon.contains(layer_point): - official_count += 1 - total_count += 1 - - percentage_osm = osm_count / total_count if total_count else 0 - percentage_official = official_count / total_count if total_count else 0 - # weight = True if bool(osm_count) == bool(official_count) else False - if bool(osm_count) == bool(official_count): - weight_count += 1 - osm_true.append(osm_count) - official_true.append(official_count) - osm_percentages.append(percentage_osm) - official_percentages.append(percentage_official) - - weight_percentage = weight_count / len(hex_grid_clipped["geometry"]) - osm_mean = sum(osm_percentages) / len(hex_grid_clipped["geometry"]) - # osm_median = statistics.median(osm_percentages) - osm_true_mean = sum(osm_true) / weight_count - # osm_true_median = statistics.median(osm_true) - official_mean = sum(official_percentages) / len(hex_grid_clipped["geometry"]) - # official_median = statistics.median(official_percentages) - official_true_mean = sum(official_true) / weight_count - # official_true_median = statistics.median(official_true) - - return weight_percentage, osm_mean, official_mean, osm_true_mean, official_true_mean - - -# RUN THE SCRIPT -indicators = {} -for city in cities: - - print(ox.ts(), f"begin processing {city}") - indicators[city] = {} - - # load this city's configs - with open(f"../configuration/{city}.json") as f: - config = json.load(f) - - # load destination gdfs from osm graph and official shapefile - study_area, gdf_osm_destinations_clipped, gdf_official_destinations_clipped = load_data( - config["osm_buffer_gpkg_path"], - config["official_dests_filepath"], - config["destinations_column"], - config["destinations_values"], - ) - - # create plot of hexbins for the city - gdf_boundary, hex_grid_clipped = hex_bins(config["osm_buffer_gpkg_path"], study_area, gdf_osm_destinations_clipped) - - # plot map of study area, hex bins, and osm and official destinations, save to disk - fp = figure_filepath.format(city=city) - fig, ax = plot_hex_bins( - gdf_boundary, hex_grid_clipped, gdf_official_destinations_clipped, gdf_osm_destinations_clipped, fp - ) - - # calculate the indicators at the hexbin level - weight_percentage, osm_mean, official_mean, osm_true_mean, official_true_mean = calc_hex_indicators( - hex_grid_clipped, gdf_osm_destinations_clipped, gdf_official_destinations_clipped - ) - indicators[city]["weight_percentage"] = weight_percentage - indicators[city]["osm_mean"] = osm_mean - indicators[city]["official_mean"] = official_mean - indicators[city]["osm_true_mean"] = osm_true_mean - indicators[city]["official_true_meann"] = official_true_mean - print(ox.ts(), "created indictors at hexbin level") - -# turn indicators into a dataframe and save to disk -df_ind = pd.DataFrame(indicators).T -df_ind.to_csv(indicators_filepath, index=True, encoding="utf-8") -print(ox.ts(), f'all done, saved indicators to disk at "{indicators_filepath}"') +import json +import os + +import geopandas as gpd +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +from matplotlib.patches import RegularPolygon +from shapely.geometry import Polygon + +import osmnx as ox + +# configure script +cities = ["olomouc", "sao_paulo"] +indicators_filepath = "./hex_indicators.csv" +figure_filepath = "./fig/hexbins-{city}.png" + +if not os.path.exists("./fig/"): + os.makedirs("./fig/") + + +def load_data(osm_buffer_gpkg_path, official_dests_filepath, destinations_column, destinations_values): + + # load the study area boundary as a shapely (multi)polygon + gdf_study_area = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") + study_area = gdf_study_area["geometry"].iloc[0] + print(ox.ts(), "loaded study area boundary") + + # load the official destinations shapefile + # retain only rows with desired values in the destinations column + gdf_official_destinations = gpd.read_file(official_dests_filepath) + mask = gdf_official_destinations[destinations_column].isin(destinations_values) + gdf_official_destinations = gdf_official_destinations[mask] + print(ox.ts(), "loaded and filtered official destinations shapefile") + + # load the osm destinations shapefile + gdf_osm = gpd.read_file(osm_buffer_gpkg_path, layer="destinations") + gdf_osm_destinations = gdf_osm[gdf_osm["dest_name"] == "fresh_food_market"] + print(ox.ts(), "loaded osm destinations shapefile") + + # project the data to a common crs + crs = gdf_study_area.crs + if gdf_official_destinations.crs != crs: + gdf_official_destinations = gdf_official_destinations.to_crs(crs) + print(ox.ts(), "projected official destinations") + if gdf_osm_destinations.crs != crs: + gdf_osm_destinations = gdf_osm_destinations.to_crs(crs) + print(ox.ts(), "projected osm destinations") + + # spatially clip the destinationss to the study area boundary + import warnings + + warnings.filterwarnings("ignore", "GeoSeries.notna", UserWarning) # temp warning suppression + gdf_osm_destinations_clipped = gpd.clip(gdf_osm_destinations, study_area) + gdf_official_destinations_clipped = gpd.clip(gdf_official_destinations, study_area) + print(ox.ts(), "clipped osm/official destinations to study area boundary") + + # double-check everything has same CRS, then return + assert gdf_study_area.crs == gdf_osm_destinations_clipped.crs == gdf_official_destinations_clipped.crs + return study_area, gdf_osm_destinations_clipped, gdf_official_destinations_clipped + + +def hex_bins(osm_buffer_gpkg_path, study_area, gdf_osm_destinations_clipped): + + boundary = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") + gdf_boundary = boundary["geometry"] + + xmin, ymin, xmax, ymax = gdf_boundary.total_bounds # lat-long of 2 corners + xmin -= 500 + xmax += 500 + ymin -= 500 + ymax += 500 + # East-West extent of urban_study_region + EW = xmax - xmin + # North-South extent of urban_study_region + NS = ymax - ymin + # Hexagon bins diameter should equal 500 meters + d = 500 + # horizontal width of hexagon = w = d* sin(60) + w = d * np.sin(np.pi / 3) + # Approximate number of hexagons per row = EW/w + n_cols = int(EW / d) + 1 + # Approximate number of hexagons per column = NS/d + n_rows = int(NS / w) + 1 + + w = (xmax - xmin) / n_cols # width of hexagon + d = w / np.sin(np.pi / 3) # diameter of hexagon 500 meters + array_of_hexes = [] + + # +1 added to n_rows since the range function runs from 0 through (n-1), and the number of rows of hexgons plotted + # was one less than the expcted number of rows. + for rows in range(0, n_rows + 1): + hcoord = np.arange(xmin, xmax, w) + (rows % 2) * w / 2 + vcoord = [ymax - rows * d * 0.75] * n_cols + for x, y in zip(hcoord, vcoord): + hexes = RegularPolygon((x, y), numVertices=6, radius=d / 2, alpha=0.2, edgecolor="k") + verts = hexes.get_path().vertices + trans = hexes.get_patch_transform() + points = trans.transform(verts) + array_of_hexes.append(Polygon(points)) + + # turn study_area polygon into gdf with correct CRS + gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm_destinations_clipped.crs) + gdf_boundary = gpd.GeoDataFrame(gdf_boundary) + + hex_grid = gpd.GeoDataFrame({"geometry": array_of_hexes}) + hex_grid_clipped = gpd.overlay(hex_grid, gdf_boundary) + hex_grid_clipped = gpd.GeoDataFrame(hex_grid_clipped, geometry="geometry") + + return gdf_boundary, hex_grid_clipped + + +def plot_hex_bins( + gdf_boundary, + hex_grid_clipped, + gdf_official_destinations_clipped, + gdf_osm_destinations_clipped, + filepath, + figsize=(10, 10), + bgcolor="#333333", + projected=True, +): + + fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) + ax.set_facecolor(bgcolor) + + # plot study area, then official destinations, then osm destinations as layers + _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") + _ = hex_grid_clipped.plot(ax=ax, facecolor="k", edgecolor="w", lw=2, label="Hex Bins") + _ = gdf_official_destinations_clipped.plot(ax=ax, color="r", lw=1, label="Official Data") + _ = gdf_osm_destinations_clipped.plot(ax=ax, color="y", lw=1, label="OSM Data") + + ax.axis("off") + if projected: + # only make x/y equal-aspect if data are projected + ax.set_aspect("equal") + + # create legend + ax.legend() + + # save to disk + fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) + print(ox.ts(), f'figure saved to disk at "{filepath}"') + + plt.close() + return fig, ax + + +def calc_hex_indicators(hex_grid_clipped, gdf_osm_destinations, gdf_official_destinations): + osm_true = [] + official_true = [] + osm_percentages = [] + official_percentages = [] + weight_count = 0 + osm_layer_df = gpd.GeoDataFrame(gdf_osm_destinations) + official_layer_df = gpd.GeoDataFrame(gdf_official_destinations) + # Loop through hexagon bins + for _, hexagon in enumerate(hex_grid_clipped["geometry"]): + osm_count = 0 + official_count = 0 + total_count = 0 + # Loop through OSM Points + for row in osm_layer_df.iterrows(): + layer_point = row[1]["geometry"] + if hexagon.contains(layer_point): + osm_count += 1 + total_count += 1 + # Loop through Official Points + for row in official_layer_df.iterrows(): + layer_point = row[1]["geometry"] + if hexagon.contains(layer_point): + official_count += 1 + total_count += 1 + + percentage_osm = osm_count / total_count if total_count else 0 + percentage_official = official_count / total_count if total_count else 0 + # weight = True if bool(osm_count) == bool(official_count) else False + if bool(osm_count) == bool(official_count): + weight_count += 1 + osm_true.append(osm_count) + official_true.append(official_count) + osm_percentages.append(percentage_osm) + official_percentages.append(percentage_official) + + weight_percentage = weight_count / len(hex_grid_clipped["geometry"]) + osm_mean = sum(osm_percentages) / len(hex_grid_clipped["geometry"]) + # osm_median = statistics.median(osm_percentages) + osm_true_mean = sum(osm_true) / weight_count + # osm_true_median = statistics.median(osm_true) + official_mean = sum(official_percentages) / len(hex_grid_clipped["geometry"]) + # official_median = statistics.median(official_percentages) + official_true_mean = sum(official_true) / weight_count + # official_true_median = statistics.median(official_true) + + return weight_percentage, osm_mean, official_mean, osm_true_mean, official_true_mean + + +# RUN THE SCRIPT +indicators = {} +for city in cities: + + print(ox.ts(), f"begin processing {city}") + indicators[city] = {} + + # load this city's configs + with open(f"../configuration/{city}.json") as f: + config = json.load(f) + + # load destination gdfs from osm graph and official shapefile + study_area, gdf_osm_destinations_clipped, gdf_official_destinations_clipped = load_data( + config["osm_buffer_gpkg_path"], + config["official_dests_filepath"], + config["destinations_column"], + config["destinations_values"], + ) + + # create plot of hexbins for the city + gdf_boundary, hex_grid_clipped = hex_bins(config["osm_buffer_gpkg_path"], study_area, gdf_osm_destinations_clipped) + + # plot map of study area, hex bins, and osm and official destinations, save to disk + fp = figure_filepath.format(city=city) + fig, ax = plot_hex_bins( + gdf_boundary, hex_grid_clipped, gdf_official_destinations_clipped, gdf_osm_destinations_clipped, fp + ) + + # calculate the indicators at the hexbin level + weight_percentage, osm_mean, official_mean, osm_true_mean, official_true_mean = calc_hex_indicators( + hex_grid_clipped, gdf_osm_destinations_clipped, gdf_official_destinations_clipped + ) + indicators[city]["weight_percentage"] = weight_percentage + indicators[city]["osm_mean"] = osm_mean + indicators[city]["official_mean"] = official_mean + indicators[city]["osm_true_mean"] = osm_true_mean + indicators[city]["official_true_meann"] = official_true_mean + print(ox.ts(), "created indictors at hexbin level") + +# turn indicators into a dataframe and save to disk +df_ind = pd.DataFrame(indicators).T +df_ind.to_csv(indicators_filepath, index=True, encoding="utf-8") +print(ox.ts(), f'all done, saved indicators to disk at "{indicators_filepath}"') diff --git a/validation/destination/indicators.csv b/validation/destination/indicators.csv index 481225d8..7a409632 100644 --- a/validation/destination/indicators.csv +++ b/validation/destination/indicators.csv @@ -1,3 +1,3 @@ -,osm_core_dests_count,official_core_dests_count,osm_dest_count,official_dest_count,osm_buff_overlap_count_10,official_buff_overlap_count_10,osm_buff_overlap_count_50,official_buff_overlap_count_50 -olomouc,51.0,36.0,60.0,50.0,0.2,0.31666666666666665,0.5,0.5166666666666667 -sao_paulo,797.0,12.0,1562.0,34.0,0.017285531370038413,0.007042253521126761,0.1350832266325224,0.01088348271446863 +,osm_core_dests_count,official_core_dests_count,osm_dest_count,official_dest_count,osm_buff_overlap_count_10,official_buff_overlap_count_10,osm_buff_overlap_count_50,official_buff_overlap_count_50 +olomouc,51.0,36.0,60.0,50.0,0.2,0.31666666666666665,0.5,0.5166666666666667 +sao_paulo,797.0,12.0,1562.0,34.0,0.017285531370038413,0.007042253521126761,0.1350832266325224,0.01088348271446863 diff --git a/validation/destination/readme.md b/validation/destination/readme.md index 4acec0f6..29722193 100644 --- a/validation/destination/readme.md +++ b/validation/destination/readme.md @@ -1,17 +1,17 @@ -## Destination Validation Indicators - -| Indicator Name | Indicator Description | -| -------------- | --------------------- | -| osm_core_dests_count | Count of OSM destinations in city core -| official_core_dests_count | Count of Official Desitinations in city core -| osm_dest_count | Total count of OSM destinations -| official_dest_count | Total count of OSM destinations -| osm_buff_overlap_count_10 | Proportion of OSM destinations that intersect with an offical desitnation when destination is buffered by 10 meters -| official_buff_overlap_count_10 | Proportion of official destinations that intersect with an OSM desitnation when destination is buffered by 10 meters -| osm_buff_overlap_count_50 | Proportion of OSM destinations that intersect with an offical desitnation when destination is buffered by 50 meters -| official_buff_overlap_count_50 | Proportion of official destinations that intersect with an OSM desitnation when destination is buffered by 50 meters -| weight percentage | Percentage of hexagons that contain a true weight attribute. -| OSM mean | Average of the sum of percentages of true weight hexagons present in the OSM dataset divided by the total number of hexagons -| Official mean | Average of the sum of percentages of true weight hexagons present in the official dataset divided by the total number of hexagons -| OSM true mean | Share of the sum of percentages of true weight hexagons present in the OSM dataset divided by the total true hexagon count -| Official true mean | Share of the sum of percentages of true weight hexagons present in the official dataset divided by the total true hexagon count +## Destination Validation Indicators + +| Indicator Name | Indicator Description | +| -------------- | --------------------- | +| osm_core_dests_count | Count of OSM destinations in city core +| official_core_dests_count | Count of Official Desitinations in city core +| osm_dest_count | Total count of OSM destinations +| official_dest_count | Total count of OSM destinations +| osm_buff_overlap_count_10 | Proportion of OSM destinations that intersect with an offical desitnation when destination is buffered by 10 meters +| official_buff_overlap_count_10 | Proportion of official destinations that intersect with an OSM desitnation when destination is buffered by 10 meters +| osm_buff_overlap_count_50 | Proportion of OSM destinations that intersect with an offical desitnation when destination is buffered by 50 meters +| official_buff_overlap_count_50 | Proportion of official destinations that intersect with an OSM desitnation when destination is buffered by 50 meters +| weight percentage | Percentage of hexagons that contain a true weight attribute. +| OSM mean | Average of the sum of percentages of true weight hexagons present in the OSM dataset divided by the total number of hexagons +| Official mean | Average of the sum of percentages of true weight hexagons present in the official dataset divided by the total number of hexagons +| OSM true mean | Share of the sum of percentages of true weight hexagons present in the OSM dataset divided by the total true hexagon count +| Official true mean | Share of the sum of percentages of true weight hexagons present in the official dataset divided by the total true hexagon count diff --git a/validation/edge/edge_validation.py b/validation/edge/edge_validation.py index cd5c25bd..22244dd7 100644 --- a/validation/edge/edge_validation.py +++ b/validation/edge/edge_validation.py @@ -1,239 +1,239 @@ -import json -import os - -import geopandas as gpd -import matplotlib.pyplot as plt -import pandas as pd - -import osmnx as ox - -# configure script -cities = ["olomouc", "belfast", "hong_kong"] -edge_buffer_dists = [10, 50] -indicators_filepath = "./indicators.csv" -figure_filepath = "./fig/street-comparison-{city}.png" - -if not os.path.exists("./fig/"): - os.makedirs("./fig/") - - -def load_data(osm_graphml_path, osm_buffer_gpkg_path, official_streets_gpkg_path): - """ - Load the street network edges and study boundary. - - Parameters - ---------- - osm_graphml_path : str - path to the OSM graphml file - osm_buffer_gpkg_path : str - path to the buffered study area geopackage - official_streets_gpkg_path : str - path to the official streets shapefile - - Returns - ------- - gdf_osm_streets_clipped, gdf_official_streets_clipped, study_area : tuple - the osm streets (clipped to the study area), the official streets - (clipped to the study area), and the study area polygon - """ - - # load the study area boundary as a shapely (multi)polygon - gdf_study_area = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") - study_area = gdf_study_area["geometry"].iloc[0] - print(ox.ts(), "loaded study area boundary") - - # load the official streets shapefile - gdf_official_streets = gpd.read_file(official_streets_gpkg_path) - print(ox.ts(), "loaded official streets shapefile") - - # load the graph, make it undirected, then get edges GeoDataFrame - gdf_osm_streets = ox.graph_to_gdfs(ox.get_undirected(ox.load_graphml(osm_graphml_path)), nodes=False) - print(ox.ts(), "loaded osm edges and made undirected streets") - - # Project the data to a common crs - crs = gdf_study_area.crs - if gdf_osm_streets.crs != crs: - gdf_osm_streets = gdf_osm_streets.to_crs(crs) - print(ox.ts(), "projected osm streets") - if gdf_official_streets.crs != crs: - gdf_official_streets = gdf_official_streets.to_crs(crs) - print(ox.ts(), "projected official streets") - - # spatially clip the streets to the study area boundary - import warnings - - warnings.filterwarnings("ignore", "GeoSeries.notna", UserWarning) # temp warning suppression - gdf_osm_streets_clipped = gpd.clip(gdf_osm_streets, study_area) - gdf_official_streets_clipped = gpd.clip(gdf_official_streets, study_area) - print(ox.ts(), "clipped osm/official streets to study area boundary") - - # double-check everything has same CRS, then return - assert gdf_osm_streets_clipped.crs == gdf_official_streets_clipped.crs == gdf_study_area.crs - return gdf_osm_streets_clipped, gdf_official_streets_clipped, study_area - - -def plot_data(gdf_osm, gdf_official, study_area, filepath, figsize=(10, 10), bgcolor="#333333", projected=True): - """ - Plot the OSM vs official streets and save to disk. - - Parameters - ---------- - gdf_osm : geopandas.GeoDataFrame - the osm streets - gdf_official : geopandas.GeoDataFrame - the official streets - study_area : shapely.Polygon or shapely.MultiPolygon - the study area boundary - filepath : str - path to save figure as file - figsize : tuple - size of plotting figure - bgcolor : str - background color of plot - projected : bool - True if gdfs are projected rather than lat-lng - - Returns - ------- - fig, ax : tuple - """ - - fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) - ax.set_facecolor(bgcolor) - - # turn study_area polygon into gdf with correct CRS - gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm.crs) - - # plot study area, then official streets, then osm streets as layers - _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") - _ = gdf_official.plot(ax=ax, color="r", lw=1, label="Official Data") - _ = gdf_osm.plot(ax=ax, color="y", lw=1, label="OSM Data") - - ax.axis("off") - if projected: - # only make x/y equal-aspect if data are projected - ax.set_aspect("equal") - - # create legend - ax.legend() - - # save to disk - fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) - print(ox.ts(), f'figure saved to disk at "{filepath}"') - - plt.close() - return fig, ax - - -def total_edge_length_count(gdf_streets): - """ - Calculate the total length and count of streets in gdf. - - Parameters - ---------- - gdf_streets : geopandas.GeoDataFrame - the osm or official streets - - Returns - ------- - streets_total_length, streets_count : tuple - """ - streets_total_length = gdf_streets.length.sum() - streets_count = len(gdf_streets) - return streets_total_length, streets_count - - -def calculate_overlap(a, b, dist): - """ - Calculate the % overlap of a and b's lines and buffered lines' areas - given different buffering distances. - - Parameters - ---------- - a : geopandas.GeoDataFrame - the osm streets - b : geopandas.GeoDataFrame - the osm streets - dist : int - buffer distance in meters - - Returns - ------- - a_area_pct, b_area_pct, a_length_pct, b_length_pct : tuple - """ - - # buffer each by the current distance - a_buff = a.buffer(dist) - b_buff = b.buffer(dist) - - # take the unary union of each's buffered geometry - a_buff_unary = a_buff.unary_union - b_buff_unary = b_buff.unary_union - - # find the portion of each's buffered geometry that intersects with the other's buffered geometry - a_buff_overlap = a_buff_unary.intersection(b_buff_unary) - b_buff_overlap = b_buff_unary.intersection(a_buff_unary) - - # what % of each's buffered area does that intersecting portion comprise? - a_area_pct = a_buff_overlap.area / a_buff_unary.area - b_area_pct = b_buff_overlap.area / b_buff_unary.area - - # take the unary union of each's original unbuffered lines - a_unary = a.unary_union - b_unary = b.unary_union - - # find each's lines that intersect the intersecting buffered portion - a_overlap = a_unary.intersection(a_buff_overlap) - b_overlap = b_unary.intersection(b_buff_overlap) - - # what % of each's lines length does that intersecting portion comprise? - a_length_pct = a_overlap.length / a_unary.length - b_length_pct = b_overlap.length / b_unary.length - - return a_area_pct, b_area_pct, a_length_pct, b_length_pct - - -# RUN THE SCRIPT -indicators = {} -for city in cities: - - print(ox.ts(), f"begin processing {city}") - indicators[city] = {} - - # load this city's configs - with open(f"../configuration/{city}.json") as f: - config = json.load(f) - - # load street gdfs from osm graph and official shapefile, then clip to study area boundary polygon - gdf_osm_streets, gdf_official_streets, study_area = load_data( - config["osm_graphml_path"], config["osm_buffer_gpkg_path"], config["official_streets_gpkg_path"] - ) - - # plot map of study area + osm and official streets, save to disk - fp = figure_filepath.format(city=city) - fig, ax = plot_data(gdf_osm_streets, gdf_official_streets, study_area, fp) - - # calculate total street length and edge count in each dataset, then add to indicators - osm_total_length, osm_edge_count = total_edge_length_count(gdf_osm_streets) - official_total_length, official_edge_count = total_edge_length_count(gdf_official_streets) - indicators[city]["osm_total_length"] = osm_total_length - indicators[city]["osm_edge_count"] = osm_edge_count - indicators[city]["official_total_length"] = official_total_length - indicators[city]["official_edge_count"] = official_edge_count - print(ox.ts(), "calculated edge lengths and counts") - - # calculate the % overlaps of areas and lengths between osm and official streets with different buffer distances - for dist in edge_buffer_dists: - osm_area_pct, official_area_pct, osm_length_pct, official_length_pct = calculate_overlap( - gdf_osm_streets, gdf_official_streets, dist - ) - indicators[city][f"osm_area_pct_{dist}"] = osm_area_pct - indicators[city][f"official_area_pct_{dist}"] = official_area_pct - indicators[city][f"osm_length_pct_{dist}"] = osm_length_pct - indicators[city][f"official_length_pct_{dist}"] = official_length_pct - print(ox.ts(), f"calculated area/length of overlaps for buffer {dist}") - -# turn indicators into a dataframe and save to disk -df_ind = pd.DataFrame(indicators).T -df_ind.to_csv(indicators_filepath, index=True, encoding="utf-8") -print(ox.ts(), f'all done, saved indicators to disk at "{indicators_filepath}"') +import json +import os + +import geopandas as gpd +import matplotlib.pyplot as plt +import pandas as pd + +import osmnx as ox + +# configure script +cities = ["olomouc", "belfast", "hong_kong"] +edge_buffer_dists = [10, 50] +indicators_filepath = "./indicators.csv" +figure_filepath = "./fig/street-comparison-{city}.png" + +if not os.path.exists("./fig/"): + os.makedirs("./fig/") + + +def load_data(osm_graphml_path, osm_buffer_gpkg_path, official_streets_gpkg_path): + """ + Load the street network edges and study boundary. + + Parameters + ---------- + osm_graphml_path : str + path to the OSM graphml file + osm_buffer_gpkg_path : str + path to the buffered study area geopackage + official_streets_gpkg_path : str + path to the official streets shapefile + + Returns + ------- + gdf_osm_streets_clipped, gdf_official_streets_clipped, study_area : tuple + the osm streets (clipped to the study area), the official streets + (clipped to the study area), and the study area polygon + """ + + # load the study area boundary as a shapely (multi)polygon + gdf_study_area = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region") + study_area = gdf_study_area["geometry"].iloc[0] + print(ox.ts(), "loaded study area boundary") + + # load the official streets shapefile + gdf_official_streets = gpd.read_file(official_streets_gpkg_path) + print(ox.ts(), "loaded official streets shapefile") + + # load the graph, make it undirected, then get edges GeoDataFrame + gdf_osm_streets = ox.graph_to_gdfs(ox.get_undirected(ox.load_graphml(osm_graphml_path)), nodes=False) + print(ox.ts(), "loaded osm edges and made undirected streets") + + # Project the data to a common crs + crs = gdf_study_area.crs + if gdf_osm_streets.crs != crs: + gdf_osm_streets = gdf_osm_streets.to_crs(crs) + print(ox.ts(), "projected osm streets") + if gdf_official_streets.crs != crs: + gdf_official_streets = gdf_official_streets.to_crs(crs) + print(ox.ts(), "projected official streets") + + # spatially clip the streets to the study area boundary + import warnings + + warnings.filterwarnings("ignore", "GeoSeries.notna", UserWarning) # temp warning suppression + gdf_osm_streets_clipped = gpd.clip(gdf_osm_streets, study_area) + gdf_official_streets_clipped = gpd.clip(gdf_official_streets, study_area) + print(ox.ts(), "clipped osm/official streets to study area boundary") + + # double-check everything has same CRS, then return + assert gdf_osm_streets_clipped.crs == gdf_official_streets_clipped.crs == gdf_study_area.crs + return gdf_osm_streets_clipped, gdf_official_streets_clipped, study_area + + +def plot_data(gdf_osm, gdf_official, study_area, filepath, figsize=(10, 10), bgcolor="#333333", projected=True): + """ + Plot the OSM vs official streets and save to disk. + + Parameters + ---------- + gdf_osm : geopandas.GeoDataFrame + the osm streets + gdf_official : geopandas.GeoDataFrame + the official streets + study_area : shapely.Polygon or shapely.MultiPolygon + the study area boundary + filepath : str + path to save figure as file + figsize : tuple + size of plotting figure + bgcolor : str + background color of plot + projected : bool + True if gdfs are projected rather than lat-lng + + Returns + ------- + fig, ax : tuple + """ + + fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor) + ax.set_facecolor(bgcolor) + + # turn study_area polygon into gdf with correct CRS + gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm.crs) + + # plot study area, then official streets, then osm streets as layers + _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area") + _ = gdf_official.plot(ax=ax, color="r", lw=1, label="Official Data") + _ = gdf_osm.plot(ax=ax, color="y", lw=1, label="OSM Data") + + ax.axis("off") + if projected: + # only make x/y equal-aspect if data are projected + ax.set_aspect("equal") + + # create legend + ax.legend() + + # save to disk + fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor()) + print(ox.ts(), f'figure saved to disk at "{filepath}"') + + plt.close() + return fig, ax + + +def total_edge_length_count(gdf_streets): + """ + Calculate the total length and count of streets in gdf. + + Parameters + ---------- + gdf_streets : geopandas.GeoDataFrame + the osm or official streets + + Returns + ------- + streets_total_length, streets_count : tuple + """ + streets_total_length = gdf_streets.length.sum() + streets_count = len(gdf_streets) + return streets_total_length, streets_count + + +def calculate_overlap(a, b, dist): + """ + Calculate the % overlap of a and b's lines and buffered lines' areas + given different buffering distances. + + Parameters + ---------- + a : geopandas.GeoDataFrame + the osm streets + b : geopandas.GeoDataFrame + the osm streets + dist : int + buffer distance in meters + + Returns + ------- + a_area_pct, b_area_pct, a_length_pct, b_length_pct : tuple + """ + + # buffer each by the current distance + a_buff = a.buffer(dist) + b_buff = b.buffer(dist) + + # take the unary union of each's buffered geometry + a_buff_unary = a_buff.unary_union + b_buff_unary = b_buff.unary_union + + # find the portion of each's buffered geometry that intersects with the other's buffered geometry + a_buff_overlap = a_buff_unary.intersection(b_buff_unary) + b_buff_overlap = b_buff_unary.intersection(a_buff_unary) + + # what % of each's buffered area does that intersecting portion comprise? + a_area_pct = a_buff_overlap.area / a_buff_unary.area + b_area_pct = b_buff_overlap.area / b_buff_unary.area + + # take the unary union of each's original unbuffered lines + a_unary = a.unary_union + b_unary = b.unary_union + + # find each's lines that intersect the intersecting buffered portion + a_overlap = a_unary.intersection(a_buff_overlap) + b_overlap = b_unary.intersection(b_buff_overlap) + + # what % of each's lines length does that intersecting portion comprise? + a_length_pct = a_overlap.length / a_unary.length + b_length_pct = b_overlap.length / b_unary.length + + return a_area_pct, b_area_pct, a_length_pct, b_length_pct + + +# RUN THE SCRIPT +indicators = {} +for city in cities: + + print(ox.ts(), f"begin processing {city}") + indicators[city] = {} + + # load this city's configs + with open(f"../configuration/{city}.json") as f: + config = json.load(f) + + # load street gdfs from osm graph and official shapefile, then clip to study area boundary polygon + gdf_osm_streets, gdf_official_streets, study_area = load_data( + config["osm_graphml_path"], config["osm_buffer_gpkg_path"], config["official_streets_gpkg_path"] + ) + + # plot map of study area + osm and official streets, save to disk + fp = figure_filepath.format(city=city) + fig, ax = plot_data(gdf_osm_streets, gdf_official_streets, study_area, fp) + + # calculate total street length and edge count in each dataset, then add to indicators + osm_total_length, osm_edge_count = total_edge_length_count(gdf_osm_streets) + official_total_length, official_edge_count = total_edge_length_count(gdf_official_streets) + indicators[city]["osm_total_length"] = osm_total_length + indicators[city]["osm_edge_count"] = osm_edge_count + indicators[city]["official_total_length"] = official_total_length + indicators[city]["official_edge_count"] = official_edge_count + print(ox.ts(), "calculated edge lengths and counts") + + # calculate the % overlaps of areas and lengths between osm and official streets with different buffer distances + for dist in edge_buffer_dists: + osm_area_pct, official_area_pct, osm_length_pct, official_length_pct = calculate_overlap( + gdf_osm_streets, gdf_official_streets, dist + ) + indicators[city][f"osm_area_pct_{dist}"] = osm_area_pct + indicators[city][f"official_area_pct_{dist}"] = official_area_pct + indicators[city][f"osm_length_pct_{dist}"] = osm_length_pct + indicators[city][f"official_length_pct_{dist}"] = official_length_pct + print(ox.ts(), f"calculated area/length of overlaps for buffer {dist}") + +# turn indicators into a dataframe and save to disk +df_ind = pd.DataFrame(indicators).T +df_ind.to_csv(indicators_filepath, index=True, encoding="utf-8") +print(ox.ts(), f'all done, saved indicators to disk at "{indicators_filepath}"') diff --git a/validation/edge/indicators.csv b/validation/edge/indicators.csv index 05e2d680..6048187d 100644 --- a/validation/edge/indicators.csv +++ b/validation/edge/indicators.csv @@ -1,4 +1,4 @@ -,osm_total_length,osm_edge_count,official_total_length,official_edge_count,osm_area_pct_10,official_area_pct_10,osm_length_pct_10,official_length_pct_10,osm_area_pct_50,official_area_pct_50,osm_length_pct_50,official_length_pct_50 -olomouc,615698.9807693845,14164.0,310453.8120588681,4149.0,0.5706732938611149,0.9014617543325479,0.663416809717805,0.9344340231961282,0.8242369451593459,0.9648785210159337,0.9024458956615621,0.9812246969043628 -belfast,1700228.4192550103,26244.0,1330205.3149234985,18662.0,0.7073693626426616,0.8521559850051947,0.7506685528606951,0.9070976047575989,0.873122038420173,0.9622240439550545,0.9081632964124647,0.9812388816692991 -hong_kong,7216556.596995515,108435.0,2910775.120067608,28953.0,0.399247822283021,0.9404854786571645,0.5094358041011204,0.9894850661660249,0.48401699998375664,0.993650166817977,0.6962067174965808,0.9985834243019279 +,osm_total_length,osm_edge_count,official_total_length,official_edge_count,osm_area_pct_10,official_area_pct_10,osm_length_pct_10,official_length_pct_10,osm_area_pct_50,official_area_pct_50,osm_length_pct_50,official_length_pct_50 +olomouc,615698.9807693845,14164.0,310453.8120588681,4149.0,0.5706732938611149,0.9014617543325479,0.663416809717805,0.9344340231961282,0.8242369451593459,0.9648785210159337,0.9024458956615621,0.9812246969043628 +belfast,1700228.4192550103,26244.0,1330205.3149234985,18662.0,0.7073693626426616,0.8521559850051947,0.7506685528606951,0.9070976047575989,0.873122038420173,0.9622240439550545,0.9081632964124647,0.9812388816692991 +hong_kong,7216556.596995515,108435.0,2910775.120067608,28953.0,0.399247822283021,0.9404854786571645,0.5094358041011204,0.9894850661660249,0.48401699998375664,0.993650166817977,0.6962067174965808,0.9985834243019279 diff --git a/validation/edge/readme.md b/validation/edge/readme.md index f69f8c44..f47126ee 100644 --- a/validation/edge/readme.md +++ b/validation/edge/readme.md @@ -1,14 +1,14 @@ -| Indicator Name | Indicator Decription | -| -------------- | -------------------- | -| osm_total_length | Total length of streets in the OSM dervived street network in meters -| osm_edge_count | Total count of streets in the OSM derived street network in meters -| official_total_length | Total length of streets in the Official dervived street network in meters -| official_edge_count | Total count of streets in the Official dervived street network in meters -| osm_area_pct_10 | Proportion of area of buffered OSM network that overlaps with buffered Official network out of total area of buffered OSM network when buffer is 10 meters -| official_area_pct_10 | Proportion of area of buffered Official network that overlaps with buffered OSM network out of total area of buffered Official network when buffer is 10 meters -| osm_length_pct_10 | Proportion of length of OSM network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the OSM network when said buffer is 10 meters -| official_length_pct_10 | Proportion of length of Official network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the Official network when said buffer is 10 meters -| osm_area_pct_50 | Proportion of area of buffered OSM network that overlaps with buffered Official network out of total area of buffered OSM network when buffer is 50 meters -| official_area_pct_50 | Proportion of area of buffered Official network that overlaps with buffered OSM network out of total area of buffered Official network when buffer is 50 meters -| osm_length_pct_50 | Proportion of length of OSM network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the OSM network when said buffer is 50 meters -| official_length_pct_50 | Proportion of length of Official network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the Official network when said buffer is 50 meters +| Indicator Name | Indicator Decription | +| -------------- | -------------------- | +| osm_total_length | Total length of streets in the OSM dervived street network in meters +| osm_edge_count | Total count of streets in the OSM derived street network in meters +| official_total_length | Total length of streets in the Official dervived street network in meters +| official_edge_count | Total count of streets in the Official dervived street network in meters +| osm_area_pct_10 | Proportion of area of buffered OSM network that overlaps with buffered Official network out of total area of buffered OSM network when buffer is 10 meters +| official_area_pct_10 | Proportion of area of buffered Official network that overlaps with buffered OSM network out of total area of buffered Official network when buffer is 10 meters +| osm_length_pct_10 | Proportion of length of OSM network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the OSM network when said buffer is 10 meters +| official_length_pct_10 | Proportion of length of Official network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the Official network when said buffer is 10 meters +| osm_area_pct_50 | Proportion of area of buffered OSM network that overlaps with buffered Official network out of total area of buffered OSM network when buffer is 50 meters +| official_area_pct_50 | Proportion of area of buffered Official network that overlaps with buffered OSM network out of total area of buffered Official network when buffer is 50 meters +| osm_length_pct_50 | Proportion of length of OSM network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the OSM network when said buffer is 50 meters +| official_length_pct_50 | Proportion of length of Official network that intersects with the geometry of the overlapping buffer areas of both the OSM and Official networks out of the total length of the Official network when said buffer is 50 meters diff --git a/validation/groundtruthing/1.CreateExcel.ipynb b/validation/groundtruthing/1.CreateExcel.ipynb index f8049a1c..b7e200d5 100644 --- a/validation/groundtruthing/1.CreateExcel.ipynb +++ b/validation/groundtruthing/1.CreateExcel.ipynb @@ -1,657 +1,657 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "import os\n", - "import geopandas as gpd\n", - "import matplotlib.pyplot as plt\n", - "import pandas as pd\n", - "import osmnx as ox\n", - "import random\n", - "import numpy as np\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "cities = ['adelaide',\n", - "'auckland',\n", - "'baltimore',\n", - "'bangkok',\n", - "'barcelona',\n", - "'belfast',\n", - "'bern',\n", - "'chennai',\n", - "'mexico_city',\n", - "'cologne',\n", - "'ghent',\n", - "'graz',\n", - "'hanoi',\n", - "'hong_kong',\n", - "'lisbon',\n", - "'melbourne',\n", - "'odense',\n", - "'olomouc',\n", - "'sao_paulo', \n", - "'phoenix',\n", - "'seattle',\n", - "'sydney',\n", - "'valencia',\n", - "'vic'\n", - " ]" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "process_folder = '../../process'\n", - "pop_col = [\"pop_ghs_2015\"]\n", - "dest_col = [\"destinations\"]\n", - "filenames_filepath = \"./groundtruthing.csv\"\n", - "np.random.seed(24)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "start adelaide\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "adelaide shape below\n", - "(50, 29)\n", - "2020-11-02 04:32:31 finshed names for adelaide\n", - "start auckland\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "auckland shape below\n", - "(50, 29)\n", - "2020-11-02 04:44:55 finshed names for auckland\n", - "start baltimore\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "baltimore shape below\n", - "(50, 29)\n", - "2020-11-02 04:45:19 finshed names for baltimore\n", - "start bangkok\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "bangkok shape below\n", - "(50, 29)\n", - "2020-11-02 04:47:13 finshed names for bangkok\n", - "start barcelona\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "barcelona shape below\n", - "(50, 29)\n", - "2020-11-02 04:48:14 finshed names for barcelona\n", - "start belfast\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "belfast shape below\n", - "(50, 29)\n", - "2020-11-02 04:48:27 finshed names for belfast\n", - "start bern\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "bern shape below\n", - "(50, 29)\n", - "2020-11-02 04:48:30 finshed names for bern\n", - "start chennai\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "chennai shape below\n", - "(50, 29)\n", - "2020-11-02 04:48:48 finshed names for chennai\n", - "start mexico_city\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "mexico_city shape below\n", - "(50, 29)\n", - "2020-11-02 04:51:29 finshed names for mexico_city\n", - "start cologne\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cologne shape below\n", - "(50, 29)\n", - "2020-11-02 04:51:59 finshed names for cologne\n", - "start ghent\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ghent shape below\n", - "(50, 29)\n", - "2020-11-02 04:52:05 finshed names for ghent\n", - "start graz\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "graz shape below\n", - "(50, 28)\n", - "2020-11-02 04:52:09 finshed names for graz\n", - "start hanoi\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "hanoi shape below\n", - "(50, 29)\n", - "2020-11-02 04:53:50 finshed names for hanoi\n", - "start hong_kong\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "hong_kong shape below\n", - "(50, 29)\n", - "2020-11-02 05:03:21 finshed names for hong_kong\n", - "start lisbon\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "lisbon shape below\n", - "(50, 29)\n", - "2020-11-02 05:03:31 finshed names for lisbon\n", - "start melbourne\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "melbourne shape below\n", - "(50, 29)\n", - "2020-11-02 05:08:07 finshed names for melbourne\n", - "start odense\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "odense shape below\n", - "(50, 28)\n", - "2020-11-02 05:08:35 finshed names for odense\n", - "start olomouc\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "olomouc shape below\n", - "(50, 29)\n", - "2020-11-02 05:08:37 finshed names for olomouc\n", - "start sao_paulo\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sao_paulo shape below\n", - "(50, 29)\n", - "2020-11-02 05:09:16 finshed names for sao_paulo\n", - "start phoenix\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "phoenix shape below\n", - "(50, 29)\n", - "2020-11-02 05:10:42 finshed names for phoenix\n", - "start seattle\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "seattle shape below\n", - "(50, 29)\n", - "2020-11-02 05:12:33 finshed names for seattle\n", - "start sydney\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sydney shape below\n", - "(50, 29)\n", - "2020-11-02 06:06:58 finshed names for sydney\n", - "start valencia\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "valencia shape below\n", - "(50, 29)\n", - "2020-11-02 06:07:12 finshed names for valencia\n", - "start vic\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", - " return _prepare_from_string(\" \".join(pjargs))\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "vic shape below\n", - "(50, 28)\n", - "2020-11-02 06:07:15 finshed names for vic\n", - "2020-11-02 06:07:15 all done, saved filenames to disk at \"./groundtruthing.csv\"\n" - ] - } - ], - "source": [ - "filenames = {}\n", - "\n", - "for city in cities:\n", - " \n", - " print(f\"start {city}\")\n", - "\n", - " process_config_path = f\"../../process/configuration/{city}.json\"\n", - "\n", - " with open(process_config_path) as json_file:\n", - " config = json.load(json_file)\n", - "\n", - " input_folder = os.path.join(process_folder, config['folder'])\n", - "\n", - " gpkg_input = os.path.join(input_folder, config['geopackagePath'])\n", - "\n", - " pop = gpd.read_file(gpkg_input, layer='pop_ghs_2015' )\n", - "\n", - " dests = gpd.read_file(gpkg_input, layer='destinations' )\n", - "\n", - " fresh_food = dests[dests['dest_name_full'].str.contains('Fresh Food / Market')]\n", - "\n", - " gdf_study_area = gpd.read_file(gpkg_input, layer=\"urban_study_region\")\n", - " study_area = gdf_study_area[\"geometry\"].iloc[0]\n", - "\n", - " crs = gdf_study_area.crs\n", - " if pop.crs != crs:\n", - " pop = pop.to_crs(crs)\n", - " if fresh_food.crs != crs:\n", - " fresh_food = fresh_food.to_crs(crs)\n", - "\n", - " import warnings\n", - "\n", - " warnings.filterwarnings(\"ignore\", \"GeoSeries.notna\", UserWarning) # temp warning suppression\n", - " pop_clipped = gpd.clip(pop, study_area)\n", - " fresh_food_clipped = gpd.clip(fresh_food, study_area)\n", - "\n", - " joined_freshfood = gpd.sjoin(fresh_food_clipped, pop_clipped, how='left', op='within')\n", - "\n", - " ordered_joined_freshfood = joined_freshfood.sort_values('pop_est')\n", - "\n", - " split_joined_freshfood = np.array_split(ordered_joined_freshfood, 5)\n", - "\n", - " q1_dests = (split_joined_freshfood[0])\n", - " q2_dests = (split_joined_freshfood[1])\n", - " q3_dests = (split_joined_freshfood[2])\n", - " q4_dests = (split_joined_freshfood[3])\n", - " q5_dests = (split_joined_freshfood[4])\n", - "\n", - " q1_dests['quantile'] = 1\n", - " q2_dests['quantile'] = 2\n", - " q3_dests['quantile'] = 3\n", - " q4_dests['quantile'] = 4\n", - " q5_dests['quantile'] = 5\n", - "\n", - " q1_sample_dests = q1_dests.sample(10)\n", - " q2_sample_dests = q2_dests.sample(10)\n", - " q3_sample_dests = q3_dests.sample(10)\n", - " q4_sample_dests = q4_dests.sample(10)\n", - " q5_sample_dests = q5_dests.sample(10)\n", - "\n", - " sample_dests = [q1_sample_dests, q2_sample_dests, q3_sample_dests, q4_sample_dests, q5_sample_dests]\n", - "\n", - " final_sample_dests = pd.concat(sample_dests)\n", - "\n", - " final_sample_dests = final_sample_dests.to_crs({'init': 'epsg:4326'})\n", - "\n", - " final_sample_dests['lat'] = final_sample_dests.geometry.y\n", - " final_sample_dests['lon'] = final_sample_dests.geometry.x\n", - " \n", - " final_sample_dests = final_sample_dests.set_index('osm_id')\n", - " \n", - " \n", - " print(f\"{city} shape below\")\n", - " print(final_sample_dests.shape)\n", - "\n", - " for index, row in final_sample_dests.iterrows():\n", - " filenames[index] = {}\n", - "\n", - " city_name = city\n", - " hexagon_pop_quantile = row['quantile']\n", - " latitude = row['lat']\n", - " longitude = row['lon']\n", - " google_maps_screenshot = f\"{latitude}_{longitude}_{city}_google_maps_image\"\n", - " google_satellite_screenshot = f\"{latitude}_{longitude}_{city}_google_satellite_image\"\n", - " google_street_view_screenshot = f\"{latitude}_{longitude}_{city}_google_street_view_image\"\n", - "\n", - " # calculate total street length and edge count in each dataset, then add to indicators\n", - " filenames[index][\"Hexagon_Pop_Quintile\"] = hexagon_pop_quantile\n", - " filenames[index][\"City_Name\"] = city_name\n", - " filenames[index][\"Latitude\"] = latitude\n", - " filenames[index][\"Longitude\"] = longitude\n", - " filenames[index][\"Google_Maps_Date\"] = \"\"\n", - " filenames[index][\"Google_Maps_Screenshot\"] = google_maps_screenshot\n", - " filenames[index][\"Google_Satellite_Date\"] = \"\"\n", - " filenames[index][\"Google_Satellite_Screenshot\"] = google_satellite_screenshot\n", - " filenames[index][\"Google_Street_View_Date\"] = \"\"\n", - " filenames[index][\"Google_Street_View_Screenshot\"] = google_street_view_screenshot\n", - " filenames[index][\"Assessment\"] = \"\"\n", - " filenames[index][\"Comments\"] = \"\"\n", - "\n", - " print(ox.ts(), f\"finshed names for {city}\")\n", - "\n", - "# turn indicators into a dataframe and save to disk\n", - "df_filenames = pd.DataFrame(filenames).T\n", - "df_filenames.to_csv(filenames_filepath, index=True, encoding=\"utf-8\")\n", - "print(ox.ts(), f'all done, saved filenames to disk at \"{filenames_filepath}\"')\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python (GlobalInd)", - "language": "python", - "name": "globalind" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import os\n", + "import geopandas as gpd\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "import osmnx as ox\n", + "import random\n", + "import numpy as np\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "cities = ['adelaide',\n", + "'auckland',\n", + "'baltimore',\n", + "'bangkok',\n", + "'barcelona',\n", + "'belfast',\n", + "'bern',\n", + "'chennai',\n", + "'mexico_city',\n", + "'cologne',\n", + "'ghent',\n", + "'graz',\n", + "'hanoi',\n", + "'hong_kong',\n", + "'lisbon',\n", + "'melbourne',\n", + "'odense',\n", + "'olomouc',\n", + "'sao_paulo', \n", + "'phoenix',\n", + "'seattle',\n", + "'sydney',\n", + "'valencia',\n", + "'vic'\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "process_folder = '../../process'\n", + "pop_col = [\"pop_ghs_2015\"]\n", + "dest_col = [\"destinations\"]\n", + "filenames_filepath = \"./groundtruthing.csv\"\n", + "np.random.seed(24)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "start adelaide\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "adelaide shape below\n", + "(50, 29)\n", + "2020-11-02 04:32:31 finshed names for adelaide\n", + "start auckland\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "auckland shape below\n", + "(50, 29)\n", + "2020-11-02 04:44:55 finshed names for auckland\n", + "start baltimore\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "baltimore shape below\n", + "(50, 29)\n", + "2020-11-02 04:45:19 finshed names for baltimore\n", + "start bangkok\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bangkok shape below\n", + "(50, 29)\n", + "2020-11-02 04:47:13 finshed names for bangkok\n", + "start barcelona\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "barcelona shape below\n", + "(50, 29)\n", + "2020-11-02 04:48:14 finshed names for barcelona\n", + "start belfast\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "belfast shape below\n", + "(50, 29)\n", + "2020-11-02 04:48:27 finshed names for belfast\n", + "start bern\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bern shape below\n", + "(50, 29)\n", + "2020-11-02 04:48:30 finshed names for bern\n", + "start chennai\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "chennai shape below\n", + "(50, 29)\n", + "2020-11-02 04:48:48 finshed names for chennai\n", + "start mexico_city\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mexico_city shape below\n", + "(50, 29)\n", + "2020-11-02 04:51:29 finshed names for mexico_city\n", + "start cologne\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cologne shape below\n", + "(50, 29)\n", + "2020-11-02 04:51:59 finshed names for cologne\n", + "start ghent\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ghent shape below\n", + "(50, 29)\n", + "2020-11-02 04:52:05 finshed names for ghent\n", + "start graz\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "graz shape below\n", + "(50, 28)\n", + "2020-11-02 04:52:09 finshed names for graz\n", + "start hanoi\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hanoi shape below\n", + "(50, 29)\n", + "2020-11-02 04:53:50 finshed names for hanoi\n", + "start hong_kong\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hong_kong shape below\n", + "(50, 29)\n", + "2020-11-02 05:03:21 finshed names for hong_kong\n", + "start lisbon\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "lisbon shape below\n", + "(50, 29)\n", + "2020-11-02 05:03:31 finshed names for lisbon\n", + "start melbourne\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "melbourne shape below\n", + "(50, 29)\n", + "2020-11-02 05:08:07 finshed names for melbourne\n", + "start odense\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "odense shape below\n", + "(50, 28)\n", + "2020-11-02 05:08:35 finshed names for odense\n", + "start olomouc\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "olomouc shape below\n", + "(50, 29)\n", + "2020-11-02 05:08:37 finshed names for olomouc\n", + "start sao_paulo\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sao_paulo shape below\n", + "(50, 29)\n", + "2020-11-02 05:09:16 finshed names for sao_paulo\n", + "start phoenix\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "phoenix shape below\n", + "(50, 29)\n", + "2020-11-02 05:10:42 finshed names for phoenix\n", + "start seattle\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "seattle shape below\n", + "(50, 29)\n", + "2020-11-02 05:12:33 finshed names for seattle\n", + "start sydney\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sydney shape below\n", + "(50, 29)\n", + "2020-11-02 06:06:58 finshed names for sydney\n", + "start valencia\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "valencia shape below\n", + "(50, 29)\n", + "2020-11-02 06:07:12 finshed names for valencia\n", + "start vic\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.7/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=:' syntax is deprecated. ':' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6\n", + " return _prepare_from_string(\" \".join(pjargs))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "vic shape below\n", + "(50, 28)\n", + "2020-11-02 06:07:15 finshed names for vic\n", + "2020-11-02 06:07:15 all done, saved filenames to disk at \"./groundtruthing.csv\"\n" + ] + } + ], + "source": [ + "filenames = {}\n", + "\n", + "for city in cities:\n", + " \n", + " print(f\"start {city}\")\n", + "\n", + " process_config_path = f\"../../process/configuration/{city}.json\"\n", + "\n", + " with open(process_config_path) as json_file:\n", + " config = json.load(json_file)\n", + "\n", + " input_folder = os.path.join(process_folder, config['folder'])\n", + "\n", + " gpkg_input = os.path.join(input_folder, config['geopackagePath'])\n", + "\n", + " pop = gpd.read_file(gpkg_input, layer='pop_ghs_2015' )\n", + "\n", + " dests = gpd.read_file(gpkg_input, layer='destinations' )\n", + "\n", + " fresh_food = dests[dests['dest_name_full'].str.contains('Fresh Food / Market')]\n", + "\n", + " gdf_study_area = gpd.read_file(gpkg_input, layer=\"urban_study_region\")\n", + " study_area = gdf_study_area[\"geometry\"].iloc[0]\n", + "\n", + " crs = gdf_study_area.crs\n", + " if pop.crs != crs:\n", + " pop = pop.to_crs(crs)\n", + " if fresh_food.crs != crs:\n", + " fresh_food = fresh_food.to_crs(crs)\n", + "\n", + " import warnings\n", + "\n", + " warnings.filterwarnings(\"ignore\", \"GeoSeries.notna\", UserWarning) # temp warning suppression\n", + " pop_clipped = gpd.clip(pop, study_area)\n", + " fresh_food_clipped = gpd.clip(fresh_food, study_area)\n", + "\n", + " joined_freshfood = gpd.sjoin(fresh_food_clipped, pop_clipped, how='left', op='within')\n", + "\n", + " ordered_joined_freshfood = joined_freshfood.sort_values('pop_est')\n", + "\n", + " split_joined_freshfood = np.array_split(ordered_joined_freshfood, 5)\n", + "\n", + " q1_dests = (split_joined_freshfood[0])\n", + " q2_dests = (split_joined_freshfood[1])\n", + " q3_dests = (split_joined_freshfood[2])\n", + " q4_dests = (split_joined_freshfood[3])\n", + " q5_dests = (split_joined_freshfood[4])\n", + "\n", + " q1_dests['quantile'] = 1\n", + " q2_dests['quantile'] = 2\n", + " q3_dests['quantile'] = 3\n", + " q4_dests['quantile'] = 4\n", + " q5_dests['quantile'] = 5\n", + "\n", + " q1_sample_dests = q1_dests.sample(10)\n", + " q2_sample_dests = q2_dests.sample(10)\n", + " q3_sample_dests = q3_dests.sample(10)\n", + " q4_sample_dests = q4_dests.sample(10)\n", + " q5_sample_dests = q5_dests.sample(10)\n", + "\n", + " sample_dests = [q1_sample_dests, q2_sample_dests, q3_sample_dests, q4_sample_dests, q5_sample_dests]\n", + "\n", + " final_sample_dests = pd.concat(sample_dests)\n", + "\n", + " final_sample_dests = final_sample_dests.to_crs({'init': 'epsg:4326'})\n", + "\n", + " final_sample_dests['lat'] = final_sample_dests.geometry.y\n", + " final_sample_dests['lon'] = final_sample_dests.geometry.x\n", + " \n", + " final_sample_dests = final_sample_dests.set_index('osm_id')\n", + " \n", + " \n", + " print(f\"{city} shape below\")\n", + " print(final_sample_dests.shape)\n", + "\n", + " for index, row in final_sample_dests.iterrows():\n", + " filenames[index] = {}\n", + "\n", + " city_name = city\n", + " hexagon_pop_quantile = row['quantile']\n", + " latitude = row['lat']\n", + " longitude = row['lon']\n", + " google_maps_screenshot = f\"{latitude}_{longitude}_{city}_google_maps_image\"\n", + " google_satellite_screenshot = f\"{latitude}_{longitude}_{city}_google_satellite_image\"\n", + " google_street_view_screenshot = f\"{latitude}_{longitude}_{city}_google_street_view_image\"\n", + "\n", + " # calculate total street length and edge count in each dataset, then add to indicators\n", + " filenames[index][\"Hexagon_Pop_Quintile\"] = hexagon_pop_quantile\n", + " filenames[index][\"City_Name\"] = city_name\n", + " filenames[index][\"Latitude\"] = latitude\n", + " filenames[index][\"Longitude\"] = longitude\n", + " filenames[index][\"Google_Maps_Date\"] = \"\"\n", + " filenames[index][\"Google_Maps_Screenshot\"] = google_maps_screenshot\n", + " filenames[index][\"Google_Satellite_Date\"] = \"\"\n", + " filenames[index][\"Google_Satellite_Screenshot\"] = google_satellite_screenshot\n", + " filenames[index][\"Google_Street_View_Date\"] = \"\"\n", + " filenames[index][\"Google_Street_View_Screenshot\"] = google_street_view_screenshot\n", + " filenames[index][\"Assessment\"] = \"\"\n", + " filenames[index][\"Comments\"] = \"\"\n", + "\n", + " print(ox.ts(), f\"finshed names for {city}\")\n", + "\n", + "# turn indicators into a dataframe and save to disk\n", + "df_filenames = pd.DataFrame(filenames).T\n", + "df_filenames.to_csv(filenames_filepath, index=True, encoding=\"utf-8\")\n", + "print(ox.ts(), f'all done, saved filenames to disk at \"{filenames_filepath}\"')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (GlobalInd)", + "language": "python", + "name": "globalind" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/validation/groundtruthing/groundtruthing.csv b/validation/groundtruthing/groundtruthing.csv index 6870f599..a63ea817 100644 --- a/validation/groundtruthing/groundtruthing.csv +++ b/validation/groundtruthing/groundtruthing.csv @@ -1,1201 +1,1201 @@ -,Hexagon_Pop_Quintile,City_Name,Latitude,Longitude,Google_Maps_Date,Google_Maps_Screenshot,Google_Satellite_Date,Google_Satellite_Screenshot,Google_Street_View_Date,Google_Street_View_Screenshot,Assessment,Comments -554005639,1,adelaide,-35.143438257775365,138.51536002777152,,-35.143438257775365_138.51536002777152_adelaide_google_maps_image,,-35.143438257775365_138.51536002777152_adelaide_google_satellite_image,,-35.143438257775365_138.51536002777152_adelaide_google_street_view_image,, -4836645274,1,adelaide,-34.86514799001913,138.5803557751897,,-34.86514799001913_138.5803557751897_adelaide_google_maps_image,,-34.86514799001913_138.5803557751897_adelaide_google_satellite_image,,-34.86514799001913_138.5803557751897_adelaide_google_street_view_image,, -2424960625,1,adelaide,-34.76357904120694,138.63967983856986,,-34.76357904120694_138.63967983856986_adelaide_google_maps_image,,-34.76357904120694_138.63967983856986_adelaide_google_satellite_image,,-34.76357904120694_138.63967983856986_adelaide_google_street_view_image,, -5330994352,1,adelaide,-35.106989199999674,138.5209602,,-35.106989199999674_138.5209602_adelaide_google_maps_image,,-35.106989199999674_138.5209602_adelaide_google_satellite_image,,-35.106989199999674_138.5209602_adelaide_google_street_view_image,, -2029087875,1,adelaide,-35.0783784187871,138.51632720510028,,-35.0783784187871_138.51632720510028_adelaide_google_maps_image,,-35.0783784187871_138.51632720510028_adelaide_google_satellite_image,,-35.0783784187871_138.51632720510028_adelaide_google_street_view_image,, -5344476192,1,adelaide,-35.143583429488004,138.49892445433653,,-35.143583429488004_138.49892445433653_adelaide_google_maps_image,,-35.143583429488004_138.49892445433653_adelaide_google_satellite_image,,-35.143583429488004_138.49892445433653_adelaide_google_street_view_image,, -4835897220,1,adelaide,-34.8807639145066,138.49080207813984,,-34.8807639145066_138.49080207813984_adelaide_google_maps_image,,-34.8807639145066_138.49080207813984_adelaide_google_satellite_image,,-34.8807639145066_138.49080207813984_adelaide_google_street_view_image,, -4504321790,1,adelaide,-34.83022588935792,138.69150549539364,,-34.83022588935792_138.69150549539364_adelaide_google_maps_image,,-34.83022588935792_138.69150549539364_adelaide_google_satellite_image,,-34.83022588935792_138.69150549539364_adelaide_google_street_view_image,, -653722296,1,adelaide,-34.93503095760668,138.5233089708756,,-34.93503095760668_138.5233089708756_adelaide_google_maps_image,,-34.93503095760668_138.5233089708756_adelaide_google_satellite_image,,-34.93503095760668_138.5233089708756_adelaide_google_street_view_image,, -5411249887,1,adelaide,-35.08979629131564,138.54053603057898,,-35.08979629131564_138.54053603057898_adelaide_google_maps_image,,-35.08979629131564_138.54053603057898_adelaide_google_satellite_image,,-35.08979629131564_138.54053603057898_adelaide_google_street_view_image,, -5062044427,2,adelaide,-34.92461232633713,138.6758709298667,,-34.92461232633713_138.6758709298667_adelaide_google_maps_image,,-34.92461232633713_138.6758709298667_adelaide_google_satellite_image,,-34.92461232633713_138.6758709298667_adelaide_google_street_view_image,, -2396009490,2,adelaide,-34.87399205684018,138.54941641900663,,-34.87399205684018_138.54941641900663_adelaide_google_maps_image,,-34.87399205684018_138.54941641900663_adelaide_google_satellite_image,,-34.87399205684018_138.54941641900663_adelaide_google_street_view_image,, -6251187686,2,adelaide,-34.9255422399459,138.66330807616768,,-34.9255422399459_138.66330807616768_adelaide_google_maps_image,,-34.9255422399459_138.66330807616768_adelaide_google_satellite_image,,-34.9255422399459_138.66330807616768_adelaide_google_street_view_image,, -451871161,2,adelaide,-34.87412100705163,138.54887612296613,,-34.87412100705163_138.54887612296613_adelaide_google_maps_image,,-34.87412100705163_138.54887612296613_adelaide_google_satellite_image,,-34.87412100705163_138.54887612296613_adelaide_google_street_view_image,, -581224379,2,adelaide,-35.01595031912655,138.52212632385462,,-35.01595031912655_138.52212632385462_adelaide_google_maps_image,,-35.01595031912655_138.52212632385462_adelaide_google_satellite_image,,-35.01595031912655_138.52212632385462_adelaide_google_street_view_image,, -4449963307,2,adelaide,-34.86955596867659,138.52934424630982,,-34.86955596867659_138.52934424630982_adelaide_google_maps_image,,-34.86955596867659_138.52934424630982_adelaide_google_satellite_image,,-34.86955596867659_138.52934424630982_adelaide_google_street_view_image,, -3475954745,2,adelaide,-35.083634984404576,138.56148516157248,,-35.083634984404576_138.56148516157248_adelaide_google_maps_image,,-35.083634984404576_138.56148516157248_adelaide_google_satellite_image,,-35.083634984404576_138.56148516157248_adelaide_google_street_view_image,, -7628155095,2,adelaide,-34.915732357477715,138.6282090255454,,-34.915732357477715_138.6282090255454_adelaide_google_maps_image,,-34.915732357477715_138.6282090255454_adelaide_google_satellite_image,,-34.915732357477715_138.6282090255454_adelaide_google_street_view_image,, -4504307296,2,adelaide,-34.815610148888986,138.69952115036799,,-34.815610148888986_138.69952115036799_adelaide_google_maps_image,,-34.815610148888986_138.69952115036799_adelaide_google_satellite_image,,-34.815610148888986_138.69952115036799_adelaide_google_street_view_image,, -247052429,2,adelaide,-34.89667491882652,138.55682957362384,,-34.89667491882652_138.55682957362384_adelaide_google_maps_image,,-34.89667491882652_138.55682957362384_adelaide_google_satellite_image,,-34.89667491882652_138.55682957362384_adelaide_google_street_view_image,, -6917370085,3,adelaide,-34.90501225689983,138.6561626164692,,-34.90501225689983_138.6561626164692_adelaide_google_maps_image,,-34.90501225689983_138.6561626164692_adelaide_google_satellite_image,,-34.90501225689983_138.6561626164692_adelaide_google_street_view_image,, -187373304,3,adelaide,-34.85180479966862,138.52740469578174,,-34.85180479966862_138.52740469578174_adelaide_google_maps_image,,-34.85180479966862_138.52740469578174_adelaide_google_satellite_image,,-34.85180479966862_138.52740469578174_adelaide_google_street_view_image,, -854633067,3,adelaide,-34.82109013748485,138.71803898114976,,-34.82109013748485_138.71803898114976_adelaide_google_maps_image,,-34.82109013748485_138.71803898114976_adelaide_google_satellite_image,,-34.82109013748485_138.71803898114976_adelaide_google_street_view_image,, -5279252491,3,adelaide,-34.82902578582543,138.67302537884981,,-34.82902578582543_138.67302537884981_adelaide_google_maps_image,,-34.82902578582543_138.67302537884981_adelaide_google_satellite_image,,-34.82902578582543_138.67302537884981_adelaide_google_street_view_image,, -5276627283,3,adelaide,-34.82956401883604,138.6721821352397,,-34.82956401883604_138.6721821352397_adelaide_google_maps_image,,-34.82956401883604_138.6721821352397_adelaide_google_satellite_image,,-34.82956401883604_138.6721821352397_adelaide_google_street_view_image,, -6109038000,3,adelaide,-34.9127703739852,138.67381743342398,,-34.9127703739852_138.67381743342398_adelaide_google_maps_image,,-34.9127703739852_138.67381743342398_adelaide_google_satellite_image,,-34.9127703739852_138.67381743342398_adelaide_google_street_view_image,, -5279252487,3,adelaide,-34.8290433668837,138.67277678975933,,-34.8290433668837_138.67277678975933_adelaide_google_maps_image,,-34.8290433668837_138.67277678975933_adelaide_google_satellite_image,,-34.8290433668837_138.67277678975933_adelaide_google_street_view_image,, -848338230,3,adelaide,-34.874987384168534,138.60159693909236,,-34.874987384168534_138.60159693909236_adelaide_google_maps_image,,-34.874987384168534_138.60159693909236_adelaide_google_satellite_image,,-34.874987384168534_138.60159693909236_adelaide_google_street_view_image,, -447248196,3,adelaide,-34.881058732570345,138.50305979874994,,-34.881058732570345_138.50305979874994_adelaide_google_maps_image,,-34.881058732570345_138.50305979874994_adelaide_google_satellite_image,,-34.881058732570345_138.50305979874994_adelaide_google_street_view_image,, -820424383,3,adelaide,-34.87137581396339,138.7007071923653,,-34.87137581396339_138.7007071923653_adelaide_google_maps_image,,-34.87137581396339_138.7007071923653_adelaide_google_satellite_image,,-34.87137581396339_138.7007071923653_adelaide_google_street_view_image,, -4405228845,4,adelaide,-34.90715509841505,138.59500975793637,,-34.90715509841505_138.59500975793637_adelaide_google_maps_image,,-34.90715509841505_138.59500975793637_adelaide_google_satellite_image,,-34.90715509841505_138.59500975793637_adelaide_google_street_view_image,, -280726477,4,adelaide,-34.95677451738414,138.61477356864373,,-34.95677451738414_138.61477356864373_adelaide_google_maps_image,,-34.95677451738414_138.61477356864373_adelaide_google_satellite_image,,-34.95677451738414_138.61477356864373_adelaide_google_street_view_image,, -2391427400,4,adelaide,-34.90422128999778,138.53066007756823,,-34.90422128999778_138.53066007756823_adelaide_google_maps_image,,-34.90422128999778_138.53066007756823_adelaide_google_satellite_image,,-34.90422128999778_138.53066007756823_adelaide_google_street_view_image,, -5121171286,4,adelaide,-34.89668430471438,138.56536930825325,,-34.89668430471438_138.56536930825325_adelaide_google_maps_image,,-34.89668430471438_138.56536930825325_adelaide_google_satellite_image,,-34.89668430471438_138.56536930825325_adelaide_google_street_view_image,, -2311759501,4,adelaide,-34.91402682289617,138.51424705983135,,-34.91402682289617_138.51424705983135_adelaide_google_maps_image,,-34.91402682289617_138.51424705983135_adelaide_google_satellite_image,,-34.91402682289617_138.51424705983135_adelaide_google_street_view_image,, -2382205204,4,adelaide,-34.85885216244488,138.51962228074902,,-34.85885216244488_138.51962228074902_adelaide_google_maps_image,,-34.85885216244488_138.51962228074902_adelaide_google_satellite_image,,-34.85885216244488_138.51962228074902_adelaide_google_street_view_image,, -479978814,4,adelaide,-34.91446893866868,138.65049014346167,,-34.91446893866868_138.65049014346167_adelaide_google_maps_image,,-34.91446893866868_138.65049014346167_adelaide_google_satellite_image,,-34.91446893866868_138.65049014346167_adelaide_google_street_view_image,, -4438466555,4,adelaide,-34.838636248512685,138.48282194704367,,-34.838636248512685_138.48282194704367_adelaide_google_maps_image,,-34.838636248512685_138.48282194704367_adelaide_google_satellite_image,,-34.838636248512685_138.48282194704367_adelaide_google_street_view_image,, -1868639259,4,adelaide,-34.951825516900925,138.5896636665884,,-34.951825516900925_138.5896636665884_adelaide_google_maps_image,,-34.951825516900925_138.5896636665884_adelaide_google_satellite_image,,-34.951825516900925_138.5896636665884_adelaide_google_street_view_image,, -215062216,4,adelaide,-34.89417336602643,138.56850229074618,,-34.89417336602643_138.56850229074618_adelaide_google_maps_image,,-34.89417336602643_138.56850229074618_adelaide_google_satellite_image,,-34.89417336602643_138.56850229074618_adelaide_google_street_view_image,, -5842960944,5,adelaide,-34.99323107858127,138.56558272241966,,-34.99323107858127_138.56558272241966_adelaide_google_maps_image,,-34.99323107858127_138.56558272241966_adelaide_google_satellite_image,,-34.99323107858127_138.56558272241966_adelaide_google_street_view_image,, -2285373485,5,adelaide,-34.890121587327116,138.57255248555282,,-34.890121587327116_138.57255248555282_adelaide_google_maps_image,,-34.890121587327116_138.57255248555282_adelaide_google_satellite_image,,-34.890121587327116_138.57255248555282_adelaide_google_street_view_image,, -2534586738,5,adelaide,-34.919480495980906,138.51440408277762,,-34.919480495980906_138.51440408277762_adelaide_google_maps_image,,-34.919480495980906_138.51440408277762_adelaide_google_satellite_image,,-34.919480495980906_138.51440408277762_adelaide_google_street_view_image,, -6839233326,5,adelaide,-34.935479273282624,138.63165544920383,,-34.935479273282624_138.63165544920383_adelaide_google_maps_image,,-34.935479273282624_138.63165544920383_adelaide_google_satellite_image,,-34.935479273282624_138.63165544920383_adelaide_google_street_view_image,, -2980575418,5,adelaide,-34.92701442181462,138.65032928948548,,-34.92701442181462_138.65032928948548_adelaide_google_maps_image,,-34.92701442181462_138.65032928948548_adelaide_google_satellite_image,,-34.92701442181462_138.65032928948548_adelaide_google_street_view_image,, -93730429,5,adelaide,-34.92450814949956,138.56186630060256,,-34.92450814949956_138.56186630060256_adelaide_google_maps_image,,-34.92450814949956_138.56186630060256_adelaide_google_satellite_image,,-34.92450814949956_138.56186630060256_adelaide_google_street_view_image,, -1475563597,5,adelaide,-34.77100408312502,138.70648617736288,,-34.77100408312502_138.70648617736288_adelaide_google_maps_image,,-34.77100408312502_138.70648617736288_adelaide_google_satellite_image,,-34.77100408312502_138.70648617736288_adelaide_google_street_view_image,, -6649086885,5,adelaide,-34.91521456266078,138.6319643493004,,-34.91521456266078_138.6319643493004_adelaide_google_maps_image,,-34.91521456266078_138.6319643493004_adelaide_google_satellite_image,,-34.91521456266078_138.6319643493004_adelaide_google_street_view_image,, -1252175664,5,adelaide,-34.83876587531177,138.48385950390235,,-34.83876587531177_138.48385950390235_adelaide_google_maps_image,,-34.83876587531177_138.48385950390235_adelaide_google_satellite_image,,-34.83876587531177_138.48385950390235_adelaide_google_street_view_image,, -314933815,5,adelaide,-34.92742142924,138.65036126675705,,-34.92742142924_138.65036126675705_adelaide_google_maps_image,,-34.92742142924_138.65036126675705_adelaide_google_satellite_image,,-34.92742142924_138.65036126675705_adelaide_google_street_view_image,, -3659973168,1,auckland,-37.0123038643229,174.87616226747159,,-37.0123038643229_174.87616226747159_auckland_google_maps_image,,-37.0123038643229_174.87616226747159_auckland_google_satellite_image,,-37.0123038643229_174.87616226747159_auckland_google_street_view_image,, -4855099660,1,auckland,-36.85230735334339,174.6305803216304,,-36.85230735334339_174.6305803216304_auckland_google_maps_image,,-36.85230735334339_174.6305803216304_auckland_google_satellite_image,,-36.85230735334339_174.6305803216304_auckland_google_street_view_image,, -4855100403,1,auckland,-36.8551879,174.6313899,,-36.8551879_174.6313899_auckland_google_maps_image,,-36.8551879_174.6313899_auckland_google_satellite_image,,-36.8551879_174.6313899_auckland_google_street_view_image,, -5177815913,1,auckland,-36.91124247786922,174.8717508552371,,-36.91124247786922_174.8717508552371_auckland_google_maps_image,,-36.91124247786922_174.8717508552371_auckland_google_satellite_image,,-36.91124247786922_174.8717508552371_auckland_google_street_view_image,, -7689836586,1,auckland,-36.98687240951792,174.88409615465378,,-36.98687240951792_174.88409615465378_auckland_google_maps_image,,-36.98687240951792_174.88409615465378_auckland_google_satellite_image,,-36.98687240951792_174.88409615465378_auckland_google_street_view_image,, -3431101850,1,auckland,-36.77068322884491,174.73638456093389,,-36.77068322884491_174.73638456093389_auckland_google_maps_image,,-36.77068322884491_174.73638456093389_auckland_google_satellite_image,,-36.77068322884491_174.73638456093389_auckland_google_street_view_image,, -5151218411,1,auckland,-36.9661074,174.825764,,-36.9661074_174.825764_auckland_google_maps_image,,-36.9661074_174.825764_auckland_google_satellite_image,,-36.9661074_174.825764_auckland_google_street_view_image,, -5340052864,1,auckland,-36.95765570087596,174.85489039668784,,-36.95765570087596_174.85489039668784_auckland_google_maps_image,,-36.95765570087596_174.85489039668784_auckland_google_satellite_image,,-36.95765570087596_174.85489039668784_auckland_google_street_view_image,, -3994429764,1,auckland,-36.88629305046057,174.62833822862814,,-36.88629305046057_174.62833822862814_auckland_google_maps_image,,-36.88629305046057_174.62833822862814_auckland_google_satellite_image,,-36.88629305046057_174.62833822862814_auckland_google_street_view_image,, -3674684238,1,auckland,-36.94446439564092,174.88154172041084,,-36.94446439564092_174.88154172041084_auckland_google_maps_image,,-36.94446439564092_174.88154172041084_auckland_google_satellite_image,,-36.94446439564092_174.88154172041084_auckland_google_street_view_image,, -5057225422,2,auckland,-36.73925599999999,174.7533953,,-36.73925599999999_174.7533953_auckland_google_maps_image,,-36.73925599999999_174.7533953_auckland_google_satellite_image,,-36.73925599999999_174.7533953_auckland_google_street_view_image,, -5013799076,2,auckland,-37.06635380639986,174.94363464509547,,-37.06635380639986_174.94363464509547_auckland_google_maps_image,,-37.06635380639986_174.94363464509547_auckland_google_satellite_image,,-37.06635380639986_174.94363464509547_auckland_google_street_view_image,, -5013799341,2,auckland,-37.060683426914245,174.94246060181297,,-37.060683426914245_174.94246060181297_auckland_google_maps_image,,-37.060683426914245_174.94246060181297_auckland_google_satellite_image,,-37.060683426914245_174.94246060181297_auckland_google_street_view_image,, -5053006713,2,auckland,-37.014600500142166,174.87531565797755,,-37.014600500142166_174.87531565797755_auckland_google_maps_image,,-37.014600500142166_174.87531565797755_auckland_google_satellite_image,,-37.014600500142166_174.87531565797755_auckland_google_street_view_image,, -58841005,2,auckland,-36.857804406017856,174.6285448423473,,-36.857804406017856_174.6285448423473_auckland_google_maps_image,,-36.857804406017856_174.6285448423473_auckland_google_satellite_image,,-36.857804406017856_174.6285448423473_auckland_google_street_view_image,, -5057225481,2,auckland,-36.7397777733357,174.7420585598188,,-36.7397777733357_174.7420585598188_auckland_google_maps_image,,-36.7397777733357_174.7420585598188_auckland_google_satellite_image,,-36.7397777733357_174.7420585598188_auckland_google_street_view_image,, -2100727882,2,auckland,-36.86041563483351,174.83002652722683,,-36.86041563483351_174.83002652722683_auckland_google_maps_image,,-36.86041563483351_174.83002652722683_auckland_google_satellite_image,,-36.86041563483351_174.83002652722683_auckland_google_street_view_image,, -5913292093,2,auckland,-36.81157979999999,174.7236332,,-36.81157979999999_174.7236332_auckland_google_maps_image,,-36.81157979999999_174.7236332_auckland_google_satellite_image,,-36.81157979999999_174.7236332_auckland_google_street_view_image,, -2158628064,2,auckland,-36.81134228695914,174.724357840925,,-36.81134228695914_174.724357840925_auckland_google_maps_image,,-36.81134228695914_174.724357840925_auckland_google_satellite_image,,-36.81134228695914_174.724357840925_auckland_google_street_view_image,, -5029943787,2,auckland,-36.94158769880559,174.8412085213773,,-36.94158769880559_174.8412085213773_auckland_google_maps_image,,-36.94158769880559_174.8412085213773_auckland_google_satellite_image,,-36.94158769880559_174.8412085213773_auckland_google_street_view_image,, -4956180988,3,auckland,-36.92219517307905,174.71275760580338,,-36.92219517307905_174.71275760580338_auckland_google_maps_image,,-36.92219517307905_174.71275760580338_auckland_google_satellite_image,,-36.92219517307905_174.71275760580338_auckland_google_street_view_image,, -5047602337,3,auckland,-36.759760467319325,174.74043690103835,,-36.759760467319325_174.74043690103835_auckland_google_maps_image,,-36.759760467319325_174.74043690103835_auckland_google_satellite_image,,-36.759760467319325_174.74043690103835_auckland_google_street_view_image,, -5843116420,3,auckland,-36.91058855691557,174.6506670263708,,-36.91058855691557_174.6506670263708_auckland_google_maps_image,,-36.91058855691557_174.6506670263708_auckland_google_satellite_image,,-36.91058855691557_174.6506670263708_auckland_google_street_view_image,, -4410690791,3,auckland,-36.788972690095086,174.77124843534293,,-36.788972690095086_174.77124843534293_auckland_google_maps_image,,-36.788972690095086_174.77124843534293_auckland_google_satellite_image,,-36.788972690095086_174.77124843534293_auckland_google_street_view_image,, -2100719532,3,auckland,-36.85304193432865,174.8438125745177,,-36.85304193432865_174.8438125745177_auckland_google_maps_image,,-36.85304193432865_174.8438125745177_auckland_google_satellite_image,,-36.85304193432865_174.8438125745177_auckland_google_street_view_image,, -3472437512,3,auckland,-36.761737169587754,174.7248816671117,,-36.761737169587754_174.7248816671117_auckland_google_maps_image,,-36.761737169587754_174.7248816671117_auckland_google_satellite_image,,-36.761737169587754_174.7248816671117_auckland_google_street_view_image,, -4855260710,3,auckland,-36.86399800770286,174.61454105099645,,-36.86399800770286_174.61454105099645_auckland_google_maps_image,,-36.86399800770286_174.61454105099645_auckland_google_satellite_image,,-36.86399800770286_174.61454105099645_auckland_google_street_view_image,, -5141828308,3,auckland,-36.91048484845646,174.65267470821254,,-36.91048484845646_174.65267470821254_auckland_google_maps_image,,-36.91048484845646_174.65267470821254_auckland_google_satellite_image,,-36.91048484845646_174.65267470821254_auckland_google_street_view_image,, -353564209,3,auckland,-36.73959434641423,174.75308288672272,,-36.73959434641423_174.75308288672272_auckland_google_maps_image,,-36.73959434641423_174.75308288672272_auckland_google_satellite_image,,-36.73959434641423_174.75308288672272_auckland_google_street_view_image,, -62280838,3,auckland,-36.913266215446306,174.87154351203284,,-36.913266215446306_174.87154351203284_auckland_google_maps_image,,-36.913266215446306_174.87154351203284_auckland_google_satellite_image,,-36.913266215446306_174.87154351203284_auckland_google_street_view_image,, -1290034835,4,auckland,-36.85009499027466,174.8422411427827,,-36.85009499027466_174.8422411427827_auckland_google_maps_image,,-36.85009499027466_174.8422411427827_auckland_google_satellite_image,,-36.85009499027466_174.8422411427827_auckland_google_street_view_image,, -7590567639,4,auckland,-36.85414327072335,174.71834991372967,,-36.85414327072335_174.71834991372967_auckland_google_maps_image,,-36.85414327072335_174.71834991372967_auckland_google_satellite_image,,-36.85414327072335_174.71834991372967_auckland_google_street_view_image,, -5030003412,4,auckland,-36.970325293939915,174.8455994863601,,-36.970325293939915_174.8455994863601_auckland_google_maps_image,,-36.970325293939915_174.8455994863601_auckland_google_satellite_image,,-36.970325293939915_174.8455994863601_auckland_google_street_view_image,, -5057172416,4,auckland,-36.72875048956933,174.73092146931623,,-36.72875048956933_174.73092146931623_auckland_google_maps_image,,-36.72875048956933_174.73092146931623_auckland_google_satellite_image,,-36.72875048956933_174.73092146931623_auckland_google_street_view_image,, -4910282473,4,auckland,-36.886728003214174,174.64499210347978,,-36.886728003214174_174.64499210347978_auckland_google_maps_image,,-36.886728003214174_174.64499210347978_auckland_google_satellite_image,,-36.886728003214174_174.64499210347978_auckland_google_street_view_image,, -4910282488,4,auckland,-36.873713619123286,174.64564486859268,,-36.873713619123286_174.64564486859268_auckland_google_maps_image,,-36.873713619123286_174.64564486859268_auckland_google_satellite_image,,-36.873713619123286_174.64564486859268_auckland_google_street_view_image,, -3666604236,4,auckland,-36.90601107118147,174.927522034169,,-36.90601107118147_174.927522034169_auckland_google_maps_image,,-36.90601107118147_174.927522034169_auckland_google_satellite_image,,-36.90601107118147_174.927522034169_auckland_google_street_view_image,, -5156242297,4,auckland,-36.85666338583509,174.7461853366752,,-36.85666338583509_174.7461853366752_auckland_google_maps_image,,-36.85666338583509_174.7461853366752_auckland_google_satellite_image,,-36.85666338583509_174.7461853366752_auckland_google_street_view_image,, -778150745,4,auckland,-36.90379339825787,174.9246612720973,,-36.90379339825787_174.9246612720973_auckland_google_maps_image,,-36.90379339825787_174.9246612720973_auckland_google_satellite_image,,-36.90379339825787_174.9246612720973_auckland_google_street_view_image,, -3456962101,4,auckland,-36.783199383644046,174.73136534153699,,-36.783199383644046_174.73136534153699_auckland_google_maps_image,,-36.783199383644046_174.73136534153699_auckland_google_satellite_image,,-36.783199383644046_174.73136534153699_auckland_google_street_view_image,, -5151218092,5,auckland,-36.97250488941118,174.8339127736801,,-36.97250488941118_174.8339127736801_auckland_google_maps_image,,-36.97250488941118_174.8339127736801_auckland_google_satellite_image,,-36.97250488941118_174.8339127736801_auckland_google_street_view_image,, -336630320,5,auckland,-36.899454368584195,174.74442028356722,,-36.899454368584195_174.74442028356722_auckland_google_maps_image,,-36.899454368584195_174.74442028356722_auckland_google_satellite_image,,-36.899454368584195_174.74442028356722_auckland_google_street_view_image,, -3380256432,5,auckland,-36.8578308703826,174.7590550416262,,-36.8578308703826_174.7590550416262_auckland_google_maps_image,,-36.8578308703826_174.7590550416262_auckland_google_satellite_image,,-36.8578308703826_174.7590550416262_auckland_google_street_view_image,, -7092241148,5,auckland,-36.843970252262025,174.7654467733103,,-36.843970252262025_174.7654467733103_auckland_google_maps_image,,-36.843970252262025_174.7654467733103_auckland_google_satellite_image,,-36.843970252262025_174.7654467733103_auckland_google_street_view_image,, -6550726535,5,auckland,-36.89632105828324,174.7444358751894,,-36.89632105828324_174.7444358751894_auckland_google_maps_image,,-36.89632105828324_174.7444358751894_auckland_google_satellite_image,,-36.89632105828324_174.7444358751894_auckland_google_street_view_image,, -6294498985,5,auckland,-36.84704872130957,174.764541444604,,-36.84704872130957_174.764541444604_auckland_google_maps_image,,-36.84704872130957_174.764541444604_auckland_google_satellite_image,,-36.84704872130957_174.764541444604_auckland_google_street_view_image,, -6550726538,5,auckland,-36.90369310767926,174.74208431137032,,-36.90369310767926_174.74208431137032_auckland_google_maps_image,,-36.90369310767926_174.74208431137032_auckland_google_satellite_image,,-36.90369310767926_174.74208431137032_auckland_google_street_view_image,, -2632013352,5,auckland,-36.851099879142936,174.78218605394915,,-36.851099879142936_174.78218605394915_auckland_google_maps_image,,-36.851099879142936_174.78218605394915_auckland_google_satellite_image,,-36.851099879142936_174.78218605394915_auckland_google_street_view_image,, -4753906347,5,auckland,-36.85815036153281,174.76326572201035,,-36.85815036153281_174.76326572201035_auckland_google_maps_image,,-36.85815036153281_174.76326572201035_auckland_google_satellite_image,,-36.85815036153281_174.76326572201035_auckland_google_street_view_image,, -2700429659,5,auckland,-36.91075015517064,174.77551494456267,,-36.91075015517064_174.77551494456267_auckland_google_maps_image,,-36.91075015517064_174.77551494456267_auckland_google_satellite_image,,-36.91075015517064_174.77551494456267_auckland_google_street_view_image,, -6788833594,1,baltimore,39.4233411790282,-76.80627449740476,,39.4233411790282_-76.80627449740476_baltimore_google_maps_image,,39.4233411790282_-76.80627449740476_baltimore_google_satellite_image,,39.4233411790282_-76.80627449740476_baltimore_google_street_view_image,, -159115264,1,baltimore,39.43063976267354,-76.62319629306191,,39.43063976267354_-76.62319629306191_baltimore_google_maps_image,,39.43063976267354_-76.62319629306191_baltimore_google_satellite_image,,39.43063976267354_-76.62319629306191_baltimore_google_street_view_image,, -240449342,1,baltimore,39.25910014320543,-76.66205846388277,,39.25910014320543_-76.66205846388277_baltimore_google_maps_image,,39.25910014320543_-76.66205846388277_baltimore_google_satellite_image,,39.25910014320543_-76.66205846388277_baltimore_google_street_view_image,, -717794789,1,baltimore,39.4059062575352,-76.79085344090109,,39.4059062575352_-76.79085344090109_baltimore_google_maps_image,,39.4059062575352_-76.79085344090109_baltimore_google_satellite_image,,39.4059062575352_-76.79085344090109_baltimore_google_street_view_image,, -298710396,1,baltimore,39.378303448947314,-76.62602690183553,,39.378303448947314_-76.62602690183553_baltimore_google_maps_image,,39.378303448947314_-76.62602690183553_baltimore_google_satellite_image,,39.378303448947314_-76.62602690183553_baltimore_google_street_view_image,, -3847890557,1,baltimore,39.44413103913071,-76.62477305633409,,39.44413103913071_-76.62477305633409_baltimore_google_maps_image,,39.44413103913071_-76.62477305633409_baltimore_google_satellite_image,,39.44413103913071_-76.62477305633409_baltimore_google_street_view_image,, -171582462,1,baltimore,39.293889918897214,-76.69549060376814,,39.293889918897214_-76.69549060376814_baltimore_google_maps_image,,39.293889918897214_-76.69549060376814_baltimore_google_satellite_image,,39.293889918897214_-76.69549060376814_baltimore_google_street_view_image,, -6006099656,1,baltimore,39.36558914520734,-76.64764743396593,,39.36558914520734_-76.64764743396593_baltimore_google_maps_image,,39.36558914520734_-76.64764743396593_baltimore_google_satellite_image,,39.36558914520734_-76.64764743396593_baltimore_google_street_view_image,, -53101339,1,baltimore,39.497432335179106,-76.65639733239344,,39.497432335179106_-76.65639733239344_baltimore_google_maps_image,,39.497432335179106_-76.65639733239344_baltimore_google_satellite_image,,39.497432335179106_-76.65639733239344_baltimore_google_street_view_image,, -2501047707,1,baltimore,39.20694080101815,-76.68987617685923,,39.20694080101815_-76.68987617685923_baltimore_google_maps_image,,39.20694080101815_-76.68987617685923_baltimore_google_satellite_image,,39.20694080101815_-76.68987617685923_baltimore_google_street_view_image,, -114497307,2,baltimore,39.332824358711,-76.44579139898003,,39.332824358711_-76.44579139898003_baltimore_google_maps_image,,39.332824358711_-76.44579139898003_baltimore_google_satellite_image,,39.332824358711_-76.44579139898003_baltimore_google_street_view_image,, -398700992,2,baltimore,39.39745705328534,-76.58441516443344,,39.39745705328534_-76.58441516443344_baltimore_google_maps_image,,39.39745705328534_-76.58441516443344_baltimore_google_satellite_image,,39.39745705328534_-76.58441516443344_baltimore_google_street_view_image,, -65162501,2,baltimore,39.337651400664235,-76.48735615147646,,39.337651400664235_-76.48735615147646_baltimore_google_maps_image,,39.337651400664235_-76.48735615147646_baltimore_google_satellite_image,,39.337651400664235_-76.48735615147646_baltimore_google_street_view_image,, -170399584,2,baltimore,39.26797712306708,-76.59965174147638,,39.26797712306708_-76.59965174147638_baltimore_google_maps_image,,39.26797712306708_-76.59965174147638_baltimore_google_satellite_image,,39.26797712306708_-76.59965174147638_baltimore_google_street_view_image,, -3025614615,2,baltimore,39.40734936949507,-76.51486168800021,,39.40734936949507_-76.51486168800021_baltimore_google_maps_image,,39.40734936949507_-76.51486168800021_baltimore_google_satellite_image,,39.40734936949507_-76.51486168800021_baltimore_google_street_view_image,, -298914425,2,baltimore,39.316480399999996,-76.450541,,39.316480399999996_-76.450541_baltimore_google_maps_image,,39.316480399999996_-76.450541_baltimore_google_satellite_image,,39.316480399999996_-76.450541_baltimore_google_street_view_image,, -3659200044,2,baltimore,39.1363823242475,-76.58519239985915,,39.1363823242475_-76.58519239985915_baltimore_google_maps_image,,39.1363823242475_-76.58519239985915_baltimore_google_satellite_image,,39.1363823242475_-76.58519239985915_baltimore_google_street_view_image,, -2480610216,2,baltimore,39.290163999331064,-76.60470509178845,,39.290163999331064_-76.60470509178845_baltimore_google_maps_image,,39.290163999331064_-76.60470509178845_baltimore_google_satellite_image,,39.290163999331064_-76.60470509178845_baltimore_google_street_view_image,, -185219339,2,baltimore,39.271721103427105,-76.73330303621823,,39.271721103427105_-76.73330303621823_baltimore_google_maps_image,,39.271721103427105_-76.73330303621823_baltimore_google_satellite_image,,39.271721103427105_-76.73330303621823_baltimore_google_street_view_image,, -123758634,2,baltimore,39.39714878746854,-76.47983381163374,,39.39714878746854_-76.47983381163374_baltimore_google_maps_image,,39.39714878746854_-76.47983381163374_baltimore_google_satellite_image,,39.39714878746854_-76.47983381163374_baltimore_google_street_view_image,, -1595567254,3,baltimore,39.265931223927645,-76.69894114775624,,39.265931223927645_-76.69894114775624_baltimore_google_maps_image,,39.265931223927645_-76.69894114775624_baltimore_google_satellite_image,,39.265931223927645_-76.69894114775624_baltimore_google_street_view_image,, -336192613,3,baltimore,39.3348220568945,-76.55635564015755,,39.3348220568945_-76.55635564015755_baltimore_google_maps_image,,39.3348220568945_-76.55635564015755_baltimore_google_satellite_image,,39.3348220568945_-76.55635564015755_baltimore_google_street_view_image,, -3025590016,3,baltimore,39.3986970128765,-76.53735207273031,,39.3986970128765_-76.53735207273031_baltimore_google_maps_image,,39.3986970128765_-76.53735207273031_baltimore_google_satellite_image,,39.3986970128765_-76.53735207273031_baltimore_google_street_view_image,, -55547321,3,baltimore,39.418486420085195,-76.77610848698835,,39.418486420085195_-76.77610848698835_baltimore_google_maps_image,,39.418486420085195_-76.77610848698835_baltimore_google_satellite_image,,39.418486420085195_-76.77610848698835_baltimore_google_street_view_image,, -6125944256,3,baltimore,39.330141261084336,-76.51981640528915,,39.330141261084336_-76.51981640528915_baltimore_google_maps_image,,39.330141261084336_-76.51981640528915_baltimore_google_satellite_image,,39.330141261084336_-76.51981640528915_baltimore_google_street_view_image,, -299154086,3,baltimore,39.27113085390868,-76.50433059093905,,39.27113085390868_-76.50433059093905_baltimore_google_maps_image,,39.27113085390868_-76.50433059093905_baltimore_google_satellite_image,,39.27113085390868_-76.50433059093905_baltimore_google_street_view_image,, -3026454268,3,baltimore,39.32498787603193,-76.44971426346432,,39.32498787603193_-76.44971426346432_baltimore_google_maps_image,,39.32498787603193_-76.44971426346432_baltimore_google_satellite_image,,39.32498787603193_-76.44971426346432_baltimore_google_street_view_image,, -336301885,3,baltimore,39.26896901481033,-76.59427641580616,,39.26896901481033_-76.59427641580616_baltimore_google_maps_image,,39.26896901481033_-76.59427641580616_baltimore_google_satellite_image,,39.26896901481033_-76.59427641580616_baltimore_google_street_view_image,, -7470873582,3,baltimore,39.33467001873526,-76.55657744021252,,39.33467001873526_-76.55657744021252_baltimore_google_maps_image,,39.33467001873526_-76.55657744021252_baltimore_google_satellite_image,,39.33467001873526_-76.55657744021252_baltimore_google_street_view_image,, -592868020,3,baltimore,39.15070596165896,-76.61478102753644,,39.15070596165896_-76.61478102753644_baltimore_google_maps_image,,39.15070596165896_-76.61478102753644_baltimore_google_satellite_image,,39.15070596165896_-76.61478102753644_baltimore_google_street_view_image,, -90694903,4,baltimore,39.26069287089995,-76.6964529057291,,39.26069287089995_-76.6964529057291_baltimore_google_maps_image,,39.26069287089995_-76.6964529057291_baltimore_google_satellite_image,,39.26069287089995_-76.6964529057291_baltimore_google_street_view_image,, -132459599,4,baltimore,39.440539961786364,-76.80761292001905,,39.440539961786364_-76.80761292001905_baltimore_google_maps_image,,39.440539961786364_-76.80761292001905_baltimore_google_satellite_image,,39.440539961786364_-76.80761292001905_baltimore_google_street_view_image,, -279142464,4,baltimore,39.38849047002029,-76.507715266536,,39.38849047002029_-76.507715266536_baltimore_google_maps_image,,39.38849047002029_-76.507715266536_baltimore_google_satellite_image,,39.38849047002029_-76.507715266536_baltimore_google_street_view_image,, -4741601565,4,baltimore,39.32596190007805,-76.60941149999078,,39.32596190007805_-76.60941149999078_baltimore_google_maps_image,,39.32596190007805_-76.60941149999078_baltimore_google_satellite_image,,39.32596190007805_-76.60941149999078_baltimore_google_street_view_image,, -336204596,4,baltimore,39.35160931830831,-76.56205966383047,,39.35160931830831_-76.56205966383047_baltimore_google_maps_image,,39.35160931830831_-76.56205966383047_baltimore_google_satellite_image,,39.35160931830831_-76.56205966383047_baltimore_google_street_view_image,, -3025607108,4,baltimore,39.38015920459807,-76.53736644235391,,39.38015920459807_-76.53736644235391_baltimore_google_maps_image,,39.38015920459807_-76.53736644235391_baltimore_google_satellite_image,,39.38015920459807_-76.53736644235391_baltimore_google_street_view_image,, -5553735127,4,baltimore,39.3578727619507,-76.70653734963494,,39.3578727619507_-76.70653734963494_baltimore_google_maps_image,,39.3578727619507_-76.70653734963494_baltimore_google_satellite_image,,39.3578727619507_-76.70653734963494_baltimore_google_street_view_image,, -232497151,4,baltimore,39.13320128021018,-76.6380396730981,,39.13320128021018_-76.6380396730981_baltimore_google_maps_image,,39.13320128021018_-76.6380396730981_baltimore_google_satellite_image,,39.13320128021018_-76.6380396730981_baltimore_google_street_view_image,, -5282843923,4,baltimore,39.28957119999999,-76.6163313,,39.28957119999999_-76.6163313_baltimore_google_maps_image,,39.28957119999999_-76.6163313_baltimore_google_satellite_image,,39.28957119999999_-76.6163313_baltimore_google_street_view_image,, -191346993,4,baltimore,39.3599678596374,-76.70896674598472,,39.3599678596374_-76.70896674598472_baltimore_google_maps_image,,39.3599678596374_-76.70896674598472_baltimore_google_satellite_image,,39.3599678596374_-76.70896674598472_baltimore_google_street_view_image,, -336223822,5,baltimore,39.288567240907916,-76.56939001745654,,39.288567240907916_-76.56939001745654_baltimore_google_maps_image,,39.288567240907916_-76.56939001745654_baltimore_google_satellite_image,,39.288567240907916_-76.56939001745654_baltimore_google_street_view_image,, -1148183217,5,baltimore,39.32648248924767,-76.61578784619739,,39.32648248924767_-76.61578784619739_baltimore_google_maps_image,,39.32648248924767_-76.61578784619739_baltimore_google_satellite_image,,39.32648248924767_-76.61578784619739_baltimore_google_street_view_image,, -4567907233,5,baltimore,39.2922446,-76.6154321,,39.2922446_-76.6154321_baltimore_google_maps_image,,39.2922446_-76.6154321_baltimore_google_satellite_image,,39.2922446_-76.6154321_baltimore_google_street_view_image,, --8955169,5,baltimore,39.2876445516368,-76.63595807648218,,39.2876445516368_-76.63595807648218_baltimore_google_maps_image,,39.2876445516368_-76.63595807648218_baltimore_google_satellite_image,,39.2876445516368_-76.63595807648218_baltimore_google_street_view_image,, -1577067795,5,baltimore,39.40545679565556,-76.60218683482036,,39.40545679565556_-76.60218683482036_baltimore_google_maps_image,,39.40545679565556_-76.60218683482036_baltimore_google_satellite_image,,39.40545679565556_-76.60218683482036_baltimore_google_street_view_image,, -531133208,5,baltimore,39.336198800000005,-76.630839,,39.336198800000005_-76.630839_baltimore_google_maps_image,,39.336198800000005_-76.630839_baltimore_google_satellite_image,,39.336198800000005_-76.630839_baltimore_google_street_view_image,, -337536824,5,baltimore,39.31787662110797,-76.57695883835787,,39.31787662110797_-76.57695883835787_baltimore_google_maps_image,,39.31787662110797_-76.57695883835787_baltimore_google_satellite_image,,39.31787662110797_-76.57695883835787_baltimore_google_street_view_image,, -336373055,5,baltimore,39.30319629525222,-76.61672785460912,,39.30319629525222_-76.61672785460912_baltimore_google_maps_image,,39.30319629525222_-76.61672785460912_baltimore_google_satellite_image,,39.30319629525222_-76.61672785460912_baltimore_google_street_view_image,, -177620353,5,baltimore,39.28054171449186,-76.57922596957705,,39.28054171449186_-76.57922596957705_baltimore_google_maps_image,,39.28054171449186_-76.57922596957705_baltimore_google_satellite_image,,39.28054171449186_-76.57922596957705_baltimore_google_street_view_image,, -241571290,5,baltimore,39.28304077179726,-76.65303217347157,,39.28304077179726_-76.65303217347157_baltimore_google_maps_image,,39.28304077179726_-76.65303217347157_baltimore_google_satellite_image,,39.28304077179726_-76.65303217347157_baltimore_google_street_view_image,, -1597529880,1,bangkok,13.849674666522924,100.56412825333632,,13.849674666522924_100.56412825333632_bangkok_google_maps_image,,13.849674666522924_100.56412825333632_bangkok_google_satellite_image,,13.849674666522924_100.56412825333632_bangkok_google_street_view_image,, -99450842,1,bangkok,13.663941097975266,100.44033266743412,,13.663941097975266_100.44033266743412_bangkok_google_maps_image,,13.663941097975266_100.44033266743412_bangkok_google_satellite_image,,13.663941097975266_100.44033266743412_bangkok_google_street_view_image,, -4527517188,1,bangkok,13.68418019485134,100.35383788054041,,13.68418019485134_100.35383788054041_bangkok_google_maps_image,,13.68418019485134_100.35383788054041_bangkok_google_satellite_image,,13.68418019485134_100.35383788054041_bangkok_google_street_view_image,, -449808122,1,bangkok,13.826270499999998,100.660181,,13.826270499999998_100.660181_bangkok_google_maps_image,,13.826270499999998_100.660181_bangkok_google_satellite_image,,13.826270499999998_100.660181_bangkok_google_street_view_image,, -6068369586,1,bangkok,13.921726005157476,100.65509470090788,,13.921726005157476_100.65509470090788_bangkok_google_maps_image,,13.921726005157476_100.65509470090788_bangkok_google_satellite_image,,13.921726005157476_100.65509470090788_bangkok_google_street_view_image,, -5267492421,1,bangkok,13.739108751720089,100.54669161246598,,13.739108751720089_100.54669161246598_bangkok_google_maps_image,,13.739108751720089_100.54669161246598_bangkok_google_satellite_image,,13.739108751720089_100.54669161246598_bangkok_google_street_view_image,, -2299993194,1,bangkok,13.738186600000002,100.5419478,,13.738186600000002_100.5419478_bangkok_google_maps_image,,13.738186600000002_100.5419478_bangkok_google_satellite_image,,13.738186600000002_100.5419478_bangkok_google_street_view_image,, -316417449,1,bangkok,13.80009594699123,100.64857930681839,,13.80009594699123_100.64857930681839_bangkok_google_maps_image,,13.80009594699123_100.64857930681839_bangkok_google_satellite_image,,13.80009594699123_100.64857930681839_bangkok_google_street_view_image,, -34499729,1,bangkok,13.685836437274048,100.66919727929407,,13.685836437274048_100.66919727929407_bangkok_google_maps_image,,13.685836437274048_100.66919727929407_bangkok_google_satellite_image,,13.685836437274048_100.66919727929407_bangkok_google_street_view_image,, -5088450302,1,bangkok,13.757085510664185,100.7902633392472,,13.757085510664185_100.7902633392472_bangkok_google_maps_image,,13.757085510664185_100.7902633392472_bangkok_google_satellite_image,,13.757085510664185_100.7902633392472_bangkok_google_street_view_image,, -5355896404,2,bangkok,13.92171352822775,100.68303227353393,,13.92171352822775_100.68303227353393_bangkok_google_maps_image,,13.92171352822775_100.68303227353393_bangkok_google_satellite_image,,13.92171352822775_100.68303227353393_bangkok_google_street_view_image,, -187179977,2,bangkok,13.862260032763633,100.61509916896114,,13.862260032763633_100.61509916896114_bangkok_google_maps_image,,13.862260032763633_100.61509916896114_bangkok_google_satellite_image,,13.862260032763633_100.61509916896114_bangkok_google_street_view_image,, -2099171796,2,bangkok,13.839248897426966,100.55062176545533,,13.839248897426966_100.55062176545533_bangkok_google_maps_image,,13.839248897426966_100.55062176545533_bangkok_google_satellite_image,,13.839248897426966_100.55062176545533_bangkok_google_street_view_image,, -196107455,2,bangkok,13.7044804965112,100.50319049066647,,13.7044804965112_100.50319049066647_bangkok_google_maps_image,,13.7044804965112_100.50319049066647_bangkok_google_satellite_image,,13.7044804965112_100.50319049066647_bangkok_google_street_view_image,, -7231919792,2,bangkok,13.704040520596246,100.41983606169232,,13.704040520596246_100.41983606169232_bangkok_google_maps_image,,13.704040520596246_100.41983606169232_bangkok_google_satellite_image,,13.704040520596246_100.41983606169232_bangkok_google_street_view_image,, -3502221453,2,bangkok,13.67400026747181,100.54545081466276,,13.67400026747181_100.54545081466276_bangkok_google_maps_image,,13.67400026747181_100.54545081466276_bangkok_google_satellite_image,,13.67400026747181_100.54545081466276_bangkok_google_street_view_image,, -199926245,2,bangkok,13.838829729806958,100.55055706909236,,13.838829729806958_100.55055706909236_bangkok_google_maps_image,,13.838829729806958_100.55055706909236_bangkok_google_satellite_image,,13.838829729806958_100.55055706909236_bangkok_google_street_view_image,, -156723174,2,bangkok,13.894608399999996,100.560209,,13.894608399999996_100.560209_bangkok_google_maps_image,,13.894608399999996_100.560209_bangkok_google_satellite_image,,13.894608399999996_100.560209_bangkok_google_street_view_image,, -6059978137,2,bangkok,13.81888669165045,100.59202180477908,,13.81888669165045_100.59202180477908_bangkok_google_maps_image,,13.81888669165045_100.59202180477908_bangkok_google_satellite_image,,13.81888669165045_100.59202180477908_bangkok_google_street_view_image,, -199926216,2,bangkok,13.83924870565924,100.55062122501938,,13.83924870565924_100.55062122501938_bangkok_google_maps_image,,13.83924870565924_100.55062122501938_bangkok_google_satellite_image,,13.83924870565924_100.55062122501938_bangkok_google_street_view_image,, -323347384,3,bangkok,13.722820680400257,100.58425388173939,,13.722820680400257_100.58425388173939_bangkok_google_maps_image,,13.722820680400257_100.58425388173939_bangkok_google_satellite_image,,13.722820680400257_100.58425388173939_bangkok_google_street_view_image,, -3860265993,3,bangkok,13.7375072,100.5603419,,13.7375072_100.5603419_bangkok_google_maps_image,,13.7375072_100.5603419_bangkok_google_satellite_image,,13.7375072_100.5603419_bangkok_google_street_view_image,, -4254764090,3,bangkok,13.756675002646817,100.49809935754523,,13.756675002646817_100.49809935754523_bangkok_google_maps_image,,13.756675002646817_100.49809935754523_bangkok_google_satellite_image,,13.756675002646817_100.49809935754523_bangkok_google_street_view_image,, -4815734522,3,bangkok,13.741276266080995,100.51288782506194,,13.741276266080995_100.51288782506194_bangkok_google_maps_image,,13.741276266080995_100.51288782506194_bangkok_google_satellite_image,,13.741276266080995_100.51288782506194_bangkok_google_street_view_image,, -697558275,3,bangkok,13.813600183249362,100.7281142422845,,13.813600183249362_100.7281142422845_bangkok_google_maps_image,,13.813600183249362_100.7281142422845_bangkok_google_satellite_image,,13.813600183249362_100.7281142422845_bangkok_google_street_view_image,, -7325627585,3,bangkok,13.6823919930044,100.4817063781228,,13.6823919930044_100.4817063781228_bangkok_google_maps_image,,13.6823919930044_100.4817063781228_bangkok_google_satellite_image,,13.6823919930044_100.4817063781228_bangkok_google_street_view_image,, -1063290343,3,bangkok,13.887247021114556,100.58180629374222,,13.887247021114556_100.58180629374222_bangkok_google_maps_image,,13.887247021114556_100.58180629374222_bangkok_google_satellite_image,,13.887247021114556_100.58180629374222_bangkok_google_street_view_image,, -5902026985,3,bangkok,13.744430298673507,100.53028243550618,,13.744430298673507_100.53028243550618_bangkok_google_maps_image,,13.744430298673507_100.53028243550618_bangkok_google_satellite_image,,13.744430298673507_100.53028243550618_bangkok_google_street_view_image,, -214152293,3,bangkok,13.770340137126484,100.50340521130626,,13.770340137126484_100.50340521130626_bangkok_google_maps_image,,13.770340137126484_100.50340521130626_bangkok_google_satellite_image,,13.770340137126484_100.50340521130626_bangkok_google_street_view_image,, -7178945686,3,bangkok,13.777436806101173,100.58002187593789,,13.777436806101173_100.58002187593789_bangkok_google_maps_image,,13.777436806101173_100.58002187593789_bangkok_google_satellite_image,,13.777436806101173_100.58002187593789_bangkok_google_street_view_image,, -231732621,4,bangkok,13.897297025748712,100.60866550173242,,13.897297025748712_100.60866550173242_bangkok_google_maps_image,,13.897297025748712_100.60866550173242_bangkok_google_satellite_image,,13.897297025748712_100.60866550173242_bangkok_google_street_view_image,, -4668717191,4,bangkok,13.75479678929426,100.53269881020535,,13.75479678929426_100.53269881020535_bangkok_google_maps_image,,13.75479678929426_100.53269881020535_bangkok_google_satellite_image,,13.75479678929426_100.53269881020535_bangkok_google_street_view_image,, -151991140,4,bangkok,13.736418994555205,100.5239963012267,,13.736418994555205_100.5239963012267_bangkok_google_maps_image,,13.736418994555205_100.5239963012267_bangkok_google_satellite_image,,13.736418994555205_100.5239963012267_bangkok_google_street_view_image,, -228106721,4,bangkok,13.751600476542638,100.54379975850526,,13.751600476542638_100.54379975850526_bangkok_google_maps_image,,13.751600476542638_100.54379975850526_bangkok_google_satellite_image,,13.751600476542638_100.54379975850526_bangkok_google_street_view_image,, -3316629478,4,bangkok,13.733979750071622,100.58010836491863,,13.733979750071622_100.58010836491863_bangkok_google_maps_image,,13.733979750071622_100.58010836491863_bangkok_google_satellite_image,,13.733979750071622_100.58010836491863_bangkok_google_street_view_image,, -5363677833,4,bangkok,13.764555105168348,100.52676876880163,,13.764555105168348_100.52676876880163_bangkok_google_maps_image,,13.764555105168348_100.52676876880163_bangkok_google_satellite_image,,13.764555105168348_100.52676876880163_bangkok_google_street_view_image,, -6594505985,4,bangkok,13.798984009688025,100.55027855033083,,13.798984009688025_100.55027855033083_bangkok_google_maps_image,,13.798984009688025_100.55027855033083_bangkok_google_satellite_image,,13.798984009688025_100.55027855033083_bangkok_google_street_view_image,, -224714999,4,bangkok,13.718502915421588,100.56028580034813,,13.718502915421588_100.56028580034813_bangkok_google_maps_image,,13.718502915421588_100.56028580034813_bangkok_google_satellite_image,,13.718502915421588_100.56028580034813_bangkok_google_street_view_image,, -4132492349,4,bangkok,13.772299367949945,100.61021978675944,,13.772299367949945_100.61021978675944_bangkok_google_maps_image,,13.772299367949945_100.61021978675944_bangkok_google_satellite_image,,13.772299367949945_100.61021978675944_bangkok_google_street_view_image,, -1639162480,4,bangkok,13.742169966563857,100.55420920715783,,13.742169966563857_100.55420920715783_bangkok_google_maps_image,,13.742169966563857_100.55420920715783_bangkok_google_satellite_image,,13.742169966563857_100.55420920715783_bangkok_google_street_view_image,, -379863487,5,bangkok,13.697578485629055,100.48264656045937,,13.697578485629055_100.48264656045937_bangkok_google_maps_image,,13.697578485629055_100.48264656045937_bangkok_google_satellite_image,,13.697578485629055_100.48264656045937_bangkok_google_street_view_image,, -322651065,5,bangkok,13.791357599999998,100.55006550000002,,13.791357599999998_100.55006550000002_bangkok_google_maps_image,,13.791357599999998_100.55006550000002_bangkok_google_satellite_image,,13.791357599999998_100.55006550000002_bangkok_google_street_view_image,, -103670923,5,bangkok,13.710950130603234,100.51807559270352,,13.710950130603234_100.51807559270352_bangkok_google_maps_image,,13.710950130603234_100.51807559270352_bangkok_google_satellite_image,,13.710950130603234_100.51807559270352_bangkok_google_street_view_image,, -320483765,5,bangkok,13.710856990950395,100.54208569095071,,13.710856990950395_100.54208569095071_bangkok_google_maps_image,,13.710856990950395_100.54208569095071_bangkok_google_satellite_image,,13.710856990950395_100.54208569095071_bangkok_google_street_view_image,, -139333081,5,bangkok,13.733140851361425,100.49331104304478,,13.733140851361425_100.49331104304478_bangkok_google_maps_image,,13.733140851361425_100.49331104304478_bangkok_google_satellite_image,,13.733140851361425_100.49331104304478_bangkok_google_street_view_image,, -4355467996,5,bangkok,13.728519803790471,100.50890907095493,,13.728519803790471_100.50890907095493_bangkok_google_maps_image,,13.728519803790471_100.50890907095493_bangkok_google_satellite_image,,13.728519803790471_100.50890907095493_bangkok_google_street_view_image,, -2280188077,5,bangkok,13.745435356214205,100.51108737637246,,13.745435356214205_100.51108737637246_bangkok_google_maps_image,,13.745435356214205_100.51108737637246_bangkok_google_satellite_image,,13.745435356214205_100.51108737637246_bangkok_google_street_view_image,, -637381858,5,bangkok,13.752907528303128,100.52829648506611,,13.752907528303128_100.52829648506611_bangkok_google_maps_image,,13.752907528303128_100.52829648506611_bangkok_google_satellite_image,,13.752907528303128_100.52829648506611_bangkok_google_street_view_image,, -6276438186,5,bangkok,13.795069872455473,100.55024689105696,,13.795069872455473_100.55024689105696_bangkok_google_maps_image,,13.795069872455473_100.55024689105696_bangkok_google_satellite_image,,13.795069872455473_100.55024689105696_bangkok_google_street_view_image,, -1597521876,5,bangkok,13.780167141032228,100.54553671463344,,13.780167141032228_100.54553671463344_bangkok_google_maps_image,,13.780167141032228_100.54553671463344_bangkok_google_satellite_image,,13.780167141032228_100.54553671463344_bangkok_google_street_view_image,, -4473660723,1,barcelona,41.4895879791037,2.133347205395721,,41.4895879791037_2.133347205395721_barcelona_google_maps_image,,41.4895879791037_2.133347205395721_barcelona_google_satellite_image,,41.4895879791037_2.133347205395721_barcelona_google_street_view_image,, -3153064305,1,barcelona,41.3615402665667,2.027783781857484,,41.3615402665667_2.027783781857484_barcelona_google_maps_image,,41.3615402665667_2.027783781857484_barcelona_google_satellite_image,,41.3615402665667_2.027783781857484_barcelona_google_street_view_image,, -6541474968,1,barcelona,41.493800006713336,2.142518825890501,,41.493800006713336_2.142518825890501_barcelona_google_maps_image,,41.493800006713336_2.142518825890501_barcelona_google_satellite_image,,41.493800006713336_2.142518825890501_barcelona_google_street_view_image,, -122820773,1,barcelona,41.50675777902313,2.118142981022385,,41.50675777902313_2.118142981022385_barcelona_google_maps_image,,41.50675777902313_2.118142981022385_barcelona_google_satellite_image,,41.50675777902313_2.118142981022385_barcelona_google_street_view_image,, -5827209216,1,barcelona,41.49520859831593,2.1565672248782466,,41.49520859831593_2.1565672248782466_barcelona_google_maps_image,,41.49520859831593_2.1565672248782466_barcelona_google_satellite_image,,41.49520859831593_2.1565672248782466_barcelona_google_street_view_image,, -3241096475,1,barcelona,41.32283441907746,2.1035026066796054,,41.32283441907746_2.1035026066796054_barcelona_google_maps_image,,41.32283441907746_2.1035026066796054_barcelona_google_satellite_image,,41.32283441907746_2.1035026066796054_barcelona_google_street_view_image,, -185078579,1,barcelona,41.281177606368935,1.9862486375777553,,41.281177606368935_1.9862486375777553_barcelona_google_maps_image,,41.281177606368935_1.9862486375777553_barcelona_google_satellite_image,,41.281177606368935_1.9862486375777553_barcelona_google_street_view_image,, -2383118579,1,barcelona,41.41807024022814,2.1489777740486167,,41.41807024022814_2.1489777740486167_barcelona_google_maps_image,,41.41807024022814_2.1489777740486167_barcelona_google_satellite_image,,41.41807024022814_2.1489777740486167_barcelona_google_street_view_image,, -6668763888,1,barcelona,41.48394959642878,2.1489991256680905,,41.48394959642878_2.1489991256680905_barcelona_google_maps_image,,41.48394959642878_2.1489991256680905_barcelona_google_satellite_image,,41.48394959642878_2.1489991256680905_barcelona_google_street_view_image,, -4767325124,1,barcelona,41.342716885596744,2.0404821316905717,,41.342716885596744_2.0404821316905717_barcelona_google_maps_image,,41.342716885596744_2.0404821316905717_barcelona_google_satellite_image,,41.342716885596744_2.0404821316905717_barcelona_google_street_view_image,, -3548613598,2,barcelona,41.43900573214387,2.2169882332044,,41.43900573214387_2.2169882332044_barcelona_google_maps_image,,41.43900573214387_2.2169882332044_barcelona_google_satellite_image,,41.43900573214387_2.2169882332044_barcelona_google_street_view_image,, -2175616321,2,barcelona,41.38681881765392,2.112393975494676,,41.38681881765392_2.112393975494676_barcelona_google_maps_image,,41.38681881765392_2.112393975494676_barcelona_google_satellite_image,,41.38681881765392_2.112393975494676_barcelona_google_street_view_image,, -2117060426,2,barcelona,41.446042070977235,2.240454811939617,,41.446042070977235_2.240454811939617_barcelona_google_maps_image,,41.446042070977235_2.240454811939617_barcelona_google_satellite_image,,41.446042070977235_2.240454811939617_barcelona_google_street_view_image,, -847721548,2,barcelona,41.416541117727974,2.1702805447835476,,41.416541117727974_2.1702805447835476_barcelona_google_maps_image,,41.416541117727974_2.1702805447835476_barcelona_google_satellite_image,,41.416541117727974_2.1702805447835476_barcelona_google_street_view_image,, -7518898718,2,barcelona,41.363394774902986,2.1001910882323513,,41.363394774902986_2.1001910882323513_barcelona_google_maps_image,,41.363394774902986_2.1001910882323513_barcelona_google_satellite_image,,41.363394774902986_2.1001910882323513_barcelona_google_street_view_image,, -7997135,2,barcelona,41.365532187425664,2.1272280534056254,,41.365532187425664_2.1272280534056254_barcelona_google_maps_image,,41.365532187425664_2.1272280534056254_barcelona_google_satellite_image,,41.365532187425664_2.1272280534056254_barcelona_google_street_view_image,, -2077932091,2,barcelona,41.37585041258002,2.1175734834996027,,41.37585041258002_2.1175734834996027_barcelona_google_maps_image,,41.37585041258002_2.1175734834996027_barcelona_google_satellite_image,,41.37585041258002_2.1175734834996027_barcelona_google_street_view_image,, -5484560922,2,barcelona,41.36052236121411,2.0751920444844303,,41.36052236121411_2.0751920444844303_barcelona_google_maps_image,,41.36052236121411_2.0751920444844303_barcelona_google_satellite_image,,41.36052236121411_2.0751920444844303_barcelona_google_street_view_image,, -2085728937,2,barcelona,41.39030417945104,2.197333972664933,,41.39030417945104_2.197333972664933_barcelona_google_maps_image,,41.39030417945104_2.197333972664933_barcelona_google_satellite_image,,41.39030417945104_2.197333972664933_barcelona_google_street_view_image,, -222540000,2,barcelona,41.36043452618159,2.0694254854974954,,41.36043452618159_2.0694254854974954_barcelona_google_maps_image,,41.36043452618159_2.0694254854974954_barcelona_google_satellite_image,,41.36043452618159_2.0694254854974954_barcelona_google_street_view_image,, -6334053690,3,barcelona,41.39997502161453,2.1642509766203815,,41.39997502161453_2.1642509766203815_barcelona_google_maps_image,,41.39997502161453_2.1642509766203815_barcelona_google_satellite_image,,41.39997502161453_2.1642509766203815_barcelona_google_street_view_image,, -1845294520,3,barcelona,41.40584326748737,2.1739842560263676,,41.40584326748737_2.1739842560263676_barcelona_google_maps_image,,41.40584326748737_2.1739842560263676_barcelona_google_satellite_image,,41.40584326748737_2.1739842560263676_barcelona_google_street_view_image,, -571182738,3,barcelona,41.44586509562727,2.1764751468105525,,41.44586509562727_2.1764751468105525_barcelona_google_maps_image,,41.44586509562727_2.1764751468105525_barcelona_google_satellite_image,,41.44586509562727_2.1764751468105525_barcelona_google_street_view_image,, -2430077720,3,barcelona,41.418157186374856,2.1897120399788963,,41.418157186374856_2.1897120399788963_barcelona_google_maps_image,,41.418157186374856_2.1897120399788963_barcelona_google_satellite_image,,41.418157186374856_2.1897120399788963_barcelona_google_street_view_image,, -6053049669,3,barcelona,41.38842342211086,2.1806763512511775,,41.38842342211086_2.1806763512511775_barcelona_google_maps_image,,41.38842342211086_2.1806763512511775_barcelona_google_satellite_image,,41.38842342211086_2.1806763512511775_barcelona_google_street_view_image,, -4172413190,3,barcelona,41.38626927156164,2.1575090346287396,,41.38626927156164_2.1575090346287396_barcelona_google_maps_image,,41.38626927156164_2.1575090346287396_barcelona_google_satellite_image,,41.38626927156164_2.1575090346287396_barcelona_google_street_view_image,, -4727188392,3,barcelona,41.40508581994903,2.166101531162817,,41.40508581994903_2.166101531162817_barcelona_google_maps_image,,41.40508581994903_2.166101531162817_barcelona_google_satellite_image,,41.40508581994903_2.166101531162817_barcelona_google_street_view_image,, -7704818549,3,barcelona,41.374684738362554,2.1329591281987113,,41.374684738362554_2.1329591281987113_barcelona_google_maps_image,,41.374684738362554_2.1329591281987113_barcelona_google_satellite_image,,41.374684738362554_2.1329591281987113_barcelona_google_street_view_image,, -7525316985,3,barcelona,41.41986976137159,2.174837906350266,,41.41986976137159_2.174837906350266_barcelona_google_maps_image,,41.41986976137159_2.174837906350266_barcelona_google_satellite_image,,41.41986976137159_2.174837906350266_barcelona_google_street_view_image,, -1361887258,3,barcelona,41.4055223899813,2.177394220288314,,41.4055223899813_2.177394220288314_barcelona_google_maps_image,,41.4055223899813_2.177394220288314_barcelona_google_satellite_image,,41.4055223899813_2.177394220288314_barcelona_google_street_view_image,, -4776901740,4,barcelona,41.38605912065319,2.1614010662356127,,41.38605912065319_2.1614010662356127_barcelona_google_maps_image,,41.38605912065319_2.1614010662356127_barcelona_google_satellite_image,,41.38605912065319_2.1614010662356127_barcelona_google_street_view_image,, -1755467726,4,barcelona,41.40559964124466,2.1533171848145565,,41.40559964124466_2.1533171848145565_barcelona_google_maps_image,,41.40559964124466_2.1533171848145565_barcelona_google_satellite_image,,41.40559964124466_2.1533171848145565_barcelona_google_street_view_image,, -5960931987,4,barcelona,41.386316601778674,2.1726872490633555,,41.386316601778674_2.1726872490633555_barcelona_google_maps_image,,41.386316601778674_2.1726872490633555_barcelona_google_satellite_image,,41.386316601778674_2.1726872490633555_barcelona_google_street_view_image,, -7556638085,4,barcelona,41.4045546587343,2.1965350895505966,,41.4045546587343_2.1965350895505966_barcelona_google_maps_image,,41.4045546587343_2.1965350895505966_barcelona_google_satellite_image,,41.4045546587343_2.1965350895505966_barcelona_google_street_view_image,, -5960910889,4,barcelona,41.38627721821352,2.1725983882403295,,41.38627721821352_2.1725983882403295_barcelona_google_maps_image,,41.38627721821352_2.1725983882403295_barcelona_google_satellite_image,,41.38627721821352_2.1725983882403295_barcelona_google_street_view_image,, -1357211197,4,barcelona,41.40400372828592,2.158059424491088,,41.40400372828592_2.158059424491088_barcelona_google_maps_image,,41.40400372828592_2.158059424491088_barcelona_google_satellite_image,,41.40400372828592_2.158059424491088_barcelona_google_street_view_image,, -1688067150,4,barcelona,41.38043701875776,2.129694498238833,,41.38043701875776_2.129694498238833_barcelona_google_maps_image,,41.38043701875776_2.129694498238833_barcelona_google_satellite_image,,41.38043701875776_2.129694498238833_barcelona_google_street_view_image,, -6247265677,4,barcelona,41.38187223172009,2.142160145424603,,41.38187223172009_2.142160145424603_barcelona_google_maps_image,,41.38187223172009_2.142160145424603_barcelona_google_satellite_image,,41.38187223172009_2.142160145424603_barcelona_google_street_view_image,, -4762854029,4,barcelona,41.38455407696959,2.163896302774564,,41.38455407696959_2.163896302774564_barcelona_google_maps_image,,41.38455407696959_2.163896302774564_barcelona_google_satellite_image,,41.38455407696959_2.163896302774564_barcelona_google_street_view_image,, -4873757769,4,barcelona,41.38507326909497,2.148620819331917,,41.38507326909497_2.148620819331917_barcelona_google_maps_image,,41.38507326909497_2.148620819331917_barcelona_google_satellite_image,,41.38507326909497_2.148620819331917_barcelona_google_street_view_image,, -1727174980,5,barcelona,41.427848511733906,2.1793931829707787,,41.427848511733906_2.1793931829707787_barcelona_google_maps_image,,41.427848511733906_2.1793931829707787_barcelona_google_satellite_image,,41.427848511733906_2.1793931829707787_barcelona_google_street_view_image,, -6823999785,5,barcelona,41.38365954857229,2.183888117131694,,41.38365954857229_2.183888117131694_barcelona_google_maps_image,,41.38365954857229_2.183888117131694_barcelona_google_satellite_image,,41.38365954857229_2.183888117131694_barcelona_google_street_view_image,, -4736328731,5,barcelona,41.38346002226871,2.129535922772446,,41.38346002226871_2.129535922772446_barcelona_google_maps_image,,41.38346002226871_2.129535922772446_barcelona_google_satellite_image,,41.38346002226871_2.129535922772446_barcelona_google_street_view_image,, -5972455502,5,barcelona,41.3972930253656,2.152248794029433,,41.3972930253656_2.152248794029433_barcelona_google_maps_image,,41.3972930253656_2.152248794029433_barcelona_google_satellite_image,,41.3972930253656_2.152248794029433_barcelona_google_street_view_image,, -7389224441,5,barcelona,41.45133085607761,2.2161410891877686,,41.45133085607761_2.2161410891877686_barcelona_google_maps_image,,41.45133085607761_2.2161410891877686_barcelona_google_satellite_image,,41.45133085607761_2.2161410891877686_barcelona_google_street_view_image,, -5845800585,5,barcelona,41.411752841906825,2.1795547060626808,,41.411752841906825_2.1795547060626808_barcelona_google_maps_image,,41.411752841906825_2.1795547060626808_barcelona_google_satellite_image,,41.411752841906825_2.1795547060626808_barcelona_google_street_view_image,, -4727951590,5,barcelona,41.41112276907388,2.182069305291159,,41.41112276907388_2.182069305291159_barcelona_google_maps_image,,41.41112276907388_2.182069305291159_barcelona_google_satellite_image,,41.41112276907388_2.182069305291159_barcelona_google_street_view_image,, -5531275475,5,barcelona,41.398135180878555,2.194259978287318,,41.398135180878555_2.194259978287318_barcelona_google_maps_image,,41.398135180878555_2.194259978287318_barcelona_google_satellite_image,,41.398135180878555_2.194259978287318_barcelona_google_street_view_image,, -1710707056,5,barcelona,41.38285172454865,2.1383177827340623,,41.38285172454865_2.1383177827340623_barcelona_google_maps_image,,41.38285172454865_2.1383177827340623_barcelona_google_satellite_image,,41.38285172454865_2.1383177827340623_barcelona_google_street_view_image,, -4727953590,5,barcelona,41.411863561247706,2.18112277770277,,41.411863561247706_2.18112277770277_barcelona_google_maps_image,,41.411863561247706_2.18112277770277_barcelona_google_satellite_image,,41.411863561247706_2.18112277770277_barcelona_google_street_view_image,, -3931020290,1,belfast,54.60010083094839,-5.925526950504084,,54.60010083094839_-5.925526950504084_belfast_google_maps_image,,54.60010083094839_-5.925526950504084_belfast_google_satellite_image,,54.60010083094839_-5.925526950504084_belfast_google_street_view_image,, -3930730200,1,belfast,54.6001966957186,-5.927904241881721,,54.6001966957186_-5.927904241881721_belfast_google_maps_image,,54.6001966957186_-5.927904241881721_belfast_google_satellite_image,,54.6001966957186_-5.927904241881721_belfast_google_street_view_image,, -4385113583,1,belfast,54.5980190649593,-5.932266684922414,,54.5980190649593_-5.932266684922414_belfast_google_maps_image,,54.5980190649593_-5.932266684922414_belfast_google_satellite_image,,54.5980190649593_-5.932266684922414_belfast_google_street_view_image,, -215403125,1,belfast,54.599454637088186,-5.931261126207947,,54.599454637088186_-5.931261126207947_belfast_google_maps_image,,54.599454637088186_-5.931261126207947_belfast_google_satellite_image,,54.599454637088186_-5.931261126207947_belfast_google_street_view_image,, -226265468,1,belfast,54.625673900755025,-5.913621390401916,,54.625673900755025_-5.913621390401916_belfast_google_maps_image,,54.625673900755025_-5.913621390401916_belfast_google_satellite_image,,54.625673900755025_-5.913621390401916_belfast_google_street_view_image,, -6732348036,1,belfast,54.59983195145868,-5.930568057575755,,54.59983195145868_-5.930568057575755_belfast_google_maps_image,,54.59983195145868_-5.930568057575755_belfast_google_satellite_image,,54.59983195145868_-5.930568057575755_belfast_google_street_view_image,, -5139201584,1,belfast,54.598031039303216,-5.931971211193691,,54.598031039303216_-5.931971211193691_belfast_google_maps_image,,54.598031039303216_-5.931971211193691_belfast_google_satellite_image,,54.598031039303216_-5.931971211193691_belfast_google_street_view_image,, -148530921,1,belfast,54.60801602110841,-5.968292699630438,,54.60801602110841_-5.968292699630438_belfast_google_maps_image,,54.60801602110841_-5.968292699630438_belfast_google_satellite_image,,54.60801602110841_-5.968292699630438_belfast_google_street_view_image,, -1667293021,1,belfast,54.65612560430331,-5.93387414093062,,54.65612560430331_-5.93387414093062_belfast_google_maps_image,,54.65612560430331_-5.93387414093062_belfast_google_satellite_image,,54.65612560430331_-5.93387414093062_belfast_google_street_view_image,, -1945583840,1,belfast,54.59779874205468,-5.9287751997175855,,54.59779874205468_-5.9287751997175855_belfast_google_maps_image,,54.59779874205468_-5.9287751997175855_belfast_google_satellite_image,,54.59779874205468_-5.9287751997175855_belfast_google_street_view_image,, -671740101,2,belfast,54.557540452669926,-6.025868780535815,,54.557540452669926_-6.025868780535815_belfast_google_maps_image,,54.557540452669926_-6.025868780535815_belfast_google_satellite_image,,54.557540452669926_-6.025868780535815_belfast_google_street_view_image,, -602205145,2,belfast,54.589637851659376,-5.844580448369623,,54.589637851659376_-5.844580448369623_belfast_google_maps_image,,54.589637851659376_-5.844580448369623_belfast_google_satellite_image,,54.589637851659376_-5.844580448369623_belfast_google_street_view_image,, -151506724,2,belfast,54.62774774330262,-5.921992750777932,,54.62774774330262_-5.921992750777932_belfast_google_maps_image,,54.62774774330262_-5.921992750777932_belfast_google_satellite_image,,54.62774774330262_-5.921992750777932_belfast_google_street_view_image,, -146477241,2,belfast,54.57893230432017,-5.978891660448143,,54.57893230432017_-5.978891660448143_belfast_google_maps_image,,54.57893230432017_-5.978891660448143_belfast_google_satellite_image,,54.57893230432017_-5.978891660448143_belfast_google_street_view_image,, -665148239,2,belfast,54.59597094181296,-5.892402925958394,,54.59597094181296_-5.892402925958394_belfast_google_maps_image,,54.59597094181296_-5.892402925958394_belfast_google_satellite_image,,54.59597094181296_-5.892402925958394_belfast_google_street_view_image,, -377474322,2,belfast,54.59047278932073,-5.91233954966689,,54.59047278932073_-5.91233954966689_belfast_google_maps_image,,54.59047278932073_-5.91233954966689_belfast_google_satellite_image,,54.59047278932073_-5.91233954966689_belfast_google_street_view_image,, -3178035574,2,belfast,54.582033900713185,-5.9777355904765255,,54.582033900713185_-5.9777355904765255_belfast_google_maps_image,,54.582033900713185_-5.9777355904765255_belfast_google_satellite_image,,54.582033900713185_-5.9777355904765255_belfast_google_street_view_image,, -560114632,2,belfast,54.55233231685459,-6.000363945445143,,54.55233231685459_-6.000363945445143_belfast_google_maps_image,,54.55233231685459_-6.000363945445143_belfast_google_satellite_image,,54.55233231685459_-6.000363945445143_belfast_google_street_view_image,, -6783379052,2,belfast,54.58951130071995,-5.961341290458311,,54.58951130071995_-5.961341290458311_belfast_google_maps_image,,54.58951130071995_-5.961341290458311_belfast_google_satellite_image,,54.58951130071995_-5.961341290458311_belfast_google_street_view_image,, -6895327586,2,belfast,54.58935064954835,-5.845127434255506,,54.58935064954835_-5.845127434255506_belfast_google_maps_image,,54.58935064954835_-5.845127434255506_belfast_google_satellite_image,,54.58935064954835_-5.845127434255506_belfast_google_street_view_image,, -769156357,3,belfast,54.595959052490066,-5.873499010142215,,54.595959052490066_-5.873499010142215_belfast_google_maps_image,,54.595959052490066_-5.873499010142215_belfast_google_satellite_image,,54.595959052490066_-5.873499010142215_belfast_google_street_view_image,, -3023216893,3,belfast,54.57335572469245,-5.931849125012466,,54.57335572469245_-5.931849125012466_belfast_google_maps_image,,54.57335572469245_-5.931849125012466_belfast_google_satellite_image,,54.57335572469245_-5.931849125012466_belfast_google_street_view_image,, -151506725,3,belfast,54.6270276398455,-5.924608165821086,,54.6270276398455_-5.924608165821086_belfast_google_maps_image,,54.6270276398455_-5.924608165821086_belfast_google_satellite_image,,54.6270276398455_-5.924608165821086_belfast_google_street_view_image,, -653139484,3,belfast,54.568829132910125,-5.913399650162852,,54.568829132910125_-5.913399650162852_belfast_google_maps_image,,54.568829132910125_-5.913399650162852_belfast_google_satellite_image,,54.568829132910125_-5.913399650162852_belfast_google_street_view_image,, -7004217324,3,belfast,54.58934165028636,-5.969118803104395,,54.58934165028636_-5.969118803104395_belfast_google_maps_image,,54.58934165028636_-5.969118803104395_belfast_google_satellite_image,,54.58934165028636_-5.969118803104395_belfast_google_street_view_image,, -389983466,3,belfast,54.56843874739376,-6.0081721672124715,,54.56843874739376_-6.0081721672124715_belfast_google_maps_image,,54.56843874739376_-6.0081721672124715_belfast_google_satellite_image,,54.56843874739376_-6.0081721672124715_belfast_google_street_view_image,, -1715618826,3,belfast,54.575843331527686,-5.896180850512349,,54.575843331527686_-5.896180850512349_belfast_google_maps_image,,54.575843331527686_-5.896180850512349_belfast_google_satellite_image,,54.575843331527686_-5.896180850512349_belfast_google_street_view_image,, -2096353580,3,belfast,54.584592789102366,-5.9226225644365735,,54.584592789102366_-5.9226225644365735_belfast_google_maps_image,,54.584592789102366_-5.9226225644365735_belfast_google_satellite_image,,54.584592789102366_-5.9226225644365735_belfast_google_street_view_image,, -161367736,3,belfast,54.59634880072208,-5.894502090389789,,54.59634880072208_-5.894502090389789_belfast_google_maps_image,,54.59634880072208_-5.894502090389789_belfast_google_satellite_image,,54.59634880072208_-5.894502090389789_belfast_google_street_view_image,, -7062914629,3,belfast,54.59019847907826,-5.9273093132071235,,54.59019847907826_-5.9273093132071235_belfast_google_maps_image,,54.59019847907826_-5.9273093132071235_belfast_google_satellite_image,,54.59019847907826_-5.9273093132071235_belfast_google_street_view_image,, -141747886,4,belfast,54.58165554077348,-5.923041738474682,,54.58165554077348_-5.923041738474682_belfast_google_maps_image,,54.58165554077348_-5.923041738474682_belfast_google_satellite_image,,54.58165554077348_-5.923041738474682_belfast_google_street_view_image,, -2445259295,4,belfast,54.591784725762835,-5.898864292852408,,54.591784725762835_-5.898864292852408_belfast_google_maps_image,,54.591784725762835_-5.898864292852408_belfast_google_satellite_image,,54.591784725762835_-5.898864292852408_belfast_google_street_view_image,, -2048688282,4,belfast,54.5786703019085,-5.919339849923161,,54.5786703019085_-5.919339849923161_belfast_google_maps_image,,54.5786703019085_-5.919339849923161_belfast_google_satellite_image,,54.5786703019085_-5.919339849923161_belfast_google_street_view_image,, -398720096,4,belfast,54.62614398827238,-5.937366566979514,,54.62614398827238_-5.937366566979514_belfast_google_maps_image,,54.62614398827238_-5.937366566979514_belfast_google_satellite_image,,54.62614398827238_-5.937366566979514_belfast_google_street_view_image,, -438772404,4,belfast,54.63103080076335,-5.946526690433616,,54.63103080076335_-5.946526690433616_belfast_google_maps_image,,54.63103080076335_-5.946526690433616_belfast_google_satellite_image,,54.63103080076335_-5.946526690433616_belfast_google_street_view_image,, -4393526723,4,belfast,54.622617800753645,-5.93775269042681,,54.622617800753645_-5.93775269042681_belfast_google_maps_image,,54.622617800753645_-5.93775269042681_belfast_google_satellite_image,,54.622617800753645_-5.93775269042681_belfast_google_street_view_image,, -7251887726,4,belfast,54.59464230071988,-5.88995019038565,,54.59464230071988_-5.88995019038565_belfast_google_maps_image,,54.59464230071988_-5.88995019038565_belfast_google_satellite_image,,54.59464230071988_-5.88995019038565_belfast_google_street_view_image,, -4038588698,4,belfast,54.578718093707224,-5.919376944580229,,54.578718093707224_-5.919376944580229_belfast_google_maps_image,,54.578718093707224_-5.919376944580229_belfast_google_satellite_image,,54.578718093707224_-5.919376944580229_belfast_google_street_view_image,, -298418084,4,belfast,54.588142990278335,-5.894104044995761,,54.588142990278335_-5.894104044995761_belfast_google_maps_image,,54.588142990278335_-5.894104044995761_belfast_google_satellite_image,,54.588142990278335_-5.894104044995761_belfast_google_street_view_image,, -211044241,4,belfast,54.61215233391405,-5.95565464274492,,54.61215233391405_-5.95565464274492_belfast_google_maps_image,,54.61215233391405_-5.95565464274492_belfast_google_satellite_image,,54.61215233391405_-5.95565464274492_belfast_google_street_view_image,, -621452538,5,belfast,54.58853545693416,-5.948497170439899,,54.58853545693416_-5.948497170439899_belfast_google_maps_image,,54.58853545693416_-5.948497170439899_belfast_google_satellite_image,,54.58853545693416_-5.948497170439899_belfast_google_street_view_image,, -2445264511,5,belfast,54.58871937386414,-5.900954150092114,,54.58871937386414_-5.900954150092114_belfast_google_maps_image,,54.58871937386414_-5.900954150092114_belfast_google_satellite_image,,54.58871937386414_-5.900954150092114_belfast_google_street_view_image,, -341513798,5,belfast,54.58147183129029,-5.9490978839627315,,54.58147183129029_-5.9490978839627315_belfast_google_maps_image,,54.58147183129029_-5.9490978839627315_belfast_google_satellite_image,,54.58147183129029_-5.9490978839627315_belfast_google_street_view_image,, -6997205819,5,belfast,54.598034848581946,-5.887563010140464,,54.598034848581946_-5.887563010140464_belfast_google_maps_image,,54.598034848581946_-5.887563010140464_belfast_google_satellite_image,,54.598034848581946_-5.887563010140464_belfast_google_street_view_image,, -2445232380,5,belfast,54.58730124785496,-5.9002784419032945,,54.58730124785496_-5.9002784419032945_belfast_google_maps_image,,54.58730124785496_-5.9002784419032945_belfast_google_satellite_image,,54.58730124785496_-5.9002784419032945_belfast_google_street_view_image,, -2445261883,5,belfast,54.59100740071698,-5.902541590399099,,54.59100740071698_-5.902541590399099_belfast_google_maps_image,,54.59100740071698_-5.902541590399099_belfast_google_satellite_image,,54.59100740071698_-5.902541590399099_belfast_google_street_view_image,, -618579152,5,belfast,54.59792560072871,-5.957815890452777,,54.59792560072871_-5.957815890452777_belfast_google_maps_image,,54.59792560072871_-5.957815890452777_belfast_google_satellite_image,,54.59792560072871_-5.957815890452777_belfast_google_street_view_image,, -4038588656,5,belfast,54.576002857018146,-5.917401539939645,,54.576002857018146_-5.917401539939645_belfast_google_maps_image,,54.576002857018146_-5.917401539939645_belfast_google_satellite_image,,54.576002857018146_-5.917401539939645_belfast_google_street_view_image,, -2445211936,5,belfast,54.5884374555479,-5.9009640012197275,,54.5884374555479_-5.9009640012197275_belfast_google_maps_image,,54.5884374555479_-5.9009640012197275_belfast_google_satellite_image,,54.5884374555479_-5.9009640012197275_belfast_google_street_view_image,, -2445264431,5,belfast,54.589053102101616,-5.90135543363438,,54.589053102101616_-5.90135543363438_belfast_google_maps_image,,54.589053102101616_-5.90135543363438_belfast_google_satellite_image,,54.589053102101616_-5.90135543363438_belfast_google_street_view_image,, -7640147839,1,bern,46.945370779062095,7.373375851987099,,46.945370779062095_7.373375851987099_bern_google_maps_image,,46.945370779062095_7.373375851987099_bern_google_satellite_image,,46.945370779062095_7.373375851987099_bern_google_street_view_image,, --9364832,1,bern,46.94677253757923,7.451827340951852,,46.94677253757923_7.451827340951852_bern_google_maps_image,,46.94677253757923_7.451827340951852_bern_google_satellite_image,,46.94677253757923_7.451827340951852_bern_google_street_view_image,, -7601934683,1,bern,46.96794366206422,7.464499483905497,,46.96794366206422_7.464499483905497_bern_google_maps_image,,46.96794366206422_7.464499483905497_bern_google_satellite_image,,46.96794366206422_7.464499483905497_bern_google_street_view_image,, -3573717230,1,bern,46.943126550360304,7.450991486699755,,46.943126550360304_7.450991486699755_bern_google_maps_image,,46.943126550360304_7.450991486699755_bern_google_satellite_image,,46.943126550360304_7.450991486699755_bern_google_street_view_image,, -564771189,1,bern,46.942763996879144,7.443534413721496,,46.942763996879144_7.443534413721496_bern_google_maps_image,,46.942763996879144_7.443534413721496_bern_google_satellite_image,,46.942763996879144_7.443534413721496_bern_google_street_view_image,, -3345300147,1,bern,46.957235932037364,7.437179012336026,,46.957235932037364_7.437179012336026_bern_google_maps_image,,46.957235932037364_7.437179012336026_bern_google_satellite_image,,46.957235932037364_7.437179012336026_bern_google_street_view_image,, -3522686123,1,bern,46.95129769999999,7.3949183,,46.95129769999999_7.3949183_bern_google_maps_image,,46.95129769999999_7.3949183_bern_google_satellite_image,,46.95129769999999_7.3949183_bern_google_street_view_image,, -6166590461,1,bern,46.94978513901572,7.412526031790052,,46.94978513901572_7.412526031790052_bern_google_maps_image,,46.94978513901572_7.412526031790052_bern_google_satellite_image,,46.94978513901572_7.412526031790052_bern_google_street_view_image,, -536764788,1,bern,46.939578832630964,7.481465445792677,,46.939578832630964_7.481465445792677_bern_google_maps_image,,46.939578832630964_7.481465445792677_bern_google_satellite_image,,46.939578832630964_7.481465445792677_bern_google_street_view_image,, -536764783,1,bern,46.93940889228398,7.480728354644646,,46.93940889228398_7.480728354644646_bern_google_maps_image,,46.93940889228398_7.480728354644646_bern_google_satellite_image,,46.93940889228398_7.480728354644646_bern_google_street_view_image,, -7128513589,2,bern,46.9531668,7.458189000000003,,46.9531668_7.458189000000003_bern_google_maps_image,,46.9531668_7.458189000000003_bern_google_satellite_image,,46.9531668_7.458189000000003_bern_google_street_view_image,, -454141500,2,bern,46.94106028605951,7.418754624815147,,46.94106028605951_7.418754624815147_bern_google_maps_image,,46.94106028605951_7.418754624815147_bern_google_satellite_image,,46.94106028605951_7.418754624815147_bern_google_street_view_image,, -5750260296,2,bern,46.94800137654151,7.3833007840557405,,46.94800137654151_7.3833007840557405_bern_google_maps_image,,46.94800137654151_7.3833007840557405_bern_google_satellite_image,,46.94800137654151_7.3833007840557405_bern_google_street_view_image,, -6283505194,2,bern,46.94856254059506,7.447817695347167,,46.94856254059506_7.447817695347167_bern_google_maps_image,,46.94856254059506_7.447817695347167_bern_google_satellite_image,,46.94856254059506_7.447817695347167_bern_google_street_view_image,, -506258000,2,bern,46.94370258095633,7.469968256162423,,46.94370258095633_7.469968256162423_bern_google_maps_image,,46.94370258095633_7.469968256162423_bern_google_satellite_image,,46.94370258095633_7.469968256162423_bern_google_street_view_image,, -2212710376,2,bern,46.94814105097623,7.446101016046004,,46.94814105097623_7.446101016046004_bern_google_maps_image,,46.94814105097623_7.446101016046004_bern_google_satellite_image,,46.94814105097623_7.446101016046004_bern_google_street_view_image,, -474362125,2,bern,46.94158607531534,7.462785375669382,,46.94158607531534_7.462785375669382_bern_google_maps_image,,46.94158607531534_7.462785375669382_bern_google_satellite_image,,46.94158607531534_7.462785375669382_bern_google_street_view_image,, -667410514,2,bern,46.937564652320184,7.43229317700543,,46.937564652320184_7.43229317700543_bern_google_maps_image,,46.937564652320184_7.43229317700543_bern_google_satellite_image,,46.937564652320184_7.43229317700543_bern_google_street_view_image,, -279803128,2,bern,46.95565126894074,7.445146618275452,,46.95565126894074_7.445146618275452_bern_google_maps_image,,46.95565126894074_7.445146618275452_bern_google_satellite_image,,46.95565126894074_7.445146618275452_bern_google_street_view_image,, -489771088,2,bern,46.94232200829762,7.453174297632006,,46.94232200829762_7.453174297632006_bern_google_maps_image,,46.94232200829762_7.453174297632006_bern_google_satellite_image,,46.94232200829762_7.453174297632006_bern_google_street_view_image,, -507607630,3,bern,46.93958358413784,7.388728659220972,,46.93958358413784_7.388728659220972_bern_google_maps_image,,46.93958358413784_7.388728659220972_bern_google_satellite_image,,46.93958358413784_7.388728659220972_bern_google_street_view_image,, -2969434883,3,bern,46.948128058837575,7.441686382455266,,46.948128058837575_7.441686382455266_bern_google_maps_image,,46.948128058837575_7.441686382455266_bern_google_satellite_image,,46.948128058837575_7.441686382455266_bern_google_street_view_image,, -3623056337,3,bern,46.94951071129533,7.441209801360913,,46.94951071129533_7.441209801360913_bern_google_maps_image,,46.94951071129533_7.441209801360913_bern_google_satellite_image,,46.94951071129533_7.441209801360913_bern_google_street_view_image,, -2915808790,3,bern,46.94676701740003,7.437586853802117,,46.94676701740003_7.437586853802117_bern_google_maps_image,,46.94676701740003_7.437586853802117_bern_google_satellite_image,,46.94676701740003_7.437586853802117_bern_google_street_view_image,, -2917664561,3,bern,46.947783098320926,7.441569902669729,,46.947783098320926_7.441569902669729_bern_google_maps_image,,46.947783098320926_7.441569902669729_bern_google_satellite_image,,46.947783098320926_7.441569902669729_bern_google_street_view_image,, -3623072602,3,bern,46.93980985510001,7.38976047161021,,46.93980985510001_7.38976047161021_bern_google_maps_image,,46.93980985510001_7.38976047161021_bern_google_satellite_image,,46.93980985510001_7.38976047161021_bern_google_street_view_image,, -6928113140,3,bern,46.94904570325827,7.440865324883112,,46.94904570325827_7.440865324883112_bern_google_maps_image,,46.94904570325827_7.440865324883112_bern_google_satellite_image,,46.94904570325827_7.440865324883112_bern_google_street_view_image,, -4995140829,3,bern,46.947616432350955,7.443584257005478,,46.947616432350955_7.443584257005478_bern_google_maps_image,,46.947616432350955_7.443584257005478_bern_google_satellite_image,,46.947616432350955_7.443584257005478_bern_google_street_view_image,, -2969434882,3,bern,46.94824222329538,7.441054114609541,,46.94824222329538_7.441054114609541_bern_google_maps_image,,46.94824222329538_7.441054114609541_bern_google_satellite_image,,46.94824222329538_7.441054114609541_bern_google_street_view_image,, -312385262,3,bern,46.94966896592594,7.441788412178158,,46.94966896592594_7.441788412178158_bern_google_maps_image,,46.94966896592594_7.441788412178158_bern_google_satellite_image,,46.94966896592594_7.441788412178158_bern_google_street_view_image,, -4039021088,4,bern,46.9488859107926,7.437619301840851,,46.9488859107926_7.437619301840851_bern_google_maps_image,,46.9488859107926_7.437619301840851_bern_google_satellite_image,,46.9488859107926_7.437619301840851_bern_google_street_view_image,, -6324987839,4,bern,46.94371218301658,7.411668484288689,,46.94371218301658_7.411668484288689_bern_google_maps_image,,46.94371218301658_7.411668484288689_bern_google_satellite_image,,46.94371218301658_7.411668484288689_bern_google_street_view_image,, -5674726173,4,bern,46.95871556250214,7.454428491325774,,46.95871556250214_7.454428491325774_bern_google_maps_image,,46.95871556250214_7.454428491325774_bern_google_satellite_image,,46.95871556250214_7.454428491325774_bern_google_street_view_image,, -7403456487,4,bern,46.963601867807114,7.455899479942447,,46.963601867807114_7.455899479942447_bern_google_maps_image,,46.963601867807114_7.455899479942447_bern_google_satellite_image,,46.963601867807114_7.455899479942447_bern_google_street_view_image,, -6283505193,4,bern,46.94751963352514,7.448419232720182,,46.94751963352514_7.448419232720182_bern_google_maps_image,,46.94751963352514_7.448419232720182_bern_google_satellite_image,,46.94751963352514_7.448419232720182_bern_google_street_view_image,, -280528118,4,bern,46.95675292763683,7.432109010573549,,46.95675292763683_7.432109010573549_bern_google_maps_image,,46.95675292763683_7.432109010573549_bern_google_satellite_image,,46.95675292763683_7.432109010573549_bern_google_street_view_image,, -2319568957,4,bern,46.94448467982089,7.3995651743113635,,46.94448467982089_7.3995651743113635_bern_google_maps_image,,46.94448467982089_7.3995651743113635_bern_google_satellite_image,,46.94448467982089_7.3995651743113635_bern_google_street_view_image,, -1714599215,4,bern,46.94875933364523,7.3940632243182165,,46.94875933364523_7.3940632243182165_bern_google_maps_image,,46.94875933364523_7.3940632243182165_bern_google_satellite_image,,46.94875933364523_7.3940632243182165_bern_google_street_view_image,, -892818865,4,bern,46.948660647955904,7.43744900158191,,46.948660647955904_7.43744900158191_bern_google_maps_image,,46.948660647955904_7.43744900158191_bern_google_satellite_image,,46.948660647955904_7.43744900158191_bern_google_street_view_image,, -280528081,4,bern,46.9560726065404,7.446872482829162,,46.9560726065404_7.446872482829162_bern_google_maps_image,,46.9560726065404_7.446872482829162_bern_google_satellite_image,,46.9560726065404_7.446872482829162_bern_google_street_view_image,, -540597931,5,bern,46.96142672298649,7.4528740745586015,,46.96142672298649_7.4528740745586015_bern_google_maps_image,,46.96142672298649_7.4528740745586015_bern_google_satellite_image,,46.96142672298649_7.4528740745586015_bern_google_street_view_image,, -379582591,5,bern,46.94854048227348,7.43962547117718,,46.94854048227348_7.43962547117718_bern_google_maps_image,,46.94854048227348_7.43962547117718_bern_google_satellite_image,,46.94854048227348_7.43962547117718_bern_google_street_view_image,, -558568861,5,bern,46.95335707677212,7.432576056490557,,46.95335707677212_7.432576056490557_bern_google_maps_image,,46.95335707677212_7.432576056490557_bern_google_satellite_image,,46.95335707677212_7.432576056490557_bern_google_street_view_image,, -811210957,5,bern,46.95366581375531,7.429247521478107,,46.95366581375531_7.429247521478107_bern_google_maps_image,,46.95366581375531_7.429247521478107_bern_google_satellite_image,,46.95366581375531_7.429247521478107_bern_google_street_view_image,, -811329218,5,bern,46.95411505285083,7.430811218665848,,46.95411505285083_7.430811218665848_bern_google_maps_image,,46.95411505285083_7.430811218665848_bern_google_satellite_image,,46.95411505285083_7.430811218665848_bern_google_street_view_image,, -2984992145,5,bern,46.95385156468184,7.428824909094237,,46.95385156468184_7.428824909094237_bern_google_maps_image,,46.95385156468184_7.428824909094237_bern_google_satellite_image,,46.95385156468184_7.428824909094237_bern_google_street_view_image,, -667410777,5,bern,46.94017450190598,7.431902613019022,,46.94017450190598_7.431902613019022_bern_google_maps_image,,46.94017450190598_7.431902613019022_bern_google_satellite_image,,46.94017450190598_7.431902613019022_bern_google_street_view_image,, -533642537,5,bern,46.94403378566885,7.427586891293928,,46.94403378566885_7.427586891293928_bern_google_maps_image,,46.94403378566885_7.427586891293928_bern_google_satellite_image,,46.94403378566885_7.427586891293928_bern_google_street_view_image,, -678194273,5,bern,46.948542613572215,7.440070115902962,,46.948542613572215_7.440070115902962_bern_google_maps_image,,46.948542613572215_7.440070115902962_bern_google_satellite_image,,46.948542613572215_7.440070115902962_bern_google_street_view_image,, -2031938751,5,bern,46.95376557573043,7.431786822776838,,46.95376557573043_7.431786822776838_bern_google_maps_image,,46.95376557573043_7.431786822776838_bern_google_satellite_image,,46.95376557573043_7.431786822776838_bern_google_street_view_image,, -3040100731,1,chennai,12.97298392331194,80.19178500041505,,12.97298392331194_80.19178500041505_chennai_google_maps_image,,12.97298392331194_80.19178500041505_chennai_google_satellite_image,,12.97298392331194_80.19178500041505_chennai_google_street_view_image,, -355002675,1,chennai,12.97109596211607,80.19044846460791,,12.97109596211607_80.19044846460791_chennai_google_maps_image,,12.97109596211607_80.19044846460791_chennai_google_satellite_image,,12.97109596211607_80.19044846460791_chennai_google_street_view_image,, -223937121,1,chennai,12.9843200357826,80.18851633315549,,12.9843200357826_80.18851633315549_chennai_google_maps_image,,12.9843200357826_80.18851633315549_chennai_google_satellite_image,,12.9843200357826_80.18851633315549_chennai_google_street_view_image,, -6535920667,1,chennai,13.122258352120205,80.14990843059988,,13.122258352120205_80.14990843059988_chennai_google_maps_image,,13.122258352120205_80.14990843059988_chennai_google_satellite_image,,13.122258352120205_80.14990843059988_chennai_google_street_view_image,, -2734244476,1,chennai,13.017422169878886,80.17454770397339,,13.017422169878886_80.17454770397339_chennai_google_maps_image,,13.017422169878886_80.17454770397339_chennai_google_satellite_image,,13.017422169878886_80.17454770397339_chennai_google_street_view_image,, -5230405189,1,chennai,13.080799177244824,80.16466595414377,,13.080799177244824_80.16466595414377_chennai_google_maps_image,,13.080799177244824_80.16466595414377_chennai_google_satellite_image,,13.080799177244824_80.16466595414377_chennai_google_street_view_image,, -1411883069,1,chennai,13.020630024865872,80.2429945071415,,13.020630024865872_80.2429945071415_chennai_google_maps_image,,13.020630024865872_80.2429945071415_chennai_google_satellite_image,,13.020630024865872_80.2429945071415_chennai_google_street_view_image,, -4469843445,1,chennai,12.997067199999996,80.2406534,,12.997067199999996_80.2406534_chennai_google_maps_image,,12.997067199999996_80.2406534_chennai_google_satellite_image,,12.997067199999996_80.2406534_chennai_google_street_view_image,, -3687708989,1,chennai,12.997109140652528,80.2404666661655,,12.997109140652528_80.2404666661655_chennai_google_maps_image,,12.997109140652528_80.2404666661655_chennai_google_satellite_image,,12.997109140652528_80.2404666661655_chennai_google_street_view_image,, -772926217,1,chennai,13.228517027051677,80.32402186352023,,13.228517027051677_80.32402186352023_chennai_google_maps_image,,13.228517027051677_80.32402186352023_chennai_google_satellite_image,,13.228517027051677_80.32402186352023_chennai_google_street_view_image,, -1775800576,2,chennai,12.99601909761322,80.26773807532396,,12.99601909761322_80.26773807532396_chennai_google_maps_image,,12.99601909761322_80.26773807532396_chennai_google_satellite_image,,12.99601909761322_80.26773807532396_chennai_google_street_view_image,, -4766458866,2,chennai,12.985683550028115,80.23067809608818,,12.985683550028115_80.23067809608818_chennai_google_maps_image,,12.985683550028115_80.23067809608818_chennai_google_satellite_image,,12.985683550028115_80.23067809608818_chennai_google_street_view_image,, -5653260321,2,chennai,13.029210770129911,80.248556662744,,13.029210770129911_80.248556662744_chennai_google_maps_image,,13.029210770129911_80.248556662744_chennai_google_satellite_image,,13.029210770129911_80.248556662744_chennai_google_street_view_image,, -5570539460,2,chennai,12.985934875405722,80.22797137137769,,12.985934875405722_80.22797137137769_chennai_google_maps_image,,12.985934875405722_80.22797137137769_chennai_google_satellite_image,,12.985934875405722_80.22797137137769_chennai_google_street_view_image,, -7551657315,2,chennai,12.96955201771676,80.2442215504774,,12.96955201771676_80.2442215504774_chennai_google_maps_image,,12.96955201771676_80.2442215504774_chennai_google_satellite_image,,12.96955201771676_80.2442215504774_chennai_google_street_view_image,, -378688535,2,chennai,13.028669942563571,80.2496403556352,,13.028669942563571_80.2496403556352_chennai_google_maps_image,,13.028669942563571_80.2496403556352_chennai_google_satellite_image,,13.028669942563571_80.2496403556352_chennai_google_street_view_image,, -217849598,2,chennai,13.085421444668144,80.279163960729,,13.085421444668144_80.279163960729_chennai_google_maps_image,,13.085421444668144_80.279163960729_chennai_google_satellite_image,,13.085421444668144_80.279163960729_chennai_google_street_view_image,, -4379537181,2,chennai,13.006595228767429,80.2519156368438,,13.006595228767429_80.2519156368438_chennai_google_maps_image,,13.006595228767429_80.2519156368438_chennai_google_satellite_image,,13.006595228767429_80.2519156368438_chennai_google_street_view_image,, -864565812,2,chennai,13.039841165924516,80.25178855744187,,13.039841165924516_80.25178855744187_chennai_google_maps_image,,13.039841165924516_80.25178855744187_chennai_google_satellite_image,,13.039841165924516_80.25178855744187_chennai_google_street_view_image,, -2455032488,2,chennai,13.110408660658885,80.21059911480252,,13.110408660658885_80.21059911480252_chennai_google_maps_image,,13.110408660658885_80.21059911480252_chennai_google_satellite_image,,13.110408660658885_80.21059911480252_chennai_google_street_view_image,, -321504325,3,chennai,13.005805734783932,80.25184243690636,,13.005805734783932_80.25184243690636_chennai_google_maps_image,,13.005805734783932_80.25184243690636_chennai_google_satellite_image,,13.005805734783932_80.25184243690636_chennai_google_street_view_image,, -7271112274,3,chennai,13.057397080450746,80.2428330832012,,13.057397080450746_80.2428330832012_chennai_google_maps_image,,13.057397080450746_80.2428330832012_chennai_google_satellite_image,,13.057397080450746_80.2428330832012_chennai_google_street_view_image,, -3961459336,3,chennai,13.081581699946831,80.22538647587787,,13.081581699946831_80.22538647587787_chennai_google_maps_image,,13.081581699946831_80.22538647587787_chennai_google_satellite_image,,13.081581699946831_80.22538647587787_chennai_google_street_view_image,, -7652633333,3,chennai,13.03431070262116,80.21553816978636,,13.03431070262116_80.21553816978636_chennai_google_maps_image,,13.03431070262116_80.21553816978636_chennai_google_satellite_image,,13.03431070262116_80.21553816978636_chennai_google_street_view_image,, -279527198,3,chennai,13.085008980724401,80.20598603962524,,13.085008980724401_80.20598603962524_chennai_google_maps_image,,13.085008980724401_80.20598603962524_chennai_google_satellite_image,,13.085008980724401_80.20598603962524_chennai_google_street_view_image,, -1640625233,3,chennai,12.981240820144643,80.22999418662502,,12.981240820144643_80.22999418662502_chennai_google_maps_image,,12.981240820144643_80.22999418662502_chennai_google_satellite_image,,12.981240820144643_80.22999418662502_chennai_google_street_view_image,, -7652723880,3,chennai,12.990565541785143,80.21622206763652,,12.990565541785143_80.21622206763652_chennai_google_maps_image,,12.990565541785143_80.21622206763652_chennai_google_satellite_image,,12.990565541785143_80.21622206763652_chennai_google_street_view_image,, -3875702945,3,chennai,13.09890178013752,80.25987985287269,,13.09890178013752_80.25987985287269_chennai_google_maps_image,,13.09890178013752_80.25987985287269_chennai_google_satellite_image,,13.09890178013752_80.25987985287269_chennai_google_street_view_image,, -1024556272,3,chennai,13.035402210751034,80.21626524937062,,13.035402210751034_80.21626524937062_chennai_google_maps_image,,13.035402210751034_80.21626524937062_chennai_google_satellite_image,,13.035402210751034_80.21626524937062_chennai_google_street_view_image,, -934859085,3,chennai,13.044569248422441,80.18545654819863,,13.044569248422441_80.18545654819863_chennai_google_maps_image,,13.044569248422441_80.18545654819863_chennai_google_satellite_image,,13.044569248422441_80.18545654819863_chennai_google_street_view_image,, -231053133,4,chennai,13.090340832642346,80.21788470297457,,13.090340832642346_80.21788470297457_chennai_google_maps_image,,13.090340832642346_80.21788470297457_chennai_google_satellite_image,,13.090340832642346_80.21788470297457_chennai_google_street_view_image,, -4308320004,4,chennai,13.024336167693983,80.2144462443253,,13.024336167693983_80.2144462443253_chennai_google_maps_image,,13.024336167693983_80.2144462443253_chennai_google_satellite_image,,13.024336167693983_80.2144462443253_chennai_google_street_view_image,, -2296728885,4,chennai,13.075318033770154,80.26988237874345,,13.075318033770154_80.26988237874345_chennai_google_maps_image,,13.075318033770154_80.26988237874345_chennai_google_satellite_image,,13.075318033770154_80.26988237874345_chennai_google_street_view_image,, -5242605023,4,chennai,12.977164518011488,80.2620912613245,,12.977164518011488_80.2620912613245_chennai_google_maps_image,,12.977164518011488_80.2620912613245_chennai_google_satellite_image,,12.977164518011488_80.2620912613245_chennai_google_street_view_image,, -4688930495,4,chennai,13.038040713483538,80.2295149741751,,13.038040713483538_80.2295149741751_chennai_google_maps_image,,13.038040713483538_80.2295149741751_chennai_google_satellite_image,,13.038040713483538_80.2295149741751_chennai_google_street_view_image,, -612552098,4,chennai,13.07705233700919,80.21088890170279,,13.07705233700919_80.21088890170279_chennai_google_maps_image,,13.07705233700919_80.21088890170279_chennai_google_satellite_image,,13.07705233700919_80.21088890170279_chennai_google_street_view_image,, -214711575,4,chennai,13.075313798270342,80.26989956349696,,13.075313798270342_80.26989956349696_chennai_google_maps_image,,13.075313798270342_80.26989956349696_chennai_google_satellite_image,,13.075313798270342_80.26989956349696_chennai_google_street_view_image,, -1640625237,4,chennai,12.981172898847838,80.22929561469421,,12.981172898847838_80.22929561469421_chennai_google_maps_image,,12.981172898847838_80.22929561469421_chennai_google_satellite_image,,12.981172898847838_80.22929561469421_chennai_google_street_view_image,, -7252446776,4,chennai,13.054878605994553,80.24554982426895,,13.054878605994553_80.24554982426895_chennai_google_maps_image,,13.054878605994553_80.24554982426895_chennai_google_satellite_image,,13.054878605994553_80.24554982426895_chennai_google_street_view_image,, -1800440276,4,chennai,13.084538383658579,80.2056855544979,,13.084538383658579_80.2056855544979_chennai_google_maps_image,,13.084538383658579_80.2056855544979_chennai_google_satellite_image,,13.084538383658579_80.2056855544979_chennai_google_street_view_image,, -1640621203,5,chennai,12.981045108537622,80.22928646623167,,12.981045108537622_80.22928646623167_chennai_google_maps_image,,12.981045108537622_80.22928646623167_chennai_google_satellite_image,,12.981045108537622_80.22928646623167_chennai_google_street_view_image,, -1764308007,5,chennai,12.971751999616933,80.21931337288298,,12.971751999616933_80.21931337288298_chennai_google_maps_image,,12.971751999616933_80.21931337288298_chennai_google_satellite_image,,12.971751999616933_80.21931337288298_chennai_google_street_view_image,, -386890403,5,chennai,13.044372698490648,80.26354543302881,,13.044372698490648_80.26354543302881_chennai_google_maps_image,,13.044372698490648_80.26354543302881_chennai_google_satellite_image,,13.044372698490648_80.26354543302881_chennai_google_street_view_image,, -354999189,5,chennai,13.04792341928793,80.26412309286681,,13.04792341928793_80.26412309286681_chennai_google_maps_image,,13.04792341928793_80.26412309286681_chennai_google_satellite_image,,13.04792341928793_80.26412309286681_chennai_google_street_view_image,, -6010172976,5,chennai,13.036212742904606,80.22067224928986,,13.036212742904606_80.22067224928986_chennai_google_maps_image,,13.036212742904606_80.22067224928986_chennai_google_satellite_image,,13.036212742904606_80.22067224928986_chennai_google_street_view_image,, -214148769,5,chennai,13.021168332187155,80.22359252100476,,13.021168332187155_80.22359252100476_chennai_google_maps_image,,13.021168332187155_80.22359252100476_chennai_google_satellite_image,,13.021168332187155_80.22359252100476_chennai_google_street_view_image,, -5338507327,5,chennai,13.105691014308052,80.20787788510337,,13.105691014308052_80.20787788510337_chennai_google_maps_image,,13.105691014308052_80.20787788510337_chennai_google_satellite_image,,13.105691014308052_80.20787788510337_chennai_google_street_view_image,, -459639891,5,chennai,13.051928310945684,80.20401308344194,,13.051928310945684_80.20401308344194_chennai_google_maps_image,,13.051928310945684_80.20401308344194_chennai_google_satellite_image,,13.051928310945684_80.20401308344194_chennai_google_street_view_image,, -334478862,5,chennai,13.021445544040086,80.22397692029948,,13.021445544040086_80.22397692029948_chennai_google_maps_image,,13.021445544040086_80.22397692029948_chennai_google_satellite_image,,13.021445544040086_80.22397692029948_chennai_google_street_view_image,, -595659823,5,chennai,13.057526592392296,80.19434382634462,,13.057526592392296_80.19434382634462_chennai_google_maps_image,,13.057526592392296_80.19434382634462_chennai_google_satellite_image,,13.057526592392296_80.19434382634462_chennai_google_street_view_image,, -6011381413,1,mexico_city,19.51403416660249,-99.22981436725821,,19.51403416660249_-99.22981436725821_mexico_city_google_maps_image,,19.51403416660249_-99.22981436725821_mexico_city_google_satellite_image,,19.51403416660249_-99.22981436725821_mexico_city_google_street_view_image,, -5625373021,1,mexico_city,19.619868299999993,-98.9955415,,19.619868299999993_-98.9955415_mexico_city_google_maps_image,,19.619868299999993_-98.9955415_mexico_city_google_satellite_image,,19.619868299999993_-98.9955415_mexico_city_google_street_view_image,, -4971055822,1,mexico_city,19.53104549074699,-99.22811173035574,,19.53104549074699_-99.22811173035574_mexico_city_google_maps_image,,19.53104549074699_-99.22811173035574_mexico_city_google_satellite_image,,19.53104549074699_-99.22811173035574_mexico_city_google_street_view_image,, -4479755389,1,mexico_city,19.33595418581395,-99.19583341922599,,19.33595418581395_-99.19583341922599_mexico_city_google_maps_image,,19.33595418581395_-99.19583341922599_mexico_city_google_satellite_image,,19.33595418581395_-99.19583341922599_mexico_city_google_street_view_image,, -1120443998,1,mexico_city,19.42236627053319,-99.20457123748297,,19.42236627053319_-99.20457123748297_mexico_city_google_maps_image,,19.42236627053319_-99.20457123748297_mexico_city_google_satellite_image,,19.42236627053319_-99.20457123748297_mexico_city_google_street_view_image,, -319651892,1,mexico_city,19.3468000206549,-99.18025881388044,,19.3468000206549_-99.18025881388044_mexico_city_google_maps_image,,19.3468000206549_-99.18025881388044_mexico_city_google_satellite_image,,19.3468000206549_-99.18025881388044_mexico_city_google_street_view_image,, -463012548,1,mexico_city,19.491929948760486,-99.22743339696706,,19.491929948760486_-99.22743339696706_mexico_city_google_maps_image,,19.491929948760486_-99.22743339696706_mexico_city_google_satellite_image,,19.491929948760486_-99.22743339696706_mexico_city_google_street_view_image,, -6687091253,1,mexico_city,19.292200317783077,-99.16106164206218,,19.292200317783077_-99.16106164206218_mexico_city_google_maps_image,,19.292200317783077_-99.16106164206218_mexico_city_google_satellite_image,,19.292200317783077_-99.16106164206218_mexico_city_google_street_view_image,, -578726124,1,mexico_city,19.549041369410695,-99.20748187329792,,19.549041369410695_-99.20748187329792_mexico_city_google_maps_image,,19.549041369410695_-99.20748187329792_mexico_city_google_satellite_image,,19.549041369410695_-99.20748187329792_mexico_city_google_street_view_image,, -5881888414,1,mexico_city,19.638540332196268,-99.21852313664104,,19.638540332196268_-99.21852313664104_mexico_city_google_maps_image,,19.638540332196268_-99.21852313664104_mexico_city_google_satellite_image,,19.638540332196268_-99.21852313664104_mexico_city_google_street_view_image,, -2126803747,2,mexico_city,19.5197308545474,-99.10825467575036,,19.5197308545474_-99.10825467575036_mexico_city_google_maps_image,,19.5197308545474_-99.10825467575036_mexico_city_google_satellite_image,,19.5197308545474_-99.10825467575036_mexico_city_google_street_view_image,, -551492401,2,mexico_city,19.387196458066352,-99.07753094589833,,19.387196458066352_-99.07753094589833_mexico_city_google_maps_image,,19.387196458066352_-99.07753094589833_mexico_city_google_satellite_image,,19.387196458066352_-99.07753094589833_mexico_city_google_street_view_image,, -5417791322,2,mexico_city,19.416405954914598,-99.16980466126468,,19.416405954914598_-99.16980466126468_mexico_city_google_maps_image,,19.416405954914598_-99.16980466126468_mexico_city_google_satellite_image,,19.416405954914598_-99.16980466126468_mexico_city_google_street_view_image,, -5618752637,2,mexico_city,19.6256717,-99.2925373,,19.6256717_-99.2925373_mexico_city_google_maps_image,,19.6256717_-99.2925373_mexico_city_google_satellite_image,,19.6256717_-99.2925373_mexico_city_google_street_view_image,, -4316280989,2,mexico_city,19.27460805534499,-99.1199937834964,,19.27460805534499_-99.1199937834964_mexico_city_google_maps_image,,19.27460805534499_-99.1199937834964_mexico_city_google_satellite_image,,19.27460805534499_-99.1199937834964_mexico_city_google_street_view_image,, -5881888416,2,mexico_city,19.638667548677986,-99.21805774644656,,19.638667548677986_-99.21805774644656_mexico_city_google_maps_image,,19.638667548677986_-99.21805774644656_mexico_city_google_satellite_image,,19.638667548677986_-99.21805774644656_mexico_city_google_street_view_image,, -5197360579,2,mexico_city,19.325007376692454,-99.22382090711858,,19.325007376692454_-99.22382090711858_mexico_city_google_maps_image,,19.325007376692454_-99.22382090711858_mexico_city_google_satellite_image,,19.325007376692454_-99.22382090711858_mexico_city_google_street_view_image,, -713545878,2,mexico_city,19.611529655247026,-99.03755890263231,,19.611529655247026_-99.03755890263231_mexico_city_google_maps_image,,19.611529655247026_-99.03755890263231_mexico_city_google_satellite_image,,19.611529655247026_-99.03755890263231_mexico_city_google_street_view_image,, -790801394,2,mexico_city,19.391685762589706,-99.27925290555264,,19.391685762589706_-99.27925290555264_mexico_city_google_maps_image,,19.391685762589706_-99.27925290555264_mexico_city_google_satellite_image,,19.391685762589706_-99.27925290555264_mexico_city_google_street_view_image,, -327297512,2,mexico_city,19.251681814829016,-99.17081540274361,,19.251681814829016_-99.17081540274361_mexico_city_google_maps_image,,19.251681814829016_-99.17081540274361_mexico_city_google_satellite_image,,19.251681814829016_-99.17081540274361_mexico_city_google_street_view_image,, -3380713564,3,mexico_city,19.252103604004134,-99.1724056566158,,19.252103604004134_-99.1724056566158_mexico_city_google_maps_image,,19.252103604004134_-99.1724056566158_mexico_city_google_satellite_image,,19.252103604004134_-99.1724056566158_mexico_city_google_street_view_image,, -531758826,3,mexico_city,19.602246993030853,-99.00921628410761,,19.602246993030853_-99.00921628410761_mexico_city_google_maps_image,,19.602246993030853_-99.00921628410761_mexico_city_google_satellite_image,,19.602246993030853_-99.00921628410761_mexico_city_google_street_view_image,, -818881354,3,mexico_city,19.409249417820284,-99.07473349082271,,19.409249417820284_-99.07473349082271_mexico_city_google_maps_image,,19.409249417820284_-99.07473349082271_mexico_city_google_satellite_image,,19.409249417820284_-99.07473349082271_mexico_city_google_street_view_image,, -4661403216,3,mexico_city,19.3061212,-99.1657359,,19.3061212_-99.1657359_mexico_city_google_maps_image,,19.3061212_-99.1657359_mexico_city_google_satellite_image,,19.3061212_-99.1657359_mexico_city_google_street_view_image,, -5247968921,3,mexico_city,19.430435114542913,-99.16947402488798,,19.430435114542913_-99.16947402488798_mexico_city_google_maps_image,,19.430435114542913_-99.16947402488798_mexico_city_google_satellite_image,,19.430435114542913_-99.16947402488798_mexico_city_google_street_view_image,, -316738852,3,mexico_city,19.415954035141777,-99.10095674099989,,19.415954035141777_-99.10095674099989_mexico_city_google_maps_image,,19.415954035141777_-99.10095674099989_mexico_city_google_satellite_image,,19.415954035141777_-99.10095674099989_mexico_city_google_street_view_image,, -5533987020,3,mexico_city,19.449378085540932,-99.21368058993912,,19.449378085540932_-99.21368058993912_mexico_city_google_maps_image,,19.449378085540932_-99.21368058993912_mexico_city_google_satellite_image,,19.449378085540932_-99.21368058993912_mexico_city_google_street_view_image,, -3802504185,3,mexico_city,19.418567696058847,-99.11709182250064,,19.418567696058847_-99.11709182250064_mexico_city_google_maps_image,,19.418567696058847_-99.11709182250064_mexico_city_google_satellite_image,,19.418567696058847_-99.11709182250064_mexico_city_google_street_view_image,, -830603055,3,mexico_city,19.356222350373088,-99.15525872859979,,19.356222350373088_-99.15525872859979_mexico_city_google_maps_image,,19.356222350373088_-99.15525872859979_mexico_city_google_satellite_image,,19.356222350373088_-99.15525872859979_mexico_city_google_street_view_image,, -3263840121,3,mexico_city,19.60721548569304,-98.97327956895045,,19.60721548569304_-98.97327956895045_mexico_city_google_maps_image,,19.60721548569304_-98.97327956895045_mexico_city_google_satellite_image,,19.60721548569304_-98.97327956895045_mexico_city_google_street_view_image,, -3802845836,4,mexico_city,19.370007382037823,-99.17319076827603,,19.370007382037823_-99.17319076827603_mexico_city_google_maps_image,,19.370007382037823_-99.17319076827603_mexico_city_google_satellite_image,,19.370007382037823_-99.17319076827603_mexico_city_google_street_view_image,, -5108093422,4,mexico_city,19.5098055351056,-99.08629600828012,,19.5098055351056_-99.08629600828012_mexico_city_google_maps_image,,19.5098055351056_-99.08629600828012_mexico_city_google_satellite_image,,19.5098055351056_-99.08629600828012_mexico_city_google_street_view_image,, -4066846457,4,mexico_city,19.376220421324923,-99.1539222521892,,19.376220421324923_-99.1539222521892_mexico_city_google_maps_image,,19.376220421324923_-99.1539222521892_mexico_city_google_satellite_image,,19.376220421324923_-99.1539222521892_mexico_city_google_street_view_image,, -404795916,4,mexico_city,19.40162848187196,-99.15880716780337,,19.40162848187196_-99.15880716780337_mexico_city_google_maps_image,,19.40162848187196_-99.15880716780337_mexico_city_google_satellite_image,,19.40162848187196_-99.15880716780337_mexico_city_google_street_view_image,, -355215483,4,mexico_city,19.456114655705782,-99.10435781053914,,19.456114655705782_-99.10435781053914_mexico_city_google_maps_image,,19.456114655705782_-99.10435781053914_mexico_city_google_satellite_image,,19.456114655705782_-99.10435781053914_mexico_city_google_street_view_image,, -717761768,4,mexico_city,19.59493623796497,-98.99569593615188,,19.59493623796497_-98.99569593615188_mexico_city_google_maps_image,,19.59493623796497_-98.99569593615188_mexico_city_google_satellite_image,,19.59493623796497_-98.99569593615188_mexico_city_google_street_view_image,, -620181905,4,mexico_city,19.419251705059608,-99.0875584444067,,19.419251705059608_-99.0875584444067_mexico_city_google_maps_image,,19.419251705059608_-99.0875584444067_mexico_city_google_satellite_image,,19.419251705059608_-99.0875584444067_mexico_city_google_street_view_image,, -83589291,4,mexico_city,19.534283891153496,-99.02719708539541,,19.534283891153496_-99.02719708539541_mexico_city_google_maps_image,,19.534283891153496_-99.02719708539541_mexico_city_google_satellite_image,,19.534283891153496_-99.02719708539541_mexico_city_google_street_view_image,, -359241465,4,mexico_city,19.4594477204163,-99.091861403534,,19.4594477204163_-99.091861403534_mexico_city_google_maps_image,,19.4594477204163_-99.091861403534_mexico_city_google_satellite_image,,19.4594477204163_-99.091861403534_mexico_city_google_street_view_image,, -601784893,4,mexico_city,19.402130562993637,-99.12188565976768,,19.402130562993637_-99.12188565976768_mexico_city_google_maps_image,,19.402130562993637_-99.12188565976768_mexico_city_google_satellite_image,,19.402130562993637_-99.12188565976768_mexico_city_google_street_view_image,, -5694106223,5,mexico_city,19.44723060277377,-99.24557241439541,,19.44723060277377_-99.24557241439541_mexico_city_google_maps_image,,19.44723060277377_-99.24557241439541_mexico_city_google_satellite_image,,19.44723060277377_-99.24557241439541_mexico_city_google_street_view_image,, -6644579936,5,mexico_city,19.442327639174398,-99.15820955785016,,19.442327639174398_-99.15820955785016_mexico_city_google_maps_image,,19.442327639174398_-99.15820955785016_mexico_city_google_satellite_image,,19.442327639174398_-99.15820955785016_mexico_city_google_street_view_image,, -263257550,5,mexico_city,19.41636850413102,-99.0218279996463,,19.41636850413102_-99.0218279996463_mexico_city_google_maps_image,,19.41636850413102_-99.0218279996463_mexico_city_google_satellite_image,,19.41636850413102_-99.0218279996463_mexico_city_google_street_view_image,, -1499489411,5,mexico_city,19.509192194994526,-99.10030494794222,,19.509192194994526_-99.10030494794222_mexico_city_google_maps_image,,19.509192194994526_-99.10030494794222_mexico_city_google_satellite_image,,19.509192194994526_-99.10030494794222_mexico_city_google_street_view_image,, -4536274297,5,mexico_city,19.628960580316544,-99.1392991095664,,19.628960580316544_-99.1392991095664_mexico_city_google_maps_image,,19.628960580316544_-99.1392991095664_mexico_city_google_satellite_image,,19.628960580316544_-99.1392991095664_mexico_city_google_street_view_image,, -293809368,5,mexico_city,19.326671499999996,-98.8819042,,19.326671499999996_-98.8819042_mexico_city_google_maps_image,,19.326671499999996_-98.8819042_mexico_city_google_satellite_image,,19.326671499999996_-98.8819042_mexico_city_google_street_view_image,, -217662063,5,mexico_city,19.44189326824857,-99.13885337788817,,19.44189326824857_-99.13885337788817_mexico_city_google_maps_image,,19.44189326824857_-99.13885337788817_mexico_city_google_satellite_image,,19.44189326824857_-99.13885337788817_mexico_city_google_street_view_image,, -4039082262,5,mexico_city,19.360839473243438,-99.14997110009426,,19.360839473243438_-99.14997110009426_mexico_city_google_maps_image,,19.360839473243438_-99.14997110009426_mexico_city_google_satellite_image,,19.360839473243438_-99.14997110009426_mexico_city_google_street_view_image,, -766584728,5,mexico_city,19.662553823635136,-99.0707784206159,,19.662553823635136_-99.0707784206159_mexico_city_google_maps_image,,19.662553823635136_-99.0707784206159_mexico_city_google_satellite_image,,19.662553823635136_-99.0707784206159_mexico_city_google_street_view_image,, -1677171707,5,mexico_city,19.4642461563854,-99.12660040878647,,19.4642461563854_-99.12660040878647_mexico_city_google_maps_image,,19.4642461563854_-99.12660040878647_mexico_city_google_satellite_image,,19.4642461563854_-99.12660040878647_mexico_city_google_street_view_image,, -2798786972,1,cologne,50.898249122575564,7.02945390050806,,50.898249122575564_7.02945390050806_cologne_google_maps_image,,50.898249122575564_7.02945390050806_cologne_google_satellite_image,,50.898249122575564_7.02945390050806_cologne_google_street_view_image,, -155144241,1,cologne,50.89383823888894,7.047768417465601,,50.89383823888894_7.047768417465601_cologne_google_maps_image,,50.89383823888894_7.047768417465601_cologne_google_satellite_image,,50.89383823888894_7.047768417465601_cologne_google_street_view_image,, -1808374631,1,cologne,50.884686852412024,7.057938865588942,,50.884686852412024_7.057938865588942_cologne_google_maps_image,,50.884686852412024_7.057938865588942_cologne_google_satellite_image,,50.884686852412024_7.057938865588942_cologne_google_street_view_image,, -1038105378,1,cologne,50.92877655226211,7.0006978124369095,,50.92877655226211_7.0006978124369095_cologne_google_maps_image,,50.92877655226211_7.0006978124369095_cologne_google_satellite_image,,50.92877655226211_7.0006978124369095_cologne_google_street_view_image,, -218586953,1,cologne,50.9468089,6.847064400000002,,50.9468089_6.847064400000002_cologne_google_maps_image,,50.9468089_6.847064400000002_cologne_google_satellite_image,,50.9468089_6.847064400000002_cologne_google_street_view_image,, -366725737,1,cologne,50.98980726446304,6.961434933768049,,50.98980726446304_6.961434933768049_cologne_google_maps_image,,50.98980726446304_6.961434933768049_cologne_google_satellite_image,,50.98980726446304_6.961434933768049_cologne_google_street_view_image,, -32343354,1,cologne,51.00161465278052,6.9876208930376285,,51.00161465278052_6.9876208930376285_cologne_google_maps_image,,51.00161465278052_6.9876208930376285_cologne_google_satellite_image,,51.00161465278052_6.9876208930376285_cologne_google_street_view_image,, -1434135027,1,cologne,50.84629079999999,7.096374899999999,,50.84629079999999_7.096374899999999_cologne_google_maps_image,,50.84629079999999_7.096374899999999_cologne_google_satellite_image,,50.84629079999999_7.096374899999999_cologne_google_street_view_image,, -904988831,1,cologne,50.88220434681379,7.0118102418560655,,50.88220434681379_7.0118102418560655_cologne_google_maps_image,,50.88220434681379_7.0118102418560655_cologne_google_satellite_image,,50.88220434681379_7.0118102418560655_cologne_google_street_view_image,, -366662669,1,cologne,50.97711095571608,6.960381574351235,,50.97711095571608_6.960381574351235_cologne_google_maps_image,,50.97711095571608_6.960381574351235_cologne_google_satellite_image,,50.97711095571608_6.960381574351235_cologne_google_street_view_image,, -1924165807,2,cologne,50.97115339999999,6.959627999999999,,50.97115339999999_6.959627999999999_cologne_google_maps_image,,50.97115339999999_6.959627999999999_cologne_google_satellite_image,,50.97115339999999_6.959627999999999_cologne_google_street_view_image,, -164851648,2,cologne,51.003068912791974,6.873682680963931,,51.003068912791974_6.873682680963931_cologne_google_maps_image,,51.003068912791974_6.873682680963931_cologne_google_satellite_image,,51.003068912791974_6.873682680963931_cologne_google_street_view_image,, -4546959772,2,cologne,50.898366688002845,6.965904234562772,,50.898366688002845_6.965904234562772_cologne_google_maps_image,,50.898366688002845_6.965904234562772_cologne_google_satellite_image,,50.898366688002845_6.965904234562772_cologne_google_street_view_image,, -258092650,2,cologne,50.97494439238988,6.947056388681244,,50.97494439238988_6.947056388681244_cologne_google_maps_image,,50.97494439238988_6.947056388681244_cologne_google_satellite_image,,50.97494439238988_6.947056388681244_cologne_google_street_view_image,, -2141323066,2,cologne,50.93095759913993,6.852956151064677,,50.93095759913993_6.852956151064677_cologne_google_maps_image,,50.93095759913993_6.852956151064677_cologne_google_satellite_image,,50.93095759913993_6.852956151064677_cologne_google_street_view_image,, -155440122,2,cologne,50.856045422022305,7.087079964625161,,50.856045422022305_7.087079964625161_cologne_google_maps_image,,50.856045422022305_7.087079964625161_cologne_google_satellite_image,,50.856045422022305_7.087079964625161_cologne_google_street_view_image,, -1741318998,2,cologne,50.96567334203133,6.836430482061221,,50.96567334203133_6.836430482061221_cologne_google_maps_image,,50.96567334203133_6.836430482061221_cologne_google_satellite_image,,50.96567334203133_6.836430482061221_cologne_google_street_view_image,, -986290367,2,cologne,50.92881046571001,6.911392406204731,,50.92881046571001_6.911392406204731_cologne_google_maps_image,,50.92881046571001_6.911392406204731_cologne_google_satellite_image,,50.92881046571001_6.911392406204731_cologne_google_street_view_image,, -847541789,2,cologne,50.942781385216826,7.049905948656818,,50.942781385216826_7.049905948656818_cologne_google_maps_image,,50.942781385216826_7.049905948656818_cologne_google_satellite_image,,50.942781385216826_7.049905948656818_cologne_google_street_view_image,, -5359016021,2,cologne,50.99777974997925,6.9136134163229634,,50.99777974997925_6.9136134163229634_cologne_google_maps_image,,50.99777974997925_6.9136134163229634_cologne_google_satellite_image,,50.99777974997925_6.9136134163229634_cologne_google_street_view_image,, -448860271,3,cologne,50.966488189174655,6.834006396296986,,50.966488189174655_6.834006396296986_cologne_google_maps_image,,50.966488189174655_6.834006396296986_cologne_google_satellite_image,,50.966488189174655_6.834006396296986_cologne_google_street_view_image,, -82097104,3,cologne,50.96445468475809,6.975805878158244,,50.96445468475809_6.975805878158244_cologne_google_maps_image,,50.96445468475809_6.975805878158244_cologne_google_satellite_image,,50.96445468475809_6.975805878158244_cologne_google_street_view_image,, -429523110,3,cologne,50.95510500567307,6.916412252269436,,50.95510500567307_6.916412252269436_cologne_google_maps_image,,50.95510500567307_6.916412252269436_cologne_google_satellite_image,,50.95510500567307_6.916412252269436_cologne_google_street_view_image,, -5976221914,3,cologne,50.97982,6.867865600000001,,50.97982_6.867865600000001_cologne_google_maps_image,,50.97982_6.867865600000001_cologne_google_satellite_image,,50.97982_6.867865600000001_cologne_google_street_view_image,, -603316682,3,cologne,50.959567688983,7.008290212426442,,50.959567688983_7.008290212426442_cologne_google_maps_image,,50.959567688983_7.008290212426442_cologne_google_satellite_image,,50.959567688983_7.008290212426442_cologne_google_street_view_image,, -3992509400,3,cologne,50.891144215232906,6.996977905573185,,50.891144215232906_6.996977905573185_cologne_google_maps_image,,50.891144215232906_6.996977905573185_cologne_google_satellite_image,,50.891144215232906_6.996977905573185_cologne_google_street_view_image,, -946072102,3,cologne,50.93810566355929,7.005189926068315,,50.93810566355929_7.005189926068315_cologne_google_maps_image,,50.93810566355929_7.005189926068315_cologne_google_satellite_image,,50.93810566355929_7.005189926068315_cologne_google_street_view_image,, -1841208275,3,cologne,50.9627456059562,7.003331694073337,,50.9627456059562_7.003331694073337_cologne_google_maps_image,,50.9627456059562_7.003331694073337_cologne_google_satellite_image,,50.9627456059562_7.003331694073337_cologne_google_street_view_image,, -444401494,3,cologne,50.95698588661255,6.918518966901978,,50.95698588661255_6.918518966901978_cologne_google_maps_image,,50.95698588661255_6.918518966901978_cologne_google_satellite_image,,50.95698588661255_6.918518966901978_cologne_google_street_view_image,, -6202847455,3,cologne,50.93808553109019,6.8435032191359735,,50.93808553109019_6.8435032191359735_cologne_google_maps_image,,50.93808553109019_6.8435032191359735_cologne_google_satellite_image,,50.93808553109019_6.8435032191359735_cologne_google_street_view_image,, -905234692,4,cologne,50.933333290661416,7.019910313985369,,50.933333290661416_7.019910313985369_cologne_google_maps_image,,50.933333290661416_7.019910313985369_cologne_google_satellite_image,,50.933333290661416_7.019910313985369_cologne_google_street_view_image,, -107360172,4,cologne,50.89569833808621,7.072964683684729,,50.89569833808621_7.072964683684729_cologne_google_maps_image,,50.89569833808621_7.072964683684729_cologne_google_satellite_image,,50.89569833808621_7.072964683684729_cologne_google_street_view_image,, -6388749727,4,cologne,50.98133409828571,7.032800023816504,,50.98133409828571_7.032800023816504_cologne_google_maps_image,,50.98133409828571_7.032800023816504_cologne_google_satellite_image,,50.98133409828571_7.032800023816504_cologne_google_street_view_image,, -4126586308,4,cologne,50.95142363470696,6.957058979365362,,50.95142363470696_6.957058979365362_cologne_google_maps_image,,50.95142363470696_6.957058979365362_cologne_google_satellite_image,,50.95142363470696_6.957058979365362_cologne_google_street_view_image,, -353945432,4,cologne,50.92160299209089,6.928993909727928,,50.92160299209089_6.928993909727928_cologne_google_maps_image,,50.92160299209089_6.928993909727928_cologne_google_satellite_image,,50.92160299209089_6.928993909727928_cologne_google_street_view_image,, -87761318,4,cologne,50.91586013318439,6.93406352193762,,50.91586013318439_6.93406352193762_cologne_google_maps_image,,50.91586013318439_6.93406352193762_cologne_google_satellite_image,,50.91586013318439_6.93406352193762_cologne_google_street_view_image,, -641220538,4,cologne,50.92636315107418,6.958083606809124,,50.92636315107418_6.958083606809124_cologne_google_maps_image,,50.92636315107418_6.958083606809124_cologne_google_satellite_image,,50.92636315107418_6.958083606809124_cologne_google_street_view_image,, -1895932177,4,cologne,50.9500192,6.9171075,,50.9500192_6.9171075_cologne_google_maps_image,,50.9500192_6.9171075_cologne_google_satellite_image,,50.9500192_6.9171075_cologne_google_street_view_image,, -5693413723,4,cologne,50.94912418104523,6.953010766568366,,50.94912418104523_6.953010766568366_cologne_google_maps_image,,50.94912418104523_6.953010766568366_cologne_google_satellite_image,,50.94912418104523_6.953010766568366_cologne_google_street_view_image,, -1380532321,4,cologne,50.94871275589644,6.98759090771506,,50.94871275589644_6.98759090771506_cologne_google_maps_image,,50.94871275589644_6.98759090771506_cologne_google_satellite_image,,50.94871275589644_6.98759090771506_cologne_google_street_view_image,, -729932436,5,cologne,50.94820373105129,6.920118858751327,,50.94820373105129_6.920118858751327_cologne_google_maps_image,,50.94820373105129_6.920118858751327_cologne_google_satellite_image,,50.94820373105129_6.920118858751327_cologne_google_street_view_image,, -1166597378,5,cologne,50.94630554096603,6.925121138019788,,50.94630554096603_6.925121138019788_cologne_google_maps_image,,50.94630554096603_6.925121138019788_cologne_google_satellite_image,,50.94630554096603_6.925121138019788_cologne_google_street_view_image,, -4692617938,5,cologne,50.94761098081893,6.956309612578662,,50.94761098081893_6.956309612578662_cologne_google_maps_image,,50.94761098081893_6.956309612578662_cologne_google_satellite_image,,50.94761098081893_6.956309612578662_cologne_google_street_view_image,, -325189646,5,cologne,50.971373092309754,7.010040627386005,,50.971373092309754_7.010040627386005_cologne_google_maps_image,,50.971373092309754_7.010040627386005_cologne_google_satellite_image,,50.971373092309754_7.010040627386005_cologne_google_street_view_image,, -583434186,5,cologne,50.97094759627577,7.00945865057715,,50.97094759627577_7.00945865057715_cologne_google_maps_image,,50.97094759627577_7.00945865057715_cologne_google_satellite_image,,50.97094759627577_7.00945865057715_cologne_google_street_view_image,, -252608602,5,cologne,50.9201661,6.9361017,,50.9201661_6.9361017_cologne_google_maps_image,,50.9201661_6.9361017_cologne_google_satellite_image,,50.9201661_6.9361017_cologne_google_street_view_image,, -582824099,5,cologne,50.911660899999994,6.963516099999999,,50.911660899999994_6.963516099999999_cologne_google_maps_image,,50.911660899999994_6.963516099999999_cologne_google_satellite_image,,50.911660899999994_6.963516099999999_cologne_google_street_view_image,, -3470965473,5,cologne,50.92280545226893,6.9591087470916175,,50.92280545226893_6.9591087470916175_cologne_google_maps_image,,50.92280545226893_6.9591087470916175_cologne_google_satellite_image,,50.92280545226893_6.9591087470916175_cologne_google_street_view_image,, -4679581462,5,cologne,50.94820774752281,6.954592264963115,,50.94820774752281_6.954592264963115_cologne_google_maps_image,,50.94820774752281_6.954592264963115_cologne_google_satellite_image,,50.94820774752281_6.954592264963115_cologne_google_street_view_image,, -6564494812,5,cologne,50.92214239304427,6.921829654333054,,50.92214239304427_6.921829654333054_cologne_google_maps_image,,50.92214239304427_6.921829654333054_cologne_google_satellite_image,,50.92214239304427_6.921829654333054_cologne_google_street_view_image,, -6327109986,1,ghent,51.051366299999984,3.7617922999999993,,51.051366299999984_3.7617922999999993_ghent_google_maps_image,,51.051366299999984_3.7617922999999993_ghent_google_satellite_image,,51.051366299999984_3.7617922999999993_ghent_google_street_view_image,, -6174916886,1,ghent,51.075211206978054,3.7524107978352728,,51.075211206978054_3.7524107978352728_ghent_google_maps_image,,51.075211206978054_3.7524107978352728_ghent_google_satellite_image,,51.075211206978054_3.7524107978352728_ghent_google_street_view_image,, -2498828925,1,ghent,51.016789334638986,3.734894792387552,,51.016789334638986_3.734894792387552_ghent_google_maps_image,,51.016789334638986_3.734894792387552_ghent_google_satellite_image,,51.016789334638986_3.734894792387552_ghent_google_street_view_image,, -239251697,1,ghent,51.068121680673144,3.6831862529014208,,51.068121680673144_3.6831862529014208_ghent_google_maps_image,,51.068121680673144_3.6831862529014208_ghent_google_satellite_image,,51.068121680673144_3.6831862529014208_ghent_google_street_view_image,, -6299254488,1,ghent,51.079405763538624,3.7631868014895034,,51.079405763538624_3.7631868014895034_ghent_google_maps_image,,51.079405763538624_3.7631868014895034_ghent_google_satellite_image,,51.079405763538624_3.7631868014895034_ghent_google_street_view_image,, -5550198948,1,ghent,51.00397103420439,3.717453802688445,,51.00397103420439_3.717453802688445_ghent_google_maps_image,,51.00397103420439_3.717453802688445_ghent_google_satellite_image,,51.00397103420439_3.717453802688445_ghent_google_street_view_image,, -600508259,1,ghent,51.088974045590625,3.7078271931425686,,51.088974045590625_3.7078271931425686_ghent_google_maps_image,,51.088974045590625_3.7078271931425686_ghent_google_satellite_image,,51.088974045590625_3.7078271931425686_ghent_google_street_view_image,, -483071802,1,ghent,51.076543169062425,3.683485828827118,,51.076543169062425_3.683485828827118_ghent_google_maps_image,,51.076543169062425_3.683485828827118_ghent_google_satellite_image,,51.076543169062425_3.683485828827118_ghent_google_street_view_image,, -158715226,1,ghent,51.090626619640226,3.7590429378029215,,51.090626619640226_3.7590429378029215_ghent_google_maps_image,,51.090626619640226_3.7590429378029215_ghent_google_satellite_image,,51.090626619640226_3.7590429378029215_ghent_google_street_view_image,, -206897095,1,ghent,51.07416805405659,3.6797243730680615,,51.07416805405659_3.6797243730680615_ghent_google_maps_image,,51.07416805405659_3.6797243730680615_ghent_google_satellite_image,,51.07416805405659_3.6797243730680615_ghent_google_street_view_image,, -1239962113,2,ghent,51.051392432375465,3.7019979676639667,,51.051392432375465_3.7019979676639667_ghent_google_maps_image,,51.051392432375465_3.7019979676639667_ghent_google_satellite_image,,51.051392432375465_3.7019979676639667_ghent_google_street_view_image,, -2485998498,2,ghent,51.071781698668055,3.707033930082326,,51.071781698668055_3.707033930082326_ghent_google_maps_image,,51.071781698668055_3.707033930082326_ghent_google_satellite_image,,51.071781698668055_3.707033930082326_ghent_google_street_view_image,, -4831549869,2,ghent,51.070763893535094,3.709766110340651,,51.070763893535094_3.709766110340651_ghent_google_maps_image,,51.070763893535094_3.709766110340651_ghent_google_satellite_image,,51.070763893535094_3.709766110340651_ghent_google_street_view_image,, -6900570088,2,ghent,51.05781831381282,3.7067567553707046,,51.05781831381282_3.7067567553707046_ghent_google_maps_image,,51.05781831381282_3.7067567553707046_ghent_google_satellite_image,,51.05781831381282_3.7067567553707046_ghent_google_street_view_image,, -104385257,2,ghent,51.04755719181594,3.708450450262417,,51.04755719181594_3.708450450262417_ghent_google_maps_image,,51.04755719181594_3.708450450262417_ghent_google_satellite_image,,51.04755719181594_3.708450450262417_ghent_google_street_view_image,, -451769815,2,ghent,51.05500310794491,3.695426113563651,,51.05500310794491_3.695426113563651_ghent_google_maps_image,,51.05500310794491_3.695426113563651_ghent_google_satellite_image,,51.05500310794491_3.695426113563651_ghent_google_street_view_image,, -6466580996,2,ghent,51.099495228483676,3.7641445150839568,,51.099495228483676_3.7641445150839568_ghent_google_maps_image,,51.099495228483676_3.7641445150839568_ghent_google_satellite_image,,51.099495228483676_3.7641445150839568_ghent_google_street_view_image,, -6983077089,2,ghent,51.06404998382594,3.709709379658549,,51.06404998382594_3.709709379658549_ghent_google_maps_image,,51.06404998382594_3.709709379658549_ghent_google_satellite_image,,51.06404998382594_3.709709379658549_ghent_google_street_view_image,, -417796798,2,ghent,51.0733946810587,3.687136710316848,,51.0733946810587_3.687136710316848_ghent_google_maps_image,,51.0733946810587_3.687136710316848_ghent_google_satellite_image,,51.0733946810587_3.687136710316848_ghent_google_street_view_image,, -7448200576,2,ghent,51.05320379369902,3.7550846837166882,,51.05320379369902_3.7550846837166882_ghent_google_maps_image,,51.05320379369902_3.7550846837166882_ghent_google_satellite_image,,51.05320379369902_3.7550846837166882_ghent_google_street_view_image,, -6434028388,3,ghent,51.061225720427004,3.7484227168373003,,51.061225720427004_3.7484227168373003_ghent_google_maps_image,,51.061225720427004_3.7484227168373003_ghent_google_satellite_image,,51.061225720427004_3.7484227168373003_ghent_google_street_view_image,, -180127971,3,ghent,51.02734959571888,3.7302628193268093,,51.02734959571888_3.7302628193268093_ghent_google_maps_image,,51.02734959571888_3.7302628193268093_ghent_google_satellite_image,,51.02734959571888_3.7302628193268093_ghent_google_street_view_image,, -1598830944,3,ghent,51.036336223806636,3.7098356888293593,,51.036336223806636_3.7098356888293593_ghent_google_maps_image,,51.036336223806636_3.7098356888293593_ghent_google_satellite_image,,51.036336223806636_3.7098356888293593_ghent_google_street_view_image,, -3876171904,3,ghent,51.05221322454478,3.723636928088199,,51.05221322454478_3.723636928088199_ghent_google_maps_image,,51.05221322454478_3.723636928088199_ghent_google_satellite_image,,51.05221322454478_3.723636928088199_ghent_google_street_view_image,, -115446302,3,ghent,51.05390319326428,3.7424353486665005,,51.05390319326428_3.7424353486665005_ghent_google_maps_image,,51.05390319326428_3.7424353486665005_ghent_google_satellite_image,,51.05390319326428_3.7424353486665005_ghent_google_street_view_image,, -176368079,3,ghent,51.04033045098958,3.717157728129874,,51.04033045098958_3.717157728129874_ghent_google_maps_image,,51.04033045098958_3.717157728129874_ghent_google_satellite_image,,51.04033045098958_3.717157728129874_ghent_google_street_view_image,, -1301268094,3,ghent,51.054268823440594,3.743329030040363,,51.054268823440594_3.743329030040363_ghent_google_maps_image,,51.054268823440594_3.743329030040363_ghent_google_satellite_image,,51.054268823440594_3.743329030040363_ghent_google_street_view_image,, -1630724940,3,ghent,51.0269365868416,3.7097563552966215,,51.0269365868416_3.7097563552966215_ghent_google_maps_image,,51.0269365868416_3.7097563552966215_ghent_google_satellite_image,,51.0269365868416_3.7097563552966215_ghent_google_street_view_image,, -6440678288,3,ghent,51.064641161095,3.726358225148234,,51.064641161095_3.726358225148234_ghent_google_maps_image,,51.064641161095_3.726358225148234_ghent_google_satellite_image,,51.064641161095_3.726358225148234_ghent_google_street_view_image,, -6900570185,3,ghent,51.056863606969,3.709392409658695,,51.056863606969_3.709392409658695_ghent_google_maps_image,,51.056863606969_3.709392409658695_ghent_google_satellite_image,,51.056863606969_3.709392409658695_ghent_google_street_view_image,, -5859316519,4,ghent,51.06247846938567,3.710039664951906,,51.06247846938567_3.710039664951906_ghent_google_maps_image,,51.06247846938567_3.710039664951906_ghent_google_satellite_image,,51.06247846938567_3.710039664951906_ghent_google_street_view_image,, -4712254515,4,ghent,51.041253767757574,3.718294370126334,,51.041253767757574_3.718294370126334_ghent_google_maps_image,,51.041253767757574_3.718294370126334_ghent_google_satellite_image,,51.041253767757574_3.718294370126334_ghent_google_street_view_image,, -6533980221,4,ghent,51.0606658742048,3.7017336663687863,,51.0606658742048_3.7017336663687863_ghent_google_maps_image,,51.0606658742048_3.7017336663687863_ghent_google_satellite_image,,51.0606658742048_3.7017336663687863_ghent_google_street_view_image,, -555274388,4,ghent,51.08416463912916,3.7173228608250537,,51.08416463912916_3.7173228608250537_ghent_google_maps_image,,51.08416463912916_3.7173228608250537_ghent_google_satellite_image,,51.08416463912916_3.7173228608250537_ghent_google_street_view_image,, -6942598388,4,ghent,51.0566620727313,3.7416358652971433,,51.0566620727313_3.7416358652971433_ghent_google_maps_image,,51.0566620727313_3.7416358652971433_ghent_google_satellite_image,,51.0566620727313_3.7416358652971433_ghent_google_street_view_image,, -6983076913,4,ghent,51.062440260557665,3.710051494679923,,51.062440260557665_3.710051494679923_ghent_google_maps_image,,51.062440260557665_3.710051494679923_ghent_google_satellite_image,,51.062440260557665_3.710051494679923_ghent_google_street_view_image,, -451557497,4,ghent,51.056832699999994,3.6967075000000005,,51.056832699999994_3.6967075000000005_ghent_google_maps_image,,51.056832699999994_3.6967075000000005_ghent_google_satellite_image,,51.056832699999994_3.6967075000000005_ghent_google_street_view_image,, -1802839228,4,ghent,51.036983166082784,3.7132114857964074,,51.036983166082784_3.7132114857964074_ghent_google_maps_image,,51.036983166082784_3.7132114857964074_ghent_google_satellite_image,,51.036983166082784_3.7132114857964074_ghent_google_street_view_image,, -7198244688,4,ghent,51.06019876528515,3.7023542588798546,,51.06019876528515_3.7023542588798546_ghent_google_maps_image,,51.06019876528515_3.7023542588798546_ghent_google_satellite_image,,51.06019876528515_3.7023542588798546_ghent_google_street_view_image,, -6255559989,4,ghent,51.056797555724096,3.7335630238526716,,51.056797555724096_3.7335630238526716_ghent_google_maps_image,,51.056797555724096_3.7335630238526716_ghent_google_satellite_image,,51.056797555724096_3.7335630238526716_ghent_google_street_view_image,, -1426081014,5,ghent,51.03702305449802,3.7424962842294653,,51.03702305449802_3.7424962842294653_ghent_google_maps_image,,51.03702305449802_3.7424962842294653_ghent_google_satellite_image,,51.03702305449802_3.7424962842294653_ghent_google_street_view_image,, -2225073604,5,ghent,51.0494989056728,3.7444801836856962,,51.0494989056728_3.7444801836856962_ghent_google_maps_image,,51.0494989056728_3.7444801836856962_ghent_google_satellite_image,,51.0494989056728_3.7444801836856962_ghent_google_street_view_image,, -3517496239,5,ghent,51.05713416039469,3.7306964287875823,,51.05713416039469_3.7306964287875823_ghent_google_maps_image,,51.05713416039469_3.7306964287875823_ghent_google_satellite_image,,51.05713416039469_3.7306964287875823_ghent_google_street_view_image,, -1795819240,5,ghent,51.050336127091,3.723182341107955,,51.050336127091_3.723182341107955_ghent_google_maps_image,,51.050336127091_3.723182341107955_ghent_google_satellite_image,,51.050336127091_3.723182341107955_ghent_google_street_view_image,, -7079394607,5,ghent,51.05088795205988,3.727861466773262,,51.05088795205988_3.727861466773262_ghent_google_maps_image,,51.05088795205988_3.727861466773262_ghent_google_satellite_image,,51.05088795205988_3.727861466773262_ghent_google_street_view_image,, -6138790502,5,ghent,51.040690079723035,3.7405428318486713,,51.040690079723035_3.7405428318486713_ghent_google_maps_image,,51.040690079723035_3.7405428318486713_ghent_google_satellite_image,,51.040690079723035_3.7405428318486713_ghent_google_street_view_image,, -1687422666,5,ghent,51.05092984466987,3.704243446912032,,51.05092984466987_3.704243446912032_ghent_google_maps_image,,51.05092984466987_3.704243446912032_ghent_google_satellite_image,,51.05092984466987_3.704243446912032_ghent_google_street_view_image,, -1598830941,5,ghent,51.038536403900096,3.709045786494365,,51.038536403900096_3.709045786494365_ghent_google_maps_image,,51.038536403900096_3.709045786494365_ghent_google_satellite_image,,51.038536403900096_3.709045786494365_ghent_google_street_view_image,, -5918606636,5,ghent,51.04869218904633,3.72132597253425,,51.04869218904633_3.72132597253425_ghent_google_maps_image,,51.04869218904633_3.72132597253425_ghent_google_satellite_image,,51.04869218904633_3.72132597253425_ghent_google_street_view_image,, -1295215428,5,ghent,51.059687099547354,3.727870181086064,,51.059687099547354_3.727870181086064_ghent_google_maps_image,,51.059687099547354_3.727870181086064_ghent_google_satellite_image,,51.059687099547354_3.727870181086064_ghent_google_street_view_image,, -6173128482,1,graz,47.07749298981534,15.434732982116689,,47.07749298981534_15.434732982116689_graz_google_maps_image,,47.07749298981534_15.434732982116689_graz_google_satellite_image,,47.07749298981534_15.434732982116689_graz_google_street_view_image,, -825158290,1,graz,47.08169058347534,15.468114065116948,,47.08169058347534_15.468114065116948_graz_google_maps_image,,47.08169058347534_15.468114065116948_graz_google_satellite_image,,47.08169058347534_15.468114065116948_graz_google_street_view_image,, -5713866806,1,graz,47.032929039736096,15.4316960350709,,47.032929039736096_15.4316960350709_graz_google_maps_image,,47.032929039736096_15.4316960350709_graz_google_satellite_image,,47.032929039736096_15.4316960350709_graz_google_street_view_image,, -21306980,1,graz,47.05056339999999,15.4785402,,47.05056339999999_15.4785402_graz_google_maps_image,,47.05056339999999_15.4785402_graz_google_satellite_image,,47.05056339999999_15.4785402_graz_google_street_view_image,, -107877896,1,graz,47.100835930965,15.426204360727988,,47.100835930965_15.426204360727988_graz_google_maps_image,,47.100835930965_15.426204360727988_graz_google_satellite_image,,47.100835930965_15.426204360727988_graz_google_street_view_image,, -372409546,1,graz,47.11376087680128,15.421656431286198,,47.11376087680128_15.421656431286198_graz_google_maps_image,,47.11376087680128_15.421656431286198_graz_google_satellite_image,,47.11376087680128_15.421656431286198_graz_google_street_view_image,, -33054365,1,graz,47.0787376,15.4730586,,47.0787376_15.4730586_graz_google_maps_image,,47.0787376_15.4730586_graz_google_satellite_image,,47.0787376_15.4730586_graz_google_street_view_image,, -5871235120,1,graz,47.027670455919214,15.46637684580302,,47.027670455919214_15.46637684580302_graz_google_maps_image,,47.027670455919214_15.46637684580302_graz_google_satellite_image,,47.027670455919214_15.46637684580302_graz_google_street_view_image,, -31620673,1,graz,47.02840659999999,15.4338649,,47.02840659999999_15.4338649_graz_google_maps_image,,47.02840659999999_15.4338649_graz_google_satellite_image,,47.02840659999999_15.4338649_graz_google_street_view_image,, -1363117573,1,graz,47.066961074212564,15.467476705898548,,47.066961074212564_15.467476705898548_graz_google_maps_image,,47.066961074212564_15.467476705898548_graz_google_satellite_image,,47.066961074212564_15.467476705898548_graz_google_street_view_image,, -5147474662,2,graz,47.07441620096659,15.431035045149669,,47.07441620096659_15.431035045149669_graz_google_maps_image,,47.07441620096659_15.431035045149669_graz_google_satellite_image,,47.07441620096659_15.431035045149669_graz_google_street_view_image,, -991630578,2,graz,47.0778083,15.4626039,,47.0778083_15.4626039_graz_google_maps_image,,47.0778083_15.4626039_graz_google_satellite_image,,47.0778083_15.4626039_graz_google_street_view_image,, -367079334,2,graz,47.079567691515145,15.467113619122438,,47.079567691515145_15.467113619122438_graz_google_maps_image,,47.079567691515145_15.467113619122438_graz_google_satellite_image,,47.079567691515145_15.467113619122438_graz_google_street_view_image,, -371197149,2,graz,47.07203198514327,15.436851842038411,,47.07203198514327_15.436851842038411_graz_google_maps_image,,47.07203198514327_15.436851842038411_graz_google_satellite_image,,47.07203198514327_15.436851842038411_graz_google_street_view_image,, -289182754,2,graz,47.062884611801096,15.465883429175388,,47.062884611801096_15.465883429175388_graz_google_maps_image,,47.062884611801096_15.465883429175388_graz_google_satellite_image,,47.062884611801096_15.465883429175388_graz_google_street_view_image,, -146904669,2,graz,47.059827917240405,15.39671379231068,,47.059827917240405_15.39671379231068_graz_google_maps_image,,47.059827917240405_15.39671379231068_graz_google_satellite_image,,47.059827917240405_15.39671379231068_graz_google_street_view_image,, -6200932089,2,graz,47.07478170455035,15.43135228917076,,47.07478170455035_15.43135228917076_graz_google_maps_image,,47.07478170455035_15.43135228917076_graz_google_satellite_image,,47.07478170455035_15.43135228917076_graz_google_street_view_image,, -96700819,2,graz,47.0619820164163,15.467675196662245,,47.0619820164163_15.467675196662245_graz_google_maps_image,,47.0619820164163_15.467675196662245_graz_google_satellite_image,,47.0619820164163_15.467675196662245_graz_google_street_view_image,, -199824392,2,graz,47.05997514380375,15.396174465462135,,47.05997514380375_15.396174465462135_graz_google_maps_image,,47.05997514380375_15.396174465462135_graz_google_satellite_image,,47.05997514380375_15.396174465462135_graz_google_street_view_image,, -1457222996,2,graz,47.08873915750338,15.428427131979845,,47.08873915750338_15.428427131979845_graz_google_maps_image,,47.08873915750338_15.428427131979845_graz_google_satellite_image,,47.08873915750338_15.428427131979845_graz_google_street_view_image,, -209747834,3,graz,47.08140590509027,15.444760675353093,,47.08140590509027_15.444760675353093_graz_google_maps_image,,47.08140590509027_15.444760675353093_graz_google_satellite_image,,47.08140590509027_15.444760675353093_graz_google_street_view_image,, -7066278891,3,graz,47.04784479999999,15.453480400000002,,47.04784479999999_15.453480400000002_graz_google_maps_image,,47.04784479999999_15.453480400000002_graz_google_satellite_image,,47.04784479999999_15.453480400000002_graz_google_street_view_image,, -6175091243,3,graz,47.06397698854764,15.431509069213012,,47.06397698854764_15.431509069213012_graz_google_maps_image,,47.06397698854764_15.431509069213012_graz_google_satellite_image,,47.06397698854764_15.431509069213012_graz_google_street_view_image,, -2896669721,3,graz,47.07554409999999,15.4310643,,47.07554409999999_15.4310643_graz_google_maps_image,,47.07554409999999_15.4310643_graz_google_satellite_image,,47.07554409999999_15.4310643_graz_google_street_view_image,, -111681954,3,graz,47.089446276044626,15.407834188355928,,47.089446276044626_15.407834188355928_graz_google_maps_image,,47.089446276044626_15.407834188355928_graz_google_satellite_image,,47.089446276044626_15.407834188355928_graz_google_street_view_image,, -202514625,3,graz,47.075677886529974,15.427859203915624,,47.075677886529974_15.427859203915624_graz_google_maps_image,,47.075677886529974_15.427859203915624_graz_google_satellite_image,,47.075677886529974_15.427859203915624_graz_google_street_view_image,, -6175091246,3,graz,47.065764684246176,15.431396432973846,,47.065764684246176_15.431396432973846_graz_google_maps_image,,47.065764684246176_15.431396432973846_graz_google_satellite_image,,47.065764684246176_15.431396432973846_graz_google_street_view_image,, -31611256,3,graz,47.06294791887,15.45794422889628,,47.06294791887_15.45794422889628_graz_google_maps_image,,47.06294791887_15.45794422889628_graz_google_satellite_image,,47.06294791887_15.45794422889628_graz_google_street_view_image,, -3274523680,3,graz,47.045818674923105,15.43317736526208,,47.045818674923105_15.43317736526208_graz_google_maps_image,,47.045818674923105_15.43317736526208_graz_google_satellite_image,,47.045818674923105_15.43317736526208_graz_google_street_view_image,, -2503804465,3,graz,47.051752699999994,15.4288421,,47.051752699999994_15.4288421_graz_google_maps_image,,47.051752699999994_15.4288421_graz_google_satellite_image,,47.051752699999994_15.4288421_graz_google_street_view_image,, -4078510935,4,graz,47.06581846471563,15.428119267611368,,47.06581846471563_15.428119267611368_graz_google_maps_image,,47.06581846471563_15.428119267611368_graz_google_satellite_image,,47.06581846471563_15.428119267611368_graz_google_street_view_image,, -371204222,4,graz,47.060816625984906,15.426402149782804,,47.060816625984906_15.426402149782804_graz_google_maps_image,,47.060816625984906_15.426402149782804_graz_google_satellite_image,,47.060816625984906_15.426402149782804_graz_google_street_view_image,, -85666832,4,graz,47.055576224299664,15.441634138653525,,47.055576224299664_15.441634138653525_graz_google_maps_image,,47.055576224299664_15.441634138653525_graz_google_satellite_image,,47.055576224299664_15.441634138653525_graz_google_street_view_image,, -1084426931,4,graz,47.07209159999999,15.450777799999997,,47.07209159999999_15.450777799999997_graz_google_maps_image,,47.07209159999999_15.450777799999997_graz_google_satellite_image,,47.07209159999999_15.450777799999997_graz_google_street_view_image,, -280171006,4,graz,47.0709970595606,15.432596533114502,,47.0709970595606_15.432596533114502_graz_google_maps_image,,47.0709970595606_15.432596533114502_graz_google_satellite_image,,47.0709970595606_15.432596533114502_graz_google_street_view_image,, -1264399993,4,graz,47.06822209748811,15.446736724640502,,47.06822209748811_15.446736724640502_graz_google_maps_image,,47.06822209748811_15.446736724640502_graz_google_satellite_image,,47.06822209748811_15.446736724640502_graz_google_street_view_image,, -97935285,4,graz,47.080162504289895,15.45049484924463,,47.080162504289895_15.45049484924463_graz_google_maps_image,,47.080162504289895_15.45049484924463_graz_google_satellite_image,,47.080162504289895_15.45049484924463_graz_google_street_view_image,, -906742088,4,graz,47.0724593773178,15.439754888111121,,47.0724593773178_15.439754888111121_graz_google_maps_image,,47.0724593773178_15.439754888111121_graz_google_satellite_image,,47.0724593773178_15.439754888111121_graz_google_street_view_image,, -1420207253,4,graz,47.069369499999986,15.4515449,,47.069369499999986_15.4515449_graz_google_maps_image,,47.069369499999986_15.4515449_graz_google_satellite_image,,47.069369499999986_15.4515449_graz_google_street_view_image,, -88015872,4,graz,47.06633275180773,15.446623732630812,,47.06633275180773_15.446623732630812_graz_google_maps_image,,47.06633275180773_15.446623732630812_graz_google_satellite_image,,47.06633275180773_15.446623732630812_graz_google_street_view_image,, -1601202088,5,graz,47.074398599999995,15.418842,,47.074398599999995_15.418842_graz_google_maps_image,,47.074398599999995_15.418842_graz_google_satellite_image,,47.074398599999995_15.418842_graz_google_street_view_image,, -366271309,5,graz,47.067493050726334,15.440533559702844,,47.067493050726334_15.440533559702844_graz_google_maps_image,,47.067493050726334_15.440533559702844_graz_google_satellite_image,,47.067493050726334_15.440533559702844_graz_google_street_view_image,, -1615186056,5,graz,47.053937146738406,15.448496466938671,,47.053937146738406_15.448496466938671_graz_google_maps_image,,47.053937146738406_15.448496466938671_graz_google_satellite_image,,47.053937146738406_15.448496466938671_graz_google_street_view_image,, -7402681135,5,graz,47.08028676740791,15.415723007909477,,47.08028676740791_15.415723007909477_graz_google_maps_image,,47.08028676740791_15.415723007909477_graz_google_satellite_image,,47.08028676740791_15.415723007909477_graz_google_street_view_image,, -366566728,5,graz,47.07041965736281,15.437991690645154,,47.07041965736281_15.437991690645154_graz_google_maps_image,,47.07041965736281_15.437991690645154_graz_google_satellite_image,,47.07041965736281_15.437991690645154_graz_google_street_view_image,, -4693752897,5,graz,47.072496900000004,15.41698,,47.072496900000004_15.41698_graz_google_maps_image,,47.072496900000004_15.41698_graz_google_satellite_image,,47.072496900000004_15.41698_graz_google_street_view_image,, -373020329,5,graz,47.07239200949782,15.416995377895535,,47.07239200949782_15.416995377895535_graz_google_maps_image,,47.07239200949782_15.416995377895535_graz_google_satellite_image,,47.07239200949782_15.416995377895535_graz_google_street_view_image,, -5536615311,5,graz,47.06710152140713,15.439590516030501,,47.06710152140713_15.439590516030501_graz_google_maps_image,,47.06710152140713_15.439590516030501_graz_google_satellite_image,,47.06710152140713_15.439590516030501_graz_google_street_view_image,, -5503873205,5,graz,47.07095275419845,15.43745850776562,,47.07095275419845_15.43745850776562_graz_google_maps_image,,47.07095275419845_15.43745850776562_graz_google_satellite_image,,47.07095275419845_15.43745850776562_graz_google_street_view_image,, -7073784418,5,graz,47.07116881836481,15.44106146010659,,47.07116881836481_15.44106146010659_graz_google_maps_image,,47.07116881836481_15.44106146010659_graz_google_satellite_image,,47.07116881836481_15.44106146010659_graz_google_street_view_image,, -6722142985,1,hanoi,21.068922733102795,105.70753807503452,,21.068922733102795_105.70753807503452_hanoi_google_maps_image,,21.068922733102795_105.70753807503452_hanoi_google_satellite_image,,21.068922733102795_105.70753807503452_hanoi_google_street_view_image,, -479832688,1,hanoi,21.017069179521965,105.94583671623174,,21.017069179521965_105.94583671623174_hanoi_google_maps_image,,21.017069179521965_105.94583671623174_hanoi_google_satellite_image,,21.017069179521965_105.94583671623174_hanoi_google_street_view_image,, -6758493185,1,hanoi,21.003441491118526,105.73220805652882,,21.003441491118526_105.73220805652882_hanoi_google_maps_image,,21.003441491118526_105.73220805652882_hanoi_google_satellite_image,,21.003441491118526_105.73220805652882_hanoi_google_street_view_image,, -6223959585,1,hanoi,20.9543479262088,105.80992396690392,,20.9543479262088_105.80992396690392_hanoi_google_maps_image,,20.9543479262088_105.80992396690392_hanoi_google_satellite_image,,20.9543479262088_105.80992396690392_hanoi_google_street_view_image,, -6776174785,1,hanoi,21.027002023325384,105.74040148345286,,21.027002023325384_105.74040148345286_hanoi_google_maps_image,,21.027002023325384_105.74040148345286_hanoi_google_satellite_image,,21.027002023325384_105.74040148345286_hanoi_google_street_view_image,, -660703617,1,hanoi,21.097550727421265,105.92020007310403,,21.097550727421265_105.92020007310403_hanoi_google_maps_image,,21.097550727421265_105.92020007310403_hanoi_google_satellite_image,,21.097550727421265_105.92020007310403_hanoi_google_street_view_image,, -5621453821,1,hanoi,21.029170402331154,105.91671085381081,,21.029170402331154_105.91671085381081_hanoi_google_maps_image,,21.029170402331154_105.91671085381081_hanoi_google_satellite_image,,21.029170402331154_105.91671085381081_hanoi_google_street_view_image,, -5686499421,1,hanoi,21.036729539284515,105.75942338376385,,21.036729539284515_105.75942338376385_hanoi_google_maps_image,,21.036729539284515_105.75942338376385_hanoi_google_satellite_image,,21.036729539284515_105.75942338376385_hanoi_google_street_view_image,, -6725510486,1,hanoi,20.970071220440932,105.87791195799343,,20.970071220440932_105.87791195799343_hanoi_google_maps_image,,20.970071220440932_105.87791195799343_hanoi_google_satellite_image,,20.970071220440932_105.87791195799343_hanoi_google_street_view_image,, -6745101586,1,hanoi,20.995433820848515,105.78431367150611,,20.995433820848515_105.78431367150611_hanoi_google_maps_image,,20.995433820848515_105.78431367150611_hanoi_google_satellite_image,,20.995433820848515_105.78431367150611_hanoi_google_street_view_image,, -5603707722,2,hanoi,21.060615604217126,105.89526636036369,,21.060615604217126_105.89526636036369_hanoi_google_maps_image,,21.060615604217126_105.89526636036369_hanoi_google_satellite_image,,21.060615604217126_105.89526636036369_hanoi_google_street_view_image,, -5463378180,2,hanoi,20.969396660487366,105.8653765685603,,20.969396660487366_105.8653765685603_hanoi_google_maps_image,,20.969396660487366_105.8653765685603_hanoi_google_satellite_image,,20.969396660487366_105.8653765685603_hanoi_google_street_view_image,, -6754857785,2,hanoi,21.028786066443622,105.76501194849482,,21.028786066443622_105.76501194849482_hanoi_google_maps_image,,21.028786066443622_105.76501194849482_hanoi_google_satellite_image,,21.028786066443622_105.76501194849482_hanoi_google_street_view_image,, -1927580774,2,hanoi,20.949618858270064,105.84513049645689,,20.949618858270064_105.84513049645689_hanoi_google_maps_image,,20.949618858270064_105.84513049645689_hanoi_google_satellite_image,,20.949618858270064_105.84513049645689_hanoi_google_street_view_image,, -6243854385,2,hanoi,20.996959281125314,105.79433788580187,,20.996959281125314_105.79433788580187_hanoi_google_maps_image,,20.996959281125314_105.79433788580187_hanoi_google_satellite_image,,20.996959281125314_105.79433788580187_hanoi_google_street_view_image,, -6794340541,2,hanoi,20.97058185387772,105.8295671687706,,20.97058185387772_105.8295671687706_hanoi_google_maps_image,,20.97058185387772_105.8295671687706_hanoi_google_satellite_image,,20.97058185387772_105.8295671687706_hanoi_google_street_view_image,, -5918039687,2,hanoi,21.05276854587558,105.83448155005497,,21.05276854587558_105.83448155005497_hanoi_google_maps_image,,21.05276854587558_105.83448155005497_hanoi_google_satellite_image,,21.05276854587558_105.83448155005497_hanoi_google_street_view_image,, -5123787182,2,hanoi,20.983900630226547,105.8595544436176,,20.983900630226547_105.8595544436176_hanoi_google_maps_image,,20.983900630226547_105.8595544436176_hanoi_google_satellite_image,,20.983900630226547_105.8595544436176_hanoi_google_street_view_image,, -705844951,2,hanoi,20.98150677468427,105.87101553908224,,20.98150677468427_105.87101553908224_hanoi_google_maps_image,,20.98150677468427_105.87101553908224_hanoi_google_satellite_image,,20.98150677468427_105.87101553908224_hanoi_google_street_view_image,, -6849107685,2,hanoi,21.034918114959215,105.73967236536781,,21.034918114959215_105.73967236536781_hanoi_google_maps_image,,21.034918114959215_105.73967236536781_hanoi_google_satellite_image,,21.034918114959215_105.73967236536781_hanoi_google_street_view_image,, -5485666060,3,hanoi,21.029211780913204,105.81249361311525,,21.029211780913204_105.81249361311525_hanoi_google_maps_image,,21.029211780913204_105.81249361311525_hanoi_google_satellite_image,,21.029211780913204_105.81249361311525_hanoi_google_street_view_image,, -7055975987,3,hanoi,20.98917138443581,105.80812608306697,,20.98917138443581_105.80812608306697_hanoi_google_maps_image,,20.98917138443581_105.80812608306697_hanoi_google_satellite_image,,20.98917138443581_105.80812608306697_hanoi_google_street_view_image,, -5678697421,3,hanoi,21.04994755729565,105.83921342208959,,21.04994755729565_105.83921342208959_hanoi_google_maps_image,,21.04994755729565_105.83921342208959_hanoi_google_satellite_image,,21.04994755729565_105.83921342208959_hanoi_google_street_view_image,, -7365666585,3,hanoi,21.00841652607623,105.7947007080327,,21.00841652607623_105.7947007080327_hanoi_google_maps_image,,21.00841652607623_105.7947007080327_hanoi_google_satellite_image,,21.00841652607623_105.7947007080327_hanoi_google_street_view_image,, -4090306852,3,hanoi,20.964577274890374,105.77184344107837,,20.964577274890374_105.77184344107837_hanoi_google_maps_image,,20.964577274890374_105.77184344107837_hanoi_google_satellite_image,,20.964577274890374_105.77184344107837_hanoi_google_street_view_image,, -5603809224,3,hanoi,21.029313278450548,105.8178029578799,,21.029313278450548_105.8178029578799_hanoi_google_maps_image,,21.029313278450548_105.8178029578799_hanoi_google_satellite_image,,21.029313278450548_105.8178029578799_hanoi_google_street_view_image,, -5521484621,3,hanoi,20.99398482690741,105.84207306240376,,20.99398482690741_105.84207306240376_hanoi_google_maps_image,,20.99398482690741_105.84207306240376_hanoi_google_satellite_image,,20.99398482690741_105.84207306240376_hanoi_google_street_view_image,, -4427721996,3,hanoi,21.03243902871824,105.85067581813661,,21.03243902871824_105.85067581813661_hanoi_google_maps_image,,21.03243902871824_105.85067581813661_hanoi_google_satellite_image,,21.03243902871824_105.85067581813661_hanoi_google_street_view_image,, -5757756521,3,hanoi,20.988201531401888,105.87741371589735,,20.988201531401888_105.87741371589735_hanoi_google_maps_image,,20.988201531401888_105.87741371589735_hanoi_google_satellite_image,,20.988201531401888_105.87741371589735_hanoi_google_street_view_image,, -3471347683,3,hanoi,21.04518443787649,105.79932552693185,,21.04518443787649_105.79932552693185_hanoi_google_maps_image,,21.04518443787649_105.79932552693185_hanoi_google_satellite_image,,21.04518443787649_105.79932552693185_hanoi_google_street_view_image,, -4171014889,4,hanoi,21.033027557877745,105.85362223212037,,21.033027557877745_105.85362223212037_hanoi_google_maps_image,,21.033027557877745_105.85362223212037_hanoi_google_satellite_image,,21.033027557877745_105.85362223212037_hanoi_google_street_view_image,, -5529931421,4,hanoi,21.01788493704499,105.86420199394303,,21.01788493704499_105.86420199394303_hanoi_google_maps_image,,21.01788493704499_105.86420199394303_hanoi_google_satellite_image,,21.01788493704499_105.86420199394303_hanoi_google_street_view_image,, -6684446887,4,hanoi,21.002831830376383,105.85477258246779,,21.002831830376383_105.85477258246779_hanoi_google_maps_image,,21.002831830376383_105.85477258246779_hanoi_google_satellite_image,,21.002831830376383_105.85477258246779_hanoi_google_street_view_image,, -5382848321,4,hanoi,21.016876554273694,105.85356045065343,,21.016876554273694_105.85356045065343_hanoi_google_maps_image,,21.016876554273694_105.85356045065343_hanoi_google_satellite_image,,21.016876554273694_105.85356045065343_hanoi_google_street_view_image,, -4458010392,4,hanoi,21.0357616,105.8533458,,21.0357616_105.8533458_hanoi_google_maps_image,,21.0357616_105.8533458_hanoi_google_satellite_image,,21.0357616_105.8533458_hanoi_google_street_view_image,, -6684446289,4,hanoi,20.991489045694973,105.84893675781264,,20.991489045694973_105.84893675781264_hanoi_google_maps_image,,20.991489045694973_105.84893675781264_hanoi_google_satellite_image,,20.991489045694973_105.84893675781264_hanoi_google_street_view_image,, -5485733755,4,hanoi,21.025797873573296,105.8223492511277,,21.025797873573296_105.8223492511277_hanoi_google_maps_image,,21.025797873573296_105.8223492511277_hanoi_google_satellite_image,,21.025797873573296_105.8223492511277_hanoi_google_street_view_image,, -4330652389,4,hanoi,21.03202805105592,105.85388845371705,,21.03202805105592_105.85388845371705_hanoi_google_maps_image,,21.03202805105592_105.85388845371705_hanoi_google_satellite_image,,21.03202805105592_105.85388845371705_hanoi_google_street_view_image,, -6798176413,4,hanoi,21.023383267194657,105.8566763008743,,21.023383267194657_105.8566763008743_hanoi_google_maps_image,,21.023383267194657_105.8566763008743_hanoi_google_satellite_image,,21.023383267194657_105.8566763008743_hanoi_google_street_view_image,, -6696644285,4,hanoi,21.015994552353664,105.82375046442098,,21.015994552353664_105.82375046442098_hanoi_google_maps_image,,21.015994552353664_105.82375046442098_hanoi_google_satellite_image,,21.015994552353664_105.82375046442098_hanoi_google_street_view_image,, -6684445888,5,hanoi,20.99867583893234,105.85242428805039,,20.99867583893234_105.85242428805039_hanoi_google_maps_image,,20.99867583893234_105.85242428805039_hanoi_google_satellite_image,,20.99867583893234_105.85242428805039_hanoi_google_street_view_image,, -6684446691,5,hanoi,21.020764764425014,105.83391005875832,,21.020764764425014_105.83391005875832_hanoi_google_maps_image,,21.020764764425014_105.83391005875832_hanoi_google_satellite_image,,21.020764764425014_105.83391005875832_hanoi_google_street_view_image,, -4706594119,5,hanoi,21.00738220868797,105.82141266107998,,21.00738220868797_105.82141266107998_hanoi_google_maps_image,,21.00738220868797_105.82141266107998_hanoi_google_satellite_image,,21.00738220868797_105.82141266107998_hanoi_google_street_view_image,, -4578730790,5,hanoi,20.999444665519622,105.87037885974038,,20.999444665519622_105.87037885974038_hanoi_google_maps_image,,20.999444665519622_105.87037885974038_hanoi_google_satellite_image,,20.999444665519622_105.87037885974038_hanoi_google_street_view_image,, -4155614990,5,hanoi,21.02670889474851,105.83872278163015,,21.02670889474851_105.83872278163015_hanoi_google_maps_image,,21.02670889474851_105.83872278163015_hanoi_google_satellite_image,,21.02670889474851_105.83872278163015_hanoi_google_street_view_image,, -5640928226,5,hanoi,20.998700008568832,105.85243902577905,,20.998700008568832_105.85243902577905_hanoi_google_maps_image,,20.998700008568832_105.85243902577905_hanoi_google_satellite_image,,20.998700008568832_105.85243902577905_hanoi_google_street_view_image,, -6682444185,5,hanoi,21.019737994699003,105.8233895262396,,21.019737994699003_105.8233895262396_hanoi_google_maps_image,,21.019737994699003_105.8233895262396_hanoi_google_satellite_image,,21.019737994699003_105.8233895262396_hanoi_google_street_view_image,, -3937714032,5,hanoi,21.008292741724393,105.85127133720407,,21.008292741724393_105.85127133720407_hanoi_google_maps_image,,21.008292741724393_105.85127133720407_hanoi_google_satellite_image,,21.008292741724393_105.85127133720407_hanoi_google_street_view_image,, -6897692985,5,hanoi,21.020251237893806,105.8216042586936,,21.020251237893806_105.8216042586936_hanoi_google_maps_image,,21.020251237893806_105.8216042586936_hanoi_google_satellite_image,,21.020251237893806_105.8216042586936_hanoi_google_street_view_image,, -5254163722,5,hanoi,21.039320849668325,105.85129075502276,,21.039320849668325_105.85129075502276_hanoi_google_maps_image,,21.039320849668325_105.85129075502276_hanoi_google_satellite_image,,21.039320849668325_105.85129075502276_hanoi_google_street_view_image,, -4892069827,1,hong_kong,22.284133698639288,114.18620675026642,,22.284133698639288_114.18620675026642_hong_kong_google_maps_image,,22.284133698639288_114.18620675026642_hong_kong_google_satellite_image,,22.284133698639288_114.18620675026642_hong_kong_google_street_view_image,, -4796625657,1,hong_kong,22.395456199999998,114.1985323,,22.395456199999998_114.1985323_hong_kong_google_maps_image,,22.395456199999998_114.1985323_hong_kong_google_satellite_image,,22.395456199999998_114.1985323_hong_kong_google_street_view_image,, -205719285,1,hong_kong,22.30692719527565,114.22231798308853,,22.30692719527565_114.22231798308853_hong_kong_google_maps_image,,22.30692719527565_114.22231798308853_hong_kong_google_satellite_image,,22.30692719527565_114.22231798308853_hong_kong_google_street_view_image,, -449876412,1,hong_kong,22.438756578053916,114.06494814322687,,22.438756578053916_114.06494814322687_hong_kong_google_maps_image,,22.438756578053916_114.06494814322687_hong_kong_google_satellite_image,,22.438756578053916_114.06494814322687_hong_kong_google_street_view_image,, -4929022970,1,hong_kong,22.372182039452962,114.19863426804811,,22.372182039452962_114.19863426804811_hong_kong_google_maps_image,,22.372182039452962_114.19863426804811_hong_kong_google_satellite_image,,22.372182039452962_114.19863426804811_hong_kong_google_street_view_image,, -1797941167,1,hong_kong,22.284718725860476,114.21170658297555,,22.284718725860476_114.21170658297555_hong_kong_google_maps_image,,22.284718725860476_114.21170658297555_hong_kong_google_satellite_image,,22.284718725860476_114.21170658297555_hong_kong_google_street_view_image,, -2411988977,1,hong_kong,22.300353191732224,114.17803962954156,,22.300353191732224_114.17803962954156_hong_kong_google_maps_image,,22.300353191732224_114.17803962954156_hong_kong_google_satellite_image,,22.300353191732224_114.17803962954156_hong_kong_google_street_view_image,, -448228055,1,hong_kong,22.43305331603814,113.99546771857557,,22.43305331603814_113.99546771857557_hong_kong_google_maps_image,,22.43305331603814_113.99546771857557_hong_kong_google_satellite_image,,22.43305331603814_113.99546771857557_hong_kong_google_street_view_image,, -369378651,1,hong_kong,22.50118642581332,114.14816314433028,,22.50118642581332_114.14816314433028_hong_kong_google_maps_image,,22.50118642581332_114.14816314433028_hong_kong_google_satellite_image,,22.50118642581332_114.14816314433028_hong_kong_google_street_view_image,, -1026522021,1,hong_kong,22.26550244118609,114.16150005809982,,22.26550244118609_114.16150005809982_hong_kong_google_maps_image,,22.26550244118609_114.16150005809982_hong_kong_google_satellite_image,,22.26550244118609_114.16150005809982_hong_kong_google_street_view_image,, -4714345992,2,hong_kong,22.276216706228734,114.17223512948674,,22.276216706228734_114.17223512948674_hong_kong_google_maps_image,,22.276216706228734_114.17223512948674_hong_kong_google_satellite_image,,22.276216706228734_114.17223512948674_hong_kong_google_street_view_image,, -2668679565,2,hong_kong,22.3310895,114.2042301,,22.3310895_114.2042301_hong_kong_google_maps_image,,22.3310895_114.2042301_hong_kong_google_satellite_image,,22.3310895_114.2042301_hong_kong_google_street_view_image,, -4332082788,2,hong_kong,22.344318661329456,114.10707595198313,,22.344318661329456_114.10707595198313_hong_kong_google_maps_image,,22.344318661329456_114.10707595198313_hong_kong_google_satellite_image,,22.344318661329456_114.10707595198313_hong_kong_google_street_view_image,, -207402934,2,hong_kong,22.443569281211314,114.03051306330704,,22.443569281211314_114.03051306330704_hong_kong_google_maps_image,,22.443569281211314_114.03051306330704_hong_kong_google_satellite_image,,22.443569281211314_114.03051306330704_hong_kong_google_street_view_image,, -6713630045,2,hong_kong,22.27864236348188,114.17278940379133,,22.27864236348188_114.17278940379133_hong_kong_google_maps_image,,22.27864236348188_114.17278940379133_hong_kong_google_satellite_image,,22.27864236348188_114.17278940379133_hong_kong_google_street_view_image,, -7104352625,2,hong_kong,22.30442181064681,114.16918179396565,,22.30442181064681_114.16918179396565_hong_kong_google_maps_image,,22.30442181064681_114.16918179396565_hong_kong_google_satellite_image,,22.30442181064681_114.16918179396565_hong_kong_google_street_view_image,, -4535490115,2,hong_kong,22.307189365009883,114.16639275849363,,22.307189365009883_114.16639275849363_hong_kong_google_maps_image,,22.307189365009883_114.16639275849363_hong_kong_google_satellite_image,,22.307189365009883_114.16639275849363_hong_kong_google_street_view_image,, -7528483966,2,hong_kong,22.446968377444716,114.02752379879898,,22.446968377444716_114.02752379879898_hong_kong_google_maps_image,,22.446968377444716_114.02752379879898_hong_kong_google_satellite_image,,22.446968377444716_114.02752379879898_hong_kong_google_street_view_image,, -4860792300,2,hong_kong,22.30518567025006,114.19040977857748,,22.30518567025006_114.19040977857748_hong_kong_google_maps_image,,22.30518567025006_114.19040977857748_hong_kong_google_satellite_image,,22.30518567025006_114.19040977857748_hong_kong_google_street_view_image,, -1698966259,2,hong_kong,22.535821600000002,114.0894877,,22.535821600000002_114.0894877_hong_kong_google_maps_image,,22.535821600000002_114.0894877_hong_kong_google_satellite_image,,22.535821600000002_114.0894877_hong_kong_google_street_view_image,, -6575813313,3,hong_kong,22.337462334621495,114.13847618743775,,22.337462334621495_114.13847618743775_hong_kong_google_maps_image,,22.337462334621495_114.13847618743775_hong_kong_google_satellite_image,,22.337462334621495_114.13847618743775_hong_kong_google_street_view_image,, -4377531470,3,hong_kong,22.333547345397413,114.19618840192908,,22.333547345397413_114.19618840192908_hong_kong_google_maps_image,,22.333547345397413_114.19618840192908_hong_kong_google_satellite_image,,22.333547345397413_114.19618840192908_hong_kong_google_street_view_image,, -4846225287,3,hong_kong,22.334469367610204,114.19779226860872,,22.334469367610204_114.19779226860872_hong_kong_google_maps_image,,22.334469367610204_114.19779226860872_hong_kong_google_satellite_image,,22.334469367610204_114.19779226860872_hong_kong_google_street_view_image,, -4448807066,3,hong_kong,22.328983454514894,114.1875223434335,,22.328983454514894_114.1875223434335_hong_kong_google_maps_image,,22.328983454514894_114.1875223434335_hong_kong_google_satellite_image,,22.328983454514894_114.1875223434335_hong_kong_google_street_view_image,, -4844544925,3,hong_kong,22.328986232442436,114.1874326291503,,22.328986232442436_114.1874326291503_hong_kong_google_maps_image,,22.328986232442436_114.1874326291503_hong_kong_google_satellite_image,,22.328986232442436_114.1874326291503_hong_kong_google_street_view_image,, -4735641521,3,hong_kong,22.266400789793277,114.25024598816081,,22.266400789793277_114.25024598816081_hong_kong_google_maps_image,,22.266400789793277_114.25024598816081_hong_kong_google_satellite_image,,22.266400789793277_114.25024598816081_hong_kong_google_street_view_image,, -135952234,3,hong_kong,22.385129492278143,114.20434152245105,,22.385129492278143_114.20434152245105_hong_kong_google_maps_image,,22.385129492278143_114.20434152245105_hong_kong_google_satellite_image,,22.385129492278143_114.20434152245105_hong_kong_google_street_view_image,, -6536997943,3,hong_kong,22.31499045556765,114.22450904910619,,22.31499045556765_114.22450904910619_hong_kong_google_maps_image,,22.31499045556765_114.22450904910619_hong_kong_google_satellite_image,,22.31499045556765_114.22450904910619_hong_kong_google_street_view_image,, -4239530853,3,hong_kong,22.284460005702247,114.15093592770678,,22.284460005702247_114.15093592770678_hong_kong_google_maps_image,,22.284460005702247_114.15093592770678_hong_kong_google_satellite_image,,22.284460005702247_114.15093592770678_hong_kong_google_street_view_image,, -259578104,3,hong_kong,22.332773219154767,114.15370100960129,,22.332773219154767_114.15370100960129_hong_kong_google_maps_image,,22.332773219154767_114.15370100960129_hong_kong_google_satellite_image,,22.332773219154767_114.15370100960129_hong_kong_google_street_view_image,, -3125709385,4,hong_kong,22.28280239275675,114.12936540767328,,22.28280239275675_114.12936540767328_hong_kong_google_maps_image,,22.28280239275675_114.12936540767328_hong_kong_google_satellite_image,,22.28280239275675_114.12936540767328_hong_kong_google_street_view_image,, -4850400062,4,hong_kong,22.3418432306103,114.19228650803899,,22.3418432306103_114.19228650803899_hong_kong_google_maps_image,,22.3418432306103_114.19228650803899_hong_kong_google_satellite_image,,22.3418432306103_114.19228650803899_hong_kong_google_street_view_image,, -2374461156,4,hong_kong,22.2920894,114.1989031,,22.2920894_114.1989031_hong_kong_google_maps_image,,22.2920894_114.1989031_hong_kong_google_satellite_image,,22.2920894_114.1989031_hong_kong_google_street_view_image,, -4860767139,4,hong_kong,22.370883378450664,114.11749322473084,,22.370883378450664_114.11749322473084_hong_kong_google_maps_image,,22.370883378450664_114.11749322473084_hong_kong_google_satellite_image,,22.370883378450664_114.11749322473084_hong_kong_google_street_view_image,, -4507124689,4,hong_kong,22.315525199999996,114.219406,,22.315525199999996_114.219406_hong_kong_google_maps_image,,22.315525199999996_114.219406_hong_kong_google_satellite_image,,22.315525199999996_114.219406_hong_kong_google_street_view_image,, -4862556866,4,hong_kong,22.285763392743434,114.13656747105472,,22.285763392743434_114.13656747105472_hong_kong_google_maps_image,,22.285763392743434_114.13656747105472_hong_kong_google_satellite_image,,22.285763392743434_114.13656747105472_hong_kong_google_street_view_image,, -4858295348,4,hong_kong,22.292229508399178,114.20147571753012,,22.292229508399178_114.20147571753012_hong_kong_google_maps_image,,22.292229508399178_114.20147571753012_hong_kong_google_satellite_image,,22.292229508399178_114.20147571753012_hong_kong_google_street_view_image,, -6837889661,4,hong_kong,22.277769071191972,114.22684808096034,,22.277769071191972_114.22684808096034_hong_kong_google_maps_image,,22.277769071191972_114.22684808096034_hong_kong_google_satellite_image,,22.277769071191972_114.22684808096034_hong_kong_google_street_view_image,, -184798478,4,hong_kong,22.288940695856468,114.13728890745946,,22.288940695856468_114.13728890745946_hong_kong_google_maps_image,,22.288940695856468_114.13728890745946_hong_kong_google_satellite_image,,22.288940695856468_114.13728890745946_hong_kong_google_street_view_image,, -412685601,4,hong_kong,22.323921779584147,114.16751683359722,,22.323921779584147_114.16751683359722_hong_kong_google_maps_image,,22.323921779584147_114.16751683359722_hong_kong_google_satellite_image,,22.323921779584147_114.16751683359722_hong_kong_google_street_view_image,, -4265740938,5,hong_kong,22.29134124852563,114.19809722395156,,22.29134124852563_114.19809722395156_hong_kong_google_maps_image,,22.29134124852563_114.19809722395156_hong_kong_google_satellite_image,,22.29134124852563_114.19809722395156_hong_kong_google_street_view_image,, -4085111529,5,hong_kong,22.305732581981363,114.1865769466339,,22.305732581981363_114.1865769466339_hong_kong_google_maps_image,,22.305732581981363_114.1865769466339_hong_kong_google_satellite_image,,22.305732581981363_114.1865769466339_hong_kong_google_street_view_image,, -4085888180,5,hong_kong,22.321084346445794,114.16894636524125,,22.321084346445794_114.16894636524125_hong_kong_google_maps_image,,22.321084346445794_114.16894636524125_hong_kong_google_satellite_image,,22.321084346445794_114.16894636524125_hong_kong_google_street_view_image,, -4850219814,5,hong_kong,22.249003532685723,114.15610284337879,,22.249003532685723_114.15610284337879_hong_kong_google_maps_image,,22.249003532685723_114.15610284337879_hong_kong_google_satellite_image,,22.249003532685723_114.15610284337879_hong_kong_google_street_view_image,, -3483855627,5,hong_kong,22.317589030551233,114.26543205646237,,22.317589030551233_114.26543205646237_hong_kong_google_maps_image,,22.317589030551233_114.26543205646237_hong_kong_google_satellite_image,,22.317589030551233_114.26543205646237_hong_kong_google_street_view_image,, -5529769123,5,hong_kong,22.386789766657888,114.2033676235673,,22.386789766657888_114.2033676235673_hong_kong_google_maps_image,,22.386789766657888_114.2033676235673_hong_kong_google_satellite_image,,22.386789766657888_114.2033676235673_hong_kong_google_street_view_image,, -2146262929,5,hong_kong,22.321436753617395,114.16180592296789,,22.321436753617395_114.16180592296789_hong_kong_google_maps_image,,22.321436753617395_114.16180592296789_hong_kong_google_satellite_image,,22.321436753617395_114.16180592296789_hong_kong_google_street_view_image,, -5529800921,5,hong_kong,22.386605327053417,114.20328394120013,,22.386605327053417_114.20328394120013_hong_kong_google_maps_image,,22.386605327053417_114.20328394120013_hong_kong_google_satellite_image,,22.386605327053417_114.20328394120013_hong_kong_google_street_view_image,, -465800314,5,hong_kong,22.24130655896862,114.15521825902438,,22.24130655896862_114.15521825902438_hong_kong_google_maps_image,,22.24130655896862_114.15521825902438_hong_kong_google_satellite_image,,22.24130655896862_114.15521825902438_hong_kong_google_street_view_image,, -1299465475,5,hong_kong,22.29052556670896,114.19748546214171,,22.29052556670896_114.19748546214171_hong_kong_google_maps_image,,22.29052556670896_114.19748546214171_hong_kong_google_satellite_image,,22.29052556670896_114.19748546214171_hong_kong_google_street_view_image,, -1545693817,1,lisbon,38.70966287724227,-9.140123829550635,,38.70966287724227_-9.140123829550635_lisbon_google_maps_image,,38.70966287724227_-9.140123829550635_lisbon_google_satellite_image,,38.70966287724227_-9.140123829550635_lisbon_google_street_view_image,, -6707461586,1,lisbon,38.705600573157014,-9.161490871745999,,38.705600573157014_-9.161490871745999_lisbon_google_maps_image,,38.705600573157014_-9.161490871745999_lisbon_google_satellite_image,,38.705600573157014_-9.161490871745999_lisbon_google_street_view_image,, -6366440072,1,lisbon,38.74430350132741,-9.149393634220065,,38.74430350132741_-9.149393634220065_lisbon_google_maps_image,,38.74430350132741_-9.149393634220065_lisbon_google_satellite_image,,38.74430350132741_-9.149393634220065_lisbon_google_street_view_image,, -4023605758,1,lisbon,38.74980839245447,-9.117581390729129,,38.74980839245447_-9.117581390729129_lisbon_google_maps_image,,38.74980839245447_-9.117581390729129_lisbon_google_satellite_image,,38.74980839245447_-9.117581390729129_lisbon_google_street_view_image,, -5984944787,1,lisbon,38.73555107121585,-9.14552187742019,,38.73555107121585_-9.14552187742019_lisbon_google_maps_image,,38.73555107121585_-9.14552187742019_lisbon_google_satellite_image,,38.73555107121585_-9.14552187742019_lisbon_google_street_view_image,, -5427721798,1,lisbon,38.73331861089569,-9.147531312446892,,38.73331861089569_-9.147531312446892_lisbon_google_maps_image,,38.73331861089569_-9.147531312446892_lisbon_google_satellite_image,,38.73331861089569_-9.147531312446892_lisbon_google_street_view_image,, -6307188788,1,lisbon,38.726024798001916,-9.112265702090244,,38.726024798001916_-9.112265702090244_lisbon_google_maps_image,,38.726024798001916_-9.112265702090244_lisbon_google_satellite_image,,38.726024798001916_-9.112265702090244_lisbon_google_street_view_image,, -3157752612,1,lisbon,38.741275,-9.1660437,,38.741275_-9.1660437_lisbon_google_maps_image,,38.741275_-9.1660437_lisbon_google_satellite_image,,38.741275_-9.1660437_lisbon_google_street_view_image,, -7539039885,1,lisbon,38.740038754474725,-9.167147608897007,,38.740038754474725_-9.167147608897007_lisbon_google_maps_image,,38.740038754474725_-9.167147608897007_lisbon_google_satellite_image,,38.740038754474725_-9.167147608897007_lisbon_google_street_view_image,, -2295708194,1,lisbon,38.705907367041455,-9.208838705227363,,38.705907367041455_-9.208838705227363_lisbon_google_maps_image,,38.705907367041455_-9.208838705227363_lisbon_google_satellite_image,,38.705907367041455_-9.208838705227363_lisbon_google_street_view_image,, -6262730577,2,lisbon,38.756249098471045,-9.139818637865963,,38.756249098471045_-9.139818637865963_lisbon_google_maps_image,,38.756249098471045_-9.139818637865963_lisbon_google_satellite_image,,38.756249098471045_-9.139818637865963_lisbon_google_street_view_image,, -6326009249,2,lisbon,38.73931600240588,-9.152317852337573,,38.73931600240588_-9.152317852337573_lisbon_google_maps_image,,38.73931600240588_-9.152317852337573_lisbon_google_satellite_image,,38.73931600240588_-9.152317852337573_lisbon_google_street_view_image,, -663925349,2,lisbon,38.71385759211145,-9.137879992827276,,38.71385759211145_-9.137879992827276_lisbon_google_maps_image,,38.71385759211145_-9.137879992827276_lisbon_google_satellite_image,,38.71385759211145_-9.137879992827276_lisbon_google_street_view_image,, -4622636093,2,lisbon,38.71250094463224,-9.125709281250519,,38.71250094463224_-9.125709281250519_lisbon_google_maps_image,,38.71250094463224_-9.125709281250519_lisbon_google_satellite_image,,38.71250094463224_-9.125709281250519_lisbon_google_street_view_image,, -97277780,2,lisbon,38.73113838911016,-9.144663546508824,,38.73113838911016_-9.144663546508824_lisbon_google_maps_image,,38.73113838911016_-9.144663546508824_lisbon_google_satellite_image,,38.73113838911016_-9.144663546508824_lisbon_google_street_view_image,, -5141865824,2,lisbon,38.71118460769638,-9.14293666558514,,38.71118460769638_-9.14293666558514_lisbon_google_maps_image,,38.71118460769638_-9.14293666558514_lisbon_google_satellite_image,,38.71118460769638_-9.14293666558514_lisbon_google_street_view_image,, -4226508186,2,lisbon,38.71556728235288,-9.146179981223728,,38.71556728235288_-9.146179981223728_lisbon_google_maps_image,,38.71556728235288_-9.146179981223728_lisbon_google_satellite_image,,38.71556728235288_-9.146179981223728_lisbon_google_street_view_image,, -5164905587,2,lisbon,38.73509014946658,-9.149790314950465,,38.73509014946658_-9.149790314950465_lisbon_google_maps_image,,38.73509014946658_-9.149790314950465_lisbon_google_satellite_image,,38.73509014946658_-9.149790314950465_lisbon_google_street_view_image,, -6427585145,2,lisbon,38.70471154696579,-9.168350448728575,,38.70471154696579_-9.168350448728575_lisbon_google_maps_image,,38.70471154696579_-9.168350448728575_lisbon_google_satellite_image,,38.70471154696579_-9.168350448728575_lisbon_google_street_view_image,, -4530470190,2,lisbon,38.73303296858585,-9.150064841274663,,38.73303296858585_-9.150064841274663_lisbon_google_maps_image,,38.73303296858585_-9.150064841274663_lisbon_google_satellite_image,,38.73303296858585_-9.150064841274663_lisbon_google_street_view_image,, -1743702474,3,lisbon,38.74320421192193,-9.133698814961022,,38.74320421192193_-9.133698814961022_lisbon_google_maps_image,,38.74320421192193_-9.133698814961022_lisbon_google_satellite_image,,38.74320421192193_-9.133698814961022_lisbon_google_street_view_image,, -6453992485,3,lisbon,38.71525972963288,-9.137102250557195,,38.71525972963288_-9.137102250557195_lisbon_google_maps_image,,38.71525972963288_-9.137102250557195_lisbon_google_satellite_image,,38.71525972963288_-9.137102250557195_lisbon_google_street_view_image,, -4839836049,3,lisbon,38.73295043539661,-9.141001232246735,,38.73295043539661_-9.141001232246735_lisbon_google_maps_image,,38.73295043539661_-9.141001232246735_lisbon_google_satellite_image,,38.73295043539661_-9.141001232246735_lisbon_google_street_view_image,, -3003135433,3,lisbon,38.7624225,-9.1134113,,38.7624225_-9.1134113_lisbon_google_maps_image,,38.7624225_-9.1134113_lisbon_google_satellite_image,,38.7624225_-9.1134113_lisbon_google_street_view_image,, -5565322521,3,lisbon,38.72319377709821,-9.145689855970039,,38.72319377709821_-9.145689855970039_lisbon_google_maps_image,,38.72319377709821_-9.145689855970039_lisbon_google_satellite_image,,38.72319377709821_-9.145689855970039_lisbon_google_street_view_image,, -6124616185,3,lisbon,38.710236788304506,-9.145270678079891,,38.710236788304506_-9.145270678079891_lisbon_google_maps_image,,38.710236788304506_-9.145270678079891_lisbon_google_satellite_image,,38.710236788304506_-9.145270678079891_lisbon_google_street_view_image,, -5631421818,3,lisbon,38.74816695467958,-9.188352574429125,,38.74816695467958_-9.188352574429125_lisbon_google_maps_image,,38.74816695467958_-9.188352574429125_lisbon_google_satellite_image,,38.74816695467958_-9.188352574429125_lisbon_google_street_view_image,, -3999539689,3,lisbon,38.738134073850965,-9.147085165587445,,38.738134073850965_-9.147085165587445_lisbon_google_maps_image,,38.738134073850965_-9.147085165587445_lisbon_google_satellite_image,,38.738134073850965_-9.147085165587445_lisbon_google_street_view_image,, -4624286128,3,lisbon,38.71082442420567,-9.136883577728488,,38.71082442420567_-9.136883577728488_lisbon_google_maps_image,,38.71082442420567_-9.136883577728488_lisbon_google_satellite_image,,38.71082442420567_-9.136883577728488_lisbon_google_street_view_image,, -454653397,3,lisbon,38.77927101269666,-9.160503526615129,,38.77927101269666_-9.160503526615129_lisbon_google_maps_image,,38.77927101269666_-9.160503526615129_lisbon_google_satellite_image,,38.77927101269666_-9.160503526615129_lisbon_google_street_view_image,, -3376281170,4,lisbon,38.745068775256456,-9.180649288650995,,38.745068775256456_-9.180649288650995_lisbon_google_maps_image,,38.745068775256456_-9.180649288650995_lisbon_google_satellite_image,,38.745068775256456_-9.180649288650995_lisbon_google_street_view_image,, -5433711050,4,lisbon,38.70892617854385,-9.166882837385984,,38.70892617854385_-9.166882837385984_lisbon_google_maps_image,,38.70892617854385_-9.166882837385984_lisbon_google_satellite_image,,38.70892617854385_-9.166882837385984_lisbon_google_street_view_image,, -2620375202,4,lisbon,38.71134955960933,-9.145557584917777,,38.71134955960933_-9.145557584917777_lisbon_google_maps_image,,38.71134955960933_-9.145557584917777_lisbon_google_satellite_image,,38.71134955960933_-9.145557584917777_lisbon_google_street_view_image,, -6307214586,4,lisbon,38.7268700771402,-9.120876353709441,,38.7268700771402_-9.120876353709441_lisbon_google_maps_image,,38.7268700771402_-9.120876353709441_lisbon_google_satellite_image,,38.7268700771402_-9.120876353709441_lisbon_google_street_view_image,, -6022965179,4,lisbon,38.722488465181144,-9.135351122023408,,38.722488465181144_-9.135351122023408_lisbon_google_maps_image,,38.722488465181144_-9.135351122023408_lisbon_google_satellite_image,,38.722488465181144_-9.135351122023408_lisbon_google_street_view_image,, -3624591180,4,lisbon,38.71929219441708,-9.135593221978837,,38.71929219441708_-9.135593221978837_lisbon_google_maps_image,,38.71929219441708_-9.135593221978837_lisbon_google_satellite_image,,38.71929219441708_-9.135593221978837_lisbon_google_street_view_image,, -5963845096,4,lisbon,38.742330800000005,-9.1399983,,38.742330800000005_-9.1399983_lisbon_google_maps_image,,38.742330800000005_-9.1399983_lisbon_google_satellite_image,,38.742330800000005_-9.1399983_lisbon_google_street_view_image,, -97680513,4,lisbon,38.7494282800985,-9.146032297652159,,38.7494282800985_-9.146032297652159_lisbon_google_maps_image,,38.7494282800985_-9.146032297652159_lisbon_google_satellite_image,,38.7494282800985_-9.146032297652159_lisbon_google_street_view_image,, -2516634850,4,lisbon,38.74978544166516,-9.173100412338812,,38.74978544166516_-9.173100412338812_lisbon_google_maps_image,,38.74978544166516_-9.173100412338812_lisbon_google_satellite_image,,38.74978544166516_-9.173100412338812_lisbon_google_street_view_image,, -1587098198,4,lisbon,38.70525240555577,-9.193846082503352,,38.70525240555577_-9.193846082503352_lisbon_google_maps_image,,38.70525240555577_-9.193846082503352_lisbon_google_satellite_image,,38.70525240555577_-9.193846082503352_lisbon_google_street_view_image,, -4639845489,5,lisbon,38.73309861145979,-9.134301593579302,,38.73309861145979_-9.134301593579302_lisbon_google_maps_image,,38.73309861145979_-9.134301593579302_lisbon_google_satellite_image,,38.73309861145979_-9.134301593579302_lisbon_google_street_view_image,, -4287522394,5,lisbon,38.72607004572371,-9.13294234496399,,38.72607004572371_-9.13294234496399_lisbon_google_maps_image,,38.72607004572371_-9.13294234496399_lisbon_google_satellite_image,,38.72607004572371_-9.13294234496399_lisbon_google_street_view_image,, -1832831352,5,lisbon,38.723659358373595,-9.129508409179365,,38.723659358373595_-9.129508409179365_lisbon_google_maps_image,,38.723659358373595_-9.129508409179365_lisbon_google_satellite_image,,38.723659358373595_-9.129508409179365_lisbon_google_street_view_image,, -4510657283,5,lisbon,38.71949307744241,-9.12975798953745,,38.71949307744241_-9.12975798953745_lisbon_google_maps_image,,38.71949307744241_-9.12975798953745_lisbon_google_satellite_image,,38.71949307744241_-9.12975798953745_lisbon_google_street_view_image,, -3997125184,5,lisbon,38.73414497252993,-9.128573237178719,,38.73414497252993_-9.128573237178719_lisbon_google_maps_image,,38.73414497252993_-9.128573237178719_lisbon_google_satellite_image,,38.73414497252993_-9.128573237178719_lisbon_google_street_view_image,, -6206335524,5,lisbon,38.71796314871114,-9.166435785049844,,38.71796314871114_-9.166435785049844_lisbon_google_maps_image,,38.71796314871114_-9.166435785049844_lisbon_google_satellite_image,,38.71796314871114_-9.166435785049844_lisbon_google_street_view_image,, -98625344,5,lisbon,38.73526918675126,-9.133157942472199,,38.73526918675126_-9.133157942472199_lisbon_google_maps_image,,38.73526918675126_-9.133157942472199_lisbon_google_satellite_image,,38.73526918675126_-9.133157942472199_lisbon_google_street_view_image,, -2908623658,5,lisbon,38.7183950062489,-9.129897590539246,,38.7183950062489_-9.129897590539246_lisbon_google_maps_image,,38.7183950062489_-9.129897590539246_lisbon_google_satellite_image,,38.7183950062489_-9.129897590539246_lisbon_google_street_view_image,, -5688444724,5,lisbon,38.73273056041424,-9.134251425001864,,38.73273056041424_-9.134251425001864_lisbon_google_maps_image,,38.73273056041424_-9.134251425001864_lisbon_google_satellite_image,,38.73273056041424_-9.134251425001864_lisbon_google_street_view_image,, -3663653601,5,lisbon,38.731261719462296,-9.136411705274716,,38.731261719462296_-9.136411705274716_lisbon_google_maps_image,,38.731261719462296_-9.136411705274716_lisbon_google_satellite_image,,38.731261719462296_-9.136411705274716_lisbon_google_street_view_image,, -1505918056,1,melbourne,-37.72634093236668,144.80690060968655,,-37.72634093236668_144.80690060968655_melbourne_google_maps_image,,-37.72634093236668_144.80690060968655_melbourne_google_satellite_image,,-37.72634093236668_144.80690060968655_melbourne_google_street_view_image,, -2172299040,1,melbourne,-37.679679899999755,144.9180914,,-37.679679899999755_144.9180914_melbourne_google_maps_image,,-37.679679899999755_144.9180914_melbourne_google_satellite_image,,-37.679679899999755_144.9180914_melbourne_google_street_view_image,, -365210773,1,melbourne,-38.14249693427462,145.12327956942863,,-38.14249693427462_145.12327956942863_melbourne_google_maps_image,,-38.14249693427462_145.12327956942863_melbourne_google_satellite_image,,-38.14249693427462_145.12327956942863_melbourne_google_street_view_image,, -5824764073,1,melbourne,-37.78246724295598,144.83367791035027,,-37.78246724295598_144.83367791035027_melbourne_google_maps_image,,-37.78246724295598_144.83367791035027_melbourne_google_satellite_image,,-37.78246724295598_144.83367791035027_melbourne_google_street_view_image,, -190526844,1,melbourne,-38.004547914836444,145.26656385045845,,-38.004547914836444_145.26656385045845_melbourne_google_maps_image,,-38.004547914836444_145.26656385045845_melbourne_google_satellite_image,,-38.004547914836444_145.26656385045845_melbourne_google_street_view_image,, -881751151,1,melbourne,-37.687230278894226,144.88494206982634,,-37.687230278894226_144.88494206982634_melbourne_google_maps_image,,-37.687230278894226_144.88494206982634_melbourne_google_satellite_image,,-37.687230278894226_144.88494206982634_melbourne_google_street_view_image,, -508030779,1,melbourne,-37.79367239999974,144.8610359,,-37.79367239999974_144.8610359_melbourne_google_maps_image,,-37.79367239999974_144.8610359_melbourne_google_satellite_image,,-37.79367239999974_144.8610359_melbourne_google_street_view_image,, -2343283482,1,melbourne,-37.902768161867854,144.6518352001569,,-37.902768161867854_144.6518352001569_melbourne_google_maps_image,,-37.902768161867854_144.6518352001569_melbourne_google_satellite_image,,-37.902768161867854_144.6518352001569_melbourne_google_street_view_image,, -3387681615,1,melbourne,-37.71909461875353,145.03838420810493,,-37.71909461875353_145.03838420810493_melbourne_google_maps_image,,-37.71909461875353_145.03838420810493_melbourne_google_satellite_image,,-37.71909461875353_145.03838420810493_melbourne_google_street_view_image,, -2388090624,1,melbourne,-37.783659999999756,144.8323507,,-37.783659999999756_144.8323507_melbourne_google_maps_image,,-37.783659999999756_144.8323507_melbourne_google_satellite_image,,-37.783659999999756_144.8323507_melbourne_google_street_view_image,, -5640738710,2,melbourne,-37.73892283660425,145.00169864808183,,-37.73892283660425_145.00169864808183_melbourne_google_maps_image,,-37.73892283660425_145.00169864808183_melbourne_google_satellite_image,,-37.73892283660425_145.00169864808183_melbourne_google_street_view_image,, -1432376901,2,melbourne,-37.74810720111193,145.04266874870487,,-37.74810720111193_145.04266874870487_melbourne_google_maps_image,,-37.74810720111193_145.04266874870487_melbourne_google_satellite_image,,-37.74810720111193_145.04266874870487_melbourne_google_street_view_image,, -1658371416,2,melbourne,-37.892058612946784,145.14399105974852,,-37.892058612946784_145.14399105974852_melbourne_google_maps_image,,-37.892058612946784_145.14399105974852_melbourne_google_satellite_image,,-37.892058612946784_145.14399105974852_melbourne_google_street_view_image,, -2285130249,2,melbourne,-37.702123027939486,144.79954309277667,,-37.702123027939486_144.79954309277667_melbourne_google_maps_image,,-37.702123027939486_144.79954309277667_melbourne_google_satellite_image,,-37.702123027939486_144.79954309277667_melbourne_google_street_view_image,, -5242175957,2,melbourne,-37.69388360881736,144.75469735430232,,-37.69388360881736_144.75469735430232_melbourne_google_maps_image,,-37.69388360881736_144.75469735430232_melbourne_google_satellite_image,,-37.69388360881736_144.75469735430232_melbourne_google_street_view_image,, -4456047388,2,melbourne,-37.913863468399136,145.25705024230396,,-37.913863468399136_145.25705024230396_melbourne_google_maps_image,,-37.913863468399136_145.25705024230396_melbourne_google_satellite_image,,-37.913863468399136_145.25705024230396_melbourne_google_street_view_image,, -5076265958,2,melbourne,-37.77327138862686,145.11397856155645,,-37.77327138862686_145.11397856155645_melbourne_google_maps_image,,-37.77327138862686_145.11397856155645_melbourne_google_satellite_image,,-37.77327138862686_145.11397856155645_melbourne_google_street_view_image,, -539840860,2,melbourne,-37.67292040527805,145.016654795642,,-37.67292040527805_145.016654795642_melbourne_google_maps_image,,-37.67292040527805_145.016654795642_melbourne_google_satellite_image,,-37.67292040527805_145.016654795642_melbourne_google_street_view_image,, -2918617899,2,melbourne,-37.69724287593561,145.05750954609184,,-37.69724287593561_145.05750954609184_melbourne_google_maps_image,,-37.69724287593561_145.05750954609184_melbourne_google_satellite_image,,-37.69724287593561_145.05750954609184_melbourne_google_street_view_image,, -640788713,2,melbourne,-37.931331944519705,145.15537043900713,,-37.931331944519705_145.15537043900713_melbourne_google_maps_image,,-37.931331944519705_145.15537043900713_melbourne_google_satellite_image,,-37.931331944519705_145.15537043900713_melbourne_google_street_view_image,, -1864449244,3,melbourne,-37.715648388275234,145.12133933865198,,-37.715648388275234_145.12133933865198_melbourne_google_maps_image,,-37.715648388275234_145.12133933865198_melbourne_google_satellite_image,,-37.715648388275234_145.12133933865198_melbourne_google_street_view_image,, -1893236280,3,melbourne,-37.84863974794789,145.0803363097369,,-37.84863974794789_145.0803363097369_melbourne_google_maps_image,,-37.84863974794789_145.0803363097369_melbourne_google_satellite_image,,-37.84863974794789_145.0803363097369_melbourne_google_street_view_image,, -5963317160,3,melbourne,-37.945170020793796,145.15126299083795,,-37.945170020793796_145.15126299083795_melbourne_google_maps_image,,-37.945170020793796_145.15126299083795_melbourne_google_satellite_image,,-37.945170020793796_145.15126299083795_melbourne_google_street_view_image,, -6065623710,3,melbourne,-37.8989760782216,145.09194026091464,,-37.8989760782216_145.09194026091464_melbourne_google_maps_image,,-37.8989760782216_145.09194026091464_melbourne_google_satellite_image,,-37.8989760782216_145.09194026091464_melbourne_google_street_view_image,, -1864405191,3,melbourne,-37.716529707420456,145.12119078722694,,-37.716529707420456_145.12119078722694_melbourne_google_maps_image,,-37.716529707420456_145.12119078722694_melbourne_google_satellite_image,,-37.716529707420456_145.12119078722694_melbourne_google_street_view_image,, -5203746966,3,melbourne,-37.951286370029955,145.1512037278662,,-37.951286370029955_145.1512037278662_melbourne_google_maps_image,,-37.951286370029955_145.1512037278662_melbourne_google_satellite_image,,-37.951286370029955_145.1512037278662_melbourne_google_street_view_image,, -5213706361,3,melbourne,-37.951579542866526,145.15140985690735,,-37.951579542866526_145.15140985690735_melbourne_google_maps_image,,-37.951579542866526_145.15140985690735_melbourne_google_satellite_image,,-37.951579542866526_145.15140985690735_melbourne_google_street_view_image,, -1864449245,3,melbourne,-37.715717754910585,145.12132800287327,,-37.715717754910585_145.12132800287327_melbourne_google_maps_image,,-37.715717754910585_145.12132800287327_melbourne_google_satellite_image,,-37.715717754910585_145.12132800287327_melbourne_google_street_view_image,, -4186252195,3,melbourne,-37.871640811186154,144.77513306592417,,-37.871640811186154_144.77513306592417_melbourne_google_maps_image,,-37.871640811186154_144.77513306592417_melbourne_google_satellite_image,,-37.871640811186154_144.77513306592417_melbourne_google_street_view_image,, -1865226630,3,melbourne,-37.716296651798096,145.1212318973898,,-37.716296651798096_145.1212318973898_melbourne_google_maps_image,,-37.716296651798096_145.1212318973898_melbourne_google_satellite_image,,-37.716296651798096_145.1212318973898_melbourne_google_street_view_image,, -6734873390,4,melbourne,-37.806734534075844,145.02951552133834,,-37.806734534075844_145.02951552133834_melbourne_google_maps_image,,-37.806734534075844_145.02951552133834_melbourne_google_satellite_image,,-37.806734534075844_145.02951552133834_melbourne_google_street_view_image,, -5241952634,4,melbourne,-37.971695683458265,145.14966013431146,,-37.971695683458265_145.14966013431146_melbourne_google_maps_image,,-37.971695683458265_145.14966013431146_melbourne_google_satellite_image,,-37.971695683458265_145.14966013431146_melbourne_google_street_view_image,, -636550055,4,melbourne,-37.80080337874809,144.90133323784005,,-37.80080337874809_144.90133323784005_melbourne_google_maps_image,,-37.80080337874809_144.90133323784005_melbourne_google_satellite_image,,-37.80080337874809_144.90133323784005_melbourne_google_street_view_image,, -2372890188,4,melbourne,-37.81934530415186,144.94838027345284,,-37.81934530415186_144.94838027345284_melbourne_google_maps_image,,-37.81934530415186_144.94838027345284_melbourne_google_satellite_image,,-37.81934530415186_144.94838027345284_melbourne_google_street_view_image,, -542182657,4,melbourne,-37.92765372866354,145.11924437501168,,-37.92765372866354_145.11924437501168_melbourne_google_maps_image,,-37.92765372866354_145.11924437501168_melbourne_google_satellite_image,,-37.92765372866354_145.11924437501168_melbourne_google_street_view_image,, -669188509,4,melbourne,-37.76919954441362,145.00099898338325,,-37.76919954441362_145.00099898338325_melbourne_google_maps_image,,-37.76919954441362_145.00099898338325_melbourne_google_satellite_image,,-37.76919954441362_145.00099898338325_melbourne_google_street_view_image,, -5242064718,4,melbourne,-37.92530842629705,145.11903162086756,,-37.92530842629705_145.11903162086756_melbourne_google_maps_image,,-37.92530842629705_145.11903162086756_melbourne_google_satellite_image,,-37.92530842629705_145.11903162086756_melbourne_google_street_view_image,, -4815465776,4,melbourne,-37.965617338651015,145.1768451249083,,-37.965617338651015_145.1768451249083_melbourne_google_maps_image,,-37.965617338651015_145.1768451249083_melbourne_google_satellite_image,,-37.965617338651015_145.1768451249083_melbourne_google_street_view_image,, -2440470792,4,melbourne,-37.70247117154502,144.96551332224362,,-37.70247117154502_144.96551332224362_melbourne_google_maps_image,,-37.70247117154502_144.96551332224362_melbourne_google_satellite_image,,-37.70247117154502_144.96551332224362_melbourne_google_street_view_image,, -5074739721,4,melbourne,-37.993491901656,145.07643030587695,,-37.993491901656_145.07643030587695_melbourne_google_maps_image,,-37.993491901656_145.07643030587695_melbourne_google_satellite_image,,-37.993491901656_145.07643030587695_melbourne_google_street_view_image,, -732904918,5,melbourne,-37.788656616545076,144.93011574196427,,-37.788656616545076_144.93011574196427_melbourne_google_maps_image,,-37.788656616545076_144.93011574196427_melbourne_google_satellite_image,,-37.788656616545076_144.93011574196427_melbourne_google_street_view_image,, -538980964,5,melbourne,-37.965842568787274,145.17358786253862,,-37.965842568787274_145.17358786253862_melbourne_google_maps_image,,-37.965842568787274_145.17358786253862_melbourne_google_satellite_image,,-37.965842568787274_145.17358786253862_melbourne_google_street_view_image,, -2526463421,5,melbourne,-37.68972658594108,144.92714089267045,,-37.68972658594108_144.92714089267045_melbourne_google_maps_image,,-37.68972658594108_144.92714089267045_melbourne_google_satellite_image,,-37.68972658594108_144.92714089267045_melbourne_google_street_view_image,, -7418267481,5,melbourne,-37.783799581911765,144.97737726029933,,-37.783799581911765_144.97737726029933_melbourne_google_maps_image,,-37.783799581911765_144.97737726029933_melbourne_google_satellite_image,,-37.783799581911765_144.97737726029933_melbourne_google_street_view_image,, -86072173,5,melbourne,-37.758688824633346,144.94506521121076,,-37.758688824633346_144.94506521121076_melbourne_google_maps_image,,-37.758688824633346_144.94506521121076_melbourne_google_satellite_image,,-37.758688824633346_144.94506521121076_melbourne_google_street_view_image,, -543294996,5,melbourne,-37.98234631349976,145.2025905410507,,-37.98234631349976_145.2025905410507_melbourne_google_maps_image,,-37.98234631349976_145.2025905410507_melbourne_google_satellite_image,,-37.98234631349976_145.2025905410507_melbourne_google_street_view_image,, -1021355276,5,melbourne,-37.876734360399205,144.99650112858146,,-37.876734360399205_144.99650112858146_melbourne_google_maps_image,,-37.876734360399205_144.99650112858146_melbourne_google_satellite_image,,-37.876734360399205_144.99650112858146_melbourne_google_street_view_image,, -2643285274,5,melbourne,-37.81029275974744,144.9627803038081,,-37.81029275974744_144.9627803038081_melbourne_google_maps_image,,-37.81029275974744_144.9627803038081_melbourne_google_satellite_image,,-37.81029275974744_144.9627803038081_melbourne_google_street_view_image,, -1055795509,5,melbourne,-37.8382631963956,144.98712328118418,,-37.8382631963956_144.98712328118418_melbourne_google_maps_image,,-37.8382631963956_144.98712328118418_melbourne_google_satellite_image,,-37.8382631963956_144.98712328118418_melbourne_google_street_view_image,, -4290861195,5,melbourne,-37.79591315942575,144.9801055340467,,-37.79591315942575_144.9801055340467_melbourne_google_maps_image,,-37.79591315942575_144.9801055340467_melbourne_google_satellite_image,,-37.79591315942575_144.9801055340467_melbourne_google_street_view_image,, -1283108236,1,odense,55.34792011185958,10.337093563112308,,55.34792011185958_10.337093563112308_odense_google_maps_image,,55.34792011185958_10.337093563112308_odense_google_satellite_image,,55.34792011185958_10.337093563112308_odense_google_street_view_image,, -88220818,1,odense,55.35698537792091,10.38920237091158,,55.35698537792091_10.38920237091158_odense_google_maps_image,,55.35698537792091_10.38920237091158_odense_google_satellite_image,,55.35698537792091_10.38920237091158_odense_google_street_view_image,, -317270318,1,odense,55.389719571397755,10.424143749905634,,55.389719571397755_10.424143749905634_odense_google_maps_image,,55.389719571397755_10.424143749905634_odense_google_satellite_image,,55.389719571397755_10.424143749905634_odense_google_street_view_image,, -2456944016,1,odense,55.41226529481542,10.327528790652767,,55.41226529481542_10.327528790652767_odense_google_maps_image,,55.41226529481542_10.327528790652767_odense_google_satellite_image,,55.41226529481542_10.327528790652767_odense_google_street_view_image,, -3012543239,1,odense,55.358625092224784,10.389705718524745,,55.358625092224784_10.389705718524745_odense_google_maps_image,,55.358625092224784_10.389705718524745_odense_google_satellite_image,,55.358625092224784_10.389705718524745_odense_google_street_view_image,, -161033374,1,odense,55.36546850628367,10.344337349314165,,55.36546850628367_10.344337349314165_odense_google_maps_image,,55.36546850628367_10.344337349314165_odense_google_satellite_image,,55.36546850628367_10.344337349314165_odense_google_street_view_image,, -229973016,1,odense,55.43697290000001,10.4109166,,55.43697290000001_10.4109166_odense_google_maps_image,,55.43697290000001_10.4109166_odense_google_satellite_image,,55.43697290000001_10.4109166_odense_google_street_view_image,, -807348060,1,odense,55.402584427365404,10.35736392725704,,55.402584427365404_10.35736392725704_odense_google_maps_image,,55.402584427365404_10.35736392725704_odense_google_satellite_image,,55.402584427365404_10.35736392725704_odense_google_street_view_image,, -89406334,1,odense,55.358402316762536,10.398537331770799,,55.358402316762536_10.398537331770799_odense_google_maps_image,,55.358402316762536_10.398537331770799_odense_google_satellite_image,,55.358402316762536_10.398537331770799_odense_google_street_view_image,, -219546252,1,odense,55.36342351937621,10.349999032740081,,55.36342351937621_10.349999032740081_odense_google_maps_image,,55.36342351937621_10.349999032740081_odense_google_satellite_image,,55.36342351937621_10.349999032740081_odense_google_street_view_image,, -3928398472,2,odense,55.38471435941438,10.424581290002582,,55.38471435941438_10.424581290002582_odense_google_maps_image,,55.38471435941438_10.424581290002582_odense_google_satellite_image,,55.38471435941438_10.424581290002582_odense_google_street_view_image,, -134774079,2,odense,55.41028260717352,10.4088896860233,,55.41028260717352_10.4088896860233_odense_google_maps_image,,55.41028260717352_10.4088896860233_odense_google_satellite_image,,55.41028260717352_10.4088896860233_odense_google_street_view_image,, -7082127136,2,odense,55.39343677839279,10.423358247772079,,55.39343677839279_10.423358247772079_odense_google_maps_image,,55.39343677839279_10.423358247772079_odense_google_satellite_image,,55.39343677839279_10.423358247772079_odense_google_street_view_image,, -3927606880,2,odense,55.38297894626153,10.427830021839734,,55.38297894626153_10.427830021839734_odense_google_maps_image,,55.38297894626153_10.427830021839734_odense_google_satellite_image,,55.38297894626153_10.427830021839734_odense_google_street_view_image,, -5370003679,2,odense,55.393092643220754,10.42139265652369,,55.393092643220754_10.42139265652369_odense_google_maps_image,,55.393092643220754_10.42139265652369_odense_google_satellite_image,,55.393092643220754_10.42139265652369_odense_google_street_view_image,, -2264700908,2,odense,55.38490548047652,10.424614695877118,,55.38490548047652_10.424614695877118_odense_google_maps_image,,55.38490548047652_10.424614695877118_odense_google_satellite_image,,55.38490548047652_10.424614695877118_odense_google_street_view_image,, -258430747,2,odense,55.36820093480394,10.357599753926149,,55.36820093480394_10.357599753926149_odense_google_maps_image,,55.36820093480394_10.357599753926149_odense_google_satellite_image,,55.36820093480394_10.357599753926149_odense_google_street_view_image,, -174302873,2,odense,55.418487699999986,10.4040199,,55.418487699999986_10.4040199_odense_google_maps_image,,55.418487699999986_10.4040199_odense_google_satellite_image,,55.418487699999986_10.4040199_odense_google_street_view_image,, -1137953620,2,odense,55.40786567141743,10.344627751900923,,55.40786567141743_10.344627751900923_odense_google_maps_image,,55.40786567141743_10.344627751900923_odense_google_satellite_image,,55.40786567141743_10.344627751900923_odense_google_street_view_image,, -97539705,2,odense,55.39255510772686,10.435510802877149,,55.39255510772686_10.435510802877149_odense_google_maps_image,,55.39255510772686_10.435510802877149_odense_google_satellite_image,,55.39255510772686_10.435510802877149_odense_google_street_view_image,, -7256183482,3,odense,55.398826749793706,10.376789979881721,,55.398826749793706_10.376789979881721_odense_google_maps_image,,55.398826749793706_10.376789979881721_odense_google_satellite_image,,55.398826749793706_10.376789979881721_odense_google_street_view_image,, -490530277,3,odense,55.373417105215644,10.37048242238291,,55.373417105215644_10.37048242238291_odense_google_maps_image,,55.373417105215644_10.37048242238291_odense_google_satellite_image,,55.373417105215644_10.37048242238291_odense_google_street_view_image,, -577338005,3,odense,55.414007104178076,10.396447058275141,,55.414007104178076_10.396447058275141_odense_google_maps_image,,55.414007104178076_10.396447058275141_odense_google_satellite_image,,55.414007104178076_10.396447058275141_odense_google_street_view_image,, -4800870647,3,odense,55.37516343786433,10.39858060544466,,55.37516343786433_10.39858060544466_odense_google_maps_image,,55.37516343786433_10.39858060544466_odense_google_satellite_image,,55.37516343786433_10.39858060544466_odense_google_street_view_image,, -3402665047,3,odense,55.405712259315315,10.39367508177815,,55.405712259315315_10.39367508177815_odense_google_maps_image,,55.405712259315315_10.39367508177815_odense_google_satellite_image,,55.405712259315315_10.39367508177815_odense_google_street_view_image,, -2508288968,3,odense,55.3792279,10.396774799999998,,55.3792279_10.396774799999998_odense_google_maps_image,,55.3792279_10.396774799999998_odense_google_satellite_image,,55.3792279_10.396774799999998_odense_google_street_view_image,, -664002868,3,odense,55.36754559515405,10.372733387061288,,55.36754559515405_10.372733387061288_odense_google_maps_image,,55.36754559515405_10.372733387061288_odense_google_satellite_image,,55.36754559515405_10.372733387061288_odense_google_street_view_image,, -289331240,3,odense,55.37481758712163,10.395791147973268,,55.37481758712163_10.395791147973268_odense_google_maps_image,,55.37481758712163_10.395791147973268_odense_google_satellite_image,,55.37481758712163_10.395791147973268_odense_google_street_view_image,, -71147650,3,odense,55.37796887832027,10.404359797941561,,55.37796887832027_10.404359797941561_odense_google_maps_image,,55.37796887832027_10.404359797941561_odense_google_satellite_image,,55.37796887832027_10.404359797941561_odense_google_street_view_image,, -1357609272,3,odense,55.40956482526284,10.338716197119354,,55.40956482526284_10.338716197119354_odense_google_maps_image,,55.40956482526284_10.338716197119354_odense_google_satellite_image,,55.40956482526284_10.338716197119354_odense_google_street_view_image,, -141959434,4,odense,55.39636330542289,10.349145626895728,,55.39636330542289_10.349145626895728_odense_google_maps_image,,55.39636330542289_10.349145626895728_odense_google_satellite_image,,55.39636330542289_10.349145626895728_odense_google_street_view_image,, -133965327,4,odense,55.40660427171952,10.441997371137127,,55.40660427171952_10.441997371137127_odense_google_maps_image,,55.40660427171952_10.441997371137127_odense_google_satellite_image,,55.40660427171952_10.441997371137127_odense_google_street_view_image,, -144649200,4,odense,55.40458537249529,10.340731214767281,,55.40458537249529_10.340731214767281_odense_google_maps_image,,55.40458537249529_10.340731214767281_odense_google_satellite_image,,55.40458537249529_10.340731214767281_odense_google_street_view_image,, -7775571092,4,odense,55.37980759999999,10.39691,,55.37980759999999_10.39691_odense_google_maps_image,,55.37980759999999_10.39691_odense_google_satellite_image,,55.37980759999999_10.39691_odense_google_street_view_image,, -3402665079,4,odense,55.378325958557454,10.379682787648651,,55.378325958557454_10.379682787648651_odense_google_maps_image,,55.378325958557454_10.379682787648651_odense_google_satellite_image,,55.378325958557454_10.379682787648651_odense_google_street_view_image,, -1783413181,4,odense,55.39797260000001,10.387632199999999,,55.39797260000001_10.387632199999999_odense_google_maps_image,,55.39797260000001_10.387632199999999_odense_google_satellite_image,,55.39797260000001_10.387632199999999_odense_google_street_view_image,, -152978976,4,odense,55.3937052,10.3657946,,55.3937052_10.3657946_odense_google_maps_image,,55.3937052_10.3657946_odense_google_satellite_image,,55.3937052_10.3657946_odense_google_street_view_image,, -341660677,4,odense,55.39451591962425,10.348111039300287,,55.39451591962425_10.348111039300287_odense_google_maps_image,,55.39451591962425_10.348111039300287_odense_google_satellite_image,,55.39451591962425_10.348111039300287_odense_google_street_view_image,, -92414361,4,odense,55.39466502707325,10.376702309599974,,55.39466502707325_10.376702309599974_odense_google_maps_image,,55.39466502707325_10.376702309599974_odense_google_satellite_image,,55.39466502707325_10.376702309599974_odense_google_street_view_image,, -5334645502,4,odense,55.400597810181125,10.391263514199865,,55.400597810181125_10.391263514199865_odense_google_maps_image,,55.400597810181125_10.391263514199865_odense_google_satellite_image,,55.400597810181125_10.391263514199865_odense_google_street_view_image,, -219651198,5,odense,55.39318647951937,10.399409284886316,,55.39318647951937_10.399409284886316_odense_google_maps_image,,55.39318647951937_10.399409284886316_odense_google_satellite_image,,55.39318647951937_10.399409284886316_odense_google_street_view_image,, -340216483,5,odense,55.396768997021745,10.38924129739305,,55.396768997021745_10.38924129739305_odense_google_maps_image,,55.396768997021745_10.38924129739305_odense_google_satellite_image,,55.396768997021745_10.38924129739305_odense_google_street_view_image,, -663192816,5,odense,55.39655484407623,10.382942928365717,,55.39655484407623_10.382942928365717_odense_google_maps_image,,55.39655484407623_10.382942928365717_odense_google_satellite_image,,55.39655484407623_10.382942928365717_odense_google_street_view_image,, -3402665046,5,odense,55.39274204754997,10.397320827586658,,55.39274204754997_10.397320827586658_odense_google_maps_image,,55.39274204754997_10.397320827586658_odense_google_satellite_image,,55.39274204754997_10.397320827586658_odense_google_street_view_image,, -6708833722,5,odense,55.397415356711164,10.391980602838114,,55.397415356711164_10.391980602838114_odense_google_maps_image,,55.397415356711164_10.391980602838114_odense_google_satellite_image,,55.397415356711164_10.391980602838114_odense_google_street_view_image,, -311607276,5,odense,55.39910978457271,10.404734045213733,,55.39910978457271_10.404734045213733_odense_google_maps_image,,55.39910978457271_10.404734045213733_odense_google_satellite_image,,55.39910978457271_10.404734045213733_odense_google_street_view_image,, -339817137,5,odense,55.393446770474064,10.395706501034262,,55.393446770474064_10.395706501034262_odense_google_maps_image,,55.393446770474064_10.395706501034262_odense_google_satellite_image,,55.393446770474064_10.395706501034262_odense_google_street_view_image,, -4516653659,5,odense,55.390739942959605,10.387965348677184,,55.390739942959605_10.387965348677184_odense_google_maps_image,,55.390739942959605_10.387965348677184_odense_google_satellite_image,,55.390739942959605_10.387965348677184_odense_google_street_view_image,, -779097661,5,odense,55.39405271165437,10.37678395876849,,55.39405271165437_10.37678395876849_odense_google_maps_image,,55.39405271165437_10.37678395876849_odense_google_satellite_image,,55.39405271165437_10.37678395876849_odense_google_street_view_image,, -117632444,5,odense,55.39217573760271,10.407376244769512,,55.39217573760271_10.407376244769512_odense_google_maps_image,,55.39217573760271_10.407376244769512_odense_google_satellite_image,,55.39217573760271_10.407376244769512_odense_google_street_view_image,, -2747734898,1,olomouc,49.604812171506396,17.240407827541382,,49.604812171506396_17.240407827541382_olomouc_google_maps_image,,49.604812171506396_17.240407827541382_olomouc_google_satellite_image,,49.604812171506396_17.240407827541382_olomouc_google_street_view_image,, -35897981,1,olomouc,49.57848124287224,17.242551859627667,,49.57848124287224_17.242551859627667_olomouc_google_maps_image,,49.57848124287224_17.242551859627667_olomouc_google_satellite_image,,49.57848124287224_17.242551859627667_olomouc_google_street_view_image,, -35898108,1,olomouc,49.57583739752839,17.247996707801693,,49.57583739752839_17.247996707801693_olomouc_google_maps_image,,49.57583739752839_17.247996707801693_olomouc_google_satellite_image,,49.57583739752839_17.247996707801693_olomouc_google_street_view_image,, -5975052178,1,olomouc,49.5745695556657,17.24950289035961,,49.5745695556657_17.24950289035961_olomouc_google_maps_image,,49.5745695556657_17.24950289035961_olomouc_google_satellite_image,,49.5745695556657_17.24950289035961_olomouc_google_street_view_image,, -899808007,1,olomouc,49.60232082212211,17.243655172780194,,49.60232082212211_17.243655172780194_olomouc_google_maps_image,,49.60232082212211_17.243655172780194_olomouc_google_satellite_image,,49.60232082212211_17.243655172780194_olomouc_google_street_view_image,, -5975062744,1,olomouc,49.57450046829268,17.249439073786878,,49.57450046829268_17.249439073786878_olomouc_google_maps_image,,49.57450046829268_17.249439073786878_olomouc_google_satellite_image,,49.57450046829268_17.249439073786878_olomouc_google_street_view_image,, -5329662824,1,olomouc,49.59222078355007,17.250328994335725,,49.59222078355007_17.250328994335725_olomouc_google_maps_image,,49.59222078355007_17.250328994335725_olomouc_google_satellite_image,,49.59222078355007_17.250328994335725_olomouc_google_street_view_image,, -5329663121,1,olomouc,49.5925491342712,17.250633672617568,,49.5925491342712_17.250633672617568_olomouc_google_maps_image,,49.5925491342712_17.250633672617568_olomouc_google_satellite_image,,49.5925491342712_17.250633672617568_olomouc_google_street_view_image,, -5975022069,1,olomouc,49.57466727532713,17.249411640682613,,49.57466727532713_17.249411640682613_olomouc_google_maps_image,,49.57466727532713_17.249411640682613_olomouc_google_satellite_image,,49.57466727532713_17.249411640682613_olomouc_google_street_view_image,, -670812040,1,olomouc,49.59291026294765,17.249156370959074,,49.59291026294765_17.249156370959074_olomouc_google_maps_image,,49.59291026294765_17.249156370959074_olomouc_google_satellite_image,,49.59291026294765_17.249156370959074_olomouc_google_street_view_image,, -437712834,2,olomouc,49.58893748049946,17.254124162177845,,49.58893748049946_17.254124162177845_olomouc_google_maps_image,,49.58893748049946_17.254124162177845_olomouc_google_satellite_image,,49.58893748049946_17.254124162177845_olomouc_google_street_view_image,, -1102132022,2,olomouc,49.589722728948054,17.254625045477532,,49.589722728948054_17.254625045477532_olomouc_google_maps_image,,49.589722728948054_17.254625045477532_olomouc_google_satellite_image,,49.589722728948054_17.254625045477532_olomouc_google_street_view_image,, -16914580,2,olomouc,49.58918031631491,17.25577818636671,,49.58918031631491_17.25577818636671_olomouc_google_maps_image,,49.58918031631491_17.25577818636671_olomouc_google_satellite_image,,49.58918031631491_17.25577818636671_olomouc_google_street_view_image,, -58530469,2,olomouc,49.6032266,17.2782117,,49.6032266_17.2782117_olomouc_google_maps_image,,49.6032266_17.2782117_olomouc_google_satellite_image,,49.6032266_17.2782117_olomouc_google_street_view_image,, -57858060,2,olomouc,49.58937216836056,17.254908394340816,,49.58937216836056_17.254908394340816_olomouc_google_maps_image,,49.58937216836056_17.254908394340816_olomouc_google_satellite_image,,49.58937216836056_17.254908394340816_olomouc_google_street_view_image,, -898627364,2,olomouc,49.5770818,17.2557422,,49.5770818_17.2557422_olomouc_google_maps_image,,49.5770818_17.2557422_olomouc_google_satellite_image,,49.5770818_17.2557422_olomouc_google_street_view_image,, -4744618108,2,olomouc,49.57673122722261,17.25425767387718,,49.57673122722261_17.25425767387718_olomouc_google_maps_image,,49.57673122722261_17.25425767387718_olomouc_google_satellite_image,,49.57673122722261_17.25425767387718_olomouc_google_street_view_image,, -3994191985,2,olomouc,49.601713438553666,17.278196798416225,,49.601713438553666_17.278196798416225_olomouc_google_maps_image,,49.601713438553666_17.278196798416225_olomouc_google_satellite_image,,49.601713438553666_17.278196798416225_olomouc_google_street_view_image,, -899821291,2,olomouc,49.59423247400176,17.250672049735563,,49.59423247400176_17.250672049735563_olomouc_google_maps_image,,49.59423247400176_17.250672049735563_olomouc_google_satellite_image,,49.59423247400176_17.250672049735563_olomouc_google_street_view_image,, -898627336,2,olomouc,49.5767211944337,17.25674029708548,,49.5767211944337_17.25674029708548_olomouc_google_maps_image,,49.5767211944337_17.25674029708548_olomouc_google_satellite_image,,49.5767211944337_17.25674029708548_olomouc_google_street_view_image,, -5124119942,3,olomouc,49.59152874341055,17.253168307870084,,49.59152874341055_17.253168307870084_olomouc_google_maps_image,,49.59152874341055_17.253168307870084_olomouc_google_satellite_image,,49.59152874341055_17.253168307870084_olomouc_google_street_view_image,, -2213447371,3,olomouc,49.59550163539226,17.26679502622463,,49.59550163539226_17.26679502622463_olomouc_google_maps_image,,49.59550163539226_17.26679502622463_olomouc_google_satellite_image,,49.59550163539226_17.26679502622463_olomouc_google_street_view_image,, -685779307,3,olomouc,49.59734327828507,17.2459812445235,,49.59734327828507_17.2459812445235_olomouc_google_maps_image,,49.59734327828507_17.2459812445235_olomouc_google_satellite_image,,49.59734327828507_17.2459812445235_olomouc_google_street_view_image,, -937891405,3,olomouc,49.5950652,17.2499469,,49.5950652_17.2499469_olomouc_google_maps_image,,49.5950652_17.2499469_olomouc_google_satellite_image,,49.5950652_17.2499469_olomouc_google_street_view_image,, -1133601794,3,olomouc,49.5950652,17.2499469,,49.5950652_17.2499469_olomouc_google_maps_image,,49.5950652_17.2499469_olomouc_google_satellite_image,,49.5950652_17.2499469_olomouc_google_street_view_image,, -2205115791,3,olomouc,49.59488288493668,17.26902430833058,,49.59488288493668_17.26902430833058_olomouc_google_maps_image,,49.59488288493668_17.26902430833058_olomouc_google_satellite_image,,49.59488288493668_17.26902430833058_olomouc_google_street_view_image,, -3618080553,3,olomouc,49.590364400000006,17.2702625,,49.590364400000006_17.2702625_olomouc_google_maps_image,,49.590364400000006_17.2702625_olomouc_google_satellite_image,,49.590364400000006_17.2702625_olomouc_google_street_view_image,, -4032937693,3,olomouc,49.58623959999999,17.2578531,,49.58623959999999_17.2578531_olomouc_google_maps_image,,49.58623959999999_17.2578531_olomouc_google_satellite_image,,49.58623959999999_17.2578531_olomouc_google_street_view_image,, -5318046191,3,olomouc,49.58718568820402,17.258488438630604,,49.58718568820402_17.258488438630604_olomouc_google_maps_image,,49.58718568820402_17.258488438630604_olomouc_google_satellite_image,,49.58718568820402_17.258488438630604_olomouc_google_street_view_image,, -5957431389,3,olomouc,49.58194865076289,17.23693947554527,,49.58194865076289_17.23693947554527_olomouc_google_maps_image,,49.58194865076289_17.23693947554527_olomouc_google_satellite_image,,49.58194865076289_17.23693947554527_olomouc_google_street_view_image,, -5329662833,4,olomouc,49.59260223866954,17.252387610096147,,49.59260223866954_17.252387610096147_olomouc_google_maps_image,,49.59260223866954_17.252387610096147_olomouc_google_satellite_image,,49.59260223866954_17.252387610096147_olomouc_google_street_view_image,, -5329662834,4,olomouc,49.59210778146773,17.252185846085666,,49.59210778146773_17.252185846085666_olomouc_google_maps_image,,49.59210778146773_17.252185846085666_olomouc_google_satellite_image,,49.59210778146773_17.252185846085666_olomouc_google_street_view_image,, -5329663724,4,olomouc,49.59326302780411,17.25184522573286,,49.59326302780411_17.25184522573286_olomouc_google_maps_image,,49.59326302780411_17.25184522573286_olomouc_google_satellite_image,,49.59326302780411_17.25184522573286_olomouc_google_street_view_image,, -900953095,4,olomouc,49.59928103376165,17.27266567021335,,49.59928103376165_17.27266567021335_olomouc_google_maps_image,,49.59928103376165_17.27266567021335_olomouc_google_satellite_image,,49.59928103376165_17.27266567021335_olomouc_google_street_view_image,, -3105589733,4,olomouc,49.58684579384117,17.238899787926535,,49.58684579384117_17.238899787926535_olomouc_google_maps_image,,49.58684579384117_17.238899787926535_olomouc_google_satellite_image,,49.58684579384117_17.238899787926535_olomouc_google_street_view_image,, -2205115971,4,olomouc,49.5939981736539,17.272274522436376,,49.5939981736539_17.272274522436376_olomouc_google_maps_image,,49.5939981736539_17.272274522436376_olomouc_google_satellite_image,,49.5939981736539_17.272274522436376_olomouc_google_street_view_image,, -2260266180,4,olomouc,49.59109453317078,17.27161874374886,,49.59109453317078_17.27161874374886_olomouc_google_maps_image,,49.59109453317078_17.27161874374886_olomouc_google_satellite_image,,49.59109453317078_17.27161874374886_olomouc_google_street_view_image,, -53034215,4,olomouc,49.59879279999999,17.2732146,,49.59879279999999_17.2732146_olomouc_google_maps_image,,49.59879279999999_17.2732146_olomouc_google_satellite_image,,49.59879279999999_17.2732146_olomouc_google_street_view_image,, -5329662829,4,olomouc,49.59278907503999,17.252117820538466,,49.59278907503999_17.252117820538466_olomouc_google_maps_image,,49.59278907503999_17.252117820538466_olomouc_google_satellite_image,,49.59278907503999_17.252117820538466_olomouc_google_street_view_image,, -3623128228,4,olomouc,49.58772997053009,17.270463406769185,,49.58772997053009_17.270463406769185_olomouc_google_maps_image,,49.58772997053009_17.270463406769185_olomouc_google_satellite_image,,49.58772997053009_17.270463406769185_olomouc_google_street_view_image,, -712691848,5,olomouc,49.58804865340112,17.27195182054297,,49.58804865340112_17.27195182054297_olomouc_google_maps_image,,49.58804865340112_17.27195182054297_olomouc_google_satellite_image,,49.58804865340112_17.27195182054297_olomouc_google_street_view_image,, -1711820823,5,olomouc,49.59632127249841,17.248452273013537,,49.59632127249841_17.248452273013537_olomouc_google_maps_image,,49.59632127249841_17.248452273013537_olomouc_google_satellite_image,,49.59632127249841_17.248452273013537_olomouc_google_street_view_image,, -58280569,5,olomouc,49.59114542391838,17.235124343510982,,49.59114542391838_17.235124343510982_olomouc_google_maps_image,,49.59114542391838_17.235124343510982_olomouc_google_satellite_image,,49.59114542391838_17.235124343510982_olomouc_google_street_view_image,, -2213447427,5,olomouc,49.59311039820254,17.275046339110556,,49.59311039820254_17.275046339110556_olomouc_google_maps_image,,49.59311039820254_17.275046339110556_olomouc_google_satellite_image,,49.59311039820254_17.275046339110556_olomouc_google_street_view_image,, -2213447430,5,olomouc,49.59327081755778,17.274851643527388,,49.59327081755778_17.274851643527388_olomouc_google_maps_image,,49.59327081755778_17.274851643527388_olomouc_google_satellite_image,,49.59327081755778_17.274851643527388_olomouc_google_street_view_image,, -1574134061,5,olomouc,49.59541331427761,17.249187019212034,,49.59541331427761_17.249187019212034_olomouc_google_maps_image,,49.59541331427761_17.249187019212034_olomouc_google_satellite_image,,49.59541331427761_17.249187019212034_olomouc_google_street_view_image,, -2260266181,5,olomouc,49.59236819822377,17.27805318667824,,49.59236819822377_17.27805318667824_olomouc_google_maps_image,,49.59236819822377_17.27805318667824_olomouc_google_satellite_image,,49.59236819822377_17.27805318667824_olomouc_google_street_view_image,, -2688541541,5,olomouc,49.59283688161055,17.277450812419456,,49.59283688161055_17.277450812419456_olomouc_google_maps_image,,49.59283688161055_17.277450812419456_olomouc_google_satellite_image,,49.59283688161055_17.277450812419456_olomouc_google_street_view_image,, -58280836,5,olomouc,49.5909535381399,17.23393396991465,,49.5909535381399_17.23393396991465_olomouc_google_maps_image,,49.5909535381399_17.23393396991465_olomouc_google_satellite_image,,49.5909535381399_17.23393396991465_olomouc_google_street_view_image,, -2260266177,5,olomouc,49.59283823419789,17.277450108854687,,49.59283823419789_17.277450108854687_olomouc_google_maps_image,,49.59283823419789_17.277450108854687_olomouc_google_satellite_image,,49.59283823419789_17.277450108854687_olomouc_google_street_view_image,, -329033172,1,sao_paulo,-23.541697900000006,-46.62917680000001,,-23.541697900000006_-46.62917680000001_sao_paulo_google_maps_image,,-23.541697900000006_-46.62917680000001_sao_paulo_google_satellite_image,,-23.541697900000006_-46.62917680000001_sao_paulo_google_street_view_image,, --4602922,1,sao_paulo,-23.54177592356298,-46.62918725011454,,-23.54177592356298_-46.62918725011454_sao_paulo_google_maps_image,,-23.54177592356298_-46.62918725011454_sao_paulo_google_satellite_image,,-23.54177592356298_-46.62918725011454_sao_paulo_google_street_view_image,, --4602968,1,sao_paulo,-23.541263431540635,-46.62919094379415,,-23.541263431540635_-46.62919094379415_sao_paulo_google_maps_image,,-23.541263431540635_-46.62919094379415_sao_paulo_google_satellite_image,,-23.541263431540635_-46.62919094379415_sao_paulo_google_street_view_image,, -329033179,1,sao_paulo,-23.541263241218296,-46.62935885991646,,-23.541263241218296_-46.62935885991646_sao_paulo_google_maps_image,,-23.541263241218296_-46.62935885991646_sao_paulo_google_satellite_image,,-23.541263241218296_-46.62935885991646_sao_paulo_google_street_view_image,, --4602885,1,sao_paulo,-23.541401725530154,-46.62921577989605,,-23.541401725530154_-46.62921577989605_sao_paulo_google_maps_image,,-23.541401725530154_-46.62921577989605_sao_paulo_google_satellite_image,,-23.541401725530154_-46.62921577989605_sao_paulo_google_street_view_image,, -690742306,1,sao_paulo,-23.57572793761542,-46.501841843859125,,-23.57572793761542_-46.501841843859125_sao_paulo_google_maps_image,,-23.57572793761542_-46.501841843859125_sao_paulo_google_satellite_image,,-23.57572793761542_-46.501841843859125_sao_paulo_google_street_view_image,, --4602916,1,sao_paulo,-23.54200894840106,-46.62989859927149,,-23.54200894840106_-46.62989859927149_sao_paulo_google_maps_image,,-23.54200894840106_-46.62989859927149_sao_paulo_google_satellite_image,,-23.54200894840106_-46.62989859927149_sao_paulo_google_street_view_image,, --4602892,1,sao_paulo,-23.541387718949974,-46.629698577919335,,-23.541387718949974_-46.629698577919335_sao_paulo_google_maps_image,,-23.541387718949974_-46.629698577919335_sao_paulo_google_satellite_image,,-23.541387718949974_-46.629698577919335_sao_paulo_google_street_view_image,, --4603050,1,sao_paulo,-23.54146898983592,-46.629338852141224,,-23.54146898983592_-46.629338852141224_sao_paulo_google_maps_image,,-23.54146898983592_-46.629338852141224_sao_paulo_google_satellite_image,,-23.54146898983592_-46.629338852141224_sao_paulo_google_street_view_image,, --4603065,1,sao_paulo,-23.541875969369872,-46.62981831820935,,-23.541875969369872_-46.62981831820935_sao_paulo_google_maps_image,,-23.541875969369872_-46.62981831820935_sao_paulo_google_satellite_image,,-23.541875969369872_-46.62981831820935_sao_paulo_google_street_view_image,, -6561340944,2,sao_paulo,-23.550898910168215,-46.622177411892835,,-23.550898910168215_-46.622177411892835_sao_paulo_google_maps_image,,-23.550898910168215_-46.622177411892835_sao_paulo_google_satellite_image,,-23.550898910168215_-46.622177411892835_sao_paulo_google_street_view_image,, -6449378140,2,sao_paulo,-23.573809399630605,-46.55747832528324,,-23.573809399630605_-46.55747832528324_sao_paulo_google_maps_image,,-23.573809399630605_-46.55747832528324_sao_paulo_google_satellite_image,,-23.573809399630605_-46.55747832528324_sao_paulo_google_street_view_image,, -37498469,2,sao_paulo,-23.5624739,-46.5018372,,-23.5624739_-46.5018372_sao_paulo_google_maps_image,,-23.5624739_-46.5018372_sao_paulo_google_satellite_image,,-23.5624739_-46.5018372_sao_paulo_google_street_view_image,, -4572425831,2,sao_paulo,-23.569414416518953,-46.566270195061705,,-23.569414416518953_-46.566270195061705_sao_paulo_google_maps_image,,-23.569414416518953_-46.566270195061705_sao_paulo_google_satellite_image,,-23.569414416518953_-46.566270195061705_sao_paulo_google_street_view_image,, -5462421680,2,sao_paulo,-23.474372547965906,-46.589928135370805,,-23.474372547965906_-46.589928135370805_sao_paulo_google_maps_image,,-23.474372547965906_-46.589928135370805_sao_paulo_google_satellite_image,,-23.474372547965906_-46.589928135370805_sao_paulo_google_street_view_image,, -4371222245,2,sao_paulo,-23.611125245665434,-46.70482719615664,,-23.611125245665434_-46.70482719615664_sao_paulo_google_maps_image,,-23.611125245665434_-46.70482719615664_sao_paulo_google_satellite_image,,-23.611125245665434_-46.70482719615664_sao_paulo_google_street_view_image,, -914049517,2,sao_paulo,-23.55495386829887,-46.685737772839346,,-23.55495386829887_-46.685737772839346_sao_paulo_google_maps_image,,-23.55495386829887_-46.685737772839346_sao_paulo_google_satellite_image,,-23.55495386829887_-46.685737772839346_sao_paulo_google_street_view_image,, -3679556542,2,sao_paulo,-23.44655295808692,-46.690111283829516,,-23.44655295808692_-46.690111283829516_sao_paulo_google_maps_image,,-23.44655295808692_-46.690111283829516_sao_paulo_google_satellite_image,,-23.44655295808692_-46.690111283829516_sao_paulo_google_street_view_image,, -341043259,2,sao_paulo,-23.55438666878408,-46.49292047048889,,-23.55438666878408_-46.49292047048889_sao_paulo_google_maps_image,,-23.55438666878408_-46.49292047048889_sao_paulo_google_satellite_image,,-23.55438666878408_-46.49292047048889_sao_paulo_google_street_view_image,, -2299046831,2,sao_paulo,-23.599100857170892,-46.68336319123428,,-23.599100857170892_-46.68336319123428_sao_paulo_google_maps_image,,-23.599100857170892_-46.68336319123428_sao_paulo_google_satellite_image,,-23.599100857170892_-46.68336319123428_sao_paulo_google_street_view_image,, -4527458049,3,sao_paulo,-23.577414499999996,-46.7311945,,-23.577414499999996_-46.7311945_sao_paulo_google_maps_image,,-23.577414499999996_-46.7311945_sao_paulo_google_satellite_image,,-23.577414499999996_-46.7311945_sao_paulo_google_street_view_image,, -4103932589,3,sao_paulo,-23.68545932233089,-46.68070510295093,,-23.68545932233089_-46.68070510295093_sao_paulo_google_maps_image,,-23.68545932233089_-46.68070510295093_sao_paulo_google_satellite_image,,-23.68545932233089_-46.68070510295093_sao_paulo_google_street_view_image,, -2677539172,3,sao_paulo,-23.5056546332568,-46.594358472104076,,-23.5056546332568_-46.594358472104076_sao_paulo_google_maps_image,,-23.5056546332568_-46.594358472104076_sao_paulo_google_satellite_image,,-23.5056546332568_-46.594358472104076_sao_paulo_google_street_view_image,, -3969229726,3,sao_paulo,-23.539320900046107,-46.59644127660393,,-23.539320900046107_-46.59644127660393_sao_paulo_google_maps_image,,-23.539320900046107_-46.59644127660393_sao_paulo_google_satellite_image,,-23.539320900046107_-46.59644127660393_sao_paulo_google_street_view_image,, -2344707800,3,sao_paulo,-23.52609009985865,-46.52701091189782,,-23.52609009985865_-46.52701091189782_sao_paulo_google_maps_image,,-23.52609009985865_-46.52701091189782_sao_paulo_google_satellite_image,,-23.52609009985865_-46.52701091189782_sao_paulo_google_street_view_image,, -5294381070,3,sao_paulo,-23.583613828914224,-46.627600003297104,,-23.583613828914224_-46.627600003297104_sao_paulo_google_maps_image,,-23.583613828914224_-46.627600003297104_sao_paulo_google_satellite_image,,-23.583613828914224_-46.627600003297104_sao_paulo_google_street_view_image,, -681392468,3,sao_paulo,-23.574096945327483,-46.51326008140862,,-23.574096945327483_-46.51326008140862_sao_paulo_google_maps_image,,-23.574096945327483_-46.51326008140862_sao_paulo_google_satellite_image,,-23.574096945327483_-46.51326008140862_sao_paulo_google_street_view_image,, -619217884,3,sao_paulo,-23.60207530443384,-46.636627422869175,,-23.60207530443384_-46.636627422869175_sao_paulo_google_maps_image,,-23.60207530443384_-46.636627422869175_sao_paulo_google_satellite_image,,-23.60207530443384_-46.636627422869175_sao_paulo_google_street_view_image,, -4145597085,3,sao_paulo,-23.48528574773012,-46.641177456458216,,-23.48528574773012_-46.641177456458216_sao_paulo_google_maps_image,,-23.48528574773012_-46.641177456458216_sao_paulo_google_satellite_image,,-23.48528574773012_-46.641177456458216_sao_paulo_google_street_view_image,, -277075163,3,sao_paulo,-23.60222632102584,-46.63991047872621,,-23.60222632102584_-46.63991047872621_sao_paulo_google_maps_image,,-23.60222632102584_-46.63991047872621_sao_paulo_google_satellite_image,,-23.60222632102584_-46.63991047872621_sao_paulo_google_street_view_image,, -431438184,4,sao_paulo,-23.572964943936835,-46.636357214748166,,-23.572964943936835_-46.636357214748166_sao_paulo_google_maps_image,,-23.572964943936835_-46.636357214748166_sao_paulo_google_satellite_image,,-23.572964943936835_-46.636357214748166_sao_paulo_google_street_view_image,, -2421036956,4,sao_paulo,-23.605013777188894,-46.65894603260714,,-23.605013777188894_-46.65894603260714_sao_paulo_google_maps_image,,-23.605013777188894_-46.65894603260714_sao_paulo_google_satellite_image,,-23.605013777188894_-46.65894603260714_sao_paulo_google_street_view_image,, -2873424014,4,sao_paulo,-23.450483141013507,-46.572483528344215,,-23.450483141013507_-46.572483528344215_sao_paulo_google_maps_image,,-23.450483141013507_-46.572483528344215_sao_paulo_google_satellite_image,,-23.450483141013507_-46.572483528344215_sao_paulo_google_street_view_image,, -5880426362,4,sao_paulo,-23.58310095453419,-46.409459429350875,,-23.58310095453419_-46.409459429350875_sao_paulo_google_maps_image,,-23.58310095453419_-46.409459429350875_sao_paulo_google_satellite_image,,-23.58310095453419_-46.409459429350875_sao_paulo_google_street_view_image,, -2037560043,4,sao_paulo,-23.632230234847068,-46.60470295646081,,-23.632230234847068_-46.60470295646081_sao_paulo_google_maps_image,,-23.632230234847068_-46.60470295646081_sao_paulo_google_satellite_image,,-23.632230234847068_-46.60470295646081_sao_paulo_google_street_view_image,, -4715781594,4,sao_paulo,-23.696892446160973,-46.779430842643656,,-23.696892446160973_-46.779430842643656_sao_paulo_google_maps_image,,-23.696892446160973_-46.779430842643656_sao_paulo_google_satellite_image,,-23.696892446160973_-46.779430842643656_sao_paulo_google_street_view_image,, -4514018990,4,sao_paulo,-23.700540101159486,-46.781567273963425,,-23.700540101159486_-46.781567273963425_sao_paulo_google_maps_image,,-23.700540101159486_-46.781567273963425_sao_paulo_google_satellite_image,,-23.700540101159486_-46.781567273963425_sao_paulo_google_street_view_image,, -3588207435,4,sao_paulo,-23.47502706313275,-46.57015886919148,,-23.47502706313275_-46.57015886919148_sao_paulo_google_maps_image,,-23.47502706313275_-46.57015886919148_sao_paulo_google_satellite_image,,-23.47502706313275_-46.57015886919148_sao_paulo_google_street_view_image,, -3928633744,4,sao_paulo,-23.487190083353465,-46.568585164594424,,-23.487190083353465_-46.568585164594424_sao_paulo_google_maps_image,,-23.487190083353465_-46.568585164594424_sao_paulo_google_satellite_image,,-23.487190083353465_-46.568585164594424_sao_paulo_google_street_view_image,, -5918601795,4,sao_paulo,-23.490527460999356,-46.58586395016518,,-23.490527460999356_-46.58586395016518_sao_paulo_google_maps_image,,-23.490527460999356_-46.58586395016518_sao_paulo_google_satellite_image,,-23.490527460999356_-46.58586395016518_sao_paulo_google_street_view_image,, -635319387,5,sao_paulo,-23.563935856567845,-46.68321969342855,,-23.563935856567845_-46.68321969342855_sao_paulo_google_maps_image,,-23.563935856567845_-46.68321969342855_sao_paulo_google_satellite_image,,-23.563935856567845_-46.68321969342855_sao_paulo_google_street_view_image,, -5272030990,5,sao_paulo,-23.684822710580775,-46.64767419219624,,-23.684822710580775_-46.64767419219624_sao_paulo_google_maps_image,,-23.684822710580775_-46.64767419219624_sao_paulo_google_satellite_image,,-23.684822710580775_-46.64767419219624_sao_paulo_google_street_view_image,, -4964023963,5,sao_paulo,-23.566741186660213,-46.649927663038,,-23.566741186660213_-46.649927663038_sao_paulo_google_maps_image,,-23.566741186660213_-46.649927663038_sao_paulo_google_satellite_image,,-23.566741186660213_-46.649927663038_sao_paulo_google_street_view_image,, --3963497,5,sao_paulo,-23.47931670278812,-46.643891453137506,,-23.47931670278812_-46.643891453137506_sao_paulo_google_maps_image,,-23.47931670278812_-46.643891453137506_sao_paulo_google_satellite_image,,-23.47931670278812_-46.643891453137506_sao_paulo_google_street_view_image,, -6017776056,5,sao_paulo,-23.626488903990104,-46.63367355388614,,-23.626488903990104_-46.63367355388614_sao_paulo_google_maps_image,,-23.626488903990104_-46.63367355388614_sao_paulo_google_satellite_image,,-23.626488903990104_-46.63367355388614_sao_paulo_google_street_view_image,, -143331528,5,sao_paulo,-23.646366588657976,-46.75730525326663,,-23.646366588657976_-46.75730525326663_sao_paulo_google_maps_image,,-23.646366588657976_-46.75730525326663_sao_paulo_google_satellite_image,,-23.646366588657976_-46.75730525326663_sao_paulo_google_street_view_image,, -3919726882,5,sao_paulo,-23.47738617778817,-46.58216406628867,,-23.47738617778817_-46.58216406628867_sao_paulo_google_maps_image,,-23.47738617778817_-46.58216406628867_sao_paulo_google_satellite_image,,-23.47738617778817_-46.58216406628867_sao_paulo_google_street_view_image,, -2810275124,5,sao_paulo,-23.552828087058273,-46.64556244829638,,-23.552828087058273_-46.64556244829638_sao_paulo_google_maps_image,,-23.552828087058273_-46.64556244829638_sao_paulo_google_satellite_image,,-23.552828087058273_-46.64556244829638_sao_paulo_google_street_view_image,, -2269730180,5,sao_paulo,-23.5344953928889,-46.68638112679506,,-23.5344953928889_-46.68638112679506_sao_paulo_google_maps_image,,-23.5344953928889_-46.68638112679506_sao_paulo_google_satellite_image,,-23.5344953928889_-46.68638112679506_sao_paulo_google_street_view_image,, -3527356819,5,sao_paulo,-23.55308343146685,-46.654593334760705,,-23.55308343146685_-46.654593334760705_sao_paulo_google_maps_image,,-23.55308343146685_-46.654593334760705_sao_paulo_google_satellite_image,,-23.55308343146685_-46.654593334760705_sao_paulo_google_street_view_image,, -129591176,1,phoenix,33.49618387083415,-112.17273491252895,,33.49618387083415_-112.17273491252895_phoenix_google_maps_image,,33.49618387083415_-112.17273491252895_phoenix_google_satellite_image,,33.49618387083415_-112.17273491252895_phoenix_google_street_view_image,, -597445227,1,phoenix,33.58302517213424,-111.9790476188274,,33.58302517213424_-111.9790476188274_phoenix_google_maps_image,,33.58302517213424_-111.9790476188274_phoenix_google_satellite_image,,33.58302517213424_-111.9790476188274_phoenix_google_street_view_image,, -1015278486,1,phoenix,33.583522165345336,-111.9773303898694,,33.583522165345336_-111.9773303898694_phoenix_google_maps_image,,33.583522165345336_-111.9773303898694_phoenix_google_satellite_image,,33.583522165345336_-111.9773303898694_phoenix_google_street_view_image,, -2999125091,1,phoenix,33.49388319693427,-112.17068007936246,,33.49388319693427_-112.17068007936246_phoenix_google_maps_image,,33.49388319693427_-112.17068007936246_phoenix_google_satellite_image,,33.49388319693427_-112.17068007936246_phoenix_google_street_view_image,, -2120305890,1,phoenix,33.63865653464909,-112.12005632401943,,33.63865653464909_-112.12005632401943_phoenix_google_maps_image,,33.63865653464909_-112.12005632401943_phoenix_google_satellite_image,,33.63865653464909_-112.12005632401943_phoenix_google_street_view_image,, -3081249899,1,phoenix,33.436326300000005,-112.0109522,,33.436326300000005_-112.0109522_phoenix_google_maps_image,,33.436326300000005_-112.0109522_phoenix_google_satellite_image,,33.436326300000005_-112.0109522_phoenix_google_street_view_image,, -706931745,1,phoenix,33.59950324633909,-111.97888760482499,,33.59950324633909_-111.97888760482499_phoenix_google_maps_image,,33.59950324633909_-111.97888760482499_phoenix_google_satellite_image,,33.59950324633909_-111.97888760482499_phoenix_google_street_view_image,, -485723486,1,phoenix,33.52134906976979,-112.09270988613655,,33.52134906976979_-112.09270988613655_phoenix_google_maps_image,,33.52134906976979_-112.09270988613655_phoenix_google_satellite_image,,33.52134906976979_-112.09270988613655_phoenix_google_street_view_image,, -707448102,1,phoenix,33.58529786040639,-111.97906788281102,,33.58529786040639_-111.97906788281102_phoenix_google_maps_image,,33.58529786040639_-111.97906788281102_phoenix_google_satellite_image,,33.58529786040639_-111.97906788281102_phoenix_google_street_view_image,, -1015432761,1,phoenix,33.60265448510628,-111.9811437887164,,33.60265448510628_-111.9811437887164_phoenix_google_maps_image,,33.60265448510628_-111.9811437887164_phoenix_google_satellite_image,,33.60265448510628_-111.9811437887164_phoenix_google_street_view_image,, -4015696484,2,phoenix,33.510065186384765,-112.07227504420547,,33.510065186384765_-112.07227504420547_phoenix_google_maps_image,,33.510065186384765_-112.07227504420547_phoenix_google_satellite_image,,33.510065186384765_-112.07227504420547_phoenix_google_street_view_image,, -1656471455,2,phoenix,33.49350727505362,-112.20169176073925,,33.49350727505362_-112.20169176073925_phoenix_google_maps_image,,33.49350727505362_-112.20169176073925_phoenix_google_satellite_image,,33.49350727505362_-112.20169176073925_phoenix_google_street_view_image,, -2325086801,2,phoenix,33.34819558920091,-111.98173154192371,,33.34819558920091_-111.98173154192371_phoenix_google_maps_image,,33.34819558920091_-111.98173154192371_phoenix_google_satellite_image,,33.34819558920091_-111.98173154192371_phoenix_google_street_view_image,, -4989597947,2,phoenix,33.62431638368412,-111.94461094575492,,33.62431638368412_-111.94461094575492_phoenix_google_maps_image,,33.62431638368412_-111.94461094575492_phoenix_google_satellite_image,,33.62431638368412_-111.94461094575492_phoenix_google_street_view_image,, -6516441383,2,phoenix,33.62482911847935,-111.97896775669815,,33.62482911847935_-111.97896775669815_phoenix_google_maps_image,,33.62482911847935_-111.97896775669815_phoenix_google_satellite_image,,33.62482911847935_-111.97896775669815_phoenix_google_street_view_image,, -1680973812,2,phoenix,33.641448557620066,-112.01107896417196,,33.641448557620066_-112.01107896417196_phoenix_google_maps_image,,33.641448557620066_-112.01107896417196_phoenix_google_satellite_image,,33.641448557620066_-112.01107896417196_phoenix_google_street_view_image,, -2169665274,2,phoenix,33.3757888,-112.0291247,,33.3757888_-112.0291247_phoenix_google_maps_image,,33.3757888_-112.0291247_phoenix_google_satellite_image,,33.3757888_-112.0291247_phoenix_google_street_view_image,, -473852564,2,phoenix,33.30407134586127,-111.99479322265371,,33.30407134586127_-111.99479322265371_phoenix_google_maps_image,,33.30407134586127_-111.99479322265371_phoenix_google_satellite_image,,33.30407134586127_-111.99479322265371_phoenix_google_street_view_image,, -286664010,2,phoenix,33.496281399999994,-111.97934430000001,,33.496281399999994_-111.97934430000001_phoenix_google_maps_image,,33.496281399999994_-111.97934430000001_phoenix_google_satellite_image,,33.496281399999994_-111.97934430000001_phoenix_google_street_view_image,, -1798894170,2,phoenix,33.306554638387844,-112.05400486205016,,33.306554638387844_-112.05400486205016_phoenix_google_maps_image,,33.306554638387844_-112.05400486205016_phoenix_google_satellite_image,,33.306554638387844_-112.05400486205016_phoenix_google_street_view_image,, -5315598847,3,phoenix,33.65641296485599,-112.15035766601495,,33.65641296485599_-112.15035766601495_phoenix_google_maps_image,,33.65641296485599_-112.15035766601495_phoenix_google_satellite_image,,33.65641296485599_-112.15035766601495_phoenix_google_street_view_image,, -7259780428,3,phoenix,33.43810571619067,-112.07433678772438,,33.43810571619067_-112.07433678772438_phoenix_google_maps_image,,33.43810571619067_-112.07433678772438_phoenix_google_satellite_image,,33.43810571619067_-112.07433678772438_phoenix_google_street_view_image,, -4931775422,3,phoenix,33.7089963,-112.1129997,,33.7089963_-112.1129997_phoenix_google_maps_image,,33.7089963_-112.1129997_phoenix_google_satellite_image,,33.7089963_-112.1129997_phoenix_google_street_view_image,, -7152736885,3,phoenix,33.516618495033214,-112.08215139002274,,33.516618495033214_-112.08215139002274_phoenix_google_maps_image,,33.516618495033214_-112.08215139002274_phoenix_google_satellite_image,,33.516618495033214_-112.08215139002274_phoenix_google_street_view_image,, -6816511292,3,phoenix,33.5108981391705,-112.08550068470576,,33.5108981391705_-112.08550068470576_phoenix_google_maps_image,,33.5108981391705_-112.08550068470576_phoenix_google_satellite_image,,33.5108981391705_-112.08550068470576_phoenix_google_street_view_image,, -4382713606,3,phoenix,33.523983060110965,-112.04860692068318,,33.523983060110965_-112.04860692068318_phoenix_google_maps_image,,33.523983060110965_-112.04860692068318_phoenix_google_satellite_image,,33.523983060110965_-112.04860692068318_phoenix_google_street_view_image,, -65716522,3,phoenix,33.53980976781218,-112.06243620645012,,33.53980976781218_-112.06243620645012_phoenix_google_maps_image,,33.53980976781218_-112.06243620645012_phoenix_google_satellite_image,,33.53980976781218_-112.06243620645012_phoenix_google_street_view_image,, -3630195377,3,phoenix,33.48085773533956,-112.2538476020432,,33.48085773533956_-112.2538476020432_phoenix_google_maps_image,,33.48085773533956_-112.2538476020432_phoenix_google_satellite_image,,33.48085773533956_-112.2538476020432_phoenix_google_street_view_image,, -2181863598,3,phoenix,33.58349506750248,-112.01194727997495,,33.58349506750248_-112.01194727997495_phoenix_google_maps_image,,33.58349506750248_-112.01194727997495_phoenix_google_satellite_image,,33.58349506750248_-112.01194727997495_phoenix_google_street_view_image,, -5426636684,3,phoenix,33.321291680916836,-111.98240527011345,,33.321291680916836_-111.98240527011345_phoenix_google_maps_image,,33.321291680916836_-111.98240527011345_phoenix_google_satellite_image,,33.321291680916836_-111.98240527011345_phoenix_google_street_view_image,, -130341162,4,phoenix,33.47872268768254,-112.25384651354823,,33.47872268768254_-112.25384651354823_phoenix_google_maps_image,,33.47872268768254_-112.25384651354823_phoenix_google_satellite_image,,33.47872268768254_-112.25384651354823_phoenix_google_street_view_image,, -2315133795,4,phoenix,33.517647526416766,-112.0629210088304,,33.517647526416766_-112.0629210088304_phoenix_google_maps_image,,33.517647526416766_-112.0629210088304_phoenix_google_satellite_image,,33.517647526416766_-112.0629210088304_phoenix_google_street_view_image,, -4452509037,4,phoenix,33.48127892512827,-112.01423569449182,,33.48127892512827_-112.01423569449182_phoenix_google_maps_image,,33.48127892512827_-112.01423569449182_phoenix_google_satellite_image,,33.48127892512827_-112.01423569449182_phoenix_google_street_view_image,, -2458567936,4,phoenix,33.57110433135084,-112.08042839778024,,33.57110433135084_-112.08042839778024_phoenix_google_maps_image,,33.57110433135084_-112.08042839778024_phoenix_google_satellite_image,,33.57110433135084_-112.08042839778024_phoenix_google_street_view_image,, -250226344,4,phoenix,33.583713724947124,-112.13541837733315,,33.583713724947124_-112.13541837733315_phoenix_google_maps_image,,33.583713724947124_-112.13541837733315_phoenix_google_satellite_image,,33.583713724947124_-112.13541837733315_phoenix_google_street_view_image,, -5426615946,4,phoenix,33.4955582,-111.9892178,,33.4955582_-111.9892178_phoenix_google_maps_image,,33.4955582_-111.9892178_phoenix_google_satellite_image,,33.4955582_-111.9892178_phoenix_google_street_view_image,, -152448046,4,phoenix,33.527367465924705,-112.1325935340939,,33.527367465924705_-112.1325935340939_phoenix_google_maps_image,,33.527367465924705_-112.1325935340939_phoenix_google_satellite_image,,33.527367465924705_-112.1325935340939_phoenix_google_street_view_image,, -2810933508,4,phoenix,33.638252898576816,-112.15260335915141,,33.638252898576816_-112.15260335915141_phoenix_google_maps_image,,33.638252898576816_-112.15260335915141_phoenix_google_satellite_image,,33.638252898576816_-112.15260335915141_phoenix_google_street_view_image,, -480970526,4,phoenix,33.59843520036625,-112.15000849719037,,33.59843520036625_-112.15000849719037_phoenix_google_maps_image,,33.59843520036625_-112.15000849719037_phoenix_google_satellite_image,,33.59843520036625_-112.15000849719037_phoenix_google_street_view_image,, -2493829141,4,phoenix,33.57224995594046,-112.0609669088735,,33.57224995594046_-112.0609669088735_phoenix_google_maps_image,,33.57224995594046_-112.0609669088735_phoenix_google_satellite_image,,33.57224995594046_-112.0609669088735_phoenix_google_street_view_image,, -2324983396,5,phoenix,33.53758301748267,-112.13316094638326,,33.53758301748267_-112.13316094638326_phoenix_google_maps_image,,33.53758301748267_-112.13316094638326_phoenix_google_satellite_image,,33.53758301748267_-112.13316094638326_phoenix_google_street_view_image,, -6600083736,5,phoenix,33.49319330533305,-112.23917653996784,,33.49319330533305_-112.23917653996784_phoenix_google_maps_image,,33.49319330533305_-112.23917653996784_phoenix_google_satellite_image,,33.49319330533305_-112.23917653996784_phoenix_google_street_view_image,, -631702487,5,phoenix,33.65359410008661,-112.02973709999844,,33.65359410008661_-112.02973709999844_phoenix_google_maps_image,,33.65359410008661_-112.02973709999844_phoenix_google_satellite_image,,33.65359410008661_-112.02973709999844_phoenix_google_street_view_image,, -263101091,5,phoenix,33.64147779999999,-112.0788481,,33.64147779999999_-112.0788481_phoenix_google_maps_image,,33.64147779999999_-112.0788481_phoenix_google_satellite_image,,33.64147779999999_-112.0788481_phoenix_google_street_view_image,, -1140259217,5,phoenix,33.61051217188889,-112.014553667286,,33.61051217188889_-112.014553667286_phoenix_google_maps_image,,33.61051217188889_-112.014553667286_phoenix_google_satellite_image,,33.61051217188889_-112.014553667286_phoenix_google_street_view_image,, -3972840012,5,phoenix,33.46617382445832,-111.985535870184,,33.46617382445832_-111.985535870184_phoenix_google_maps_image,,33.46617382445832_-111.985535870184_phoenix_google_satellite_image,,33.46617382445832_-111.985535870184_phoenix_google_street_view_image,, -6254635472,5,phoenix,33.64143027188616,-112.0671296800922,,33.64143027188616_-112.0671296800922_phoenix_google_maps_image,,33.64143027188616_-112.0671296800922_phoenix_google_satellite_image,,33.64143027188616_-112.0671296800922_phoenix_google_street_view_image,, -1659598962,5,phoenix,33.48112370307971,-112.20205420648273,,33.48112370307971_-112.20205420648273_phoenix_google_maps_image,,33.48112370307971_-112.20205420648273_phoenix_google_satellite_image,,33.48112370307971_-112.20205420648273_phoenix_google_street_view_image,, -2482210418,5,phoenix,33.5396466577925,-112.13534016785471,,33.5396466577925_-112.13534016785471_phoenix_google_maps_image,,33.5396466577925_-112.13534016785471_phoenix_google_satellite_image,,33.5396466577925_-112.13534016785471_phoenix_google_street_view_image,, -3009696977,5,phoenix,33.53756646132701,-112.09831545941557,,33.53756646132701_-112.09831545941557_phoenix_google_maps_image,,33.53756646132701_-112.09831545941557_phoenix_google_satellite_image,,33.53756646132701_-112.09831545941557_phoenix_google_street_view_image,, -231287359,1,seattle,47.547915815786915,-122.31882441802148,,47.547915815786915_-122.31882441802148_seattle_google_maps_image,,47.547915815786915_-122.31882441802148_seattle_google_satellite_image,,47.547915815786915_-122.31882441802148_seattle_google_street_view_image,, -4377499029,1,seattle,47.79248851688081,-122.21455600463672,,47.79248851688081_-122.21455600463672_seattle_google_maps_image,,47.79248851688081_-122.21455600463672_seattle_google_satellite_image,,47.79248851688081_-122.21455600463672_seattle_google_street_view_image,, -144348145,1,seattle,47.164134512373124,-122.51783568100625,,47.164134512373124_-122.51783568100625_seattle_google_maps_image,,47.164134512373124_-122.51783568100625_seattle_google_satellite_image,,47.164134512373124_-122.51783568100625_seattle_google_street_view_image,, -4012419398,1,seattle,47.57032303806308,-122.34800339861893,,47.57032303806308_-122.34800339861893_seattle_google_maps_image,,47.57032303806308_-122.34800339861893_seattle_google_satellite_image,,47.57032303806308_-122.34800339861893_seattle_google_street_view_image,, -642975105,1,seattle,47.75475360000001,-122.16005430000001,,47.75475360000001_-122.16005430000001_seattle_google_maps_image,,47.75475360000001_-122.16005430000001_seattle_google_satellite_image,,47.75475360000001_-122.16005430000001_seattle_google_street_view_image,, -161888072,1,seattle,47.629753238116535,-122.15702540397726,,47.629753238116535_-122.15702540397726_seattle_google_maps_image,,47.629753238116535_-122.15702540397726_seattle_google_satellite_image,,47.629753238116535_-122.15702540397726_seattle_google_street_view_image,, -340336012,1,seattle,47.63079718083004,-122.14473379744996,,47.63079718083004_-122.14473379744996_seattle_google_maps_image,,47.63079718083004_-122.14473379744996_seattle_google_satellite_image,,47.63079718083004_-122.14473379744996_seattle_google_street_view_image,, -4703926637,1,seattle,47.61365401057268,-122.18449119267898,,47.61365401057268_-122.18449119267898_seattle_google_maps_image,,47.61365401057268_-122.18449119267898_seattle_google_satellite_image,,47.61365401057268_-122.18449119267898_seattle_google_street_view_image,, -221425097,1,seattle,47.54637027490851,-122.06039057931191,,47.54637027490851_-122.06039057931191_seattle_google_maps_image,,47.54637027490851_-122.06039057931191_seattle_google_satellite_image,,47.54637027490851_-122.06039057931191_seattle_google_street_view_image,, -379944235,1,seattle,47.57678765073876,-122.13815705001498,,47.57678765073876_-122.13815705001498_seattle_google_maps_image,,47.57678765073876_-122.13815705001498_seattle_google_satellite_image,,47.57678765073876_-122.13815705001498_seattle_google_street_view_image,, -2462428043,2,seattle,47.6309376345791,-122.37435224941656,,47.6309376345791_-122.37435224941656_seattle_google_maps_image,,47.6309376345791_-122.37435224941656_seattle_google_satellite_image,,47.6309376345791_-122.37435224941656_seattle_google_street_view_image,, -6208934685,2,seattle,47.18963700419304,-122.40870744944965,,47.18963700419304_-122.40870744944965_seattle_google_maps_image,,47.18963700419304_-122.40870744944965_seattle_google_satellite_image,,47.18963700419304_-122.40870744944965_seattle_google_street_view_image,, -56228516,2,seattle,47.616404484116984,-122.13172153119481,,47.616404484116984_-122.13172153119481_seattle_google_maps_image,,47.616404484116984_-122.13172153119481_seattle_google_satellite_image,,47.616404484116984_-122.13172153119481_seattle_google_street_view_image,, -40183590,2,seattle,47.31483906341251,-122.22624404649977,,47.31483906341251_-122.22624404649977_seattle_google_maps_image,,47.31483906341251_-122.22624404649977_seattle_google_satellite_image,,47.31483906341251_-122.22624404649977_seattle_google_street_view_image,, -5583694644,2,seattle,47.46695772817513,-122.34289478959678,,47.46695772817513_-122.34289478959678_seattle_google_maps_image,,47.46695772817513_-122.34289478959678_seattle_google_satellite_image,,47.46695772817513_-122.34289478959678_seattle_google_street_view_image,, -2102155082,2,seattle,47.82228997983158,-122.3163121111638,,47.82228997983158_-122.3163121111638_seattle_google_maps_image,,47.82228997983158_-122.3163121111638_seattle_google_satellite_image,,47.82228997983158_-122.3163121111638_seattle_google_street_view_image,, -51255014,2,seattle,47.25684667506376,-122.52026833603817,,47.25684667506376_-122.52026833603817_seattle_google_maps_image,,47.25684667506376_-122.52026833603817_seattle_google_satellite_image,,47.25684667506376_-122.52026833603817_seattle_google_street_view_image,, -184540212,2,seattle,47.60172032489827,-122.2856837894088,,47.60172032489827_-122.2856837894088_seattle_google_maps_image,,47.60172032489827_-122.2856837894088_seattle_google_satellite_image,,47.60172032489827_-122.2856837894088_seattle_google_street_view_image,, -589999070,2,seattle,47.2424129,-122.53677069999999,,47.2424129_-122.53677069999999_seattle_google_maps_image,,47.2424129_-122.53677069999999_seattle_google_satellite_image,,47.2424129_-122.53677069999999_seattle_google_street_view_image,, -160981529,2,seattle,47.563194130013954,-122.31306754987405,,47.563194130013954_-122.31306754987405_seattle_google_maps_image,,47.563194130013954_-122.31306754987405_seattle_google_satellite_image,,47.563194130013954_-122.31306754987405_seattle_google_street_view_image,, -1774098606,3,seattle,47.48782820130981,-122.14720693984452,,47.48782820130981_-122.14720693984452_seattle_google_maps_image,,47.48782820130981_-122.14720693984452_seattle_google_satellite_image,,47.48782820130981_-122.14720693984452_seattle_google_street_view_image,, -221145066,3,seattle,47.68977672823216,-122.29050735308064,,47.68977672823216_-122.29050735308064_seattle_google_maps_image,,47.68977672823216_-122.29050735308064_seattle_google_satellite_image,,47.68977672823216_-122.29050735308064_seattle_google_street_view_image,, -3329431642,3,seattle,47.71023201198618,-122.17063266280248,,47.71023201198618_-122.17063266280248_seattle_google_maps_image,,47.71023201198618_-122.17063266280248_seattle_google_satellite_image,,47.71023201198618_-122.17063266280248_seattle_google_street_view_image,, -4909107330,3,seattle,47.48760920291759,-122.14758185712988,,47.48760920291759_-122.14758185712988_seattle_google_maps_image,,47.48760920291759_-122.14758185712988_seattle_google_satellite_image,,47.48760920291759_-122.14758185712988_seattle_google_street_view_image,, -786129976,3,seattle,47.876999986661495,-122.18714917606742,,47.876999986661495_-122.18714917606742_seattle_google_maps_image,,47.876999986661495_-122.18714917606742_seattle_google_satellite_image,,47.876999986661495_-122.18714917606742_seattle_google_street_view_image,, -138541945,3,seattle,47.85678984166777,-122.21960023407709,,47.85678984166777_-122.21960023407709_seattle_google_maps_image,,47.85678984166777_-122.21960023407709_seattle_google_satellite_image,,47.85678984166777_-122.21960023407709_seattle_google_street_view_image,, -545895883,3,seattle,47.44180657997207,-122.33531180000021,,47.44180657997207_-122.33531180000021_seattle_google_maps_image,,47.44180657997207_-122.33531180000021_seattle_google_satellite_image,,47.44180657997207_-122.33531180000021_seattle_google_street_view_image,, -4348054289,3,seattle,47.98040689207639,-122.2130368747519,,47.98040689207639_-122.2130368747519_seattle_google_maps_image,,47.98040689207639_-122.2130368747519_seattle_google_satellite_image,,47.98040689207639_-122.2130368747519_seattle_google_street_view_image,, -5560877506,3,seattle,47.50455765856497,-122.16394956087532,,47.50455765856497_-122.16394956087532_seattle_google_maps_image,,47.50455765856497_-122.16394956087532_seattle_google_satellite_image,,47.50455765856497_-122.16394956087532_seattle_google_street_view_image,, -41831159,3,seattle,47.15646639999999,-122.43565019999998,,47.15646639999999_-122.43565019999998_seattle_google_maps_image,,47.15646639999999_-122.43565019999998_seattle_google_satellite_image,,47.15646639999999_-122.43565019999998_seattle_google_street_view_image,, -1076268999,4,seattle,47.67561882881142,-122.12790372439396,,47.67561882881142_-122.12790372439396_seattle_google_maps_image,,47.67561882881142_-122.12790372439396_seattle_google_satellite_image,,47.67561882881142_-122.12790372439396_seattle_google_street_view_image,, -2459612950,4,seattle,47.51818415194702,-122.3564892739769,,47.51818415194702_-122.3564892739769_seattle_google_maps_image,,47.51818415194702_-122.3564892739769_seattle_google_satellite_image,,47.51818415194702_-122.3564892739769_seattle_google_street_view_image,, -5283439759,4,seattle,47.819006234772566,-122.29447275632992,,47.819006234772566_-122.29447275632992_seattle_google_maps_image,,47.819006234772566_-122.29447275632992_seattle_google_satellite_image,,47.819006234772566_-122.29447275632992_seattle_google_street_view_image,, -144136765,4,seattle,47.13524249042996,-122.29451275313622,,47.13524249042996_-122.29451275313622_seattle_google_maps_image,,47.13524249042996_-122.29451275313622_seattle_google_satellite_image,,47.13524249042996_-122.29451275313622_seattle_google_street_view_image,, -5818837454,4,seattle,47.61206698033566,-122.19859121480994,,47.61206698033566_-122.19859121480994_seattle_google_maps_image,,47.61206698033566_-122.19859121480994_seattle_google_satellite_image,,47.61206698033566_-122.19859121480994_seattle_google_street_view_image,, -97526535,4,seattle,47.72150126199394,-122.29516974617317,,47.72150126199394_-122.29516974617317_seattle_google_maps_image,,47.72150126199394_-122.29516974617317_seattle_google_satellite_image,,47.72150126199394_-122.29516974617317_seattle_google_street_view_image,, -6466038789,4,seattle,47.612941507225344,-122.30091563169185,,47.612941507225344_-122.30091563169185_seattle_google_maps_image,,47.612941507225344_-122.30091563169185_seattle_google_satellite_image,,47.612941507225344_-122.30091563169185_seattle_google_street_view_image,, -136051469,4,seattle,47.579819576651246,-122.38603386382405,,47.579819576651246_-122.38603386382405_seattle_google_maps_image,,47.579819576651246_-122.38603386382405_seattle_google_satellite_image,,47.579819576651246_-122.38603386382405_seattle_google_street_view_image,, -457863565,4,seattle,47.619519152546985,-122.13124895753259,,47.619519152546985_-122.13124895753259_seattle_google_maps_image,,47.619519152546985_-122.13124895753259_seattle_google_satellite_image,,47.619519152546985_-122.13124895753259_seattle_google_street_view_image,, -2462453190,4,seattle,47.73337769999999,-122.31094139999999,,47.73337769999999_-122.31094139999999_seattle_google_maps_image,,47.73337769999999_-122.31094139999999_seattle_google_satellite_image,,47.73337769999999_-122.31094139999999_seattle_google_street_view_image,, -2323794471,5,seattle,47.66302817121764,-122.3134175655301,,47.66302817121764_-122.3134175655301_seattle_google_maps_image,,47.66302817121764_-122.3134175655301_seattle_google_satellite_image,,47.66302817121764_-122.3134175655301_seattle_google_street_view_image,, -1735895556,5,seattle,47.615800086117815,-122.31013897285999,,47.615800086117815_-122.31013897285999_seattle_google_maps_image,,47.615800086117815_-122.31013897285999_seattle_google_satellite_image,,47.615800086117815_-122.31013897285999_seattle_google_street_view_image,, -4458635049,5,seattle,47.60732200119781,-122.33543019969913,,47.60732200119781_-122.33543019969913_seattle_google_maps_image,,47.60732200119781_-122.33543019969913_seattle_google_satellite_image,,47.60732200119781_-122.33543019969913_seattle_google_street_view_image,, -2397401982,5,seattle,47.55999349697797,-122.38697566354044,,47.55999349697797_-122.38697566354044_seattle_google_maps_image,,47.55999349697797_-122.38697566354044_seattle_google_satellite_image,,47.55999349697797_-122.38697566354044_seattle_google_street_view_image,, -6781294438,5,seattle,47.61862658412955,-122.3374148077011,,47.61862658412955_-122.3374148077011_seattle_google_maps_image,,47.61862658412955_-122.3374148077011_seattle_google_satellite_image,,47.61862658412955_-122.3374148077011_seattle_google_street_view_image,, -2397497093,5,seattle,47.60894580871663,-122.34082817411597,,47.60894580871663_-122.34082817411597_seattle_google_maps_image,,47.60894580871663_-122.34082817411597_seattle_google_satellite_image,,47.60894580871663_-122.34082817411597_seattle_google_street_view_image,, -6781330674,5,seattle,47.610379278506244,-122.34009675832141,,47.610379278506244_-122.34009675832141_seattle_google_maps_image,,47.610379278506244_-122.34009675832141_seattle_google_satellite_image,,47.610379278506244_-122.34009675832141_seattle_google_street_view_image,, -2666623806,5,seattle,47.63450865215028,-122.35711235039064,,47.63450865215028_-122.35711235039064_seattle_google_maps_image,,47.63450865215028_-122.35711235039064_seattle_google_satellite_image,,47.63450865215028_-122.35711235039064_seattle_google_street_view_image,, -3379016191,5,seattle,47.61475952929407,-122.32790985266821,,47.61475952929407_-122.32790985266821_seattle_google_maps_image,,47.61475952929407_-122.32790985266821_seattle_google_satellite_image,,47.61475952929407_-122.32790985266821_seattle_google_street_view_image,, -206858876,5,seattle,47.608858796601815,-122.34069468343448,,47.608858796601815_-122.34069468343448_seattle_google_maps_image,,47.608858796601815_-122.34069468343448_seattle_google_satellite_image,,47.608858796601815_-122.34069468343448_seattle_google_street_view_image,, -3207004265,1,sydney,-33.93698786058448,150.8464217420261,,-33.93698786058448_150.8464217420261_sydney_google_maps_image,,-33.93698786058448_150.8464217420261_sydney_google_satellite_image,,-33.93698786058448_150.8464217420261_sydney_google_street_view_image,, -537535100,1,sydney,-33.71780402234493,150.9202597698209,,-33.71780402234493_150.9202597698209_sydney_google_maps_image,,-33.71780402234493_150.9202597698209_sydney_google_satellite_image,,-33.71780402234493_150.9202597698209_sydney_google_street_view_image,, -6576901203,1,sydney,-33.82415428658629,151.07862747217405,,-33.82415428658629_151.07862747217405_sydney_google_maps_image,,-33.82415428658629_151.07862747217405_sydney_google_satellite_image,,-33.82415428658629_151.07862747217405_sydney_google_street_view_image,, -319649390,1,sydney,-33.798783899999634,150.95787410000003,,-33.798783899999634_150.95787410000003_sydney_google_maps_image,,-33.798783899999634_150.95787410000003_sydney_google_satellite_image,,-33.798783899999634_150.95787410000003_sydney_google_street_view_image,, -1893124559,1,sydney,-33.76998633741108,150.7730188485084,,-33.76998633741108_150.7730188485084_sydney_google_maps_image,,-33.76998633741108_150.7730188485084_sydney_google_satellite_image,,-33.76998633741108_150.7730188485084_sydney_google_street_view_image,, -7448392528,1,sydney,-33.71267605159711,150.95836948796511,,-33.71267605159711_150.95836948796511_sydney_google_maps_image,,-33.71267605159711_150.95836948796511_sydney_google_satellite_image,,-33.71267605159711_150.95836948796511_sydney_google_street_view_image,, -792213520,1,sydney,-33.98596620543193,151.14692817466056,,-33.98596620543193_151.14692817466056_sydney_google_maps_image,,-33.98596620543193_151.14692817466056_sydney_google_satellite_image,,-33.98596620543193_151.14692817466056_sydney_google_street_view_image,, -7194087677,1,sydney,-33.75508246136216,150.7042533212603,,-33.75508246136216_150.7042533212603_sydney_google_maps_image,,-33.75508246136216_150.7042533212603_sydney_google_satellite_image,,-33.75508246136216_150.7042533212603_sydney_google_street_view_image,, -1974543144,1,sydney,-33.79516507042692,151.1223010825233,,-33.79516507042692_151.1223010825233_sydney_google_maps_image,,-33.79516507042692_151.1223010825233_sydney_google_satellite_image,,-33.79516507042692_151.1223010825233_sydney_google_street_view_image,, -221933531,1,sydney,-33.75485360042116,150.70604429119996,,-33.75485360042116_150.70604429119996_sydney_google_maps_image,,-33.75485360042116_150.70604429119996_sydney_google_satellite_image,,-33.75485360042116_150.70604429119996_sydney_google_street_view_image,, -2060895650,2,sydney,-33.76074204520165,151.12880870381755,,-33.76074204520165_151.12880870381755_sydney_google_maps_image,,-33.76074204520165_151.12880870381755_sydney_google_satellite_image,,-33.76074204520165_151.12880870381755_sydney_google_street_view_image,, -399121769,2,sydney,-33.814814265517626,151.05436563951298,,-33.814814265517626_151.05436563951298_sydney_google_maps_image,,-33.814814265517626_151.05436563951298_sydney_google_satellite_image,,-33.814814265517626_151.05436563951298_sydney_google_street_view_image,, -1612463931,2,sydney,-33.82274961375412,150.98036233033224,,-33.82274961375412_150.98036233033224_sydney_google_maps_image,,-33.82274961375412_150.98036233033224_sydney_google_satellite_image,,-33.82274961375412_150.98036233033224_sydney_google_street_view_image,, -428468942,2,sydney,-33.81442865579148,151.05481607271815,,-33.81442865579148_151.05481607271815_sydney_google_maps_image,,-33.81442865579148_151.05481607271815_sydney_google_satellite_image,,-33.81442865579148_151.05481607271815_sydney_google_street_view_image,, -6115467798,2,sydney,-33.9165581813648,151.1666292861455,,-33.9165581813648_151.1666292861455_sydney_google_maps_image,,-33.9165581813648_151.1666292861455_sydney_google_satellite_image,,-33.9165581813648_151.1666292861455_sydney_google_street_view_image,, -4924219553,2,sydney,-33.90276226253167,151.19469906341232,,-33.90276226253167_151.19469906341232_sydney_google_maps_image,,-33.90276226253167_151.19469906341232_sydney_google_satellite_image,,-33.90276226253167_151.19469906341232_sydney_google_street_view_image,, -2189527088,2,sydney,-33.782236376836465,150.82660678611362,,-33.782236376836465_150.82660678611362_sydney_google_maps_image,,-33.782236376836465_150.82660678611362_sydney_google_satellite_image,,-33.782236376836465_150.82660678611362_sydney_google_street_view_image,, -813186510,2,sydney,-33.69119227782244,151.10150773087983,,-33.69119227782244_151.10150773087983_sydney_google_maps_image,,-33.69119227782244_151.10150773087983_sydney_google_satellite_image,,-33.69119227782244_151.10150773087983_sydney_google_street_view_image,, -222582855,2,sydney,-33.912606003359606,150.98365463772956,,-33.912606003359606_150.98365463772956_sydney_google_maps_image,,-33.912606003359606_150.98365463772956_sydney_google_satellite_image,,-33.912606003359606_150.98365463772956_sydney_google_street_view_image,, -4546260408,2,sydney,-33.92070858361609,150.92405416837957,,-33.92070858361609_150.92405416837957_sydney_google_maps_image,,-33.92070858361609_150.92405416837957_sydney_google_satellite_image,,-33.92070858361609_150.92405416837957_sydney_google_street_view_image,, -6718063062,3,sydney,-33.87006611870223,151.27018484811944,,-33.87006611870223_151.27018484811944_sydney_google_maps_image,,-33.87006611870223_151.27018484811944_sydney_google_satellite_image,,-33.87006611870223_151.27018484811944_sydney_google_street_view_image,, -3296252561,3,sydney,-33.77309630902993,151.08178711325579,,-33.77309630902993_151.08178711325579_sydney_google_maps_image,,-33.77309630902993_151.08178711325579_sydney_google_satellite_image,,-33.77309630902993_151.08178711325579_sydney_google_street_view_image,, -4478143699,3,sydney,-33.79401559999961,151.18671450000002,,-33.79401559999961_151.18671450000002_sydney_google_maps_image,,-33.79401559999961_151.18671450000002_sydney_google_satellite_image,,-33.79401559999961_151.18671450000002_sydney_google_street_view_image,, -7455590962,3,sydney,-33.88091426735227,151.1391816075202,,-33.88091426735227_151.1391816075202_sydney_google_maps_image,,-33.88091426735227_151.1391816075202_sydney_google_satellite_image,,-33.88091426735227_151.1391816075202_sydney_google_street_view_image,, -3502499372,3,sydney,-34.03426353117276,151.07117700846507,,-34.03426353117276_151.07117700846507_sydney_google_maps_image,,-34.03426353117276_151.07117700846507_sydney_google_satellite_image,,-34.03426353117276_151.07117700846507_sydney_google_street_view_image,, -4983992021,3,sydney,-33.89061679181626,151.2736592878431,,-33.89061679181626_151.2736592878431_sydney_google_maps_image,,-33.89061679181626_151.2736592878431_sydney_google_satellite_image,,-33.89061679181626_151.2736592878431_sydney_google_street_view_image,, -1346628721,3,sydney,-33.86680300882241,151.20378197822808,,-33.86680300882241_151.20378197822808_sydney_google_maps_image,,-33.86680300882241_151.20378197822808_sydney_google_satellite_image,,-33.86680300882241_151.20378197822808_sydney_google_street_view_image,, -173897520,3,sydney,-33.771774306176226,151.07992588326127,,-33.771774306176226_151.07992588326127_sydney_google_maps_image,,-33.771774306176226_151.07992588326127_sydney_google_satellite_image,,-33.771774306176226_151.07992588326127_sydney_google_street_view_image,, -6053610954,3,sydney,-33.807760498515314,151.09063231683487,,-33.807760498515314_151.09063231683487_sydney_google_maps_image,,-33.807760498515314_151.09063231683487_sydney_google_satellite_image,,-33.807760498515314_151.09063231683487_sydney_google_street_view_image,, -809372673,3,sydney,-33.96493719999962,151.1418048,,-33.96493719999962_151.1418048_sydney_google_maps_image,,-33.96493719999962_151.1418048_sydney_google_satellite_image,,-33.96493719999962_151.1418048_sydney_google_street_view_image,, -7097821928,4,sydney,-33.84580348093946,151.21121596770317,,-33.84580348093946_151.21121596770317_sydney_google_maps_image,,-33.84580348093946_151.21121596770317_sydney_google_satellite_image,,-33.84580348093946_151.21121596770317_sydney_google_street_view_image,, -207331854,4,sydney,-33.87431479999959,151.1071721,,-33.87431479999959_151.1071721_sydney_google_maps_image,,-33.87431479999959_151.1071721_sydney_google_satellite_image,,-33.87431479999959_151.1071721_sydney_google_street_view_image,, -4353406491,4,sydney,-33.70411547645366,151.10142469329003,,-33.70411547645366_151.10142469329003_sydney_google_maps_image,,-33.70411547645366_151.10142469329003_sydney_google_satellite_image,,-33.70411547645366_151.10142469329003_sydney_google_street_view_image,, -6371771205,4,sydney,-33.918959639988216,151.2574738634685,,-33.918959639988216_151.2574738634685_sydney_google_maps_image,,-33.918959639988216_151.2574738634685_sydney_google_satellite_image,,-33.918959639988216_151.2574738634685_sydney_google_street_view_image,, -584530131,4,sydney,-33.915050945647224,151.2403330804831,,-33.915050945647224_151.2403330804831_sydney_google_maps_image,,-33.915050945647224_151.2403330804831_sydney_google_satellite_image,,-33.915050945647224_151.2403330804831_sydney_google_street_view_image,, -4450003390,4,sydney,-33.8654604999996,151.277738,,-33.8654604999996_151.277738_sydney_google_maps_image,,-33.8654604999996_151.277738_sydney_google_satellite_image,,-33.8654604999996_151.277738_sydney_google_street_view_image,, -5099993626,4,sydney,-33.85762590152955,151.1815009561314,,-33.85762590152955_151.1815009561314_sydney_google_maps_image,,-33.85762590152955_151.1815009561314_sydney_google_satellite_image,,-33.85762590152955_151.1815009561314_sydney_google_street_view_image,, -5774499609,4,sydney,-33.943638967283476,151.24003352729176,,-33.943638967283476_151.24003352729176_sydney_google_maps_image,,-33.943638967283476_151.24003352729176_sydney_google_satellite_image,,-33.943638967283476_151.24003352729176_sydney_google_street_view_image,, -4956462389,4,sydney,-33.89343628856618,151.247933582083,,-33.89343628856618_151.247933582083_sydney_google_maps_image,,-33.89343628856618_151.247933582083_sydney_google_satellite_image,,-33.89343628856618_151.247933582083_sydney_google_street_view_image,, -5872695843,4,sydney,-33.91430321060813,151.24003357268805,,-33.91430321060813_151.24003357268805_sydney_google_maps_image,,-33.91430321060813_151.24003357268805_sydney_google_satellite_image,,-33.91430321060813_151.24003357268805_sydney_google_street_view_image,, -1081217611,5,sydney,-33.96762896444103,151.10423162344804,,-33.96762896444103_151.10423162344804_sydney_google_maps_image,,-33.96762896444103_151.10423162344804_sydney_google_satellite_image,,-33.96762896444103_151.10423162344804_sydney_google_street_view_image,, -5886974732,5,sydney,-33.79644388181618,151.18331872307652,,-33.79644388181618_151.18331872307652_sydney_google_maps_image,,-33.79644388181618_151.18331872307652_sydney_google_satellite_image,,-33.79644388181618_151.18331872307652_sydney_google_street_view_image,, -3921514862,5,sydney,-33.88483179999965,151.2005316,,-33.88483179999965_151.2005316_sydney_google_maps_image,,-33.88483179999965_151.2005316_sydney_google_satellite_image,,-33.88483179999965_151.2005316_sydney_google_street_view_image,, -2312254908,5,sydney,-33.877610042893465,151.21302434745317,,-33.877610042893465_151.21302434745317_sydney_google_maps_image,,-33.877610042893465_151.21302434745317_sydney_google_satellite_image,,-33.877610042893465_151.21302434745317_sydney_google_street_view_image,, -3626039515,5,sydney,-33.899123980486024,151.17173769606052,,-33.899123980486024_151.17173769606052_sydney_google_maps_image,,-33.899123980486024_151.17173769606052_sydney_google_satellite_image,,-33.899123980486024_151.17173769606052_sydney_google_street_view_image,, -5729354132,5,sydney,-33.796508247052806,151.18460588445558,,-33.796508247052806_151.18460588445558_sydney_google_maps_image,,-33.796508247052806_151.18460588445558_sydney_google_satellite_image,,-33.796508247052806_151.18460588445558_sydney_google_street_view_image,, -1264487049,5,sydney,-33.828426924417144,151.2297350829877,,-33.828426924417144_151.2297350829877_sydney_google_maps_image,,-33.828426924417144_151.2297350829877_sydney_google_satellite_image,,-33.828426924417144_151.2297350829877_sydney_google_street_view_image,, -514947290,5,sydney,-33.8776137579799,151.21302915432227,,-33.8776137579799_151.21302915432227_sydney_google_maps_image,,-33.8776137579799_151.21302915432227_sydney_google_satellite_image,,-33.8776137579799_151.21302915432227_sydney_google_street_view_image,, -1081257981,5,sydney,-33.96639019999964,151.1055112,,-33.96639019999964_151.1055112_sydney_google_maps_image,,-33.96639019999964_151.1055112_sydney_google_satellite_image,,-33.96639019999964_151.1055112_sydney_google_street_view_image,, -4941850644,5,sydney,-33.89398165714167,151.26374581410917,,-33.89398165714167_151.26374581410917_sydney_google_maps_image,,-33.89398165714167_151.26374581410917_sydney_google_satellite_image,,-33.89398165714167_151.26374581410917_sydney_google_street_view_image,, -5820219899,1,valencia,39.47944041395021,-0.32795889607769707,,39.47944041395021_-0.32795889607769707_valencia_google_maps_image,,39.47944041395021_-0.32795889607769707_valencia_google_satellite_image,,39.47944041395021_-0.32795889607769707_valencia_google_street_view_image,, -7615543187,1,valencia,39.453906605635,-0.35961113299367226,,39.453906605635_-0.35961113299367226_valencia_google_maps_image,,39.453906605635_-0.35961113299367226_valencia_google_satellite_image,,39.453906605635_-0.35961113299367226_valencia_google_street_view_image,, -3316779669,1,valencia,39.457499000565605,-0.3658361195517701,,39.457499000565605_-0.3658361195517701_valencia_google_maps_image,,39.457499000565605_-0.3658361195517701_valencia_google_satellite_image,,39.457499000565605_-0.3658361195517701_valencia_google_street_view_image,, -6584941787,1,valencia,39.42488042574295,-0.36405182457733015,,39.42488042574295_-0.36405182457733015_valencia_google_maps_image,,39.42488042574295_-0.36405182457733015_valencia_google_satellite_image,,39.42488042574295_-0.36405182457733015_valencia_google_street_view_image,, -256966146,1,valencia,39.497926261829804,-0.3756100713970001,,39.497926261829804_-0.3756100713970001_valencia_google_maps_image,,39.497926261829804_-0.3756100713970001_valencia_google_satellite_image,,39.497926261829804_-0.3756100713970001_valencia_google_street_view_image,, -1719308792,1,valencia,39.434838740989456,-0.3909214820609415,,39.434838740989456_-0.3909214820609415_valencia_google_maps_image,,39.434838740989456_-0.3909214820609415_valencia_google_satellite_image,,39.434838740989456_-0.3909214820609415_valencia_google_street_view_image,, -6638503684,1,valencia,39.477481818937264,-0.38293193671028813,,39.477481818937264_-0.38293193671028813_valencia_google_maps_image,,39.477481818937264_-0.38293193671028813_valencia_google_satellite_image,,39.477481818937264_-0.38293193671028813_valencia_google_street_view_image,, -6959663422,1,valencia,39.480765059231985,-0.36142724695837525,,39.480765059231985_-0.36142724695837525_valencia_google_maps_image,,39.480765059231985_-0.36142724695837525_valencia_google_satellite_image,,39.480765059231985_-0.36142724695837525_valencia_google_street_view_image,, -6395687842,1,valencia,39.47612866268815,-0.3651666345201981,,39.47612866268815_-0.3651666345201981_valencia_google_maps_image,,39.47612866268815_-0.3651666345201981_valencia_google_satellite_image,,39.47612866268815_-0.3651666345201981_valencia_google_street_view_image,, -657857713,1,valencia,39.44996077979142,-0.38001390526542506,,39.44996077979142_-0.38001390526542506_valencia_google_maps_image,,39.44996077979142_-0.38001390526542506_valencia_google_satellite_image,,39.44996077979142_-0.38001390526542506_valencia_google_street_view_image,, -10120283,2,valencia,39.46918479099177,-0.3685254230157961,,39.46918479099177_-0.3685254230157961_valencia_google_maps_image,,39.46918479099177_-0.3685254230157961_valencia_google_satellite_image,,39.46918479099177_-0.3685254230157961_valencia_google_street_view_image,, -4307621589,2,valencia,39.47481523656729,-0.3896406053929307,,39.47481523656729_-0.3896406053929307_valencia_google_maps_image,,39.47481523656729_-0.3896406053929307_valencia_google_satellite_image,,39.47481523656729_-0.3896406053929307_valencia_google_street_view_image,, -1452342492,2,valencia,39.47970994148924,-0.39653547645834863,,39.47970994148924_-0.39653547645834863_valencia_google_maps_image,,39.47970994148924_-0.39653547645834863_valencia_google_satellite_image,,39.47970994148924_-0.39653547645834863_valencia_google_street_view_image,, -23455760,2,valencia,39.46788068635267,-0.3336291566899967,,39.46788068635267_-0.3336291566899967_valencia_google_maps_image,,39.46788068635267_-0.3336291566899967_valencia_google_satellite_image,,39.46788068635267_-0.3336291566899967_valencia_google_street_view_image,, -4633920690,2,valencia,39.46817634623685,-0.3514821029216269,,39.46817634623685_-0.3514821029216269_valencia_google_maps_image,,39.46817634623685_-0.3514821029216269_valencia_google_satellite_image,,39.46817634623685_-0.3514821029216269_valencia_google_street_view_image,, -6445298659,2,valencia,39.49270231487079,-0.38944530593827414,,39.49270231487079_-0.38944530593827414_valencia_google_maps_image,,39.49270231487079_-0.38944530593827414_valencia_google_satellite_image,,39.49270231487079_-0.38944530593827414_valencia_google_street_view_image,, -6617346030,2,valencia,39.468041712788455,-0.3510203409721477,,39.468041712788455_-0.3510203409721477_valencia_google_maps_image,,39.468041712788455_-0.3510203409721477_valencia_google_satellite_image,,39.468041712788455_-0.3510203409721477_valencia_google_street_view_image,, -4741566835,2,valencia,39.47761217422326,-0.39837179017981,,39.47761217422326_-0.39837179017981_valencia_google_maps_image,,39.47761217422326_-0.39837179017981_valencia_google_satellite_image,,39.47761217422326_-0.39837179017981_valencia_google_street_view_image,, -4523277176,2,valencia,39.48436225366254,-0.3832592825626807,,39.48436225366254_-0.3832592825626807_valencia_google_maps_image,,39.48436225366254_-0.3832592825626807_valencia_google_satellite_image,,39.48436225366254_-0.3832592825626807_valencia_google_street_view_image,, -197384433,2,valencia,39.473961665520854,-0.3834447489236085,,39.473961665520854_-0.3834447489236085_valencia_google_maps_image,,39.473961665520854_-0.3834447489236085_valencia_google_satellite_image,,39.473961665520854_-0.3834447489236085_valencia_google_street_view_image,, -2656119556,3,valencia,39.491276205363334,-0.3807078309216622,,39.491276205363334_-0.3807078309216622_valencia_google_maps_image,,39.491276205363334_-0.3807078309216622_valencia_google_satellite_image,,39.491276205363334_-0.3807078309216622_valencia_google_street_view_image,, -5257504624,3,valencia,39.48593423345085,-0.3927002240358755,,39.48593423345085_-0.3927002240358755_valencia_google_maps_image,,39.48593423345085_-0.3927002240358755_valencia_google_satellite_image,,39.48593423345085_-0.3927002240358755_valencia_google_street_view_image,, -7395350141,3,valencia,39.49449278337023,-0.37859299719305484,,39.49449278337023_-0.37859299719305484_valencia_google_maps_image,,39.49449278337023_-0.37859299719305484_valencia_google_satellite_image,,39.49449278337023_-0.37859299719305484_valencia_google_street_view_image,, -6404014385,3,valencia,39.47177372103371,-0.3962729613861756,,39.47177372103371_-0.3962729613861756_valencia_google_maps_image,,39.47177372103371_-0.3962729613861756_valencia_google_satellite_image,,39.47177372103371_-0.3962729613861756_valencia_google_street_view_image,, -1386005512,3,valencia,39.49492974467926,-0.3803357786471776,,39.49492974467926_-0.3803357786471776_valencia_google_maps_image,,39.49492974467926_-0.3803357786471776_valencia_google_satellite_image,,39.49492974467926_-0.3803357786471776_valencia_google_street_view_image,, -3316779670,3,valencia,39.45804955060059,-0.36548870941267364,,39.45804955060059_-0.36548870941267364_valencia_google_maps_image,,39.45804955060059_-0.36548870941267364_valencia_google_satellite_image,,39.45804955060059_-0.36548870941267364_valencia_google_street_view_image,, -5046970845,3,valencia,39.473067282167825,-0.3760932950480865,,39.473067282167825_-0.3760932950480865_valencia_google_maps_image,,39.473067282167825_-0.3760932950480865_valencia_google_satellite_image,,39.473067282167825_-0.3760932950480865_valencia_google_street_view_image,, -23776578,3,valencia,39.492922480305914,-0.38025355960926677,,39.492922480305914_-0.38025355960926677_valencia_google_maps_image,,39.492922480305914_-0.38025355960926677_valencia_google_satellite_image,,39.492922480305914_-0.38025355960926677_valencia_google_street_view_image,, -3607188804,3,valencia,39.50266836960625,-0.42011620754781415,,39.50266836960625_-0.42011620754781415_valencia_google_maps_image,,39.50266836960625_-0.42011620754781415_valencia_google_satellite_image,,39.50266836960625_-0.42011620754781415_valencia_google_street_view_image,, -1452368050,3,valencia,39.47875416889303,-0.39602860983659877,,39.47875416889303_-0.39602860983659877_valencia_google_maps_image,,39.47875416889303_-0.39602860983659877_valencia_google_satellite_image,,39.47875416889303_-0.39602860983659877_valencia_google_street_view_image,, -4103882463,4,valencia,39.45809835038438,-0.3927642594365756,,39.45809835038438_-0.3927642594365756_valencia_google_maps_image,,39.45809835038438_-0.3927642594365756_valencia_google_satellite_image,,39.45809835038438_-0.3927642594365756_valencia_google_street_view_image,, -4989970386,4,valencia,39.46071430307684,-0.33517838888347806,,39.46071430307684_-0.33517838888347806_valencia_google_maps_image,,39.46071430307684_-0.33517838888347806_valencia_google_satellite_image,,39.46071430307684_-0.33517838888347806_valencia_google_street_view_image,, -2264306798,4,valencia,39.47408519945665,-0.377923104794742,,39.47408519945665_-0.377923104794742_valencia_google_maps_image,,39.47408519945665_-0.377923104794742_valencia_google_satellite_image,,39.47408519945665_-0.377923104794742_valencia_google_street_view_image,, -4111725006,4,valencia,39.46346388653347,-0.35222995869103474,,39.46346388653347_-0.35222995869103474_valencia_google_maps_image,,39.46346388653347_-0.35222995869103474_valencia_google_satellite_image,,39.46346388653347_-0.35222995869103474_valencia_google_street_view_image,, -3608183846,4,valencia,39.50040481755207,-0.4187434111724148,,39.50040481755207_-0.4187434111724148_valencia_google_maps_image,,39.50040481755207_-0.4187434111724148_valencia_google_satellite_image,,39.50040481755207_-0.4187434111724148_valencia_google_street_view_image,, -5382634205,4,valencia,39.48888613713267,-0.37305738607900424,,39.48888613713267_-0.37305738607900424_valencia_google_maps_image,,39.48888613713267_-0.37305738607900424_valencia_google_satellite_image,,39.48888613713267_-0.37305738607900424_valencia_google_street_view_image,, -6822193923,4,valencia,39.465856218581514,-0.3510310879639834,,39.465856218581514_-0.3510310879639834_valencia_google_maps_image,,39.465856218581514_-0.3510310879639834_valencia_google_satellite_image,,39.465856218581514_-0.3510310879639834_valencia_google_street_view_image,, -777291452,4,valencia,39.454196024888084,-0.37488666077946176,,39.454196024888084_-0.37488666077946176_valencia_google_maps_image,,39.454196024888084_-0.37488666077946176_valencia_google_satellite_image,,39.454196024888084_-0.37488666077946176_valencia_google_street_view_image,, -7081005114,4,valencia,39.465816711838684,-0.39254115963754793,,39.465816711838684_-0.39254115963754793_valencia_google_maps_image,,39.465816711838684_-0.39254115963754793_valencia_google_satellite_image,,39.465816711838684_-0.39254115963754793_valencia_google_street_view_image,, -4893666924,4,valencia,39.469551825485695,-0.389694732258049,,39.469551825485695_-0.389694732258049_valencia_google_maps_image,,39.469551825485695_-0.389694732258049_valencia_google_satellite_image,,39.469551825485695_-0.389694732258049_valencia_google_street_view_image,, -825264576,5,valencia,39.495490340638575,-0.3705974705540262,,39.495490340638575_-0.3705974705540262_valencia_google_maps_image,,39.495490340638575_-0.3705974705540262_valencia_google_satellite_image,,39.495490340638575_-0.3705974705540262_valencia_google_street_view_image,, -5299082008,5,valencia,39.48755147406303,-0.39366519946820894,,39.48755147406303_-0.39366519946820894_valencia_google_maps_image,,39.48755147406303_-0.39366519946820894_valencia_google_satellite_image,,39.48755147406303_-0.39366519946820894_valencia_google_street_view_image,, -2288376112,5,valencia,39.46256831193777,-0.37293831658842413,,39.46256831193777_-0.37293831658842413_valencia_google_maps_image,,39.46256831193777_-0.37293831658842413_valencia_google_satellite_image,,39.46256831193777_-0.37293831658842413_valencia_google_street_view_image,, -6520546739,5,valencia,39.47353829857786,-0.35340940952003375,,39.47353829857786_-0.35340940952003375_valencia_google_maps_image,,39.47353829857786_-0.35340940952003375_valencia_google_satellite_image,,39.47353829857786_-0.35340940952003375_valencia_google_street_view_image,, -3686352663,5,valencia,39.4620799050774,-0.3425859129117003,,39.4620799050774_-0.3425859129117003_valencia_google_maps_image,,39.4620799050774_-0.3425859129117003_valencia_google_satellite_image,,39.4620799050774_-0.3425859129117003_valencia_google_street_view_image,, -2625796996,5,valencia,39.49605573652206,-0.37034230970581455,,39.49605573652206_-0.37034230970581455_valencia_google_maps_image,,39.49605573652206_-0.37034230970581455_valencia_google_satellite_image,,39.49605573652206_-0.37034230970581455_valencia_google_street_view_image,, -4608688991,5,valencia,39.46286573182253,-0.3421113955928668,,39.46286573182253_-0.3421113955928668_valencia_google_maps_image,,39.46286573182253_-0.3421113955928668_valencia_google_satellite_image,,39.46286573182253_-0.3421113955928668_valencia_google_street_view_image,, -6318095964,5,valencia,39.48949944896898,-0.3599938518995235,,39.48949944896898_-0.3599938518995235_valencia_google_maps_image,,39.48949944896898_-0.3599938518995235_valencia_google_satellite_image,,39.48949944896898_-0.3599938518995235_valencia_google_street_view_image,, -3316778157,5,valencia,39.460378436299656,-0.3761088765787719,,39.460378436299656_-0.3761088765787719_valencia_google_maps_image,,39.460378436299656_-0.3761088765787719_valencia_google_satellite_image,,39.460378436299656_-0.3761088765787719_valencia_google_street_view_image,, -372352252,5,valencia,39.47316826588193,-0.38551028171268553,,39.47316826588193_-0.38551028171268553_valencia_google_maps_image,,39.47316826588193_-0.38551028171268553_valencia_google_satellite_image,,39.47316826588193_-0.38551028171268553_valencia_google_street_view_image,, -316081856,1,vic,41.92591313729815,2.246212969281069,,41.92591313729815_2.246212969281069_vic_google_maps_image,,41.92591313729815_2.246212969281069_vic_google_satellite_image,,41.92591313729815_2.246212969281069_vic_google_street_view_image,, -180222391,1,vic,41.93037754053714,2.265662962905963,,41.93037754053714_2.265662962905963_vic_google_maps_image,,41.93037754053714_2.265662962905963_vic_google_satellite_image,,41.93037754053714_2.265662962905963_vic_google_street_view_image,, -3221296626,1,vic,41.921277705130926,2.252697776235735,,41.921277705130926_2.252697776235735_vic_google_maps_image,,41.921277705130926_2.252697776235735_vic_google_satellite_image,,41.921277705130926_2.252697776235735_vic_google_street_view_image,, -3822573804,1,vic,41.931317207389945,2.242743935499561,,41.931317207389945_2.242743935499561_vic_google_maps_image,,41.931317207389945_2.242743935499561_vic_google_satellite_image,,41.931317207389945_2.242743935499561_vic_google_street_view_image,, -578129672,1,vic,41.92381742413861,2.247214936670592,,41.92381742413861_2.247214936670592_vic_google_maps_image,,41.92381742413861_2.247214936670592_vic_google_satellite_image,,41.92381742413861_2.247214936670592_vic_google_street_view_image,, -315822627,1,vic,41.93484314459451,2.2666793618041736,,41.93484314459451_2.2666793618041736_vic_google_maps_image,,41.93484314459451_2.2666793618041736_vic_google_satellite_image,,41.93484314459451_2.2666793618041736_vic_google_street_view_image,, -4522494391,1,vic,41.94669846456933,2.2839258768833774,,41.94669846456933_2.2839258768833774_vic_google_maps_image,,41.94669846456933_2.2839258768833774_vic_google_satellite_image,,41.94669846456933_2.2839258768833774_vic_google_street_view_image,, -1638918440,1,vic,41.914658079015354,2.229188154682545,,41.914658079015354_2.229188154682545_vic_google_maps_image,,41.914658079015354_2.229188154682545_vic_google_satellite_image,,41.914658079015354_2.229188154682545_vic_google_street_view_image,, -166369645,1,vic,41.944914575545354,2.2516350329645634,,41.944914575545354_2.2516350329645634_vic_google_maps_image,,41.944914575545354_2.2516350329645634_vic_google_satellite_image,,41.944914575545354_2.2516350329645634_vic_google_street_view_image,, -318106310,1,vic,41.941476169947805,2.2530142517304164,,41.941476169947805_2.2530142517304164_vic_google_maps_image,,41.941476169947805_2.2530142517304164_vic_google_satellite_image,,41.941476169947805_2.2530142517304164_vic_google_street_view_image,, -6056021285,2,vic,41.940631694228706,2.2539151901721217,,41.940631694228706_2.2539151901721217_vic_google_maps_image,,41.940631694228706_2.2539151901721217_vic_google_satellite_image,,41.940631694228706_2.2539151901721217_vic_google_street_view_image,, -6221830417,2,vic,41.93193158804071,2.252876920065436,,41.93193158804071_2.252876920065436_vic_google_maps_image,,41.93193158804071_2.252876920065436_vic_google_satellite_image,,41.93193158804071_2.252876920065436_vic_google_street_view_image,, -6174756180,2,vic,41.93209985017114,2.2526981846520737,,41.93209985017114_2.2526981846520737_vic_google_maps_image,,41.93209985017114_2.2526981846520737_vic_google_satellite_image,,41.93209985017114_2.2526981846520737_vic_google_street_view_image,, -6056018583,2,vic,41.93966294406402,2.254148043353885,,41.93966294406402_2.254148043353885_vic_google_maps_image,,41.93966294406402_2.254148043353885_vic_google_satellite_image,,41.93966294406402_2.254148043353885_vic_google_street_view_image,, -6174756176,2,vic,41.9321988682738,2.2525857895253765,,41.9321988682738_2.2525857895253765_vic_google_maps_image,,41.9321988682738_2.2525857895253765_vic_google_satellite_image,,41.9321988682738_2.2525857895253765_vic_google_street_view_image,, -5910245370,2,vic,41.923145061606625,2.2506873578971343,,41.923145061606625_2.2506873578971343_vic_google_maps_image,,41.923145061606625_2.2506873578971343_vic_google_satellite_image,,41.923145061606625_2.2506873578971343_vic_google_street_view_image,, -6174756388,2,vic,41.932144497208704,2.253280363761519,,41.932144497208704_2.253280363761519_vic_google_maps_image,,41.932144497208704_2.253280363761519_vic_google_satellite_image,,41.932144497208704_2.253280363761519_vic_google_street_view_image,, -6221830426,2,vic,41.931656792756655,2.253165216599444,,41.931656792756655_2.253165216599444_vic_google_maps_image,,41.931656792756655_2.253165216599444_vic_google_satellite_image,,41.931656792756655_2.253165216599444_vic_google_street_view_image,, -6221830430,2,vic,41.93158979329575,2.2532355073830876,,41.93158979329575_2.2532355073830876_vic_google_maps_image,,41.93158979329575_2.2532355073830876_vic_google_satellite_image,,41.93158979329575_2.2532355073830876_vic_google_street_view_image,, -6174756170,2,vic,41.932361099731935,2.252339171013428,,41.932361099731935_2.252339171013428_vic_google_maps_image,,41.932361099731935_2.252339171013428_vic_google_satellite_image,,41.932361099731935_2.252339171013428_vic_google_street_view_image,, -3310768356,3,vic,41.92830423599381,2.248130428573768,,41.92830423599381_2.248130428573768_vic_google_maps_image,,41.92830423599381_2.248130428573768_vic_google_satellite_image,,41.92830423599381_2.248130428573768_vic_google_street_view_image,, -6221769270,3,vic,41.928622245214314,2.252229973267793,,41.928622245214314_2.252229973267793_vic_google_maps_image,,41.928622245214314_2.252229973267793_vic_google_satellite_image,,41.928622245214314_2.252229973267793_vic_google_street_view_image,, -3239150438,3,vic,41.93019663333702,2.261418397729625,,41.93019663333702_2.261418397729625_vic_google_maps_image,,41.93019663333702_2.261418397729625_vic_google_satellite_image,,41.93019663333702_2.261418397729625_vic_google_street_view_image,, -6221830425,3,vic,41.9316973344315,2.253122683235833,,41.9316973344315_2.253122683235833_vic_google_maps_image,,41.9316973344315_2.253122683235833_vic_google_satellite_image,,41.9316973344315_2.253122683235833_vic_google_street_view_image,, -6511493370,3,vic,41.933819643216054,2.25541238048663,,41.933819643216054_2.25541238048663_vic_google_maps_image,,41.933819643216054_2.25541238048663_vic_google_satellite_image,,41.933819643216054_2.25541238048663_vic_google_street_view_image,, -4054362919,3,vic,41.930833697354764,2.2567110589958728,,41.930833697354764_2.2567110589958728_vic_google_maps_image,,41.930833697354764_2.2567110589958728_vic_google_satellite_image,,41.930833697354764_2.2567110589958728_vic_google_street_view_image,, -6174756416,3,vic,41.92995846424069,2.250996213619746,,41.92995846424069_2.250996213619746_vic_google_maps_image,,41.92995846424069_2.250996213619746_vic_google_satellite_image,,41.92995846424069_2.250996213619746_vic_google_street_view_image,, -289341146,3,vic,41.92961906273809,2.2500734974518433,,41.92961906273809_2.2500734974518433_vic_google_maps_image,,41.92961906273809_2.2500734974518433_vic_google_satellite_image,,41.92961906273809_2.2500734974518433_vic_google_street_view_image,, -6221769264,3,vic,41.927823602894655,2.252526720530348,,41.927823602894655_2.252526720530348_vic_google_maps_image,,41.927823602894655_2.252526720530348_vic_google_satellite_image,,41.927823602894655_2.252526720530348_vic_google_street_view_image,, -5831644537,3,vic,41.92955120048565,2.256683913695918,,41.92955120048565_2.256683913695918_vic_google_maps_image,,41.92955120048565_2.256683913695918_vic_google_satellite_image,,41.92955120048565_2.256683913695918_vic_google_street_view_image,, -6572679122,4,vic,41.9299291072068,2.25529491630342,,41.9299291072068_2.25529491630342_vic_google_maps_image,,41.9299291072068_2.25529491630342_vic_google_satellite_image,,41.9299291072068_2.25529491630342_vic_google_street_view_image,, -5231525318,4,vic,41.9303113790793,2.2530391278103425,,41.9303113790793_2.2530391278103425_vic_google_maps_image,,41.9303113790793_2.2530391278103425_vic_google_satellite_image,,41.9303113790793_2.2530391278103425_vic_google_street_view_image,, -6572717480,4,vic,41.93041883380873,2.255422718181759,,41.93041883380873_2.255422718181759_vic_google_maps_image,,41.93041883380873_2.255422718181759_vic_google_satellite_image,,41.93041883380873_2.255422718181759_vic_google_street_view_image,, -6192655185,4,vic,41.93043425659179,2.2553907717776633,,41.93043425659179_2.2553907717776633_vic_google_maps_image,,41.93043425659179_2.2553907717776633_vic_google_satellite_image,,41.93043425659179_2.2553907717776633_vic_google_street_view_image,, -5231526025,4,vic,41.930324965092844,2.25355176315105,,41.930324965092844_2.25355176315105_vic_google_maps_image,,41.930324965092844_2.25355176315105_vic_google_satellite_image,,41.930324965092844_2.25355176315105_vic_google_street_view_image,, -6221709554,4,vic,41.92962532429341,2.2527247381848343,,41.92962532429341_2.2527247381848343_vic_google_maps_image,,41.92962532429341_2.2527247381848343_vic_google_satellite_image,,41.92962532429341_2.2527247381848343_vic_google_street_view_image,, -6572717470,4,vic,41.93054518126139,2.255076751562613,,41.93054518126139_2.255076751562613_vic_google_maps_image,,41.93054518126139_2.255076751562613_vic_google_satellite_image,,41.93054518126139_2.255076751562613_vic_google_street_view_image,, -6572679127,4,vic,41.92942883494961,2.2555289786388455,,41.92942883494961_2.2555289786388455_vic_google_maps_image,,41.92942883494961_2.2555289786388455_vic_google_satellite_image,,41.92942883494961_2.2555289786388455_vic_google_street_view_image,, -6221843896,4,vic,41.92983091398559,2.2553254315873508,,41.92983091398559_2.2553254315873508_vic_google_maps_image,,41.92983091398559_2.2553254315873508_vic_google_satellite_image,,41.92983091398559_2.2553254315873508_vic_google_street_view_image,, -6572717464,4,vic,41.930062075977744,2.255387188833223,,41.930062075977744_2.255387188833223_vic_google_maps_image,,41.930062075977744_2.255387188833223_vic_google_satellite_image,,41.930062075977744_2.255387188833223_vic_google_street_view_image,, -5231526042,5,vic,41.93029281775988,2.253701522883409,,41.93029281775988_2.253701522883409_vic_google_maps_image,,41.93029281775988_2.253701522883409_vic_google_satellite_image,,41.93029281775988_2.253701522883409_vic_google_street_view_image,, -5231526036,5,vic,41.93029087489445,2.253710573771352,,41.93029087489445_2.253710573771352_vic_google_maps_image,,41.93029087489445_2.253710573771352_vic_google_satellite_image,,41.93029087489445_2.253710573771352_vic_google_street_view_image,, -6221784183,5,vic,41.93105379519471,2.253357778265639,,41.93105379519471_2.253357778265639_vic_google_maps_image,,41.93105379519471_2.253357778265639_vic_google_satellite_image,,41.93105379519471_2.253357778265639_vic_google_street_view_image,, -5231526051,5,vic,41.930304811576846,2.253645649295967,,41.930304811576846_2.253645649295967_vic_google_maps_image,,41.930304811576846_2.253645649295967_vic_google_satellite_image,,41.930304811576846_2.253645649295967_vic_google_street_view_image,, -5231526034,5,vic,41.93024301431513,2.2539738226618553,,41.93024301431513_2.2539738226618553_vic_google_maps_image,,41.93024301431513_2.2539738226618553_vic_google_satellite_image,,41.93024301431513_2.2539738226618553_vic_google_street_view_image,, -6221769242,5,vic,41.93069498079539,2.2531102025309533,,41.93069498079539_2.2531102025309533_vic_google_maps_image,,41.93069498079539_2.2531102025309533_vic_google_satellite_image,,41.93069498079539_2.2531102025309533_vic_google_street_view_image,, -6221769241,5,vic,41.9308045941191,2.2531616066270255,,41.9308045941191_2.2531616066270255_vic_google_maps_image,,41.9308045941191_2.2531616066270255_vic_google_satellite_image,,41.9308045941191_2.2531616066270255_vic_google_street_view_image,, -6056018558,5,vic,41.9304936,2.2529112000000002,,41.9304936_2.2529112000000002_vic_google_maps_image,,41.9304936_2.2529112000000002_vic_google_satellite_image,,41.9304936_2.2529112000000002_vic_google_street_view_image,, -6572679134,5,vic,41.93092216011053,2.2537976150351313,,41.93092216011053_2.2537976150351313_vic_google_maps_image,,41.93092216011053_2.2537976150351313_vic_google_satellite_image,,41.93092216011053_2.2537976150351313_vic_google_street_view_image,, -5231525303,5,vic,41.9308269,2.2539109,,41.9308269_2.2539109_vic_google_maps_image,,41.9308269_2.2539109_vic_google_satellite_image,,41.9308269_2.2539109_vic_google_street_view_image,, +,Hexagon_Pop_Quintile,City_Name,Latitude,Longitude,Google_Maps_Date,Google_Maps_Screenshot,Google_Satellite_Date,Google_Satellite_Screenshot,Google_Street_View_Date,Google_Street_View_Screenshot,Assessment,Comments +554005639,1,adelaide,-35.143438257775365,138.51536002777152,,-35.143438257775365_138.51536002777152_adelaide_google_maps_image,,-35.143438257775365_138.51536002777152_adelaide_google_satellite_image,,-35.143438257775365_138.51536002777152_adelaide_google_street_view_image,, +4836645274,1,adelaide,-34.86514799001913,138.5803557751897,,-34.86514799001913_138.5803557751897_adelaide_google_maps_image,,-34.86514799001913_138.5803557751897_adelaide_google_satellite_image,,-34.86514799001913_138.5803557751897_adelaide_google_street_view_image,, +2424960625,1,adelaide,-34.76357904120694,138.63967983856986,,-34.76357904120694_138.63967983856986_adelaide_google_maps_image,,-34.76357904120694_138.63967983856986_adelaide_google_satellite_image,,-34.76357904120694_138.63967983856986_adelaide_google_street_view_image,, +5330994352,1,adelaide,-35.106989199999674,138.5209602,,-35.106989199999674_138.5209602_adelaide_google_maps_image,,-35.106989199999674_138.5209602_adelaide_google_satellite_image,,-35.106989199999674_138.5209602_adelaide_google_street_view_image,, +2029087875,1,adelaide,-35.0783784187871,138.51632720510028,,-35.0783784187871_138.51632720510028_adelaide_google_maps_image,,-35.0783784187871_138.51632720510028_adelaide_google_satellite_image,,-35.0783784187871_138.51632720510028_adelaide_google_street_view_image,, +5344476192,1,adelaide,-35.143583429488004,138.49892445433653,,-35.143583429488004_138.49892445433653_adelaide_google_maps_image,,-35.143583429488004_138.49892445433653_adelaide_google_satellite_image,,-35.143583429488004_138.49892445433653_adelaide_google_street_view_image,, +4835897220,1,adelaide,-34.8807639145066,138.49080207813984,,-34.8807639145066_138.49080207813984_adelaide_google_maps_image,,-34.8807639145066_138.49080207813984_adelaide_google_satellite_image,,-34.8807639145066_138.49080207813984_adelaide_google_street_view_image,, +4504321790,1,adelaide,-34.83022588935792,138.69150549539364,,-34.83022588935792_138.69150549539364_adelaide_google_maps_image,,-34.83022588935792_138.69150549539364_adelaide_google_satellite_image,,-34.83022588935792_138.69150549539364_adelaide_google_street_view_image,, +653722296,1,adelaide,-34.93503095760668,138.5233089708756,,-34.93503095760668_138.5233089708756_adelaide_google_maps_image,,-34.93503095760668_138.5233089708756_adelaide_google_satellite_image,,-34.93503095760668_138.5233089708756_adelaide_google_street_view_image,, +5411249887,1,adelaide,-35.08979629131564,138.54053603057898,,-35.08979629131564_138.54053603057898_adelaide_google_maps_image,,-35.08979629131564_138.54053603057898_adelaide_google_satellite_image,,-35.08979629131564_138.54053603057898_adelaide_google_street_view_image,, +5062044427,2,adelaide,-34.92461232633713,138.6758709298667,,-34.92461232633713_138.6758709298667_adelaide_google_maps_image,,-34.92461232633713_138.6758709298667_adelaide_google_satellite_image,,-34.92461232633713_138.6758709298667_adelaide_google_street_view_image,, +2396009490,2,adelaide,-34.87399205684018,138.54941641900663,,-34.87399205684018_138.54941641900663_adelaide_google_maps_image,,-34.87399205684018_138.54941641900663_adelaide_google_satellite_image,,-34.87399205684018_138.54941641900663_adelaide_google_street_view_image,, +6251187686,2,adelaide,-34.9255422399459,138.66330807616768,,-34.9255422399459_138.66330807616768_adelaide_google_maps_image,,-34.9255422399459_138.66330807616768_adelaide_google_satellite_image,,-34.9255422399459_138.66330807616768_adelaide_google_street_view_image,, +451871161,2,adelaide,-34.87412100705163,138.54887612296613,,-34.87412100705163_138.54887612296613_adelaide_google_maps_image,,-34.87412100705163_138.54887612296613_adelaide_google_satellite_image,,-34.87412100705163_138.54887612296613_adelaide_google_street_view_image,, +581224379,2,adelaide,-35.01595031912655,138.52212632385462,,-35.01595031912655_138.52212632385462_adelaide_google_maps_image,,-35.01595031912655_138.52212632385462_adelaide_google_satellite_image,,-35.01595031912655_138.52212632385462_adelaide_google_street_view_image,, +4449963307,2,adelaide,-34.86955596867659,138.52934424630982,,-34.86955596867659_138.52934424630982_adelaide_google_maps_image,,-34.86955596867659_138.52934424630982_adelaide_google_satellite_image,,-34.86955596867659_138.52934424630982_adelaide_google_street_view_image,, +3475954745,2,adelaide,-35.083634984404576,138.56148516157248,,-35.083634984404576_138.56148516157248_adelaide_google_maps_image,,-35.083634984404576_138.56148516157248_adelaide_google_satellite_image,,-35.083634984404576_138.56148516157248_adelaide_google_street_view_image,, +7628155095,2,adelaide,-34.915732357477715,138.6282090255454,,-34.915732357477715_138.6282090255454_adelaide_google_maps_image,,-34.915732357477715_138.6282090255454_adelaide_google_satellite_image,,-34.915732357477715_138.6282090255454_adelaide_google_street_view_image,, +4504307296,2,adelaide,-34.815610148888986,138.69952115036799,,-34.815610148888986_138.69952115036799_adelaide_google_maps_image,,-34.815610148888986_138.69952115036799_adelaide_google_satellite_image,,-34.815610148888986_138.69952115036799_adelaide_google_street_view_image,, +247052429,2,adelaide,-34.89667491882652,138.55682957362384,,-34.89667491882652_138.55682957362384_adelaide_google_maps_image,,-34.89667491882652_138.55682957362384_adelaide_google_satellite_image,,-34.89667491882652_138.55682957362384_adelaide_google_street_view_image,, +6917370085,3,adelaide,-34.90501225689983,138.6561626164692,,-34.90501225689983_138.6561626164692_adelaide_google_maps_image,,-34.90501225689983_138.6561626164692_adelaide_google_satellite_image,,-34.90501225689983_138.6561626164692_adelaide_google_street_view_image,, +187373304,3,adelaide,-34.85180479966862,138.52740469578174,,-34.85180479966862_138.52740469578174_adelaide_google_maps_image,,-34.85180479966862_138.52740469578174_adelaide_google_satellite_image,,-34.85180479966862_138.52740469578174_adelaide_google_street_view_image,, +854633067,3,adelaide,-34.82109013748485,138.71803898114976,,-34.82109013748485_138.71803898114976_adelaide_google_maps_image,,-34.82109013748485_138.71803898114976_adelaide_google_satellite_image,,-34.82109013748485_138.71803898114976_adelaide_google_street_view_image,, +5279252491,3,adelaide,-34.82902578582543,138.67302537884981,,-34.82902578582543_138.67302537884981_adelaide_google_maps_image,,-34.82902578582543_138.67302537884981_adelaide_google_satellite_image,,-34.82902578582543_138.67302537884981_adelaide_google_street_view_image,, +5276627283,3,adelaide,-34.82956401883604,138.6721821352397,,-34.82956401883604_138.6721821352397_adelaide_google_maps_image,,-34.82956401883604_138.6721821352397_adelaide_google_satellite_image,,-34.82956401883604_138.6721821352397_adelaide_google_street_view_image,, +6109038000,3,adelaide,-34.9127703739852,138.67381743342398,,-34.9127703739852_138.67381743342398_adelaide_google_maps_image,,-34.9127703739852_138.67381743342398_adelaide_google_satellite_image,,-34.9127703739852_138.67381743342398_adelaide_google_street_view_image,, +5279252487,3,adelaide,-34.8290433668837,138.67277678975933,,-34.8290433668837_138.67277678975933_adelaide_google_maps_image,,-34.8290433668837_138.67277678975933_adelaide_google_satellite_image,,-34.8290433668837_138.67277678975933_adelaide_google_street_view_image,, +848338230,3,adelaide,-34.874987384168534,138.60159693909236,,-34.874987384168534_138.60159693909236_adelaide_google_maps_image,,-34.874987384168534_138.60159693909236_adelaide_google_satellite_image,,-34.874987384168534_138.60159693909236_adelaide_google_street_view_image,, +447248196,3,adelaide,-34.881058732570345,138.50305979874994,,-34.881058732570345_138.50305979874994_adelaide_google_maps_image,,-34.881058732570345_138.50305979874994_adelaide_google_satellite_image,,-34.881058732570345_138.50305979874994_adelaide_google_street_view_image,, +820424383,3,adelaide,-34.87137581396339,138.7007071923653,,-34.87137581396339_138.7007071923653_adelaide_google_maps_image,,-34.87137581396339_138.7007071923653_adelaide_google_satellite_image,,-34.87137581396339_138.7007071923653_adelaide_google_street_view_image,, +4405228845,4,adelaide,-34.90715509841505,138.59500975793637,,-34.90715509841505_138.59500975793637_adelaide_google_maps_image,,-34.90715509841505_138.59500975793637_adelaide_google_satellite_image,,-34.90715509841505_138.59500975793637_adelaide_google_street_view_image,, +280726477,4,adelaide,-34.95677451738414,138.61477356864373,,-34.95677451738414_138.61477356864373_adelaide_google_maps_image,,-34.95677451738414_138.61477356864373_adelaide_google_satellite_image,,-34.95677451738414_138.61477356864373_adelaide_google_street_view_image,, +2391427400,4,adelaide,-34.90422128999778,138.53066007756823,,-34.90422128999778_138.53066007756823_adelaide_google_maps_image,,-34.90422128999778_138.53066007756823_adelaide_google_satellite_image,,-34.90422128999778_138.53066007756823_adelaide_google_street_view_image,, +5121171286,4,adelaide,-34.89668430471438,138.56536930825325,,-34.89668430471438_138.56536930825325_adelaide_google_maps_image,,-34.89668430471438_138.56536930825325_adelaide_google_satellite_image,,-34.89668430471438_138.56536930825325_adelaide_google_street_view_image,, +2311759501,4,adelaide,-34.91402682289617,138.51424705983135,,-34.91402682289617_138.51424705983135_adelaide_google_maps_image,,-34.91402682289617_138.51424705983135_adelaide_google_satellite_image,,-34.91402682289617_138.51424705983135_adelaide_google_street_view_image,, +2382205204,4,adelaide,-34.85885216244488,138.51962228074902,,-34.85885216244488_138.51962228074902_adelaide_google_maps_image,,-34.85885216244488_138.51962228074902_adelaide_google_satellite_image,,-34.85885216244488_138.51962228074902_adelaide_google_street_view_image,, +479978814,4,adelaide,-34.91446893866868,138.65049014346167,,-34.91446893866868_138.65049014346167_adelaide_google_maps_image,,-34.91446893866868_138.65049014346167_adelaide_google_satellite_image,,-34.91446893866868_138.65049014346167_adelaide_google_street_view_image,, +4438466555,4,adelaide,-34.838636248512685,138.48282194704367,,-34.838636248512685_138.48282194704367_adelaide_google_maps_image,,-34.838636248512685_138.48282194704367_adelaide_google_satellite_image,,-34.838636248512685_138.48282194704367_adelaide_google_street_view_image,, +1868639259,4,adelaide,-34.951825516900925,138.5896636665884,,-34.951825516900925_138.5896636665884_adelaide_google_maps_image,,-34.951825516900925_138.5896636665884_adelaide_google_satellite_image,,-34.951825516900925_138.5896636665884_adelaide_google_street_view_image,, +215062216,4,adelaide,-34.89417336602643,138.56850229074618,,-34.89417336602643_138.56850229074618_adelaide_google_maps_image,,-34.89417336602643_138.56850229074618_adelaide_google_satellite_image,,-34.89417336602643_138.56850229074618_adelaide_google_street_view_image,, +5842960944,5,adelaide,-34.99323107858127,138.56558272241966,,-34.99323107858127_138.56558272241966_adelaide_google_maps_image,,-34.99323107858127_138.56558272241966_adelaide_google_satellite_image,,-34.99323107858127_138.56558272241966_adelaide_google_street_view_image,, +2285373485,5,adelaide,-34.890121587327116,138.57255248555282,,-34.890121587327116_138.57255248555282_adelaide_google_maps_image,,-34.890121587327116_138.57255248555282_adelaide_google_satellite_image,,-34.890121587327116_138.57255248555282_adelaide_google_street_view_image,, +2534586738,5,adelaide,-34.919480495980906,138.51440408277762,,-34.919480495980906_138.51440408277762_adelaide_google_maps_image,,-34.919480495980906_138.51440408277762_adelaide_google_satellite_image,,-34.919480495980906_138.51440408277762_adelaide_google_street_view_image,, +6839233326,5,adelaide,-34.935479273282624,138.63165544920383,,-34.935479273282624_138.63165544920383_adelaide_google_maps_image,,-34.935479273282624_138.63165544920383_adelaide_google_satellite_image,,-34.935479273282624_138.63165544920383_adelaide_google_street_view_image,, +2980575418,5,adelaide,-34.92701442181462,138.65032928948548,,-34.92701442181462_138.65032928948548_adelaide_google_maps_image,,-34.92701442181462_138.65032928948548_adelaide_google_satellite_image,,-34.92701442181462_138.65032928948548_adelaide_google_street_view_image,, +93730429,5,adelaide,-34.92450814949956,138.56186630060256,,-34.92450814949956_138.56186630060256_adelaide_google_maps_image,,-34.92450814949956_138.56186630060256_adelaide_google_satellite_image,,-34.92450814949956_138.56186630060256_adelaide_google_street_view_image,, +1475563597,5,adelaide,-34.77100408312502,138.70648617736288,,-34.77100408312502_138.70648617736288_adelaide_google_maps_image,,-34.77100408312502_138.70648617736288_adelaide_google_satellite_image,,-34.77100408312502_138.70648617736288_adelaide_google_street_view_image,, +6649086885,5,adelaide,-34.91521456266078,138.6319643493004,,-34.91521456266078_138.6319643493004_adelaide_google_maps_image,,-34.91521456266078_138.6319643493004_adelaide_google_satellite_image,,-34.91521456266078_138.6319643493004_adelaide_google_street_view_image,, +1252175664,5,adelaide,-34.83876587531177,138.48385950390235,,-34.83876587531177_138.48385950390235_adelaide_google_maps_image,,-34.83876587531177_138.48385950390235_adelaide_google_satellite_image,,-34.83876587531177_138.48385950390235_adelaide_google_street_view_image,, +314933815,5,adelaide,-34.92742142924,138.65036126675705,,-34.92742142924_138.65036126675705_adelaide_google_maps_image,,-34.92742142924_138.65036126675705_adelaide_google_satellite_image,,-34.92742142924_138.65036126675705_adelaide_google_street_view_image,, +3659973168,1,auckland,-37.0123038643229,174.87616226747159,,-37.0123038643229_174.87616226747159_auckland_google_maps_image,,-37.0123038643229_174.87616226747159_auckland_google_satellite_image,,-37.0123038643229_174.87616226747159_auckland_google_street_view_image,, +4855099660,1,auckland,-36.85230735334339,174.6305803216304,,-36.85230735334339_174.6305803216304_auckland_google_maps_image,,-36.85230735334339_174.6305803216304_auckland_google_satellite_image,,-36.85230735334339_174.6305803216304_auckland_google_street_view_image,, +4855100403,1,auckland,-36.8551879,174.6313899,,-36.8551879_174.6313899_auckland_google_maps_image,,-36.8551879_174.6313899_auckland_google_satellite_image,,-36.8551879_174.6313899_auckland_google_street_view_image,, +5177815913,1,auckland,-36.91124247786922,174.8717508552371,,-36.91124247786922_174.8717508552371_auckland_google_maps_image,,-36.91124247786922_174.8717508552371_auckland_google_satellite_image,,-36.91124247786922_174.8717508552371_auckland_google_street_view_image,, +7689836586,1,auckland,-36.98687240951792,174.88409615465378,,-36.98687240951792_174.88409615465378_auckland_google_maps_image,,-36.98687240951792_174.88409615465378_auckland_google_satellite_image,,-36.98687240951792_174.88409615465378_auckland_google_street_view_image,, +3431101850,1,auckland,-36.77068322884491,174.73638456093389,,-36.77068322884491_174.73638456093389_auckland_google_maps_image,,-36.77068322884491_174.73638456093389_auckland_google_satellite_image,,-36.77068322884491_174.73638456093389_auckland_google_street_view_image,, +5151218411,1,auckland,-36.9661074,174.825764,,-36.9661074_174.825764_auckland_google_maps_image,,-36.9661074_174.825764_auckland_google_satellite_image,,-36.9661074_174.825764_auckland_google_street_view_image,, +5340052864,1,auckland,-36.95765570087596,174.85489039668784,,-36.95765570087596_174.85489039668784_auckland_google_maps_image,,-36.95765570087596_174.85489039668784_auckland_google_satellite_image,,-36.95765570087596_174.85489039668784_auckland_google_street_view_image,, +3994429764,1,auckland,-36.88629305046057,174.62833822862814,,-36.88629305046057_174.62833822862814_auckland_google_maps_image,,-36.88629305046057_174.62833822862814_auckland_google_satellite_image,,-36.88629305046057_174.62833822862814_auckland_google_street_view_image,, +3674684238,1,auckland,-36.94446439564092,174.88154172041084,,-36.94446439564092_174.88154172041084_auckland_google_maps_image,,-36.94446439564092_174.88154172041084_auckland_google_satellite_image,,-36.94446439564092_174.88154172041084_auckland_google_street_view_image,, +5057225422,2,auckland,-36.73925599999999,174.7533953,,-36.73925599999999_174.7533953_auckland_google_maps_image,,-36.73925599999999_174.7533953_auckland_google_satellite_image,,-36.73925599999999_174.7533953_auckland_google_street_view_image,, +5013799076,2,auckland,-37.06635380639986,174.94363464509547,,-37.06635380639986_174.94363464509547_auckland_google_maps_image,,-37.06635380639986_174.94363464509547_auckland_google_satellite_image,,-37.06635380639986_174.94363464509547_auckland_google_street_view_image,, +5013799341,2,auckland,-37.060683426914245,174.94246060181297,,-37.060683426914245_174.94246060181297_auckland_google_maps_image,,-37.060683426914245_174.94246060181297_auckland_google_satellite_image,,-37.060683426914245_174.94246060181297_auckland_google_street_view_image,, +5053006713,2,auckland,-37.014600500142166,174.87531565797755,,-37.014600500142166_174.87531565797755_auckland_google_maps_image,,-37.014600500142166_174.87531565797755_auckland_google_satellite_image,,-37.014600500142166_174.87531565797755_auckland_google_street_view_image,, +58841005,2,auckland,-36.857804406017856,174.6285448423473,,-36.857804406017856_174.6285448423473_auckland_google_maps_image,,-36.857804406017856_174.6285448423473_auckland_google_satellite_image,,-36.857804406017856_174.6285448423473_auckland_google_street_view_image,, +5057225481,2,auckland,-36.7397777733357,174.7420585598188,,-36.7397777733357_174.7420585598188_auckland_google_maps_image,,-36.7397777733357_174.7420585598188_auckland_google_satellite_image,,-36.7397777733357_174.7420585598188_auckland_google_street_view_image,, +2100727882,2,auckland,-36.86041563483351,174.83002652722683,,-36.86041563483351_174.83002652722683_auckland_google_maps_image,,-36.86041563483351_174.83002652722683_auckland_google_satellite_image,,-36.86041563483351_174.83002652722683_auckland_google_street_view_image,, +5913292093,2,auckland,-36.81157979999999,174.7236332,,-36.81157979999999_174.7236332_auckland_google_maps_image,,-36.81157979999999_174.7236332_auckland_google_satellite_image,,-36.81157979999999_174.7236332_auckland_google_street_view_image,, +2158628064,2,auckland,-36.81134228695914,174.724357840925,,-36.81134228695914_174.724357840925_auckland_google_maps_image,,-36.81134228695914_174.724357840925_auckland_google_satellite_image,,-36.81134228695914_174.724357840925_auckland_google_street_view_image,, +5029943787,2,auckland,-36.94158769880559,174.8412085213773,,-36.94158769880559_174.8412085213773_auckland_google_maps_image,,-36.94158769880559_174.8412085213773_auckland_google_satellite_image,,-36.94158769880559_174.8412085213773_auckland_google_street_view_image,, +4956180988,3,auckland,-36.92219517307905,174.71275760580338,,-36.92219517307905_174.71275760580338_auckland_google_maps_image,,-36.92219517307905_174.71275760580338_auckland_google_satellite_image,,-36.92219517307905_174.71275760580338_auckland_google_street_view_image,, +5047602337,3,auckland,-36.759760467319325,174.74043690103835,,-36.759760467319325_174.74043690103835_auckland_google_maps_image,,-36.759760467319325_174.74043690103835_auckland_google_satellite_image,,-36.759760467319325_174.74043690103835_auckland_google_street_view_image,, +5843116420,3,auckland,-36.91058855691557,174.6506670263708,,-36.91058855691557_174.6506670263708_auckland_google_maps_image,,-36.91058855691557_174.6506670263708_auckland_google_satellite_image,,-36.91058855691557_174.6506670263708_auckland_google_street_view_image,, +4410690791,3,auckland,-36.788972690095086,174.77124843534293,,-36.788972690095086_174.77124843534293_auckland_google_maps_image,,-36.788972690095086_174.77124843534293_auckland_google_satellite_image,,-36.788972690095086_174.77124843534293_auckland_google_street_view_image,, +2100719532,3,auckland,-36.85304193432865,174.8438125745177,,-36.85304193432865_174.8438125745177_auckland_google_maps_image,,-36.85304193432865_174.8438125745177_auckland_google_satellite_image,,-36.85304193432865_174.8438125745177_auckland_google_street_view_image,, +3472437512,3,auckland,-36.761737169587754,174.7248816671117,,-36.761737169587754_174.7248816671117_auckland_google_maps_image,,-36.761737169587754_174.7248816671117_auckland_google_satellite_image,,-36.761737169587754_174.7248816671117_auckland_google_street_view_image,, +4855260710,3,auckland,-36.86399800770286,174.61454105099645,,-36.86399800770286_174.61454105099645_auckland_google_maps_image,,-36.86399800770286_174.61454105099645_auckland_google_satellite_image,,-36.86399800770286_174.61454105099645_auckland_google_street_view_image,, +5141828308,3,auckland,-36.91048484845646,174.65267470821254,,-36.91048484845646_174.65267470821254_auckland_google_maps_image,,-36.91048484845646_174.65267470821254_auckland_google_satellite_image,,-36.91048484845646_174.65267470821254_auckland_google_street_view_image,, +353564209,3,auckland,-36.73959434641423,174.75308288672272,,-36.73959434641423_174.75308288672272_auckland_google_maps_image,,-36.73959434641423_174.75308288672272_auckland_google_satellite_image,,-36.73959434641423_174.75308288672272_auckland_google_street_view_image,, +62280838,3,auckland,-36.913266215446306,174.87154351203284,,-36.913266215446306_174.87154351203284_auckland_google_maps_image,,-36.913266215446306_174.87154351203284_auckland_google_satellite_image,,-36.913266215446306_174.87154351203284_auckland_google_street_view_image,, +1290034835,4,auckland,-36.85009499027466,174.8422411427827,,-36.85009499027466_174.8422411427827_auckland_google_maps_image,,-36.85009499027466_174.8422411427827_auckland_google_satellite_image,,-36.85009499027466_174.8422411427827_auckland_google_street_view_image,, +7590567639,4,auckland,-36.85414327072335,174.71834991372967,,-36.85414327072335_174.71834991372967_auckland_google_maps_image,,-36.85414327072335_174.71834991372967_auckland_google_satellite_image,,-36.85414327072335_174.71834991372967_auckland_google_street_view_image,, +5030003412,4,auckland,-36.970325293939915,174.8455994863601,,-36.970325293939915_174.8455994863601_auckland_google_maps_image,,-36.970325293939915_174.8455994863601_auckland_google_satellite_image,,-36.970325293939915_174.8455994863601_auckland_google_street_view_image,, +5057172416,4,auckland,-36.72875048956933,174.73092146931623,,-36.72875048956933_174.73092146931623_auckland_google_maps_image,,-36.72875048956933_174.73092146931623_auckland_google_satellite_image,,-36.72875048956933_174.73092146931623_auckland_google_street_view_image,, +4910282473,4,auckland,-36.886728003214174,174.64499210347978,,-36.886728003214174_174.64499210347978_auckland_google_maps_image,,-36.886728003214174_174.64499210347978_auckland_google_satellite_image,,-36.886728003214174_174.64499210347978_auckland_google_street_view_image,, +4910282488,4,auckland,-36.873713619123286,174.64564486859268,,-36.873713619123286_174.64564486859268_auckland_google_maps_image,,-36.873713619123286_174.64564486859268_auckland_google_satellite_image,,-36.873713619123286_174.64564486859268_auckland_google_street_view_image,, +3666604236,4,auckland,-36.90601107118147,174.927522034169,,-36.90601107118147_174.927522034169_auckland_google_maps_image,,-36.90601107118147_174.927522034169_auckland_google_satellite_image,,-36.90601107118147_174.927522034169_auckland_google_street_view_image,, +5156242297,4,auckland,-36.85666338583509,174.7461853366752,,-36.85666338583509_174.7461853366752_auckland_google_maps_image,,-36.85666338583509_174.7461853366752_auckland_google_satellite_image,,-36.85666338583509_174.7461853366752_auckland_google_street_view_image,, +778150745,4,auckland,-36.90379339825787,174.9246612720973,,-36.90379339825787_174.9246612720973_auckland_google_maps_image,,-36.90379339825787_174.9246612720973_auckland_google_satellite_image,,-36.90379339825787_174.9246612720973_auckland_google_street_view_image,, +3456962101,4,auckland,-36.783199383644046,174.73136534153699,,-36.783199383644046_174.73136534153699_auckland_google_maps_image,,-36.783199383644046_174.73136534153699_auckland_google_satellite_image,,-36.783199383644046_174.73136534153699_auckland_google_street_view_image,, +5151218092,5,auckland,-36.97250488941118,174.8339127736801,,-36.97250488941118_174.8339127736801_auckland_google_maps_image,,-36.97250488941118_174.8339127736801_auckland_google_satellite_image,,-36.97250488941118_174.8339127736801_auckland_google_street_view_image,, +336630320,5,auckland,-36.899454368584195,174.74442028356722,,-36.899454368584195_174.74442028356722_auckland_google_maps_image,,-36.899454368584195_174.74442028356722_auckland_google_satellite_image,,-36.899454368584195_174.74442028356722_auckland_google_street_view_image,, +3380256432,5,auckland,-36.8578308703826,174.7590550416262,,-36.8578308703826_174.7590550416262_auckland_google_maps_image,,-36.8578308703826_174.7590550416262_auckland_google_satellite_image,,-36.8578308703826_174.7590550416262_auckland_google_street_view_image,, +7092241148,5,auckland,-36.843970252262025,174.7654467733103,,-36.843970252262025_174.7654467733103_auckland_google_maps_image,,-36.843970252262025_174.7654467733103_auckland_google_satellite_image,,-36.843970252262025_174.7654467733103_auckland_google_street_view_image,, +6550726535,5,auckland,-36.89632105828324,174.7444358751894,,-36.89632105828324_174.7444358751894_auckland_google_maps_image,,-36.89632105828324_174.7444358751894_auckland_google_satellite_image,,-36.89632105828324_174.7444358751894_auckland_google_street_view_image,, +6294498985,5,auckland,-36.84704872130957,174.764541444604,,-36.84704872130957_174.764541444604_auckland_google_maps_image,,-36.84704872130957_174.764541444604_auckland_google_satellite_image,,-36.84704872130957_174.764541444604_auckland_google_street_view_image,, +6550726538,5,auckland,-36.90369310767926,174.74208431137032,,-36.90369310767926_174.74208431137032_auckland_google_maps_image,,-36.90369310767926_174.74208431137032_auckland_google_satellite_image,,-36.90369310767926_174.74208431137032_auckland_google_street_view_image,, +2632013352,5,auckland,-36.851099879142936,174.78218605394915,,-36.851099879142936_174.78218605394915_auckland_google_maps_image,,-36.851099879142936_174.78218605394915_auckland_google_satellite_image,,-36.851099879142936_174.78218605394915_auckland_google_street_view_image,, +4753906347,5,auckland,-36.85815036153281,174.76326572201035,,-36.85815036153281_174.76326572201035_auckland_google_maps_image,,-36.85815036153281_174.76326572201035_auckland_google_satellite_image,,-36.85815036153281_174.76326572201035_auckland_google_street_view_image,, +2700429659,5,auckland,-36.91075015517064,174.77551494456267,,-36.91075015517064_174.77551494456267_auckland_google_maps_image,,-36.91075015517064_174.77551494456267_auckland_google_satellite_image,,-36.91075015517064_174.77551494456267_auckland_google_street_view_image,, +6788833594,1,baltimore,39.4233411790282,-76.80627449740476,,39.4233411790282_-76.80627449740476_baltimore_google_maps_image,,39.4233411790282_-76.80627449740476_baltimore_google_satellite_image,,39.4233411790282_-76.80627449740476_baltimore_google_street_view_image,, +159115264,1,baltimore,39.43063976267354,-76.62319629306191,,39.43063976267354_-76.62319629306191_baltimore_google_maps_image,,39.43063976267354_-76.62319629306191_baltimore_google_satellite_image,,39.43063976267354_-76.62319629306191_baltimore_google_street_view_image,, +240449342,1,baltimore,39.25910014320543,-76.66205846388277,,39.25910014320543_-76.66205846388277_baltimore_google_maps_image,,39.25910014320543_-76.66205846388277_baltimore_google_satellite_image,,39.25910014320543_-76.66205846388277_baltimore_google_street_view_image,, +717794789,1,baltimore,39.4059062575352,-76.79085344090109,,39.4059062575352_-76.79085344090109_baltimore_google_maps_image,,39.4059062575352_-76.79085344090109_baltimore_google_satellite_image,,39.4059062575352_-76.79085344090109_baltimore_google_street_view_image,, +298710396,1,baltimore,39.378303448947314,-76.62602690183553,,39.378303448947314_-76.62602690183553_baltimore_google_maps_image,,39.378303448947314_-76.62602690183553_baltimore_google_satellite_image,,39.378303448947314_-76.62602690183553_baltimore_google_street_view_image,, +3847890557,1,baltimore,39.44413103913071,-76.62477305633409,,39.44413103913071_-76.62477305633409_baltimore_google_maps_image,,39.44413103913071_-76.62477305633409_baltimore_google_satellite_image,,39.44413103913071_-76.62477305633409_baltimore_google_street_view_image,, +171582462,1,baltimore,39.293889918897214,-76.69549060376814,,39.293889918897214_-76.69549060376814_baltimore_google_maps_image,,39.293889918897214_-76.69549060376814_baltimore_google_satellite_image,,39.293889918897214_-76.69549060376814_baltimore_google_street_view_image,, +6006099656,1,baltimore,39.36558914520734,-76.64764743396593,,39.36558914520734_-76.64764743396593_baltimore_google_maps_image,,39.36558914520734_-76.64764743396593_baltimore_google_satellite_image,,39.36558914520734_-76.64764743396593_baltimore_google_street_view_image,, +53101339,1,baltimore,39.497432335179106,-76.65639733239344,,39.497432335179106_-76.65639733239344_baltimore_google_maps_image,,39.497432335179106_-76.65639733239344_baltimore_google_satellite_image,,39.497432335179106_-76.65639733239344_baltimore_google_street_view_image,, +2501047707,1,baltimore,39.20694080101815,-76.68987617685923,,39.20694080101815_-76.68987617685923_baltimore_google_maps_image,,39.20694080101815_-76.68987617685923_baltimore_google_satellite_image,,39.20694080101815_-76.68987617685923_baltimore_google_street_view_image,, +114497307,2,baltimore,39.332824358711,-76.44579139898003,,39.332824358711_-76.44579139898003_baltimore_google_maps_image,,39.332824358711_-76.44579139898003_baltimore_google_satellite_image,,39.332824358711_-76.44579139898003_baltimore_google_street_view_image,, +398700992,2,baltimore,39.39745705328534,-76.58441516443344,,39.39745705328534_-76.58441516443344_baltimore_google_maps_image,,39.39745705328534_-76.58441516443344_baltimore_google_satellite_image,,39.39745705328534_-76.58441516443344_baltimore_google_street_view_image,, +65162501,2,baltimore,39.337651400664235,-76.48735615147646,,39.337651400664235_-76.48735615147646_baltimore_google_maps_image,,39.337651400664235_-76.48735615147646_baltimore_google_satellite_image,,39.337651400664235_-76.48735615147646_baltimore_google_street_view_image,, +170399584,2,baltimore,39.26797712306708,-76.59965174147638,,39.26797712306708_-76.59965174147638_baltimore_google_maps_image,,39.26797712306708_-76.59965174147638_baltimore_google_satellite_image,,39.26797712306708_-76.59965174147638_baltimore_google_street_view_image,, +3025614615,2,baltimore,39.40734936949507,-76.51486168800021,,39.40734936949507_-76.51486168800021_baltimore_google_maps_image,,39.40734936949507_-76.51486168800021_baltimore_google_satellite_image,,39.40734936949507_-76.51486168800021_baltimore_google_street_view_image,, +298914425,2,baltimore,39.316480399999996,-76.450541,,39.316480399999996_-76.450541_baltimore_google_maps_image,,39.316480399999996_-76.450541_baltimore_google_satellite_image,,39.316480399999996_-76.450541_baltimore_google_street_view_image,, +3659200044,2,baltimore,39.1363823242475,-76.58519239985915,,39.1363823242475_-76.58519239985915_baltimore_google_maps_image,,39.1363823242475_-76.58519239985915_baltimore_google_satellite_image,,39.1363823242475_-76.58519239985915_baltimore_google_street_view_image,, +2480610216,2,baltimore,39.290163999331064,-76.60470509178845,,39.290163999331064_-76.60470509178845_baltimore_google_maps_image,,39.290163999331064_-76.60470509178845_baltimore_google_satellite_image,,39.290163999331064_-76.60470509178845_baltimore_google_street_view_image,, +185219339,2,baltimore,39.271721103427105,-76.73330303621823,,39.271721103427105_-76.73330303621823_baltimore_google_maps_image,,39.271721103427105_-76.73330303621823_baltimore_google_satellite_image,,39.271721103427105_-76.73330303621823_baltimore_google_street_view_image,, +123758634,2,baltimore,39.39714878746854,-76.47983381163374,,39.39714878746854_-76.47983381163374_baltimore_google_maps_image,,39.39714878746854_-76.47983381163374_baltimore_google_satellite_image,,39.39714878746854_-76.47983381163374_baltimore_google_street_view_image,, +1595567254,3,baltimore,39.265931223927645,-76.69894114775624,,39.265931223927645_-76.69894114775624_baltimore_google_maps_image,,39.265931223927645_-76.69894114775624_baltimore_google_satellite_image,,39.265931223927645_-76.69894114775624_baltimore_google_street_view_image,, +336192613,3,baltimore,39.3348220568945,-76.55635564015755,,39.3348220568945_-76.55635564015755_baltimore_google_maps_image,,39.3348220568945_-76.55635564015755_baltimore_google_satellite_image,,39.3348220568945_-76.55635564015755_baltimore_google_street_view_image,, +3025590016,3,baltimore,39.3986970128765,-76.53735207273031,,39.3986970128765_-76.53735207273031_baltimore_google_maps_image,,39.3986970128765_-76.53735207273031_baltimore_google_satellite_image,,39.3986970128765_-76.53735207273031_baltimore_google_street_view_image,, +55547321,3,baltimore,39.418486420085195,-76.77610848698835,,39.418486420085195_-76.77610848698835_baltimore_google_maps_image,,39.418486420085195_-76.77610848698835_baltimore_google_satellite_image,,39.418486420085195_-76.77610848698835_baltimore_google_street_view_image,, +6125944256,3,baltimore,39.330141261084336,-76.51981640528915,,39.330141261084336_-76.51981640528915_baltimore_google_maps_image,,39.330141261084336_-76.51981640528915_baltimore_google_satellite_image,,39.330141261084336_-76.51981640528915_baltimore_google_street_view_image,, +299154086,3,baltimore,39.27113085390868,-76.50433059093905,,39.27113085390868_-76.50433059093905_baltimore_google_maps_image,,39.27113085390868_-76.50433059093905_baltimore_google_satellite_image,,39.27113085390868_-76.50433059093905_baltimore_google_street_view_image,, +3026454268,3,baltimore,39.32498787603193,-76.44971426346432,,39.32498787603193_-76.44971426346432_baltimore_google_maps_image,,39.32498787603193_-76.44971426346432_baltimore_google_satellite_image,,39.32498787603193_-76.44971426346432_baltimore_google_street_view_image,, +336301885,3,baltimore,39.26896901481033,-76.59427641580616,,39.26896901481033_-76.59427641580616_baltimore_google_maps_image,,39.26896901481033_-76.59427641580616_baltimore_google_satellite_image,,39.26896901481033_-76.59427641580616_baltimore_google_street_view_image,, +7470873582,3,baltimore,39.33467001873526,-76.55657744021252,,39.33467001873526_-76.55657744021252_baltimore_google_maps_image,,39.33467001873526_-76.55657744021252_baltimore_google_satellite_image,,39.33467001873526_-76.55657744021252_baltimore_google_street_view_image,, +592868020,3,baltimore,39.15070596165896,-76.61478102753644,,39.15070596165896_-76.61478102753644_baltimore_google_maps_image,,39.15070596165896_-76.61478102753644_baltimore_google_satellite_image,,39.15070596165896_-76.61478102753644_baltimore_google_street_view_image,, +90694903,4,baltimore,39.26069287089995,-76.6964529057291,,39.26069287089995_-76.6964529057291_baltimore_google_maps_image,,39.26069287089995_-76.6964529057291_baltimore_google_satellite_image,,39.26069287089995_-76.6964529057291_baltimore_google_street_view_image,, +132459599,4,baltimore,39.440539961786364,-76.80761292001905,,39.440539961786364_-76.80761292001905_baltimore_google_maps_image,,39.440539961786364_-76.80761292001905_baltimore_google_satellite_image,,39.440539961786364_-76.80761292001905_baltimore_google_street_view_image,, +279142464,4,baltimore,39.38849047002029,-76.507715266536,,39.38849047002029_-76.507715266536_baltimore_google_maps_image,,39.38849047002029_-76.507715266536_baltimore_google_satellite_image,,39.38849047002029_-76.507715266536_baltimore_google_street_view_image,, +4741601565,4,baltimore,39.32596190007805,-76.60941149999078,,39.32596190007805_-76.60941149999078_baltimore_google_maps_image,,39.32596190007805_-76.60941149999078_baltimore_google_satellite_image,,39.32596190007805_-76.60941149999078_baltimore_google_street_view_image,, +336204596,4,baltimore,39.35160931830831,-76.56205966383047,,39.35160931830831_-76.56205966383047_baltimore_google_maps_image,,39.35160931830831_-76.56205966383047_baltimore_google_satellite_image,,39.35160931830831_-76.56205966383047_baltimore_google_street_view_image,, +3025607108,4,baltimore,39.38015920459807,-76.53736644235391,,39.38015920459807_-76.53736644235391_baltimore_google_maps_image,,39.38015920459807_-76.53736644235391_baltimore_google_satellite_image,,39.38015920459807_-76.53736644235391_baltimore_google_street_view_image,, +5553735127,4,baltimore,39.3578727619507,-76.70653734963494,,39.3578727619507_-76.70653734963494_baltimore_google_maps_image,,39.3578727619507_-76.70653734963494_baltimore_google_satellite_image,,39.3578727619507_-76.70653734963494_baltimore_google_street_view_image,, +232497151,4,baltimore,39.13320128021018,-76.6380396730981,,39.13320128021018_-76.6380396730981_baltimore_google_maps_image,,39.13320128021018_-76.6380396730981_baltimore_google_satellite_image,,39.13320128021018_-76.6380396730981_baltimore_google_street_view_image,, +5282843923,4,baltimore,39.28957119999999,-76.6163313,,39.28957119999999_-76.6163313_baltimore_google_maps_image,,39.28957119999999_-76.6163313_baltimore_google_satellite_image,,39.28957119999999_-76.6163313_baltimore_google_street_view_image,, +191346993,4,baltimore,39.3599678596374,-76.70896674598472,,39.3599678596374_-76.70896674598472_baltimore_google_maps_image,,39.3599678596374_-76.70896674598472_baltimore_google_satellite_image,,39.3599678596374_-76.70896674598472_baltimore_google_street_view_image,, +336223822,5,baltimore,39.288567240907916,-76.56939001745654,,39.288567240907916_-76.56939001745654_baltimore_google_maps_image,,39.288567240907916_-76.56939001745654_baltimore_google_satellite_image,,39.288567240907916_-76.56939001745654_baltimore_google_street_view_image,, +1148183217,5,baltimore,39.32648248924767,-76.61578784619739,,39.32648248924767_-76.61578784619739_baltimore_google_maps_image,,39.32648248924767_-76.61578784619739_baltimore_google_satellite_image,,39.32648248924767_-76.61578784619739_baltimore_google_street_view_image,, +4567907233,5,baltimore,39.2922446,-76.6154321,,39.2922446_-76.6154321_baltimore_google_maps_image,,39.2922446_-76.6154321_baltimore_google_satellite_image,,39.2922446_-76.6154321_baltimore_google_street_view_image,, +-8955169,5,baltimore,39.2876445516368,-76.63595807648218,,39.2876445516368_-76.63595807648218_baltimore_google_maps_image,,39.2876445516368_-76.63595807648218_baltimore_google_satellite_image,,39.2876445516368_-76.63595807648218_baltimore_google_street_view_image,, +1577067795,5,baltimore,39.40545679565556,-76.60218683482036,,39.40545679565556_-76.60218683482036_baltimore_google_maps_image,,39.40545679565556_-76.60218683482036_baltimore_google_satellite_image,,39.40545679565556_-76.60218683482036_baltimore_google_street_view_image,, +531133208,5,baltimore,39.336198800000005,-76.630839,,39.336198800000005_-76.630839_baltimore_google_maps_image,,39.336198800000005_-76.630839_baltimore_google_satellite_image,,39.336198800000005_-76.630839_baltimore_google_street_view_image,, +337536824,5,baltimore,39.31787662110797,-76.57695883835787,,39.31787662110797_-76.57695883835787_baltimore_google_maps_image,,39.31787662110797_-76.57695883835787_baltimore_google_satellite_image,,39.31787662110797_-76.57695883835787_baltimore_google_street_view_image,, +336373055,5,baltimore,39.30319629525222,-76.61672785460912,,39.30319629525222_-76.61672785460912_baltimore_google_maps_image,,39.30319629525222_-76.61672785460912_baltimore_google_satellite_image,,39.30319629525222_-76.61672785460912_baltimore_google_street_view_image,, +177620353,5,baltimore,39.28054171449186,-76.57922596957705,,39.28054171449186_-76.57922596957705_baltimore_google_maps_image,,39.28054171449186_-76.57922596957705_baltimore_google_satellite_image,,39.28054171449186_-76.57922596957705_baltimore_google_street_view_image,, +241571290,5,baltimore,39.28304077179726,-76.65303217347157,,39.28304077179726_-76.65303217347157_baltimore_google_maps_image,,39.28304077179726_-76.65303217347157_baltimore_google_satellite_image,,39.28304077179726_-76.65303217347157_baltimore_google_street_view_image,, +1597529880,1,bangkok,13.849674666522924,100.56412825333632,,13.849674666522924_100.56412825333632_bangkok_google_maps_image,,13.849674666522924_100.56412825333632_bangkok_google_satellite_image,,13.849674666522924_100.56412825333632_bangkok_google_street_view_image,, +99450842,1,bangkok,13.663941097975266,100.44033266743412,,13.663941097975266_100.44033266743412_bangkok_google_maps_image,,13.663941097975266_100.44033266743412_bangkok_google_satellite_image,,13.663941097975266_100.44033266743412_bangkok_google_street_view_image,, +4527517188,1,bangkok,13.68418019485134,100.35383788054041,,13.68418019485134_100.35383788054041_bangkok_google_maps_image,,13.68418019485134_100.35383788054041_bangkok_google_satellite_image,,13.68418019485134_100.35383788054041_bangkok_google_street_view_image,, +449808122,1,bangkok,13.826270499999998,100.660181,,13.826270499999998_100.660181_bangkok_google_maps_image,,13.826270499999998_100.660181_bangkok_google_satellite_image,,13.826270499999998_100.660181_bangkok_google_street_view_image,, +6068369586,1,bangkok,13.921726005157476,100.65509470090788,,13.921726005157476_100.65509470090788_bangkok_google_maps_image,,13.921726005157476_100.65509470090788_bangkok_google_satellite_image,,13.921726005157476_100.65509470090788_bangkok_google_street_view_image,, +5267492421,1,bangkok,13.739108751720089,100.54669161246598,,13.739108751720089_100.54669161246598_bangkok_google_maps_image,,13.739108751720089_100.54669161246598_bangkok_google_satellite_image,,13.739108751720089_100.54669161246598_bangkok_google_street_view_image,, +2299993194,1,bangkok,13.738186600000002,100.5419478,,13.738186600000002_100.5419478_bangkok_google_maps_image,,13.738186600000002_100.5419478_bangkok_google_satellite_image,,13.738186600000002_100.5419478_bangkok_google_street_view_image,, +316417449,1,bangkok,13.80009594699123,100.64857930681839,,13.80009594699123_100.64857930681839_bangkok_google_maps_image,,13.80009594699123_100.64857930681839_bangkok_google_satellite_image,,13.80009594699123_100.64857930681839_bangkok_google_street_view_image,, +34499729,1,bangkok,13.685836437274048,100.66919727929407,,13.685836437274048_100.66919727929407_bangkok_google_maps_image,,13.685836437274048_100.66919727929407_bangkok_google_satellite_image,,13.685836437274048_100.66919727929407_bangkok_google_street_view_image,, +5088450302,1,bangkok,13.757085510664185,100.7902633392472,,13.757085510664185_100.7902633392472_bangkok_google_maps_image,,13.757085510664185_100.7902633392472_bangkok_google_satellite_image,,13.757085510664185_100.7902633392472_bangkok_google_street_view_image,, +5355896404,2,bangkok,13.92171352822775,100.68303227353393,,13.92171352822775_100.68303227353393_bangkok_google_maps_image,,13.92171352822775_100.68303227353393_bangkok_google_satellite_image,,13.92171352822775_100.68303227353393_bangkok_google_street_view_image,, +187179977,2,bangkok,13.862260032763633,100.61509916896114,,13.862260032763633_100.61509916896114_bangkok_google_maps_image,,13.862260032763633_100.61509916896114_bangkok_google_satellite_image,,13.862260032763633_100.61509916896114_bangkok_google_street_view_image,, +2099171796,2,bangkok,13.839248897426966,100.55062176545533,,13.839248897426966_100.55062176545533_bangkok_google_maps_image,,13.839248897426966_100.55062176545533_bangkok_google_satellite_image,,13.839248897426966_100.55062176545533_bangkok_google_street_view_image,, +196107455,2,bangkok,13.7044804965112,100.50319049066647,,13.7044804965112_100.50319049066647_bangkok_google_maps_image,,13.7044804965112_100.50319049066647_bangkok_google_satellite_image,,13.7044804965112_100.50319049066647_bangkok_google_street_view_image,, +7231919792,2,bangkok,13.704040520596246,100.41983606169232,,13.704040520596246_100.41983606169232_bangkok_google_maps_image,,13.704040520596246_100.41983606169232_bangkok_google_satellite_image,,13.704040520596246_100.41983606169232_bangkok_google_street_view_image,, +3502221453,2,bangkok,13.67400026747181,100.54545081466276,,13.67400026747181_100.54545081466276_bangkok_google_maps_image,,13.67400026747181_100.54545081466276_bangkok_google_satellite_image,,13.67400026747181_100.54545081466276_bangkok_google_street_view_image,, +199926245,2,bangkok,13.838829729806958,100.55055706909236,,13.838829729806958_100.55055706909236_bangkok_google_maps_image,,13.838829729806958_100.55055706909236_bangkok_google_satellite_image,,13.838829729806958_100.55055706909236_bangkok_google_street_view_image,, +156723174,2,bangkok,13.894608399999996,100.560209,,13.894608399999996_100.560209_bangkok_google_maps_image,,13.894608399999996_100.560209_bangkok_google_satellite_image,,13.894608399999996_100.560209_bangkok_google_street_view_image,, +6059978137,2,bangkok,13.81888669165045,100.59202180477908,,13.81888669165045_100.59202180477908_bangkok_google_maps_image,,13.81888669165045_100.59202180477908_bangkok_google_satellite_image,,13.81888669165045_100.59202180477908_bangkok_google_street_view_image,, +199926216,2,bangkok,13.83924870565924,100.55062122501938,,13.83924870565924_100.55062122501938_bangkok_google_maps_image,,13.83924870565924_100.55062122501938_bangkok_google_satellite_image,,13.83924870565924_100.55062122501938_bangkok_google_street_view_image,, +323347384,3,bangkok,13.722820680400257,100.58425388173939,,13.722820680400257_100.58425388173939_bangkok_google_maps_image,,13.722820680400257_100.58425388173939_bangkok_google_satellite_image,,13.722820680400257_100.58425388173939_bangkok_google_street_view_image,, +3860265993,3,bangkok,13.7375072,100.5603419,,13.7375072_100.5603419_bangkok_google_maps_image,,13.7375072_100.5603419_bangkok_google_satellite_image,,13.7375072_100.5603419_bangkok_google_street_view_image,, +4254764090,3,bangkok,13.756675002646817,100.49809935754523,,13.756675002646817_100.49809935754523_bangkok_google_maps_image,,13.756675002646817_100.49809935754523_bangkok_google_satellite_image,,13.756675002646817_100.49809935754523_bangkok_google_street_view_image,, +4815734522,3,bangkok,13.741276266080995,100.51288782506194,,13.741276266080995_100.51288782506194_bangkok_google_maps_image,,13.741276266080995_100.51288782506194_bangkok_google_satellite_image,,13.741276266080995_100.51288782506194_bangkok_google_street_view_image,, +697558275,3,bangkok,13.813600183249362,100.7281142422845,,13.813600183249362_100.7281142422845_bangkok_google_maps_image,,13.813600183249362_100.7281142422845_bangkok_google_satellite_image,,13.813600183249362_100.7281142422845_bangkok_google_street_view_image,, +7325627585,3,bangkok,13.6823919930044,100.4817063781228,,13.6823919930044_100.4817063781228_bangkok_google_maps_image,,13.6823919930044_100.4817063781228_bangkok_google_satellite_image,,13.6823919930044_100.4817063781228_bangkok_google_street_view_image,, +1063290343,3,bangkok,13.887247021114556,100.58180629374222,,13.887247021114556_100.58180629374222_bangkok_google_maps_image,,13.887247021114556_100.58180629374222_bangkok_google_satellite_image,,13.887247021114556_100.58180629374222_bangkok_google_street_view_image,, +5902026985,3,bangkok,13.744430298673507,100.53028243550618,,13.744430298673507_100.53028243550618_bangkok_google_maps_image,,13.744430298673507_100.53028243550618_bangkok_google_satellite_image,,13.744430298673507_100.53028243550618_bangkok_google_street_view_image,, +214152293,3,bangkok,13.770340137126484,100.50340521130626,,13.770340137126484_100.50340521130626_bangkok_google_maps_image,,13.770340137126484_100.50340521130626_bangkok_google_satellite_image,,13.770340137126484_100.50340521130626_bangkok_google_street_view_image,, +7178945686,3,bangkok,13.777436806101173,100.58002187593789,,13.777436806101173_100.58002187593789_bangkok_google_maps_image,,13.777436806101173_100.58002187593789_bangkok_google_satellite_image,,13.777436806101173_100.58002187593789_bangkok_google_street_view_image,, +231732621,4,bangkok,13.897297025748712,100.60866550173242,,13.897297025748712_100.60866550173242_bangkok_google_maps_image,,13.897297025748712_100.60866550173242_bangkok_google_satellite_image,,13.897297025748712_100.60866550173242_bangkok_google_street_view_image,, +4668717191,4,bangkok,13.75479678929426,100.53269881020535,,13.75479678929426_100.53269881020535_bangkok_google_maps_image,,13.75479678929426_100.53269881020535_bangkok_google_satellite_image,,13.75479678929426_100.53269881020535_bangkok_google_street_view_image,, +151991140,4,bangkok,13.736418994555205,100.5239963012267,,13.736418994555205_100.5239963012267_bangkok_google_maps_image,,13.736418994555205_100.5239963012267_bangkok_google_satellite_image,,13.736418994555205_100.5239963012267_bangkok_google_street_view_image,, +228106721,4,bangkok,13.751600476542638,100.54379975850526,,13.751600476542638_100.54379975850526_bangkok_google_maps_image,,13.751600476542638_100.54379975850526_bangkok_google_satellite_image,,13.751600476542638_100.54379975850526_bangkok_google_street_view_image,, +3316629478,4,bangkok,13.733979750071622,100.58010836491863,,13.733979750071622_100.58010836491863_bangkok_google_maps_image,,13.733979750071622_100.58010836491863_bangkok_google_satellite_image,,13.733979750071622_100.58010836491863_bangkok_google_street_view_image,, +5363677833,4,bangkok,13.764555105168348,100.52676876880163,,13.764555105168348_100.52676876880163_bangkok_google_maps_image,,13.764555105168348_100.52676876880163_bangkok_google_satellite_image,,13.764555105168348_100.52676876880163_bangkok_google_street_view_image,, +6594505985,4,bangkok,13.798984009688025,100.55027855033083,,13.798984009688025_100.55027855033083_bangkok_google_maps_image,,13.798984009688025_100.55027855033083_bangkok_google_satellite_image,,13.798984009688025_100.55027855033083_bangkok_google_street_view_image,, +224714999,4,bangkok,13.718502915421588,100.56028580034813,,13.718502915421588_100.56028580034813_bangkok_google_maps_image,,13.718502915421588_100.56028580034813_bangkok_google_satellite_image,,13.718502915421588_100.56028580034813_bangkok_google_street_view_image,, +4132492349,4,bangkok,13.772299367949945,100.61021978675944,,13.772299367949945_100.61021978675944_bangkok_google_maps_image,,13.772299367949945_100.61021978675944_bangkok_google_satellite_image,,13.772299367949945_100.61021978675944_bangkok_google_street_view_image,, +1639162480,4,bangkok,13.742169966563857,100.55420920715783,,13.742169966563857_100.55420920715783_bangkok_google_maps_image,,13.742169966563857_100.55420920715783_bangkok_google_satellite_image,,13.742169966563857_100.55420920715783_bangkok_google_street_view_image,, +379863487,5,bangkok,13.697578485629055,100.48264656045937,,13.697578485629055_100.48264656045937_bangkok_google_maps_image,,13.697578485629055_100.48264656045937_bangkok_google_satellite_image,,13.697578485629055_100.48264656045937_bangkok_google_street_view_image,, +322651065,5,bangkok,13.791357599999998,100.55006550000002,,13.791357599999998_100.55006550000002_bangkok_google_maps_image,,13.791357599999998_100.55006550000002_bangkok_google_satellite_image,,13.791357599999998_100.55006550000002_bangkok_google_street_view_image,, +103670923,5,bangkok,13.710950130603234,100.51807559270352,,13.710950130603234_100.51807559270352_bangkok_google_maps_image,,13.710950130603234_100.51807559270352_bangkok_google_satellite_image,,13.710950130603234_100.51807559270352_bangkok_google_street_view_image,, +320483765,5,bangkok,13.710856990950395,100.54208569095071,,13.710856990950395_100.54208569095071_bangkok_google_maps_image,,13.710856990950395_100.54208569095071_bangkok_google_satellite_image,,13.710856990950395_100.54208569095071_bangkok_google_street_view_image,, +139333081,5,bangkok,13.733140851361425,100.49331104304478,,13.733140851361425_100.49331104304478_bangkok_google_maps_image,,13.733140851361425_100.49331104304478_bangkok_google_satellite_image,,13.733140851361425_100.49331104304478_bangkok_google_street_view_image,, +4355467996,5,bangkok,13.728519803790471,100.50890907095493,,13.728519803790471_100.50890907095493_bangkok_google_maps_image,,13.728519803790471_100.50890907095493_bangkok_google_satellite_image,,13.728519803790471_100.50890907095493_bangkok_google_street_view_image,, +2280188077,5,bangkok,13.745435356214205,100.51108737637246,,13.745435356214205_100.51108737637246_bangkok_google_maps_image,,13.745435356214205_100.51108737637246_bangkok_google_satellite_image,,13.745435356214205_100.51108737637246_bangkok_google_street_view_image,, +637381858,5,bangkok,13.752907528303128,100.52829648506611,,13.752907528303128_100.52829648506611_bangkok_google_maps_image,,13.752907528303128_100.52829648506611_bangkok_google_satellite_image,,13.752907528303128_100.52829648506611_bangkok_google_street_view_image,, +6276438186,5,bangkok,13.795069872455473,100.55024689105696,,13.795069872455473_100.55024689105696_bangkok_google_maps_image,,13.795069872455473_100.55024689105696_bangkok_google_satellite_image,,13.795069872455473_100.55024689105696_bangkok_google_street_view_image,, +1597521876,5,bangkok,13.780167141032228,100.54553671463344,,13.780167141032228_100.54553671463344_bangkok_google_maps_image,,13.780167141032228_100.54553671463344_bangkok_google_satellite_image,,13.780167141032228_100.54553671463344_bangkok_google_street_view_image,, +4473660723,1,barcelona,41.4895879791037,2.133347205395721,,41.4895879791037_2.133347205395721_barcelona_google_maps_image,,41.4895879791037_2.133347205395721_barcelona_google_satellite_image,,41.4895879791037_2.133347205395721_barcelona_google_street_view_image,, +3153064305,1,barcelona,41.3615402665667,2.027783781857484,,41.3615402665667_2.027783781857484_barcelona_google_maps_image,,41.3615402665667_2.027783781857484_barcelona_google_satellite_image,,41.3615402665667_2.027783781857484_barcelona_google_street_view_image,, +6541474968,1,barcelona,41.493800006713336,2.142518825890501,,41.493800006713336_2.142518825890501_barcelona_google_maps_image,,41.493800006713336_2.142518825890501_barcelona_google_satellite_image,,41.493800006713336_2.142518825890501_barcelona_google_street_view_image,, +122820773,1,barcelona,41.50675777902313,2.118142981022385,,41.50675777902313_2.118142981022385_barcelona_google_maps_image,,41.50675777902313_2.118142981022385_barcelona_google_satellite_image,,41.50675777902313_2.118142981022385_barcelona_google_street_view_image,, +5827209216,1,barcelona,41.49520859831593,2.1565672248782466,,41.49520859831593_2.1565672248782466_barcelona_google_maps_image,,41.49520859831593_2.1565672248782466_barcelona_google_satellite_image,,41.49520859831593_2.1565672248782466_barcelona_google_street_view_image,, +3241096475,1,barcelona,41.32283441907746,2.1035026066796054,,41.32283441907746_2.1035026066796054_barcelona_google_maps_image,,41.32283441907746_2.1035026066796054_barcelona_google_satellite_image,,41.32283441907746_2.1035026066796054_barcelona_google_street_view_image,, +185078579,1,barcelona,41.281177606368935,1.9862486375777553,,41.281177606368935_1.9862486375777553_barcelona_google_maps_image,,41.281177606368935_1.9862486375777553_barcelona_google_satellite_image,,41.281177606368935_1.9862486375777553_barcelona_google_street_view_image,, +2383118579,1,barcelona,41.41807024022814,2.1489777740486167,,41.41807024022814_2.1489777740486167_barcelona_google_maps_image,,41.41807024022814_2.1489777740486167_barcelona_google_satellite_image,,41.41807024022814_2.1489777740486167_barcelona_google_street_view_image,, +6668763888,1,barcelona,41.48394959642878,2.1489991256680905,,41.48394959642878_2.1489991256680905_barcelona_google_maps_image,,41.48394959642878_2.1489991256680905_barcelona_google_satellite_image,,41.48394959642878_2.1489991256680905_barcelona_google_street_view_image,, +4767325124,1,barcelona,41.342716885596744,2.0404821316905717,,41.342716885596744_2.0404821316905717_barcelona_google_maps_image,,41.342716885596744_2.0404821316905717_barcelona_google_satellite_image,,41.342716885596744_2.0404821316905717_barcelona_google_street_view_image,, +3548613598,2,barcelona,41.43900573214387,2.2169882332044,,41.43900573214387_2.2169882332044_barcelona_google_maps_image,,41.43900573214387_2.2169882332044_barcelona_google_satellite_image,,41.43900573214387_2.2169882332044_barcelona_google_street_view_image,, +2175616321,2,barcelona,41.38681881765392,2.112393975494676,,41.38681881765392_2.112393975494676_barcelona_google_maps_image,,41.38681881765392_2.112393975494676_barcelona_google_satellite_image,,41.38681881765392_2.112393975494676_barcelona_google_street_view_image,, +2117060426,2,barcelona,41.446042070977235,2.240454811939617,,41.446042070977235_2.240454811939617_barcelona_google_maps_image,,41.446042070977235_2.240454811939617_barcelona_google_satellite_image,,41.446042070977235_2.240454811939617_barcelona_google_street_view_image,, +847721548,2,barcelona,41.416541117727974,2.1702805447835476,,41.416541117727974_2.1702805447835476_barcelona_google_maps_image,,41.416541117727974_2.1702805447835476_barcelona_google_satellite_image,,41.416541117727974_2.1702805447835476_barcelona_google_street_view_image,, +7518898718,2,barcelona,41.363394774902986,2.1001910882323513,,41.363394774902986_2.1001910882323513_barcelona_google_maps_image,,41.363394774902986_2.1001910882323513_barcelona_google_satellite_image,,41.363394774902986_2.1001910882323513_barcelona_google_street_view_image,, +7997135,2,barcelona,41.365532187425664,2.1272280534056254,,41.365532187425664_2.1272280534056254_barcelona_google_maps_image,,41.365532187425664_2.1272280534056254_barcelona_google_satellite_image,,41.365532187425664_2.1272280534056254_barcelona_google_street_view_image,, +2077932091,2,barcelona,41.37585041258002,2.1175734834996027,,41.37585041258002_2.1175734834996027_barcelona_google_maps_image,,41.37585041258002_2.1175734834996027_barcelona_google_satellite_image,,41.37585041258002_2.1175734834996027_barcelona_google_street_view_image,, +5484560922,2,barcelona,41.36052236121411,2.0751920444844303,,41.36052236121411_2.0751920444844303_barcelona_google_maps_image,,41.36052236121411_2.0751920444844303_barcelona_google_satellite_image,,41.36052236121411_2.0751920444844303_barcelona_google_street_view_image,, +2085728937,2,barcelona,41.39030417945104,2.197333972664933,,41.39030417945104_2.197333972664933_barcelona_google_maps_image,,41.39030417945104_2.197333972664933_barcelona_google_satellite_image,,41.39030417945104_2.197333972664933_barcelona_google_street_view_image,, +222540000,2,barcelona,41.36043452618159,2.0694254854974954,,41.36043452618159_2.0694254854974954_barcelona_google_maps_image,,41.36043452618159_2.0694254854974954_barcelona_google_satellite_image,,41.36043452618159_2.0694254854974954_barcelona_google_street_view_image,, +6334053690,3,barcelona,41.39997502161453,2.1642509766203815,,41.39997502161453_2.1642509766203815_barcelona_google_maps_image,,41.39997502161453_2.1642509766203815_barcelona_google_satellite_image,,41.39997502161453_2.1642509766203815_barcelona_google_street_view_image,, +1845294520,3,barcelona,41.40584326748737,2.1739842560263676,,41.40584326748737_2.1739842560263676_barcelona_google_maps_image,,41.40584326748737_2.1739842560263676_barcelona_google_satellite_image,,41.40584326748737_2.1739842560263676_barcelona_google_street_view_image,, +571182738,3,barcelona,41.44586509562727,2.1764751468105525,,41.44586509562727_2.1764751468105525_barcelona_google_maps_image,,41.44586509562727_2.1764751468105525_barcelona_google_satellite_image,,41.44586509562727_2.1764751468105525_barcelona_google_street_view_image,, +2430077720,3,barcelona,41.418157186374856,2.1897120399788963,,41.418157186374856_2.1897120399788963_barcelona_google_maps_image,,41.418157186374856_2.1897120399788963_barcelona_google_satellite_image,,41.418157186374856_2.1897120399788963_barcelona_google_street_view_image,, +6053049669,3,barcelona,41.38842342211086,2.1806763512511775,,41.38842342211086_2.1806763512511775_barcelona_google_maps_image,,41.38842342211086_2.1806763512511775_barcelona_google_satellite_image,,41.38842342211086_2.1806763512511775_barcelona_google_street_view_image,, +4172413190,3,barcelona,41.38626927156164,2.1575090346287396,,41.38626927156164_2.1575090346287396_barcelona_google_maps_image,,41.38626927156164_2.1575090346287396_barcelona_google_satellite_image,,41.38626927156164_2.1575090346287396_barcelona_google_street_view_image,, +4727188392,3,barcelona,41.40508581994903,2.166101531162817,,41.40508581994903_2.166101531162817_barcelona_google_maps_image,,41.40508581994903_2.166101531162817_barcelona_google_satellite_image,,41.40508581994903_2.166101531162817_barcelona_google_street_view_image,, +7704818549,3,barcelona,41.374684738362554,2.1329591281987113,,41.374684738362554_2.1329591281987113_barcelona_google_maps_image,,41.374684738362554_2.1329591281987113_barcelona_google_satellite_image,,41.374684738362554_2.1329591281987113_barcelona_google_street_view_image,, +7525316985,3,barcelona,41.41986976137159,2.174837906350266,,41.41986976137159_2.174837906350266_barcelona_google_maps_image,,41.41986976137159_2.174837906350266_barcelona_google_satellite_image,,41.41986976137159_2.174837906350266_barcelona_google_street_view_image,, +1361887258,3,barcelona,41.4055223899813,2.177394220288314,,41.4055223899813_2.177394220288314_barcelona_google_maps_image,,41.4055223899813_2.177394220288314_barcelona_google_satellite_image,,41.4055223899813_2.177394220288314_barcelona_google_street_view_image,, +4776901740,4,barcelona,41.38605912065319,2.1614010662356127,,41.38605912065319_2.1614010662356127_barcelona_google_maps_image,,41.38605912065319_2.1614010662356127_barcelona_google_satellite_image,,41.38605912065319_2.1614010662356127_barcelona_google_street_view_image,, +1755467726,4,barcelona,41.40559964124466,2.1533171848145565,,41.40559964124466_2.1533171848145565_barcelona_google_maps_image,,41.40559964124466_2.1533171848145565_barcelona_google_satellite_image,,41.40559964124466_2.1533171848145565_barcelona_google_street_view_image,, +5960931987,4,barcelona,41.386316601778674,2.1726872490633555,,41.386316601778674_2.1726872490633555_barcelona_google_maps_image,,41.386316601778674_2.1726872490633555_barcelona_google_satellite_image,,41.386316601778674_2.1726872490633555_barcelona_google_street_view_image,, +7556638085,4,barcelona,41.4045546587343,2.1965350895505966,,41.4045546587343_2.1965350895505966_barcelona_google_maps_image,,41.4045546587343_2.1965350895505966_barcelona_google_satellite_image,,41.4045546587343_2.1965350895505966_barcelona_google_street_view_image,, +5960910889,4,barcelona,41.38627721821352,2.1725983882403295,,41.38627721821352_2.1725983882403295_barcelona_google_maps_image,,41.38627721821352_2.1725983882403295_barcelona_google_satellite_image,,41.38627721821352_2.1725983882403295_barcelona_google_street_view_image,, +1357211197,4,barcelona,41.40400372828592,2.158059424491088,,41.40400372828592_2.158059424491088_barcelona_google_maps_image,,41.40400372828592_2.158059424491088_barcelona_google_satellite_image,,41.40400372828592_2.158059424491088_barcelona_google_street_view_image,, +1688067150,4,barcelona,41.38043701875776,2.129694498238833,,41.38043701875776_2.129694498238833_barcelona_google_maps_image,,41.38043701875776_2.129694498238833_barcelona_google_satellite_image,,41.38043701875776_2.129694498238833_barcelona_google_street_view_image,, +6247265677,4,barcelona,41.38187223172009,2.142160145424603,,41.38187223172009_2.142160145424603_barcelona_google_maps_image,,41.38187223172009_2.142160145424603_barcelona_google_satellite_image,,41.38187223172009_2.142160145424603_barcelona_google_street_view_image,, +4762854029,4,barcelona,41.38455407696959,2.163896302774564,,41.38455407696959_2.163896302774564_barcelona_google_maps_image,,41.38455407696959_2.163896302774564_barcelona_google_satellite_image,,41.38455407696959_2.163896302774564_barcelona_google_street_view_image,, +4873757769,4,barcelona,41.38507326909497,2.148620819331917,,41.38507326909497_2.148620819331917_barcelona_google_maps_image,,41.38507326909497_2.148620819331917_barcelona_google_satellite_image,,41.38507326909497_2.148620819331917_barcelona_google_street_view_image,, +1727174980,5,barcelona,41.427848511733906,2.1793931829707787,,41.427848511733906_2.1793931829707787_barcelona_google_maps_image,,41.427848511733906_2.1793931829707787_barcelona_google_satellite_image,,41.427848511733906_2.1793931829707787_barcelona_google_street_view_image,, +6823999785,5,barcelona,41.38365954857229,2.183888117131694,,41.38365954857229_2.183888117131694_barcelona_google_maps_image,,41.38365954857229_2.183888117131694_barcelona_google_satellite_image,,41.38365954857229_2.183888117131694_barcelona_google_street_view_image,, +4736328731,5,barcelona,41.38346002226871,2.129535922772446,,41.38346002226871_2.129535922772446_barcelona_google_maps_image,,41.38346002226871_2.129535922772446_barcelona_google_satellite_image,,41.38346002226871_2.129535922772446_barcelona_google_street_view_image,, +5972455502,5,barcelona,41.3972930253656,2.152248794029433,,41.3972930253656_2.152248794029433_barcelona_google_maps_image,,41.3972930253656_2.152248794029433_barcelona_google_satellite_image,,41.3972930253656_2.152248794029433_barcelona_google_street_view_image,, +7389224441,5,barcelona,41.45133085607761,2.2161410891877686,,41.45133085607761_2.2161410891877686_barcelona_google_maps_image,,41.45133085607761_2.2161410891877686_barcelona_google_satellite_image,,41.45133085607761_2.2161410891877686_barcelona_google_street_view_image,, +5845800585,5,barcelona,41.411752841906825,2.1795547060626808,,41.411752841906825_2.1795547060626808_barcelona_google_maps_image,,41.411752841906825_2.1795547060626808_barcelona_google_satellite_image,,41.411752841906825_2.1795547060626808_barcelona_google_street_view_image,, +4727951590,5,barcelona,41.41112276907388,2.182069305291159,,41.41112276907388_2.182069305291159_barcelona_google_maps_image,,41.41112276907388_2.182069305291159_barcelona_google_satellite_image,,41.41112276907388_2.182069305291159_barcelona_google_street_view_image,, +5531275475,5,barcelona,41.398135180878555,2.194259978287318,,41.398135180878555_2.194259978287318_barcelona_google_maps_image,,41.398135180878555_2.194259978287318_barcelona_google_satellite_image,,41.398135180878555_2.194259978287318_barcelona_google_street_view_image,, +1710707056,5,barcelona,41.38285172454865,2.1383177827340623,,41.38285172454865_2.1383177827340623_barcelona_google_maps_image,,41.38285172454865_2.1383177827340623_barcelona_google_satellite_image,,41.38285172454865_2.1383177827340623_barcelona_google_street_view_image,, +4727953590,5,barcelona,41.411863561247706,2.18112277770277,,41.411863561247706_2.18112277770277_barcelona_google_maps_image,,41.411863561247706_2.18112277770277_barcelona_google_satellite_image,,41.411863561247706_2.18112277770277_barcelona_google_street_view_image,, +3931020290,1,belfast,54.60010083094839,-5.925526950504084,,54.60010083094839_-5.925526950504084_belfast_google_maps_image,,54.60010083094839_-5.925526950504084_belfast_google_satellite_image,,54.60010083094839_-5.925526950504084_belfast_google_street_view_image,, +3930730200,1,belfast,54.6001966957186,-5.927904241881721,,54.6001966957186_-5.927904241881721_belfast_google_maps_image,,54.6001966957186_-5.927904241881721_belfast_google_satellite_image,,54.6001966957186_-5.927904241881721_belfast_google_street_view_image,, +4385113583,1,belfast,54.5980190649593,-5.932266684922414,,54.5980190649593_-5.932266684922414_belfast_google_maps_image,,54.5980190649593_-5.932266684922414_belfast_google_satellite_image,,54.5980190649593_-5.932266684922414_belfast_google_street_view_image,, +215403125,1,belfast,54.599454637088186,-5.931261126207947,,54.599454637088186_-5.931261126207947_belfast_google_maps_image,,54.599454637088186_-5.931261126207947_belfast_google_satellite_image,,54.599454637088186_-5.931261126207947_belfast_google_street_view_image,, +226265468,1,belfast,54.625673900755025,-5.913621390401916,,54.625673900755025_-5.913621390401916_belfast_google_maps_image,,54.625673900755025_-5.913621390401916_belfast_google_satellite_image,,54.625673900755025_-5.913621390401916_belfast_google_street_view_image,, +6732348036,1,belfast,54.59983195145868,-5.930568057575755,,54.59983195145868_-5.930568057575755_belfast_google_maps_image,,54.59983195145868_-5.930568057575755_belfast_google_satellite_image,,54.59983195145868_-5.930568057575755_belfast_google_street_view_image,, +5139201584,1,belfast,54.598031039303216,-5.931971211193691,,54.598031039303216_-5.931971211193691_belfast_google_maps_image,,54.598031039303216_-5.931971211193691_belfast_google_satellite_image,,54.598031039303216_-5.931971211193691_belfast_google_street_view_image,, +148530921,1,belfast,54.60801602110841,-5.968292699630438,,54.60801602110841_-5.968292699630438_belfast_google_maps_image,,54.60801602110841_-5.968292699630438_belfast_google_satellite_image,,54.60801602110841_-5.968292699630438_belfast_google_street_view_image,, +1667293021,1,belfast,54.65612560430331,-5.93387414093062,,54.65612560430331_-5.93387414093062_belfast_google_maps_image,,54.65612560430331_-5.93387414093062_belfast_google_satellite_image,,54.65612560430331_-5.93387414093062_belfast_google_street_view_image,, +1945583840,1,belfast,54.59779874205468,-5.9287751997175855,,54.59779874205468_-5.9287751997175855_belfast_google_maps_image,,54.59779874205468_-5.9287751997175855_belfast_google_satellite_image,,54.59779874205468_-5.9287751997175855_belfast_google_street_view_image,, +671740101,2,belfast,54.557540452669926,-6.025868780535815,,54.557540452669926_-6.025868780535815_belfast_google_maps_image,,54.557540452669926_-6.025868780535815_belfast_google_satellite_image,,54.557540452669926_-6.025868780535815_belfast_google_street_view_image,, +602205145,2,belfast,54.589637851659376,-5.844580448369623,,54.589637851659376_-5.844580448369623_belfast_google_maps_image,,54.589637851659376_-5.844580448369623_belfast_google_satellite_image,,54.589637851659376_-5.844580448369623_belfast_google_street_view_image,, +151506724,2,belfast,54.62774774330262,-5.921992750777932,,54.62774774330262_-5.921992750777932_belfast_google_maps_image,,54.62774774330262_-5.921992750777932_belfast_google_satellite_image,,54.62774774330262_-5.921992750777932_belfast_google_street_view_image,, +146477241,2,belfast,54.57893230432017,-5.978891660448143,,54.57893230432017_-5.978891660448143_belfast_google_maps_image,,54.57893230432017_-5.978891660448143_belfast_google_satellite_image,,54.57893230432017_-5.978891660448143_belfast_google_street_view_image,, +665148239,2,belfast,54.59597094181296,-5.892402925958394,,54.59597094181296_-5.892402925958394_belfast_google_maps_image,,54.59597094181296_-5.892402925958394_belfast_google_satellite_image,,54.59597094181296_-5.892402925958394_belfast_google_street_view_image,, +377474322,2,belfast,54.59047278932073,-5.91233954966689,,54.59047278932073_-5.91233954966689_belfast_google_maps_image,,54.59047278932073_-5.91233954966689_belfast_google_satellite_image,,54.59047278932073_-5.91233954966689_belfast_google_street_view_image,, +3178035574,2,belfast,54.582033900713185,-5.9777355904765255,,54.582033900713185_-5.9777355904765255_belfast_google_maps_image,,54.582033900713185_-5.9777355904765255_belfast_google_satellite_image,,54.582033900713185_-5.9777355904765255_belfast_google_street_view_image,, +560114632,2,belfast,54.55233231685459,-6.000363945445143,,54.55233231685459_-6.000363945445143_belfast_google_maps_image,,54.55233231685459_-6.000363945445143_belfast_google_satellite_image,,54.55233231685459_-6.000363945445143_belfast_google_street_view_image,, +6783379052,2,belfast,54.58951130071995,-5.961341290458311,,54.58951130071995_-5.961341290458311_belfast_google_maps_image,,54.58951130071995_-5.961341290458311_belfast_google_satellite_image,,54.58951130071995_-5.961341290458311_belfast_google_street_view_image,, +6895327586,2,belfast,54.58935064954835,-5.845127434255506,,54.58935064954835_-5.845127434255506_belfast_google_maps_image,,54.58935064954835_-5.845127434255506_belfast_google_satellite_image,,54.58935064954835_-5.845127434255506_belfast_google_street_view_image,, +769156357,3,belfast,54.595959052490066,-5.873499010142215,,54.595959052490066_-5.873499010142215_belfast_google_maps_image,,54.595959052490066_-5.873499010142215_belfast_google_satellite_image,,54.595959052490066_-5.873499010142215_belfast_google_street_view_image,, +3023216893,3,belfast,54.57335572469245,-5.931849125012466,,54.57335572469245_-5.931849125012466_belfast_google_maps_image,,54.57335572469245_-5.931849125012466_belfast_google_satellite_image,,54.57335572469245_-5.931849125012466_belfast_google_street_view_image,, +151506725,3,belfast,54.6270276398455,-5.924608165821086,,54.6270276398455_-5.924608165821086_belfast_google_maps_image,,54.6270276398455_-5.924608165821086_belfast_google_satellite_image,,54.6270276398455_-5.924608165821086_belfast_google_street_view_image,, +653139484,3,belfast,54.568829132910125,-5.913399650162852,,54.568829132910125_-5.913399650162852_belfast_google_maps_image,,54.568829132910125_-5.913399650162852_belfast_google_satellite_image,,54.568829132910125_-5.913399650162852_belfast_google_street_view_image,, +7004217324,3,belfast,54.58934165028636,-5.969118803104395,,54.58934165028636_-5.969118803104395_belfast_google_maps_image,,54.58934165028636_-5.969118803104395_belfast_google_satellite_image,,54.58934165028636_-5.969118803104395_belfast_google_street_view_image,, +389983466,3,belfast,54.56843874739376,-6.0081721672124715,,54.56843874739376_-6.0081721672124715_belfast_google_maps_image,,54.56843874739376_-6.0081721672124715_belfast_google_satellite_image,,54.56843874739376_-6.0081721672124715_belfast_google_street_view_image,, +1715618826,3,belfast,54.575843331527686,-5.896180850512349,,54.575843331527686_-5.896180850512349_belfast_google_maps_image,,54.575843331527686_-5.896180850512349_belfast_google_satellite_image,,54.575843331527686_-5.896180850512349_belfast_google_street_view_image,, +2096353580,3,belfast,54.584592789102366,-5.9226225644365735,,54.584592789102366_-5.9226225644365735_belfast_google_maps_image,,54.584592789102366_-5.9226225644365735_belfast_google_satellite_image,,54.584592789102366_-5.9226225644365735_belfast_google_street_view_image,, +161367736,3,belfast,54.59634880072208,-5.894502090389789,,54.59634880072208_-5.894502090389789_belfast_google_maps_image,,54.59634880072208_-5.894502090389789_belfast_google_satellite_image,,54.59634880072208_-5.894502090389789_belfast_google_street_view_image,, +7062914629,3,belfast,54.59019847907826,-5.9273093132071235,,54.59019847907826_-5.9273093132071235_belfast_google_maps_image,,54.59019847907826_-5.9273093132071235_belfast_google_satellite_image,,54.59019847907826_-5.9273093132071235_belfast_google_street_view_image,, +141747886,4,belfast,54.58165554077348,-5.923041738474682,,54.58165554077348_-5.923041738474682_belfast_google_maps_image,,54.58165554077348_-5.923041738474682_belfast_google_satellite_image,,54.58165554077348_-5.923041738474682_belfast_google_street_view_image,, +2445259295,4,belfast,54.591784725762835,-5.898864292852408,,54.591784725762835_-5.898864292852408_belfast_google_maps_image,,54.591784725762835_-5.898864292852408_belfast_google_satellite_image,,54.591784725762835_-5.898864292852408_belfast_google_street_view_image,, +2048688282,4,belfast,54.5786703019085,-5.919339849923161,,54.5786703019085_-5.919339849923161_belfast_google_maps_image,,54.5786703019085_-5.919339849923161_belfast_google_satellite_image,,54.5786703019085_-5.919339849923161_belfast_google_street_view_image,, +398720096,4,belfast,54.62614398827238,-5.937366566979514,,54.62614398827238_-5.937366566979514_belfast_google_maps_image,,54.62614398827238_-5.937366566979514_belfast_google_satellite_image,,54.62614398827238_-5.937366566979514_belfast_google_street_view_image,, +438772404,4,belfast,54.63103080076335,-5.946526690433616,,54.63103080076335_-5.946526690433616_belfast_google_maps_image,,54.63103080076335_-5.946526690433616_belfast_google_satellite_image,,54.63103080076335_-5.946526690433616_belfast_google_street_view_image,, +4393526723,4,belfast,54.622617800753645,-5.93775269042681,,54.622617800753645_-5.93775269042681_belfast_google_maps_image,,54.622617800753645_-5.93775269042681_belfast_google_satellite_image,,54.622617800753645_-5.93775269042681_belfast_google_street_view_image,, +7251887726,4,belfast,54.59464230071988,-5.88995019038565,,54.59464230071988_-5.88995019038565_belfast_google_maps_image,,54.59464230071988_-5.88995019038565_belfast_google_satellite_image,,54.59464230071988_-5.88995019038565_belfast_google_street_view_image,, +4038588698,4,belfast,54.578718093707224,-5.919376944580229,,54.578718093707224_-5.919376944580229_belfast_google_maps_image,,54.578718093707224_-5.919376944580229_belfast_google_satellite_image,,54.578718093707224_-5.919376944580229_belfast_google_street_view_image,, +298418084,4,belfast,54.588142990278335,-5.894104044995761,,54.588142990278335_-5.894104044995761_belfast_google_maps_image,,54.588142990278335_-5.894104044995761_belfast_google_satellite_image,,54.588142990278335_-5.894104044995761_belfast_google_street_view_image,, +211044241,4,belfast,54.61215233391405,-5.95565464274492,,54.61215233391405_-5.95565464274492_belfast_google_maps_image,,54.61215233391405_-5.95565464274492_belfast_google_satellite_image,,54.61215233391405_-5.95565464274492_belfast_google_street_view_image,, +621452538,5,belfast,54.58853545693416,-5.948497170439899,,54.58853545693416_-5.948497170439899_belfast_google_maps_image,,54.58853545693416_-5.948497170439899_belfast_google_satellite_image,,54.58853545693416_-5.948497170439899_belfast_google_street_view_image,, +2445264511,5,belfast,54.58871937386414,-5.900954150092114,,54.58871937386414_-5.900954150092114_belfast_google_maps_image,,54.58871937386414_-5.900954150092114_belfast_google_satellite_image,,54.58871937386414_-5.900954150092114_belfast_google_street_view_image,, +341513798,5,belfast,54.58147183129029,-5.9490978839627315,,54.58147183129029_-5.9490978839627315_belfast_google_maps_image,,54.58147183129029_-5.9490978839627315_belfast_google_satellite_image,,54.58147183129029_-5.9490978839627315_belfast_google_street_view_image,, +6997205819,5,belfast,54.598034848581946,-5.887563010140464,,54.598034848581946_-5.887563010140464_belfast_google_maps_image,,54.598034848581946_-5.887563010140464_belfast_google_satellite_image,,54.598034848581946_-5.887563010140464_belfast_google_street_view_image,, +2445232380,5,belfast,54.58730124785496,-5.9002784419032945,,54.58730124785496_-5.9002784419032945_belfast_google_maps_image,,54.58730124785496_-5.9002784419032945_belfast_google_satellite_image,,54.58730124785496_-5.9002784419032945_belfast_google_street_view_image,, +2445261883,5,belfast,54.59100740071698,-5.902541590399099,,54.59100740071698_-5.902541590399099_belfast_google_maps_image,,54.59100740071698_-5.902541590399099_belfast_google_satellite_image,,54.59100740071698_-5.902541590399099_belfast_google_street_view_image,, +618579152,5,belfast,54.59792560072871,-5.957815890452777,,54.59792560072871_-5.957815890452777_belfast_google_maps_image,,54.59792560072871_-5.957815890452777_belfast_google_satellite_image,,54.59792560072871_-5.957815890452777_belfast_google_street_view_image,, +4038588656,5,belfast,54.576002857018146,-5.917401539939645,,54.576002857018146_-5.917401539939645_belfast_google_maps_image,,54.576002857018146_-5.917401539939645_belfast_google_satellite_image,,54.576002857018146_-5.917401539939645_belfast_google_street_view_image,, +2445211936,5,belfast,54.5884374555479,-5.9009640012197275,,54.5884374555479_-5.9009640012197275_belfast_google_maps_image,,54.5884374555479_-5.9009640012197275_belfast_google_satellite_image,,54.5884374555479_-5.9009640012197275_belfast_google_street_view_image,, +2445264431,5,belfast,54.589053102101616,-5.90135543363438,,54.589053102101616_-5.90135543363438_belfast_google_maps_image,,54.589053102101616_-5.90135543363438_belfast_google_satellite_image,,54.589053102101616_-5.90135543363438_belfast_google_street_view_image,, +7640147839,1,bern,46.945370779062095,7.373375851987099,,46.945370779062095_7.373375851987099_bern_google_maps_image,,46.945370779062095_7.373375851987099_bern_google_satellite_image,,46.945370779062095_7.373375851987099_bern_google_street_view_image,, +-9364832,1,bern,46.94677253757923,7.451827340951852,,46.94677253757923_7.451827340951852_bern_google_maps_image,,46.94677253757923_7.451827340951852_bern_google_satellite_image,,46.94677253757923_7.451827340951852_bern_google_street_view_image,, +7601934683,1,bern,46.96794366206422,7.464499483905497,,46.96794366206422_7.464499483905497_bern_google_maps_image,,46.96794366206422_7.464499483905497_bern_google_satellite_image,,46.96794366206422_7.464499483905497_bern_google_street_view_image,, +3573717230,1,bern,46.943126550360304,7.450991486699755,,46.943126550360304_7.450991486699755_bern_google_maps_image,,46.943126550360304_7.450991486699755_bern_google_satellite_image,,46.943126550360304_7.450991486699755_bern_google_street_view_image,, +564771189,1,bern,46.942763996879144,7.443534413721496,,46.942763996879144_7.443534413721496_bern_google_maps_image,,46.942763996879144_7.443534413721496_bern_google_satellite_image,,46.942763996879144_7.443534413721496_bern_google_street_view_image,, +3345300147,1,bern,46.957235932037364,7.437179012336026,,46.957235932037364_7.437179012336026_bern_google_maps_image,,46.957235932037364_7.437179012336026_bern_google_satellite_image,,46.957235932037364_7.437179012336026_bern_google_street_view_image,, +3522686123,1,bern,46.95129769999999,7.3949183,,46.95129769999999_7.3949183_bern_google_maps_image,,46.95129769999999_7.3949183_bern_google_satellite_image,,46.95129769999999_7.3949183_bern_google_street_view_image,, +6166590461,1,bern,46.94978513901572,7.412526031790052,,46.94978513901572_7.412526031790052_bern_google_maps_image,,46.94978513901572_7.412526031790052_bern_google_satellite_image,,46.94978513901572_7.412526031790052_bern_google_street_view_image,, +536764788,1,bern,46.939578832630964,7.481465445792677,,46.939578832630964_7.481465445792677_bern_google_maps_image,,46.939578832630964_7.481465445792677_bern_google_satellite_image,,46.939578832630964_7.481465445792677_bern_google_street_view_image,, +536764783,1,bern,46.93940889228398,7.480728354644646,,46.93940889228398_7.480728354644646_bern_google_maps_image,,46.93940889228398_7.480728354644646_bern_google_satellite_image,,46.93940889228398_7.480728354644646_bern_google_street_view_image,, +7128513589,2,bern,46.9531668,7.458189000000003,,46.9531668_7.458189000000003_bern_google_maps_image,,46.9531668_7.458189000000003_bern_google_satellite_image,,46.9531668_7.458189000000003_bern_google_street_view_image,, +454141500,2,bern,46.94106028605951,7.418754624815147,,46.94106028605951_7.418754624815147_bern_google_maps_image,,46.94106028605951_7.418754624815147_bern_google_satellite_image,,46.94106028605951_7.418754624815147_bern_google_street_view_image,, +5750260296,2,bern,46.94800137654151,7.3833007840557405,,46.94800137654151_7.3833007840557405_bern_google_maps_image,,46.94800137654151_7.3833007840557405_bern_google_satellite_image,,46.94800137654151_7.3833007840557405_bern_google_street_view_image,, +6283505194,2,bern,46.94856254059506,7.447817695347167,,46.94856254059506_7.447817695347167_bern_google_maps_image,,46.94856254059506_7.447817695347167_bern_google_satellite_image,,46.94856254059506_7.447817695347167_bern_google_street_view_image,, +506258000,2,bern,46.94370258095633,7.469968256162423,,46.94370258095633_7.469968256162423_bern_google_maps_image,,46.94370258095633_7.469968256162423_bern_google_satellite_image,,46.94370258095633_7.469968256162423_bern_google_street_view_image,, +2212710376,2,bern,46.94814105097623,7.446101016046004,,46.94814105097623_7.446101016046004_bern_google_maps_image,,46.94814105097623_7.446101016046004_bern_google_satellite_image,,46.94814105097623_7.446101016046004_bern_google_street_view_image,, +474362125,2,bern,46.94158607531534,7.462785375669382,,46.94158607531534_7.462785375669382_bern_google_maps_image,,46.94158607531534_7.462785375669382_bern_google_satellite_image,,46.94158607531534_7.462785375669382_bern_google_street_view_image,, +667410514,2,bern,46.937564652320184,7.43229317700543,,46.937564652320184_7.43229317700543_bern_google_maps_image,,46.937564652320184_7.43229317700543_bern_google_satellite_image,,46.937564652320184_7.43229317700543_bern_google_street_view_image,, +279803128,2,bern,46.95565126894074,7.445146618275452,,46.95565126894074_7.445146618275452_bern_google_maps_image,,46.95565126894074_7.445146618275452_bern_google_satellite_image,,46.95565126894074_7.445146618275452_bern_google_street_view_image,, +489771088,2,bern,46.94232200829762,7.453174297632006,,46.94232200829762_7.453174297632006_bern_google_maps_image,,46.94232200829762_7.453174297632006_bern_google_satellite_image,,46.94232200829762_7.453174297632006_bern_google_street_view_image,, +507607630,3,bern,46.93958358413784,7.388728659220972,,46.93958358413784_7.388728659220972_bern_google_maps_image,,46.93958358413784_7.388728659220972_bern_google_satellite_image,,46.93958358413784_7.388728659220972_bern_google_street_view_image,, +2969434883,3,bern,46.948128058837575,7.441686382455266,,46.948128058837575_7.441686382455266_bern_google_maps_image,,46.948128058837575_7.441686382455266_bern_google_satellite_image,,46.948128058837575_7.441686382455266_bern_google_street_view_image,, +3623056337,3,bern,46.94951071129533,7.441209801360913,,46.94951071129533_7.441209801360913_bern_google_maps_image,,46.94951071129533_7.441209801360913_bern_google_satellite_image,,46.94951071129533_7.441209801360913_bern_google_street_view_image,, +2915808790,3,bern,46.94676701740003,7.437586853802117,,46.94676701740003_7.437586853802117_bern_google_maps_image,,46.94676701740003_7.437586853802117_bern_google_satellite_image,,46.94676701740003_7.437586853802117_bern_google_street_view_image,, +2917664561,3,bern,46.947783098320926,7.441569902669729,,46.947783098320926_7.441569902669729_bern_google_maps_image,,46.947783098320926_7.441569902669729_bern_google_satellite_image,,46.947783098320926_7.441569902669729_bern_google_street_view_image,, +3623072602,3,bern,46.93980985510001,7.38976047161021,,46.93980985510001_7.38976047161021_bern_google_maps_image,,46.93980985510001_7.38976047161021_bern_google_satellite_image,,46.93980985510001_7.38976047161021_bern_google_street_view_image,, +6928113140,3,bern,46.94904570325827,7.440865324883112,,46.94904570325827_7.440865324883112_bern_google_maps_image,,46.94904570325827_7.440865324883112_bern_google_satellite_image,,46.94904570325827_7.440865324883112_bern_google_street_view_image,, +4995140829,3,bern,46.947616432350955,7.443584257005478,,46.947616432350955_7.443584257005478_bern_google_maps_image,,46.947616432350955_7.443584257005478_bern_google_satellite_image,,46.947616432350955_7.443584257005478_bern_google_street_view_image,, +2969434882,3,bern,46.94824222329538,7.441054114609541,,46.94824222329538_7.441054114609541_bern_google_maps_image,,46.94824222329538_7.441054114609541_bern_google_satellite_image,,46.94824222329538_7.441054114609541_bern_google_street_view_image,, +312385262,3,bern,46.94966896592594,7.441788412178158,,46.94966896592594_7.441788412178158_bern_google_maps_image,,46.94966896592594_7.441788412178158_bern_google_satellite_image,,46.94966896592594_7.441788412178158_bern_google_street_view_image,, +4039021088,4,bern,46.9488859107926,7.437619301840851,,46.9488859107926_7.437619301840851_bern_google_maps_image,,46.9488859107926_7.437619301840851_bern_google_satellite_image,,46.9488859107926_7.437619301840851_bern_google_street_view_image,, +6324987839,4,bern,46.94371218301658,7.411668484288689,,46.94371218301658_7.411668484288689_bern_google_maps_image,,46.94371218301658_7.411668484288689_bern_google_satellite_image,,46.94371218301658_7.411668484288689_bern_google_street_view_image,, +5674726173,4,bern,46.95871556250214,7.454428491325774,,46.95871556250214_7.454428491325774_bern_google_maps_image,,46.95871556250214_7.454428491325774_bern_google_satellite_image,,46.95871556250214_7.454428491325774_bern_google_street_view_image,, +7403456487,4,bern,46.963601867807114,7.455899479942447,,46.963601867807114_7.455899479942447_bern_google_maps_image,,46.963601867807114_7.455899479942447_bern_google_satellite_image,,46.963601867807114_7.455899479942447_bern_google_street_view_image,, +6283505193,4,bern,46.94751963352514,7.448419232720182,,46.94751963352514_7.448419232720182_bern_google_maps_image,,46.94751963352514_7.448419232720182_bern_google_satellite_image,,46.94751963352514_7.448419232720182_bern_google_street_view_image,, +280528118,4,bern,46.95675292763683,7.432109010573549,,46.95675292763683_7.432109010573549_bern_google_maps_image,,46.95675292763683_7.432109010573549_bern_google_satellite_image,,46.95675292763683_7.432109010573549_bern_google_street_view_image,, +2319568957,4,bern,46.94448467982089,7.3995651743113635,,46.94448467982089_7.3995651743113635_bern_google_maps_image,,46.94448467982089_7.3995651743113635_bern_google_satellite_image,,46.94448467982089_7.3995651743113635_bern_google_street_view_image,, +1714599215,4,bern,46.94875933364523,7.3940632243182165,,46.94875933364523_7.3940632243182165_bern_google_maps_image,,46.94875933364523_7.3940632243182165_bern_google_satellite_image,,46.94875933364523_7.3940632243182165_bern_google_street_view_image,, +892818865,4,bern,46.948660647955904,7.43744900158191,,46.948660647955904_7.43744900158191_bern_google_maps_image,,46.948660647955904_7.43744900158191_bern_google_satellite_image,,46.948660647955904_7.43744900158191_bern_google_street_view_image,, +280528081,4,bern,46.9560726065404,7.446872482829162,,46.9560726065404_7.446872482829162_bern_google_maps_image,,46.9560726065404_7.446872482829162_bern_google_satellite_image,,46.9560726065404_7.446872482829162_bern_google_street_view_image,, +540597931,5,bern,46.96142672298649,7.4528740745586015,,46.96142672298649_7.4528740745586015_bern_google_maps_image,,46.96142672298649_7.4528740745586015_bern_google_satellite_image,,46.96142672298649_7.4528740745586015_bern_google_street_view_image,, +379582591,5,bern,46.94854048227348,7.43962547117718,,46.94854048227348_7.43962547117718_bern_google_maps_image,,46.94854048227348_7.43962547117718_bern_google_satellite_image,,46.94854048227348_7.43962547117718_bern_google_street_view_image,, +558568861,5,bern,46.95335707677212,7.432576056490557,,46.95335707677212_7.432576056490557_bern_google_maps_image,,46.95335707677212_7.432576056490557_bern_google_satellite_image,,46.95335707677212_7.432576056490557_bern_google_street_view_image,, +811210957,5,bern,46.95366581375531,7.429247521478107,,46.95366581375531_7.429247521478107_bern_google_maps_image,,46.95366581375531_7.429247521478107_bern_google_satellite_image,,46.95366581375531_7.429247521478107_bern_google_street_view_image,, +811329218,5,bern,46.95411505285083,7.430811218665848,,46.95411505285083_7.430811218665848_bern_google_maps_image,,46.95411505285083_7.430811218665848_bern_google_satellite_image,,46.95411505285083_7.430811218665848_bern_google_street_view_image,, +2984992145,5,bern,46.95385156468184,7.428824909094237,,46.95385156468184_7.428824909094237_bern_google_maps_image,,46.95385156468184_7.428824909094237_bern_google_satellite_image,,46.95385156468184_7.428824909094237_bern_google_street_view_image,, +667410777,5,bern,46.94017450190598,7.431902613019022,,46.94017450190598_7.431902613019022_bern_google_maps_image,,46.94017450190598_7.431902613019022_bern_google_satellite_image,,46.94017450190598_7.431902613019022_bern_google_street_view_image,, +533642537,5,bern,46.94403378566885,7.427586891293928,,46.94403378566885_7.427586891293928_bern_google_maps_image,,46.94403378566885_7.427586891293928_bern_google_satellite_image,,46.94403378566885_7.427586891293928_bern_google_street_view_image,, +678194273,5,bern,46.948542613572215,7.440070115902962,,46.948542613572215_7.440070115902962_bern_google_maps_image,,46.948542613572215_7.440070115902962_bern_google_satellite_image,,46.948542613572215_7.440070115902962_bern_google_street_view_image,, +2031938751,5,bern,46.95376557573043,7.431786822776838,,46.95376557573043_7.431786822776838_bern_google_maps_image,,46.95376557573043_7.431786822776838_bern_google_satellite_image,,46.95376557573043_7.431786822776838_bern_google_street_view_image,, +3040100731,1,chennai,12.97298392331194,80.19178500041505,,12.97298392331194_80.19178500041505_chennai_google_maps_image,,12.97298392331194_80.19178500041505_chennai_google_satellite_image,,12.97298392331194_80.19178500041505_chennai_google_street_view_image,, +355002675,1,chennai,12.97109596211607,80.19044846460791,,12.97109596211607_80.19044846460791_chennai_google_maps_image,,12.97109596211607_80.19044846460791_chennai_google_satellite_image,,12.97109596211607_80.19044846460791_chennai_google_street_view_image,, +223937121,1,chennai,12.9843200357826,80.18851633315549,,12.9843200357826_80.18851633315549_chennai_google_maps_image,,12.9843200357826_80.18851633315549_chennai_google_satellite_image,,12.9843200357826_80.18851633315549_chennai_google_street_view_image,, +6535920667,1,chennai,13.122258352120205,80.14990843059988,,13.122258352120205_80.14990843059988_chennai_google_maps_image,,13.122258352120205_80.14990843059988_chennai_google_satellite_image,,13.122258352120205_80.14990843059988_chennai_google_street_view_image,, +2734244476,1,chennai,13.017422169878886,80.17454770397339,,13.017422169878886_80.17454770397339_chennai_google_maps_image,,13.017422169878886_80.17454770397339_chennai_google_satellite_image,,13.017422169878886_80.17454770397339_chennai_google_street_view_image,, +5230405189,1,chennai,13.080799177244824,80.16466595414377,,13.080799177244824_80.16466595414377_chennai_google_maps_image,,13.080799177244824_80.16466595414377_chennai_google_satellite_image,,13.080799177244824_80.16466595414377_chennai_google_street_view_image,, +1411883069,1,chennai,13.020630024865872,80.2429945071415,,13.020630024865872_80.2429945071415_chennai_google_maps_image,,13.020630024865872_80.2429945071415_chennai_google_satellite_image,,13.020630024865872_80.2429945071415_chennai_google_street_view_image,, +4469843445,1,chennai,12.997067199999996,80.2406534,,12.997067199999996_80.2406534_chennai_google_maps_image,,12.997067199999996_80.2406534_chennai_google_satellite_image,,12.997067199999996_80.2406534_chennai_google_street_view_image,, +3687708989,1,chennai,12.997109140652528,80.2404666661655,,12.997109140652528_80.2404666661655_chennai_google_maps_image,,12.997109140652528_80.2404666661655_chennai_google_satellite_image,,12.997109140652528_80.2404666661655_chennai_google_street_view_image,, +772926217,1,chennai,13.228517027051677,80.32402186352023,,13.228517027051677_80.32402186352023_chennai_google_maps_image,,13.228517027051677_80.32402186352023_chennai_google_satellite_image,,13.228517027051677_80.32402186352023_chennai_google_street_view_image,, +1775800576,2,chennai,12.99601909761322,80.26773807532396,,12.99601909761322_80.26773807532396_chennai_google_maps_image,,12.99601909761322_80.26773807532396_chennai_google_satellite_image,,12.99601909761322_80.26773807532396_chennai_google_street_view_image,, +4766458866,2,chennai,12.985683550028115,80.23067809608818,,12.985683550028115_80.23067809608818_chennai_google_maps_image,,12.985683550028115_80.23067809608818_chennai_google_satellite_image,,12.985683550028115_80.23067809608818_chennai_google_street_view_image,, +5653260321,2,chennai,13.029210770129911,80.248556662744,,13.029210770129911_80.248556662744_chennai_google_maps_image,,13.029210770129911_80.248556662744_chennai_google_satellite_image,,13.029210770129911_80.248556662744_chennai_google_street_view_image,, +5570539460,2,chennai,12.985934875405722,80.22797137137769,,12.985934875405722_80.22797137137769_chennai_google_maps_image,,12.985934875405722_80.22797137137769_chennai_google_satellite_image,,12.985934875405722_80.22797137137769_chennai_google_street_view_image,, +7551657315,2,chennai,12.96955201771676,80.2442215504774,,12.96955201771676_80.2442215504774_chennai_google_maps_image,,12.96955201771676_80.2442215504774_chennai_google_satellite_image,,12.96955201771676_80.2442215504774_chennai_google_street_view_image,, +378688535,2,chennai,13.028669942563571,80.2496403556352,,13.028669942563571_80.2496403556352_chennai_google_maps_image,,13.028669942563571_80.2496403556352_chennai_google_satellite_image,,13.028669942563571_80.2496403556352_chennai_google_street_view_image,, +217849598,2,chennai,13.085421444668144,80.279163960729,,13.085421444668144_80.279163960729_chennai_google_maps_image,,13.085421444668144_80.279163960729_chennai_google_satellite_image,,13.085421444668144_80.279163960729_chennai_google_street_view_image,, +4379537181,2,chennai,13.006595228767429,80.2519156368438,,13.006595228767429_80.2519156368438_chennai_google_maps_image,,13.006595228767429_80.2519156368438_chennai_google_satellite_image,,13.006595228767429_80.2519156368438_chennai_google_street_view_image,, +864565812,2,chennai,13.039841165924516,80.25178855744187,,13.039841165924516_80.25178855744187_chennai_google_maps_image,,13.039841165924516_80.25178855744187_chennai_google_satellite_image,,13.039841165924516_80.25178855744187_chennai_google_street_view_image,, +2455032488,2,chennai,13.110408660658885,80.21059911480252,,13.110408660658885_80.21059911480252_chennai_google_maps_image,,13.110408660658885_80.21059911480252_chennai_google_satellite_image,,13.110408660658885_80.21059911480252_chennai_google_street_view_image,, +321504325,3,chennai,13.005805734783932,80.25184243690636,,13.005805734783932_80.25184243690636_chennai_google_maps_image,,13.005805734783932_80.25184243690636_chennai_google_satellite_image,,13.005805734783932_80.25184243690636_chennai_google_street_view_image,, +7271112274,3,chennai,13.057397080450746,80.2428330832012,,13.057397080450746_80.2428330832012_chennai_google_maps_image,,13.057397080450746_80.2428330832012_chennai_google_satellite_image,,13.057397080450746_80.2428330832012_chennai_google_street_view_image,, +3961459336,3,chennai,13.081581699946831,80.22538647587787,,13.081581699946831_80.22538647587787_chennai_google_maps_image,,13.081581699946831_80.22538647587787_chennai_google_satellite_image,,13.081581699946831_80.22538647587787_chennai_google_street_view_image,, +7652633333,3,chennai,13.03431070262116,80.21553816978636,,13.03431070262116_80.21553816978636_chennai_google_maps_image,,13.03431070262116_80.21553816978636_chennai_google_satellite_image,,13.03431070262116_80.21553816978636_chennai_google_street_view_image,, +279527198,3,chennai,13.085008980724401,80.20598603962524,,13.085008980724401_80.20598603962524_chennai_google_maps_image,,13.085008980724401_80.20598603962524_chennai_google_satellite_image,,13.085008980724401_80.20598603962524_chennai_google_street_view_image,, +1640625233,3,chennai,12.981240820144643,80.22999418662502,,12.981240820144643_80.22999418662502_chennai_google_maps_image,,12.981240820144643_80.22999418662502_chennai_google_satellite_image,,12.981240820144643_80.22999418662502_chennai_google_street_view_image,, +7652723880,3,chennai,12.990565541785143,80.21622206763652,,12.990565541785143_80.21622206763652_chennai_google_maps_image,,12.990565541785143_80.21622206763652_chennai_google_satellite_image,,12.990565541785143_80.21622206763652_chennai_google_street_view_image,, +3875702945,3,chennai,13.09890178013752,80.25987985287269,,13.09890178013752_80.25987985287269_chennai_google_maps_image,,13.09890178013752_80.25987985287269_chennai_google_satellite_image,,13.09890178013752_80.25987985287269_chennai_google_street_view_image,, +1024556272,3,chennai,13.035402210751034,80.21626524937062,,13.035402210751034_80.21626524937062_chennai_google_maps_image,,13.035402210751034_80.21626524937062_chennai_google_satellite_image,,13.035402210751034_80.21626524937062_chennai_google_street_view_image,, +934859085,3,chennai,13.044569248422441,80.18545654819863,,13.044569248422441_80.18545654819863_chennai_google_maps_image,,13.044569248422441_80.18545654819863_chennai_google_satellite_image,,13.044569248422441_80.18545654819863_chennai_google_street_view_image,, +231053133,4,chennai,13.090340832642346,80.21788470297457,,13.090340832642346_80.21788470297457_chennai_google_maps_image,,13.090340832642346_80.21788470297457_chennai_google_satellite_image,,13.090340832642346_80.21788470297457_chennai_google_street_view_image,, +4308320004,4,chennai,13.024336167693983,80.2144462443253,,13.024336167693983_80.2144462443253_chennai_google_maps_image,,13.024336167693983_80.2144462443253_chennai_google_satellite_image,,13.024336167693983_80.2144462443253_chennai_google_street_view_image,, +2296728885,4,chennai,13.075318033770154,80.26988237874345,,13.075318033770154_80.26988237874345_chennai_google_maps_image,,13.075318033770154_80.26988237874345_chennai_google_satellite_image,,13.075318033770154_80.26988237874345_chennai_google_street_view_image,, +5242605023,4,chennai,12.977164518011488,80.2620912613245,,12.977164518011488_80.2620912613245_chennai_google_maps_image,,12.977164518011488_80.2620912613245_chennai_google_satellite_image,,12.977164518011488_80.2620912613245_chennai_google_street_view_image,, +4688930495,4,chennai,13.038040713483538,80.2295149741751,,13.038040713483538_80.2295149741751_chennai_google_maps_image,,13.038040713483538_80.2295149741751_chennai_google_satellite_image,,13.038040713483538_80.2295149741751_chennai_google_street_view_image,, +612552098,4,chennai,13.07705233700919,80.21088890170279,,13.07705233700919_80.21088890170279_chennai_google_maps_image,,13.07705233700919_80.21088890170279_chennai_google_satellite_image,,13.07705233700919_80.21088890170279_chennai_google_street_view_image,, +214711575,4,chennai,13.075313798270342,80.26989956349696,,13.075313798270342_80.26989956349696_chennai_google_maps_image,,13.075313798270342_80.26989956349696_chennai_google_satellite_image,,13.075313798270342_80.26989956349696_chennai_google_street_view_image,, +1640625237,4,chennai,12.981172898847838,80.22929561469421,,12.981172898847838_80.22929561469421_chennai_google_maps_image,,12.981172898847838_80.22929561469421_chennai_google_satellite_image,,12.981172898847838_80.22929561469421_chennai_google_street_view_image,, +7252446776,4,chennai,13.054878605994553,80.24554982426895,,13.054878605994553_80.24554982426895_chennai_google_maps_image,,13.054878605994553_80.24554982426895_chennai_google_satellite_image,,13.054878605994553_80.24554982426895_chennai_google_street_view_image,, +1800440276,4,chennai,13.084538383658579,80.2056855544979,,13.084538383658579_80.2056855544979_chennai_google_maps_image,,13.084538383658579_80.2056855544979_chennai_google_satellite_image,,13.084538383658579_80.2056855544979_chennai_google_street_view_image,, +1640621203,5,chennai,12.981045108537622,80.22928646623167,,12.981045108537622_80.22928646623167_chennai_google_maps_image,,12.981045108537622_80.22928646623167_chennai_google_satellite_image,,12.981045108537622_80.22928646623167_chennai_google_street_view_image,, +1764308007,5,chennai,12.971751999616933,80.21931337288298,,12.971751999616933_80.21931337288298_chennai_google_maps_image,,12.971751999616933_80.21931337288298_chennai_google_satellite_image,,12.971751999616933_80.21931337288298_chennai_google_street_view_image,, +386890403,5,chennai,13.044372698490648,80.26354543302881,,13.044372698490648_80.26354543302881_chennai_google_maps_image,,13.044372698490648_80.26354543302881_chennai_google_satellite_image,,13.044372698490648_80.26354543302881_chennai_google_street_view_image,, +354999189,5,chennai,13.04792341928793,80.26412309286681,,13.04792341928793_80.26412309286681_chennai_google_maps_image,,13.04792341928793_80.26412309286681_chennai_google_satellite_image,,13.04792341928793_80.26412309286681_chennai_google_street_view_image,, +6010172976,5,chennai,13.036212742904606,80.22067224928986,,13.036212742904606_80.22067224928986_chennai_google_maps_image,,13.036212742904606_80.22067224928986_chennai_google_satellite_image,,13.036212742904606_80.22067224928986_chennai_google_street_view_image,, +214148769,5,chennai,13.021168332187155,80.22359252100476,,13.021168332187155_80.22359252100476_chennai_google_maps_image,,13.021168332187155_80.22359252100476_chennai_google_satellite_image,,13.021168332187155_80.22359252100476_chennai_google_street_view_image,, +5338507327,5,chennai,13.105691014308052,80.20787788510337,,13.105691014308052_80.20787788510337_chennai_google_maps_image,,13.105691014308052_80.20787788510337_chennai_google_satellite_image,,13.105691014308052_80.20787788510337_chennai_google_street_view_image,, +459639891,5,chennai,13.051928310945684,80.20401308344194,,13.051928310945684_80.20401308344194_chennai_google_maps_image,,13.051928310945684_80.20401308344194_chennai_google_satellite_image,,13.051928310945684_80.20401308344194_chennai_google_street_view_image,, +334478862,5,chennai,13.021445544040086,80.22397692029948,,13.021445544040086_80.22397692029948_chennai_google_maps_image,,13.021445544040086_80.22397692029948_chennai_google_satellite_image,,13.021445544040086_80.22397692029948_chennai_google_street_view_image,, +595659823,5,chennai,13.057526592392296,80.19434382634462,,13.057526592392296_80.19434382634462_chennai_google_maps_image,,13.057526592392296_80.19434382634462_chennai_google_satellite_image,,13.057526592392296_80.19434382634462_chennai_google_street_view_image,, +6011381413,1,mexico_city,19.51403416660249,-99.22981436725821,,19.51403416660249_-99.22981436725821_mexico_city_google_maps_image,,19.51403416660249_-99.22981436725821_mexico_city_google_satellite_image,,19.51403416660249_-99.22981436725821_mexico_city_google_street_view_image,, +5625373021,1,mexico_city,19.619868299999993,-98.9955415,,19.619868299999993_-98.9955415_mexico_city_google_maps_image,,19.619868299999993_-98.9955415_mexico_city_google_satellite_image,,19.619868299999993_-98.9955415_mexico_city_google_street_view_image,, +4971055822,1,mexico_city,19.53104549074699,-99.22811173035574,,19.53104549074699_-99.22811173035574_mexico_city_google_maps_image,,19.53104549074699_-99.22811173035574_mexico_city_google_satellite_image,,19.53104549074699_-99.22811173035574_mexico_city_google_street_view_image,, +4479755389,1,mexico_city,19.33595418581395,-99.19583341922599,,19.33595418581395_-99.19583341922599_mexico_city_google_maps_image,,19.33595418581395_-99.19583341922599_mexico_city_google_satellite_image,,19.33595418581395_-99.19583341922599_mexico_city_google_street_view_image,, +1120443998,1,mexico_city,19.42236627053319,-99.20457123748297,,19.42236627053319_-99.20457123748297_mexico_city_google_maps_image,,19.42236627053319_-99.20457123748297_mexico_city_google_satellite_image,,19.42236627053319_-99.20457123748297_mexico_city_google_street_view_image,, +319651892,1,mexico_city,19.3468000206549,-99.18025881388044,,19.3468000206549_-99.18025881388044_mexico_city_google_maps_image,,19.3468000206549_-99.18025881388044_mexico_city_google_satellite_image,,19.3468000206549_-99.18025881388044_mexico_city_google_street_view_image,, +463012548,1,mexico_city,19.491929948760486,-99.22743339696706,,19.491929948760486_-99.22743339696706_mexico_city_google_maps_image,,19.491929948760486_-99.22743339696706_mexico_city_google_satellite_image,,19.491929948760486_-99.22743339696706_mexico_city_google_street_view_image,, +6687091253,1,mexico_city,19.292200317783077,-99.16106164206218,,19.292200317783077_-99.16106164206218_mexico_city_google_maps_image,,19.292200317783077_-99.16106164206218_mexico_city_google_satellite_image,,19.292200317783077_-99.16106164206218_mexico_city_google_street_view_image,, +578726124,1,mexico_city,19.549041369410695,-99.20748187329792,,19.549041369410695_-99.20748187329792_mexico_city_google_maps_image,,19.549041369410695_-99.20748187329792_mexico_city_google_satellite_image,,19.549041369410695_-99.20748187329792_mexico_city_google_street_view_image,, +5881888414,1,mexico_city,19.638540332196268,-99.21852313664104,,19.638540332196268_-99.21852313664104_mexico_city_google_maps_image,,19.638540332196268_-99.21852313664104_mexico_city_google_satellite_image,,19.638540332196268_-99.21852313664104_mexico_city_google_street_view_image,, +2126803747,2,mexico_city,19.5197308545474,-99.10825467575036,,19.5197308545474_-99.10825467575036_mexico_city_google_maps_image,,19.5197308545474_-99.10825467575036_mexico_city_google_satellite_image,,19.5197308545474_-99.10825467575036_mexico_city_google_street_view_image,, +551492401,2,mexico_city,19.387196458066352,-99.07753094589833,,19.387196458066352_-99.07753094589833_mexico_city_google_maps_image,,19.387196458066352_-99.07753094589833_mexico_city_google_satellite_image,,19.387196458066352_-99.07753094589833_mexico_city_google_street_view_image,, +5417791322,2,mexico_city,19.416405954914598,-99.16980466126468,,19.416405954914598_-99.16980466126468_mexico_city_google_maps_image,,19.416405954914598_-99.16980466126468_mexico_city_google_satellite_image,,19.416405954914598_-99.16980466126468_mexico_city_google_street_view_image,, +5618752637,2,mexico_city,19.6256717,-99.2925373,,19.6256717_-99.2925373_mexico_city_google_maps_image,,19.6256717_-99.2925373_mexico_city_google_satellite_image,,19.6256717_-99.2925373_mexico_city_google_street_view_image,, +4316280989,2,mexico_city,19.27460805534499,-99.1199937834964,,19.27460805534499_-99.1199937834964_mexico_city_google_maps_image,,19.27460805534499_-99.1199937834964_mexico_city_google_satellite_image,,19.27460805534499_-99.1199937834964_mexico_city_google_street_view_image,, +5881888416,2,mexico_city,19.638667548677986,-99.21805774644656,,19.638667548677986_-99.21805774644656_mexico_city_google_maps_image,,19.638667548677986_-99.21805774644656_mexico_city_google_satellite_image,,19.638667548677986_-99.21805774644656_mexico_city_google_street_view_image,, +5197360579,2,mexico_city,19.325007376692454,-99.22382090711858,,19.325007376692454_-99.22382090711858_mexico_city_google_maps_image,,19.325007376692454_-99.22382090711858_mexico_city_google_satellite_image,,19.325007376692454_-99.22382090711858_mexico_city_google_street_view_image,, +713545878,2,mexico_city,19.611529655247026,-99.03755890263231,,19.611529655247026_-99.03755890263231_mexico_city_google_maps_image,,19.611529655247026_-99.03755890263231_mexico_city_google_satellite_image,,19.611529655247026_-99.03755890263231_mexico_city_google_street_view_image,, +790801394,2,mexico_city,19.391685762589706,-99.27925290555264,,19.391685762589706_-99.27925290555264_mexico_city_google_maps_image,,19.391685762589706_-99.27925290555264_mexico_city_google_satellite_image,,19.391685762589706_-99.27925290555264_mexico_city_google_street_view_image,, +327297512,2,mexico_city,19.251681814829016,-99.17081540274361,,19.251681814829016_-99.17081540274361_mexico_city_google_maps_image,,19.251681814829016_-99.17081540274361_mexico_city_google_satellite_image,,19.251681814829016_-99.17081540274361_mexico_city_google_street_view_image,, +3380713564,3,mexico_city,19.252103604004134,-99.1724056566158,,19.252103604004134_-99.1724056566158_mexico_city_google_maps_image,,19.252103604004134_-99.1724056566158_mexico_city_google_satellite_image,,19.252103604004134_-99.1724056566158_mexico_city_google_street_view_image,, +531758826,3,mexico_city,19.602246993030853,-99.00921628410761,,19.602246993030853_-99.00921628410761_mexico_city_google_maps_image,,19.602246993030853_-99.00921628410761_mexico_city_google_satellite_image,,19.602246993030853_-99.00921628410761_mexico_city_google_street_view_image,, +818881354,3,mexico_city,19.409249417820284,-99.07473349082271,,19.409249417820284_-99.07473349082271_mexico_city_google_maps_image,,19.409249417820284_-99.07473349082271_mexico_city_google_satellite_image,,19.409249417820284_-99.07473349082271_mexico_city_google_street_view_image,, +4661403216,3,mexico_city,19.3061212,-99.1657359,,19.3061212_-99.1657359_mexico_city_google_maps_image,,19.3061212_-99.1657359_mexico_city_google_satellite_image,,19.3061212_-99.1657359_mexico_city_google_street_view_image,, +5247968921,3,mexico_city,19.430435114542913,-99.16947402488798,,19.430435114542913_-99.16947402488798_mexico_city_google_maps_image,,19.430435114542913_-99.16947402488798_mexico_city_google_satellite_image,,19.430435114542913_-99.16947402488798_mexico_city_google_street_view_image,, +316738852,3,mexico_city,19.415954035141777,-99.10095674099989,,19.415954035141777_-99.10095674099989_mexico_city_google_maps_image,,19.415954035141777_-99.10095674099989_mexico_city_google_satellite_image,,19.415954035141777_-99.10095674099989_mexico_city_google_street_view_image,, +5533987020,3,mexico_city,19.449378085540932,-99.21368058993912,,19.449378085540932_-99.21368058993912_mexico_city_google_maps_image,,19.449378085540932_-99.21368058993912_mexico_city_google_satellite_image,,19.449378085540932_-99.21368058993912_mexico_city_google_street_view_image,, +3802504185,3,mexico_city,19.418567696058847,-99.11709182250064,,19.418567696058847_-99.11709182250064_mexico_city_google_maps_image,,19.418567696058847_-99.11709182250064_mexico_city_google_satellite_image,,19.418567696058847_-99.11709182250064_mexico_city_google_street_view_image,, +830603055,3,mexico_city,19.356222350373088,-99.15525872859979,,19.356222350373088_-99.15525872859979_mexico_city_google_maps_image,,19.356222350373088_-99.15525872859979_mexico_city_google_satellite_image,,19.356222350373088_-99.15525872859979_mexico_city_google_street_view_image,, +3263840121,3,mexico_city,19.60721548569304,-98.97327956895045,,19.60721548569304_-98.97327956895045_mexico_city_google_maps_image,,19.60721548569304_-98.97327956895045_mexico_city_google_satellite_image,,19.60721548569304_-98.97327956895045_mexico_city_google_street_view_image,, +3802845836,4,mexico_city,19.370007382037823,-99.17319076827603,,19.370007382037823_-99.17319076827603_mexico_city_google_maps_image,,19.370007382037823_-99.17319076827603_mexico_city_google_satellite_image,,19.370007382037823_-99.17319076827603_mexico_city_google_street_view_image,, +5108093422,4,mexico_city,19.5098055351056,-99.08629600828012,,19.5098055351056_-99.08629600828012_mexico_city_google_maps_image,,19.5098055351056_-99.08629600828012_mexico_city_google_satellite_image,,19.5098055351056_-99.08629600828012_mexico_city_google_street_view_image,, +4066846457,4,mexico_city,19.376220421324923,-99.1539222521892,,19.376220421324923_-99.1539222521892_mexico_city_google_maps_image,,19.376220421324923_-99.1539222521892_mexico_city_google_satellite_image,,19.376220421324923_-99.1539222521892_mexico_city_google_street_view_image,, +404795916,4,mexico_city,19.40162848187196,-99.15880716780337,,19.40162848187196_-99.15880716780337_mexico_city_google_maps_image,,19.40162848187196_-99.15880716780337_mexico_city_google_satellite_image,,19.40162848187196_-99.15880716780337_mexico_city_google_street_view_image,, +355215483,4,mexico_city,19.456114655705782,-99.10435781053914,,19.456114655705782_-99.10435781053914_mexico_city_google_maps_image,,19.456114655705782_-99.10435781053914_mexico_city_google_satellite_image,,19.456114655705782_-99.10435781053914_mexico_city_google_street_view_image,, +717761768,4,mexico_city,19.59493623796497,-98.99569593615188,,19.59493623796497_-98.99569593615188_mexico_city_google_maps_image,,19.59493623796497_-98.99569593615188_mexico_city_google_satellite_image,,19.59493623796497_-98.99569593615188_mexico_city_google_street_view_image,, +620181905,4,mexico_city,19.419251705059608,-99.0875584444067,,19.419251705059608_-99.0875584444067_mexico_city_google_maps_image,,19.419251705059608_-99.0875584444067_mexico_city_google_satellite_image,,19.419251705059608_-99.0875584444067_mexico_city_google_street_view_image,, +83589291,4,mexico_city,19.534283891153496,-99.02719708539541,,19.534283891153496_-99.02719708539541_mexico_city_google_maps_image,,19.534283891153496_-99.02719708539541_mexico_city_google_satellite_image,,19.534283891153496_-99.02719708539541_mexico_city_google_street_view_image,, +359241465,4,mexico_city,19.4594477204163,-99.091861403534,,19.4594477204163_-99.091861403534_mexico_city_google_maps_image,,19.4594477204163_-99.091861403534_mexico_city_google_satellite_image,,19.4594477204163_-99.091861403534_mexico_city_google_street_view_image,, +601784893,4,mexico_city,19.402130562993637,-99.12188565976768,,19.402130562993637_-99.12188565976768_mexico_city_google_maps_image,,19.402130562993637_-99.12188565976768_mexico_city_google_satellite_image,,19.402130562993637_-99.12188565976768_mexico_city_google_street_view_image,, +5694106223,5,mexico_city,19.44723060277377,-99.24557241439541,,19.44723060277377_-99.24557241439541_mexico_city_google_maps_image,,19.44723060277377_-99.24557241439541_mexico_city_google_satellite_image,,19.44723060277377_-99.24557241439541_mexico_city_google_street_view_image,, +6644579936,5,mexico_city,19.442327639174398,-99.15820955785016,,19.442327639174398_-99.15820955785016_mexico_city_google_maps_image,,19.442327639174398_-99.15820955785016_mexico_city_google_satellite_image,,19.442327639174398_-99.15820955785016_mexico_city_google_street_view_image,, +263257550,5,mexico_city,19.41636850413102,-99.0218279996463,,19.41636850413102_-99.0218279996463_mexico_city_google_maps_image,,19.41636850413102_-99.0218279996463_mexico_city_google_satellite_image,,19.41636850413102_-99.0218279996463_mexico_city_google_street_view_image,, +1499489411,5,mexico_city,19.509192194994526,-99.10030494794222,,19.509192194994526_-99.10030494794222_mexico_city_google_maps_image,,19.509192194994526_-99.10030494794222_mexico_city_google_satellite_image,,19.509192194994526_-99.10030494794222_mexico_city_google_street_view_image,, +4536274297,5,mexico_city,19.628960580316544,-99.1392991095664,,19.628960580316544_-99.1392991095664_mexico_city_google_maps_image,,19.628960580316544_-99.1392991095664_mexico_city_google_satellite_image,,19.628960580316544_-99.1392991095664_mexico_city_google_street_view_image,, +293809368,5,mexico_city,19.326671499999996,-98.8819042,,19.326671499999996_-98.8819042_mexico_city_google_maps_image,,19.326671499999996_-98.8819042_mexico_city_google_satellite_image,,19.326671499999996_-98.8819042_mexico_city_google_street_view_image,, +217662063,5,mexico_city,19.44189326824857,-99.13885337788817,,19.44189326824857_-99.13885337788817_mexico_city_google_maps_image,,19.44189326824857_-99.13885337788817_mexico_city_google_satellite_image,,19.44189326824857_-99.13885337788817_mexico_city_google_street_view_image,, +4039082262,5,mexico_city,19.360839473243438,-99.14997110009426,,19.360839473243438_-99.14997110009426_mexico_city_google_maps_image,,19.360839473243438_-99.14997110009426_mexico_city_google_satellite_image,,19.360839473243438_-99.14997110009426_mexico_city_google_street_view_image,, +766584728,5,mexico_city,19.662553823635136,-99.0707784206159,,19.662553823635136_-99.0707784206159_mexico_city_google_maps_image,,19.662553823635136_-99.0707784206159_mexico_city_google_satellite_image,,19.662553823635136_-99.0707784206159_mexico_city_google_street_view_image,, +1677171707,5,mexico_city,19.4642461563854,-99.12660040878647,,19.4642461563854_-99.12660040878647_mexico_city_google_maps_image,,19.4642461563854_-99.12660040878647_mexico_city_google_satellite_image,,19.4642461563854_-99.12660040878647_mexico_city_google_street_view_image,, +2798786972,1,cologne,50.898249122575564,7.02945390050806,,50.898249122575564_7.02945390050806_cologne_google_maps_image,,50.898249122575564_7.02945390050806_cologne_google_satellite_image,,50.898249122575564_7.02945390050806_cologne_google_street_view_image,, +155144241,1,cologne,50.89383823888894,7.047768417465601,,50.89383823888894_7.047768417465601_cologne_google_maps_image,,50.89383823888894_7.047768417465601_cologne_google_satellite_image,,50.89383823888894_7.047768417465601_cologne_google_street_view_image,, +1808374631,1,cologne,50.884686852412024,7.057938865588942,,50.884686852412024_7.057938865588942_cologne_google_maps_image,,50.884686852412024_7.057938865588942_cologne_google_satellite_image,,50.884686852412024_7.057938865588942_cologne_google_street_view_image,, +1038105378,1,cologne,50.92877655226211,7.0006978124369095,,50.92877655226211_7.0006978124369095_cologne_google_maps_image,,50.92877655226211_7.0006978124369095_cologne_google_satellite_image,,50.92877655226211_7.0006978124369095_cologne_google_street_view_image,, +218586953,1,cologne,50.9468089,6.847064400000002,,50.9468089_6.847064400000002_cologne_google_maps_image,,50.9468089_6.847064400000002_cologne_google_satellite_image,,50.9468089_6.847064400000002_cologne_google_street_view_image,, +366725737,1,cologne,50.98980726446304,6.961434933768049,,50.98980726446304_6.961434933768049_cologne_google_maps_image,,50.98980726446304_6.961434933768049_cologne_google_satellite_image,,50.98980726446304_6.961434933768049_cologne_google_street_view_image,, +32343354,1,cologne,51.00161465278052,6.9876208930376285,,51.00161465278052_6.9876208930376285_cologne_google_maps_image,,51.00161465278052_6.9876208930376285_cologne_google_satellite_image,,51.00161465278052_6.9876208930376285_cologne_google_street_view_image,, +1434135027,1,cologne,50.84629079999999,7.096374899999999,,50.84629079999999_7.096374899999999_cologne_google_maps_image,,50.84629079999999_7.096374899999999_cologne_google_satellite_image,,50.84629079999999_7.096374899999999_cologne_google_street_view_image,, +904988831,1,cologne,50.88220434681379,7.0118102418560655,,50.88220434681379_7.0118102418560655_cologne_google_maps_image,,50.88220434681379_7.0118102418560655_cologne_google_satellite_image,,50.88220434681379_7.0118102418560655_cologne_google_street_view_image,, +366662669,1,cologne,50.97711095571608,6.960381574351235,,50.97711095571608_6.960381574351235_cologne_google_maps_image,,50.97711095571608_6.960381574351235_cologne_google_satellite_image,,50.97711095571608_6.960381574351235_cologne_google_street_view_image,, +1924165807,2,cologne,50.97115339999999,6.959627999999999,,50.97115339999999_6.959627999999999_cologne_google_maps_image,,50.97115339999999_6.959627999999999_cologne_google_satellite_image,,50.97115339999999_6.959627999999999_cologne_google_street_view_image,, +164851648,2,cologne,51.003068912791974,6.873682680963931,,51.003068912791974_6.873682680963931_cologne_google_maps_image,,51.003068912791974_6.873682680963931_cologne_google_satellite_image,,51.003068912791974_6.873682680963931_cologne_google_street_view_image,, +4546959772,2,cologne,50.898366688002845,6.965904234562772,,50.898366688002845_6.965904234562772_cologne_google_maps_image,,50.898366688002845_6.965904234562772_cologne_google_satellite_image,,50.898366688002845_6.965904234562772_cologne_google_street_view_image,, +258092650,2,cologne,50.97494439238988,6.947056388681244,,50.97494439238988_6.947056388681244_cologne_google_maps_image,,50.97494439238988_6.947056388681244_cologne_google_satellite_image,,50.97494439238988_6.947056388681244_cologne_google_street_view_image,, +2141323066,2,cologne,50.93095759913993,6.852956151064677,,50.93095759913993_6.852956151064677_cologne_google_maps_image,,50.93095759913993_6.852956151064677_cologne_google_satellite_image,,50.93095759913993_6.852956151064677_cologne_google_street_view_image,, +155440122,2,cologne,50.856045422022305,7.087079964625161,,50.856045422022305_7.087079964625161_cologne_google_maps_image,,50.856045422022305_7.087079964625161_cologne_google_satellite_image,,50.856045422022305_7.087079964625161_cologne_google_street_view_image,, +1741318998,2,cologne,50.96567334203133,6.836430482061221,,50.96567334203133_6.836430482061221_cologne_google_maps_image,,50.96567334203133_6.836430482061221_cologne_google_satellite_image,,50.96567334203133_6.836430482061221_cologne_google_street_view_image,, +986290367,2,cologne,50.92881046571001,6.911392406204731,,50.92881046571001_6.911392406204731_cologne_google_maps_image,,50.92881046571001_6.911392406204731_cologne_google_satellite_image,,50.92881046571001_6.911392406204731_cologne_google_street_view_image,, +847541789,2,cologne,50.942781385216826,7.049905948656818,,50.942781385216826_7.049905948656818_cologne_google_maps_image,,50.942781385216826_7.049905948656818_cologne_google_satellite_image,,50.942781385216826_7.049905948656818_cologne_google_street_view_image,, +5359016021,2,cologne,50.99777974997925,6.9136134163229634,,50.99777974997925_6.9136134163229634_cologne_google_maps_image,,50.99777974997925_6.9136134163229634_cologne_google_satellite_image,,50.99777974997925_6.9136134163229634_cologne_google_street_view_image,, +448860271,3,cologne,50.966488189174655,6.834006396296986,,50.966488189174655_6.834006396296986_cologne_google_maps_image,,50.966488189174655_6.834006396296986_cologne_google_satellite_image,,50.966488189174655_6.834006396296986_cologne_google_street_view_image,, +82097104,3,cologne,50.96445468475809,6.975805878158244,,50.96445468475809_6.975805878158244_cologne_google_maps_image,,50.96445468475809_6.975805878158244_cologne_google_satellite_image,,50.96445468475809_6.975805878158244_cologne_google_street_view_image,, +429523110,3,cologne,50.95510500567307,6.916412252269436,,50.95510500567307_6.916412252269436_cologne_google_maps_image,,50.95510500567307_6.916412252269436_cologne_google_satellite_image,,50.95510500567307_6.916412252269436_cologne_google_street_view_image,, +5976221914,3,cologne,50.97982,6.867865600000001,,50.97982_6.867865600000001_cologne_google_maps_image,,50.97982_6.867865600000001_cologne_google_satellite_image,,50.97982_6.867865600000001_cologne_google_street_view_image,, +603316682,3,cologne,50.959567688983,7.008290212426442,,50.959567688983_7.008290212426442_cologne_google_maps_image,,50.959567688983_7.008290212426442_cologne_google_satellite_image,,50.959567688983_7.008290212426442_cologne_google_street_view_image,, +3992509400,3,cologne,50.891144215232906,6.996977905573185,,50.891144215232906_6.996977905573185_cologne_google_maps_image,,50.891144215232906_6.996977905573185_cologne_google_satellite_image,,50.891144215232906_6.996977905573185_cologne_google_street_view_image,, +946072102,3,cologne,50.93810566355929,7.005189926068315,,50.93810566355929_7.005189926068315_cologne_google_maps_image,,50.93810566355929_7.005189926068315_cologne_google_satellite_image,,50.93810566355929_7.005189926068315_cologne_google_street_view_image,, +1841208275,3,cologne,50.9627456059562,7.003331694073337,,50.9627456059562_7.003331694073337_cologne_google_maps_image,,50.9627456059562_7.003331694073337_cologne_google_satellite_image,,50.9627456059562_7.003331694073337_cologne_google_street_view_image,, +444401494,3,cologne,50.95698588661255,6.918518966901978,,50.95698588661255_6.918518966901978_cologne_google_maps_image,,50.95698588661255_6.918518966901978_cologne_google_satellite_image,,50.95698588661255_6.918518966901978_cologne_google_street_view_image,, +6202847455,3,cologne,50.93808553109019,6.8435032191359735,,50.93808553109019_6.8435032191359735_cologne_google_maps_image,,50.93808553109019_6.8435032191359735_cologne_google_satellite_image,,50.93808553109019_6.8435032191359735_cologne_google_street_view_image,, +905234692,4,cologne,50.933333290661416,7.019910313985369,,50.933333290661416_7.019910313985369_cologne_google_maps_image,,50.933333290661416_7.019910313985369_cologne_google_satellite_image,,50.933333290661416_7.019910313985369_cologne_google_street_view_image,, +107360172,4,cologne,50.89569833808621,7.072964683684729,,50.89569833808621_7.072964683684729_cologne_google_maps_image,,50.89569833808621_7.072964683684729_cologne_google_satellite_image,,50.89569833808621_7.072964683684729_cologne_google_street_view_image,, +6388749727,4,cologne,50.98133409828571,7.032800023816504,,50.98133409828571_7.032800023816504_cologne_google_maps_image,,50.98133409828571_7.032800023816504_cologne_google_satellite_image,,50.98133409828571_7.032800023816504_cologne_google_street_view_image,, +4126586308,4,cologne,50.95142363470696,6.957058979365362,,50.95142363470696_6.957058979365362_cologne_google_maps_image,,50.95142363470696_6.957058979365362_cologne_google_satellite_image,,50.95142363470696_6.957058979365362_cologne_google_street_view_image,, +353945432,4,cologne,50.92160299209089,6.928993909727928,,50.92160299209089_6.928993909727928_cologne_google_maps_image,,50.92160299209089_6.928993909727928_cologne_google_satellite_image,,50.92160299209089_6.928993909727928_cologne_google_street_view_image,, +87761318,4,cologne,50.91586013318439,6.93406352193762,,50.91586013318439_6.93406352193762_cologne_google_maps_image,,50.91586013318439_6.93406352193762_cologne_google_satellite_image,,50.91586013318439_6.93406352193762_cologne_google_street_view_image,, +641220538,4,cologne,50.92636315107418,6.958083606809124,,50.92636315107418_6.958083606809124_cologne_google_maps_image,,50.92636315107418_6.958083606809124_cologne_google_satellite_image,,50.92636315107418_6.958083606809124_cologne_google_street_view_image,, +1895932177,4,cologne,50.9500192,6.9171075,,50.9500192_6.9171075_cologne_google_maps_image,,50.9500192_6.9171075_cologne_google_satellite_image,,50.9500192_6.9171075_cologne_google_street_view_image,, +5693413723,4,cologne,50.94912418104523,6.953010766568366,,50.94912418104523_6.953010766568366_cologne_google_maps_image,,50.94912418104523_6.953010766568366_cologne_google_satellite_image,,50.94912418104523_6.953010766568366_cologne_google_street_view_image,, +1380532321,4,cologne,50.94871275589644,6.98759090771506,,50.94871275589644_6.98759090771506_cologne_google_maps_image,,50.94871275589644_6.98759090771506_cologne_google_satellite_image,,50.94871275589644_6.98759090771506_cologne_google_street_view_image,, +729932436,5,cologne,50.94820373105129,6.920118858751327,,50.94820373105129_6.920118858751327_cologne_google_maps_image,,50.94820373105129_6.920118858751327_cologne_google_satellite_image,,50.94820373105129_6.920118858751327_cologne_google_street_view_image,, +1166597378,5,cologne,50.94630554096603,6.925121138019788,,50.94630554096603_6.925121138019788_cologne_google_maps_image,,50.94630554096603_6.925121138019788_cologne_google_satellite_image,,50.94630554096603_6.925121138019788_cologne_google_street_view_image,, +4692617938,5,cologne,50.94761098081893,6.956309612578662,,50.94761098081893_6.956309612578662_cologne_google_maps_image,,50.94761098081893_6.956309612578662_cologne_google_satellite_image,,50.94761098081893_6.956309612578662_cologne_google_street_view_image,, +325189646,5,cologne,50.971373092309754,7.010040627386005,,50.971373092309754_7.010040627386005_cologne_google_maps_image,,50.971373092309754_7.010040627386005_cologne_google_satellite_image,,50.971373092309754_7.010040627386005_cologne_google_street_view_image,, +583434186,5,cologne,50.97094759627577,7.00945865057715,,50.97094759627577_7.00945865057715_cologne_google_maps_image,,50.97094759627577_7.00945865057715_cologne_google_satellite_image,,50.97094759627577_7.00945865057715_cologne_google_street_view_image,, +252608602,5,cologne,50.9201661,6.9361017,,50.9201661_6.9361017_cologne_google_maps_image,,50.9201661_6.9361017_cologne_google_satellite_image,,50.9201661_6.9361017_cologne_google_street_view_image,, +582824099,5,cologne,50.911660899999994,6.963516099999999,,50.911660899999994_6.963516099999999_cologne_google_maps_image,,50.911660899999994_6.963516099999999_cologne_google_satellite_image,,50.911660899999994_6.963516099999999_cologne_google_street_view_image,, +3470965473,5,cologne,50.92280545226893,6.9591087470916175,,50.92280545226893_6.9591087470916175_cologne_google_maps_image,,50.92280545226893_6.9591087470916175_cologne_google_satellite_image,,50.92280545226893_6.9591087470916175_cologne_google_street_view_image,, +4679581462,5,cologne,50.94820774752281,6.954592264963115,,50.94820774752281_6.954592264963115_cologne_google_maps_image,,50.94820774752281_6.954592264963115_cologne_google_satellite_image,,50.94820774752281_6.954592264963115_cologne_google_street_view_image,, +6564494812,5,cologne,50.92214239304427,6.921829654333054,,50.92214239304427_6.921829654333054_cologne_google_maps_image,,50.92214239304427_6.921829654333054_cologne_google_satellite_image,,50.92214239304427_6.921829654333054_cologne_google_street_view_image,, +6327109986,1,ghent,51.051366299999984,3.7617922999999993,,51.051366299999984_3.7617922999999993_ghent_google_maps_image,,51.051366299999984_3.7617922999999993_ghent_google_satellite_image,,51.051366299999984_3.7617922999999993_ghent_google_street_view_image,, +6174916886,1,ghent,51.075211206978054,3.7524107978352728,,51.075211206978054_3.7524107978352728_ghent_google_maps_image,,51.075211206978054_3.7524107978352728_ghent_google_satellite_image,,51.075211206978054_3.7524107978352728_ghent_google_street_view_image,, +2498828925,1,ghent,51.016789334638986,3.734894792387552,,51.016789334638986_3.734894792387552_ghent_google_maps_image,,51.016789334638986_3.734894792387552_ghent_google_satellite_image,,51.016789334638986_3.734894792387552_ghent_google_street_view_image,, +239251697,1,ghent,51.068121680673144,3.6831862529014208,,51.068121680673144_3.6831862529014208_ghent_google_maps_image,,51.068121680673144_3.6831862529014208_ghent_google_satellite_image,,51.068121680673144_3.6831862529014208_ghent_google_street_view_image,, +6299254488,1,ghent,51.079405763538624,3.7631868014895034,,51.079405763538624_3.7631868014895034_ghent_google_maps_image,,51.079405763538624_3.7631868014895034_ghent_google_satellite_image,,51.079405763538624_3.7631868014895034_ghent_google_street_view_image,, +5550198948,1,ghent,51.00397103420439,3.717453802688445,,51.00397103420439_3.717453802688445_ghent_google_maps_image,,51.00397103420439_3.717453802688445_ghent_google_satellite_image,,51.00397103420439_3.717453802688445_ghent_google_street_view_image,, +600508259,1,ghent,51.088974045590625,3.7078271931425686,,51.088974045590625_3.7078271931425686_ghent_google_maps_image,,51.088974045590625_3.7078271931425686_ghent_google_satellite_image,,51.088974045590625_3.7078271931425686_ghent_google_street_view_image,, +483071802,1,ghent,51.076543169062425,3.683485828827118,,51.076543169062425_3.683485828827118_ghent_google_maps_image,,51.076543169062425_3.683485828827118_ghent_google_satellite_image,,51.076543169062425_3.683485828827118_ghent_google_street_view_image,, +158715226,1,ghent,51.090626619640226,3.7590429378029215,,51.090626619640226_3.7590429378029215_ghent_google_maps_image,,51.090626619640226_3.7590429378029215_ghent_google_satellite_image,,51.090626619640226_3.7590429378029215_ghent_google_street_view_image,, +206897095,1,ghent,51.07416805405659,3.6797243730680615,,51.07416805405659_3.6797243730680615_ghent_google_maps_image,,51.07416805405659_3.6797243730680615_ghent_google_satellite_image,,51.07416805405659_3.6797243730680615_ghent_google_street_view_image,, +1239962113,2,ghent,51.051392432375465,3.7019979676639667,,51.051392432375465_3.7019979676639667_ghent_google_maps_image,,51.051392432375465_3.7019979676639667_ghent_google_satellite_image,,51.051392432375465_3.7019979676639667_ghent_google_street_view_image,, +2485998498,2,ghent,51.071781698668055,3.707033930082326,,51.071781698668055_3.707033930082326_ghent_google_maps_image,,51.071781698668055_3.707033930082326_ghent_google_satellite_image,,51.071781698668055_3.707033930082326_ghent_google_street_view_image,, +4831549869,2,ghent,51.070763893535094,3.709766110340651,,51.070763893535094_3.709766110340651_ghent_google_maps_image,,51.070763893535094_3.709766110340651_ghent_google_satellite_image,,51.070763893535094_3.709766110340651_ghent_google_street_view_image,, +6900570088,2,ghent,51.05781831381282,3.7067567553707046,,51.05781831381282_3.7067567553707046_ghent_google_maps_image,,51.05781831381282_3.7067567553707046_ghent_google_satellite_image,,51.05781831381282_3.7067567553707046_ghent_google_street_view_image,, +104385257,2,ghent,51.04755719181594,3.708450450262417,,51.04755719181594_3.708450450262417_ghent_google_maps_image,,51.04755719181594_3.708450450262417_ghent_google_satellite_image,,51.04755719181594_3.708450450262417_ghent_google_street_view_image,, +451769815,2,ghent,51.05500310794491,3.695426113563651,,51.05500310794491_3.695426113563651_ghent_google_maps_image,,51.05500310794491_3.695426113563651_ghent_google_satellite_image,,51.05500310794491_3.695426113563651_ghent_google_street_view_image,, +6466580996,2,ghent,51.099495228483676,3.7641445150839568,,51.099495228483676_3.7641445150839568_ghent_google_maps_image,,51.099495228483676_3.7641445150839568_ghent_google_satellite_image,,51.099495228483676_3.7641445150839568_ghent_google_street_view_image,, +6983077089,2,ghent,51.06404998382594,3.709709379658549,,51.06404998382594_3.709709379658549_ghent_google_maps_image,,51.06404998382594_3.709709379658549_ghent_google_satellite_image,,51.06404998382594_3.709709379658549_ghent_google_street_view_image,, +417796798,2,ghent,51.0733946810587,3.687136710316848,,51.0733946810587_3.687136710316848_ghent_google_maps_image,,51.0733946810587_3.687136710316848_ghent_google_satellite_image,,51.0733946810587_3.687136710316848_ghent_google_street_view_image,, +7448200576,2,ghent,51.05320379369902,3.7550846837166882,,51.05320379369902_3.7550846837166882_ghent_google_maps_image,,51.05320379369902_3.7550846837166882_ghent_google_satellite_image,,51.05320379369902_3.7550846837166882_ghent_google_street_view_image,, +6434028388,3,ghent,51.061225720427004,3.7484227168373003,,51.061225720427004_3.7484227168373003_ghent_google_maps_image,,51.061225720427004_3.7484227168373003_ghent_google_satellite_image,,51.061225720427004_3.7484227168373003_ghent_google_street_view_image,, +180127971,3,ghent,51.02734959571888,3.7302628193268093,,51.02734959571888_3.7302628193268093_ghent_google_maps_image,,51.02734959571888_3.7302628193268093_ghent_google_satellite_image,,51.02734959571888_3.7302628193268093_ghent_google_street_view_image,, +1598830944,3,ghent,51.036336223806636,3.7098356888293593,,51.036336223806636_3.7098356888293593_ghent_google_maps_image,,51.036336223806636_3.7098356888293593_ghent_google_satellite_image,,51.036336223806636_3.7098356888293593_ghent_google_street_view_image,, +3876171904,3,ghent,51.05221322454478,3.723636928088199,,51.05221322454478_3.723636928088199_ghent_google_maps_image,,51.05221322454478_3.723636928088199_ghent_google_satellite_image,,51.05221322454478_3.723636928088199_ghent_google_street_view_image,, +115446302,3,ghent,51.05390319326428,3.7424353486665005,,51.05390319326428_3.7424353486665005_ghent_google_maps_image,,51.05390319326428_3.7424353486665005_ghent_google_satellite_image,,51.05390319326428_3.7424353486665005_ghent_google_street_view_image,, +176368079,3,ghent,51.04033045098958,3.717157728129874,,51.04033045098958_3.717157728129874_ghent_google_maps_image,,51.04033045098958_3.717157728129874_ghent_google_satellite_image,,51.04033045098958_3.717157728129874_ghent_google_street_view_image,, +1301268094,3,ghent,51.054268823440594,3.743329030040363,,51.054268823440594_3.743329030040363_ghent_google_maps_image,,51.054268823440594_3.743329030040363_ghent_google_satellite_image,,51.054268823440594_3.743329030040363_ghent_google_street_view_image,, +1630724940,3,ghent,51.0269365868416,3.7097563552966215,,51.0269365868416_3.7097563552966215_ghent_google_maps_image,,51.0269365868416_3.7097563552966215_ghent_google_satellite_image,,51.0269365868416_3.7097563552966215_ghent_google_street_view_image,, +6440678288,3,ghent,51.064641161095,3.726358225148234,,51.064641161095_3.726358225148234_ghent_google_maps_image,,51.064641161095_3.726358225148234_ghent_google_satellite_image,,51.064641161095_3.726358225148234_ghent_google_street_view_image,, +6900570185,3,ghent,51.056863606969,3.709392409658695,,51.056863606969_3.709392409658695_ghent_google_maps_image,,51.056863606969_3.709392409658695_ghent_google_satellite_image,,51.056863606969_3.709392409658695_ghent_google_street_view_image,, +5859316519,4,ghent,51.06247846938567,3.710039664951906,,51.06247846938567_3.710039664951906_ghent_google_maps_image,,51.06247846938567_3.710039664951906_ghent_google_satellite_image,,51.06247846938567_3.710039664951906_ghent_google_street_view_image,, +4712254515,4,ghent,51.041253767757574,3.718294370126334,,51.041253767757574_3.718294370126334_ghent_google_maps_image,,51.041253767757574_3.718294370126334_ghent_google_satellite_image,,51.041253767757574_3.718294370126334_ghent_google_street_view_image,, +6533980221,4,ghent,51.0606658742048,3.7017336663687863,,51.0606658742048_3.7017336663687863_ghent_google_maps_image,,51.0606658742048_3.7017336663687863_ghent_google_satellite_image,,51.0606658742048_3.7017336663687863_ghent_google_street_view_image,, +555274388,4,ghent,51.08416463912916,3.7173228608250537,,51.08416463912916_3.7173228608250537_ghent_google_maps_image,,51.08416463912916_3.7173228608250537_ghent_google_satellite_image,,51.08416463912916_3.7173228608250537_ghent_google_street_view_image,, +6942598388,4,ghent,51.0566620727313,3.7416358652971433,,51.0566620727313_3.7416358652971433_ghent_google_maps_image,,51.0566620727313_3.7416358652971433_ghent_google_satellite_image,,51.0566620727313_3.7416358652971433_ghent_google_street_view_image,, +6983076913,4,ghent,51.062440260557665,3.710051494679923,,51.062440260557665_3.710051494679923_ghent_google_maps_image,,51.062440260557665_3.710051494679923_ghent_google_satellite_image,,51.062440260557665_3.710051494679923_ghent_google_street_view_image,, +451557497,4,ghent,51.056832699999994,3.6967075000000005,,51.056832699999994_3.6967075000000005_ghent_google_maps_image,,51.056832699999994_3.6967075000000005_ghent_google_satellite_image,,51.056832699999994_3.6967075000000005_ghent_google_street_view_image,, +1802839228,4,ghent,51.036983166082784,3.7132114857964074,,51.036983166082784_3.7132114857964074_ghent_google_maps_image,,51.036983166082784_3.7132114857964074_ghent_google_satellite_image,,51.036983166082784_3.7132114857964074_ghent_google_street_view_image,, +7198244688,4,ghent,51.06019876528515,3.7023542588798546,,51.06019876528515_3.7023542588798546_ghent_google_maps_image,,51.06019876528515_3.7023542588798546_ghent_google_satellite_image,,51.06019876528515_3.7023542588798546_ghent_google_street_view_image,, +6255559989,4,ghent,51.056797555724096,3.7335630238526716,,51.056797555724096_3.7335630238526716_ghent_google_maps_image,,51.056797555724096_3.7335630238526716_ghent_google_satellite_image,,51.056797555724096_3.7335630238526716_ghent_google_street_view_image,, +1426081014,5,ghent,51.03702305449802,3.7424962842294653,,51.03702305449802_3.7424962842294653_ghent_google_maps_image,,51.03702305449802_3.7424962842294653_ghent_google_satellite_image,,51.03702305449802_3.7424962842294653_ghent_google_street_view_image,, +2225073604,5,ghent,51.0494989056728,3.7444801836856962,,51.0494989056728_3.7444801836856962_ghent_google_maps_image,,51.0494989056728_3.7444801836856962_ghent_google_satellite_image,,51.0494989056728_3.7444801836856962_ghent_google_street_view_image,, +3517496239,5,ghent,51.05713416039469,3.7306964287875823,,51.05713416039469_3.7306964287875823_ghent_google_maps_image,,51.05713416039469_3.7306964287875823_ghent_google_satellite_image,,51.05713416039469_3.7306964287875823_ghent_google_street_view_image,, +1795819240,5,ghent,51.050336127091,3.723182341107955,,51.050336127091_3.723182341107955_ghent_google_maps_image,,51.050336127091_3.723182341107955_ghent_google_satellite_image,,51.050336127091_3.723182341107955_ghent_google_street_view_image,, +7079394607,5,ghent,51.05088795205988,3.727861466773262,,51.05088795205988_3.727861466773262_ghent_google_maps_image,,51.05088795205988_3.727861466773262_ghent_google_satellite_image,,51.05088795205988_3.727861466773262_ghent_google_street_view_image,, +6138790502,5,ghent,51.040690079723035,3.7405428318486713,,51.040690079723035_3.7405428318486713_ghent_google_maps_image,,51.040690079723035_3.7405428318486713_ghent_google_satellite_image,,51.040690079723035_3.7405428318486713_ghent_google_street_view_image,, +1687422666,5,ghent,51.05092984466987,3.704243446912032,,51.05092984466987_3.704243446912032_ghent_google_maps_image,,51.05092984466987_3.704243446912032_ghent_google_satellite_image,,51.05092984466987_3.704243446912032_ghent_google_street_view_image,, +1598830941,5,ghent,51.038536403900096,3.709045786494365,,51.038536403900096_3.709045786494365_ghent_google_maps_image,,51.038536403900096_3.709045786494365_ghent_google_satellite_image,,51.038536403900096_3.709045786494365_ghent_google_street_view_image,, +5918606636,5,ghent,51.04869218904633,3.72132597253425,,51.04869218904633_3.72132597253425_ghent_google_maps_image,,51.04869218904633_3.72132597253425_ghent_google_satellite_image,,51.04869218904633_3.72132597253425_ghent_google_street_view_image,, +1295215428,5,ghent,51.059687099547354,3.727870181086064,,51.059687099547354_3.727870181086064_ghent_google_maps_image,,51.059687099547354_3.727870181086064_ghent_google_satellite_image,,51.059687099547354_3.727870181086064_ghent_google_street_view_image,, +6173128482,1,graz,47.07749298981534,15.434732982116689,,47.07749298981534_15.434732982116689_graz_google_maps_image,,47.07749298981534_15.434732982116689_graz_google_satellite_image,,47.07749298981534_15.434732982116689_graz_google_street_view_image,, +825158290,1,graz,47.08169058347534,15.468114065116948,,47.08169058347534_15.468114065116948_graz_google_maps_image,,47.08169058347534_15.468114065116948_graz_google_satellite_image,,47.08169058347534_15.468114065116948_graz_google_street_view_image,, +5713866806,1,graz,47.032929039736096,15.4316960350709,,47.032929039736096_15.4316960350709_graz_google_maps_image,,47.032929039736096_15.4316960350709_graz_google_satellite_image,,47.032929039736096_15.4316960350709_graz_google_street_view_image,, +21306980,1,graz,47.05056339999999,15.4785402,,47.05056339999999_15.4785402_graz_google_maps_image,,47.05056339999999_15.4785402_graz_google_satellite_image,,47.05056339999999_15.4785402_graz_google_street_view_image,, +107877896,1,graz,47.100835930965,15.426204360727988,,47.100835930965_15.426204360727988_graz_google_maps_image,,47.100835930965_15.426204360727988_graz_google_satellite_image,,47.100835930965_15.426204360727988_graz_google_street_view_image,, +372409546,1,graz,47.11376087680128,15.421656431286198,,47.11376087680128_15.421656431286198_graz_google_maps_image,,47.11376087680128_15.421656431286198_graz_google_satellite_image,,47.11376087680128_15.421656431286198_graz_google_street_view_image,, +33054365,1,graz,47.0787376,15.4730586,,47.0787376_15.4730586_graz_google_maps_image,,47.0787376_15.4730586_graz_google_satellite_image,,47.0787376_15.4730586_graz_google_street_view_image,, +5871235120,1,graz,47.027670455919214,15.46637684580302,,47.027670455919214_15.46637684580302_graz_google_maps_image,,47.027670455919214_15.46637684580302_graz_google_satellite_image,,47.027670455919214_15.46637684580302_graz_google_street_view_image,, +31620673,1,graz,47.02840659999999,15.4338649,,47.02840659999999_15.4338649_graz_google_maps_image,,47.02840659999999_15.4338649_graz_google_satellite_image,,47.02840659999999_15.4338649_graz_google_street_view_image,, +1363117573,1,graz,47.066961074212564,15.467476705898548,,47.066961074212564_15.467476705898548_graz_google_maps_image,,47.066961074212564_15.467476705898548_graz_google_satellite_image,,47.066961074212564_15.467476705898548_graz_google_street_view_image,, +5147474662,2,graz,47.07441620096659,15.431035045149669,,47.07441620096659_15.431035045149669_graz_google_maps_image,,47.07441620096659_15.431035045149669_graz_google_satellite_image,,47.07441620096659_15.431035045149669_graz_google_street_view_image,, +991630578,2,graz,47.0778083,15.4626039,,47.0778083_15.4626039_graz_google_maps_image,,47.0778083_15.4626039_graz_google_satellite_image,,47.0778083_15.4626039_graz_google_street_view_image,, +367079334,2,graz,47.079567691515145,15.467113619122438,,47.079567691515145_15.467113619122438_graz_google_maps_image,,47.079567691515145_15.467113619122438_graz_google_satellite_image,,47.079567691515145_15.467113619122438_graz_google_street_view_image,, +371197149,2,graz,47.07203198514327,15.436851842038411,,47.07203198514327_15.436851842038411_graz_google_maps_image,,47.07203198514327_15.436851842038411_graz_google_satellite_image,,47.07203198514327_15.436851842038411_graz_google_street_view_image,, +289182754,2,graz,47.062884611801096,15.465883429175388,,47.062884611801096_15.465883429175388_graz_google_maps_image,,47.062884611801096_15.465883429175388_graz_google_satellite_image,,47.062884611801096_15.465883429175388_graz_google_street_view_image,, +146904669,2,graz,47.059827917240405,15.39671379231068,,47.059827917240405_15.39671379231068_graz_google_maps_image,,47.059827917240405_15.39671379231068_graz_google_satellite_image,,47.059827917240405_15.39671379231068_graz_google_street_view_image,, +6200932089,2,graz,47.07478170455035,15.43135228917076,,47.07478170455035_15.43135228917076_graz_google_maps_image,,47.07478170455035_15.43135228917076_graz_google_satellite_image,,47.07478170455035_15.43135228917076_graz_google_street_view_image,, +96700819,2,graz,47.0619820164163,15.467675196662245,,47.0619820164163_15.467675196662245_graz_google_maps_image,,47.0619820164163_15.467675196662245_graz_google_satellite_image,,47.0619820164163_15.467675196662245_graz_google_street_view_image,, +199824392,2,graz,47.05997514380375,15.396174465462135,,47.05997514380375_15.396174465462135_graz_google_maps_image,,47.05997514380375_15.396174465462135_graz_google_satellite_image,,47.05997514380375_15.396174465462135_graz_google_street_view_image,, +1457222996,2,graz,47.08873915750338,15.428427131979845,,47.08873915750338_15.428427131979845_graz_google_maps_image,,47.08873915750338_15.428427131979845_graz_google_satellite_image,,47.08873915750338_15.428427131979845_graz_google_street_view_image,, +209747834,3,graz,47.08140590509027,15.444760675353093,,47.08140590509027_15.444760675353093_graz_google_maps_image,,47.08140590509027_15.444760675353093_graz_google_satellite_image,,47.08140590509027_15.444760675353093_graz_google_street_view_image,, +7066278891,3,graz,47.04784479999999,15.453480400000002,,47.04784479999999_15.453480400000002_graz_google_maps_image,,47.04784479999999_15.453480400000002_graz_google_satellite_image,,47.04784479999999_15.453480400000002_graz_google_street_view_image,, +6175091243,3,graz,47.06397698854764,15.431509069213012,,47.06397698854764_15.431509069213012_graz_google_maps_image,,47.06397698854764_15.431509069213012_graz_google_satellite_image,,47.06397698854764_15.431509069213012_graz_google_street_view_image,, +2896669721,3,graz,47.07554409999999,15.4310643,,47.07554409999999_15.4310643_graz_google_maps_image,,47.07554409999999_15.4310643_graz_google_satellite_image,,47.07554409999999_15.4310643_graz_google_street_view_image,, +111681954,3,graz,47.089446276044626,15.407834188355928,,47.089446276044626_15.407834188355928_graz_google_maps_image,,47.089446276044626_15.407834188355928_graz_google_satellite_image,,47.089446276044626_15.407834188355928_graz_google_street_view_image,, +202514625,3,graz,47.075677886529974,15.427859203915624,,47.075677886529974_15.427859203915624_graz_google_maps_image,,47.075677886529974_15.427859203915624_graz_google_satellite_image,,47.075677886529974_15.427859203915624_graz_google_street_view_image,, +6175091246,3,graz,47.065764684246176,15.431396432973846,,47.065764684246176_15.431396432973846_graz_google_maps_image,,47.065764684246176_15.431396432973846_graz_google_satellite_image,,47.065764684246176_15.431396432973846_graz_google_street_view_image,, +31611256,3,graz,47.06294791887,15.45794422889628,,47.06294791887_15.45794422889628_graz_google_maps_image,,47.06294791887_15.45794422889628_graz_google_satellite_image,,47.06294791887_15.45794422889628_graz_google_street_view_image,, +3274523680,3,graz,47.045818674923105,15.43317736526208,,47.045818674923105_15.43317736526208_graz_google_maps_image,,47.045818674923105_15.43317736526208_graz_google_satellite_image,,47.045818674923105_15.43317736526208_graz_google_street_view_image,, +2503804465,3,graz,47.051752699999994,15.4288421,,47.051752699999994_15.4288421_graz_google_maps_image,,47.051752699999994_15.4288421_graz_google_satellite_image,,47.051752699999994_15.4288421_graz_google_street_view_image,, +4078510935,4,graz,47.06581846471563,15.428119267611368,,47.06581846471563_15.428119267611368_graz_google_maps_image,,47.06581846471563_15.428119267611368_graz_google_satellite_image,,47.06581846471563_15.428119267611368_graz_google_street_view_image,, +371204222,4,graz,47.060816625984906,15.426402149782804,,47.060816625984906_15.426402149782804_graz_google_maps_image,,47.060816625984906_15.426402149782804_graz_google_satellite_image,,47.060816625984906_15.426402149782804_graz_google_street_view_image,, +85666832,4,graz,47.055576224299664,15.441634138653525,,47.055576224299664_15.441634138653525_graz_google_maps_image,,47.055576224299664_15.441634138653525_graz_google_satellite_image,,47.055576224299664_15.441634138653525_graz_google_street_view_image,, +1084426931,4,graz,47.07209159999999,15.450777799999997,,47.07209159999999_15.450777799999997_graz_google_maps_image,,47.07209159999999_15.450777799999997_graz_google_satellite_image,,47.07209159999999_15.450777799999997_graz_google_street_view_image,, +280171006,4,graz,47.0709970595606,15.432596533114502,,47.0709970595606_15.432596533114502_graz_google_maps_image,,47.0709970595606_15.432596533114502_graz_google_satellite_image,,47.0709970595606_15.432596533114502_graz_google_street_view_image,, +1264399993,4,graz,47.06822209748811,15.446736724640502,,47.06822209748811_15.446736724640502_graz_google_maps_image,,47.06822209748811_15.446736724640502_graz_google_satellite_image,,47.06822209748811_15.446736724640502_graz_google_street_view_image,, +97935285,4,graz,47.080162504289895,15.45049484924463,,47.080162504289895_15.45049484924463_graz_google_maps_image,,47.080162504289895_15.45049484924463_graz_google_satellite_image,,47.080162504289895_15.45049484924463_graz_google_street_view_image,, +906742088,4,graz,47.0724593773178,15.439754888111121,,47.0724593773178_15.439754888111121_graz_google_maps_image,,47.0724593773178_15.439754888111121_graz_google_satellite_image,,47.0724593773178_15.439754888111121_graz_google_street_view_image,, +1420207253,4,graz,47.069369499999986,15.4515449,,47.069369499999986_15.4515449_graz_google_maps_image,,47.069369499999986_15.4515449_graz_google_satellite_image,,47.069369499999986_15.4515449_graz_google_street_view_image,, +88015872,4,graz,47.06633275180773,15.446623732630812,,47.06633275180773_15.446623732630812_graz_google_maps_image,,47.06633275180773_15.446623732630812_graz_google_satellite_image,,47.06633275180773_15.446623732630812_graz_google_street_view_image,, +1601202088,5,graz,47.074398599999995,15.418842,,47.074398599999995_15.418842_graz_google_maps_image,,47.074398599999995_15.418842_graz_google_satellite_image,,47.074398599999995_15.418842_graz_google_street_view_image,, +366271309,5,graz,47.067493050726334,15.440533559702844,,47.067493050726334_15.440533559702844_graz_google_maps_image,,47.067493050726334_15.440533559702844_graz_google_satellite_image,,47.067493050726334_15.440533559702844_graz_google_street_view_image,, +1615186056,5,graz,47.053937146738406,15.448496466938671,,47.053937146738406_15.448496466938671_graz_google_maps_image,,47.053937146738406_15.448496466938671_graz_google_satellite_image,,47.053937146738406_15.448496466938671_graz_google_street_view_image,, +7402681135,5,graz,47.08028676740791,15.415723007909477,,47.08028676740791_15.415723007909477_graz_google_maps_image,,47.08028676740791_15.415723007909477_graz_google_satellite_image,,47.08028676740791_15.415723007909477_graz_google_street_view_image,, +366566728,5,graz,47.07041965736281,15.437991690645154,,47.07041965736281_15.437991690645154_graz_google_maps_image,,47.07041965736281_15.437991690645154_graz_google_satellite_image,,47.07041965736281_15.437991690645154_graz_google_street_view_image,, +4693752897,5,graz,47.072496900000004,15.41698,,47.072496900000004_15.41698_graz_google_maps_image,,47.072496900000004_15.41698_graz_google_satellite_image,,47.072496900000004_15.41698_graz_google_street_view_image,, +373020329,5,graz,47.07239200949782,15.416995377895535,,47.07239200949782_15.416995377895535_graz_google_maps_image,,47.07239200949782_15.416995377895535_graz_google_satellite_image,,47.07239200949782_15.416995377895535_graz_google_street_view_image,, +5536615311,5,graz,47.06710152140713,15.439590516030501,,47.06710152140713_15.439590516030501_graz_google_maps_image,,47.06710152140713_15.439590516030501_graz_google_satellite_image,,47.06710152140713_15.439590516030501_graz_google_street_view_image,, +5503873205,5,graz,47.07095275419845,15.43745850776562,,47.07095275419845_15.43745850776562_graz_google_maps_image,,47.07095275419845_15.43745850776562_graz_google_satellite_image,,47.07095275419845_15.43745850776562_graz_google_street_view_image,, +7073784418,5,graz,47.07116881836481,15.44106146010659,,47.07116881836481_15.44106146010659_graz_google_maps_image,,47.07116881836481_15.44106146010659_graz_google_satellite_image,,47.07116881836481_15.44106146010659_graz_google_street_view_image,, +6722142985,1,hanoi,21.068922733102795,105.70753807503452,,21.068922733102795_105.70753807503452_hanoi_google_maps_image,,21.068922733102795_105.70753807503452_hanoi_google_satellite_image,,21.068922733102795_105.70753807503452_hanoi_google_street_view_image,, +479832688,1,hanoi,21.017069179521965,105.94583671623174,,21.017069179521965_105.94583671623174_hanoi_google_maps_image,,21.017069179521965_105.94583671623174_hanoi_google_satellite_image,,21.017069179521965_105.94583671623174_hanoi_google_street_view_image,, +6758493185,1,hanoi,21.003441491118526,105.73220805652882,,21.003441491118526_105.73220805652882_hanoi_google_maps_image,,21.003441491118526_105.73220805652882_hanoi_google_satellite_image,,21.003441491118526_105.73220805652882_hanoi_google_street_view_image,, +6223959585,1,hanoi,20.9543479262088,105.80992396690392,,20.9543479262088_105.80992396690392_hanoi_google_maps_image,,20.9543479262088_105.80992396690392_hanoi_google_satellite_image,,20.9543479262088_105.80992396690392_hanoi_google_street_view_image,, +6776174785,1,hanoi,21.027002023325384,105.74040148345286,,21.027002023325384_105.74040148345286_hanoi_google_maps_image,,21.027002023325384_105.74040148345286_hanoi_google_satellite_image,,21.027002023325384_105.74040148345286_hanoi_google_street_view_image,, +660703617,1,hanoi,21.097550727421265,105.92020007310403,,21.097550727421265_105.92020007310403_hanoi_google_maps_image,,21.097550727421265_105.92020007310403_hanoi_google_satellite_image,,21.097550727421265_105.92020007310403_hanoi_google_street_view_image,, +5621453821,1,hanoi,21.029170402331154,105.91671085381081,,21.029170402331154_105.91671085381081_hanoi_google_maps_image,,21.029170402331154_105.91671085381081_hanoi_google_satellite_image,,21.029170402331154_105.91671085381081_hanoi_google_street_view_image,, +5686499421,1,hanoi,21.036729539284515,105.75942338376385,,21.036729539284515_105.75942338376385_hanoi_google_maps_image,,21.036729539284515_105.75942338376385_hanoi_google_satellite_image,,21.036729539284515_105.75942338376385_hanoi_google_street_view_image,, +6725510486,1,hanoi,20.970071220440932,105.87791195799343,,20.970071220440932_105.87791195799343_hanoi_google_maps_image,,20.970071220440932_105.87791195799343_hanoi_google_satellite_image,,20.970071220440932_105.87791195799343_hanoi_google_street_view_image,, +6745101586,1,hanoi,20.995433820848515,105.78431367150611,,20.995433820848515_105.78431367150611_hanoi_google_maps_image,,20.995433820848515_105.78431367150611_hanoi_google_satellite_image,,20.995433820848515_105.78431367150611_hanoi_google_street_view_image,, +5603707722,2,hanoi,21.060615604217126,105.89526636036369,,21.060615604217126_105.89526636036369_hanoi_google_maps_image,,21.060615604217126_105.89526636036369_hanoi_google_satellite_image,,21.060615604217126_105.89526636036369_hanoi_google_street_view_image,, +5463378180,2,hanoi,20.969396660487366,105.8653765685603,,20.969396660487366_105.8653765685603_hanoi_google_maps_image,,20.969396660487366_105.8653765685603_hanoi_google_satellite_image,,20.969396660487366_105.8653765685603_hanoi_google_street_view_image,, +6754857785,2,hanoi,21.028786066443622,105.76501194849482,,21.028786066443622_105.76501194849482_hanoi_google_maps_image,,21.028786066443622_105.76501194849482_hanoi_google_satellite_image,,21.028786066443622_105.76501194849482_hanoi_google_street_view_image,, +1927580774,2,hanoi,20.949618858270064,105.84513049645689,,20.949618858270064_105.84513049645689_hanoi_google_maps_image,,20.949618858270064_105.84513049645689_hanoi_google_satellite_image,,20.949618858270064_105.84513049645689_hanoi_google_street_view_image,, +6243854385,2,hanoi,20.996959281125314,105.79433788580187,,20.996959281125314_105.79433788580187_hanoi_google_maps_image,,20.996959281125314_105.79433788580187_hanoi_google_satellite_image,,20.996959281125314_105.79433788580187_hanoi_google_street_view_image,, +6794340541,2,hanoi,20.97058185387772,105.8295671687706,,20.97058185387772_105.8295671687706_hanoi_google_maps_image,,20.97058185387772_105.8295671687706_hanoi_google_satellite_image,,20.97058185387772_105.8295671687706_hanoi_google_street_view_image,, +5918039687,2,hanoi,21.05276854587558,105.83448155005497,,21.05276854587558_105.83448155005497_hanoi_google_maps_image,,21.05276854587558_105.83448155005497_hanoi_google_satellite_image,,21.05276854587558_105.83448155005497_hanoi_google_street_view_image,, +5123787182,2,hanoi,20.983900630226547,105.8595544436176,,20.983900630226547_105.8595544436176_hanoi_google_maps_image,,20.983900630226547_105.8595544436176_hanoi_google_satellite_image,,20.983900630226547_105.8595544436176_hanoi_google_street_view_image,, +705844951,2,hanoi,20.98150677468427,105.87101553908224,,20.98150677468427_105.87101553908224_hanoi_google_maps_image,,20.98150677468427_105.87101553908224_hanoi_google_satellite_image,,20.98150677468427_105.87101553908224_hanoi_google_street_view_image,, +6849107685,2,hanoi,21.034918114959215,105.73967236536781,,21.034918114959215_105.73967236536781_hanoi_google_maps_image,,21.034918114959215_105.73967236536781_hanoi_google_satellite_image,,21.034918114959215_105.73967236536781_hanoi_google_street_view_image,, +5485666060,3,hanoi,21.029211780913204,105.81249361311525,,21.029211780913204_105.81249361311525_hanoi_google_maps_image,,21.029211780913204_105.81249361311525_hanoi_google_satellite_image,,21.029211780913204_105.81249361311525_hanoi_google_street_view_image,, +7055975987,3,hanoi,20.98917138443581,105.80812608306697,,20.98917138443581_105.80812608306697_hanoi_google_maps_image,,20.98917138443581_105.80812608306697_hanoi_google_satellite_image,,20.98917138443581_105.80812608306697_hanoi_google_street_view_image,, +5678697421,3,hanoi,21.04994755729565,105.83921342208959,,21.04994755729565_105.83921342208959_hanoi_google_maps_image,,21.04994755729565_105.83921342208959_hanoi_google_satellite_image,,21.04994755729565_105.83921342208959_hanoi_google_street_view_image,, +7365666585,3,hanoi,21.00841652607623,105.7947007080327,,21.00841652607623_105.7947007080327_hanoi_google_maps_image,,21.00841652607623_105.7947007080327_hanoi_google_satellite_image,,21.00841652607623_105.7947007080327_hanoi_google_street_view_image,, +4090306852,3,hanoi,20.964577274890374,105.77184344107837,,20.964577274890374_105.77184344107837_hanoi_google_maps_image,,20.964577274890374_105.77184344107837_hanoi_google_satellite_image,,20.964577274890374_105.77184344107837_hanoi_google_street_view_image,, +5603809224,3,hanoi,21.029313278450548,105.8178029578799,,21.029313278450548_105.8178029578799_hanoi_google_maps_image,,21.029313278450548_105.8178029578799_hanoi_google_satellite_image,,21.029313278450548_105.8178029578799_hanoi_google_street_view_image,, +5521484621,3,hanoi,20.99398482690741,105.84207306240376,,20.99398482690741_105.84207306240376_hanoi_google_maps_image,,20.99398482690741_105.84207306240376_hanoi_google_satellite_image,,20.99398482690741_105.84207306240376_hanoi_google_street_view_image,, +4427721996,3,hanoi,21.03243902871824,105.85067581813661,,21.03243902871824_105.85067581813661_hanoi_google_maps_image,,21.03243902871824_105.85067581813661_hanoi_google_satellite_image,,21.03243902871824_105.85067581813661_hanoi_google_street_view_image,, +5757756521,3,hanoi,20.988201531401888,105.87741371589735,,20.988201531401888_105.87741371589735_hanoi_google_maps_image,,20.988201531401888_105.87741371589735_hanoi_google_satellite_image,,20.988201531401888_105.87741371589735_hanoi_google_street_view_image,, +3471347683,3,hanoi,21.04518443787649,105.79932552693185,,21.04518443787649_105.79932552693185_hanoi_google_maps_image,,21.04518443787649_105.79932552693185_hanoi_google_satellite_image,,21.04518443787649_105.79932552693185_hanoi_google_street_view_image,, +4171014889,4,hanoi,21.033027557877745,105.85362223212037,,21.033027557877745_105.85362223212037_hanoi_google_maps_image,,21.033027557877745_105.85362223212037_hanoi_google_satellite_image,,21.033027557877745_105.85362223212037_hanoi_google_street_view_image,, +5529931421,4,hanoi,21.01788493704499,105.86420199394303,,21.01788493704499_105.86420199394303_hanoi_google_maps_image,,21.01788493704499_105.86420199394303_hanoi_google_satellite_image,,21.01788493704499_105.86420199394303_hanoi_google_street_view_image,, +6684446887,4,hanoi,21.002831830376383,105.85477258246779,,21.002831830376383_105.85477258246779_hanoi_google_maps_image,,21.002831830376383_105.85477258246779_hanoi_google_satellite_image,,21.002831830376383_105.85477258246779_hanoi_google_street_view_image,, +5382848321,4,hanoi,21.016876554273694,105.85356045065343,,21.016876554273694_105.85356045065343_hanoi_google_maps_image,,21.016876554273694_105.85356045065343_hanoi_google_satellite_image,,21.016876554273694_105.85356045065343_hanoi_google_street_view_image,, +4458010392,4,hanoi,21.0357616,105.8533458,,21.0357616_105.8533458_hanoi_google_maps_image,,21.0357616_105.8533458_hanoi_google_satellite_image,,21.0357616_105.8533458_hanoi_google_street_view_image,, +6684446289,4,hanoi,20.991489045694973,105.84893675781264,,20.991489045694973_105.84893675781264_hanoi_google_maps_image,,20.991489045694973_105.84893675781264_hanoi_google_satellite_image,,20.991489045694973_105.84893675781264_hanoi_google_street_view_image,, +5485733755,4,hanoi,21.025797873573296,105.8223492511277,,21.025797873573296_105.8223492511277_hanoi_google_maps_image,,21.025797873573296_105.8223492511277_hanoi_google_satellite_image,,21.025797873573296_105.8223492511277_hanoi_google_street_view_image,, +4330652389,4,hanoi,21.03202805105592,105.85388845371705,,21.03202805105592_105.85388845371705_hanoi_google_maps_image,,21.03202805105592_105.85388845371705_hanoi_google_satellite_image,,21.03202805105592_105.85388845371705_hanoi_google_street_view_image,, +6798176413,4,hanoi,21.023383267194657,105.8566763008743,,21.023383267194657_105.8566763008743_hanoi_google_maps_image,,21.023383267194657_105.8566763008743_hanoi_google_satellite_image,,21.023383267194657_105.8566763008743_hanoi_google_street_view_image,, +6696644285,4,hanoi,21.015994552353664,105.82375046442098,,21.015994552353664_105.82375046442098_hanoi_google_maps_image,,21.015994552353664_105.82375046442098_hanoi_google_satellite_image,,21.015994552353664_105.82375046442098_hanoi_google_street_view_image,, +6684445888,5,hanoi,20.99867583893234,105.85242428805039,,20.99867583893234_105.85242428805039_hanoi_google_maps_image,,20.99867583893234_105.85242428805039_hanoi_google_satellite_image,,20.99867583893234_105.85242428805039_hanoi_google_street_view_image,, +6684446691,5,hanoi,21.020764764425014,105.83391005875832,,21.020764764425014_105.83391005875832_hanoi_google_maps_image,,21.020764764425014_105.83391005875832_hanoi_google_satellite_image,,21.020764764425014_105.83391005875832_hanoi_google_street_view_image,, +4706594119,5,hanoi,21.00738220868797,105.82141266107998,,21.00738220868797_105.82141266107998_hanoi_google_maps_image,,21.00738220868797_105.82141266107998_hanoi_google_satellite_image,,21.00738220868797_105.82141266107998_hanoi_google_street_view_image,, +4578730790,5,hanoi,20.999444665519622,105.87037885974038,,20.999444665519622_105.87037885974038_hanoi_google_maps_image,,20.999444665519622_105.87037885974038_hanoi_google_satellite_image,,20.999444665519622_105.87037885974038_hanoi_google_street_view_image,, +4155614990,5,hanoi,21.02670889474851,105.83872278163015,,21.02670889474851_105.83872278163015_hanoi_google_maps_image,,21.02670889474851_105.83872278163015_hanoi_google_satellite_image,,21.02670889474851_105.83872278163015_hanoi_google_street_view_image,, +5640928226,5,hanoi,20.998700008568832,105.85243902577905,,20.998700008568832_105.85243902577905_hanoi_google_maps_image,,20.998700008568832_105.85243902577905_hanoi_google_satellite_image,,20.998700008568832_105.85243902577905_hanoi_google_street_view_image,, +6682444185,5,hanoi,21.019737994699003,105.8233895262396,,21.019737994699003_105.8233895262396_hanoi_google_maps_image,,21.019737994699003_105.8233895262396_hanoi_google_satellite_image,,21.019737994699003_105.8233895262396_hanoi_google_street_view_image,, +3937714032,5,hanoi,21.008292741724393,105.85127133720407,,21.008292741724393_105.85127133720407_hanoi_google_maps_image,,21.008292741724393_105.85127133720407_hanoi_google_satellite_image,,21.008292741724393_105.85127133720407_hanoi_google_street_view_image,, +6897692985,5,hanoi,21.020251237893806,105.8216042586936,,21.020251237893806_105.8216042586936_hanoi_google_maps_image,,21.020251237893806_105.8216042586936_hanoi_google_satellite_image,,21.020251237893806_105.8216042586936_hanoi_google_street_view_image,, +5254163722,5,hanoi,21.039320849668325,105.85129075502276,,21.039320849668325_105.85129075502276_hanoi_google_maps_image,,21.039320849668325_105.85129075502276_hanoi_google_satellite_image,,21.039320849668325_105.85129075502276_hanoi_google_street_view_image,, +4892069827,1,hong_kong,22.284133698639288,114.18620675026642,,22.284133698639288_114.18620675026642_hong_kong_google_maps_image,,22.284133698639288_114.18620675026642_hong_kong_google_satellite_image,,22.284133698639288_114.18620675026642_hong_kong_google_street_view_image,, +4796625657,1,hong_kong,22.395456199999998,114.1985323,,22.395456199999998_114.1985323_hong_kong_google_maps_image,,22.395456199999998_114.1985323_hong_kong_google_satellite_image,,22.395456199999998_114.1985323_hong_kong_google_street_view_image,, +205719285,1,hong_kong,22.30692719527565,114.22231798308853,,22.30692719527565_114.22231798308853_hong_kong_google_maps_image,,22.30692719527565_114.22231798308853_hong_kong_google_satellite_image,,22.30692719527565_114.22231798308853_hong_kong_google_street_view_image,, +449876412,1,hong_kong,22.438756578053916,114.06494814322687,,22.438756578053916_114.06494814322687_hong_kong_google_maps_image,,22.438756578053916_114.06494814322687_hong_kong_google_satellite_image,,22.438756578053916_114.06494814322687_hong_kong_google_street_view_image,, +4929022970,1,hong_kong,22.372182039452962,114.19863426804811,,22.372182039452962_114.19863426804811_hong_kong_google_maps_image,,22.372182039452962_114.19863426804811_hong_kong_google_satellite_image,,22.372182039452962_114.19863426804811_hong_kong_google_street_view_image,, +1797941167,1,hong_kong,22.284718725860476,114.21170658297555,,22.284718725860476_114.21170658297555_hong_kong_google_maps_image,,22.284718725860476_114.21170658297555_hong_kong_google_satellite_image,,22.284718725860476_114.21170658297555_hong_kong_google_street_view_image,, +2411988977,1,hong_kong,22.300353191732224,114.17803962954156,,22.300353191732224_114.17803962954156_hong_kong_google_maps_image,,22.300353191732224_114.17803962954156_hong_kong_google_satellite_image,,22.300353191732224_114.17803962954156_hong_kong_google_street_view_image,, +448228055,1,hong_kong,22.43305331603814,113.99546771857557,,22.43305331603814_113.99546771857557_hong_kong_google_maps_image,,22.43305331603814_113.99546771857557_hong_kong_google_satellite_image,,22.43305331603814_113.99546771857557_hong_kong_google_street_view_image,, +369378651,1,hong_kong,22.50118642581332,114.14816314433028,,22.50118642581332_114.14816314433028_hong_kong_google_maps_image,,22.50118642581332_114.14816314433028_hong_kong_google_satellite_image,,22.50118642581332_114.14816314433028_hong_kong_google_street_view_image,, +1026522021,1,hong_kong,22.26550244118609,114.16150005809982,,22.26550244118609_114.16150005809982_hong_kong_google_maps_image,,22.26550244118609_114.16150005809982_hong_kong_google_satellite_image,,22.26550244118609_114.16150005809982_hong_kong_google_street_view_image,, +4714345992,2,hong_kong,22.276216706228734,114.17223512948674,,22.276216706228734_114.17223512948674_hong_kong_google_maps_image,,22.276216706228734_114.17223512948674_hong_kong_google_satellite_image,,22.276216706228734_114.17223512948674_hong_kong_google_street_view_image,, +2668679565,2,hong_kong,22.3310895,114.2042301,,22.3310895_114.2042301_hong_kong_google_maps_image,,22.3310895_114.2042301_hong_kong_google_satellite_image,,22.3310895_114.2042301_hong_kong_google_street_view_image,, +4332082788,2,hong_kong,22.344318661329456,114.10707595198313,,22.344318661329456_114.10707595198313_hong_kong_google_maps_image,,22.344318661329456_114.10707595198313_hong_kong_google_satellite_image,,22.344318661329456_114.10707595198313_hong_kong_google_street_view_image,, +207402934,2,hong_kong,22.443569281211314,114.03051306330704,,22.443569281211314_114.03051306330704_hong_kong_google_maps_image,,22.443569281211314_114.03051306330704_hong_kong_google_satellite_image,,22.443569281211314_114.03051306330704_hong_kong_google_street_view_image,, +6713630045,2,hong_kong,22.27864236348188,114.17278940379133,,22.27864236348188_114.17278940379133_hong_kong_google_maps_image,,22.27864236348188_114.17278940379133_hong_kong_google_satellite_image,,22.27864236348188_114.17278940379133_hong_kong_google_street_view_image,, +7104352625,2,hong_kong,22.30442181064681,114.16918179396565,,22.30442181064681_114.16918179396565_hong_kong_google_maps_image,,22.30442181064681_114.16918179396565_hong_kong_google_satellite_image,,22.30442181064681_114.16918179396565_hong_kong_google_street_view_image,, +4535490115,2,hong_kong,22.307189365009883,114.16639275849363,,22.307189365009883_114.16639275849363_hong_kong_google_maps_image,,22.307189365009883_114.16639275849363_hong_kong_google_satellite_image,,22.307189365009883_114.16639275849363_hong_kong_google_street_view_image,, +7528483966,2,hong_kong,22.446968377444716,114.02752379879898,,22.446968377444716_114.02752379879898_hong_kong_google_maps_image,,22.446968377444716_114.02752379879898_hong_kong_google_satellite_image,,22.446968377444716_114.02752379879898_hong_kong_google_street_view_image,, +4860792300,2,hong_kong,22.30518567025006,114.19040977857748,,22.30518567025006_114.19040977857748_hong_kong_google_maps_image,,22.30518567025006_114.19040977857748_hong_kong_google_satellite_image,,22.30518567025006_114.19040977857748_hong_kong_google_street_view_image,, +1698966259,2,hong_kong,22.535821600000002,114.0894877,,22.535821600000002_114.0894877_hong_kong_google_maps_image,,22.535821600000002_114.0894877_hong_kong_google_satellite_image,,22.535821600000002_114.0894877_hong_kong_google_street_view_image,, +6575813313,3,hong_kong,22.337462334621495,114.13847618743775,,22.337462334621495_114.13847618743775_hong_kong_google_maps_image,,22.337462334621495_114.13847618743775_hong_kong_google_satellite_image,,22.337462334621495_114.13847618743775_hong_kong_google_street_view_image,, +4377531470,3,hong_kong,22.333547345397413,114.19618840192908,,22.333547345397413_114.19618840192908_hong_kong_google_maps_image,,22.333547345397413_114.19618840192908_hong_kong_google_satellite_image,,22.333547345397413_114.19618840192908_hong_kong_google_street_view_image,, +4846225287,3,hong_kong,22.334469367610204,114.19779226860872,,22.334469367610204_114.19779226860872_hong_kong_google_maps_image,,22.334469367610204_114.19779226860872_hong_kong_google_satellite_image,,22.334469367610204_114.19779226860872_hong_kong_google_street_view_image,, +4448807066,3,hong_kong,22.328983454514894,114.1875223434335,,22.328983454514894_114.1875223434335_hong_kong_google_maps_image,,22.328983454514894_114.1875223434335_hong_kong_google_satellite_image,,22.328983454514894_114.1875223434335_hong_kong_google_street_view_image,, +4844544925,3,hong_kong,22.328986232442436,114.1874326291503,,22.328986232442436_114.1874326291503_hong_kong_google_maps_image,,22.328986232442436_114.1874326291503_hong_kong_google_satellite_image,,22.328986232442436_114.1874326291503_hong_kong_google_street_view_image,, +4735641521,3,hong_kong,22.266400789793277,114.25024598816081,,22.266400789793277_114.25024598816081_hong_kong_google_maps_image,,22.266400789793277_114.25024598816081_hong_kong_google_satellite_image,,22.266400789793277_114.25024598816081_hong_kong_google_street_view_image,, +135952234,3,hong_kong,22.385129492278143,114.20434152245105,,22.385129492278143_114.20434152245105_hong_kong_google_maps_image,,22.385129492278143_114.20434152245105_hong_kong_google_satellite_image,,22.385129492278143_114.20434152245105_hong_kong_google_street_view_image,, +6536997943,3,hong_kong,22.31499045556765,114.22450904910619,,22.31499045556765_114.22450904910619_hong_kong_google_maps_image,,22.31499045556765_114.22450904910619_hong_kong_google_satellite_image,,22.31499045556765_114.22450904910619_hong_kong_google_street_view_image,, +4239530853,3,hong_kong,22.284460005702247,114.15093592770678,,22.284460005702247_114.15093592770678_hong_kong_google_maps_image,,22.284460005702247_114.15093592770678_hong_kong_google_satellite_image,,22.284460005702247_114.15093592770678_hong_kong_google_street_view_image,, +259578104,3,hong_kong,22.332773219154767,114.15370100960129,,22.332773219154767_114.15370100960129_hong_kong_google_maps_image,,22.332773219154767_114.15370100960129_hong_kong_google_satellite_image,,22.332773219154767_114.15370100960129_hong_kong_google_street_view_image,, +3125709385,4,hong_kong,22.28280239275675,114.12936540767328,,22.28280239275675_114.12936540767328_hong_kong_google_maps_image,,22.28280239275675_114.12936540767328_hong_kong_google_satellite_image,,22.28280239275675_114.12936540767328_hong_kong_google_street_view_image,, +4850400062,4,hong_kong,22.3418432306103,114.19228650803899,,22.3418432306103_114.19228650803899_hong_kong_google_maps_image,,22.3418432306103_114.19228650803899_hong_kong_google_satellite_image,,22.3418432306103_114.19228650803899_hong_kong_google_street_view_image,, +2374461156,4,hong_kong,22.2920894,114.1989031,,22.2920894_114.1989031_hong_kong_google_maps_image,,22.2920894_114.1989031_hong_kong_google_satellite_image,,22.2920894_114.1989031_hong_kong_google_street_view_image,, +4860767139,4,hong_kong,22.370883378450664,114.11749322473084,,22.370883378450664_114.11749322473084_hong_kong_google_maps_image,,22.370883378450664_114.11749322473084_hong_kong_google_satellite_image,,22.370883378450664_114.11749322473084_hong_kong_google_street_view_image,, +4507124689,4,hong_kong,22.315525199999996,114.219406,,22.315525199999996_114.219406_hong_kong_google_maps_image,,22.315525199999996_114.219406_hong_kong_google_satellite_image,,22.315525199999996_114.219406_hong_kong_google_street_view_image,, +4862556866,4,hong_kong,22.285763392743434,114.13656747105472,,22.285763392743434_114.13656747105472_hong_kong_google_maps_image,,22.285763392743434_114.13656747105472_hong_kong_google_satellite_image,,22.285763392743434_114.13656747105472_hong_kong_google_street_view_image,, +4858295348,4,hong_kong,22.292229508399178,114.20147571753012,,22.292229508399178_114.20147571753012_hong_kong_google_maps_image,,22.292229508399178_114.20147571753012_hong_kong_google_satellite_image,,22.292229508399178_114.20147571753012_hong_kong_google_street_view_image,, +6837889661,4,hong_kong,22.277769071191972,114.22684808096034,,22.277769071191972_114.22684808096034_hong_kong_google_maps_image,,22.277769071191972_114.22684808096034_hong_kong_google_satellite_image,,22.277769071191972_114.22684808096034_hong_kong_google_street_view_image,, +184798478,4,hong_kong,22.288940695856468,114.13728890745946,,22.288940695856468_114.13728890745946_hong_kong_google_maps_image,,22.288940695856468_114.13728890745946_hong_kong_google_satellite_image,,22.288940695856468_114.13728890745946_hong_kong_google_street_view_image,, +412685601,4,hong_kong,22.323921779584147,114.16751683359722,,22.323921779584147_114.16751683359722_hong_kong_google_maps_image,,22.323921779584147_114.16751683359722_hong_kong_google_satellite_image,,22.323921779584147_114.16751683359722_hong_kong_google_street_view_image,, +4265740938,5,hong_kong,22.29134124852563,114.19809722395156,,22.29134124852563_114.19809722395156_hong_kong_google_maps_image,,22.29134124852563_114.19809722395156_hong_kong_google_satellite_image,,22.29134124852563_114.19809722395156_hong_kong_google_street_view_image,, +4085111529,5,hong_kong,22.305732581981363,114.1865769466339,,22.305732581981363_114.1865769466339_hong_kong_google_maps_image,,22.305732581981363_114.1865769466339_hong_kong_google_satellite_image,,22.305732581981363_114.1865769466339_hong_kong_google_street_view_image,, +4085888180,5,hong_kong,22.321084346445794,114.16894636524125,,22.321084346445794_114.16894636524125_hong_kong_google_maps_image,,22.321084346445794_114.16894636524125_hong_kong_google_satellite_image,,22.321084346445794_114.16894636524125_hong_kong_google_street_view_image,, +4850219814,5,hong_kong,22.249003532685723,114.15610284337879,,22.249003532685723_114.15610284337879_hong_kong_google_maps_image,,22.249003532685723_114.15610284337879_hong_kong_google_satellite_image,,22.249003532685723_114.15610284337879_hong_kong_google_street_view_image,, +3483855627,5,hong_kong,22.317589030551233,114.26543205646237,,22.317589030551233_114.26543205646237_hong_kong_google_maps_image,,22.317589030551233_114.26543205646237_hong_kong_google_satellite_image,,22.317589030551233_114.26543205646237_hong_kong_google_street_view_image,, +5529769123,5,hong_kong,22.386789766657888,114.2033676235673,,22.386789766657888_114.2033676235673_hong_kong_google_maps_image,,22.386789766657888_114.2033676235673_hong_kong_google_satellite_image,,22.386789766657888_114.2033676235673_hong_kong_google_street_view_image,, +2146262929,5,hong_kong,22.321436753617395,114.16180592296789,,22.321436753617395_114.16180592296789_hong_kong_google_maps_image,,22.321436753617395_114.16180592296789_hong_kong_google_satellite_image,,22.321436753617395_114.16180592296789_hong_kong_google_street_view_image,, +5529800921,5,hong_kong,22.386605327053417,114.20328394120013,,22.386605327053417_114.20328394120013_hong_kong_google_maps_image,,22.386605327053417_114.20328394120013_hong_kong_google_satellite_image,,22.386605327053417_114.20328394120013_hong_kong_google_street_view_image,, +465800314,5,hong_kong,22.24130655896862,114.15521825902438,,22.24130655896862_114.15521825902438_hong_kong_google_maps_image,,22.24130655896862_114.15521825902438_hong_kong_google_satellite_image,,22.24130655896862_114.15521825902438_hong_kong_google_street_view_image,, +1299465475,5,hong_kong,22.29052556670896,114.19748546214171,,22.29052556670896_114.19748546214171_hong_kong_google_maps_image,,22.29052556670896_114.19748546214171_hong_kong_google_satellite_image,,22.29052556670896_114.19748546214171_hong_kong_google_street_view_image,, +1545693817,1,lisbon,38.70966287724227,-9.140123829550635,,38.70966287724227_-9.140123829550635_lisbon_google_maps_image,,38.70966287724227_-9.140123829550635_lisbon_google_satellite_image,,38.70966287724227_-9.140123829550635_lisbon_google_street_view_image,, +6707461586,1,lisbon,38.705600573157014,-9.161490871745999,,38.705600573157014_-9.161490871745999_lisbon_google_maps_image,,38.705600573157014_-9.161490871745999_lisbon_google_satellite_image,,38.705600573157014_-9.161490871745999_lisbon_google_street_view_image,, +6366440072,1,lisbon,38.74430350132741,-9.149393634220065,,38.74430350132741_-9.149393634220065_lisbon_google_maps_image,,38.74430350132741_-9.149393634220065_lisbon_google_satellite_image,,38.74430350132741_-9.149393634220065_lisbon_google_street_view_image,, +4023605758,1,lisbon,38.74980839245447,-9.117581390729129,,38.74980839245447_-9.117581390729129_lisbon_google_maps_image,,38.74980839245447_-9.117581390729129_lisbon_google_satellite_image,,38.74980839245447_-9.117581390729129_lisbon_google_street_view_image,, +5984944787,1,lisbon,38.73555107121585,-9.14552187742019,,38.73555107121585_-9.14552187742019_lisbon_google_maps_image,,38.73555107121585_-9.14552187742019_lisbon_google_satellite_image,,38.73555107121585_-9.14552187742019_lisbon_google_street_view_image,, +5427721798,1,lisbon,38.73331861089569,-9.147531312446892,,38.73331861089569_-9.147531312446892_lisbon_google_maps_image,,38.73331861089569_-9.147531312446892_lisbon_google_satellite_image,,38.73331861089569_-9.147531312446892_lisbon_google_street_view_image,, +6307188788,1,lisbon,38.726024798001916,-9.112265702090244,,38.726024798001916_-9.112265702090244_lisbon_google_maps_image,,38.726024798001916_-9.112265702090244_lisbon_google_satellite_image,,38.726024798001916_-9.112265702090244_lisbon_google_street_view_image,, +3157752612,1,lisbon,38.741275,-9.1660437,,38.741275_-9.1660437_lisbon_google_maps_image,,38.741275_-9.1660437_lisbon_google_satellite_image,,38.741275_-9.1660437_lisbon_google_street_view_image,, +7539039885,1,lisbon,38.740038754474725,-9.167147608897007,,38.740038754474725_-9.167147608897007_lisbon_google_maps_image,,38.740038754474725_-9.167147608897007_lisbon_google_satellite_image,,38.740038754474725_-9.167147608897007_lisbon_google_street_view_image,, +2295708194,1,lisbon,38.705907367041455,-9.208838705227363,,38.705907367041455_-9.208838705227363_lisbon_google_maps_image,,38.705907367041455_-9.208838705227363_lisbon_google_satellite_image,,38.705907367041455_-9.208838705227363_lisbon_google_street_view_image,, +6262730577,2,lisbon,38.756249098471045,-9.139818637865963,,38.756249098471045_-9.139818637865963_lisbon_google_maps_image,,38.756249098471045_-9.139818637865963_lisbon_google_satellite_image,,38.756249098471045_-9.139818637865963_lisbon_google_street_view_image,, +6326009249,2,lisbon,38.73931600240588,-9.152317852337573,,38.73931600240588_-9.152317852337573_lisbon_google_maps_image,,38.73931600240588_-9.152317852337573_lisbon_google_satellite_image,,38.73931600240588_-9.152317852337573_lisbon_google_street_view_image,, +663925349,2,lisbon,38.71385759211145,-9.137879992827276,,38.71385759211145_-9.137879992827276_lisbon_google_maps_image,,38.71385759211145_-9.137879992827276_lisbon_google_satellite_image,,38.71385759211145_-9.137879992827276_lisbon_google_street_view_image,, +4622636093,2,lisbon,38.71250094463224,-9.125709281250519,,38.71250094463224_-9.125709281250519_lisbon_google_maps_image,,38.71250094463224_-9.125709281250519_lisbon_google_satellite_image,,38.71250094463224_-9.125709281250519_lisbon_google_street_view_image,, +97277780,2,lisbon,38.73113838911016,-9.144663546508824,,38.73113838911016_-9.144663546508824_lisbon_google_maps_image,,38.73113838911016_-9.144663546508824_lisbon_google_satellite_image,,38.73113838911016_-9.144663546508824_lisbon_google_street_view_image,, +5141865824,2,lisbon,38.71118460769638,-9.14293666558514,,38.71118460769638_-9.14293666558514_lisbon_google_maps_image,,38.71118460769638_-9.14293666558514_lisbon_google_satellite_image,,38.71118460769638_-9.14293666558514_lisbon_google_street_view_image,, +4226508186,2,lisbon,38.71556728235288,-9.146179981223728,,38.71556728235288_-9.146179981223728_lisbon_google_maps_image,,38.71556728235288_-9.146179981223728_lisbon_google_satellite_image,,38.71556728235288_-9.146179981223728_lisbon_google_street_view_image,, +5164905587,2,lisbon,38.73509014946658,-9.149790314950465,,38.73509014946658_-9.149790314950465_lisbon_google_maps_image,,38.73509014946658_-9.149790314950465_lisbon_google_satellite_image,,38.73509014946658_-9.149790314950465_lisbon_google_street_view_image,, +6427585145,2,lisbon,38.70471154696579,-9.168350448728575,,38.70471154696579_-9.168350448728575_lisbon_google_maps_image,,38.70471154696579_-9.168350448728575_lisbon_google_satellite_image,,38.70471154696579_-9.168350448728575_lisbon_google_street_view_image,, +4530470190,2,lisbon,38.73303296858585,-9.150064841274663,,38.73303296858585_-9.150064841274663_lisbon_google_maps_image,,38.73303296858585_-9.150064841274663_lisbon_google_satellite_image,,38.73303296858585_-9.150064841274663_lisbon_google_street_view_image,, +1743702474,3,lisbon,38.74320421192193,-9.133698814961022,,38.74320421192193_-9.133698814961022_lisbon_google_maps_image,,38.74320421192193_-9.133698814961022_lisbon_google_satellite_image,,38.74320421192193_-9.133698814961022_lisbon_google_street_view_image,, +6453992485,3,lisbon,38.71525972963288,-9.137102250557195,,38.71525972963288_-9.137102250557195_lisbon_google_maps_image,,38.71525972963288_-9.137102250557195_lisbon_google_satellite_image,,38.71525972963288_-9.137102250557195_lisbon_google_street_view_image,, +4839836049,3,lisbon,38.73295043539661,-9.141001232246735,,38.73295043539661_-9.141001232246735_lisbon_google_maps_image,,38.73295043539661_-9.141001232246735_lisbon_google_satellite_image,,38.73295043539661_-9.141001232246735_lisbon_google_street_view_image,, +3003135433,3,lisbon,38.7624225,-9.1134113,,38.7624225_-9.1134113_lisbon_google_maps_image,,38.7624225_-9.1134113_lisbon_google_satellite_image,,38.7624225_-9.1134113_lisbon_google_street_view_image,, +5565322521,3,lisbon,38.72319377709821,-9.145689855970039,,38.72319377709821_-9.145689855970039_lisbon_google_maps_image,,38.72319377709821_-9.145689855970039_lisbon_google_satellite_image,,38.72319377709821_-9.145689855970039_lisbon_google_street_view_image,, +6124616185,3,lisbon,38.710236788304506,-9.145270678079891,,38.710236788304506_-9.145270678079891_lisbon_google_maps_image,,38.710236788304506_-9.145270678079891_lisbon_google_satellite_image,,38.710236788304506_-9.145270678079891_lisbon_google_street_view_image,, +5631421818,3,lisbon,38.74816695467958,-9.188352574429125,,38.74816695467958_-9.188352574429125_lisbon_google_maps_image,,38.74816695467958_-9.188352574429125_lisbon_google_satellite_image,,38.74816695467958_-9.188352574429125_lisbon_google_street_view_image,, +3999539689,3,lisbon,38.738134073850965,-9.147085165587445,,38.738134073850965_-9.147085165587445_lisbon_google_maps_image,,38.738134073850965_-9.147085165587445_lisbon_google_satellite_image,,38.738134073850965_-9.147085165587445_lisbon_google_street_view_image,, +4624286128,3,lisbon,38.71082442420567,-9.136883577728488,,38.71082442420567_-9.136883577728488_lisbon_google_maps_image,,38.71082442420567_-9.136883577728488_lisbon_google_satellite_image,,38.71082442420567_-9.136883577728488_lisbon_google_street_view_image,, +454653397,3,lisbon,38.77927101269666,-9.160503526615129,,38.77927101269666_-9.160503526615129_lisbon_google_maps_image,,38.77927101269666_-9.160503526615129_lisbon_google_satellite_image,,38.77927101269666_-9.160503526615129_lisbon_google_street_view_image,, +3376281170,4,lisbon,38.745068775256456,-9.180649288650995,,38.745068775256456_-9.180649288650995_lisbon_google_maps_image,,38.745068775256456_-9.180649288650995_lisbon_google_satellite_image,,38.745068775256456_-9.180649288650995_lisbon_google_street_view_image,, +5433711050,4,lisbon,38.70892617854385,-9.166882837385984,,38.70892617854385_-9.166882837385984_lisbon_google_maps_image,,38.70892617854385_-9.166882837385984_lisbon_google_satellite_image,,38.70892617854385_-9.166882837385984_lisbon_google_street_view_image,, +2620375202,4,lisbon,38.71134955960933,-9.145557584917777,,38.71134955960933_-9.145557584917777_lisbon_google_maps_image,,38.71134955960933_-9.145557584917777_lisbon_google_satellite_image,,38.71134955960933_-9.145557584917777_lisbon_google_street_view_image,, +6307214586,4,lisbon,38.7268700771402,-9.120876353709441,,38.7268700771402_-9.120876353709441_lisbon_google_maps_image,,38.7268700771402_-9.120876353709441_lisbon_google_satellite_image,,38.7268700771402_-9.120876353709441_lisbon_google_street_view_image,, +6022965179,4,lisbon,38.722488465181144,-9.135351122023408,,38.722488465181144_-9.135351122023408_lisbon_google_maps_image,,38.722488465181144_-9.135351122023408_lisbon_google_satellite_image,,38.722488465181144_-9.135351122023408_lisbon_google_street_view_image,, +3624591180,4,lisbon,38.71929219441708,-9.135593221978837,,38.71929219441708_-9.135593221978837_lisbon_google_maps_image,,38.71929219441708_-9.135593221978837_lisbon_google_satellite_image,,38.71929219441708_-9.135593221978837_lisbon_google_street_view_image,, +5963845096,4,lisbon,38.742330800000005,-9.1399983,,38.742330800000005_-9.1399983_lisbon_google_maps_image,,38.742330800000005_-9.1399983_lisbon_google_satellite_image,,38.742330800000005_-9.1399983_lisbon_google_street_view_image,, +97680513,4,lisbon,38.7494282800985,-9.146032297652159,,38.7494282800985_-9.146032297652159_lisbon_google_maps_image,,38.7494282800985_-9.146032297652159_lisbon_google_satellite_image,,38.7494282800985_-9.146032297652159_lisbon_google_street_view_image,, +2516634850,4,lisbon,38.74978544166516,-9.173100412338812,,38.74978544166516_-9.173100412338812_lisbon_google_maps_image,,38.74978544166516_-9.173100412338812_lisbon_google_satellite_image,,38.74978544166516_-9.173100412338812_lisbon_google_street_view_image,, +1587098198,4,lisbon,38.70525240555577,-9.193846082503352,,38.70525240555577_-9.193846082503352_lisbon_google_maps_image,,38.70525240555577_-9.193846082503352_lisbon_google_satellite_image,,38.70525240555577_-9.193846082503352_lisbon_google_street_view_image,, +4639845489,5,lisbon,38.73309861145979,-9.134301593579302,,38.73309861145979_-9.134301593579302_lisbon_google_maps_image,,38.73309861145979_-9.134301593579302_lisbon_google_satellite_image,,38.73309861145979_-9.134301593579302_lisbon_google_street_view_image,, +4287522394,5,lisbon,38.72607004572371,-9.13294234496399,,38.72607004572371_-9.13294234496399_lisbon_google_maps_image,,38.72607004572371_-9.13294234496399_lisbon_google_satellite_image,,38.72607004572371_-9.13294234496399_lisbon_google_street_view_image,, +1832831352,5,lisbon,38.723659358373595,-9.129508409179365,,38.723659358373595_-9.129508409179365_lisbon_google_maps_image,,38.723659358373595_-9.129508409179365_lisbon_google_satellite_image,,38.723659358373595_-9.129508409179365_lisbon_google_street_view_image,, +4510657283,5,lisbon,38.71949307744241,-9.12975798953745,,38.71949307744241_-9.12975798953745_lisbon_google_maps_image,,38.71949307744241_-9.12975798953745_lisbon_google_satellite_image,,38.71949307744241_-9.12975798953745_lisbon_google_street_view_image,, +3997125184,5,lisbon,38.73414497252993,-9.128573237178719,,38.73414497252993_-9.128573237178719_lisbon_google_maps_image,,38.73414497252993_-9.128573237178719_lisbon_google_satellite_image,,38.73414497252993_-9.128573237178719_lisbon_google_street_view_image,, +6206335524,5,lisbon,38.71796314871114,-9.166435785049844,,38.71796314871114_-9.166435785049844_lisbon_google_maps_image,,38.71796314871114_-9.166435785049844_lisbon_google_satellite_image,,38.71796314871114_-9.166435785049844_lisbon_google_street_view_image,, +98625344,5,lisbon,38.73526918675126,-9.133157942472199,,38.73526918675126_-9.133157942472199_lisbon_google_maps_image,,38.73526918675126_-9.133157942472199_lisbon_google_satellite_image,,38.73526918675126_-9.133157942472199_lisbon_google_street_view_image,, +2908623658,5,lisbon,38.7183950062489,-9.129897590539246,,38.7183950062489_-9.129897590539246_lisbon_google_maps_image,,38.7183950062489_-9.129897590539246_lisbon_google_satellite_image,,38.7183950062489_-9.129897590539246_lisbon_google_street_view_image,, +5688444724,5,lisbon,38.73273056041424,-9.134251425001864,,38.73273056041424_-9.134251425001864_lisbon_google_maps_image,,38.73273056041424_-9.134251425001864_lisbon_google_satellite_image,,38.73273056041424_-9.134251425001864_lisbon_google_street_view_image,, +3663653601,5,lisbon,38.731261719462296,-9.136411705274716,,38.731261719462296_-9.136411705274716_lisbon_google_maps_image,,38.731261719462296_-9.136411705274716_lisbon_google_satellite_image,,38.731261719462296_-9.136411705274716_lisbon_google_street_view_image,, +1505918056,1,melbourne,-37.72634093236668,144.80690060968655,,-37.72634093236668_144.80690060968655_melbourne_google_maps_image,,-37.72634093236668_144.80690060968655_melbourne_google_satellite_image,,-37.72634093236668_144.80690060968655_melbourne_google_street_view_image,, +2172299040,1,melbourne,-37.679679899999755,144.9180914,,-37.679679899999755_144.9180914_melbourne_google_maps_image,,-37.679679899999755_144.9180914_melbourne_google_satellite_image,,-37.679679899999755_144.9180914_melbourne_google_street_view_image,, +365210773,1,melbourne,-38.14249693427462,145.12327956942863,,-38.14249693427462_145.12327956942863_melbourne_google_maps_image,,-38.14249693427462_145.12327956942863_melbourne_google_satellite_image,,-38.14249693427462_145.12327956942863_melbourne_google_street_view_image,, +5824764073,1,melbourne,-37.78246724295598,144.83367791035027,,-37.78246724295598_144.83367791035027_melbourne_google_maps_image,,-37.78246724295598_144.83367791035027_melbourne_google_satellite_image,,-37.78246724295598_144.83367791035027_melbourne_google_street_view_image,, +190526844,1,melbourne,-38.004547914836444,145.26656385045845,,-38.004547914836444_145.26656385045845_melbourne_google_maps_image,,-38.004547914836444_145.26656385045845_melbourne_google_satellite_image,,-38.004547914836444_145.26656385045845_melbourne_google_street_view_image,, +881751151,1,melbourne,-37.687230278894226,144.88494206982634,,-37.687230278894226_144.88494206982634_melbourne_google_maps_image,,-37.687230278894226_144.88494206982634_melbourne_google_satellite_image,,-37.687230278894226_144.88494206982634_melbourne_google_street_view_image,, +508030779,1,melbourne,-37.79367239999974,144.8610359,,-37.79367239999974_144.8610359_melbourne_google_maps_image,,-37.79367239999974_144.8610359_melbourne_google_satellite_image,,-37.79367239999974_144.8610359_melbourne_google_street_view_image,, +2343283482,1,melbourne,-37.902768161867854,144.6518352001569,,-37.902768161867854_144.6518352001569_melbourne_google_maps_image,,-37.902768161867854_144.6518352001569_melbourne_google_satellite_image,,-37.902768161867854_144.6518352001569_melbourne_google_street_view_image,, +3387681615,1,melbourne,-37.71909461875353,145.03838420810493,,-37.71909461875353_145.03838420810493_melbourne_google_maps_image,,-37.71909461875353_145.03838420810493_melbourne_google_satellite_image,,-37.71909461875353_145.03838420810493_melbourne_google_street_view_image,, +2388090624,1,melbourne,-37.783659999999756,144.8323507,,-37.783659999999756_144.8323507_melbourne_google_maps_image,,-37.783659999999756_144.8323507_melbourne_google_satellite_image,,-37.783659999999756_144.8323507_melbourne_google_street_view_image,, +5640738710,2,melbourne,-37.73892283660425,145.00169864808183,,-37.73892283660425_145.00169864808183_melbourne_google_maps_image,,-37.73892283660425_145.00169864808183_melbourne_google_satellite_image,,-37.73892283660425_145.00169864808183_melbourne_google_street_view_image,, +1432376901,2,melbourne,-37.74810720111193,145.04266874870487,,-37.74810720111193_145.04266874870487_melbourne_google_maps_image,,-37.74810720111193_145.04266874870487_melbourne_google_satellite_image,,-37.74810720111193_145.04266874870487_melbourne_google_street_view_image,, +1658371416,2,melbourne,-37.892058612946784,145.14399105974852,,-37.892058612946784_145.14399105974852_melbourne_google_maps_image,,-37.892058612946784_145.14399105974852_melbourne_google_satellite_image,,-37.892058612946784_145.14399105974852_melbourne_google_street_view_image,, +2285130249,2,melbourne,-37.702123027939486,144.79954309277667,,-37.702123027939486_144.79954309277667_melbourne_google_maps_image,,-37.702123027939486_144.79954309277667_melbourne_google_satellite_image,,-37.702123027939486_144.79954309277667_melbourne_google_street_view_image,, +5242175957,2,melbourne,-37.69388360881736,144.75469735430232,,-37.69388360881736_144.75469735430232_melbourne_google_maps_image,,-37.69388360881736_144.75469735430232_melbourne_google_satellite_image,,-37.69388360881736_144.75469735430232_melbourne_google_street_view_image,, +4456047388,2,melbourne,-37.913863468399136,145.25705024230396,,-37.913863468399136_145.25705024230396_melbourne_google_maps_image,,-37.913863468399136_145.25705024230396_melbourne_google_satellite_image,,-37.913863468399136_145.25705024230396_melbourne_google_street_view_image,, +5076265958,2,melbourne,-37.77327138862686,145.11397856155645,,-37.77327138862686_145.11397856155645_melbourne_google_maps_image,,-37.77327138862686_145.11397856155645_melbourne_google_satellite_image,,-37.77327138862686_145.11397856155645_melbourne_google_street_view_image,, +539840860,2,melbourne,-37.67292040527805,145.016654795642,,-37.67292040527805_145.016654795642_melbourne_google_maps_image,,-37.67292040527805_145.016654795642_melbourne_google_satellite_image,,-37.67292040527805_145.016654795642_melbourne_google_street_view_image,, +2918617899,2,melbourne,-37.69724287593561,145.05750954609184,,-37.69724287593561_145.05750954609184_melbourne_google_maps_image,,-37.69724287593561_145.05750954609184_melbourne_google_satellite_image,,-37.69724287593561_145.05750954609184_melbourne_google_street_view_image,, +640788713,2,melbourne,-37.931331944519705,145.15537043900713,,-37.931331944519705_145.15537043900713_melbourne_google_maps_image,,-37.931331944519705_145.15537043900713_melbourne_google_satellite_image,,-37.931331944519705_145.15537043900713_melbourne_google_street_view_image,, +1864449244,3,melbourne,-37.715648388275234,145.12133933865198,,-37.715648388275234_145.12133933865198_melbourne_google_maps_image,,-37.715648388275234_145.12133933865198_melbourne_google_satellite_image,,-37.715648388275234_145.12133933865198_melbourne_google_street_view_image,, +1893236280,3,melbourne,-37.84863974794789,145.0803363097369,,-37.84863974794789_145.0803363097369_melbourne_google_maps_image,,-37.84863974794789_145.0803363097369_melbourne_google_satellite_image,,-37.84863974794789_145.0803363097369_melbourne_google_street_view_image,, +5963317160,3,melbourne,-37.945170020793796,145.15126299083795,,-37.945170020793796_145.15126299083795_melbourne_google_maps_image,,-37.945170020793796_145.15126299083795_melbourne_google_satellite_image,,-37.945170020793796_145.15126299083795_melbourne_google_street_view_image,, +6065623710,3,melbourne,-37.8989760782216,145.09194026091464,,-37.8989760782216_145.09194026091464_melbourne_google_maps_image,,-37.8989760782216_145.09194026091464_melbourne_google_satellite_image,,-37.8989760782216_145.09194026091464_melbourne_google_street_view_image,, +1864405191,3,melbourne,-37.716529707420456,145.12119078722694,,-37.716529707420456_145.12119078722694_melbourne_google_maps_image,,-37.716529707420456_145.12119078722694_melbourne_google_satellite_image,,-37.716529707420456_145.12119078722694_melbourne_google_street_view_image,, +5203746966,3,melbourne,-37.951286370029955,145.1512037278662,,-37.951286370029955_145.1512037278662_melbourne_google_maps_image,,-37.951286370029955_145.1512037278662_melbourne_google_satellite_image,,-37.951286370029955_145.1512037278662_melbourne_google_street_view_image,, +5213706361,3,melbourne,-37.951579542866526,145.15140985690735,,-37.951579542866526_145.15140985690735_melbourne_google_maps_image,,-37.951579542866526_145.15140985690735_melbourne_google_satellite_image,,-37.951579542866526_145.15140985690735_melbourne_google_street_view_image,, +1864449245,3,melbourne,-37.715717754910585,145.12132800287327,,-37.715717754910585_145.12132800287327_melbourne_google_maps_image,,-37.715717754910585_145.12132800287327_melbourne_google_satellite_image,,-37.715717754910585_145.12132800287327_melbourne_google_street_view_image,, +4186252195,3,melbourne,-37.871640811186154,144.77513306592417,,-37.871640811186154_144.77513306592417_melbourne_google_maps_image,,-37.871640811186154_144.77513306592417_melbourne_google_satellite_image,,-37.871640811186154_144.77513306592417_melbourne_google_street_view_image,, +1865226630,3,melbourne,-37.716296651798096,145.1212318973898,,-37.716296651798096_145.1212318973898_melbourne_google_maps_image,,-37.716296651798096_145.1212318973898_melbourne_google_satellite_image,,-37.716296651798096_145.1212318973898_melbourne_google_street_view_image,, +6734873390,4,melbourne,-37.806734534075844,145.02951552133834,,-37.806734534075844_145.02951552133834_melbourne_google_maps_image,,-37.806734534075844_145.02951552133834_melbourne_google_satellite_image,,-37.806734534075844_145.02951552133834_melbourne_google_street_view_image,, +5241952634,4,melbourne,-37.971695683458265,145.14966013431146,,-37.971695683458265_145.14966013431146_melbourne_google_maps_image,,-37.971695683458265_145.14966013431146_melbourne_google_satellite_image,,-37.971695683458265_145.14966013431146_melbourne_google_street_view_image,, +636550055,4,melbourne,-37.80080337874809,144.90133323784005,,-37.80080337874809_144.90133323784005_melbourne_google_maps_image,,-37.80080337874809_144.90133323784005_melbourne_google_satellite_image,,-37.80080337874809_144.90133323784005_melbourne_google_street_view_image,, +2372890188,4,melbourne,-37.81934530415186,144.94838027345284,,-37.81934530415186_144.94838027345284_melbourne_google_maps_image,,-37.81934530415186_144.94838027345284_melbourne_google_satellite_image,,-37.81934530415186_144.94838027345284_melbourne_google_street_view_image,, +542182657,4,melbourne,-37.92765372866354,145.11924437501168,,-37.92765372866354_145.11924437501168_melbourne_google_maps_image,,-37.92765372866354_145.11924437501168_melbourne_google_satellite_image,,-37.92765372866354_145.11924437501168_melbourne_google_street_view_image,, +669188509,4,melbourne,-37.76919954441362,145.00099898338325,,-37.76919954441362_145.00099898338325_melbourne_google_maps_image,,-37.76919954441362_145.00099898338325_melbourne_google_satellite_image,,-37.76919954441362_145.00099898338325_melbourne_google_street_view_image,, +5242064718,4,melbourne,-37.92530842629705,145.11903162086756,,-37.92530842629705_145.11903162086756_melbourne_google_maps_image,,-37.92530842629705_145.11903162086756_melbourne_google_satellite_image,,-37.92530842629705_145.11903162086756_melbourne_google_street_view_image,, +4815465776,4,melbourne,-37.965617338651015,145.1768451249083,,-37.965617338651015_145.1768451249083_melbourne_google_maps_image,,-37.965617338651015_145.1768451249083_melbourne_google_satellite_image,,-37.965617338651015_145.1768451249083_melbourne_google_street_view_image,, +2440470792,4,melbourne,-37.70247117154502,144.96551332224362,,-37.70247117154502_144.96551332224362_melbourne_google_maps_image,,-37.70247117154502_144.96551332224362_melbourne_google_satellite_image,,-37.70247117154502_144.96551332224362_melbourne_google_street_view_image,, +5074739721,4,melbourne,-37.993491901656,145.07643030587695,,-37.993491901656_145.07643030587695_melbourne_google_maps_image,,-37.993491901656_145.07643030587695_melbourne_google_satellite_image,,-37.993491901656_145.07643030587695_melbourne_google_street_view_image,, +732904918,5,melbourne,-37.788656616545076,144.93011574196427,,-37.788656616545076_144.93011574196427_melbourne_google_maps_image,,-37.788656616545076_144.93011574196427_melbourne_google_satellite_image,,-37.788656616545076_144.93011574196427_melbourne_google_street_view_image,, +538980964,5,melbourne,-37.965842568787274,145.17358786253862,,-37.965842568787274_145.17358786253862_melbourne_google_maps_image,,-37.965842568787274_145.17358786253862_melbourne_google_satellite_image,,-37.965842568787274_145.17358786253862_melbourne_google_street_view_image,, +2526463421,5,melbourne,-37.68972658594108,144.92714089267045,,-37.68972658594108_144.92714089267045_melbourne_google_maps_image,,-37.68972658594108_144.92714089267045_melbourne_google_satellite_image,,-37.68972658594108_144.92714089267045_melbourne_google_street_view_image,, +7418267481,5,melbourne,-37.783799581911765,144.97737726029933,,-37.783799581911765_144.97737726029933_melbourne_google_maps_image,,-37.783799581911765_144.97737726029933_melbourne_google_satellite_image,,-37.783799581911765_144.97737726029933_melbourne_google_street_view_image,, +86072173,5,melbourne,-37.758688824633346,144.94506521121076,,-37.758688824633346_144.94506521121076_melbourne_google_maps_image,,-37.758688824633346_144.94506521121076_melbourne_google_satellite_image,,-37.758688824633346_144.94506521121076_melbourne_google_street_view_image,, +543294996,5,melbourne,-37.98234631349976,145.2025905410507,,-37.98234631349976_145.2025905410507_melbourne_google_maps_image,,-37.98234631349976_145.2025905410507_melbourne_google_satellite_image,,-37.98234631349976_145.2025905410507_melbourne_google_street_view_image,, +1021355276,5,melbourne,-37.876734360399205,144.99650112858146,,-37.876734360399205_144.99650112858146_melbourne_google_maps_image,,-37.876734360399205_144.99650112858146_melbourne_google_satellite_image,,-37.876734360399205_144.99650112858146_melbourne_google_street_view_image,, +2643285274,5,melbourne,-37.81029275974744,144.9627803038081,,-37.81029275974744_144.9627803038081_melbourne_google_maps_image,,-37.81029275974744_144.9627803038081_melbourne_google_satellite_image,,-37.81029275974744_144.9627803038081_melbourne_google_street_view_image,, +1055795509,5,melbourne,-37.8382631963956,144.98712328118418,,-37.8382631963956_144.98712328118418_melbourne_google_maps_image,,-37.8382631963956_144.98712328118418_melbourne_google_satellite_image,,-37.8382631963956_144.98712328118418_melbourne_google_street_view_image,, +4290861195,5,melbourne,-37.79591315942575,144.9801055340467,,-37.79591315942575_144.9801055340467_melbourne_google_maps_image,,-37.79591315942575_144.9801055340467_melbourne_google_satellite_image,,-37.79591315942575_144.9801055340467_melbourne_google_street_view_image,, +1283108236,1,odense,55.34792011185958,10.337093563112308,,55.34792011185958_10.337093563112308_odense_google_maps_image,,55.34792011185958_10.337093563112308_odense_google_satellite_image,,55.34792011185958_10.337093563112308_odense_google_street_view_image,, +88220818,1,odense,55.35698537792091,10.38920237091158,,55.35698537792091_10.38920237091158_odense_google_maps_image,,55.35698537792091_10.38920237091158_odense_google_satellite_image,,55.35698537792091_10.38920237091158_odense_google_street_view_image,, +317270318,1,odense,55.389719571397755,10.424143749905634,,55.389719571397755_10.424143749905634_odense_google_maps_image,,55.389719571397755_10.424143749905634_odense_google_satellite_image,,55.389719571397755_10.424143749905634_odense_google_street_view_image,, +2456944016,1,odense,55.41226529481542,10.327528790652767,,55.41226529481542_10.327528790652767_odense_google_maps_image,,55.41226529481542_10.327528790652767_odense_google_satellite_image,,55.41226529481542_10.327528790652767_odense_google_street_view_image,, +3012543239,1,odense,55.358625092224784,10.389705718524745,,55.358625092224784_10.389705718524745_odense_google_maps_image,,55.358625092224784_10.389705718524745_odense_google_satellite_image,,55.358625092224784_10.389705718524745_odense_google_street_view_image,, +161033374,1,odense,55.36546850628367,10.344337349314165,,55.36546850628367_10.344337349314165_odense_google_maps_image,,55.36546850628367_10.344337349314165_odense_google_satellite_image,,55.36546850628367_10.344337349314165_odense_google_street_view_image,, +229973016,1,odense,55.43697290000001,10.4109166,,55.43697290000001_10.4109166_odense_google_maps_image,,55.43697290000001_10.4109166_odense_google_satellite_image,,55.43697290000001_10.4109166_odense_google_street_view_image,, +807348060,1,odense,55.402584427365404,10.35736392725704,,55.402584427365404_10.35736392725704_odense_google_maps_image,,55.402584427365404_10.35736392725704_odense_google_satellite_image,,55.402584427365404_10.35736392725704_odense_google_street_view_image,, +89406334,1,odense,55.358402316762536,10.398537331770799,,55.358402316762536_10.398537331770799_odense_google_maps_image,,55.358402316762536_10.398537331770799_odense_google_satellite_image,,55.358402316762536_10.398537331770799_odense_google_street_view_image,, +219546252,1,odense,55.36342351937621,10.349999032740081,,55.36342351937621_10.349999032740081_odense_google_maps_image,,55.36342351937621_10.349999032740081_odense_google_satellite_image,,55.36342351937621_10.349999032740081_odense_google_street_view_image,, +3928398472,2,odense,55.38471435941438,10.424581290002582,,55.38471435941438_10.424581290002582_odense_google_maps_image,,55.38471435941438_10.424581290002582_odense_google_satellite_image,,55.38471435941438_10.424581290002582_odense_google_street_view_image,, +134774079,2,odense,55.41028260717352,10.4088896860233,,55.41028260717352_10.4088896860233_odense_google_maps_image,,55.41028260717352_10.4088896860233_odense_google_satellite_image,,55.41028260717352_10.4088896860233_odense_google_street_view_image,, +7082127136,2,odense,55.39343677839279,10.423358247772079,,55.39343677839279_10.423358247772079_odense_google_maps_image,,55.39343677839279_10.423358247772079_odense_google_satellite_image,,55.39343677839279_10.423358247772079_odense_google_street_view_image,, +3927606880,2,odense,55.38297894626153,10.427830021839734,,55.38297894626153_10.427830021839734_odense_google_maps_image,,55.38297894626153_10.427830021839734_odense_google_satellite_image,,55.38297894626153_10.427830021839734_odense_google_street_view_image,, +5370003679,2,odense,55.393092643220754,10.42139265652369,,55.393092643220754_10.42139265652369_odense_google_maps_image,,55.393092643220754_10.42139265652369_odense_google_satellite_image,,55.393092643220754_10.42139265652369_odense_google_street_view_image,, +2264700908,2,odense,55.38490548047652,10.424614695877118,,55.38490548047652_10.424614695877118_odense_google_maps_image,,55.38490548047652_10.424614695877118_odense_google_satellite_image,,55.38490548047652_10.424614695877118_odense_google_street_view_image,, +258430747,2,odense,55.36820093480394,10.357599753926149,,55.36820093480394_10.357599753926149_odense_google_maps_image,,55.36820093480394_10.357599753926149_odense_google_satellite_image,,55.36820093480394_10.357599753926149_odense_google_street_view_image,, +174302873,2,odense,55.418487699999986,10.4040199,,55.418487699999986_10.4040199_odense_google_maps_image,,55.418487699999986_10.4040199_odense_google_satellite_image,,55.418487699999986_10.4040199_odense_google_street_view_image,, +1137953620,2,odense,55.40786567141743,10.344627751900923,,55.40786567141743_10.344627751900923_odense_google_maps_image,,55.40786567141743_10.344627751900923_odense_google_satellite_image,,55.40786567141743_10.344627751900923_odense_google_street_view_image,, +97539705,2,odense,55.39255510772686,10.435510802877149,,55.39255510772686_10.435510802877149_odense_google_maps_image,,55.39255510772686_10.435510802877149_odense_google_satellite_image,,55.39255510772686_10.435510802877149_odense_google_street_view_image,, +7256183482,3,odense,55.398826749793706,10.376789979881721,,55.398826749793706_10.376789979881721_odense_google_maps_image,,55.398826749793706_10.376789979881721_odense_google_satellite_image,,55.398826749793706_10.376789979881721_odense_google_street_view_image,, +490530277,3,odense,55.373417105215644,10.37048242238291,,55.373417105215644_10.37048242238291_odense_google_maps_image,,55.373417105215644_10.37048242238291_odense_google_satellite_image,,55.373417105215644_10.37048242238291_odense_google_street_view_image,, +577338005,3,odense,55.414007104178076,10.396447058275141,,55.414007104178076_10.396447058275141_odense_google_maps_image,,55.414007104178076_10.396447058275141_odense_google_satellite_image,,55.414007104178076_10.396447058275141_odense_google_street_view_image,, +4800870647,3,odense,55.37516343786433,10.39858060544466,,55.37516343786433_10.39858060544466_odense_google_maps_image,,55.37516343786433_10.39858060544466_odense_google_satellite_image,,55.37516343786433_10.39858060544466_odense_google_street_view_image,, +3402665047,3,odense,55.405712259315315,10.39367508177815,,55.405712259315315_10.39367508177815_odense_google_maps_image,,55.405712259315315_10.39367508177815_odense_google_satellite_image,,55.405712259315315_10.39367508177815_odense_google_street_view_image,, +2508288968,3,odense,55.3792279,10.396774799999998,,55.3792279_10.396774799999998_odense_google_maps_image,,55.3792279_10.396774799999998_odense_google_satellite_image,,55.3792279_10.396774799999998_odense_google_street_view_image,, +664002868,3,odense,55.36754559515405,10.372733387061288,,55.36754559515405_10.372733387061288_odense_google_maps_image,,55.36754559515405_10.372733387061288_odense_google_satellite_image,,55.36754559515405_10.372733387061288_odense_google_street_view_image,, +289331240,3,odense,55.37481758712163,10.395791147973268,,55.37481758712163_10.395791147973268_odense_google_maps_image,,55.37481758712163_10.395791147973268_odense_google_satellite_image,,55.37481758712163_10.395791147973268_odense_google_street_view_image,, +71147650,3,odense,55.37796887832027,10.404359797941561,,55.37796887832027_10.404359797941561_odense_google_maps_image,,55.37796887832027_10.404359797941561_odense_google_satellite_image,,55.37796887832027_10.404359797941561_odense_google_street_view_image,, +1357609272,3,odense,55.40956482526284,10.338716197119354,,55.40956482526284_10.338716197119354_odense_google_maps_image,,55.40956482526284_10.338716197119354_odense_google_satellite_image,,55.40956482526284_10.338716197119354_odense_google_street_view_image,, +141959434,4,odense,55.39636330542289,10.349145626895728,,55.39636330542289_10.349145626895728_odense_google_maps_image,,55.39636330542289_10.349145626895728_odense_google_satellite_image,,55.39636330542289_10.349145626895728_odense_google_street_view_image,, +133965327,4,odense,55.40660427171952,10.441997371137127,,55.40660427171952_10.441997371137127_odense_google_maps_image,,55.40660427171952_10.441997371137127_odense_google_satellite_image,,55.40660427171952_10.441997371137127_odense_google_street_view_image,, +144649200,4,odense,55.40458537249529,10.340731214767281,,55.40458537249529_10.340731214767281_odense_google_maps_image,,55.40458537249529_10.340731214767281_odense_google_satellite_image,,55.40458537249529_10.340731214767281_odense_google_street_view_image,, +7775571092,4,odense,55.37980759999999,10.39691,,55.37980759999999_10.39691_odense_google_maps_image,,55.37980759999999_10.39691_odense_google_satellite_image,,55.37980759999999_10.39691_odense_google_street_view_image,, +3402665079,4,odense,55.378325958557454,10.379682787648651,,55.378325958557454_10.379682787648651_odense_google_maps_image,,55.378325958557454_10.379682787648651_odense_google_satellite_image,,55.378325958557454_10.379682787648651_odense_google_street_view_image,, +1783413181,4,odense,55.39797260000001,10.387632199999999,,55.39797260000001_10.387632199999999_odense_google_maps_image,,55.39797260000001_10.387632199999999_odense_google_satellite_image,,55.39797260000001_10.387632199999999_odense_google_street_view_image,, +152978976,4,odense,55.3937052,10.3657946,,55.3937052_10.3657946_odense_google_maps_image,,55.3937052_10.3657946_odense_google_satellite_image,,55.3937052_10.3657946_odense_google_street_view_image,, +341660677,4,odense,55.39451591962425,10.348111039300287,,55.39451591962425_10.348111039300287_odense_google_maps_image,,55.39451591962425_10.348111039300287_odense_google_satellite_image,,55.39451591962425_10.348111039300287_odense_google_street_view_image,, +92414361,4,odense,55.39466502707325,10.376702309599974,,55.39466502707325_10.376702309599974_odense_google_maps_image,,55.39466502707325_10.376702309599974_odense_google_satellite_image,,55.39466502707325_10.376702309599974_odense_google_street_view_image,, +5334645502,4,odense,55.400597810181125,10.391263514199865,,55.400597810181125_10.391263514199865_odense_google_maps_image,,55.400597810181125_10.391263514199865_odense_google_satellite_image,,55.400597810181125_10.391263514199865_odense_google_street_view_image,, +219651198,5,odense,55.39318647951937,10.399409284886316,,55.39318647951937_10.399409284886316_odense_google_maps_image,,55.39318647951937_10.399409284886316_odense_google_satellite_image,,55.39318647951937_10.399409284886316_odense_google_street_view_image,, +340216483,5,odense,55.396768997021745,10.38924129739305,,55.396768997021745_10.38924129739305_odense_google_maps_image,,55.396768997021745_10.38924129739305_odense_google_satellite_image,,55.396768997021745_10.38924129739305_odense_google_street_view_image,, +663192816,5,odense,55.39655484407623,10.382942928365717,,55.39655484407623_10.382942928365717_odense_google_maps_image,,55.39655484407623_10.382942928365717_odense_google_satellite_image,,55.39655484407623_10.382942928365717_odense_google_street_view_image,, +3402665046,5,odense,55.39274204754997,10.397320827586658,,55.39274204754997_10.397320827586658_odense_google_maps_image,,55.39274204754997_10.397320827586658_odense_google_satellite_image,,55.39274204754997_10.397320827586658_odense_google_street_view_image,, +6708833722,5,odense,55.397415356711164,10.391980602838114,,55.397415356711164_10.391980602838114_odense_google_maps_image,,55.397415356711164_10.391980602838114_odense_google_satellite_image,,55.397415356711164_10.391980602838114_odense_google_street_view_image,, +311607276,5,odense,55.39910978457271,10.404734045213733,,55.39910978457271_10.404734045213733_odense_google_maps_image,,55.39910978457271_10.404734045213733_odense_google_satellite_image,,55.39910978457271_10.404734045213733_odense_google_street_view_image,, +339817137,5,odense,55.393446770474064,10.395706501034262,,55.393446770474064_10.395706501034262_odense_google_maps_image,,55.393446770474064_10.395706501034262_odense_google_satellite_image,,55.393446770474064_10.395706501034262_odense_google_street_view_image,, +4516653659,5,odense,55.390739942959605,10.387965348677184,,55.390739942959605_10.387965348677184_odense_google_maps_image,,55.390739942959605_10.387965348677184_odense_google_satellite_image,,55.390739942959605_10.387965348677184_odense_google_street_view_image,, +779097661,5,odense,55.39405271165437,10.37678395876849,,55.39405271165437_10.37678395876849_odense_google_maps_image,,55.39405271165437_10.37678395876849_odense_google_satellite_image,,55.39405271165437_10.37678395876849_odense_google_street_view_image,, +117632444,5,odense,55.39217573760271,10.407376244769512,,55.39217573760271_10.407376244769512_odense_google_maps_image,,55.39217573760271_10.407376244769512_odense_google_satellite_image,,55.39217573760271_10.407376244769512_odense_google_street_view_image,, +2747734898,1,olomouc,49.604812171506396,17.240407827541382,,49.604812171506396_17.240407827541382_olomouc_google_maps_image,,49.604812171506396_17.240407827541382_olomouc_google_satellite_image,,49.604812171506396_17.240407827541382_olomouc_google_street_view_image,, +35897981,1,olomouc,49.57848124287224,17.242551859627667,,49.57848124287224_17.242551859627667_olomouc_google_maps_image,,49.57848124287224_17.242551859627667_olomouc_google_satellite_image,,49.57848124287224_17.242551859627667_olomouc_google_street_view_image,, +35898108,1,olomouc,49.57583739752839,17.247996707801693,,49.57583739752839_17.247996707801693_olomouc_google_maps_image,,49.57583739752839_17.247996707801693_olomouc_google_satellite_image,,49.57583739752839_17.247996707801693_olomouc_google_street_view_image,, +5975052178,1,olomouc,49.5745695556657,17.24950289035961,,49.5745695556657_17.24950289035961_olomouc_google_maps_image,,49.5745695556657_17.24950289035961_olomouc_google_satellite_image,,49.5745695556657_17.24950289035961_olomouc_google_street_view_image,, +899808007,1,olomouc,49.60232082212211,17.243655172780194,,49.60232082212211_17.243655172780194_olomouc_google_maps_image,,49.60232082212211_17.243655172780194_olomouc_google_satellite_image,,49.60232082212211_17.243655172780194_olomouc_google_street_view_image,, +5975062744,1,olomouc,49.57450046829268,17.249439073786878,,49.57450046829268_17.249439073786878_olomouc_google_maps_image,,49.57450046829268_17.249439073786878_olomouc_google_satellite_image,,49.57450046829268_17.249439073786878_olomouc_google_street_view_image,, +5329662824,1,olomouc,49.59222078355007,17.250328994335725,,49.59222078355007_17.250328994335725_olomouc_google_maps_image,,49.59222078355007_17.250328994335725_olomouc_google_satellite_image,,49.59222078355007_17.250328994335725_olomouc_google_street_view_image,, +5329663121,1,olomouc,49.5925491342712,17.250633672617568,,49.5925491342712_17.250633672617568_olomouc_google_maps_image,,49.5925491342712_17.250633672617568_olomouc_google_satellite_image,,49.5925491342712_17.250633672617568_olomouc_google_street_view_image,, +5975022069,1,olomouc,49.57466727532713,17.249411640682613,,49.57466727532713_17.249411640682613_olomouc_google_maps_image,,49.57466727532713_17.249411640682613_olomouc_google_satellite_image,,49.57466727532713_17.249411640682613_olomouc_google_street_view_image,, +670812040,1,olomouc,49.59291026294765,17.249156370959074,,49.59291026294765_17.249156370959074_olomouc_google_maps_image,,49.59291026294765_17.249156370959074_olomouc_google_satellite_image,,49.59291026294765_17.249156370959074_olomouc_google_street_view_image,, +437712834,2,olomouc,49.58893748049946,17.254124162177845,,49.58893748049946_17.254124162177845_olomouc_google_maps_image,,49.58893748049946_17.254124162177845_olomouc_google_satellite_image,,49.58893748049946_17.254124162177845_olomouc_google_street_view_image,, +1102132022,2,olomouc,49.589722728948054,17.254625045477532,,49.589722728948054_17.254625045477532_olomouc_google_maps_image,,49.589722728948054_17.254625045477532_olomouc_google_satellite_image,,49.589722728948054_17.254625045477532_olomouc_google_street_view_image,, +16914580,2,olomouc,49.58918031631491,17.25577818636671,,49.58918031631491_17.25577818636671_olomouc_google_maps_image,,49.58918031631491_17.25577818636671_olomouc_google_satellite_image,,49.58918031631491_17.25577818636671_olomouc_google_street_view_image,, +58530469,2,olomouc,49.6032266,17.2782117,,49.6032266_17.2782117_olomouc_google_maps_image,,49.6032266_17.2782117_olomouc_google_satellite_image,,49.6032266_17.2782117_olomouc_google_street_view_image,, +57858060,2,olomouc,49.58937216836056,17.254908394340816,,49.58937216836056_17.254908394340816_olomouc_google_maps_image,,49.58937216836056_17.254908394340816_olomouc_google_satellite_image,,49.58937216836056_17.254908394340816_olomouc_google_street_view_image,, +898627364,2,olomouc,49.5770818,17.2557422,,49.5770818_17.2557422_olomouc_google_maps_image,,49.5770818_17.2557422_olomouc_google_satellite_image,,49.5770818_17.2557422_olomouc_google_street_view_image,, +4744618108,2,olomouc,49.57673122722261,17.25425767387718,,49.57673122722261_17.25425767387718_olomouc_google_maps_image,,49.57673122722261_17.25425767387718_olomouc_google_satellite_image,,49.57673122722261_17.25425767387718_olomouc_google_street_view_image,, +3994191985,2,olomouc,49.601713438553666,17.278196798416225,,49.601713438553666_17.278196798416225_olomouc_google_maps_image,,49.601713438553666_17.278196798416225_olomouc_google_satellite_image,,49.601713438553666_17.278196798416225_olomouc_google_street_view_image,, +899821291,2,olomouc,49.59423247400176,17.250672049735563,,49.59423247400176_17.250672049735563_olomouc_google_maps_image,,49.59423247400176_17.250672049735563_olomouc_google_satellite_image,,49.59423247400176_17.250672049735563_olomouc_google_street_view_image,, +898627336,2,olomouc,49.5767211944337,17.25674029708548,,49.5767211944337_17.25674029708548_olomouc_google_maps_image,,49.5767211944337_17.25674029708548_olomouc_google_satellite_image,,49.5767211944337_17.25674029708548_olomouc_google_street_view_image,, +5124119942,3,olomouc,49.59152874341055,17.253168307870084,,49.59152874341055_17.253168307870084_olomouc_google_maps_image,,49.59152874341055_17.253168307870084_olomouc_google_satellite_image,,49.59152874341055_17.253168307870084_olomouc_google_street_view_image,, +2213447371,3,olomouc,49.59550163539226,17.26679502622463,,49.59550163539226_17.26679502622463_olomouc_google_maps_image,,49.59550163539226_17.26679502622463_olomouc_google_satellite_image,,49.59550163539226_17.26679502622463_olomouc_google_street_view_image,, +685779307,3,olomouc,49.59734327828507,17.2459812445235,,49.59734327828507_17.2459812445235_olomouc_google_maps_image,,49.59734327828507_17.2459812445235_olomouc_google_satellite_image,,49.59734327828507_17.2459812445235_olomouc_google_street_view_image,, +937891405,3,olomouc,49.5950652,17.2499469,,49.5950652_17.2499469_olomouc_google_maps_image,,49.5950652_17.2499469_olomouc_google_satellite_image,,49.5950652_17.2499469_olomouc_google_street_view_image,, +1133601794,3,olomouc,49.5950652,17.2499469,,49.5950652_17.2499469_olomouc_google_maps_image,,49.5950652_17.2499469_olomouc_google_satellite_image,,49.5950652_17.2499469_olomouc_google_street_view_image,, +2205115791,3,olomouc,49.59488288493668,17.26902430833058,,49.59488288493668_17.26902430833058_olomouc_google_maps_image,,49.59488288493668_17.26902430833058_olomouc_google_satellite_image,,49.59488288493668_17.26902430833058_olomouc_google_street_view_image,, +3618080553,3,olomouc,49.590364400000006,17.2702625,,49.590364400000006_17.2702625_olomouc_google_maps_image,,49.590364400000006_17.2702625_olomouc_google_satellite_image,,49.590364400000006_17.2702625_olomouc_google_street_view_image,, +4032937693,3,olomouc,49.58623959999999,17.2578531,,49.58623959999999_17.2578531_olomouc_google_maps_image,,49.58623959999999_17.2578531_olomouc_google_satellite_image,,49.58623959999999_17.2578531_olomouc_google_street_view_image,, +5318046191,3,olomouc,49.58718568820402,17.258488438630604,,49.58718568820402_17.258488438630604_olomouc_google_maps_image,,49.58718568820402_17.258488438630604_olomouc_google_satellite_image,,49.58718568820402_17.258488438630604_olomouc_google_street_view_image,, +5957431389,3,olomouc,49.58194865076289,17.23693947554527,,49.58194865076289_17.23693947554527_olomouc_google_maps_image,,49.58194865076289_17.23693947554527_olomouc_google_satellite_image,,49.58194865076289_17.23693947554527_olomouc_google_street_view_image,, +5329662833,4,olomouc,49.59260223866954,17.252387610096147,,49.59260223866954_17.252387610096147_olomouc_google_maps_image,,49.59260223866954_17.252387610096147_olomouc_google_satellite_image,,49.59260223866954_17.252387610096147_olomouc_google_street_view_image,, +5329662834,4,olomouc,49.59210778146773,17.252185846085666,,49.59210778146773_17.252185846085666_olomouc_google_maps_image,,49.59210778146773_17.252185846085666_olomouc_google_satellite_image,,49.59210778146773_17.252185846085666_olomouc_google_street_view_image,, +5329663724,4,olomouc,49.59326302780411,17.25184522573286,,49.59326302780411_17.25184522573286_olomouc_google_maps_image,,49.59326302780411_17.25184522573286_olomouc_google_satellite_image,,49.59326302780411_17.25184522573286_olomouc_google_street_view_image,, +900953095,4,olomouc,49.59928103376165,17.27266567021335,,49.59928103376165_17.27266567021335_olomouc_google_maps_image,,49.59928103376165_17.27266567021335_olomouc_google_satellite_image,,49.59928103376165_17.27266567021335_olomouc_google_street_view_image,, +3105589733,4,olomouc,49.58684579384117,17.238899787926535,,49.58684579384117_17.238899787926535_olomouc_google_maps_image,,49.58684579384117_17.238899787926535_olomouc_google_satellite_image,,49.58684579384117_17.238899787926535_olomouc_google_street_view_image,, +2205115971,4,olomouc,49.5939981736539,17.272274522436376,,49.5939981736539_17.272274522436376_olomouc_google_maps_image,,49.5939981736539_17.272274522436376_olomouc_google_satellite_image,,49.5939981736539_17.272274522436376_olomouc_google_street_view_image,, +2260266180,4,olomouc,49.59109453317078,17.27161874374886,,49.59109453317078_17.27161874374886_olomouc_google_maps_image,,49.59109453317078_17.27161874374886_olomouc_google_satellite_image,,49.59109453317078_17.27161874374886_olomouc_google_street_view_image,, +53034215,4,olomouc,49.59879279999999,17.2732146,,49.59879279999999_17.2732146_olomouc_google_maps_image,,49.59879279999999_17.2732146_olomouc_google_satellite_image,,49.59879279999999_17.2732146_olomouc_google_street_view_image,, +5329662829,4,olomouc,49.59278907503999,17.252117820538466,,49.59278907503999_17.252117820538466_olomouc_google_maps_image,,49.59278907503999_17.252117820538466_olomouc_google_satellite_image,,49.59278907503999_17.252117820538466_olomouc_google_street_view_image,, +3623128228,4,olomouc,49.58772997053009,17.270463406769185,,49.58772997053009_17.270463406769185_olomouc_google_maps_image,,49.58772997053009_17.270463406769185_olomouc_google_satellite_image,,49.58772997053009_17.270463406769185_olomouc_google_street_view_image,, +712691848,5,olomouc,49.58804865340112,17.27195182054297,,49.58804865340112_17.27195182054297_olomouc_google_maps_image,,49.58804865340112_17.27195182054297_olomouc_google_satellite_image,,49.58804865340112_17.27195182054297_olomouc_google_street_view_image,, +1711820823,5,olomouc,49.59632127249841,17.248452273013537,,49.59632127249841_17.248452273013537_olomouc_google_maps_image,,49.59632127249841_17.248452273013537_olomouc_google_satellite_image,,49.59632127249841_17.248452273013537_olomouc_google_street_view_image,, +58280569,5,olomouc,49.59114542391838,17.235124343510982,,49.59114542391838_17.235124343510982_olomouc_google_maps_image,,49.59114542391838_17.235124343510982_olomouc_google_satellite_image,,49.59114542391838_17.235124343510982_olomouc_google_street_view_image,, +2213447427,5,olomouc,49.59311039820254,17.275046339110556,,49.59311039820254_17.275046339110556_olomouc_google_maps_image,,49.59311039820254_17.275046339110556_olomouc_google_satellite_image,,49.59311039820254_17.275046339110556_olomouc_google_street_view_image,, +2213447430,5,olomouc,49.59327081755778,17.274851643527388,,49.59327081755778_17.274851643527388_olomouc_google_maps_image,,49.59327081755778_17.274851643527388_olomouc_google_satellite_image,,49.59327081755778_17.274851643527388_olomouc_google_street_view_image,, +1574134061,5,olomouc,49.59541331427761,17.249187019212034,,49.59541331427761_17.249187019212034_olomouc_google_maps_image,,49.59541331427761_17.249187019212034_olomouc_google_satellite_image,,49.59541331427761_17.249187019212034_olomouc_google_street_view_image,, +2260266181,5,olomouc,49.59236819822377,17.27805318667824,,49.59236819822377_17.27805318667824_olomouc_google_maps_image,,49.59236819822377_17.27805318667824_olomouc_google_satellite_image,,49.59236819822377_17.27805318667824_olomouc_google_street_view_image,, +2688541541,5,olomouc,49.59283688161055,17.277450812419456,,49.59283688161055_17.277450812419456_olomouc_google_maps_image,,49.59283688161055_17.277450812419456_olomouc_google_satellite_image,,49.59283688161055_17.277450812419456_olomouc_google_street_view_image,, +58280836,5,olomouc,49.5909535381399,17.23393396991465,,49.5909535381399_17.23393396991465_olomouc_google_maps_image,,49.5909535381399_17.23393396991465_olomouc_google_satellite_image,,49.5909535381399_17.23393396991465_olomouc_google_street_view_image,, +2260266177,5,olomouc,49.59283823419789,17.277450108854687,,49.59283823419789_17.277450108854687_olomouc_google_maps_image,,49.59283823419789_17.277450108854687_olomouc_google_satellite_image,,49.59283823419789_17.277450108854687_olomouc_google_street_view_image,, +329033172,1,sao_paulo,-23.541697900000006,-46.62917680000001,,-23.541697900000006_-46.62917680000001_sao_paulo_google_maps_image,,-23.541697900000006_-46.62917680000001_sao_paulo_google_satellite_image,,-23.541697900000006_-46.62917680000001_sao_paulo_google_street_view_image,, +-4602922,1,sao_paulo,-23.54177592356298,-46.62918725011454,,-23.54177592356298_-46.62918725011454_sao_paulo_google_maps_image,,-23.54177592356298_-46.62918725011454_sao_paulo_google_satellite_image,,-23.54177592356298_-46.62918725011454_sao_paulo_google_street_view_image,, +-4602968,1,sao_paulo,-23.541263431540635,-46.62919094379415,,-23.541263431540635_-46.62919094379415_sao_paulo_google_maps_image,,-23.541263431540635_-46.62919094379415_sao_paulo_google_satellite_image,,-23.541263431540635_-46.62919094379415_sao_paulo_google_street_view_image,, +329033179,1,sao_paulo,-23.541263241218296,-46.62935885991646,,-23.541263241218296_-46.62935885991646_sao_paulo_google_maps_image,,-23.541263241218296_-46.62935885991646_sao_paulo_google_satellite_image,,-23.541263241218296_-46.62935885991646_sao_paulo_google_street_view_image,, +-4602885,1,sao_paulo,-23.541401725530154,-46.62921577989605,,-23.541401725530154_-46.62921577989605_sao_paulo_google_maps_image,,-23.541401725530154_-46.62921577989605_sao_paulo_google_satellite_image,,-23.541401725530154_-46.62921577989605_sao_paulo_google_street_view_image,, +690742306,1,sao_paulo,-23.57572793761542,-46.501841843859125,,-23.57572793761542_-46.501841843859125_sao_paulo_google_maps_image,,-23.57572793761542_-46.501841843859125_sao_paulo_google_satellite_image,,-23.57572793761542_-46.501841843859125_sao_paulo_google_street_view_image,, +-4602916,1,sao_paulo,-23.54200894840106,-46.62989859927149,,-23.54200894840106_-46.62989859927149_sao_paulo_google_maps_image,,-23.54200894840106_-46.62989859927149_sao_paulo_google_satellite_image,,-23.54200894840106_-46.62989859927149_sao_paulo_google_street_view_image,, +-4602892,1,sao_paulo,-23.541387718949974,-46.629698577919335,,-23.541387718949974_-46.629698577919335_sao_paulo_google_maps_image,,-23.541387718949974_-46.629698577919335_sao_paulo_google_satellite_image,,-23.541387718949974_-46.629698577919335_sao_paulo_google_street_view_image,, +-4603050,1,sao_paulo,-23.54146898983592,-46.629338852141224,,-23.54146898983592_-46.629338852141224_sao_paulo_google_maps_image,,-23.54146898983592_-46.629338852141224_sao_paulo_google_satellite_image,,-23.54146898983592_-46.629338852141224_sao_paulo_google_street_view_image,, +-4603065,1,sao_paulo,-23.541875969369872,-46.62981831820935,,-23.541875969369872_-46.62981831820935_sao_paulo_google_maps_image,,-23.541875969369872_-46.62981831820935_sao_paulo_google_satellite_image,,-23.541875969369872_-46.62981831820935_sao_paulo_google_street_view_image,, +6561340944,2,sao_paulo,-23.550898910168215,-46.622177411892835,,-23.550898910168215_-46.622177411892835_sao_paulo_google_maps_image,,-23.550898910168215_-46.622177411892835_sao_paulo_google_satellite_image,,-23.550898910168215_-46.622177411892835_sao_paulo_google_street_view_image,, +6449378140,2,sao_paulo,-23.573809399630605,-46.55747832528324,,-23.573809399630605_-46.55747832528324_sao_paulo_google_maps_image,,-23.573809399630605_-46.55747832528324_sao_paulo_google_satellite_image,,-23.573809399630605_-46.55747832528324_sao_paulo_google_street_view_image,, +37498469,2,sao_paulo,-23.5624739,-46.5018372,,-23.5624739_-46.5018372_sao_paulo_google_maps_image,,-23.5624739_-46.5018372_sao_paulo_google_satellite_image,,-23.5624739_-46.5018372_sao_paulo_google_street_view_image,, +4572425831,2,sao_paulo,-23.569414416518953,-46.566270195061705,,-23.569414416518953_-46.566270195061705_sao_paulo_google_maps_image,,-23.569414416518953_-46.566270195061705_sao_paulo_google_satellite_image,,-23.569414416518953_-46.566270195061705_sao_paulo_google_street_view_image,, +5462421680,2,sao_paulo,-23.474372547965906,-46.589928135370805,,-23.474372547965906_-46.589928135370805_sao_paulo_google_maps_image,,-23.474372547965906_-46.589928135370805_sao_paulo_google_satellite_image,,-23.474372547965906_-46.589928135370805_sao_paulo_google_street_view_image,, +4371222245,2,sao_paulo,-23.611125245665434,-46.70482719615664,,-23.611125245665434_-46.70482719615664_sao_paulo_google_maps_image,,-23.611125245665434_-46.70482719615664_sao_paulo_google_satellite_image,,-23.611125245665434_-46.70482719615664_sao_paulo_google_street_view_image,, +914049517,2,sao_paulo,-23.55495386829887,-46.685737772839346,,-23.55495386829887_-46.685737772839346_sao_paulo_google_maps_image,,-23.55495386829887_-46.685737772839346_sao_paulo_google_satellite_image,,-23.55495386829887_-46.685737772839346_sao_paulo_google_street_view_image,, +3679556542,2,sao_paulo,-23.44655295808692,-46.690111283829516,,-23.44655295808692_-46.690111283829516_sao_paulo_google_maps_image,,-23.44655295808692_-46.690111283829516_sao_paulo_google_satellite_image,,-23.44655295808692_-46.690111283829516_sao_paulo_google_street_view_image,, +341043259,2,sao_paulo,-23.55438666878408,-46.49292047048889,,-23.55438666878408_-46.49292047048889_sao_paulo_google_maps_image,,-23.55438666878408_-46.49292047048889_sao_paulo_google_satellite_image,,-23.55438666878408_-46.49292047048889_sao_paulo_google_street_view_image,, +2299046831,2,sao_paulo,-23.599100857170892,-46.68336319123428,,-23.599100857170892_-46.68336319123428_sao_paulo_google_maps_image,,-23.599100857170892_-46.68336319123428_sao_paulo_google_satellite_image,,-23.599100857170892_-46.68336319123428_sao_paulo_google_street_view_image,, +4527458049,3,sao_paulo,-23.577414499999996,-46.7311945,,-23.577414499999996_-46.7311945_sao_paulo_google_maps_image,,-23.577414499999996_-46.7311945_sao_paulo_google_satellite_image,,-23.577414499999996_-46.7311945_sao_paulo_google_street_view_image,, +4103932589,3,sao_paulo,-23.68545932233089,-46.68070510295093,,-23.68545932233089_-46.68070510295093_sao_paulo_google_maps_image,,-23.68545932233089_-46.68070510295093_sao_paulo_google_satellite_image,,-23.68545932233089_-46.68070510295093_sao_paulo_google_street_view_image,, +2677539172,3,sao_paulo,-23.5056546332568,-46.594358472104076,,-23.5056546332568_-46.594358472104076_sao_paulo_google_maps_image,,-23.5056546332568_-46.594358472104076_sao_paulo_google_satellite_image,,-23.5056546332568_-46.594358472104076_sao_paulo_google_street_view_image,, +3969229726,3,sao_paulo,-23.539320900046107,-46.59644127660393,,-23.539320900046107_-46.59644127660393_sao_paulo_google_maps_image,,-23.539320900046107_-46.59644127660393_sao_paulo_google_satellite_image,,-23.539320900046107_-46.59644127660393_sao_paulo_google_street_view_image,, +2344707800,3,sao_paulo,-23.52609009985865,-46.52701091189782,,-23.52609009985865_-46.52701091189782_sao_paulo_google_maps_image,,-23.52609009985865_-46.52701091189782_sao_paulo_google_satellite_image,,-23.52609009985865_-46.52701091189782_sao_paulo_google_street_view_image,, +5294381070,3,sao_paulo,-23.583613828914224,-46.627600003297104,,-23.583613828914224_-46.627600003297104_sao_paulo_google_maps_image,,-23.583613828914224_-46.627600003297104_sao_paulo_google_satellite_image,,-23.583613828914224_-46.627600003297104_sao_paulo_google_street_view_image,, +681392468,3,sao_paulo,-23.574096945327483,-46.51326008140862,,-23.574096945327483_-46.51326008140862_sao_paulo_google_maps_image,,-23.574096945327483_-46.51326008140862_sao_paulo_google_satellite_image,,-23.574096945327483_-46.51326008140862_sao_paulo_google_street_view_image,, +619217884,3,sao_paulo,-23.60207530443384,-46.636627422869175,,-23.60207530443384_-46.636627422869175_sao_paulo_google_maps_image,,-23.60207530443384_-46.636627422869175_sao_paulo_google_satellite_image,,-23.60207530443384_-46.636627422869175_sao_paulo_google_street_view_image,, +4145597085,3,sao_paulo,-23.48528574773012,-46.641177456458216,,-23.48528574773012_-46.641177456458216_sao_paulo_google_maps_image,,-23.48528574773012_-46.641177456458216_sao_paulo_google_satellite_image,,-23.48528574773012_-46.641177456458216_sao_paulo_google_street_view_image,, +277075163,3,sao_paulo,-23.60222632102584,-46.63991047872621,,-23.60222632102584_-46.63991047872621_sao_paulo_google_maps_image,,-23.60222632102584_-46.63991047872621_sao_paulo_google_satellite_image,,-23.60222632102584_-46.63991047872621_sao_paulo_google_street_view_image,, +431438184,4,sao_paulo,-23.572964943936835,-46.636357214748166,,-23.572964943936835_-46.636357214748166_sao_paulo_google_maps_image,,-23.572964943936835_-46.636357214748166_sao_paulo_google_satellite_image,,-23.572964943936835_-46.636357214748166_sao_paulo_google_street_view_image,, +2421036956,4,sao_paulo,-23.605013777188894,-46.65894603260714,,-23.605013777188894_-46.65894603260714_sao_paulo_google_maps_image,,-23.605013777188894_-46.65894603260714_sao_paulo_google_satellite_image,,-23.605013777188894_-46.65894603260714_sao_paulo_google_street_view_image,, +2873424014,4,sao_paulo,-23.450483141013507,-46.572483528344215,,-23.450483141013507_-46.572483528344215_sao_paulo_google_maps_image,,-23.450483141013507_-46.572483528344215_sao_paulo_google_satellite_image,,-23.450483141013507_-46.572483528344215_sao_paulo_google_street_view_image,, +5880426362,4,sao_paulo,-23.58310095453419,-46.409459429350875,,-23.58310095453419_-46.409459429350875_sao_paulo_google_maps_image,,-23.58310095453419_-46.409459429350875_sao_paulo_google_satellite_image,,-23.58310095453419_-46.409459429350875_sao_paulo_google_street_view_image,, +2037560043,4,sao_paulo,-23.632230234847068,-46.60470295646081,,-23.632230234847068_-46.60470295646081_sao_paulo_google_maps_image,,-23.632230234847068_-46.60470295646081_sao_paulo_google_satellite_image,,-23.632230234847068_-46.60470295646081_sao_paulo_google_street_view_image,, +4715781594,4,sao_paulo,-23.696892446160973,-46.779430842643656,,-23.696892446160973_-46.779430842643656_sao_paulo_google_maps_image,,-23.696892446160973_-46.779430842643656_sao_paulo_google_satellite_image,,-23.696892446160973_-46.779430842643656_sao_paulo_google_street_view_image,, +4514018990,4,sao_paulo,-23.700540101159486,-46.781567273963425,,-23.700540101159486_-46.781567273963425_sao_paulo_google_maps_image,,-23.700540101159486_-46.781567273963425_sao_paulo_google_satellite_image,,-23.700540101159486_-46.781567273963425_sao_paulo_google_street_view_image,, +3588207435,4,sao_paulo,-23.47502706313275,-46.57015886919148,,-23.47502706313275_-46.57015886919148_sao_paulo_google_maps_image,,-23.47502706313275_-46.57015886919148_sao_paulo_google_satellite_image,,-23.47502706313275_-46.57015886919148_sao_paulo_google_street_view_image,, +3928633744,4,sao_paulo,-23.487190083353465,-46.568585164594424,,-23.487190083353465_-46.568585164594424_sao_paulo_google_maps_image,,-23.487190083353465_-46.568585164594424_sao_paulo_google_satellite_image,,-23.487190083353465_-46.568585164594424_sao_paulo_google_street_view_image,, +5918601795,4,sao_paulo,-23.490527460999356,-46.58586395016518,,-23.490527460999356_-46.58586395016518_sao_paulo_google_maps_image,,-23.490527460999356_-46.58586395016518_sao_paulo_google_satellite_image,,-23.490527460999356_-46.58586395016518_sao_paulo_google_street_view_image,, +635319387,5,sao_paulo,-23.563935856567845,-46.68321969342855,,-23.563935856567845_-46.68321969342855_sao_paulo_google_maps_image,,-23.563935856567845_-46.68321969342855_sao_paulo_google_satellite_image,,-23.563935856567845_-46.68321969342855_sao_paulo_google_street_view_image,, +5272030990,5,sao_paulo,-23.684822710580775,-46.64767419219624,,-23.684822710580775_-46.64767419219624_sao_paulo_google_maps_image,,-23.684822710580775_-46.64767419219624_sao_paulo_google_satellite_image,,-23.684822710580775_-46.64767419219624_sao_paulo_google_street_view_image,, +4964023963,5,sao_paulo,-23.566741186660213,-46.649927663038,,-23.566741186660213_-46.649927663038_sao_paulo_google_maps_image,,-23.566741186660213_-46.649927663038_sao_paulo_google_satellite_image,,-23.566741186660213_-46.649927663038_sao_paulo_google_street_view_image,, +-3963497,5,sao_paulo,-23.47931670278812,-46.643891453137506,,-23.47931670278812_-46.643891453137506_sao_paulo_google_maps_image,,-23.47931670278812_-46.643891453137506_sao_paulo_google_satellite_image,,-23.47931670278812_-46.643891453137506_sao_paulo_google_street_view_image,, +6017776056,5,sao_paulo,-23.626488903990104,-46.63367355388614,,-23.626488903990104_-46.63367355388614_sao_paulo_google_maps_image,,-23.626488903990104_-46.63367355388614_sao_paulo_google_satellite_image,,-23.626488903990104_-46.63367355388614_sao_paulo_google_street_view_image,, +143331528,5,sao_paulo,-23.646366588657976,-46.75730525326663,,-23.646366588657976_-46.75730525326663_sao_paulo_google_maps_image,,-23.646366588657976_-46.75730525326663_sao_paulo_google_satellite_image,,-23.646366588657976_-46.75730525326663_sao_paulo_google_street_view_image,, +3919726882,5,sao_paulo,-23.47738617778817,-46.58216406628867,,-23.47738617778817_-46.58216406628867_sao_paulo_google_maps_image,,-23.47738617778817_-46.58216406628867_sao_paulo_google_satellite_image,,-23.47738617778817_-46.58216406628867_sao_paulo_google_street_view_image,, +2810275124,5,sao_paulo,-23.552828087058273,-46.64556244829638,,-23.552828087058273_-46.64556244829638_sao_paulo_google_maps_image,,-23.552828087058273_-46.64556244829638_sao_paulo_google_satellite_image,,-23.552828087058273_-46.64556244829638_sao_paulo_google_street_view_image,, +2269730180,5,sao_paulo,-23.5344953928889,-46.68638112679506,,-23.5344953928889_-46.68638112679506_sao_paulo_google_maps_image,,-23.5344953928889_-46.68638112679506_sao_paulo_google_satellite_image,,-23.5344953928889_-46.68638112679506_sao_paulo_google_street_view_image,, +3527356819,5,sao_paulo,-23.55308343146685,-46.654593334760705,,-23.55308343146685_-46.654593334760705_sao_paulo_google_maps_image,,-23.55308343146685_-46.654593334760705_sao_paulo_google_satellite_image,,-23.55308343146685_-46.654593334760705_sao_paulo_google_street_view_image,, +129591176,1,phoenix,33.49618387083415,-112.17273491252895,,33.49618387083415_-112.17273491252895_phoenix_google_maps_image,,33.49618387083415_-112.17273491252895_phoenix_google_satellite_image,,33.49618387083415_-112.17273491252895_phoenix_google_street_view_image,, +597445227,1,phoenix,33.58302517213424,-111.9790476188274,,33.58302517213424_-111.9790476188274_phoenix_google_maps_image,,33.58302517213424_-111.9790476188274_phoenix_google_satellite_image,,33.58302517213424_-111.9790476188274_phoenix_google_street_view_image,, +1015278486,1,phoenix,33.583522165345336,-111.9773303898694,,33.583522165345336_-111.9773303898694_phoenix_google_maps_image,,33.583522165345336_-111.9773303898694_phoenix_google_satellite_image,,33.583522165345336_-111.9773303898694_phoenix_google_street_view_image,, +2999125091,1,phoenix,33.49388319693427,-112.17068007936246,,33.49388319693427_-112.17068007936246_phoenix_google_maps_image,,33.49388319693427_-112.17068007936246_phoenix_google_satellite_image,,33.49388319693427_-112.17068007936246_phoenix_google_street_view_image,, +2120305890,1,phoenix,33.63865653464909,-112.12005632401943,,33.63865653464909_-112.12005632401943_phoenix_google_maps_image,,33.63865653464909_-112.12005632401943_phoenix_google_satellite_image,,33.63865653464909_-112.12005632401943_phoenix_google_street_view_image,, +3081249899,1,phoenix,33.436326300000005,-112.0109522,,33.436326300000005_-112.0109522_phoenix_google_maps_image,,33.436326300000005_-112.0109522_phoenix_google_satellite_image,,33.436326300000005_-112.0109522_phoenix_google_street_view_image,, +706931745,1,phoenix,33.59950324633909,-111.97888760482499,,33.59950324633909_-111.97888760482499_phoenix_google_maps_image,,33.59950324633909_-111.97888760482499_phoenix_google_satellite_image,,33.59950324633909_-111.97888760482499_phoenix_google_street_view_image,, +485723486,1,phoenix,33.52134906976979,-112.09270988613655,,33.52134906976979_-112.09270988613655_phoenix_google_maps_image,,33.52134906976979_-112.09270988613655_phoenix_google_satellite_image,,33.52134906976979_-112.09270988613655_phoenix_google_street_view_image,, +707448102,1,phoenix,33.58529786040639,-111.97906788281102,,33.58529786040639_-111.97906788281102_phoenix_google_maps_image,,33.58529786040639_-111.97906788281102_phoenix_google_satellite_image,,33.58529786040639_-111.97906788281102_phoenix_google_street_view_image,, +1015432761,1,phoenix,33.60265448510628,-111.9811437887164,,33.60265448510628_-111.9811437887164_phoenix_google_maps_image,,33.60265448510628_-111.9811437887164_phoenix_google_satellite_image,,33.60265448510628_-111.9811437887164_phoenix_google_street_view_image,, +4015696484,2,phoenix,33.510065186384765,-112.07227504420547,,33.510065186384765_-112.07227504420547_phoenix_google_maps_image,,33.510065186384765_-112.07227504420547_phoenix_google_satellite_image,,33.510065186384765_-112.07227504420547_phoenix_google_street_view_image,, +1656471455,2,phoenix,33.49350727505362,-112.20169176073925,,33.49350727505362_-112.20169176073925_phoenix_google_maps_image,,33.49350727505362_-112.20169176073925_phoenix_google_satellite_image,,33.49350727505362_-112.20169176073925_phoenix_google_street_view_image,, +2325086801,2,phoenix,33.34819558920091,-111.98173154192371,,33.34819558920091_-111.98173154192371_phoenix_google_maps_image,,33.34819558920091_-111.98173154192371_phoenix_google_satellite_image,,33.34819558920091_-111.98173154192371_phoenix_google_street_view_image,, +4989597947,2,phoenix,33.62431638368412,-111.94461094575492,,33.62431638368412_-111.94461094575492_phoenix_google_maps_image,,33.62431638368412_-111.94461094575492_phoenix_google_satellite_image,,33.62431638368412_-111.94461094575492_phoenix_google_street_view_image,, +6516441383,2,phoenix,33.62482911847935,-111.97896775669815,,33.62482911847935_-111.97896775669815_phoenix_google_maps_image,,33.62482911847935_-111.97896775669815_phoenix_google_satellite_image,,33.62482911847935_-111.97896775669815_phoenix_google_street_view_image,, +1680973812,2,phoenix,33.641448557620066,-112.01107896417196,,33.641448557620066_-112.01107896417196_phoenix_google_maps_image,,33.641448557620066_-112.01107896417196_phoenix_google_satellite_image,,33.641448557620066_-112.01107896417196_phoenix_google_street_view_image,, +2169665274,2,phoenix,33.3757888,-112.0291247,,33.3757888_-112.0291247_phoenix_google_maps_image,,33.3757888_-112.0291247_phoenix_google_satellite_image,,33.3757888_-112.0291247_phoenix_google_street_view_image,, +473852564,2,phoenix,33.30407134586127,-111.99479322265371,,33.30407134586127_-111.99479322265371_phoenix_google_maps_image,,33.30407134586127_-111.99479322265371_phoenix_google_satellite_image,,33.30407134586127_-111.99479322265371_phoenix_google_street_view_image,, +286664010,2,phoenix,33.496281399999994,-111.97934430000001,,33.496281399999994_-111.97934430000001_phoenix_google_maps_image,,33.496281399999994_-111.97934430000001_phoenix_google_satellite_image,,33.496281399999994_-111.97934430000001_phoenix_google_street_view_image,, +1798894170,2,phoenix,33.306554638387844,-112.05400486205016,,33.306554638387844_-112.05400486205016_phoenix_google_maps_image,,33.306554638387844_-112.05400486205016_phoenix_google_satellite_image,,33.306554638387844_-112.05400486205016_phoenix_google_street_view_image,, +5315598847,3,phoenix,33.65641296485599,-112.15035766601495,,33.65641296485599_-112.15035766601495_phoenix_google_maps_image,,33.65641296485599_-112.15035766601495_phoenix_google_satellite_image,,33.65641296485599_-112.15035766601495_phoenix_google_street_view_image,, +7259780428,3,phoenix,33.43810571619067,-112.07433678772438,,33.43810571619067_-112.07433678772438_phoenix_google_maps_image,,33.43810571619067_-112.07433678772438_phoenix_google_satellite_image,,33.43810571619067_-112.07433678772438_phoenix_google_street_view_image,, +4931775422,3,phoenix,33.7089963,-112.1129997,,33.7089963_-112.1129997_phoenix_google_maps_image,,33.7089963_-112.1129997_phoenix_google_satellite_image,,33.7089963_-112.1129997_phoenix_google_street_view_image,, +7152736885,3,phoenix,33.516618495033214,-112.08215139002274,,33.516618495033214_-112.08215139002274_phoenix_google_maps_image,,33.516618495033214_-112.08215139002274_phoenix_google_satellite_image,,33.516618495033214_-112.08215139002274_phoenix_google_street_view_image,, +6816511292,3,phoenix,33.5108981391705,-112.08550068470576,,33.5108981391705_-112.08550068470576_phoenix_google_maps_image,,33.5108981391705_-112.08550068470576_phoenix_google_satellite_image,,33.5108981391705_-112.08550068470576_phoenix_google_street_view_image,, +4382713606,3,phoenix,33.523983060110965,-112.04860692068318,,33.523983060110965_-112.04860692068318_phoenix_google_maps_image,,33.523983060110965_-112.04860692068318_phoenix_google_satellite_image,,33.523983060110965_-112.04860692068318_phoenix_google_street_view_image,, +65716522,3,phoenix,33.53980976781218,-112.06243620645012,,33.53980976781218_-112.06243620645012_phoenix_google_maps_image,,33.53980976781218_-112.06243620645012_phoenix_google_satellite_image,,33.53980976781218_-112.06243620645012_phoenix_google_street_view_image,, +3630195377,3,phoenix,33.48085773533956,-112.2538476020432,,33.48085773533956_-112.2538476020432_phoenix_google_maps_image,,33.48085773533956_-112.2538476020432_phoenix_google_satellite_image,,33.48085773533956_-112.2538476020432_phoenix_google_street_view_image,, +2181863598,3,phoenix,33.58349506750248,-112.01194727997495,,33.58349506750248_-112.01194727997495_phoenix_google_maps_image,,33.58349506750248_-112.01194727997495_phoenix_google_satellite_image,,33.58349506750248_-112.01194727997495_phoenix_google_street_view_image,, +5426636684,3,phoenix,33.321291680916836,-111.98240527011345,,33.321291680916836_-111.98240527011345_phoenix_google_maps_image,,33.321291680916836_-111.98240527011345_phoenix_google_satellite_image,,33.321291680916836_-111.98240527011345_phoenix_google_street_view_image,, +130341162,4,phoenix,33.47872268768254,-112.25384651354823,,33.47872268768254_-112.25384651354823_phoenix_google_maps_image,,33.47872268768254_-112.25384651354823_phoenix_google_satellite_image,,33.47872268768254_-112.25384651354823_phoenix_google_street_view_image,, +2315133795,4,phoenix,33.517647526416766,-112.0629210088304,,33.517647526416766_-112.0629210088304_phoenix_google_maps_image,,33.517647526416766_-112.0629210088304_phoenix_google_satellite_image,,33.517647526416766_-112.0629210088304_phoenix_google_street_view_image,, +4452509037,4,phoenix,33.48127892512827,-112.01423569449182,,33.48127892512827_-112.01423569449182_phoenix_google_maps_image,,33.48127892512827_-112.01423569449182_phoenix_google_satellite_image,,33.48127892512827_-112.01423569449182_phoenix_google_street_view_image,, +2458567936,4,phoenix,33.57110433135084,-112.08042839778024,,33.57110433135084_-112.08042839778024_phoenix_google_maps_image,,33.57110433135084_-112.08042839778024_phoenix_google_satellite_image,,33.57110433135084_-112.08042839778024_phoenix_google_street_view_image,, +250226344,4,phoenix,33.583713724947124,-112.13541837733315,,33.583713724947124_-112.13541837733315_phoenix_google_maps_image,,33.583713724947124_-112.13541837733315_phoenix_google_satellite_image,,33.583713724947124_-112.13541837733315_phoenix_google_street_view_image,, +5426615946,4,phoenix,33.4955582,-111.9892178,,33.4955582_-111.9892178_phoenix_google_maps_image,,33.4955582_-111.9892178_phoenix_google_satellite_image,,33.4955582_-111.9892178_phoenix_google_street_view_image,, +152448046,4,phoenix,33.527367465924705,-112.1325935340939,,33.527367465924705_-112.1325935340939_phoenix_google_maps_image,,33.527367465924705_-112.1325935340939_phoenix_google_satellite_image,,33.527367465924705_-112.1325935340939_phoenix_google_street_view_image,, +2810933508,4,phoenix,33.638252898576816,-112.15260335915141,,33.638252898576816_-112.15260335915141_phoenix_google_maps_image,,33.638252898576816_-112.15260335915141_phoenix_google_satellite_image,,33.638252898576816_-112.15260335915141_phoenix_google_street_view_image,, +480970526,4,phoenix,33.59843520036625,-112.15000849719037,,33.59843520036625_-112.15000849719037_phoenix_google_maps_image,,33.59843520036625_-112.15000849719037_phoenix_google_satellite_image,,33.59843520036625_-112.15000849719037_phoenix_google_street_view_image,, +2493829141,4,phoenix,33.57224995594046,-112.0609669088735,,33.57224995594046_-112.0609669088735_phoenix_google_maps_image,,33.57224995594046_-112.0609669088735_phoenix_google_satellite_image,,33.57224995594046_-112.0609669088735_phoenix_google_street_view_image,, +2324983396,5,phoenix,33.53758301748267,-112.13316094638326,,33.53758301748267_-112.13316094638326_phoenix_google_maps_image,,33.53758301748267_-112.13316094638326_phoenix_google_satellite_image,,33.53758301748267_-112.13316094638326_phoenix_google_street_view_image,, +6600083736,5,phoenix,33.49319330533305,-112.23917653996784,,33.49319330533305_-112.23917653996784_phoenix_google_maps_image,,33.49319330533305_-112.23917653996784_phoenix_google_satellite_image,,33.49319330533305_-112.23917653996784_phoenix_google_street_view_image,, +631702487,5,phoenix,33.65359410008661,-112.02973709999844,,33.65359410008661_-112.02973709999844_phoenix_google_maps_image,,33.65359410008661_-112.02973709999844_phoenix_google_satellite_image,,33.65359410008661_-112.02973709999844_phoenix_google_street_view_image,, +263101091,5,phoenix,33.64147779999999,-112.0788481,,33.64147779999999_-112.0788481_phoenix_google_maps_image,,33.64147779999999_-112.0788481_phoenix_google_satellite_image,,33.64147779999999_-112.0788481_phoenix_google_street_view_image,, +1140259217,5,phoenix,33.61051217188889,-112.014553667286,,33.61051217188889_-112.014553667286_phoenix_google_maps_image,,33.61051217188889_-112.014553667286_phoenix_google_satellite_image,,33.61051217188889_-112.014553667286_phoenix_google_street_view_image,, +3972840012,5,phoenix,33.46617382445832,-111.985535870184,,33.46617382445832_-111.985535870184_phoenix_google_maps_image,,33.46617382445832_-111.985535870184_phoenix_google_satellite_image,,33.46617382445832_-111.985535870184_phoenix_google_street_view_image,, +6254635472,5,phoenix,33.64143027188616,-112.0671296800922,,33.64143027188616_-112.0671296800922_phoenix_google_maps_image,,33.64143027188616_-112.0671296800922_phoenix_google_satellite_image,,33.64143027188616_-112.0671296800922_phoenix_google_street_view_image,, +1659598962,5,phoenix,33.48112370307971,-112.20205420648273,,33.48112370307971_-112.20205420648273_phoenix_google_maps_image,,33.48112370307971_-112.20205420648273_phoenix_google_satellite_image,,33.48112370307971_-112.20205420648273_phoenix_google_street_view_image,, +2482210418,5,phoenix,33.5396466577925,-112.13534016785471,,33.5396466577925_-112.13534016785471_phoenix_google_maps_image,,33.5396466577925_-112.13534016785471_phoenix_google_satellite_image,,33.5396466577925_-112.13534016785471_phoenix_google_street_view_image,, +3009696977,5,phoenix,33.53756646132701,-112.09831545941557,,33.53756646132701_-112.09831545941557_phoenix_google_maps_image,,33.53756646132701_-112.09831545941557_phoenix_google_satellite_image,,33.53756646132701_-112.09831545941557_phoenix_google_street_view_image,, +231287359,1,seattle,47.547915815786915,-122.31882441802148,,47.547915815786915_-122.31882441802148_seattle_google_maps_image,,47.547915815786915_-122.31882441802148_seattle_google_satellite_image,,47.547915815786915_-122.31882441802148_seattle_google_street_view_image,, +4377499029,1,seattle,47.79248851688081,-122.21455600463672,,47.79248851688081_-122.21455600463672_seattle_google_maps_image,,47.79248851688081_-122.21455600463672_seattle_google_satellite_image,,47.79248851688081_-122.21455600463672_seattle_google_street_view_image,, +144348145,1,seattle,47.164134512373124,-122.51783568100625,,47.164134512373124_-122.51783568100625_seattle_google_maps_image,,47.164134512373124_-122.51783568100625_seattle_google_satellite_image,,47.164134512373124_-122.51783568100625_seattle_google_street_view_image,, +4012419398,1,seattle,47.57032303806308,-122.34800339861893,,47.57032303806308_-122.34800339861893_seattle_google_maps_image,,47.57032303806308_-122.34800339861893_seattle_google_satellite_image,,47.57032303806308_-122.34800339861893_seattle_google_street_view_image,, +642975105,1,seattle,47.75475360000001,-122.16005430000001,,47.75475360000001_-122.16005430000001_seattle_google_maps_image,,47.75475360000001_-122.16005430000001_seattle_google_satellite_image,,47.75475360000001_-122.16005430000001_seattle_google_street_view_image,, +161888072,1,seattle,47.629753238116535,-122.15702540397726,,47.629753238116535_-122.15702540397726_seattle_google_maps_image,,47.629753238116535_-122.15702540397726_seattle_google_satellite_image,,47.629753238116535_-122.15702540397726_seattle_google_street_view_image,, +340336012,1,seattle,47.63079718083004,-122.14473379744996,,47.63079718083004_-122.14473379744996_seattle_google_maps_image,,47.63079718083004_-122.14473379744996_seattle_google_satellite_image,,47.63079718083004_-122.14473379744996_seattle_google_street_view_image,, +4703926637,1,seattle,47.61365401057268,-122.18449119267898,,47.61365401057268_-122.18449119267898_seattle_google_maps_image,,47.61365401057268_-122.18449119267898_seattle_google_satellite_image,,47.61365401057268_-122.18449119267898_seattle_google_street_view_image,, +221425097,1,seattle,47.54637027490851,-122.06039057931191,,47.54637027490851_-122.06039057931191_seattle_google_maps_image,,47.54637027490851_-122.06039057931191_seattle_google_satellite_image,,47.54637027490851_-122.06039057931191_seattle_google_street_view_image,, +379944235,1,seattle,47.57678765073876,-122.13815705001498,,47.57678765073876_-122.13815705001498_seattle_google_maps_image,,47.57678765073876_-122.13815705001498_seattle_google_satellite_image,,47.57678765073876_-122.13815705001498_seattle_google_street_view_image,, +2462428043,2,seattle,47.6309376345791,-122.37435224941656,,47.6309376345791_-122.37435224941656_seattle_google_maps_image,,47.6309376345791_-122.37435224941656_seattle_google_satellite_image,,47.6309376345791_-122.37435224941656_seattle_google_street_view_image,, +6208934685,2,seattle,47.18963700419304,-122.40870744944965,,47.18963700419304_-122.40870744944965_seattle_google_maps_image,,47.18963700419304_-122.40870744944965_seattle_google_satellite_image,,47.18963700419304_-122.40870744944965_seattle_google_street_view_image,, +56228516,2,seattle,47.616404484116984,-122.13172153119481,,47.616404484116984_-122.13172153119481_seattle_google_maps_image,,47.616404484116984_-122.13172153119481_seattle_google_satellite_image,,47.616404484116984_-122.13172153119481_seattle_google_street_view_image,, +40183590,2,seattle,47.31483906341251,-122.22624404649977,,47.31483906341251_-122.22624404649977_seattle_google_maps_image,,47.31483906341251_-122.22624404649977_seattle_google_satellite_image,,47.31483906341251_-122.22624404649977_seattle_google_street_view_image,, +5583694644,2,seattle,47.46695772817513,-122.34289478959678,,47.46695772817513_-122.34289478959678_seattle_google_maps_image,,47.46695772817513_-122.34289478959678_seattle_google_satellite_image,,47.46695772817513_-122.34289478959678_seattle_google_street_view_image,, +2102155082,2,seattle,47.82228997983158,-122.3163121111638,,47.82228997983158_-122.3163121111638_seattle_google_maps_image,,47.82228997983158_-122.3163121111638_seattle_google_satellite_image,,47.82228997983158_-122.3163121111638_seattle_google_street_view_image,, +51255014,2,seattle,47.25684667506376,-122.52026833603817,,47.25684667506376_-122.52026833603817_seattle_google_maps_image,,47.25684667506376_-122.52026833603817_seattle_google_satellite_image,,47.25684667506376_-122.52026833603817_seattle_google_street_view_image,, +184540212,2,seattle,47.60172032489827,-122.2856837894088,,47.60172032489827_-122.2856837894088_seattle_google_maps_image,,47.60172032489827_-122.2856837894088_seattle_google_satellite_image,,47.60172032489827_-122.2856837894088_seattle_google_street_view_image,, +589999070,2,seattle,47.2424129,-122.53677069999999,,47.2424129_-122.53677069999999_seattle_google_maps_image,,47.2424129_-122.53677069999999_seattle_google_satellite_image,,47.2424129_-122.53677069999999_seattle_google_street_view_image,, +160981529,2,seattle,47.563194130013954,-122.31306754987405,,47.563194130013954_-122.31306754987405_seattle_google_maps_image,,47.563194130013954_-122.31306754987405_seattle_google_satellite_image,,47.563194130013954_-122.31306754987405_seattle_google_street_view_image,, +1774098606,3,seattle,47.48782820130981,-122.14720693984452,,47.48782820130981_-122.14720693984452_seattle_google_maps_image,,47.48782820130981_-122.14720693984452_seattle_google_satellite_image,,47.48782820130981_-122.14720693984452_seattle_google_street_view_image,, +221145066,3,seattle,47.68977672823216,-122.29050735308064,,47.68977672823216_-122.29050735308064_seattle_google_maps_image,,47.68977672823216_-122.29050735308064_seattle_google_satellite_image,,47.68977672823216_-122.29050735308064_seattle_google_street_view_image,, +3329431642,3,seattle,47.71023201198618,-122.17063266280248,,47.71023201198618_-122.17063266280248_seattle_google_maps_image,,47.71023201198618_-122.17063266280248_seattle_google_satellite_image,,47.71023201198618_-122.17063266280248_seattle_google_street_view_image,, +4909107330,3,seattle,47.48760920291759,-122.14758185712988,,47.48760920291759_-122.14758185712988_seattle_google_maps_image,,47.48760920291759_-122.14758185712988_seattle_google_satellite_image,,47.48760920291759_-122.14758185712988_seattle_google_street_view_image,, +786129976,3,seattle,47.876999986661495,-122.18714917606742,,47.876999986661495_-122.18714917606742_seattle_google_maps_image,,47.876999986661495_-122.18714917606742_seattle_google_satellite_image,,47.876999986661495_-122.18714917606742_seattle_google_street_view_image,, +138541945,3,seattle,47.85678984166777,-122.21960023407709,,47.85678984166777_-122.21960023407709_seattle_google_maps_image,,47.85678984166777_-122.21960023407709_seattle_google_satellite_image,,47.85678984166777_-122.21960023407709_seattle_google_street_view_image,, +545895883,3,seattle,47.44180657997207,-122.33531180000021,,47.44180657997207_-122.33531180000021_seattle_google_maps_image,,47.44180657997207_-122.33531180000021_seattle_google_satellite_image,,47.44180657997207_-122.33531180000021_seattle_google_street_view_image,, +4348054289,3,seattle,47.98040689207639,-122.2130368747519,,47.98040689207639_-122.2130368747519_seattle_google_maps_image,,47.98040689207639_-122.2130368747519_seattle_google_satellite_image,,47.98040689207639_-122.2130368747519_seattle_google_street_view_image,, +5560877506,3,seattle,47.50455765856497,-122.16394956087532,,47.50455765856497_-122.16394956087532_seattle_google_maps_image,,47.50455765856497_-122.16394956087532_seattle_google_satellite_image,,47.50455765856497_-122.16394956087532_seattle_google_street_view_image,, +41831159,3,seattle,47.15646639999999,-122.43565019999998,,47.15646639999999_-122.43565019999998_seattle_google_maps_image,,47.15646639999999_-122.43565019999998_seattle_google_satellite_image,,47.15646639999999_-122.43565019999998_seattle_google_street_view_image,, +1076268999,4,seattle,47.67561882881142,-122.12790372439396,,47.67561882881142_-122.12790372439396_seattle_google_maps_image,,47.67561882881142_-122.12790372439396_seattle_google_satellite_image,,47.67561882881142_-122.12790372439396_seattle_google_street_view_image,, +2459612950,4,seattle,47.51818415194702,-122.3564892739769,,47.51818415194702_-122.3564892739769_seattle_google_maps_image,,47.51818415194702_-122.3564892739769_seattle_google_satellite_image,,47.51818415194702_-122.3564892739769_seattle_google_street_view_image,, +5283439759,4,seattle,47.819006234772566,-122.29447275632992,,47.819006234772566_-122.29447275632992_seattle_google_maps_image,,47.819006234772566_-122.29447275632992_seattle_google_satellite_image,,47.819006234772566_-122.29447275632992_seattle_google_street_view_image,, +144136765,4,seattle,47.13524249042996,-122.29451275313622,,47.13524249042996_-122.29451275313622_seattle_google_maps_image,,47.13524249042996_-122.29451275313622_seattle_google_satellite_image,,47.13524249042996_-122.29451275313622_seattle_google_street_view_image,, +5818837454,4,seattle,47.61206698033566,-122.19859121480994,,47.61206698033566_-122.19859121480994_seattle_google_maps_image,,47.61206698033566_-122.19859121480994_seattle_google_satellite_image,,47.61206698033566_-122.19859121480994_seattle_google_street_view_image,, +97526535,4,seattle,47.72150126199394,-122.29516974617317,,47.72150126199394_-122.29516974617317_seattle_google_maps_image,,47.72150126199394_-122.29516974617317_seattle_google_satellite_image,,47.72150126199394_-122.29516974617317_seattle_google_street_view_image,, +6466038789,4,seattle,47.612941507225344,-122.30091563169185,,47.612941507225344_-122.30091563169185_seattle_google_maps_image,,47.612941507225344_-122.30091563169185_seattle_google_satellite_image,,47.612941507225344_-122.30091563169185_seattle_google_street_view_image,, +136051469,4,seattle,47.579819576651246,-122.38603386382405,,47.579819576651246_-122.38603386382405_seattle_google_maps_image,,47.579819576651246_-122.38603386382405_seattle_google_satellite_image,,47.579819576651246_-122.38603386382405_seattle_google_street_view_image,, +457863565,4,seattle,47.619519152546985,-122.13124895753259,,47.619519152546985_-122.13124895753259_seattle_google_maps_image,,47.619519152546985_-122.13124895753259_seattle_google_satellite_image,,47.619519152546985_-122.13124895753259_seattle_google_street_view_image,, +2462453190,4,seattle,47.73337769999999,-122.31094139999999,,47.73337769999999_-122.31094139999999_seattle_google_maps_image,,47.73337769999999_-122.31094139999999_seattle_google_satellite_image,,47.73337769999999_-122.31094139999999_seattle_google_street_view_image,, +2323794471,5,seattle,47.66302817121764,-122.3134175655301,,47.66302817121764_-122.3134175655301_seattle_google_maps_image,,47.66302817121764_-122.3134175655301_seattle_google_satellite_image,,47.66302817121764_-122.3134175655301_seattle_google_street_view_image,, +1735895556,5,seattle,47.615800086117815,-122.31013897285999,,47.615800086117815_-122.31013897285999_seattle_google_maps_image,,47.615800086117815_-122.31013897285999_seattle_google_satellite_image,,47.615800086117815_-122.31013897285999_seattle_google_street_view_image,, +4458635049,5,seattle,47.60732200119781,-122.33543019969913,,47.60732200119781_-122.33543019969913_seattle_google_maps_image,,47.60732200119781_-122.33543019969913_seattle_google_satellite_image,,47.60732200119781_-122.33543019969913_seattle_google_street_view_image,, +2397401982,5,seattle,47.55999349697797,-122.38697566354044,,47.55999349697797_-122.38697566354044_seattle_google_maps_image,,47.55999349697797_-122.38697566354044_seattle_google_satellite_image,,47.55999349697797_-122.38697566354044_seattle_google_street_view_image,, +6781294438,5,seattle,47.61862658412955,-122.3374148077011,,47.61862658412955_-122.3374148077011_seattle_google_maps_image,,47.61862658412955_-122.3374148077011_seattle_google_satellite_image,,47.61862658412955_-122.3374148077011_seattle_google_street_view_image,, +2397497093,5,seattle,47.60894580871663,-122.34082817411597,,47.60894580871663_-122.34082817411597_seattle_google_maps_image,,47.60894580871663_-122.34082817411597_seattle_google_satellite_image,,47.60894580871663_-122.34082817411597_seattle_google_street_view_image,, +6781330674,5,seattle,47.610379278506244,-122.34009675832141,,47.610379278506244_-122.34009675832141_seattle_google_maps_image,,47.610379278506244_-122.34009675832141_seattle_google_satellite_image,,47.610379278506244_-122.34009675832141_seattle_google_street_view_image,, +2666623806,5,seattle,47.63450865215028,-122.35711235039064,,47.63450865215028_-122.35711235039064_seattle_google_maps_image,,47.63450865215028_-122.35711235039064_seattle_google_satellite_image,,47.63450865215028_-122.35711235039064_seattle_google_street_view_image,, +3379016191,5,seattle,47.61475952929407,-122.32790985266821,,47.61475952929407_-122.32790985266821_seattle_google_maps_image,,47.61475952929407_-122.32790985266821_seattle_google_satellite_image,,47.61475952929407_-122.32790985266821_seattle_google_street_view_image,, +206858876,5,seattle,47.608858796601815,-122.34069468343448,,47.608858796601815_-122.34069468343448_seattle_google_maps_image,,47.608858796601815_-122.34069468343448_seattle_google_satellite_image,,47.608858796601815_-122.34069468343448_seattle_google_street_view_image,, +3207004265,1,sydney,-33.93698786058448,150.8464217420261,,-33.93698786058448_150.8464217420261_sydney_google_maps_image,,-33.93698786058448_150.8464217420261_sydney_google_satellite_image,,-33.93698786058448_150.8464217420261_sydney_google_street_view_image,, +537535100,1,sydney,-33.71780402234493,150.9202597698209,,-33.71780402234493_150.9202597698209_sydney_google_maps_image,,-33.71780402234493_150.9202597698209_sydney_google_satellite_image,,-33.71780402234493_150.9202597698209_sydney_google_street_view_image,, +6576901203,1,sydney,-33.82415428658629,151.07862747217405,,-33.82415428658629_151.07862747217405_sydney_google_maps_image,,-33.82415428658629_151.07862747217405_sydney_google_satellite_image,,-33.82415428658629_151.07862747217405_sydney_google_street_view_image,, +319649390,1,sydney,-33.798783899999634,150.95787410000003,,-33.798783899999634_150.95787410000003_sydney_google_maps_image,,-33.798783899999634_150.95787410000003_sydney_google_satellite_image,,-33.798783899999634_150.95787410000003_sydney_google_street_view_image,, +1893124559,1,sydney,-33.76998633741108,150.7730188485084,,-33.76998633741108_150.7730188485084_sydney_google_maps_image,,-33.76998633741108_150.7730188485084_sydney_google_satellite_image,,-33.76998633741108_150.7730188485084_sydney_google_street_view_image,, +7448392528,1,sydney,-33.71267605159711,150.95836948796511,,-33.71267605159711_150.95836948796511_sydney_google_maps_image,,-33.71267605159711_150.95836948796511_sydney_google_satellite_image,,-33.71267605159711_150.95836948796511_sydney_google_street_view_image,, +792213520,1,sydney,-33.98596620543193,151.14692817466056,,-33.98596620543193_151.14692817466056_sydney_google_maps_image,,-33.98596620543193_151.14692817466056_sydney_google_satellite_image,,-33.98596620543193_151.14692817466056_sydney_google_street_view_image,, +7194087677,1,sydney,-33.75508246136216,150.7042533212603,,-33.75508246136216_150.7042533212603_sydney_google_maps_image,,-33.75508246136216_150.7042533212603_sydney_google_satellite_image,,-33.75508246136216_150.7042533212603_sydney_google_street_view_image,, +1974543144,1,sydney,-33.79516507042692,151.1223010825233,,-33.79516507042692_151.1223010825233_sydney_google_maps_image,,-33.79516507042692_151.1223010825233_sydney_google_satellite_image,,-33.79516507042692_151.1223010825233_sydney_google_street_view_image,, +221933531,1,sydney,-33.75485360042116,150.70604429119996,,-33.75485360042116_150.70604429119996_sydney_google_maps_image,,-33.75485360042116_150.70604429119996_sydney_google_satellite_image,,-33.75485360042116_150.70604429119996_sydney_google_street_view_image,, +2060895650,2,sydney,-33.76074204520165,151.12880870381755,,-33.76074204520165_151.12880870381755_sydney_google_maps_image,,-33.76074204520165_151.12880870381755_sydney_google_satellite_image,,-33.76074204520165_151.12880870381755_sydney_google_street_view_image,, +399121769,2,sydney,-33.814814265517626,151.05436563951298,,-33.814814265517626_151.05436563951298_sydney_google_maps_image,,-33.814814265517626_151.05436563951298_sydney_google_satellite_image,,-33.814814265517626_151.05436563951298_sydney_google_street_view_image,, +1612463931,2,sydney,-33.82274961375412,150.98036233033224,,-33.82274961375412_150.98036233033224_sydney_google_maps_image,,-33.82274961375412_150.98036233033224_sydney_google_satellite_image,,-33.82274961375412_150.98036233033224_sydney_google_street_view_image,, +428468942,2,sydney,-33.81442865579148,151.05481607271815,,-33.81442865579148_151.05481607271815_sydney_google_maps_image,,-33.81442865579148_151.05481607271815_sydney_google_satellite_image,,-33.81442865579148_151.05481607271815_sydney_google_street_view_image,, +6115467798,2,sydney,-33.9165581813648,151.1666292861455,,-33.9165581813648_151.1666292861455_sydney_google_maps_image,,-33.9165581813648_151.1666292861455_sydney_google_satellite_image,,-33.9165581813648_151.1666292861455_sydney_google_street_view_image,, +4924219553,2,sydney,-33.90276226253167,151.19469906341232,,-33.90276226253167_151.19469906341232_sydney_google_maps_image,,-33.90276226253167_151.19469906341232_sydney_google_satellite_image,,-33.90276226253167_151.19469906341232_sydney_google_street_view_image,, +2189527088,2,sydney,-33.782236376836465,150.82660678611362,,-33.782236376836465_150.82660678611362_sydney_google_maps_image,,-33.782236376836465_150.82660678611362_sydney_google_satellite_image,,-33.782236376836465_150.82660678611362_sydney_google_street_view_image,, +813186510,2,sydney,-33.69119227782244,151.10150773087983,,-33.69119227782244_151.10150773087983_sydney_google_maps_image,,-33.69119227782244_151.10150773087983_sydney_google_satellite_image,,-33.69119227782244_151.10150773087983_sydney_google_street_view_image,, +222582855,2,sydney,-33.912606003359606,150.98365463772956,,-33.912606003359606_150.98365463772956_sydney_google_maps_image,,-33.912606003359606_150.98365463772956_sydney_google_satellite_image,,-33.912606003359606_150.98365463772956_sydney_google_street_view_image,, +4546260408,2,sydney,-33.92070858361609,150.92405416837957,,-33.92070858361609_150.92405416837957_sydney_google_maps_image,,-33.92070858361609_150.92405416837957_sydney_google_satellite_image,,-33.92070858361609_150.92405416837957_sydney_google_street_view_image,, +6718063062,3,sydney,-33.87006611870223,151.27018484811944,,-33.87006611870223_151.27018484811944_sydney_google_maps_image,,-33.87006611870223_151.27018484811944_sydney_google_satellite_image,,-33.87006611870223_151.27018484811944_sydney_google_street_view_image,, +3296252561,3,sydney,-33.77309630902993,151.08178711325579,,-33.77309630902993_151.08178711325579_sydney_google_maps_image,,-33.77309630902993_151.08178711325579_sydney_google_satellite_image,,-33.77309630902993_151.08178711325579_sydney_google_street_view_image,, +4478143699,3,sydney,-33.79401559999961,151.18671450000002,,-33.79401559999961_151.18671450000002_sydney_google_maps_image,,-33.79401559999961_151.18671450000002_sydney_google_satellite_image,,-33.79401559999961_151.18671450000002_sydney_google_street_view_image,, +7455590962,3,sydney,-33.88091426735227,151.1391816075202,,-33.88091426735227_151.1391816075202_sydney_google_maps_image,,-33.88091426735227_151.1391816075202_sydney_google_satellite_image,,-33.88091426735227_151.1391816075202_sydney_google_street_view_image,, +3502499372,3,sydney,-34.03426353117276,151.07117700846507,,-34.03426353117276_151.07117700846507_sydney_google_maps_image,,-34.03426353117276_151.07117700846507_sydney_google_satellite_image,,-34.03426353117276_151.07117700846507_sydney_google_street_view_image,, +4983992021,3,sydney,-33.89061679181626,151.2736592878431,,-33.89061679181626_151.2736592878431_sydney_google_maps_image,,-33.89061679181626_151.2736592878431_sydney_google_satellite_image,,-33.89061679181626_151.2736592878431_sydney_google_street_view_image,, +1346628721,3,sydney,-33.86680300882241,151.20378197822808,,-33.86680300882241_151.20378197822808_sydney_google_maps_image,,-33.86680300882241_151.20378197822808_sydney_google_satellite_image,,-33.86680300882241_151.20378197822808_sydney_google_street_view_image,, +173897520,3,sydney,-33.771774306176226,151.07992588326127,,-33.771774306176226_151.07992588326127_sydney_google_maps_image,,-33.771774306176226_151.07992588326127_sydney_google_satellite_image,,-33.771774306176226_151.07992588326127_sydney_google_street_view_image,, +6053610954,3,sydney,-33.807760498515314,151.09063231683487,,-33.807760498515314_151.09063231683487_sydney_google_maps_image,,-33.807760498515314_151.09063231683487_sydney_google_satellite_image,,-33.807760498515314_151.09063231683487_sydney_google_street_view_image,, +809372673,3,sydney,-33.96493719999962,151.1418048,,-33.96493719999962_151.1418048_sydney_google_maps_image,,-33.96493719999962_151.1418048_sydney_google_satellite_image,,-33.96493719999962_151.1418048_sydney_google_street_view_image,, +7097821928,4,sydney,-33.84580348093946,151.21121596770317,,-33.84580348093946_151.21121596770317_sydney_google_maps_image,,-33.84580348093946_151.21121596770317_sydney_google_satellite_image,,-33.84580348093946_151.21121596770317_sydney_google_street_view_image,, +207331854,4,sydney,-33.87431479999959,151.1071721,,-33.87431479999959_151.1071721_sydney_google_maps_image,,-33.87431479999959_151.1071721_sydney_google_satellite_image,,-33.87431479999959_151.1071721_sydney_google_street_view_image,, +4353406491,4,sydney,-33.70411547645366,151.10142469329003,,-33.70411547645366_151.10142469329003_sydney_google_maps_image,,-33.70411547645366_151.10142469329003_sydney_google_satellite_image,,-33.70411547645366_151.10142469329003_sydney_google_street_view_image,, +6371771205,4,sydney,-33.918959639988216,151.2574738634685,,-33.918959639988216_151.2574738634685_sydney_google_maps_image,,-33.918959639988216_151.2574738634685_sydney_google_satellite_image,,-33.918959639988216_151.2574738634685_sydney_google_street_view_image,, +584530131,4,sydney,-33.915050945647224,151.2403330804831,,-33.915050945647224_151.2403330804831_sydney_google_maps_image,,-33.915050945647224_151.2403330804831_sydney_google_satellite_image,,-33.915050945647224_151.2403330804831_sydney_google_street_view_image,, +4450003390,4,sydney,-33.8654604999996,151.277738,,-33.8654604999996_151.277738_sydney_google_maps_image,,-33.8654604999996_151.277738_sydney_google_satellite_image,,-33.8654604999996_151.277738_sydney_google_street_view_image,, +5099993626,4,sydney,-33.85762590152955,151.1815009561314,,-33.85762590152955_151.1815009561314_sydney_google_maps_image,,-33.85762590152955_151.1815009561314_sydney_google_satellite_image,,-33.85762590152955_151.1815009561314_sydney_google_street_view_image,, +5774499609,4,sydney,-33.943638967283476,151.24003352729176,,-33.943638967283476_151.24003352729176_sydney_google_maps_image,,-33.943638967283476_151.24003352729176_sydney_google_satellite_image,,-33.943638967283476_151.24003352729176_sydney_google_street_view_image,, +4956462389,4,sydney,-33.89343628856618,151.247933582083,,-33.89343628856618_151.247933582083_sydney_google_maps_image,,-33.89343628856618_151.247933582083_sydney_google_satellite_image,,-33.89343628856618_151.247933582083_sydney_google_street_view_image,, +5872695843,4,sydney,-33.91430321060813,151.24003357268805,,-33.91430321060813_151.24003357268805_sydney_google_maps_image,,-33.91430321060813_151.24003357268805_sydney_google_satellite_image,,-33.91430321060813_151.24003357268805_sydney_google_street_view_image,, +1081217611,5,sydney,-33.96762896444103,151.10423162344804,,-33.96762896444103_151.10423162344804_sydney_google_maps_image,,-33.96762896444103_151.10423162344804_sydney_google_satellite_image,,-33.96762896444103_151.10423162344804_sydney_google_street_view_image,, +5886974732,5,sydney,-33.79644388181618,151.18331872307652,,-33.79644388181618_151.18331872307652_sydney_google_maps_image,,-33.79644388181618_151.18331872307652_sydney_google_satellite_image,,-33.79644388181618_151.18331872307652_sydney_google_street_view_image,, +3921514862,5,sydney,-33.88483179999965,151.2005316,,-33.88483179999965_151.2005316_sydney_google_maps_image,,-33.88483179999965_151.2005316_sydney_google_satellite_image,,-33.88483179999965_151.2005316_sydney_google_street_view_image,, +2312254908,5,sydney,-33.877610042893465,151.21302434745317,,-33.877610042893465_151.21302434745317_sydney_google_maps_image,,-33.877610042893465_151.21302434745317_sydney_google_satellite_image,,-33.877610042893465_151.21302434745317_sydney_google_street_view_image,, +3626039515,5,sydney,-33.899123980486024,151.17173769606052,,-33.899123980486024_151.17173769606052_sydney_google_maps_image,,-33.899123980486024_151.17173769606052_sydney_google_satellite_image,,-33.899123980486024_151.17173769606052_sydney_google_street_view_image,, +5729354132,5,sydney,-33.796508247052806,151.18460588445558,,-33.796508247052806_151.18460588445558_sydney_google_maps_image,,-33.796508247052806_151.18460588445558_sydney_google_satellite_image,,-33.796508247052806_151.18460588445558_sydney_google_street_view_image,, +1264487049,5,sydney,-33.828426924417144,151.2297350829877,,-33.828426924417144_151.2297350829877_sydney_google_maps_image,,-33.828426924417144_151.2297350829877_sydney_google_satellite_image,,-33.828426924417144_151.2297350829877_sydney_google_street_view_image,, +514947290,5,sydney,-33.8776137579799,151.21302915432227,,-33.8776137579799_151.21302915432227_sydney_google_maps_image,,-33.8776137579799_151.21302915432227_sydney_google_satellite_image,,-33.8776137579799_151.21302915432227_sydney_google_street_view_image,, +1081257981,5,sydney,-33.96639019999964,151.1055112,,-33.96639019999964_151.1055112_sydney_google_maps_image,,-33.96639019999964_151.1055112_sydney_google_satellite_image,,-33.96639019999964_151.1055112_sydney_google_street_view_image,, +4941850644,5,sydney,-33.89398165714167,151.26374581410917,,-33.89398165714167_151.26374581410917_sydney_google_maps_image,,-33.89398165714167_151.26374581410917_sydney_google_satellite_image,,-33.89398165714167_151.26374581410917_sydney_google_street_view_image,, +5820219899,1,valencia,39.47944041395021,-0.32795889607769707,,39.47944041395021_-0.32795889607769707_valencia_google_maps_image,,39.47944041395021_-0.32795889607769707_valencia_google_satellite_image,,39.47944041395021_-0.32795889607769707_valencia_google_street_view_image,, +7615543187,1,valencia,39.453906605635,-0.35961113299367226,,39.453906605635_-0.35961113299367226_valencia_google_maps_image,,39.453906605635_-0.35961113299367226_valencia_google_satellite_image,,39.453906605635_-0.35961113299367226_valencia_google_street_view_image,, +3316779669,1,valencia,39.457499000565605,-0.3658361195517701,,39.457499000565605_-0.3658361195517701_valencia_google_maps_image,,39.457499000565605_-0.3658361195517701_valencia_google_satellite_image,,39.457499000565605_-0.3658361195517701_valencia_google_street_view_image,, +6584941787,1,valencia,39.42488042574295,-0.36405182457733015,,39.42488042574295_-0.36405182457733015_valencia_google_maps_image,,39.42488042574295_-0.36405182457733015_valencia_google_satellite_image,,39.42488042574295_-0.36405182457733015_valencia_google_street_view_image,, +256966146,1,valencia,39.497926261829804,-0.3756100713970001,,39.497926261829804_-0.3756100713970001_valencia_google_maps_image,,39.497926261829804_-0.3756100713970001_valencia_google_satellite_image,,39.497926261829804_-0.3756100713970001_valencia_google_street_view_image,, +1719308792,1,valencia,39.434838740989456,-0.3909214820609415,,39.434838740989456_-0.3909214820609415_valencia_google_maps_image,,39.434838740989456_-0.3909214820609415_valencia_google_satellite_image,,39.434838740989456_-0.3909214820609415_valencia_google_street_view_image,, +6638503684,1,valencia,39.477481818937264,-0.38293193671028813,,39.477481818937264_-0.38293193671028813_valencia_google_maps_image,,39.477481818937264_-0.38293193671028813_valencia_google_satellite_image,,39.477481818937264_-0.38293193671028813_valencia_google_street_view_image,, +6959663422,1,valencia,39.480765059231985,-0.36142724695837525,,39.480765059231985_-0.36142724695837525_valencia_google_maps_image,,39.480765059231985_-0.36142724695837525_valencia_google_satellite_image,,39.480765059231985_-0.36142724695837525_valencia_google_street_view_image,, +6395687842,1,valencia,39.47612866268815,-0.3651666345201981,,39.47612866268815_-0.3651666345201981_valencia_google_maps_image,,39.47612866268815_-0.3651666345201981_valencia_google_satellite_image,,39.47612866268815_-0.3651666345201981_valencia_google_street_view_image,, +657857713,1,valencia,39.44996077979142,-0.38001390526542506,,39.44996077979142_-0.38001390526542506_valencia_google_maps_image,,39.44996077979142_-0.38001390526542506_valencia_google_satellite_image,,39.44996077979142_-0.38001390526542506_valencia_google_street_view_image,, +10120283,2,valencia,39.46918479099177,-0.3685254230157961,,39.46918479099177_-0.3685254230157961_valencia_google_maps_image,,39.46918479099177_-0.3685254230157961_valencia_google_satellite_image,,39.46918479099177_-0.3685254230157961_valencia_google_street_view_image,, +4307621589,2,valencia,39.47481523656729,-0.3896406053929307,,39.47481523656729_-0.3896406053929307_valencia_google_maps_image,,39.47481523656729_-0.3896406053929307_valencia_google_satellite_image,,39.47481523656729_-0.3896406053929307_valencia_google_street_view_image,, +1452342492,2,valencia,39.47970994148924,-0.39653547645834863,,39.47970994148924_-0.39653547645834863_valencia_google_maps_image,,39.47970994148924_-0.39653547645834863_valencia_google_satellite_image,,39.47970994148924_-0.39653547645834863_valencia_google_street_view_image,, +23455760,2,valencia,39.46788068635267,-0.3336291566899967,,39.46788068635267_-0.3336291566899967_valencia_google_maps_image,,39.46788068635267_-0.3336291566899967_valencia_google_satellite_image,,39.46788068635267_-0.3336291566899967_valencia_google_street_view_image,, +4633920690,2,valencia,39.46817634623685,-0.3514821029216269,,39.46817634623685_-0.3514821029216269_valencia_google_maps_image,,39.46817634623685_-0.3514821029216269_valencia_google_satellite_image,,39.46817634623685_-0.3514821029216269_valencia_google_street_view_image,, +6445298659,2,valencia,39.49270231487079,-0.38944530593827414,,39.49270231487079_-0.38944530593827414_valencia_google_maps_image,,39.49270231487079_-0.38944530593827414_valencia_google_satellite_image,,39.49270231487079_-0.38944530593827414_valencia_google_street_view_image,, +6617346030,2,valencia,39.468041712788455,-0.3510203409721477,,39.468041712788455_-0.3510203409721477_valencia_google_maps_image,,39.468041712788455_-0.3510203409721477_valencia_google_satellite_image,,39.468041712788455_-0.3510203409721477_valencia_google_street_view_image,, +4741566835,2,valencia,39.47761217422326,-0.39837179017981,,39.47761217422326_-0.39837179017981_valencia_google_maps_image,,39.47761217422326_-0.39837179017981_valencia_google_satellite_image,,39.47761217422326_-0.39837179017981_valencia_google_street_view_image,, +4523277176,2,valencia,39.48436225366254,-0.3832592825626807,,39.48436225366254_-0.3832592825626807_valencia_google_maps_image,,39.48436225366254_-0.3832592825626807_valencia_google_satellite_image,,39.48436225366254_-0.3832592825626807_valencia_google_street_view_image,, +197384433,2,valencia,39.473961665520854,-0.3834447489236085,,39.473961665520854_-0.3834447489236085_valencia_google_maps_image,,39.473961665520854_-0.3834447489236085_valencia_google_satellite_image,,39.473961665520854_-0.3834447489236085_valencia_google_street_view_image,, +2656119556,3,valencia,39.491276205363334,-0.3807078309216622,,39.491276205363334_-0.3807078309216622_valencia_google_maps_image,,39.491276205363334_-0.3807078309216622_valencia_google_satellite_image,,39.491276205363334_-0.3807078309216622_valencia_google_street_view_image,, +5257504624,3,valencia,39.48593423345085,-0.3927002240358755,,39.48593423345085_-0.3927002240358755_valencia_google_maps_image,,39.48593423345085_-0.3927002240358755_valencia_google_satellite_image,,39.48593423345085_-0.3927002240358755_valencia_google_street_view_image,, +7395350141,3,valencia,39.49449278337023,-0.37859299719305484,,39.49449278337023_-0.37859299719305484_valencia_google_maps_image,,39.49449278337023_-0.37859299719305484_valencia_google_satellite_image,,39.49449278337023_-0.37859299719305484_valencia_google_street_view_image,, +6404014385,3,valencia,39.47177372103371,-0.3962729613861756,,39.47177372103371_-0.3962729613861756_valencia_google_maps_image,,39.47177372103371_-0.3962729613861756_valencia_google_satellite_image,,39.47177372103371_-0.3962729613861756_valencia_google_street_view_image,, +1386005512,3,valencia,39.49492974467926,-0.3803357786471776,,39.49492974467926_-0.3803357786471776_valencia_google_maps_image,,39.49492974467926_-0.3803357786471776_valencia_google_satellite_image,,39.49492974467926_-0.3803357786471776_valencia_google_street_view_image,, +3316779670,3,valencia,39.45804955060059,-0.36548870941267364,,39.45804955060059_-0.36548870941267364_valencia_google_maps_image,,39.45804955060059_-0.36548870941267364_valencia_google_satellite_image,,39.45804955060059_-0.36548870941267364_valencia_google_street_view_image,, +5046970845,3,valencia,39.473067282167825,-0.3760932950480865,,39.473067282167825_-0.3760932950480865_valencia_google_maps_image,,39.473067282167825_-0.3760932950480865_valencia_google_satellite_image,,39.473067282167825_-0.3760932950480865_valencia_google_street_view_image,, +23776578,3,valencia,39.492922480305914,-0.38025355960926677,,39.492922480305914_-0.38025355960926677_valencia_google_maps_image,,39.492922480305914_-0.38025355960926677_valencia_google_satellite_image,,39.492922480305914_-0.38025355960926677_valencia_google_street_view_image,, +3607188804,3,valencia,39.50266836960625,-0.42011620754781415,,39.50266836960625_-0.42011620754781415_valencia_google_maps_image,,39.50266836960625_-0.42011620754781415_valencia_google_satellite_image,,39.50266836960625_-0.42011620754781415_valencia_google_street_view_image,, +1452368050,3,valencia,39.47875416889303,-0.39602860983659877,,39.47875416889303_-0.39602860983659877_valencia_google_maps_image,,39.47875416889303_-0.39602860983659877_valencia_google_satellite_image,,39.47875416889303_-0.39602860983659877_valencia_google_street_view_image,, +4103882463,4,valencia,39.45809835038438,-0.3927642594365756,,39.45809835038438_-0.3927642594365756_valencia_google_maps_image,,39.45809835038438_-0.3927642594365756_valencia_google_satellite_image,,39.45809835038438_-0.3927642594365756_valencia_google_street_view_image,, +4989970386,4,valencia,39.46071430307684,-0.33517838888347806,,39.46071430307684_-0.33517838888347806_valencia_google_maps_image,,39.46071430307684_-0.33517838888347806_valencia_google_satellite_image,,39.46071430307684_-0.33517838888347806_valencia_google_street_view_image,, +2264306798,4,valencia,39.47408519945665,-0.377923104794742,,39.47408519945665_-0.377923104794742_valencia_google_maps_image,,39.47408519945665_-0.377923104794742_valencia_google_satellite_image,,39.47408519945665_-0.377923104794742_valencia_google_street_view_image,, +4111725006,4,valencia,39.46346388653347,-0.35222995869103474,,39.46346388653347_-0.35222995869103474_valencia_google_maps_image,,39.46346388653347_-0.35222995869103474_valencia_google_satellite_image,,39.46346388653347_-0.35222995869103474_valencia_google_street_view_image,, +3608183846,4,valencia,39.50040481755207,-0.4187434111724148,,39.50040481755207_-0.4187434111724148_valencia_google_maps_image,,39.50040481755207_-0.4187434111724148_valencia_google_satellite_image,,39.50040481755207_-0.4187434111724148_valencia_google_street_view_image,, +5382634205,4,valencia,39.48888613713267,-0.37305738607900424,,39.48888613713267_-0.37305738607900424_valencia_google_maps_image,,39.48888613713267_-0.37305738607900424_valencia_google_satellite_image,,39.48888613713267_-0.37305738607900424_valencia_google_street_view_image,, +6822193923,4,valencia,39.465856218581514,-0.3510310879639834,,39.465856218581514_-0.3510310879639834_valencia_google_maps_image,,39.465856218581514_-0.3510310879639834_valencia_google_satellite_image,,39.465856218581514_-0.3510310879639834_valencia_google_street_view_image,, +777291452,4,valencia,39.454196024888084,-0.37488666077946176,,39.454196024888084_-0.37488666077946176_valencia_google_maps_image,,39.454196024888084_-0.37488666077946176_valencia_google_satellite_image,,39.454196024888084_-0.37488666077946176_valencia_google_street_view_image,, +7081005114,4,valencia,39.465816711838684,-0.39254115963754793,,39.465816711838684_-0.39254115963754793_valencia_google_maps_image,,39.465816711838684_-0.39254115963754793_valencia_google_satellite_image,,39.465816711838684_-0.39254115963754793_valencia_google_street_view_image,, +4893666924,4,valencia,39.469551825485695,-0.389694732258049,,39.469551825485695_-0.389694732258049_valencia_google_maps_image,,39.469551825485695_-0.389694732258049_valencia_google_satellite_image,,39.469551825485695_-0.389694732258049_valencia_google_street_view_image,, +825264576,5,valencia,39.495490340638575,-0.3705974705540262,,39.495490340638575_-0.3705974705540262_valencia_google_maps_image,,39.495490340638575_-0.3705974705540262_valencia_google_satellite_image,,39.495490340638575_-0.3705974705540262_valencia_google_street_view_image,, +5299082008,5,valencia,39.48755147406303,-0.39366519946820894,,39.48755147406303_-0.39366519946820894_valencia_google_maps_image,,39.48755147406303_-0.39366519946820894_valencia_google_satellite_image,,39.48755147406303_-0.39366519946820894_valencia_google_street_view_image,, +2288376112,5,valencia,39.46256831193777,-0.37293831658842413,,39.46256831193777_-0.37293831658842413_valencia_google_maps_image,,39.46256831193777_-0.37293831658842413_valencia_google_satellite_image,,39.46256831193777_-0.37293831658842413_valencia_google_street_view_image,, +6520546739,5,valencia,39.47353829857786,-0.35340940952003375,,39.47353829857786_-0.35340940952003375_valencia_google_maps_image,,39.47353829857786_-0.35340940952003375_valencia_google_satellite_image,,39.47353829857786_-0.35340940952003375_valencia_google_street_view_image,, +3686352663,5,valencia,39.4620799050774,-0.3425859129117003,,39.4620799050774_-0.3425859129117003_valencia_google_maps_image,,39.4620799050774_-0.3425859129117003_valencia_google_satellite_image,,39.4620799050774_-0.3425859129117003_valencia_google_street_view_image,, +2625796996,5,valencia,39.49605573652206,-0.37034230970581455,,39.49605573652206_-0.37034230970581455_valencia_google_maps_image,,39.49605573652206_-0.37034230970581455_valencia_google_satellite_image,,39.49605573652206_-0.37034230970581455_valencia_google_street_view_image,, +4608688991,5,valencia,39.46286573182253,-0.3421113955928668,,39.46286573182253_-0.3421113955928668_valencia_google_maps_image,,39.46286573182253_-0.3421113955928668_valencia_google_satellite_image,,39.46286573182253_-0.3421113955928668_valencia_google_street_view_image,, +6318095964,5,valencia,39.48949944896898,-0.3599938518995235,,39.48949944896898_-0.3599938518995235_valencia_google_maps_image,,39.48949944896898_-0.3599938518995235_valencia_google_satellite_image,,39.48949944896898_-0.3599938518995235_valencia_google_street_view_image,, +3316778157,5,valencia,39.460378436299656,-0.3761088765787719,,39.460378436299656_-0.3761088765787719_valencia_google_maps_image,,39.460378436299656_-0.3761088765787719_valencia_google_satellite_image,,39.460378436299656_-0.3761088765787719_valencia_google_street_view_image,, +372352252,5,valencia,39.47316826588193,-0.38551028171268553,,39.47316826588193_-0.38551028171268553_valencia_google_maps_image,,39.47316826588193_-0.38551028171268553_valencia_google_satellite_image,,39.47316826588193_-0.38551028171268553_valencia_google_street_view_image,, +316081856,1,vic,41.92591313729815,2.246212969281069,,41.92591313729815_2.246212969281069_vic_google_maps_image,,41.92591313729815_2.246212969281069_vic_google_satellite_image,,41.92591313729815_2.246212969281069_vic_google_street_view_image,, +180222391,1,vic,41.93037754053714,2.265662962905963,,41.93037754053714_2.265662962905963_vic_google_maps_image,,41.93037754053714_2.265662962905963_vic_google_satellite_image,,41.93037754053714_2.265662962905963_vic_google_street_view_image,, +3221296626,1,vic,41.921277705130926,2.252697776235735,,41.921277705130926_2.252697776235735_vic_google_maps_image,,41.921277705130926_2.252697776235735_vic_google_satellite_image,,41.921277705130926_2.252697776235735_vic_google_street_view_image,, +3822573804,1,vic,41.931317207389945,2.242743935499561,,41.931317207389945_2.242743935499561_vic_google_maps_image,,41.931317207389945_2.242743935499561_vic_google_satellite_image,,41.931317207389945_2.242743935499561_vic_google_street_view_image,, +578129672,1,vic,41.92381742413861,2.247214936670592,,41.92381742413861_2.247214936670592_vic_google_maps_image,,41.92381742413861_2.247214936670592_vic_google_satellite_image,,41.92381742413861_2.247214936670592_vic_google_street_view_image,, +315822627,1,vic,41.93484314459451,2.2666793618041736,,41.93484314459451_2.2666793618041736_vic_google_maps_image,,41.93484314459451_2.2666793618041736_vic_google_satellite_image,,41.93484314459451_2.2666793618041736_vic_google_street_view_image,, +4522494391,1,vic,41.94669846456933,2.2839258768833774,,41.94669846456933_2.2839258768833774_vic_google_maps_image,,41.94669846456933_2.2839258768833774_vic_google_satellite_image,,41.94669846456933_2.2839258768833774_vic_google_street_view_image,, +1638918440,1,vic,41.914658079015354,2.229188154682545,,41.914658079015354_2.229188154682545_vic_google_maps_image,,41.914658079015354_2.229188154682545_vic_google_satellite_image,,41.914658079015354_2.229188154682545_vic_google_street_view_image,, +166369645,1,vic,41.944914575545354,2.2516350329645634,,41.944914575545354_2.2516350329645634_vic_google_maps_image,,41.944914575545354_2.2516350329645634_vic_google_satellite_image,,41.944914575545354_2.2516350329645634_vic_google_street_view_image,, +318106310,1,vic,41.941476169947805,2.2530142517304164,,41.941476169947805_2.2530142517304164_vic_google_maps_image,,41.941476169947805_2.2530142517304164_vic_google_satellite_image,,41.941476169947805_2.2530142517304164_vic_google_street_view_image,, +6056021285,2,vic,41.940631694228706,2.2539151901721217,,41.940631694228706_2.2539151901721217_vic_google_maps_image,,41.940631694228706_2.2539151901721217_vic_google_satellite_image,,41.940631694228706_2.2539151901721217_vic_google_street_view_image,, +6221830417,2,vic,41.93193158804071,2.252876920065436,,41.93193158804071_2.252876920065436_vic_google_maps_image,,41.93193158804071_2.252876920065436_vic_google_satellite_image,,41.93193158804071_2.252876920065436_vic_google_street_view_image,, +6174756180,2,vic,41.93209985017114,2.2526981846520737,,41.93209985017114_2.2526981846520737_vic_google_maps_image,,41.93209985017114_2.2526981846520737_vic_google_satellite_image,,41.93209985017114_2.2526981846520737_vic_google_street_view_image,, +6056018583,2,vic,41.93966294406402,2.254148043353885,,41.93966294406402_2.254148043353885_vic_google_maps_image,,41.93966294406402_2.254148043353885_vic_google_satellite_image,,41.93966294406402_2.254148043353885_vic_google_street_view_image,, +6174756176,2,vic,41.9321988682738,2.2525857895253765,,41.9321988682738_2.2525857895253765_vic_google_maps_image,,41.9321988682738_2.2525857895253765_vic_google_satellite_image,,41.9321988682738_2.2525857895253765_vic_google_street_view_image,, +5910245370,2,vic,41.923145061606625,2.2506873578971343,,41.923145061606625_2.2506873578971343_vic_google_maps_image,,41.923145061606625_2.2506873578971343_vic_google_satellite_image,,41.923145061606625_2.2506873578971343_vic_google_street_view_image,, +6174756388,2,vic,41.932144497208704,2.253280363761519,,41.932144497208704_2.253280363761519_vic_google_maps_image,,41.932144497208704_2.253280363761519_vic_google_satellite_image,,41.932144497208704_2.253280363761519_vic_google_street_view_image,, +6221830426,2,vic,41.931656792756655,2.253165216599444,,41.931656792756655_2.253165216599444_vic_google_maps_image,,41.931656792756655_2.253165216599444_vic_google_satellite_image,,41.931656792756655_2.253165216599444_vic_google_street_view_image,, +6221830430,2,vic,41.93158979329575,2.2532355073830876,,41.93158979329575_2.2532355073830876_vic_google_maps_image,,41.93158979329575_2.2532355073830876_vic_google_satellite_image,,41.93158979329575_2.2532355073830876_vic_google_street_view_image,, +6174756170,2,vic,41.932361099731935,2.252339171013428,,41.932361099731935_2.252339171013428_vic_google_maps_image,,41.932361099731935_2.252339171013428_vic_google_satellite_image,,41.932361099731935_2.252339171013428_vic_google_street_view_image,, +3310768356,3,vic,41.92830423599381,2.248130428573768,,41.92830423599381_2.248130428573768_vic_google_maps_image,,41.92830423599381_2.248130428573768_vic_google_satellite_image,,41.92830423599381_2.248130428573768_vic_google_street_view_image,, +6221769270,3,vic,41.928622245214314,2.252229973267793,,41.928622245214314_2.252229973267793_vic_google_maps_image,,41.928622245214314_2.252229973267793_vic_google_satellite_image,,41.928622245214314_2.252229973267793_vic_google_street_view_image,, +3239150438,3,vic,41.93019663333702,2.261418397729625,,41.93019663333702_2.261418397729625_vic_google_maps_image,,41.93019663333702_2.261418397729625_vic_google_satellite_image,,41.93019663333702_2.261418397729625_vic_google_street_view_image,, +6221830425,3,vic,41.9316973344315,2.253122683235833,,41.9316973344315_2.253122683235833_vic_google_maps_image,,41.9316973344315_2.253122683235833_vic_google_satellite_image,,41.9316973344315_2.253122683235833_vic_google_street_view_image,, +6511493370,3,vic,41.933819643216054,2.25541238048663,,41.933819643216054_2.25541238048663_vic_google_maps_image,,41.933819643216054_2.25541238048663_vic_google_satellite_image,,41.933819643216054_2.25541238048663_vic_google_street_view_image,, +4054362919,3,vic,41.930833697354764,2.2567110589958728,,41.930833697354764_2.2567110589958728_vic_google_maps_image,,41.930833697354764_2.2567110589958728_vic_google_satellite_image,,41.930833697354764_2.2567110589958728_vic_google_street_view_image,, +6174756416,3,vic,41.92995846424069,2.250996213619746,,41.92995846424069_2.250996213619746_vic_google_maps_image,,41.92995846424069_2.250996213619746_vic_google_satellite_image,,41.92995846424069_2.250996213619746_vic_google_street_view_image,, +289341146,3,vic,41.92961906273809,2.2500734974518433,,41.92961906273809_2.2500734974518433_vic_google_maps_image,,41.92961906273809_2.2500734974518433_vic_google_satellite_image,,41.92961906273809_2.2500734974518433_vic_google_street_view_image,, +6221769264,3,vic,41.927823602894655,2.252526720530348,,41.927823602894655_2.252526720530348_vic_google_maps_image,,41.927823602894655_2.252526720530348_vic_google_satellite_image,,41.927823602894655_2.252526720530348_vic_google_street_view_image,, +5831644537,3,vic,41.92955120048565,2.256683913695918,,41.92955120048565_2.256683913695918_vic_google_maps_image,,41.92955120048565_2.256683913695918_vic_google_satellite_image,,41.92955120048565_2.256683913695918_vic_google_street_view_image,, +6572679122,4,vic,41.9299291072068,2.25529491630342,,41.9299291072068_2.25529491630342_vic_google_maps_image,,41.9299291072068_2.25529491630342_vic_google_satellite_image,,41.9299291072068_2.25529491630342_vic_google_street_view_image,, +5231525318,4,vic,41.9303113790793,2.2530391278103425,,41.9303113790793_2.2530391278103425_vic_google_maps_image,,41.9303113790793_2.2530391278103425_vic_google_satellite_image,,41.9303113790793_2.2530391278103425_vic_google_street_view_image,, +6572717480,4,vic,41.93041883380873,2.255422718181759,,41.93041883380873_2.255422718181759_vic_google_maps_image,,41.93041883380873_2.255422718181759_vic_google_satellite_image,,41.93041883380873_2.255422718181759_vic_google_street_view_image,, +6192655185,4,vic,41.93043425659179,2.2553907717776633,,41.93043425659179_2.2553907717776633_vic_google_maps_image,,41.93043425659179_2.2553907717776633_vic_google_satellite_image,,41.93043425659179_2.2553907717776633_vic_google_street_view_image,, +5231526025,4,vic,41.930324965092844,2.25355176315105,,41.930324965092844_2.25355176315105_vic_google_maps_image,,41.930324965092844_2.25355176315105_vic_google_satellite_image,,41.930324965092844_2.25355176315105_vic_google_street_view_image,, +6221709554,4,vic,41.92962532429341,2.2527247381848343,,41.92962532429341_2.2527247381848343_vic_google_maps_image,,41.92962532429341_2.2527247381848343_vic_google_satellite_image,,41.92962532429341_2.2527247381848343_vic_google_street_view_image,, +6572717470,4,vic,41.93054518126139,2.255076751562613,,41.93054518126139_2.255076751562613_vic_google_maps_image,,41.93054518126139_2.255076751562613_vic_google_satellite_image,,41.93054518126139_2.255076751562613_vic_google_street_view_image,, +6572679127,4,vic,41.92942883494961,2.2555289786388455,,41.92942883494961_2.2555289786388455_vic_google_maps_image,,41.92942883494961_2.2555289786388455_vic_google_satellite_image,,41.92942883494961_2.2555289786388455_vic_google_street_view_image,, +6221843896,4,vic,41.92983091398559,2.2553254315873508,,41.92983091398559_2.2553254315873508_vic_google_maps_image,,41.92983091398559_2.2553254315873508_vic_google_satellite_image,,41.92983091398559_2.2553254315873508_vic_google_street_view_image,, +6572717464,4,vic,41.930062075977744,2.255387188833223,,41.930062075977744_2.255387188833223_vic_google_maps_image,,41.930062075977744_2.255387188833223_vic_google_satellite_image,,41.930062075977744_2.255387188833223_vic_google_street_view_image,, +5231526042,5,vic,41.93029281775988,2.253701522883409,,41.93029281775988_2.253701522883409_vic_google_maps_image,,41.93029281775988_2.253701522883409_vic_google_satellite_image,,41.93029281775988_2.253701522883409_vic_google_street_view_image,, +5231526036,5,vic,41.93029087489445,2.253710573771352,,41.93029087489445_2.253710573771352_vic_google_maps_image,,41.93029087489445_2.253710573771352_vic_google_satellite_image,,41.93029087489445_2.253710573771352_vic_google_street_view_image,, +6221784183,5,vic,41.93105379519471,2.253357778265639,,41.93105379519471_2.253357778265639_vic_google_maps_image,,41.93105379519471_2.253357778265639_vic_google_satellite_image,,41.93105379519471_2.253357778265639_vic_google_street_view_image,, +5231526051,5,vic,41.930304811576846,2.253645649295967,,41.930304811576846_2.253645649295967_vic_google_maps_image,,41.930304811576846_2.253645649295967_vic_google_satellite_image,,41.930304811576846_2.253645649295967_vic_google_street_view_image,, +5231526034,5,vic,41.93024301431513,2.2539738226618553,,41.93024301431513_2.2539738226618553_vic_google_maps_image,,41.93024301431513_2.2539738226618553_vic_google_satellite_image,,41.93024301431513_2.2539738226618553_vic_google_street_view_image,, +6221769242,5,vic,41.93069498079539,2.2531102025309533,,41.93069498079539_2.2531102025309533_vic_google_maps_image,,41.93069498079539_2.2531102025309533_vic_google_satellite_image,,41.93069498079539_2.2531102025309533_vic_google_street_view_image,, +6221769241,5,vic,41.9308045941191,2.2531616066270255,,41.9308045941191_2.2531616066270255_vic_google_maps_image,,41.9308045941191_2.2531616066270255_vic_google_satellite_image,,41.9308045941191_2.2531616066270255_vic_google_street_view_image,, +6056018558,5,vic,41.9304936,2.2529112000000002,,41.9304936_2.2529112000000002_vic_google_maps_image,,41.9304936_2.2529112000000002_vic_google_satellite_image,,41.9304936_2.2529112000000002_vic_google_street_view_image,, +6572679134,5,vic,41.93092216011053,2.2537976150351313,,41.93092216011053_2.2537976150351313_vic_google_maps_image,,41.93092216011053_2.2537976150351313_vic_google_satellite_image,,41.93092216011053_2.2537976150351313_vic_google_street_view_image,, +5231525303,5,vic,41.9308269,2.2539109,,41.9308269_2.2539109_vic_google_maps_image,,41.9308269_2.2539109_vic_google_satellite_image,,41.9308269_2.2539109_vic_google_street_view_image,, diff --git a/validation/readme.md b/validation/readme.md index c9a29687..3ebb8aec 100644 --- a/validation/readme.md +++ b/validation/readme.md @@ -1,40 +1,40 @@ -# Running Validation - -As of June 2020, edge validation data exists for Belfast, Olomouc, and Hong Kong and destination validation data exists for Belfast, Olomouc, and Sao Paulo. - -This data will allow for Phase II validation. In Phase II validation, the dataset sourced from OSM is compared to official data from each individual city. - -THe following serves as instuctions for how to replicate Phase II validation for both edge and destination data. - -## 1. Fork the Repo -- Make sure that you have forked the repo onto your own GitHub account and that the repository is cloned onto your machine. For help on this, please refer to the [GitHub Guides](https://guides.github.com/). -- Additionally, to make sure that your branch is up to date run the following in your command prompt / terminal window - 1. Change directory to the global-indicators folder on your machine - 1. Type the following - - git pull upstream master - -## 2. Download and Organize the Data -1. Download the data from the cloudstor. You can find the links to this data [HERE](https://docs.google.com/document/d/1NnV3g8uj0OnOQFkFIR5IbT60HO2PiF3SLoZpUUTL3B0/edit?ts=5ecc5e75). -1. Place the 'data' folder in the validation directory. - -## 3. Run Docker -1. In the command prompt / terminal window, change your directory to the global-indicators folder. Then type the following - 1. Docker pull gboeing/global-indicators:latest -1. Start running docker in your machine - - On Windows: - - docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash - - On Mac/Linux: - - docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash -1. Change directory to ‘global-indicators/validation’ - -## 4. Run the Python Scripts - -### Run edge_validation script -1. Change directory to ‘global-indicators/validation/edge’ -1. In the command prompt / terminal window, type - - python edge_validation.py - -### Run destination_validation script -1. Change directory to ‘global-indicators/validation/destination' -1. In the command prompt / terminal window, type +# Running Validation + +As of June 2020, edge validation data exists for Belfast, Olomouc, and Hong Kong and destination validation data exists for Belfast, Olomouc, and Sao Paulo. + +This data will allow for Phase II validation. In Phase II validation, the dataset sourced from OSM is compared to official data from each individual city. + +THe following serves as instuctions for how to replicate Phase II validation for both edge and destination data. + +## 1. Fork the Repo +- Make sure that you have forked the repo onto your own GitHub account and that the repository is cloned onto your machine. For help on this, please refer to the [GitHub Guides](https://guides.github.com/). +- Additionally, to make sure that your branch is up to date run the following in your command prompt / terminal window + 1. Change directory to the global-indicators folder on your machine + 1. Type the following + - git pull upstream master + +## 2. Download and Organize the Data +1. Download the data from the cloudstor. You can find the links to this data [HERE](https://docs.google.com/document/d/1NnV3g8uj0OnOQFkFIR5IbT60HO2PiF3SLoZpUUTL3B0/edit?ts=5ecc5e75). +1. Place the 'data' folder in the validation directory. + +## 3. Run Docker +1. In the command prompt / terminal window, change your directory to the global-indicators folder. Then type the following + 1. Docker pull gboeing/global-indicators:latest +1. Start running docker in your machine + - On Windows: + - docker run --rm -it -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash + - On Mac/Linux: + - docker run --rm -it -v "$PWD":/home/jovyan/work gboeing/global-indicators /bin/bash +1. Change directory to ‘global-indicators/validation’ + +## 4. Run the Python Scripts + +### Run edge_validation script +1. Change directory to ‘global-indicators/validation/edge’ +1. In the command prompt / terminal window, type + - python edge_validation.py + +### Run destination_validation script +1. Change directory to ‘global-indicators/validation/destination' +1. In the command prompt / terminal window, type - python destination_validation.py \ No newline at end of file diff --git a/validation/report.md b/validation/report.md index 099db822..31ccf064 100644 --- a/validation/report.md +++ b/validation/report.md @@ -1,242 +1,242 @@ -# Geospatial Team Phase II Validation Report - -This report summarizes the Phase II validation efforts by the global indicators geospatial team. It includes a short lit review summarizing the state of the field in validating OpenStreetMap data, an overview of the team's overall validation motives and logic, and our computational methods. Finally it presents and discusses the validation findings, comparing OpenStreetMap data to official data sets from city partners in the context of how they are used to compute global indicators. While the open data unsurprisingly diverge from the official data in various ways, their overall correspondence is high and sufficient for the purposes of calculating the global indicators. - -## Literature Review - -Over the past decade, the emphasis of the internet transitioned from users consuming predefined content to users simply contributing and sharing content (O'Reilly 2005). When working with geodata, quality is often defined by pre-established parameters compiled over the years. Quality aspects in the field of geo-information were enshrined in the International Organization for Standards (IOS) codes 19113 (quality principles) and 19114 (quality evaluation procedures) with support of ISO Technical Committee 211 (Haklay 2010). - -The OpenStreetMap Project (OSM) emerged from this growing emphasis on user-generated content. OSM is a system based on volunteered geographic information (VGI). However, the quality of spatial data provided is often questioned (Girres and Touya 2010). Thus far, OSM has produced a large amount of spatial data. However, most of OSM's contributors are volunteers or aficionados that focus on their fields of interest (Dorn et al. 2015). Many of those contributors lack training in geographical information science standards and methods. This leads to concerns regarding the data quality (Singh Sehra et al. 2020). Numerous scientific studies focused on evaluating OSM data quality. Over time, various approaches have been developed as technological advancements provided new tools producing more complex quality assessment methods. - -OSM started in London in August of 2004. One early study by Haklay (2010) utilizes London (metropolitan area) and England (country area) as its two study areas. The research focused on analyzing its quality through a comparison with Ordinance Survey datasets. An evaluation of the positional accuracy, attribute accuracy, completeness, and consistency provided an early indication of the quality of VGI. - -For this study, two elements of the possible range of quality were measured: positional accuracy and completeness. For comparison, only streets and roads were used. These are the main features collected by OSM volunteers. Junctions were collapsed to single nodes and multi-carriageways to individual links. High-resolution mapping (1:1250 urban areas, 1:2500 in rural areas, 1:10 000 in moorland), avoiding minor roads and cul-de-sacs. A grid at a resolution of 1 km was created across England. The rest of the analysis was carried out through SQL queries, which added up the length of lines that were contained in or intersected the grid cells. The results demonstrated VGI was able to reach very good spatial quality. However, the inconsistency of VGI in terms of quality demonstrated the digital and social divide of VGI. Rural areas and poorer areas evidenced a lack of coverage (Haklay 2010). - -In order to assess the completeness of OSM data, a visual comparison with aerial imagery, and fitting parametric models regarding the historical growth of the OSM street network was presented in 2017 by Barrington-Leigh and Millard-Ball. Their study found that globally, OSM is 83% complete, and more than 40% of countries have fully mapped street networks. The most notable finding is that completeness has a U-shaped relationship with density. Inter-urban roads that traverse areas with minimal population are primarily present in OSM and high-density regions with a large number of contributors. Communities that are most likely to have missing streets are smaller towns and villages. After obtaining estimates of completeness, the length of the road network in each country was obtained by dividing the existing length of mapped roads in OSM by the estimated fraction complete. The visual assessment was based on a stratified and probability-weighted sample of 45 points in each country. The sampling algorithm in QGIS selected a random point and overlays streets in the OSM database against aerial or satellite imagery provided by Google through the OpenLayersplugin, at a scale of 1:5000. The model also provided estimates of the number of road edges, which were then used to weight each grid cell when aggregating the grid-cell fraction complete predictions to the country level (Barrington-Leigh and Millard-Ball 2017). - -Extending the previous work by Haklay (2010), an article that studies the quality of French OpenStreetMap data provides a larger set of spatial data quality element assessments and uses different quality control methods. Comparisons were made between the OSM data and BD TOPO Large Scale Referential (RGE) data (reference datasets with a metric resolution). These were used to assess: geometric accuracy; attribute accuracy; completeness; logical consistency; semantic accuracy; temporal accuracy; lineage; and usage. The results raise questions such as the heterogeneity of processes, scales of production, and the compliance to standardized and accepted specifications limiting the possible applications. Finding a balance between specifications and contributor freedom is raised, proposing new research such as contributors' assistance with automatic checking of contributions (Girres and Touya 2010). - -As a result, a framework containing more than 25 methods and indicators is presented. This framework allows OSM quality assessments based solely on the data's history (OSM-Full- History-Dump). In lieu of a reference dataset, approximate statements on OSM data quality are possible. No ground truth reference dataset is deployed for OSM data quality evaluation. Instead, an alternate approach is used in specified areas within OSM. This approach can be evaluated by investigating the data's historical development and comparing features' characteristics at different timestamps. In order to assess the OSM data, the calculated results of the iOSMAnalyzer are divided into the following categories: fitness for purpose; general information on the study area; routing and navigation; geocoding; points of interest-search; map-applications; and user information and behavior. The calculated results give a compact quality overview of a freely selectable area. Quality depends on the individual use case, and the OSM data is evaluated in terms of fitness for purpose. However, absolute statements on data quality are only possible with a high-quality reference dataset as a basis for comparison. The study revealed that the interpretation of quality indicators is facilitated and supported by means of contributor activity (Barron et al., 2014). - -Multiple studies have focused on the completeness of OSM road datasets. Using both Street Map and Street View, Zhou and Lin (2019), focus on determining OSM road completeness and omission roads. An omitted road is classified into three types: public roads; private roads; and roads for non-motorized vehicles. - -The study employs an approach proposed by Zhou and Tian (2018). This approach includes the use of geometric indicators to estimate the quantitative completeness of street blocks in OSM. The authors analyze the completeness of street blocks in an OSM dataset by comparing them with a reference map. The method extracts OSM road datasets and converts them into several street blocks that are then visually compared with the Baidu Street Map. The analysis of omission roads is then determined by randomly selecting 60 incomplete street block from the OSM road dataset, overlapping it with the corresponding Baidu Street Map, and then manually digitizing all the omission roads in each of these street blocks. - -The research results indicate that most of the omitted roads were private roads, or one single lane, public roads, of lower importance within the urban road network. For 13 out of the 16 prefecture-level divisions, street block completeness values were lower than 40%, and the maximum value was only 55%. However, in roads with traffic conditions, 14 out of the 16 prefectures, street block completeness values were higher than 80%. These values indicate that major roads have been adequately mapped. The results also suggest that in terms of road length, approximately 90% of omission roads were either public roads or one private lane roads, of which no more than 10% were for non-motorized vehicles (Zhou and Lin 2019). - -A similar approach is taken by Antunes et al. (2015). In the study, they assessed the positional differences between the road-network available in OSM for some regions of the Coimbra Municipality in Portugal, and the data provided by the Coimbra City Hall, as reference (REF). A subset of the original OSM is extracted so that its line features have a direct correspondent in REF; discrepancies are then removed. This process is achieved by applying a buffer around REF and comparing the angular coefficients of REF and OSM line features. Finally, by returning, per cell, the length and length percentage of OSM having a deviation smaller than a user-specified threshold value, and the maximum deviation between OSM and REF datasets (Antunes et al. 2015). - -A study conducted by Dorn et al. in Southern Germany, focuses on two spatial data quality elements: thematic accuracy and completeness area addressed by comparing the OSM data with an authoritative German reference dataset. They were investigating the accuracy of VGI, derived from the OSM dataset. The study area is the Rhine- Neckar region, located in southern Germany. The comparison is executed through a semantic harmonization and a polygon preprocessing part that leads to an area related map comparison with a confusion matrix. Inconsistencies were previously solved to allow comparisons using kappa statistics or Cohen's kappa coefficients after merging all polygons. The kappa value indicates a substantial agreement between both datasets, quantifying the agreement between images. The DLM data shows a large area is covered by farmland and forest. There are definite variations between each location. The forest area presents the highest accuracy and completeness (97.6%) and correctness (95.1%), while the farmland indicates low completeness (45.9%) but high correctness (94.8%). The western part of the study area is more urbanized and, therefore, well mapped. This condition may explain why the eastern section still lacks completeness. The quality of OSM land use and land cover features varies between the investigated classes (Dorn et al., 2015). - -Extending the Quantum GIS processing toolbox's capabilities for assessing spatial data, a study by Singh Sehra et al. addresses the research gap regarding insufficient established methods to assess the quality of OSM data. Two types of representation of road networks are used. The first is primal that defines a two-dimensional graph where edges intersect only at nodes. The second is a dual presentation, where the dual graph represents roads as nodes and intersections as edges. - -The model developed an analysis of the topological errors and corrections using the following steps: layer re-projection to convert the layer into UTM; removes micro-segments using a threshold value of 1m, the vertices are pruned if the topology is maintained; removes dangles, using a threshold of 3m; performs line features snapping to a vertex a threshold of 3m; removes duplicate geometry features; removes lines features of zero length; and for any intersections, it validates closed holes and fixes node ordering. The research added functionality to convert shapefile data of the road network into a multidigraph representation. - -The results conclude that even the proprietary road data sets are not free from logical inconsistencies and data contributed by the general public is credible and navigable, although greater crowd contribution is necessary in order to improve its quality. The study developed models and scripts to assess logical consistency based on three components: geographical topological consistency; semantic information (tags); and structural topological consistency or morphological consistency. Developing easy-to-use workflow models to assess OSM data (Singh Sehra et al., 2020). - -## Motivation - -To run the process and main analysis for the project, the research team extracted data from OpenStreetMap (OSM) drawing on study region boundaries derived from local administrative boundaries and the Global Human Settlements (GHS) urban localities database. The datasets derived for each city arising from this process aim to provide consistent and even analysis of all 25 urban areas. To assess the extent to which the OSM derived dataset accurately reflects the real world, the research team devised three phases of validation, noting that phases could be conducted both iteratively and therefore concurrently. - -**Phase I** validation involved a qualitative analysis conducted by partners based in each of the 25 urban areas. A descriptive report of the preliminary assets prepared for each study region (e.g. the urban area's boundaries, distribution of amenities of interest, etc.) was reviewed by collaborators with local area knowledge. Feedback on data accuracy, completeness and suggestions for improvement was solicited through a Google Forms survey for each study region, with revisions undertaken as required based on feedback received. - -**Phase II** validation performed a quantitative analysis conducted by the researcher team for a selection of the 25 urban areas. Phase II validation compares data provided by local partners with the OSM derived data. While neither dataset is a perfect representation of reality, comparing the two helps give an understanding of which, if either, has better street coverage, and how this will impact the results of the project. Ultimately, by comparing the official datasets compiled by local partners with the OSM derived data, the hope is to understand how similar the OSM data is to reality. - -**Phase III** validation is quantitative analysis conducted by the researcher team for a selection of the 25 urban areas. By running the main analytical process on both the OSM derived datasets and the official datasets compiled by partners, it is possible to understand the material differences between the two. - -## Methods - -Given the summarized literature review, we are confident that these project's validation methods are supported. Since the initial inception of OSM data, researchers have focused their attention on developing validation methods, often analyzing and establishing a quality standard by comparing OSM data with official government datasets (Haklay 2010; Antunes et al. 2015; Zhou and Lin 2019). On other instances, statements on data quality are only possible with high-quality reference datasets (Barron et al. 2014). Other studies have focused on comparing high-resolution imagery to OSM data to estimate the percentage of overall coverage (Barrington- Leigh and Millard-Ball 2017). Assistance with automatic checking of contributions from OSM volunteers (Girres and Touya 2010) can improve quality and reliability. Existing literature has established that attribute accuracy, completeness, and geometric accuracy depend largely on referencing OSM data to more authoritative datasets (Dorn et al. 2015). - -The current study focuses on validating the quality of OSM data and the official datasets by comparing them to each other and obtaining accuracy percentages. - -Following other studies that address road networks' representation by predicting road edges and nodes with specific thresholds (Singh Sehra et al. 2020), the current research uses 10 and 50-meter buffers for the edge validation; and destination validation. An additional layer of quality assessment used by existing literature focuses on assigning weight values by creating a cell grid overlaid on the study area (Haklay 2010; Antunes et al. 2015 Barrington-Leigh and Millard-Ball 2017). The weighted averages can then serve as quality indicators that define the accuracy of OSM data. The hexagon grid (500-meter diameter) utilized in this study provides complete coverage of the areas where the validation model was tested. The subsequent weight values allow for a comparison between both datasets and serves as an additional validation layer. The specific procedure is detailed as follows. - - -For Phase II validation official datasets compiled by local partners, or official datasets, were analysed for the following cities: Belfast, Hong Kong, Olomouc, and Sao Paulo. The data was then divided into edge data and destination data. Official edge datasets include the urban street network and were compared with the OSM derived street network dataset. Official destination datasets include supermarkets and similar establishments and were compared to the OSM derived food destination dataset. - -Official edge data were collected from Belfast, Hong Kong, and Olomouc. Generally, the official edge data did not include pedestrian paths. Additionally, in Hong Kong's case, due to out-dated expression of its coordinate values, the edge data x and y coordinates were switched and needed to be corrected for analysis. In Olomouc's case, the projection metadata in the edge shapefile were inputted incorrectly as EPSG 5513 instead of EPSG 5514, leading the edge data's geographies to be found in Russia instead of the Czech Republic. These errors in projection support the use of open source data where coordinate reference systems are well-established and well-documented for reusability and replication like OSM. OSM's data has a format and expectations when inputting metadata that are standard globally. OSM makes analysis of street networks more feasible because it allows for researchers to compare ‘apples with apples'. - -Official destination data were collected from Belfast, Olomouc, and Sao Paulo. The official data for Olomouc and Sao Paulo were in point form. Each point is tied to the centroid of the parcel to which the destination corresponds. The official data for Belfast are expressed in polygon form. The polygon data from Belfast are parcel data to which different relevant destinations are tied. These parcels varied in size, with some the size of parks or other large plots of land that made it imposssible to convert the data into accurate centroids. Because the Belfast dataset are polygon data, and the destination data collected from OSM are point data, the Belfast data were not usable for accessibility analysis. Therefore, the Phase II validation for this project was only conducted using Olomouc and Sao Paulo's official destination data. Additionally, the Sao Paulo data were edited to exclude farmer's markets and restaurants so that the comparison between the Official data and the OSM data was more consistent. The official destinations from both Olomouc and Sao Paulo offiical were recorded in 2018. - -The issues in projection, destination datatype, and types of destinations included highlight the advantages of using global open source datasets like the OSM extracted data used for a project such as this. A global dataset makes global analysis feasible by enabling the use of uniform data standards and data types. - -Three scripts were used to calculate the indicators that compare the OSM derived dataset and the Official datasets. The scripts were divided by functionality and included edge validation, destination validation, and hexbin destination validation. The hexbin destination validation creates a map of hexagons over the study area of each city. Instead of comparing individual points, the hexagons are compared. - - -All three scripts function similarly, so when they are run they create a CSV of the indicators and a figure or figures of the data for each of the relevant cities. Each script defines a set of functions and then runs through, creating the indicators that are then populated in the CSV. Additionally, the data and configuration folders were accessed by all three scripts. The configuration files allow the code to be flexible in which cities are included in the analysis by accessing file paths specific to each urban area. - -The edge script has functions to load in the data, plot the data, count the total amount of edges for each dataset, count the summed total length of edge data for each dataset, and calculate the proportion of edges that overlap from one dataset to another using buffers of 10 and 50 meters to return a total of twelve indicators. - -The first function, **load data**, loads in the correct data by pulling file paths from the configuration files, and it extracts the appropriate data layers for edge analysis. Then, it ensures that all of the data is projected in the correct CRS. Next, it clips the data to the study region. Finally, it asserts that all the data is projected in the same CRS. The next function, **plot data**, creates a figure of the study area. Then, the clipped and correctly projected Official data is plotted. Next, it plots the clipped and correctly projected OSM derived data on top. This highlights where only Official edges exist. The OSM edges are plotted in yellow and the Official edges are plotted in red. The next function, **total edge length count**, finds the sum of the length of all the edges for a dataset. Then, it finds the total count of edges for the same dataset. The last function, **calculate overlap**, buffers each dataset by a predetermined buffer. Currently, the code buffers for 10 and 50 meters. Then it creates the unary union for both datasets. Third, it finds the intersection of the two unioned buffered datasets. Fourth, it divides this overlapping area with the area of the unioned buffer of each dataset. This finding becomes an indicator labeled with the appropriate dataset, area percent, and the buffer distance. For example, *osm area pct 10*, is the percent of the unioned buffered OSM edges that overlap with unioned buffered official data when all data is buffered by 10 meters. The process is then repeated, except for the percentage of the length of the edges that fall within the buffered area. This finding becomes an indicator labeled with the appropriate dataset, length percent, and the buffer distance. For example, *osm length pct 10*, is the percent of the length of unioned OSM edges that overlap with unioned buffered Official edges when they are buffered by 10 meters. - -The destination script has functions to load in the data, find the urban core, plot the data, and find the amount of overlap between destinations. - -The first function, **load data**, loads in the correct data by pulling file paths from the configuration files, and it extracts the appropriate data layers for destination analysis. Then, it ensures that all of the data is projected in the correct CRS. Next, it clips the data to the study region. Finally, it asserts that all the data is projected in the same CRS. The second function, **get core dests**, finds the geographical extents of the study area. It then finds the distance between the northernmost points and southernmost point and the distance between the easternmost and westernmost points. Next, it takes one tenth of the shorter distance. Finally, it finds the destinations within the negative buffer of this value. The third function, **plot city_data**, creates a figure of the study area. Then, the clipped and correctly projected Official data is plotted. Next, it plots the clipped and correctly projected OSM derived data on top. This highlights where only Official destinations exist. The OSM destinations are plotted in yellow and the Official destinations are plotted in red. The fourth function, **plot core data**, follows the same process, but only for destinations that occur within the negative buffered area. The fifth function, **calculate intersect**, buffers each destination from both datasets by a predetermined buffer. Currently, the code buffers for 10 and 50 meters. Then the code takes the unary union for both datasets. Next, it creates a list of buffered destinations from one dataset that intersect with a buffered destination from the other dataset. It does this for both OSM derived destinations and official destinations, so two lists are created, one populated with OSM destinations and the other Official destinations. Finally, the length of the lists are divided by the length of their corresponding datasets to find the proportion of destinations for each dataset that fall near destinations from the other dataset. - -A method for suitability analysis used a hexagon grid overlaid onto the edge layer to identify the **weight distribution** of destination points located within the city boundaries for Olomouc and Sao Paulo. The distribution of the hexagon layer was uniformly distributed according to the respective crs for each official and OSM layer. The selected diameter for each hexagon was established at 500 meters. Once the hexagon layer was set in place, the validation process identified two conditions: a “True” value if both OSM and Official destination points were present or if both were not present; and a “False” value if one destination point is present (irregardless of it being present on the OSM or Official dataset) and not the other. - -Upon identifying the location of destination points on the hexagon grid layer, a weight is given according to the percentage of OSM and Official destination points present on each hexagon. Thus, the points present for each individual dataset were then divided by the total sum of destination points present inside each hexagon. Once the percentage for each hexagon was obtained, the validation process produced five additional values. First, the average of True values, which identifies the number of hexagons with a true value divided by the total amount of hexagons. Next, the mean, which is the average of the sum of percentages of hexagons with a true value divided by the total amount of hexagons with a true weight. Third, the median of hexagons with a true weight. Fourth, the true mean, which is the share of hexagons with a true value that contain destinations points divided by the total hexagons with a true weight. And lastly, the true median from hexagons with a true value that contains destinations points. - -## Findings and Conclusions - -From the edge validation script, the following table presents the results. - -**Edge Validation Indicator Table** -| City | Total Length of OSM Edges (m) | Number of OSM Edges | Total Length of Offical Edges (m) | Number of Official Edges | Percent Area of Buffered OSM Edges Overlapping with Buffered Offical Edges (buffer = 10m) | Percent Area of Buffered Official Edges Overlapping with Buffered OSM Edges (buffer = 10m) | Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 10m) | Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 10m) | Percent Area of Buffered OSM Edges Overlapping with Buffered Offical Edges (buffer = 50m) | Percent Area of Buffered Official Edges Overlapping with Buffered OSM Edges (buffer = 50m) | Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 50m) | Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 50m) | -| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | -| Olomouc | 616000 | 14000 | 310000 | 4000 | 57.1% | 90.1% | 66.3% | 93.4% | 82.4% | 96.5% | 90.2% | 98.1% | -| Belfast | 1700000 | 26000 | 1330000 | 19000 | 70.7% | 85.2% | 75.1% | 90.7% | 87.3% | 96.2% | 90.8% | 98.1% | -| Hong Kong | 7217000 | 108000 | 2911000 | 29000 | 39.9% | 94.0% | 50.9% | 98.9% | 48.4% | 99.4% | 69.6% | 99.9% | - -Table 1 -NOTE: Column headers are simplified names of variables used in the script. The variables, in order of the columns left to right are city, osm_total_length, osm_edge_count, official_total_length, official_edge_count, osm_area_pct_10, official_area_pct_10, osm_length_pct_10, official_length_pct_10, osm_area_pct_50, official_area_pct_50, osm_length_pct_50, official_length_pct_50 - - -From these indicators, Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 10m) and Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 50m) speak to the coverage of OSM data. For all three cities more than 90 percent of the edges from the Official dataset fell within 10 meters of an edge from the OSM derived dataset. This suggests that a high majority of edges from official datasets are accounted for on the OSM derived dataset. For all three cities, more than 98 percent of the edges from the Official dataset fall within 50 meters of an edge from the OSM derived dataset. This suggests that almost every edge from official datasets was either a) accounted for on the OSM derived dataset or b) is concentrated relatively close to edges from the OSM derived dataset. This supports the validity of using OSM derived data, as it closely reflects the official datasets. - -Additionally, when comparing Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 10m) and Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 50m), it is clear that the OSM derived dataset was vastly more comprehensive than the Official data. On average, the OSM derived data had almost twice the coverage of the Official data when using length to compare. For example, in Olomouc, the OSm derived edges have a total length of 616,000 meters and the Official edges have a total length of 310,000 meters. This disparity is to be expected, as the OSM derived data includes pedestrian paths. The Official data, however, only includes roads, streets, and other auto-focused paths. - -Futhermore, the relatively low percentages of OSM derived edges shows that OSM derived edges conver areas that Official edges do not. For example, in Belfast, when buffered at a 50 meter buffer, 90.8% of the OSM derived edges overlap with Official edges. Thus, about 9% of the OSM derived edges reach places in Belfast that are not included in the Offical data. - -The high percentage of Official edges that overlap OSM derived edges signifies that the OSM derived dataset does well in providing similar coverage. The greater length of the OSM derived dataset signifies that the OSM derived dataset accounts for more pathways, and is cognizant of pedestrian only paths. The lower percentage overlap of OSM derived edges signifies the OSM derived dataset has greater coverage in the city overall. - -![Belfast Street Network Comparison](./edge/fig/street-comparison-belfast.png) - -Figure 1 - -This figure shows Belfast. It is possible to see that most of the disparities between datasets occur in areas with high OSM coverage, thereby not affecting the results of the walkability analysis. There are a few edges, however, not accounted for on the urban fringe. These edges account for approximately 2% of the total amount of edges. - -![Hong Kong Street Network Comparison](./edge/fig/street-comparison-hong_kong.png) - -Figure 2 - -This figure shows Hong Kong. It is possible to see that there are very few areas in which the OSM does not account for edges that exist in the Official data. About 99% of the edges from the Official data are within 10 meters of an edge from the OSM derived data. Only about 0.14% of edges from the Official data are further than 50 meters away from an edge from the OSM derived data. - -![Olomouc Street Network Comparison](./edge/fig/street-comparison-olomouc.png) - -Figure 3 - -This figure shows Olomouc. It is possible to see that most of the disparities between datasets occur in areas with high OSM coverage, thereby not affecting the results of the walkability analysis. There are a few edges, however, not accounted for on the urban fringe. These edges account for approximately 2% of the total amount of edges. - -**Destination Point Validation Indicator Table** -| City | Count of OSM Destinations in the Core | Count of Official Destinations in the Core | Total OSM Destinations | Total Official Destinations | Percentage of Buffered OSM Destinations that Intersect with Buffered Offical Destinations (buffer = 10m) | Percentage of Buffered Official Destinations that Intersect with Buffered OSM Destinations (buffer = 10m) | Percentage of Buffered OSM Destinations that Intersect with Buffered Offical Destinations (buffer = 50m) | Percentage of Buffered Official Destinations that Intersect with Buffered OSM Destinations (buffer = 50m) | -| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ | -| Olomouc | 51 | 36 | 60 | 50 | 0.2000 | 0.3166 | 0.5000 | 0.5166 | -| Sao Paulo | 797 | 12 | 1562 | 34 | 0.0172 | 0.0070 | 0.1350 | 0.0108 | - -Table 2 -NOTE: Column headers are simplified names of variables used in the script. The variables, in order of the columns left to right are city, osm_core_dests_count, official_core_dests_count, osm_dest_count, official_dest_count, osm_buff_overlap_count_10, official_buff_overlap_count_10, osm_buff_overlap_count_50, official_buff_overlap_count_50 - -**Hexagon Destination Point Indicator Values** -| City | Percentage of Hexagons with that have 1) neither OSM or Official Destinations or 2) both OSM or Official Destinations | Average Percentage of OSM Destinations in a Hexbin | Average Percentage of Official Destinations in a Hexbin | Average Percentage of OSM Destinations in True Hexbins | Average Percentage of Official Destinations in True Hexbins | -| ---- | ----------------- | -------- | ------------- | ------------- | ------------------ | -| Olomouc | 0.8969 | 0.1009 | 0.1050 | 0.2972 | 0.2500 | -| Sao Paulo | 0.8368 | 0.1628 | 0.0039 | 0.0526 | 0.0046 | - -Table 3 -NOTE: NOTE: Column headers are simplified names of variables used in the script. The variables, in order of the columns left to right are City, weight_percentage, osm_mean, official_mean, osm_true_mean, official_true_mean - -The destination validation script was performed in two cities: Olomouc and Sao Paulo. Destination point features include supermarkets and other markets where people are able to buy food, such as a butcher or a bakery, consistently. Farmer's Markets that only meet once a week, for example, are not included in the destination point features. In Olomouc, there is a faily similar number of destinations in both the Official and OSM derived dataset. In Sao Paulo, however, the OSM derived dataset contains 1562 destinations and the Official dataset contains 34 destinations. The original dataset provided by partners in Sao Paolo contained 939 destinations, but 905 destinations were removed from analysis because they do not provide consistent access to food. - -According to all indicators, there a relatively low overlap between the Offical and OSM derived destinations. At best, in Olomouc when buffered by 50 meters, approximately 50% of points intersect from one dataset to the other. This is understandable because of the nature of destination point features. Stores open and close at random intervals, leaving room for error in both datasets. The Official dataset, however, is more vulnerable to becoming outdated, depending on the data practices mantained by the local governing body. - -Fortunately, due to the methodology of the project, final indicators are not greatly affected by the precise location or quantity of destinations. The current methodology does not distinguish between a neighborhood that has 1 destination or 10 destinations because in both scenarios, there is access to food. According to this methodolgy, a hexgrid system was created. Each hexbin represents a small section of the city. If, in any individual hexbin, their exists niether an OSM derived destination nor an Official destination or there exists both an OSM derived destination and an Official destination, the Hexbin is considered True. The final indicators of the project more closely match for both datasets with a higher proportion of True hexbins. The results from the hexbin points script provided the percentage of hexbins for which this condition is true. In both cities, Olomouc and Sao Paulo, above 80% of hexbins follow this condition. Thus, while the datasets are fairly different, their affect on analysis is relatively similar. - - -![Olomouc Destination Comparison](./destination/fig/city_destination-comparison-olomouc.png) - -Figure 4 - -Both, the Official dataset and the OSM derived dataset for the city of Olomouc contain similar destination point features. As seen in Fig. 4, the Official dataset provided by the city of Olomouc accounts for 60 destination point features, while the OSM derived dataset accounts for 50 destination point features. - -![Sao Paulo Destination Network Comparison](./destination/fig/city_destination-comparison-sao_paulo.png) - -Figure 5 - -The Official dataset for the city of Sao Paulo accounts for only 34 total destination point features, as seen on Fig. 5, the OSM derived dataset contains a richer and more detailed destination point feature total with 1562. - -![Olomouc Hex Grid](destination/fig/hexbins-olomouc.png) - -Figure 6 - -At 89.7%, the analysis validates that for the city of Olomouc, as presented on Fig. 6, both OSM and Official datasets account and validate similar point features. This high compatibility is also validated by the results of the OSM mean and Official mean, which only differs by .005; as well as the OSM true mean and the Official true mean with a 4% difference between datasets. - -![Sao Paulo Hex Grid](./destination/fig/hexbins-sao_paulo.png) - -Figure 7 - -Although the results for the weight percentage for the city of Sao Paulo is at 83.68%, there is a high discrepancy between OSM mean and Official mean results. The 16% difference is driven in part by the total OSM destination count (1562 points) and the Official destination count (34 points). As a robustness test, the points originally taken out of the official data were put back in to the validation analysis. This addition of approximately 900 destinations does not significantly change indicator values. In both scenarios, the true weight value indicates that both OSM and Official datasets contain similar information, either destination points are present within a hexagon boundary or no destination points are present. - - -## External Validation - -### Edge -Google Maps Satellite View was used to understand what exists in spaces that contains Official edges, but not OSM edges. For each city, one example was examined. In all three examples, the edges should not be included in the analysis, as they do not represent paths that are a part of network circulation. - -In Bern, the space examined exist on the Northeastern area of the study area. When examined on Google Maps, the space appears to be an industrial facility. In Hong Kong, the space examined exist close to the center of the study area. When examined on Google Maps, the space appears to be an railroad juntion. In Olomouc, the space examined exist on the Eastern edge of the study area. When examined on Google Maps, the space appears to be an industrial facility. In all three examples, the edges included in the Official dataset, but not the OSM derived dataset, are access roads that are for private establishments. These edges should not be included in the analysis, and this demonstrates how OSM data can be more appropriate for urban accessibility analytics. - - -### Destination -For both cities, Olomouc and Sao Paulo, 20 OSM derived destinations and 20 more Official destinations were chosen at random using a numpy random selection. Each of the 80 destinations were then inspected based on their latitudes and longitudes on Google Maps Satellite View, Google Street Maps, and Yelp. In both cities, the Google Satellite Imagery was captured this year (2020). In Olomouc, Google Street View Imagery was captured anywhere from 2009-2019. IN Sao Paulo, Google Street View Imagery was more up to date, capptured between 2017-2020. Of the 40 OSM derived destinations, 37 are confirmed to be food vendors. All 3 of the false destinations occured in Olomouc. Two of the false destinations are pharmacies. One of these two pharmacies, however, still has a bakery Google Tag, with photos included, suggesting that the space was recently converted into a pharmacy. The final false destination occrred on a street with retail on the ground level, but no nearby food retailer. - -Of the 40 Official destinations, 29 are confirmed food destinations. In the 11 false destinations, five occured in Olomouc and six occured in Sao Paulo. In Olomouc, one false destination is a food stand, one false destination is a construction site, and the other three are other retail spaces. In Sao Paolo, one false destination was located on a single family home, and a different false destination was located in the middle of a large intersection with no nearby food retailers. Two of the false destinations are attached to buildings with no Google Label and no apparent entrance to the property. The other 2 are other retail spaces. - -Due to COVID-19 and geographi factors, the ground truthing could only be conducted online. These ground truthing examples show that the Official data is not completely accurate, and is possibly even less accurate than the OSM derived data, especailly in larger cities. This, along with the consistent data format present in OSM derived data, further supports the use of OSM derived data. Below are some examples of the destinations from all four datasets. - -![OSM True Example, Olomouc](./destination/fig/groundtruthing/Olomouc_OSM_Veggies.png) - -Image 1 - OSM True Example, Olomouc - -This example presents a true destination. This Veggetable Retailer was listed on the OSM derived dataset for Olomouc. - -Image captured on Google Street View - - -![OSM False Example, Olomouc](./destination/fig/groundtruthing/Olomouc_OSM_FoodPharma.png) - -Image 2 - OSM False Example, Olomouc - -This example presents a possibly false destination from the OSM derived data. This image shows the two Google Labels presented on the same single retail space. One label is for a pharmacy, and the other is for a bakery. The Google Street View imagery, captured in 2012, shows the pharmacy. In this case, it is impossible to be certain whether the location is currently a bakery or a pharmacy because the Google Street View imagery could be outdated, so for the purposes of this project, it is assumed to currently a false destination. - -Image captured on Google Maps - - -![Official False Example, Olomouc](./destination/fig/groundtruthing/Olomouc_Official_FoodStand.png) - -Image 3 - Official False Example, Olomouc - -This example presents a false destination. This Food Stand was listed on the Official dataset for Olomouc. The stand is in front of a hardware store. - -Image captured on Google Street View - - -![Official False Example, Sao Paulo](./destination/fig/groundtruthing/SP_Official_NoBuilding.png) - -Image 4 - Official False Example, Sao Paulo - -This example presents a false destination from the Sao Paulo official dataset. This lot is surrounded by walls and hedges, with no clear entrance. The structure on the lot does not seem to have walls, and there are no Google Labels attatched to it. - -Image captured on Google Street View - - -## References -Antunes, Francisco, Cidalia C Fonte, Maria Antonia Brovelli, Marco Minghini, Monia Molinari, and Peter Mooney. 2015. "Assessing OSM Road Positional Quality With Authoritative Data." VIII Conferencia Nacional de Cartografia e Geodesia. 1-8. - -Barrington-Leigh, Christopher, and Adam Millard-Ball. 2017. "The world's user-generated road map is more than 80% complete." Plos One, Aug 10. - -Barron, Christopher, Pascal Neis, and Alexander Zipf. 2014. "A Comprehensive Framework for Intrinsic OpenStreetMap Quality Analysis." 877-895. - -Dorn, Helen, Tobias Törnros, and Alexander Zipf. 2015. "Quality Evaluation of VGI Using Authoritative Data - A Comparison with Land Use Data in Southern Germany." ISPRS International Journal of Geo-Information 4: 1657-1671. - -Girres, Jean-Francois, and Guillaume Touya. 2010. "Quality Assessment of the French OpenStreetMap Dataset." Transactions in GIS, 435-459. - -Haklay, Mordechai. 2010. "How good is volunteer geographical information? A comparative study of OpenStreetMap and Ordnance Survey datasets." Environment and Planning B: Planning and Design, 682-703. - -O'Reilly, T. 2005. "O'Reilly." What Is Web 2.0. Accessed Aug 9, 2020. http://oreilly.com/web2/archive/what-is-web-20.html. - -Singh Sehra, Sukhjit, Jaiteg Singh, Hardeep Singh Rai, and Sarabjot Singh Anand. 2020. "Extending Processing Toolbox for assessing the logical consistency of OpenStreetMap data." Transactions in GIS, 44-71. - -Zhou, Qi, and Hao Lin. 2019. "Investigating the completeness and omission roads of OpenStreetMap data in Hubei, China by comparing with Street Map and Street View." ArXiv pre-print, arXiv:1909.04323. - -Zhou, Qi, and Yuanjian Tian. 2018. "The use of geometric indicators to estimate the quantitative completeness of street blocks in OpenStreetMap." Transactions in GIS 22 (6): 1550-1572. +# Geospatial Team Phase II Validation Report + +This report summarizes the Phase II validation efforts by the global indicators geospatial team. It includes a short lit review summarizing the state of the field in validating OpenStreetMap data, an overview of the team's overall validation motives and logic, and our computational methods. Finally it presents and discusses the validation findings, comparing OpenStreetMap data to official data sets from city partners in the context of how they are used to compute global indicators. While the open data unsurprisingly diverge from the official data in various ways, their overall correspondence is high and sufficient for the purposes of calculating the global indicators. + +## Literature Review + +Over the past decade, the emphasis of the internet transitioned from users consuming predefined content to users simply contributing and sharing content (O'Reilly 2005). When working with geodata, quality is often defined by pre-established parameters compiled over the years. Quality aspects in the field of geo-information were enshrined in the International Organization for Standards (IOS) codes 19113 (quality principles) and 19114 (quality evaluation procedures) with support of ISO Technical Committee 211 (Haklay 2010). + +The OpenStreetMap Project (OSM) emerged from this growing emphasis on user-generated content. OSM is a system based on volunteered geographic information (VGI). However, the quality of spatial data provided is often questioned (Girres and Touya 2010). Thus far, OSM has produced a large amount of spatial data. However, most of OSM's contributors are volunteers or aficionados that focus on their fields of interest (Dorn et al. 2015). Many of those contributors lack training in geographical information science standards and methods. This leads to concerns regarding the data quality (Singh Sehra et al. 2020). Numerous scientific studies focused on evaluating OSM data quality. Over time, various approaches have been developed as technological advancements provided new tools producing more complex quality assessment methods. + +OSM started in London in August of 2004. One early study by Haklay (2010) utilizes London (metropolitan area) and England (country area) as its two study areas. The research focused on analyzing its quality through a comparison with Ordinance Survey datasets. An evaluation of the positional accuracy, attribute accuracy, completeness, and consistency provided an early indication of the quality of VGI. + +For this study, two elements of the possible range of quality were measured: positional accuracy and completeness. For comparison, only streets and roads were used. These are the main features collected by OSM volunteers. Junctions were collapsed to single nodes and multi-carriageways to individual links. High-resolution mapping (1:1250 urban areas, 1:2500 in rural areas, 1:10 000 in moorland), avoiding minor roads and cul-de-sacs. A grid at a resolution of 1 km was created across England. The rest of the analysis was carried out through SQL queries, which added up the length of lines that were contained in or intersected the grid cells. The results demonstrated VGI was able to reach very good spatial quality. However, the inconsistency of VGI in terms of quality demonstrated the digital and social divide of VGI. Rural areas and poorer areas evidenced a lack of coverage (Haklay 2010). + +In order to assess the completeness of OSM data, a visual comparison with aerial imagery, and fitting parametric models regarding the historical growth of the OSM street network was presented in 2017 by Barrington-Leigh and Millard-Ball. Their study found that globally, OSM is 83% complete, and more than 40% of countries have fully mapped street networks. The most notable finding is that completeness has a U-shaped relationship with density. Inter-urban roads that traverse areas with minimal population are primarily present in OSM and high-density regions with a large number of contributors. Communities that are most likely to have missing streets are smaller towns and villages. After obtaining estimates of completeness, the length of the road network in each country was obtained by dividing the existing length of mapped roads in OSM by the estimated fraction complete. The visual assessment was based on a stratified and probability-weighted sample of 45 points in each country. The sampling algorithm in QGIS selected a random point and overlays streets in the OSM database against aerial or satellite imagery provided by Google through the OpenLayersplugin, at a scale of 1:5000. The model also provided estimates of the number of road edges, which were then used to weight each grid cell when aggregating the grid-cell fraction complete predictions to the country level (Barrington-Leigh and Millard-Ball 2017). + +Extending the previous work by Haklay (2010), an article that studies the quality of French OpenStreetMap data provides a larger set of spatial data quality element assessments and uses different quality control methods. Comparisons were made between the OSM data and BD TOPO Large Scale Referential (RGE) data (reference datasets with a metric resolution). These were used to assess: geometric accuracy; attribute accuracy; completeness; logical consistency; semantic accuracy; temporal accuracy; lineage; and usage. The results raise questions such as the heterogeneity of processes, scales of production, and the compliance to standardized and accepted specifications limiting the possible applications. Finding a balance between specifications and contributor freedom is raised, proposing new research such as contributors' assistance with automatic checking of contributions (Girres and Touya 2010). + +As a result, a framework containing more than 25 methods and indicators is presented. This framework allows OSM quality assessments based solely on the data's history (OSM-Full- History-Dump). In lieu of a reference dataset, approximate statements on OSM data quality are possible. No ground truth reference dataset is deployed for OSM data quality evaluation. Instead, an alternate approach is used in specified areas within OSM. This approach can be evaluated by investigating the data's historical development and comparing features' characteristics at different timestamps. In order to assess the OSM data, the calculated results of the iOSMAnalyzer are divided into the following categories: fitness for purpose; general information on the study area; routing and navigation; geocoding; points of interest-search; map-applications; and user information and behavior. The calculated results give a compact quality overview of a freely selectable area. Quality depends on the individual use case, and the OSM data is evaluated in terms of fitness for purpose. However, absolute statements on data quality are only possible with a high-quality reference dataset as a basis for comparison. The study revealed that the interpretation of quality indicators is facilitated and supported by means of contributor activity (Barron et al., 2014). + +Multiple studies have focused on the completeness of OSM road datasets. Using both Street Map and Street View, Zhou and Lin (2019), focus on determining OSM road completeness and omission roads. An omitted road is classified into three types: public roads; private roads; and roads for non-motorized vehicles. + +The study employs an approach proposed by Zhou and Tian (2018). This approach includes the use of geometric indicators to estimate the quantitative completeness of street blocks in OSM. The authors analyze the completeness of street blocks in an OSM dataset by comparing them with a reference map. The method extracts OSM road datasets and converts them into several street blocks that are then visually compared with the Baidu Street Map. The analysis of omission roads is then determined by randomly selecting 60 incomplete street block from the OSM road dataset, overlapping it with the corresponding Baidu Street Map, and then manually digitizing all the omission roads in each of these street blocks. + +The research results indicate that most of the omitted roads were private roads, or one single lane, public roads, of lower importance within the urban road network. For 13 out of the 16 prefecture-level divisions, street block completeness values were lower than 40%, and the maximum value was only 55%. However, in roads with traffic conditions, 14 out of the 16 prefectures, street block completeness values were higher than 80%. These values indicate that major roads have been adequately mapped. The results also suggest that in terms of road length, approximately 90% of omission roads were either public roads or one private lane roads, of which no more than 10% were for non-motorized vehicles (Zhou and Lin 2019). + +A similar approach is taken by Antunes et al. (2015). In the study, they assessed the positional differences between the road-network available in OSM for some regions of the Coimbra Municipality in Portugal, and the data provided by the Coimbra City Hall, as reference (REF). A subset of the original OSM is extracted so that its line features have a direct correspondent in REF; discrepancies are then removed. This process is achieved by applying a buffer around REF and comparing the angular coefficients of REF and OSM line features. Finally, by returning, per cell, the length and length percentage of OSM having a deviation smaller than a user-specified threshold value, and the maximum deviation between OSM and REF datasets (Antunes et al. 2015). + +A study conducted by Dorn et al. in Southern Germany, focuses on two spatial data quality elements: thematic accuracy and completeness area addressed by comparing the OSM data with an authoritative German reference dataset. They were investigating the accuracy of VGI, derived from the OSM dataset. The study area is the Rhine- Neckar region, located in southern Germany. The comparison is executed through a semantic harmonization and a polygon preprocessing part that leads to an area related map comparison with a confusion matrix. Inconsistencies were previously solved to allow comparisons using kappa statistics or Cohen's kappa coefficients after merging all polygons. The kappa value indicates a substantial agreement between both datasets, quantifying the agreement between images. The DLM data shows a large area is covered by farmland and forest. There are definite variations between each location. The forest area presents the highest accuracy and completeness (97.6%) and correctness (95.1%), while the farmland indicates low completeness (45.9%) but high correctness (94.8%). The western part of the study area is more urbanized and, therefore, well mapped. This condition may explain why the eastern section still lacks completeness. The quality of OSM land use and land cover features varies between the investigated classes (Dorn et al., 2015). + +Extending the Quantum GIS processing toolbox's capabilities for assessing spatial data, a study by Singh Sehra et al. addresses the research gap regarding insufficient established methods to assess the quality of OSM data. Two types of representation of road networks are used. The first is primal that defines a two-dimensional graph where edges intersect only at nodes. The second is a dual presentation, where the dual graph represents roads as nodes and intersections as edges. + +The model developed an analysis of the topological errors and corrections using the following steps: layer re-projection to convert the layer into UTM; removes micro-segments using a threshold value of 1m, the vertices are pruned if the topology is maintained; removes dangles, using a threshold of 3m; performs line features snapping to a vertex a threshold of 3m; removes duplicate geometry features; removes lines features of zero length; and for any intersections, it validates closed holes and fixes node ordering. The research added functionality to convert shapefile data of the road network into a multidigraph representation. + +The results conclude that even the proprietary road data sets are not free from logical inconsistencies and data contributed by the general public is credible and navigable, although greater crowd contribution is necessary in order to improve its quality. The study developed models and scripts to assess logical consistency based on three components: geographical topological consistency; semantic information (tags); and structural topological consistency or morphological consistency. Developing easy-to-use workflow models to assess OSM data (Singh Sehra et al., 2020). + +## Motivation + +To run the process and main analysis for the project, the research team extracted data from OpenStreetMap (OSM) drawing on study region boundaries derived from local administrative boundaries and the Global Human Settlements (GHS) urban localities database. The datasets derived for each city arising from this process aim to provide consistent and even analysis of all 25 urban areas. To assess the extent to which the OSM derived dataset accurately reflects the real world, the research team devised three phases of validation, noting that phases could be conducted both iteratively and therefore concurrently. + +**Phase I** validation involved a qualitative analysis conducted by partners based in each of the 25 urban areas. A descriptive report of the preliminary assets prepared for each study region (e.g. the urban area's boundaries, distribution of amenities of interest, etc.) was reviewed by collaborators with local area knowledge. Feedback on data accuracy, completeness and suggestions for improvement was solicited through a Google Forms survey for each study region, with revisions undertaken as required based on feedback received. + +**Phase II** validation performed a quantitative analysis conducted by the researcher team for a selection of the 25 urban areas. Phase II validation compares data provided by local partners with the OSM derived data. While neither dataset is a perfect representation of reality, comparing the two helps give an understanding of which, if either, has better street coverage, and how this will impact the results of the project. Ultimately, by comparing the official datasets compiled by local partners with the OSM derived data, the hope is to understand how similar the OSM data is to reality. + +**Phase III** validation is quantitative analysis conducted by the researcher team for a selection of the 25 urban areas. By running the main analytical process on both the OSM derived datasets and the official datasets compiled by partners, it is possible to understand the material differences between the two. + +## Methods + +Given the summarized literature review, we are confident that these project's validation methods are supported. Since the initial inception of OSM data, researchers have focused their attention on developing validation methods, often analyzing and establishing a quality standard by comparing OSM data with official government datasets (Haklay 2010; Antunes et al. 2015; Zhou and Lin 2019). On other instances, statements on data quality are only possible with high-quality reference datasets (Barron et al. 2014). Other studies have focused on comparing high-resolution imagery to OSM data to estimate the percentage of overall coverage (Barrington- Leigh and Millard-Ball 2017). Assistance with automatic checking of contributions from OSM volunteers (Girres and Touya 2010) can improve quality and reliability. Existing literature has established that attribute accuracy, completeness, and geometric accuracy depend largely on referencing OSM data to more authoritative datasets (Dorn et al. 2015). + +The current study focuses on validating the quality of OSM data and the official datasets by comparing them to each other and obtaining accuracy percentages. + +Following other studies that address road networks' representation by predicting road edges and nodes with specific thresholds (Singh Sehra et al. 2020), the current research uses 10 and 50-meter buffers for the edge validation; and destination validation. An additional layer of quality assessment used by existing literature focuses on assigning weight values by creating a cell grid overlaid on the study area (Haklay 2010; Antunes et al. 2015 Barrington-Leigh and Millard-Ball 2017). The weighted averages can then serve as quality indicators that define the accuracy of OSM data. The hexagon grid (500-meter diameter) utilized in this study provides complete coverage of the areas where the validation model was tested. The subsequent weight values allow for a comparison between both datasets and serves as an additional validation layer. The specific procedure is detailed as follows. + + +For Phase II validation official datasets compiled by local partners, or official datasets, were analysed for the following cities: Belfast, Hong Kong, Olomouc, and Sao Paulo. The data was then divided into edge data and destination data. Official edge datasets include the urban street network and were compared with the OSM derived street network dataset. Official destination datasets include supermarkets and similar establishments and were compared to the OSM derived food destination dataset. + +Official edge data were collected from Belfast, Hong Kong, and Olomouc. Generally, the official edge data did not include pedestrian paths. Additionally, in Hong Kong's case, due to out-dated expression of its coordinate values, the edge data x and y coordinates were switched and needed to be corrected for analysis. In Olomouc's case, the projection metadata in the edge shapefile were inputted incorrectly as EPSG 5513 instead of EPSG 5514, leading the edge data's geographies to be found in Russia instead of the Czech Republic. These errors in projection support the use of open source data where coordinate reference systems are well-established and well-documented for reusability and replication like OSM. OSM's data has a format and expectations when inputting metadata that are standard globally. OSM makes analysis of street networks more feasible because it allows for researchers to compare ‘apples with apples'. + +Official destination data were collected from Belfast, Olomouc, and Sao Paulo. The official data for Olomouc and Sao Paulo were in point form. Each point is tied to the centroid of the parcel to which the destination corresponds. The official data for Belfast are expressed in polygon form. The polygon data from Belfast are parcel data to which different relevant destinations are tied. These parcels varied in size, with some the size of parks or other large plots of land that made it imposssible to convert the data into accurate centroids. Because the Belfast dataset are polygon data, and the destination data collected from OSM are point data, the Belfast data were not usable for accessibility analysis. Therefore, the Phase II validation for this project was only conducted using Olomouc and Sao Paulo's official destination data. Additionally, the Sao Paulo data were edited to exclude farmer's markets and restaurants so that the comparison between the Official data and the OSM data was more consistent. The official destinations from both Olomouc and Sao Paulo offiical were recorded in 2018. + +The issues in projection, destination datatype, and types of destinations included highlight the advantages of using global open source datasets like the OSM extracted data used for a project such as this. A global dataset makes global analysis feasible by enabling the use of uniform data standards and data types. + +Three scripts were used to calculate the indicators that compare the OSM derived dataset and the Official datasets. The scripts were divided by functionality and included edge validation, destination validation, and hexbin destination validation. The hexbin destination validation creates a map of hexagons over the study area of each city. Instead of comparing individual points, the hexagons are compared. + + +All three scripts function similarly, so when they are run they create a CSV of the indicators and a figure or figures of the data for each of the relevant cities. Each script defines a set of functions and then runs through, creating the indicators that are then populated in the CSV. Additionally, the data and configuration folders were accessed by all three scripts. The configuration files allow the code to be flexible in which cities are included in the analysis by accessing file paths specific to each urban area. + +The edge script has functions to load in the data, plot the data, count the total amount of edges for each dataset, count the summed total length of edge data for each dataset, and calculate the proportion of edges that overlap from one dataset to another using buffers of 10 and 50 meters to return a total of twelve indicators. + +The first function, **load data**, loads in the correct data by pulling file paths from the configuration files, and it extracts the appropriate data layers for edge analysis. Then, it ensures that all of the data is projected in the correct CRS. Next, it clips the data to the study region. Finally, it asserts that all the data is projected in the same CRS. The next function, **plot data**, creates a figure of the study area. Then, the clipped and correctly projected Official data is plotted. Next, it plots the clipped and correctly projected OSM derived data on top. This highlights where only Official edges exist. The OSM edges are plotted in yellow and the Official edges are plotted in red. The next function, **total edge length count**, finds the sum of the length of all the edges for a dataset. Then, it finds the total count of edges for the same dataset. The last function, **calculate overlap**, buffers each dataset by a predetermined buffer. Currently, the code buffers for 10 and 50 meters. Then it creates the unary union for both datasets. Third, it finds the intersection of the two unioned buffered datasets. Fourth, it divides this overlapping area with the area of the unioned buffer of each dataset. This finding becomes an indicator labeled with the appropriate dataset, area percent, and the buffer distance. For example, *osm area pct 10*, is the percent of the unioned buffered OSM edges that overlap with unioned buffered official data when all data is buffered by 10 meters. The process is then repeated, except for the percentage of the length of the edges that fall within the buffered area. This finding becomes an indicator labeled with the appropriate dataset, length percent, and the buffer distance. For example, *osm length pct 10*, is the percent of the length of unioned OSM edges that overlap with unioned buffered Official edges when they are buffered by 10 meters. + +The destination script has functions to load in the data, find the urban core, plot the data, and find the amount of overlap between destinations. + +The first function, **load data**, loads in the correct data by pulling file paths from the configuration files, and it extracts the appropriate data layers for destination analysis. Then, it ensures that all of the data is projected in the correct CRS. Next, it clips the data to the study region. Finally, it asserts that all the data is projected in the same CRS. The second function, **get core dests**, finds the geographical extents of the study area. It then finds the distance between the northernmost points and southernmost point and the distance between the easternmost and westernmost points. Next, it takes one tenth of the shorter distance. Finally, it finds the destinations within the negative buffer of this value. The third function, **plot city_data**, creates a figure of the study area. Then, the clipped and correctly projected Official data is plotted. Next, it plots the clipped and correctly projected OSM derived data on top. This highlights where only Official destinations exist. The OSM destinations are plotted in yellow and the Official destinations are plotted in red. The fourth function, **plot core data**, follows the same process, but only for destinations that occur within the negative buffered area. The fifth function, **calculate intersect**, buffers each destination from both datasets by a predetermined buffer. Currently, the code buffers for 10 and 50 meters. Then the code takes the unary union for both datasets. Next, it creates a list of buffered destinations from one dataset that intersect with a buffered destination from the other dataset. It does this for both OSM derived destinations and official destinations, so two lists are created, one populated with OSM destinations and the other Official destinations. Finally, the length of the lists are divided by the length of their corresponding datasets to find the proportion of destinations for each dataset that fall near destinations from the other dataset. + +A method for suitability analysis used a hexagon grid overlaid onto the edge layer to identify the **weight distribution** of destination points located within the city boundaries for Olomouc and Sao Paulo. The distribution of the hexagon layer was uniformly distributed according to the respective crs for each official and OSM layer. The selected diameter for each hexagon was established at 500 meters. Once the hexagon layer was set in place, the validation process identified two conditions: a “True” value if both OSM and Official destination points were present or if both were not present; and a “False” value if one destination point is present (irregardless of it being present on the OSM or Official dataset) and not the other. + +Upon identifying the location of destination points on the hexagon grid layer, a weight is given according to the percentage of OSM and Official destination points present on each hexagon. Thus, the points present for each individual dataset were then divided by the total sum of destination points present inside each hexagon. Once the percentage for each hexagon was obtained, the validation process produced five additional values. First, the average of True values, which identifies the number of hexagons with a true value divided by the total amount of hexagons. Next, the mean, which is the average of the sum of percentages of hexagons with a true value divided by the total amount of hexagons with a true weight. Third, the median of hexagons with a true weight. Fourth, the true mean, which is the share of hexagons with a true value that contain destinations points divided by the total hexagons with a true weight. And lastly, the true median from hexagons with a true value that contains destinations points. + +## Findings and Conclusions + +From the edge validation script, the following table presents the results. + +**Edge Validation Indicator Table** +| City | Total Length of OSM Edges (m) | Number of OSM Edges | Total Length of Offical Edges (m) | Number of Official Edges | Percent Area of Buffered OSM Edges Overlapping with Buffered Offical Edges (buffer = 10m) | Percent Area of Buffered Official Edges Overlapping with Buffered OSM Edges (buffer = 10m) | Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 10m) | Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 10m) | Percent Area of Buffered OSM Edges Overlapping with Buffered Offical Edges (buffer = 50m) | Percent Area of Buffered Official Edges Overlapping with Buffered OSM Edges (buffer = 50m) | Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 50m) | Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 50m) | +| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | +| Olomouc | 616000 | 14000 | 310000 | 4000 | 57.1% | 90.1% | 66.3% | 93.4% | 82.4% | 96.5% | 90.2% | 98.1% | +| Belfast | 1700000 | 26000 | 1330000 | 19000 | 70.7% | 85.2% | 75.1% | 90.7% | 87.3% | 96.2% | 90.8% | 98.1% | +| Hong Kong | 7217000 | 108000 | 2911000 | 29000 | 39.9% | 94.0% | 50.9% | 98.9% | 48.4% | 99.4% | 69.6% | 99.9% | + +Table 1 +NOTE: Column headers are simplified names of variables used in the script. The variables, in order of the columns left to right are city, osm_total_length, osm_edge_count, official_total_length, official_edge_count, osm_area_pct_10, official_area_pct_10, osm_length_pct_10, official_length_pct_10, osm_area_pct_50, official_area_pct_50, osm_length_pct_50, official_length_pct_50 + + +From these indicators, Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 10m) and Percent Length of Official Edges that Overlap with Buffered OSM Edges (buffer = 50m) speak to the coverage of OSM data. For all three cities more than 90 percent of the edges from the Official dataset fell within 10 meters of an edge from the OSM derived dataset. This suggests that a high majority of edges from official datasets are accounted for on the OSM derived dataset. For all three cities, more than 98 percent of the edges from the Official dataset fall within 50 meters of an edge from the OSM derived dataset. This suggests that almost every edge from official datasets was either a) accounted for on the OSM derived dataset or b) is concentrated relatively close to edges from the OSM derived dataset. This supports the validity of using OSM derived data, as it closely reflects the official datasets. + +Additionally, when comparing Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 10m) and Percent Length of OSM Edges that Overlap with Buffered Official Edges (buffer = 50m), it is clear that the OSM derived dataset was vastly more comprehensive than the Official data. On average, the OSM derived data had almost twice the coverage of the Official data when using length to compare. For example, in Olomouc, the OSm derived edges have a total length of 616,000 meters and the Official edges have a total length of 310,000 meters. This disparity is to be expected, as the OSM derived data includes pedestrian paths. The Official data, however, only includes roads, streets, and other auto-focused paths. + +Futhermore, the relatively low percentages of OSM derived edges shows that OSM derived edges conver areas that Official edges do not. For example, in Belfast, when buffered at a 50 meter buffer, 90.8% of the OSM derived edges overlap with Official edges. Thus, about 9% of the OSM derived edges reach places in Belfast that are not included in the Offical data. + +The high percentage of Official edges that overlap OSM derived edges signifies that the OSM derived dataset does well in providing similar coverage. The greater length of the OSM derived dataset signifies that the OSM derived dataset accounts for more pathways, and is cognizant of pedestrian only paths. The lower percentage overlap of OSM derived edges signifies the OSM derived dataset has greater coverage in the city overall. + +![Belfast Street Network Comparison](./edge/fig/street-comparison-belfast.png) + +Figure 1 + +This figure shows Belfast. It is possible to see that most of the disparities between datasets occur in areas with high OSM coverage, thereby not affecting the results of the walkability analysis. There are a few edges, however, not accounted for on the urban fringe. These edges account for approximately 2% of the total amount of edges. + +![Hong Kong Street Network Comparison](./edge/fig/street-comparison-hong_kong.png) + +Figure 2 + +This figure shows Hong Kong. It is possible to see that there are very few areas in which the OSM does not account for edges that exist in the Official data. About 99% of the edges from the Official data are within 10 meters of an edge from the OSM derived data. Only about 0.14% of edges from the Official data are further than 50 meters away from an edge from the OSM derived data. + +![Olomouc Street Network Comparison](./edge/fig/street-comparison-olomouc.png) + +Figure 3 + +This figure shows Olomouc. It is possible to see that most of the disparities between datasets occur in areas with high OSM coverage, thereby not affecting the results of the walkability analysis. There are a few edges, however, not accounted for on the urban fringe. These edges account for approximately 2% of the total amount of edges. + +**Destination Point Validation Indicator Table** +| City | Count of OSM Destinations in the Core | Count of Official Destinations in the Core | Total OSM Destinations | Total Official Destinations | Percentage of Buffered OSM Destinations that Intersect with Buffered Offical Destinations (buffer = 10m) | Percentage of Buffered Official Destinations that Intersect with Buffered OSM Destinations (buffer = 10m) | Percentage of Buffered OSM Destinations that Intersect with Buffered Offical Destinations (buffer = 50m) | Percentage of Buffered Official Destinations that Intersect with Buffered OSM Destinations (buffer = 50m) | +| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ | +| Olomouc | 51 | 36 | 60 | 50 | 0.2000 | 0.3166 | 0.5000 | 0.5166 | +| Sao Paulo | 797 | 12 | 1562 | 34 | 0.0172 | 0.0070 | 0.1350 | 0.0108 | + +Table 2 +NOTE: Column headers are simplified names of variables used in the script. The variables, in order of the columns left to right are city, osm_core_dests_count, official_core_dests_count, osm_dest_count, official_dest_count, osm_buff_overlap_count_10, official_buff_overlap_count_10, osm_buff_overlap_count_50, official_buff_overlap_count_50 + +**Hexagon Destination Point Indicator Values** +| City | Percentage of Hexagons with that have 1) neither OSM or Official Destinations or 2) both OSM or Official Destinations | Average Percentage of OSM Destinations in a Hexbin | Average Percentage of Official Destinations in a Hexbin | Average Percentage of OSM Destinations in True Hexbins | Average Percentage of Official Destinations in True Hexbins | +| ---- | ----------------- | -------- | ------------- | ------------- | ------------------ | +| Olomouc | 0.8969 | 0.1009 | 0.1050 | 0.2972 | 0.2500 | +| Sao Paulo | 0.8368 | 0.1628 | 0.0039 | 0.0526 | 0.0046 | + +Table 3 +NOTE: NOTE: Column headers are simplified names of variables used in the script. The variables, in order of the columns left to right are City, weight_percentage, osm_mean, official_mean, osm_true_mean, official_true_mean + +The destination validation script was performed in two cities: Olomouc and Sao Paulo. Destination point features include supermarkets and other markets where people are able to buy food, such as a butcher or a bakery, consistently. Farmer's Markets that only meet once a week, for example, are not included in the destination point features. In Olomouc, there is a faily similar number of destinations in both the Official and OSM derived dataset. In Sao Paulo, however, the OSM derived dataset contains 1562 destinations and the Official dataset contains 34 destinations. The original dataset provided by partners in Sao Paolo contained 939 destinations, but 905 destinations were removed from analysis because they do not provide consistent access to food. + +According to all indicators, there a relatively low overlap between the Offical and OSM derived destinations. At best, in Olomouc when buffered by 50 meters, approximately 50% of points intersect from one dataset to the other. This is understandable because of the nature of destination point features. Stores open and close at random intervals, leaving room for error in both datasets. The Official dataset, however, is more vulnerable to becoming outdated, depending on the data practices mantained by the local governing body. + +Fortunately, due to the methodology of the project, final indicators are not greatly affected by the precise location or quantity of destinations. The current methodology does not distinguish between a neighborhood that has 1 destination or 10 destinations because in both scenarios, there is access to food. According to this methodolgy, a hexgrid system was created. Each hexbin represents a small section of the city. If, in any individual hexbin, their exists niether an OSM derived destination nor an Official destination or there exists both an OSM derived destination and an Official destination, the Hexbin is considered True. The final indicators of the project more closely match for both datasets with a higher proportion of True hexbins. The results from the hexbin points script provided the percentage of hexbins for which this condition is true. In both cities, Olomouc and Sao Paulo, above 80% of hexbins follow this condition. Thus, while the datasets are fairly different, their affect on analysis is relatively similar. + + +![Olomouc Destination Comparison](./destination/fig/city_destination-comparison-olomouc.png) + +Figure 4 + +Both, the Official dataset and the OSM derived dataset for the city of Olomouc contain similar destination point features. As seen in Fig. 4, the Official dataset provided by the city of Olomouc accounts for 60 destination point features, while the OSM derived dataset accounts for 50 destination point features. + +![Sao Paulo Destination Network Comparison](./destination/fig/city_destination-comparison-sao_paulo.png) + +Figure 5 + +The Official dataset for the city of Sao Paulo accounts for only 34 total destination point features, as seen on Fig. 5, the OSM derived dataset contains a richer and more detailed destination point feature total with 1562. + +![Olomouc Hex Grid](destination/fig/hexbins-olomouc.png) + +Figure 6 + +At 89.7%, the analysis validates that for the city of Olomouc, as presented on Fig. 6, both OSM and Official datasets account and validate similar point features. This high compatibility is also validated by the results of the OSM mean and Official mean, which only differs by .005; as well as the OSM true mean and the Official true mean with a 4% difference between datasets. + +![Sao Paulo Hex Grid](./destination/fig/hexbins-sao_paulo.png) + +Figure 7 + +Although the results for the weight percentage for the city of Sao Paulo is at 83.68%, there is a high discrepancy between OSM mean and Official mean results. The 16% difference is driven in part by the total OSM destination count (1562 points) and the Official destination count (34 points). As a robustness test, the points originally taken out of the official data were put back in to the validation analysis. This addition of approximately 900 destinations does not significantly change indicator values. In both scenarios, the true weight value indicates that both OSM and Official datasets contain similar information, either destination points are present within a hexagon boundary or no destination points are present. + + +## External Validation + +### Edge +Google Maps Satellite View was used to understand what exists in spaces that contains Official edges, but not OSM edges. For each city, one example was examined. In all three examples, the edges should not be included in the analysis, as they do not represent paths that are a part of network circulation. + +In Bern, the space examined exist on the Northeastern area of the study area. When examined on Google Maps, the space appears to be an industrial facility. In Hong Kong, the space examined exist close to the center of the study area. When examined on Google Maps, the space appears to be an railroad juntion. In Olomouc, the space examined exist on the Eastern edge of the study area. When examined on Google Maps, the space appears to be an industrial facility. In all three examples, the edges included in the Official dataset, but not the OSM derived dataset, are access roads that are for private establishments. These edges should not be included in the analysis, and this demonstrates how OSM data can be more appropriate for urban accessibility analytics. + + +### Destination +For both cities, Olomouc and Sao Paulo, 20 OSM derived destinations and 20 more Official destinations were chosen at random using a numpy random selection. Each of the 80 destinations were then inspected based on their latitudes and longitudes on Google Maps Satellite View, Google Street Maps, and Yelp. In both cities, the Google Satellite Imagery was captured this year (2020). In Olomouc, Google Street View Imagery was captured anywhere from 2009-2019. IN Sao Paulo, Google Street View Imagery was more up to date, capptured between 2017-2020. Of the 40 OSM derived destinations, 37 are confirmed to be food vendors. All 3 of the false destinations occured in Olomouc. Two of the false destinations are pharmacies. One of these two pharmacies, however, still has a bakery Google Tag, with photos included, suggesting that the space was recently converted into a pharmacy. The final false destination occrred on a street with retail on the ground level, but no nearby food retailer. + +Of the 40 Official destinations, 29 are confirmed food destinations. In the 11 false destinations, five occured in Olomouc and six occured in Sao Paulo. In Olomouc, one false destination is a food stand, one false destination is a construction site, and the other three are other retail spaces. In Sao Paolo, one false destination was located on a single family home, and a different false destination was located in the middle of a large intersection with no nearby food retailers. Two of the false destinations are attached to buildings with no Google Label and no apparent entrance to the property. The other 2 are other retail spaces. + +Due to COVID-19 and geographi factors, the ground truthing could only be conducted online. These ground truthing examples show that the Official data is not completely accurate, and is possibly even less accurate than the OSM derived data, especailly in larger cities. This, along with the consistent data format present in OSM derived data, further supports the use of OSM derived data. Below are some examples of the destinations from all four datasets. + +![OSM True Example, Olomouc](./destination/fig/groundtruthing/Olomouc_OSM_Veggies.png) + +Image 1 - OSM True Example, Olomouc + +This example presents a true destination. This Veggetable Retailer was listed on the OSM derived dataset for Olomouc. + +Image captured on Google Street View + + +![OSM False Example, Olomouc](./destination/fig/groundtruthing/Olomouc_OSM_FoodPharma.png) + +Image 2 - OSM False Example, Olomouc + +This example presents a possibly false destination from the OSM derived data. This image shows the two Google Labels presented on the same single retail space. One label is for a pharmacy, and the other is for a bakery. The Google Street View imagery, captured in 2012, shows the pharmacy. In this case, it is impossible to be certain whether the location is currently a bakery or a pharmacy because the Google Street View imagery could be outdated, so for the purposes of this project, it is assumed to currently a false destination. + +Image captured on Google Maps + + +![Official False Example, Olomouc](./destination/fig/groundtruthing/Olomouc_Official_FoodStand.png) + +Image 3 - Official False Example, Olomouc + +This example presents a false destination. This Food Stand was listed on the Official dataset for Olomouc. The stand is in front of a hardware store. + +Image captured on Google Street View + + +![Official False Example, Sao Paulo](./destination/fig/groundtruthing/SP_Official_NoBuilding.png) + +Image 4 - Official False Example, Sao Paulo + +This example presents a false destination from the Sao Paulo official dataset. This lot is surrounded by walls and hedges, with no clear entrance. The structure on the lot does not seem to have walls, and there are no Google Labels attatched to it. + +Image captured on Google Street View + + +## References +Antunes, Francisco, Cidalia C Fonte, Maria Antonia Brovelli, Marco Minghini, Monia Molinari, and Peter Mooney. 2015. "Assessing OSM Road Positional Quality With Authoritative Data." VIII Conferencia Nacional de Cartografia e Geodesia. 1-8. + +Barrington-Leigh, Christopher, and Adam Millard-Ball. 2017. "The world's user-generated road map is more than 80% complete." Plos One, Aug 10. + +Barron, Christopher, Pascal Neis, and Alexander Zipf. 2014. "A Comprehensive Framework for Intrinsic OpenStreetMap Quality Analysis." 877-895. + +Dorn, Helen, Tobias Törnros, and Alexander Zipf. 2015. "Quality Evaluation of VGI Using Authoritative Data - A Comparison with Land Use Data in Southern Germany." ISPRS International Journal of Geo-Information 4: 1657-1671. + +Girres, Jean-Francois, and Guillaume Touya. 2010. "Quality Assessment of the French OpenStreetMap Dataset." Transactions in GIS, 435-459. + +Haklay, Mordechai. 2010. "How good is volunteer geographical information? A comparative study of OpenStreetMap and Ordnance Survey datasets." Environment and Planning B: Planning and Design, 682-703. + +O'Reilly, T. 2005. "O'Reilly." What Is Web 2.0. Accessed Aug 9, 2020. http://oreilly.com/web2/archive/what-is-web-20.html. + +Singh Sehra, Sukhjit, Jaiteg Singh, Hardeep Singh Rai, and Sarabjot Singh Anand. 2020. "Extending Processing Toolbox for assessing the logical consistency of OpenStreetMap data." Transactions in GIS, 44-71. + +Zhou, Qi, and Hao Lin. 2019. "Investigating the completeness and omission roads of OpenStreetMap data in Hubei, China by comparing with Street Map and Street View." ArXiv pre-print, arXiv:1909.04323. + +Zhou, Qi, and Yuanjian Tian. 2018. "The use of geometric indicators to estimate the quantitative completeness of street blocks in OpenStreetMap." Transactions in GIS 22 (6): 1550-1572. diff --git a/win-docker-bash.bat b/win-docker-bash.bat index e4dfdd9e..ff9ef68a 100644 --- a/win-docker-bash.bat +++ b/win-docker-bash.bat @@ -1,3 +1,3 @@ -docker pull gboeing/global-indicators:latest -git pull -docker run --rm -it --name=global-indicators --shm-size=2g --net=host -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash +docker pull gboeing/global-indicators:latest +git pull +docker run --rm -it --name=global-indicators --shm-size=2g --net=host -v "%cd%":/home/jovyan/work gboeing/global-indicators /bin/bash