Masthead

SpPy - Spatial Python Package

Since it takes quite a bit of work to use the open source geospatial libraries, we have started investigating creating a Python library that wraps the open source libraries into a more easy to use package.

Goals

The goals of this effort are to see if we can create a package that:

Project Plan

The key to this effort is to see if we can create a design for the package that meets the goals. This effort is underway and a prototype of the code is available for you to evaluate. Your feedback on the design of the approach is critical at this stage. If successful, we'll look at flushing out the package with additional code and setting up formal testing and documentation.

Getting Started

To get started, download the SpPy (spatial pie) package here and place it in a folder that is accessible to your Python scripts. Then, add a path to the SpPy folder to your Python scripts. The following lines of code will then import the key SpPy libraries and import the shapely geometry types:

# Open source spatial libraries
from shapely.geometry import Point, LineString, Polygon,MultiPolygon

# SP Libraries
import SPPlot
import SPVectors
import SPView
import SPRasters
import SPReferencing

The libraries have the following purposes:

Working With Vector Data sets

To get information from a specific data set, you'll want to create an SPDatasetVector object and then load a file into it. This allows you to get information on the data set, modify it's contents, and save it back out again. Below is an example.

TheDataset=SPVectors.SPDatasetVector() #create a new layer

TheDataset.Load(CountriesFilePath) # load the contents of the layer

print("Type: "+format(TheDataset.GetType())) # get the type of data in the dataset

print("CRS: "+format(TheDataset.GetCRS())) # return the corodinate reference system

print("NumFeatures: "+format(TheDataset.GetNumFeatures())) # get the number of features in the dataset

print("Bounds: "+format(TheDataset.GetBounds())) # get the spatial bounds of the features

NumAttributes=TheDataset.GetNumAttributes()

print("NumAttributes: "+format(NumAttributes)) # return the definitions for the attributes (this function will change in the future)

Index=0
while (Index < NumAttributes):
	print("Attribute: "+format(TheDataset.GetAttributeName(Index))+", Type: "+format(TheDataset.GetAttributeType(Index))+", Width: "+format(TheDataset.GetAttributeWidth(Index))) 
	Index+=1

# Save the result
TheDataset.Save(OutputFolderPath+"CountryClone.shp") 

One-Line Operations On Vector Data

The following operations will take one or more data sets as the input and then typically return a transformed data set. The data set can be a path to a file, an existing data set object in memory, or a shapely geometry object. The advantage of these functions over other approaches is that you can have a single line perform an entire task. Then, you can use the result in the next function. This allows a series of geospatial transformations to be put into a single file in a very concise and yet readable way.

You can also perform "single-layer operations" on one layer at a time in just a few lines of code as below. For these functions, the "InputFile" can be a file path to a vector data set (typically a shapefile), an SPDatasetVector object, or a shapely geometry object. The example below shows that the operations can be "daisy-chained" without having to save files unless needed.

BufferedDataset=SPVectors.Buffer(InputDataset,10)

CentroidDataset=SPVectors.Centroid(BufferedDataset)

ConvexHullDataset=SPVectors.ConvexHull(CentroidDataset)

SimplifiedDataset=SPVectors.Simplify(ConvexHullDataset,10)

SimplifiedDataset.Save(OutputFolderPath+"Simplify.shp")

Overlay Operations

Finally, there are overlay operations that can be executed in just a couple lines of code.

# Create the bounding polygon
Top=45 
Bottom=20
Left=-125
Right=-40

BoundingPoly=shapely.geometry.Polygon([(Left,Top), (Right,Top), (Right,Bottom), (Left,Bottom),(Left,Top)])

# Crop a shapefile with a polygon 
NewLayer=SPVectors.Intersection(InputFile,BoundingPoly) # perform an intersection on a geometry to get the new layer
NewLayer.Save(OutputFolderPath+"Intersection.shp")

# Union the shapefile with the polygon
NewLayer=SPVectors.Union(InputFile,BoundingPoly) # perform a union on a geometry to get the new layer
NewLayer.Save(OutputFolderPath+"Union.shp") # save the output

# Find the difference between the shapefile and the polygon
NewLayer=SPVectors.Difference(InputFile,BoundingPoly) # 
NewLayer.Save(OutputFolderPath+"Difference.shp") # save the output

Adding and Removing Features

You can easily add and remove features using the commands below. When a feature is added, the attributes for the feature are set to 0 or blank values.

# add a square geometry in at 0,0
TheGeometry=shapely.geometry.Polygon([(-10,10), (10,10), (10,-10), (-10,-10),(-10,10)])
TheDataset.AddFeature(TheGeometry)


# delete the first feature in the dataset

TheDataset.DeleteFeature(0) # remove a feature based on its row index from 0

Working with Attributes

The following functions work with loaded vector datasets and modify the attributes associated with each feature.

TheDataset.GetAttributeValue("LABELRANK",0) # get the value of the atteribute "LABELRANK" for the feature in row 0

TheDataset.SetAttributeValue("sum",0,"test2") # set the attribute "sum" for the feature in row 0

TheDataset.DeleteAttribute("ADM0_DIF") # Remove an attribute

TheDataset.AddAttribute("testy","str",254,"hi") # add a new attribute with the name, type, width, and default value

Selections

You can create selections of features in a dataset using boolean comparison function calls. The functions take the name of an attribute column and a value to compare each of the attribute values to. These functionswill return an array that contains True where the comparison is True for a feature's specified attribute and False otherwise. You can then use this array to subset the dataset to just the features that had True returned. Note that you can also perform operations on the selection arrays such as AND and OR to create more complex selection critieria.

Selection=TheDataset.SelectGreater("LABELRANK",2) # select the features with label rank greater than 2


Selection=TheDataset.SelectGreaterThanOrEqual("LABELRANK",2) # select the features with label rank greater than or equal to 2

Selection=TheDataset.SelectLess("LABELRANK",2) # select the features with label rank less than or equal to 2.

Selection=TheDataset.SelectLessThanOrEqual("LABELRANK",2) # select the features with label rank less than 2.

Selection=TheDataset.SelectEqual("ADMIN","United States of America") # find the features that have the matching name
TheDataset.SubsetBySelection(Selection) # sub set the dataset to just contain features for the United States of America

Working with Raster Data

The code below will load a raster into memory and then return basic data for the raster.

 TheDataset =SPDatasetRaster()
 TheDataset.Load(TestRasterFilePath)
  
 print("Width in pixels: "+format(TheDataset.GetWidthInPixels()))
 
 print("Height in pixels: "+format(TheDataset.GetHeightInPixels()))
 
 print("Num Bands: "+format(TheDataset.GetNumBands()))
 
 print("Projection: "+format(TheDataset.GetProjection()))
 
 print("Resolution (x,y): "+format(TheDataset.GetResolution()))
 
 TheBounds=TheDataset.GetBounds()
 print("TheBounds (XMin,YMin,YMax,XMax): "+format(TheBounds))
 
 #TheBand=TheDataset.GetBandAsArray(1)
 #print("TheBands: "+format(TheBand))
 
 TheDataset.Save(TempFolderPath+"CopiedRaster.tif") 

Creating a new raster

 WidthInPixels=100
 HeightInPixels=100
 
 TheDataset=SPDatasetRaster()
 TheDataset.SetWidthInPixels(WidthInPixels)
 TheDataset.SetHeightInPixels(HeightInPixels)
 TheDataset.SetType(gdal.GDT_Float32)
 
 TheBands=TheDataset.AllocateArray()
 TheBands=TheBands[0]
 
 Row=0
 while (Row<HeightInPixels):
 Column=0
 while (Column<WidthInPixels):
 	TheBands[Row][Column]=Column
 	Column+=1
 	Row+=1
 print(TheBands)
 
 TheDataset.SetUTM(10)
 TheDataset.SetNorthWestCorner(400000,4000000)
 TheDataset.SetResolution(30,30)
 TheDataset.Save(TempFolderPath+"NewRaster.tif")
 

Transforming Rasters

Result=SPRaster.LessThan(TestRasterFilePath,TestRasterFilePath2) 

Projecting

To change the CRS for a dataset, we use the Proj4 parameters.

ProjectionCode="aea"
Parameters={
 "lon_0":0,
 "lat_1":60,
 "lat_2":40
 }
 
NewLayer=SPReferencing.Project(InputDataset,ProjectionCode,Parameters)
NewLayer.Save(OutputFolderPath+"Projected.shp")

Rendering

The SPView class allows dataset to be rendred into a view which can then be saved to a raster file or displayed in a window. Since the rendering requires symobology, the dataset is placed inside a layer object first and then sent to the view.

TheBounds=TheDataset.GetBounds()
MinX=TheBounds[0]
MinY=TheBounds[1]
MaxX=TheBounds[2]
MaxY=TheBounds[3]
TheView=SPView.SPView(500,500)
TheView.SetBounds(MinX,MaxX,MinY,MaxY) # jjg - should be able to set the bounds directly


TheLayer=SPVectors.SPLayerVector()
TheLayer.SetDataset(TheDataset)
TheLayer.Render(TheView)
TheView.Save(OutputFolderPath+"RenderedVectors.png")

API Reference

Below is an initial reference for the available functions.

SPVectors.SPDatasetVector

The functions below are available for an SPDatasetVector object.

Name Description
Data Management  
Load(FilePath) Load data from the specified file path
Save(FilePath) Save the data set to the specified path
Type=GetType() Returns the type of vector data from the OGC standards (e.g. "Polygon", "Point", "MultiPolygon", etc).
SetType(NewType) Sets the type of vector data from the OGC standards (e.g. "Polygon", "Point", "MultiPolygon", etc). Should only be called before data has been added to the data set.
CRS=GetCRS() Returns the coordinate reference system information (see https://fiona.readthedocs.io/en/latest/manual.html)
SetCRS(CRS)  
   
Attribute management  
Value=GetAttributeValue(AttributeName,Row) Return the value of the attribute with the specific name and row index.
SetAttributeValue(AttributeName,Row,NewValue) Set the value of the attribute with the specified name and row index to the NewValue.
Num=GetNumAttributes() Returns the number of attribute columns defined for the data set.
Name=GetAttributeName(ColumnIndex) Returns the attribute name for the specified attribute column
Type=GetAttributeType(ColumnIndex) Returns the attribute type ("str","int""float") for the specified attribute column
Width=GetAttributeWidth(ColumnIndex) Returns the width of the attribute (really its precision)
AddAttribute(Name,Type,Width=None,Default=None) Add a new attribute column with the specified parameters
DeleteAttribute(Name) Delete the attribute row of the specified name
RowIndex=GetAttributeColumn(Name) Return an index to the attribute column that has the specified name
Selection=SelectEqual(AttributeName,Value) Return a selection list with True where the attribute values are equal to the specified value and False otherwise
Selection=SelectGreater(AttributeName,Value) Return a selection list with True where the attribute values are greater than to the specified value and False otherwise
Selection=SelectGreaterThanOrEqual(AttributeName,Value) Return a selection list with True where the attribute values are greater than or equal to the specified value and False otherwise
Selection=SelectLess(AttributeName,Value) Return a selection list with True where the attribute values are less than to the specified value and False otherwise
Selection=SelectLessThanOrEqual(AttributeName,Value) Return a selection list with True where the attribute values are less than or equal to the specified value and False otherwise
SubsetBySelection(Selection) Remove any features from the data set that have False in the selection array.
   
Feature/Geometry Management These functions are provided to make it easy to obtain information from the features geometries
NumFeatures=GetNumFeatures() Return the number of features/rows in the dataset
DeleteFeature(Row) Remove the specified feature, including its attributes, from the data set.
AddFeature(TheGeometry,TheAttributes=None): Add a new geometry to the data set. An optional list of attribute values can also be specified.
TheGeometry=GetGeometry(FeatureIndex) Return the shapely geometry object associated with the feature, if any
SplitFeatures() Breaks up features that are collections or contain muiltple geometries (i.e. "multi") into individual features.
Bounds=GetBounds() Return the spatial bounds of all the features.
   
Area=GetFeatureArea(FeatureIndex) Returns the area of the feature
Bounds=GetFeatureBounds(FeatureIndex) Returns the spatial bounds of the feature
Length=GetFeatureLength(FeatureIndex) Returns the length of all the line segments in the feature
EmptyFlag=IsFeatureEmpty(FeatureIndex) Returns True if the feature does not contain any coordinates
ValidFlag=IsFeatureValid(FeatureIndex) Returns True if the feature contains a valid geometry (e.g. no overlapping segments)

SPVector

The following functions are available in the SPVector library. These functions take one or more inputs that can be paths to files, data sets loaded into memory, or shapely geometries.

Single-Dataset Operations  
OutputDataset=Buffer(InputDataset,Amount)  
OutputDataset=Simplify(InputDataset,Tolerance, PreserveTopology=True)  
OutputDataset=ConvexHull(InputDataset)  
OutputDataset=Centroid(InputDataset)  
   
Overlay Operations  
OutputDataset=Intersection(InputDataset1,InputDataset2)  
OutputDataset=Union(InputDataset1,InputDataset2)  
OutputDataset=Difference(InputDataset1,InputDataset2)  
OutputDataset=SymmetricDifference(InputDataset1,InputDataset2)  

SPRasterDataset

Provides functions to work with raster data sets. The operations that work on rasters can take a path to a file, an existing raster object, or a scalar value for operators.

Name Description
RasterDataset operations  
RasterDataset.Load(FilePath) Loads the data from a file into the dataset
RasterDataset.Save(FilePath) Saves the data from the dataset into a file
WidthInPixels=RasterDataset.GetWidthInPixels() Retursn the number of columns of pixels in the data
RasterDataset.SetWidthInPixels(NewWidth) Sets the overall width of the raster in pixels. Only should be called if the raster data has not been allocated yet.
HeightInPixels=RasterDataset.GetHeightInPixels() Returns the overall width of the raster in pixels. Only should be called if the raster data has not been allocated yet.
RasterDataset.SetHeightInPixels(NewHeight) Sets the number of rows of pixels in the data
NumBands=RasterDataset.GetNumBands() Returns the number of bands of data in the raster (i.e. gray=1, RGB=3).
CRS=RasterDataset.GetProjection() Note: Needs to change to GetCRS()
X,Y=RasterDataset.GetResolution() Returns the resolution (spatial reference units per pixels) as a tuple
RasterDataset.SetResolution((X,Y))  
Bounds=RasterDataset.GetBounds()  
RasterDataset.SetNorthWestCorner(X,Y)  
Band=RasterDataset.GetBand(BandIndex) Returns an array with the band data for the specified index (0 for first, 1 for second, etc.)
Bands=RasterDataset.GetBands() Return an array of arrays with the data for all the bands.
RasterDataset.SetBands(Bands) Sets an array of arrays with the data for all the bands. This function should be used carefully as the dimensions and type of the band data must match the settings in the object.
Min,Max=RasterDataset.GetMinMax(BandIndex) REturns the minimum and maximum values for the data in the specific bands.
GDALType=RasterDataset.GetType()

Returns the type of sample values based on GDAL definitions: gdal.GDT_Byte, gdal.GDT_UInt16,gdal.GDT_Int16,gdal.GDT_UInt32,gdal.GDT_Int32,gdal.GDT_Float32,dal.GDT_Float64,gdal.GDT_CFloat64

Note: Do we support all these types?

RasterDataset.SetType(New)

Sets the type of sample values based on GDAL definitions (see above)

RasterDataset.AllocateArray() Allocates the pixel data for the current data set
   

 

SPRaster Public Functions

The following functions are available in the SPRaster library as single-line operations. The inputs can be paths to files or data sets loaded into memory.

Math Operations  
OutputRaster=Add(Input1,Input2) Adds the pixels in the two rasters together.
OutputRaster=Subtract(Input1,Input2)  
OutputRaster=Multiply(Input1,Input2)  
OutputRaster=Divide(Input1,Input2)  
   
Comparisons  
OutputRaster=Equal(Input1,Input2) Creates a new raster with True (1) for pixels that are equal in both rasters and 0 otherwise.
OutputRaster=LessThan(Input1,Input2)  
OutputRaster=GreaterThan(Input1,Input2)  
OutputRaster=LessThanOrEqual(Input1,Input2)  
OutputRaster=GreaterThanOrEqual(Input1,Input2)  
   
OutputRaster=Minimum(Input1,Input2) Returns a new raster where each pixel is the minimum value of the two overlapping pixels in the inputs.
OutputRaster=Maximum(Input1,Input2)  
   
Boolean Operations  
OutputRaster=And(Input1,Input2) Returns a new raster where each pixel is the logical result of anding the overlapping pixels in the inputs.
OutputRaster=Or(Input1,Input2)  
OutputRaster=Not(Input1)  
   
Conversions  
OutputRaster=RoundInteger(Input1) Returns a new raster where the pixels have been rounded to the nearest integer.
OutputRaster=RoundFix(Input1) Round to nearest integer towards zero.
OutputRaster=RoundFloor(Input1) Returns a new raster where the pixels have been truncated to the lowest value (i.e. 0.5 -> 0, 0.6 -> 0)
OutputRaster=RoundCeiling(Input1) Returns a new raster where the pixels have been truncated to the highest nvalue (i.e. 0.5 -> 1, 0.6 -> 1)
OutputRaster=RoundTruncate(Input1) Returns a new raster where the pixels have been truncated (i.e. 0.5 -> 0, 0.6 -> 0)
   
Exponential functions  
OutputRaster=NaturalLog(Input1)  
OutputRaster=Log(Input1)  
OutputRaster=Exponent(Input1) Returns a new raster with pixels that are the result of raising the value e to the value in the input raster.
OutputRaster=Power(Input1,Power) Returns a new raster with pixels that are the result of raising the values in the input by the specified Power (i.e. New=Old ^Power).
OutputRaster=Square(Input1)  
OutputRaster=SquareRoot(Input1)  
OutputRaster=AbsoluteValue(Input1)  
   
Conversions  
OutputVector=Polygonize(Input1) Need to finish this jjg
   
   

 

Resampling - under development

This class provides resampling for raster data

Name Description
NewDataset=Zoom(Input1,ZoomFactor)  
ExtractByPixels(InputRasterDataset,StartColumn,StartRow,EndColumn,EndRow)  

SPReferencing

Provides functions to project datasets.

Name Description
NewDataset=SPReferencing.Project(InputDataset,ProjectionCode,Parameters,LatNewPole=90) Projecs the dataset to the desired spatial reference

Notes

Missing: Question, what is the core and what can be added with additional classes

© Copyright 2018 HSU - All rights reserved.