libpysal icon indicating copy to clipboard operation
libpysal copied to clipboard

Add ArcGIS API for Python Geometry Support to Weight Objects

Open achapkowski opened this issue 5 years ago • 11 comments

  • adds support for ArcGIS API for Python's Polygon and Polyline Geometry objects.

  • Point Geometry already works :)

Hello! Please make sure to check all these boxes before submitting a Pull Request (PR). Once you have checked the boxes, feel free to remove all text except the justification in point 5.

  1. [x] You have run tests on this submission, either by using Travis Continuous Integration testing testing or running nosetests on your changes?
  2. [x] This pull request is directed to the pysal/master branch.
  3. [x] This pull introduces new functionality covered by docstrings and unittests?
  4. [ ] You have assigned a reviewer and added relevant labels
  5. [x] The justification for this PR is: Esri's ArcGIS API for Python provides a DataFrame data structure and Geometry object. The Point geometry already work, but the Polygon (compares to Shapely's MultiPolygon) and Polyline (compares to LInestring and MultiLineString) are not supported. This PR makes a small change to the _get_boundary_points method without adding any new dependencies or dangerous code. Since the ArcGIS Python API allows for use of both shapely and/or arcpy as geometry engines this will allow users to leverage both OS and Esri technology next to pysal

achapkowski avatar Jul 29 '20 17:07 achapkowski

I cannot add a person to review or assign labels.

achapkowski avatar Jul 29 '20 17:07 achapkowski

Thanks for this! I don't actually think I can evaluate this without Arc, and I have no platforms that can run it currently, but this looks pretty straightforward to review just from the stated APIs.

I hope other reviewers can evaluate this with the arcpy runtime?

ljwolf avatar Jul 29 '20 17:07 ljwolf

Codecov Report

Merging #331 into master will decrease coverage by 0.11%. The diff coverage is 42.85%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #331      +/-   ##
==========================================
- Coverage   81.22%   81.11%   -0.12%     
==========================================
  Files         115      115              
  Lines       11678    11684       +6     
==========================================
- Hits         9485     9477       -8     
- Misses       2193     2207      +14     
Impacted Files Coverage Δ
libpysal/weights/_contW_lists.py 87.95% <42.85%> (-4.26%) :arrow_down:
libpysal/examples/base.py 53.02% <0.00%> (-6.72%) :arrow_down:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 9e65951...a2a3318. Read the comment docs.

codecov[bot] avatar Jul 29 '20 17:07 codecov[bot]

Super simple sample

import pandas as pd
import arcgis
pts = pd.DataFrame.spatial.from_featureclass(r"c:\gis\sample_data\Alaska Data\Trans_AirportPoint.shp")
knn_w = KNN.from_dataframe(df=pts, geom_col='SHAPE')
import pandas as pd
import arcgis
polygons = pd.DataFrame.spatial.from_featureclass(r"c:\gis\sample_data\ZipCodes.gdb\zipcodes")
geoms = polygons.SHAPE.values
rook = Rook(polygons=geoms)
queen = Queen(polygons=geoms)

Hope this helps!

achapkowski avatar Jul 29 '20 17:07 achapkowski

Super simple sample

import pandas as pd
import arcgis
pts = pd.DataFrame.spatial.from_featureclass(r"c:\gis\sample_data\Alaska Data\Trans_AirportPoint.shp")
knn_w = KNN.from_dataframe(df=pts, geom_col='SHAPE')
import pandas as pd
import arcgis
polygons = pd.DataFrame.spatial.from_featureclass(r"c:\gis\sample_data\ZipCodes.gdb\zipcodes")
geoms = polygons.SHAPE.values
rook = Rook(polygons=geoms)
queen = Queen(polygons=geoms)

Hope this helps!

@achapkowski It does not appear that arcgis is being using in these examples. Also KNN, Rook, and Queen.

jGaboardi avatar Jul 29 '20 18:07 jGaboardi

Thanks for this! I don't actually think I can evaluate this without Arc, and I have no platforms that can run it currently, but this looks pretty straightforward to review just from the stated APIs.

I hope other reviewers can evaluate this with the arcpy runtime?

I also don't have access to acrpy or arcgis.

jGaboardi avatar Jul 29 '20 19:07 jGaboardi

@jGaboardi, yeah, if I recall correctly back when I was working w/ the cartoframes team, this "monkey-patches" pandas to add a pandas.DataFrame.spatial namespace that @achapkowski uses (source)

pandas.DataFrame.spatial.from_featureclass

doesn't exist without the import arcgis before it.

On tests, it should be pretty straightforward to write a single file in the mould of:


try:
    import pandas as pd
    import arcgis
    HAS_ARCGIS=True
except ModuleNotFoundError:
    HAS_ARCGIS=False

@unittest.skipif(not HAS_ARCGIS, "ArcGIS is not installed.")
def test_arcgis_w():
    import pandas as pd
    import arcgis
    import geopandas
    from libpysal.weights import KNN, Rook, Queen
    from libpysal import examples

    baltim = examples.get_path('baltim.shp')
    columbus = examples.get_path('columbus.shp')


    pts = pd.DataFrame.spatial.from_featureclass(baltim)
    knnw = KNN.from_dataframe(df=pts, geom_col='SHAPE')
    knnw_known = KNN.from_dataframe(geopandas.read_file(baltim))

    assert (knnw.sparse != knnw_known.sparse).sum() == 0 

    polygons = pd.DataFrame.spatial.from_featureclass(columbus)
    geoms = polygons.SHAPE.values
    rook = Rook(polygons=geoms)
    rook_known = Rook.from_dataframe(geopandas.read_file(columbus))
    assert (rook.sparse != rook_known.sparse).sum() == 0 

    queen = Queen(polygons=geoms)
    queen_known = Rook.from_dataframe(geopandas.read_file(columbus))
    assert (queen.sparse != queen_known.sparse).sum() == 0 

But, I'm not sure we can run this in CI without an Arc Enterprise license... we need a solution there.

In abstract, I'd like this to land

  1. it's exceptionally simple
  2. it's improving interoperability, a pretty consistent goal of mine w/ the weights inputs

ljwolf avatar Jul 30 '20 08:07 ljwolf

@ljwolf you do not need any arc licenses to run the python package. You'll just need to have shapely installed to use as a geometry engine.

achapkowski avatar Jul 30 '20 09:07 achapkowski

Neat! very different than the last time I used this stuff. Using ArcGIS from pypi, I'm getting odd/very long delays running the test above on the contiguity operations... will need to investigate a bit.

ljwolf avatar Jul 30 '20 09:07 ljwolf

I'm trying to revisit this issue, what is needed to merge this?

achapkowski avatar Apr 06 '21 10:04 achapkowski

@achapkowski PR needs to be updated from master to resolve conflicts and we should add tests (based on those @ljwolf posted above).

martinfleis avatar Apr 09 '21 10:04 martinfleis