def _from_xy(df, x_column, y_column, sr=None):
    """
    Takes an X/Y Column and Creates a Point Geometry from it.
    """
    from arcgis.geometry import SpatialReference, Point
    from arcgis.features.geo._array import GeoArray

    def _xy_to_geometry(x, y, sr):
        """converts x/y coordinates to Point object"""
        return Point({'spatialReference': sr, 'x': x, 'y': y})

    if sr is None:
        sr = SpatialReference({'wkid': 4326})
    if not isinstance(sr, SpatialReference):
        if isinstance(sr, dict):
            sr = SpatialReference(sr)
        elif isinstance(sr, int):
            sr = SpatialReference({'wkid': sr})
        elif isinstance(sr, str):
            sr = SpatialReference({'wkt': sr})
    geoms = []
    v_func = np.vectorize(_xy_to_geometry, otypes='O')
    ags_geom = np.empty(len(df), dtype="O")
    ags_geom[:] = v_func(df[x_column].values, df[y_column].values, sr)
    df['SHAPE'] = GeoArray(ags_geom)
    df.spatial.name
    return df
示例#2
0
def _from_xy(df, x_column, y_column, sr=None):
    """

    """
    from arcgis.geometry import SpatialReference, Geometry
    from arcgis.features import SpatialDataFrame
    if sr is None:
        sr = SpatialReference({'wkid': 4326})
    if not isinstance(sr, SpatialReference):
        if isinstance(sr, dict):
            sr = SpatialReference(sr)
        elif isinstance(sr, int):
            sr = SpatialReference({'wkid': sr})
        elif isinstance(sr, str):
            sr = SpatialReference({'wkt': sr})
    geoms = []
    for idx, row in df.iterrows():
        geoms.append(
            Geometry({
                'x': row[x_column],
                'y': row[y_column],
                'spatialReference': sr
            }))
    df['SHAPE'] = geoms
    return SpatialDataFrame(data=df, sr=sr)
示例#3
0
def sdf_from_xyz(df, x_col, y_col, z_col=None, sr=None):
    """builds a SpatialDataFrame from DataFrame with
    x, y, and z columns
    
    args:
    df - the dataframe
    x_col - the dataframe column corresponding to x coordinate
    y_col - the dataframe column corresponding to y coordinate
    z_col - optional, the dataframe column corresponding to z coordinate
    sr - the spatial reference for the spatial data frame
    """

    if not z_col:
        return pd.DataFrame.spatial.from_xy(df, x_col, y_col, sr)

    def point_for_row(x, y, z, sr):
        return Point({'x': x, 'y': y, 'z': z, "spatialReference": sr})

    if sr is None:
        sr = SpatialReference({'wkid': 4326})

    df_geom = df.apply(
        lambda row: point_for_row(row[x_col], row[y_col], row[z_col], sr),
        axis=1)
    sdf = df.spatial.set_geometry(df_geom, sr=sr)
    return sdf
示例#4
0
def validate_spatial_reference(spatial_reference: Union[str, int, dict,
                                                        SpatialReference]):
    """Validate the variety of ways a spatial reference can be inputted. This does not validate the WKID."""
    # instantiate the output spatial reference variable
    sr = None

    if isinstance(spatial_reference, dict):
        assert 'wkid' in spatial_reference.keys(), 'If providing spatial reference as a dictionary, it must conform '\
                                                   'look like {"wkid": <WKID>}, such as {"wkid": 4326}.'
        sr = spatial_reference
    elif isinstance(spatial_reference, str):
        assert spatial_reference.isdecimal(), 'If providing a string to identify a spatial reference, it must be a ' \
                                              'WKID for your desired spatial reference.'
        sr = {'wkid': spatial_reference}
    elif isinstance(spatial_reference, int):
        sr = {'wkid': spatial_reference}
    elif isinstance(spatial_reference, SpatialReference):
        sr = SpatialReference
    elif avail_arcpy:
        import arcpy
        if isinstance(spatial_reference, arcpy.SpatialReference):
            sr = SpatialReference(spatial_reference.factoryCode)

    # if nothing has been found, something is wrong
    if sr is None:
        raise Exception(
            'The spatial reference must be either a string or integer specify the WKID, a dictionary '
            'specifying the WKID such as {"wkid": 4326}, or a SpatialReference object.'
        )

    return sr
示例#5
0
 def point(self):
     """
     Property to return point geometry if available.
     :return: Point geometry object if possible.
     """
     if self.x and self.y:
         return Point(x=self.x, y=self.y, sr=SpatialReference(wkid=4326))
     else:
         return None
示例#6
0
 def sr(self, sr=None):
     """
     Set the spatial reference for the dataset - defaults to 4326
     returns DataFrame object
     """
     default_sr = {"wkid": 4326}
     if sr is None:
         self.spatial_reference = SpatialReference(default_sr)
     elif isinstance(sr, SpatialReference):
         self.spatial_reference = SpatialReference(sr)
     elif isinstance(sr, int):
         default_sr["wkid"] = sr
         self.spatial_reference = SpatialReference(default_sr)
     elif isinstance(sr, dict):
         if "spatialReference" in sr.keys():
             if ("wkid" in sr["spatialReference"].keys()
                     or "latestWkid" in sr["spatialReference"].keys()):
                 self.spatial_reference = SpatialReference(sr)
             else:
                 raise ValueError(
                     "Spatial reference must specify 'wkid' or 'latestWkid'"
                 )
     elif isinstance(sr, str):
         try:
             sr = int(sr)
             default_sr["wkid"] = sr
             self.spatial_reference = SpatialReference(default_sr)
         except:
             raise ValueError(
                 "Cannot interpret spatial reference: pass an EPSG code, SpatialReference ",
                 " object, or dict",
             )
     else:
         raise ValueError(
             "Cannot interpret spatial reference: pass an EPSG code, SpatialReference object,",
             " or dict with 'wkid' property",
         )
     return self
示例#7
0
def _from_xy(df, x_column, y_column, sr=None):
    """
    Takes an X/Y Column and Creates a Point Geometry from it.
    """
    from arcgis.geometry import SpatialReference, Geometry
    if sr is None:
        sr = SpatialReference({'wkid' : 4326})
    if not isinstance(sr, SpatialReference):
        if isinstance(sr, dict):
            sr = SpatialReference(sr)
        elif isinstance(sr, int):
            sr = SpatialReference({'wkid' : sr})
        elif isinstance(sr, str):
            sr = SpatialReference({'wkt' : sr})
    geoms = []
    for idx, row in df.iterrows():
        geoms.append(
            Geometry({'x' : row[x_column], 'y' : row[y_column],
             'spatialReference' : sr})
        )
    df['SHAPE'] = geoms
    df.spatial.set_geometry('SHAPE')
    return df
示例#8
0
    def _get_sdf(self, path_directory):
        """
        Load the photos into a spatial data frame.
        :param path_directory: Path to directory containing photos.
        :return: SpatialDataFrame
        """
        # load up the photos as a list of dictionaries
        photo_list = [
            Photo(file).dictionary for file in os.listdir(path_directory)
            if file.lower().endswith('.jpg')
        ]

        # convert this list of dictionaries into a SpatialDataFrame
        photo_sdf = SpatialDataFrame(photo_list)

        # set the geometry field property
        photo_sdf.set_geometry('SHAPE',
                               inplace=True,
                               sr=SpatialReference(wkid=4326))

        # reindex all the data and return the result
        return photo_sdf.reset_index(drop=True)
def project_as(self, output_spatial_reference):
    """
    Project the geometry to another spatial reference - automatically
    applying a transformation if necessary.
    :param output_spatial_reference: Required - SpatialReference
        Spatial reference object defining the output spatial reference.
    :return: Geometry object in new spatial reference.
    """
    # get the wkid for the input and output
    if type(output_spatial_reference) == int:
        wkid_out = output_spatial_reference
    elif type(output_spatial_reference) == SpatialReference:
        wkid_out = SpatialReference['wkid']
    else:
        raise Exception('Valid output spatial reference must be provided.')

    wkid_in = self.spatial_reference['wkid']

    # if the spatial references match, don't do anything
    if wkid_in == wkid_out:
        return self

    # get the best applicable transformation, if needed
    transformation_list = find_transformation(wkid_in, wkid_out)['transformations']

    # if a transformation IS needed, project using it
    if len(transformation_list):
        out_geom = project([self], wkid_in, wkid_out, transformation_list[0])[0]

    # if a transformation IS NOT needed, project without
    else:
        out_geom = project([self], wkid_in, wkid_out)[0]

    # add the spatial reference to the geometry, since it does not have it in the response
    out_geom.spatial_reference = SpatialReference(wkid=wkid_out)

    return out_geom
示例#10
0
def project_as(input_dataframe: pd.DataFrame, output_spatial_reference: [int, SpatialReference] = 4326,
               input_spatial_reference: [int, SpatialReference] = None,
               transformation_name: str = None) -> pd.DataFrame:
    """
    Project input Spatially Enabled Dataframe to a desired output spatial reference, applying a
        transformation if needed due to the geographic coordinate system changing.
    Args:
        input_dataframe: Valid Spatially Enabled DataFrame
        output_spatial_reference: Optional - Desired output Spatial Reference. Default is
            4326 (WGS84).
        input_spatial_reference: Optional - Only necessary if the Spatial Reference is not
            properly defined for the input data geometry.
        transformation_name: Optional - Transformation name to be used, if needed, to
            convert between spatial references. If not explicitly provided, this will be
            inferred based on the spatial reference of the input data and desired output
            spatial reference.
    Returns: Spatially Enabled DataFrame in the desired output spatial reference.
    """
    # ensure the geometry is set
    geom_col_lst = [c for c in input_dataframe.columns if input_dataframe[c].dtype.name.lower() == 'geometry']
    assert len(geom_col_lst) > 0, 'The DataFrame does not appear to have a geometry column defined. This can be ' \
                                  'accomplished using the "input_dataframe.spatial.set_geometry" method.'

    # save the geometry column to a variable
    geom_col = geom_col_lst[0]

    # ensure the input spatially enabled dataframe validates
    assert input_dataframe.spatial.validate(), 'The DataFrame does not appear to be valid.'

    # if a spatial reference is set for the dataframe, just use it
    if input_dataframe.spatial.sr is not None:
        in_sr = input_dataframe.spatial.sr

    # if a spatial reference is explicitly provided, but the data does not have one set, use the one provided
    elif input_spatial_reference is not None:

        # check the input
        assert isinstance(input_spatial_reference, int) or isinstance(input_spatial_reference, SpatialReference), \
            f'input_spatial_reference must be either an int referencing a wkid or a SpatialReference object, ' \
            f'not {type(input_spatial_reference)}.'

        if isinstance(input_spatial_reference, int):
            in_sr = SpatialReference(input_spatial_reference)
        else:
            in_sr = input_spatial_reference

    # if the spatial reference is not set, common for data coming from geojson, check if values are in lat/lon
    # range, and if so, go with WGS84, as this is likely the case if in this range
    else:

        # get the bounding values for the data
        x_min, y_min, x_max, y_max = input_dataframe.spatial.full_extent

        # check the range of the values, if in longitude and latitude range
        wgs_range = True if (x_min > -181 and y_min > -91 and x_max < 181 and y_max < 91) else False
        assert wgs_range, 'Input data for projection data must have a spatial reference, or one must be provided.'

        # if the values are in range, run with it
        in_sr = SpatialReference(4326)

    # ensure the output spatial reference is a SpatialReference object instance
    if isinstance(output_spatial_reference, SpatialReference):
        out_sr = output_spatial_reference
    else:
        out_sr = SpatialReference(output_spatial_reference)

    # copy the input spatially enabled dataframe since the project function changes the dataframe in place
    out_df = input_dataframe.copy()
    out_df.spatial.set_geometry(geom_col)

    # if arcpy is available, use it to find the transformation
    if arcpy_avail and transformation_name is None:

        # get any necessary transformations using arcpy, which returns only a list of transformation names
        trns_lst = arcpy.ListTransformations(in_sr.as_arcpy, out_sr.as_arcpy)

    # otherwise we will have to use the geometry rest endpoint to find transformations
    elif transformation_name is None:

        # explicitly ensure find_transformations has a gis instance
        gis = active_gis if active_gis else GIS()

        # get any transformations, if needed due to changing geographic spatial reference, as a list of dicts
        trns_lst = find_transformation(in_sr, out_sr, gis=gis)['transformations']

    # apply across the geometries using apply since it recognizes the transformation correctly if transformation
    # is necessary and also tries arcpy first, and if not available, rolls back to rest resources elegantly
    if len(trns_lst) or transformation_name is not None:
        trns = transformation_name if transformation_name is not None else trns_lst[0]
        out_df[geom_col] = out_df[geom_col].apply(lambda geom: geom.project_as(out_sr, trns))

    # otherwise, do the same thing using the apply method since the geoaccessor project method is not working reliably
    # and only if necessary if the spatial reference is being changed
    elif in_sr.wkid != out_sr.wkid:
        out_df[geom_col] = out_df[geom_col].apply(lambda geom: geom.project_as(out_sr))

    # ensure the spatial column is set
    if not len([c for c in out_df.columns if out_df[c].dtype.name.lower() == 'geometry']):
        out_df.spatial.set_geometry(geom_col)

    return out_df
示例#11
0
# Process data
errad_summarize = erradicacion_df.groupby(['nombremunicipio'
                                           ])['hectareas'].sum()

updates = []
for row in erradicacion_lyr.query(where="nombremunicipio = '-'"):

    # get attributes
    oid = row.attributes['OBJECTID']
    x = row.geometry["x"]
    y = row.geometry["y"]

    # Create spatial filter
    point = Point({"x": x, "y": y})
    sr = SpatialReference({"wkid": 4326})
    geom_filter = filters.intersects(point, sr)

    # Query data using a point (Identify)
    mpio = mpio_layer.query(
        out_fields="coddane, nombremunicipio, nombredepartamento",
        geometry_filter=geom_filter,
        return_geometry=False)

    # Create update record
    nombre_mpio = mpio.features[0].attributes["nombremunicipio"]
    nombre_depto = mpio.features[0].attributes["nombredepartamento"]
    coddane = mpio.features[0].attributes["coddane"]
    update = {
        "attributes": {
            "objectid": oid,