Пример #1
0
def _evaluate_spatial_input(input_points):
    """
    Helper function to determine if the input is either a FeatureSet or Spatially Enabled DataFrame, and
    output to FeatureSet for subsequent processing.
    :param input_points: FeatureSet or Spatially Enabled DataFrame
    :return: FeatureSet
    """
    try:
        from arcgis.features.geo._accessor import _is_geoenabled
        from pandas import DataFrame
    except ImportError as ie:
        _log.warning(
            "One or more of the libraries needed for this feature is not available. "
            "Please resolve the following error: " + str(ie))
        raise ie

    if isinstance(input_points, FeatureSet):
        return input_points

    elif isinstance(input_points, DataFrame) and _is_geoenabled(input_points):
        return input_points.spatial.to_featureset()

    elif isinstance(input_points,
                    DataFrame) and not _is_geoenabled(input_points):
        raise Exception(
            'input_points is a DataFrame, but does not appear to be spatially enabled. Using the <df>.spatial.set_geometry(col, sr=None) may help. (https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.GeoAccessor.set_geometry)'
        )

    else:
        raise Exception(
            'input_points must be either a FeatureSet or Spatially Enabled DataFrame instead of {}'
            .format(type(input_points)))
Пример #2
0
def within(sdf, other, relation="CLEMENTINI"):
    """

    Indicates if the base geometry is within the comparison geometry.

    `within` is the opposite operator of `contains`.

    =========================    =========================================================
    **Argument**                 **Description**
    -------------------------    ---------------------------------------------------------
    sdf                          Required Spatially Enabled DataFrame. The dataframe to have the operation performed on.
    -------------------------    ---------------------------------------------------------
    other                        Required Spatially Enabled DataFrame or arcgis.Geometry.  This is the selecting data.
    -------------------------    ---------------------------------------------------------
    relation                     Optional String.  The spatial relationship type.  The
                                 allowed values are: BOUNDARY, CLEMENTINI, and PROPER.

                                 BOUNDARY - Relationship has no restrictions for interiors
                                            or boundaries.
                                 CLEMENTINI - Interiors of geometries must intersect. This
                                              is the default.
                                 PROPER - Boundaries of geometries must not intersect.
    =========================    =========================================================

    :returns: pd.DataFrame (Spatially enabled DataFrame)

    """
    global _HASARCPY, _HASSHAPELY

    if _HASARCPY == False and _HASSHAPELY == False:
        return None

    ud = pd.Series([False] * len(sdf))
    if isinstance(other, (Point, Polygon, Polyline, MultiPoint)):
        sindex = sdf.spatial.sindex()
        q1 = sindex.intersect(bbox=other.extent)
        sub = sdf.iloc[q1]
        dj = sub[sdf.spatial.name].geom.within(other, relation)
        dj.index = sub.index
        ud = ud | dj
        return sdf[ud]
    elif _is_geoenabled(other):
        sindex = sdf.spatial.sindex()
        name = other.spatial.name
        for index, seg in other.iterrows():
            g = seg[name]
            q1 = sindex.intersect(bbox=g.extent)
            sub = sdf.iloc[q1]
            if len(sub) > 0:
                dj = sub[sdf.spatial.name].geom.within(other, relation)
                dj.index = sub.index
                ud = ud | dj
        return sdf[ud]
    else:
        raise ValueError(("Invalid input, please verify that `other` "
                          "is a Point, Polygon, Polyline, MultiPoint, "
                          "or Spatially enabled DataFrame"))
    return None
Пример #3
0
def _evaluate_spatial_input(input_points):
    """
    Helper function to determine if the input is either a FeatureSet or Spatially Enabled DataFrame, and
    output to FeatureSet for subsequent processing.
    :param input_points: FeatureSet or Spatially Enabled DataFrame
    :return: FeatureSet
    """
    if isinstance(input_points, FeatureSet):
        return input_points

    elif isinstance(input_points, DataFrame) and _is_geoenabled(input_points):
        return input_points.spatial.to_featureset()

    elif isinstance(input_points, DataFrame) and not _is_geoenabled(input_points):
        raise Exception('input_points is a DataFrame, but does not appear to be spatially enabled. Using the <df>.spatial.set_geometry(col, sr=None) may help. (https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.GeoAccessor.set_geometry)')

    else:
        raise Exception('input_points must be either a FeatureSet or Spatially Enabled DataFrame instead of {}'.format(type(input_points)))
Пример #4
0
def crosses(sdf, other):
    """

    Indicates if the two geometries intersect in a geometry of a lesser
    shape type.

    Two polylines cross if they share only points in common, at least one
    of which is not an endpoint. A polyline and an polygon cross if they
    share a polyline or a point (for vertical line) in common on the
    interior of the polygon which is not equivalent to the entire polyline.

    =========================    =========================================================
    **Argument**                 **Description**
    -------------------------    ---------------------------------------------------------
    sdf                          Required Spatially Enabled DataFrame. The dataframe to have the operation performed on.
    -------------------------    ---------------------------------------------------------
    other                        Required Spatially Enabled DataFrame or arcgis.Geometry.  This is the selecting data.
    =========================    =========================================================

    :returns: pd.DataFrame (Spatially enabled DataFrame)

    """
    global _HASARCPY, _HASSHAPELY

    if _HASARCPY == False and _HASSHAPELY == False:
        return None

    ud = pd.Series([False] * len(sdf))
    if isinstance(other, (Point, Polygon, Polyline, MultiPoint)):
        sindex = sdf.spatial.sindex()
        q1 = sindex.intersect(bbox=other.extent)
        sub = sdf.iloc[q1]
        dj = sub[sdf.spatial.name].geom.crosses(other)
        dj.index = sub.index
        ud = ud | dj
        return sdf[ud]
    elif _is_geoenabled(other):
        sindex = sdf.spatial.sindex()
        name = other.spatial.name
        for index, seg in other.iterrows():
            g = seg[name]
            q1 = sindex.intersect(bbox=g.extent)
            sub = sdf.iloc[q1]
            if len(sub) > 0:
                dj = sub[sdf.spatial.name].geom.crosses(g)
                dj.index = sub.index
                ud = ud | dj
        return sdf[ud]
    else:
        raise ValueError(("Invalid input, please verify that `other` "
                          "is a Point, Polygon, Polyline, MultiPoint, "
                          "or Spatially enabled DataFrame"))
    return None
Пример #5
0
def touches(sdf, other):
    """

    Indicates if the boundaries of the geometries intersect.

    Two geometries touch when the intersection of the geometries is not
    empty, but the intersection of their interiors is empty. For example,
    a point touches a polyline only if the point is coincident with one of
    the polyline end points.

    =========================    =========================================================
    **Argument**                 **Description**
    -------------------------    ---------------------------------------------------------
    sdf                          Required Spatially Enabled DataFrame. The dataframe to have the operation performed on.
    -------------------------    ---------------------------------------------------------
    other                        Required Spatially Enabled DataFrame or arcgis.Geometry.  This is the selecting data.
    =========================    =========================================================

    :returns: pd.DataFrame (Spatially enabled DataFrame)

    """
    global _HASARCPY, _HASSHAPELY

    if _HASARCPY == False and _HASSHAPELY == False:
        return None

    ud = pd.Series([False] * len(sdf))
    if isinstance(other, (Point, Polygon, Polyline, MultiPoint)):
        sindex = sdf.spatial.sindex()
        q1 = sindex.intersect(bbox=other.extent)
        sub = sdf.iloc[q1]
        dj = sub[sdf.spatial.name].geom.touches(other)
        dj.index = sub.index
        ud = ud | dj
        return sdf[ud]
    elif _is_geoenabled(other):
        sindex = sdf.spatial.sindex()
        name = other.spatial.name
        for index, seg in other.iterrows():
            g = seg[name]
            q1 = sindex.intersect(bbox=g.extent)
            sub = sdf.iloc[q1]
            if len(sub) > 0:
                dj = sub[sdf.spatial.name].geom.touches(g)
                dj.index = sub.index
                ud = ud | dj
        return sdf[ud]
    else:
        raise ValueError(("Invalid input, please verify that `other` "
                          "is a Point, Polygon, Polyline, MultiPoint, "
                          "or Spatially enabled DataFrame"))
    return None
Пример #6
0
def equals(sdf, other):
    """

    Indicates if the base and comparison geometries are of the same shape
    type and define the same set of points in the plane. This is a 2D
    comparison only; M and Z values are ignored.

    =========================    =========================================================
    **Argument**                 **Description**
    -------------------------    ---------------------------------------------------------
    sdf                          Required Spatially Enabled DataFrame. The dataframe to have the operation performed on.
    -------------------------    ---------------------------------------------------------
    other                        Required Spatially Enabled DataFrame or arcgis.Geometry.  This is the selecting data.
    =========================    =========================================================

    :returns: pd.DataFrame (Spatially enabled DataFrame)

    """
    global _HASARCPY, _HASSHAPELY

    if _HASARCPY == False and _HASSHAPELY == False:
        return None

    ud = pd.Series([False] * len(sdf))
    if isinstance(other, (Point, Polygon, Polyline, MultiPoint)):
        sindex = sdf.spatial.sindex()
        q1 = sindex.intersect(bbox=other.extent)
        sub = sdf.iloc[q1]
        dj = sub[sdf.spatial.name].geom.equals(other)
        dj.index = sub.index
        ud = ud | dj
        return sdf[ud]
    elif _is_geoenabled(other):
        sindex = sdf.spatial.sindex()
        name = other.spatial.name
        for index, seg in other.iterrows():
            g = seg[name]
            q1 = sindex.intersect(bbox=g.extent)
            sub = sdf.iloc[q1]
            if len(sub) > 0:
                dj = sub[sdf.spatial.name].geom.equals(g)
                dj.index = sub.index
                ud = ud | dj
        return sdf[ud]
    else:
        raise ValueError(("Invalid input, please verify that `other` "
                          "is a Point, Polygon, Polyline, MultiPoint, "
                          "or Spatially enabled DataFrame"))
    return None
Пример #7
0
def select(sdf, other):
    """
    Performs a select by location operation

    =========================    =========================================================
    **Argument**                 **Description**
    -------------------------    ---------------------------------------------------------
    sdf                          Required Spatially Enabled DataFrame. The dataframe to have the operation performed on.
    -------------------------    ---------------------------------------------------------
    other                        Required Spatially Enabled DataFrame or arcgis.Geometry.  This is the selecting data.
    =========================    =========================================================

    :returns: pd.DataFrame (Spatially enabled DataFrame)

    """
    ud = pd.Series([False] * len(sdf))
    if isinstance(other, (Point, Polygon, Polyline, MultiPoint)):
        sindex = sdf.spatial.sindex()
        q1 = sindex.intersect(bbox=other.extent)
        sub = sdf.iloc[q1]
        dj = sub[sdf.spatial.name].geom.disjoint(other) == False
        dj.index = sub.index
        ud = ud | dj
        return sdf[ud]
    elif _is_geoenabled(other):
        sindex = sdf.spatial.sindex()
        name = other.spatial.name
        for index, seg in other.iterrows():
            g = seg[name]
            q1 = sindex.intersect(bbox=g.extent)
            sub = sdf.iloc[q1]
            if len(sub) > 0:
                dj = sub[sdf.spatial.name].geom.disjoint(g) == False
                dj.index = sub.index
                ud = ud | dj
        return sdf[ud]
    else:
        raise ValueError(("Invalid input, please verify that `other` "
                          "is a Point, Polygon, Polyline, MultiPoint, "
                          "or Spatially enabled DataFrame"))
    return None
Пример #8
0
def _execute_gp_tool(gis,
                     task_name,
                     params,
                     param_db,
                     return_values,
                     use_async,
                     url,
                     webtool=False,
                     add_token=True,
                     return_messages=False,
                     future=False):
    if gis is None:
        gis = arcgis.env.active_gis

    gp_params = {"f": "json"}

    # ---------------------in---------------------#
    for param_name, param_value in params.items():
        #print(param_name + " = " + str(param_value))
        if param_name in param_db:
            py_type, gp_param_name = param_db[param_name]
            if param_value is None:
                param_value = ''
            gp_params[gp_param_name] = param_value
            if py_type == FeatureSet:
                if webtool:
                    if isinstance(param_value, (tuple, list)):
                        gp_params[gp_param_name] = [
                            _layer_input_gp(p) for p in param_value
                        ]
                    else:
                        gp_params[gp_param_name] = _layer_input_gp(param_value)

                else:
                    try:
                        from arcgis.features.geo._accessor import _is_geoenabled
                    except:

                        def _is_geoenabled(o):
                            return False

                    if type(param_value) == FeatureSet:
                        gp_params[gp_param_name] = param_value.to_dict()
                    elif _is_geoenabled(param_value):
                        gp_params[gp_param_name] = json.loads(
                            json.dumps(param_value.spatial.__feature_set__,
                                       default=_date_handler))
                    elif type(param_value) == str:

                        try:
                            klass = py_type
                            gp_params[gp_param_name] = klass.from_str(
                                param_value)

                        except:
                            pass

            elif py_type in [LinearUnit, DataFile, RasterData]:
                if type(param_value) in [LinearUnit, DataFile, RasterData]:
                    gp_params[gp_param_name] = param_value.to_dict()

                elif type(param_value) == str:

                    try:
                        klass = py_type
                        gp_params[gp_param_name] = klass.from_str(param_value)

                    except:
                        pass

                elif isinstance(param_value, arcgis.gis.Layer):
                    gp_params[gp_param_name] = param_value._lyr_dict

            elif py_type == datetime.datetime:
                gp_params[gp_param_name] = _date_handler(param_value)
    # --------------------------------------------#

    _set_env_params(gp_params, params)

    # for param_name, param_value in gp_params.items():
    #     print(param_name + " = " + str(param_value))

    gptool = arcgis.gis._GISResource(url, gis)

    if use_async:
        task_url = "{}/{}".format(url, task_name)
        submit_url = "{}/submitJob".format(task_url)
        if add_token and submit_url.lower().find("arcgis.com") == -1:
            try:
                job_info = gptool._con.post(submit_url,
                                            gp_params,
                                            token=gptool._token)
            except:
                job_info = gptool._con.post(submit_url, gp_params)
        else:
            job_info = gptool._con.post(submit_url, gp_params)
        job_id = job_info['jobId']
        if future:
            executor = concurrent.futures.ThreadPoolExecutor(1)
            future = executor.submit(
                _future_op,
                *(gptool, task_url, job_info, job_id, param_db, return_values,
                  return_messages))
            executor.shutdown(False)
            gpjob = GPJob(future=future,
                          gptool=gptool,
                          jobid=job_id,
                          task_url=task_url,
                          gis=gptool._gis,
                          notify=arcgis.env.verbose)
            return gpjob
        job_info = _analysis_job_status(gptool, task_url, job_info)
        resp = _analysis_job_results(gptool, task_url, job_info, job_id)

        # ---------------------async-out---------------------#
        output_dict = {}
        for retParamName in resp.keys():
            output_val = resp[retParamName]
            try:
                ret_param_name, ret_val = _get_output_value(
                    gptool, output_val, param_db, retParamName)
                output_dict[ret_param_name] = ret_val
            except KeyError:
                pass  # cannot handle unexpected output as return tuple will change

        # tools with output map service - add another output:
        # result_layer = '' #***self.properties.resultMapServerName
        if gptool.properties.resultMapServerName != '':
            job_id = job_info.get("jobId")
            result_layer_url = url.replace('/GPServer',
                                           '/MapServer') + '/jobs/' + job_id

            output_dict['result_layer'] = MapImageLayer(
                result_layer_url, gptool._gis)

        num_returns = len(resp)
        if return_messages:
            return _return_output(num_returns, output_dict,
                                  return_values), job_info

        return _return_output(num_returns, output_dict, return_values)

    else:  # synchronous
        exec_url = url + "/" + task_name + "/execute"
        if add_token:
            resp = gptool._con.post(exec_url, gp_params, token=gptool._token)
        else:
            resp = gptool._con.post(exec_url, gp_params)

        output_dict = {}

        for result in resp['results']:
            retParamName = result['paramName']

            output_val = result['value']
            try:
                ret_param_name, ret_val = _get_output_value(
                    gptool, output_val, param_db, retParamName)
                output_dict[ret_param_name] = ret_val
            except KeyError:
                pass  # cannot handle unexpected output as return tuple will change

        num_returns = len(resp['results'])
        if return_messages:
            return _return_output(num_returns, output_dict,
                                  return_values), job_info
        return _return_output(num_returns, output_dict, return_values)