mirror of
https://github.com/wassname/geopandas.git
synced 2026-08-31 12:01:45 +08:00
214 lines
6.9 KiB
Python
214 lines
6.9 KiB
Python
import io
|
|
import os.path
|
|
from six.moves.urllib.request import urlopen
|
|
|
|
from geopandas import GeoDataFrame, GeoSeries
|
|
|
|
# Compatibility layer for Python 2.6: try loading unittest2
|
|
import sys
|
|
if sys.version_info[:2] == (2, 6):
|
|
try:
|
|
import unittest2 as unittest
|
|
except ImportError:
|
|
import unittest
|
|
|
|
else:
|
|
import unittest
|
|
|
|
try:
|
|
import psycopg2
|
|
from psycopg2 import OperationalError
|
|
except ImportError:
|
|
class OperationalError(Exception):
|
|
pass
|
|
|
|
try:
|
|
from pandas import read_sql_table
|
|
except ImportError:
|
|
PANDAS_NEW_SQL_API = False
|
|
else:
|
|
PANDAS_NEW_SQL_API = True
|
|
|
|
|
|
def download_nybb():
|
|
""" Returns the path to the NYC boroughs file. Downloads if necessary. """
|
|
# Data from http://www.nyc.gov/html/dcp/download/bytes/nybb_14aav.zip
|
|
# saved as geopandas/examples/nybb_14aav.zip.
|
|
filename = 'nybb_14aav.zip'
|
|
full_path_name = os.path.join('examples', filename)
|
|
if not os.path.exists(full_path_name):
|
|
with io.open(full_path_name, 'wb') as f:
|
|
response = urlopen('http://www.nyc.gov/html/dcp/download/bytes/{0}'.format(filename))
|
|
f.write(response.read())
|
|
return full_path_name
|
|
|
|
|
|
def validate_boro_df(test, df):
|
|
""" Tests a GeoDataFrame that has been read in from the nybb dataset."""
|
|
test.assertTrue(isinstance(df, GeoDataFrame))
|
|
# Make sure all the columns are there and the geometries
|
|
# were properly loaded as MultiPolygons
|
|
test.assertEqual(len(df), 5)
|
|
columns = ('borocode', 'boroname', 'shape_leng', 'shape_area')
|
|
for col in columns:
|
|
test.assertTrue(col in df.columns, 'Column {0} missing'.format(col))
|
|
test.assertTrue(all(df.geometry.type == 'MultiPolygon'))
|
|
|
|
|
|
def connect(dbname):
|
|
try:
|
|
con = psycopg2.connect(dbname=dbname)
|
|
except (NameError, OperationalError):
|
|
return None
|
|
|
|
return con
|
|
|
|
|
|
def create_db(df):
|
|
"""
|
|
Create a nybb table in the test_geopandas PostGIS database.
|
|
Returns a boolean indicating whether the database table was successfully
|
|
created
|
|
|
|
"""
|
|
# Try to create the database, skip the db tests if something goes
|
|
# wrong
|
|
# If you'd like these tests to run, create a database called
|
|
# 'test_geopandas' and enable postgis in it:
|
|
# > createdb test_geopandas
|
|
# > psql -c "CREATE EXTENSION postgis" -d test_geopandas
|
|
con = connect('test_geopandas')
|
|
if con is None:
|
|
return False
|
|
|
|
try:
|
|
cursor = con.cursor()
|
|
cursor.execute("DROP TABLE IF EXISTS nybb;")
|
|
|
|
sql = """CREATE TABLE nybb (
|
|
geom geometry,
|
|
borocode integer,
|
|
boroname varchar(40),
|
|
shape_leng float,
|
|
shape_area float
|
|
);"""
|
|
cursor.execute(sql)
|
|
|
|
for i, row in df.iterrows():
|
|
sql = """INSERT INTO nybb VALUES (
|
|
ST_GeometryFromText(%s), %s, %s, %s, %s
|
|
);"""
|
|
cursor.execute(sql, (row['geometry'].wkt,
|
|
row['BoroCode'],
|
|
row['BoroName'],
|
|
row['Shape_Leng'],
|
|
row['Shape_Area']))
|
|
finally:
|
|
cursor.close()
|
|
con.commit()
|
|
con.close()
|
|
|
|
return True
|
|
|
|
|
|
def assert_seq_equal(left, right):
|
|
"""Poor man's version of assert_almost_equal which isn't working with Shapely
|
|
objects right now"""
|
|
assert len(left) == len(right), "Mismatched lengths: %d != %d" % (len(left), len(right))
|
|
|
|
for elem_left, elem_right in zip(left, right):
|
|
assert elem_left == elem_right, "%r != %r" % (left, right)
|
|
|
|
|
|
def geom_equals(this, that):
|
|
"""Test for geometric equality. Empty geometries are considered equal.
|
|
|
|
Parameters
|
|
----------
|
|
this, that : arrays of Geo objects (or anything that has an `is_empty`
|
|
attribute)
|
|
"""
|
|
|
|
return (this.geom_equals(that) | (this.is_empty & that.is_empty)).all()
|
|
|
|
|
|
def geom_almost_equals(this, that):
|
|
"""Test for 'almost' geometric equality. Empty geometries considered equal.
|
|
|
|
Parameters
|
|
----------
|
|
this, that : arrays of Geo objects (or anything that has an `is_empty`
|
|
property)
|
|
"""
|
|
|
|
return (this.geom_almost_equals(that) |
|
|
(this.is_empty & that.is_empty)).all()
|
|
|
|
# TODO: Remove me when standardizing on pandas 0.13, which already includes
|
|
# this test util.
|
|
def assert_isinstance(obj, klass_or_tuple):
|
|
assert isinstance(obj, klass_or_tuple), "type: %r != %r" % (
|
|
type(obj).__name__,
|
|
getattr(klass_or_tuple, '__name__',
|
|
klass_or_tuple))
|
|
|
|
def assert_geoseries_equal(left, right, check_dtype=False,
|
|
check_index_type=False,
|
|
check_series_type=True,
|
|
check_less_precise=False,
|
|
check_geom_type=False,
|
|
check_crs=True):
|
|
"""Test util for checking that two GeoSeries are equal.
|
|
|
|
Parameters
|
|
----------
|
|
left, right : two GeoSeries
|
|
check_dtype : bool, default False
|
|
if True, check geo dtype [only included so it's a drop-in replacement
|
|
for assert_series_equal]
|
|
check_index_type : bool, default False
|
|
check that index types are equal
|
|
check_series_type : bool, default True
|
|
check that both are same type (*and* are GeoSeries). If False,
|
|
will attempt to convert both into GeoSeries.
|
|
check_less_precise : bool, default False
|
|
if True, use geom_almost_equals. if False, use geom_equals.
|
|
check_geom_type : bool, default False
|
|
if True, check that all the geom types are equal.
|
|
check_crs: bool, default True
|
|
if check_series_type is True, then also check that the
|
|
crs matches
|
|
"""
|
|
assert len(left) == len(right), "%d != %d" % (len(left), len(right))
|
|
|
|
if check_index_type:
|
|
assert_isinstance(left.index, type(right.index))
|
|
|
|
if check_dtype:
|
|
assert left.dtype == right.dtype, "dtype: %s != %s" % (left.dtype,
|
|
right.dtype)
|
|
|
|
if check_series_type:
|
|
assert isinstance(left, GeoSeries)
|
|
assert_isinstance(left, type(right))
|
|
|
|
if check_crs:
|
|
assert(left.crs == right.crs)
|
|
else:
|
|
if not isinstance(left, GeoSeries):
|
|
left = GeoSeries(left)
|
|
if not isinstance(right, GeoSeries):
|
|
right = GeoSeries(right, index=left.index)
|
|
|
|
assert left.index.equals(right.index), "index: %s != %s" % (left.index,
|
|
right.index)
|
|
|
|
if check_geom_type:
|
|
assert (left.type == right.type).all(), "type: %s != %s" % (left.type,
|
|
right.type)
|
|
|
|
if check_less_precise:
|
|
assert geom_almost_equals(left, right)
|
|
else:
|
|
assert geom_equals(left, right)
|