Skip to content

Commit

Permalink
Merge pull request #1224 from CartoDB/alasarr/grid_polyfill
Browse files Browse the repository at this point in the history
Grid polyfill
  • Loading branch information
oleurud committed Nov 25, 2019
2 parents b667955 + 9c232cf commit 5f6487e
Show file tree
Hide file tree
Showing 8 changed files with 514 additions and 1 deletion.
Empty file.
29 changes: 29 additions & 0 deletions cartoframes/analysis/grid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import mercantile
from shapely.geometry import box
import pandas as pd
from cartoframes import CartoDataFrame


class QuadGrid():

def polyfill(self, input_gdf, zoom_level):

dfs = []

for _, row in input_gdf.iterrows():
bounds = row['geometry'].bounds
tiles = mercantile.tiles(bounds[0], bounds[1], bounds[2], bounds[3], zoom_level)
resp = []
for t in tiles:
r = row.copy()
geometry = box(*mercantile.bounds(t))
if geometry.intersects(row['geometry']):
r['geometry'] = geometry
r['quadkey'] = mercantile.quadkey(t)
resp.append(r)

dfs.append(pd.DataFrame(resp))

cdf = CartoDataFrame(pd.concat(dfs).reset_index(drop=True))
cdf.crs = 'epsg:4326'
return cdf
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_categories(self, filters=None):

def get_categories_joined_datasets(self, filters=None):
query = 'SELECT DISTINCT c.* FROM categories_public c, datasets_public t'
return self._run_query(query, filters, ['c.id = t.category_id'])
return self._run_query(query, filters, ['c.id = t.category_id'])

def get_providers(self, filters=None):
query = 'SELECT t.* FROM providers_public t'
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def get_version():
'unidecode>=1.1.0,<2.0',
'pyarrow>=0.14.1,<1.0',
'google-cloud-bigquery>=1.19.0,<2.0',
'mercantile>=1.1.2,<2.0'
# 'Rtree>=0.8.3,<1.0'
]

Expand Down
Empty file added tests/unit/analysis/__init__.py
Empty file.
289 changes: 289 additions & 0 deletions tests/unit/analysis/grid_quadkey_bbox.csv

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions tests/unit/analysis/grid_quadkey_pol.csv

Large diffs are not rendered by default.

95 changes: 95 additions & 0 deletions tests/unit/analysis/test_grid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# """Unit tests for cartoframes.analysis.grid"""

import pandas as pd
import numpy as np
import os

from shapely.geometry import box, shape
from shapely import wkt
from cartoframes.analysis.grid import QuadGrid
from cartoframes import CartoDataFrame

import geopandas as gpd
from geopandas.testing import assert_geodataframe_equal

# DATA FRAME SRC BBOX
pol_1 = box(1, 1, 2, 2)
pol_2 = box(3, 3, 4, 4)
GDF_BOX = gpd.GeoDataFrame({'id': [1, 2], 'geometry': [pol_1, pol_2]}, columns=['id', 'geometry'])

pol_geojson = {
"type": "Polygon",
"coordinates": [
[
[
-5.899658203125,
38.436379603
],
[
-6.690673828125,
37.67512527892127
],
[
-6.15234375,
37.43997405227057
],
[
-5.8447265625,
37.70120736474139
],
[
-6.13037109375,
37.82280243352756
],
[
-5.877685546874999,
38.02213147353745
],
[
-6.009521484375,
38.12591462924157
],
[
-5.5810546875,
38.1777509666256
],
[
-5.899658203125,
38.436379603
]
]
]
}

GDF_IRREGULAR = gpd.GeoDataFrame({'id': [1], 'geometry': [shape(pol_geojson)]}, columns=['id', 'geometry'])

BASE_FOLDER = os.path.dirname(os.path.abspath(__file__))


class TestGrid(object):

def _load_test_gdf(self, fname):
fname = os.path.join(BASE_FOLDER, fname)
df = pd.read_csv(fname, dtype={'id': np.int64, 'geometry': object, 'quadkey': object})
df['geometry'] = df['geometry'].apply(wkt.loads)
cdf_test = CartoDataFrame(df)
cdf_test.crs = 'epsg:4326'
return cdf_test

def test_quadgrid_polyfill_box(self, mocker):
"""cartoframes.analysis.grid.QuadGrid.polyfill"""
cdf = QuadGrid().polyfill(GDF_BOX, 12)
assert isinstance(cdf, CartoDataFrame)

# Check both dataframes are equals
cdf_test = self._load_test_gdf('grid_quadkey_bbox.csv')
assert_geodataframe_equal(cdf, cdf_test, check_less_precise=True)

def test_quadgrid_polyfill_pol(self, mocker):
"""cartoframes.analysis.grid.QuadGrid.polyfill"""
cdf = QuadGrid().polyfill(GDF_IRREGULAR, 12)
assert isinstance(cdf, CartoDataFrame)

# Check both dataframes are equals
cdf_test = self._load_test_gdf('grid_quadkey_pol.csv')
assert_geodataframe_equal(cdf, cdf_test, check_less_precise=True)

0 comments on commit 5f6487e

Please sign in to comment.