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
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)
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
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
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
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
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
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
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
# 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,