invest/scripts/wave_energy_scripts/wave_csv_to_points.py

156 lines
5.4 KiB
Python

"""Python module that creates a point shapefile from a CSV
Example from command line:
>> python wave_csv_to_points.py wave_formatted_csv_data.txt my_layer shape_out.shp
Example two:
>> python wave_csv_to_points.py wave_formatted_csv_data.csv WCVI WCVI_points.shp
"""
import csv
import os
import sys
import shutil
from osgeo import ogr
from osgeo import osr
def create_wave_point_ds(wave_data_csv_uri, layer_name, output_uri):
"""Creates a point shapefile from a wave energy data csv file that is
properly formatted. The point shapefile created is not projected
and uses latitude and longitude for its geometry.
wave_data_csv_uri - a URI to a comma separated file of wave point data
that has been properly formatted (required) Example format:
ID,I,J,LONG,LATI,HSAVG,TPAVG
1,102,370,24.3,54.3,10.2,11.1
2,102,370,24.3,54.3,10.2,11.1
layer_name - a string for the name of the point shapefile
layer (required)
output_uri - a URI for the output path of the point shapefile (required)
return - Nothing"""
# Initiate a dictionary to build up data from the csv file
dict_data = {}
# Open the csv file
point_file = open(wave_data_csv_uri)
# Get a handle on the csv file by using dictReader which handles each line
# as a dictionary where the column headers are the keys
reader = csv.DictReader(point_file)
# A list of column headers that we want to remain integers all other column
# headers will become floats
int_list = ['ID', 'I', 'J']
# Iterate over the file by line
for row in reader:
# For each line's dictionary, iterate over the key-value pairs
for k,v in row.items():
# If the key represents a value that should be an integer, cast to
# an int, else cast to a float
if k in int_list:
row[k] = int(v)
else:
row[k] = float(v)
# Build up the new dictionary
dict_data[row['ID']] = row
# If the output_uri exists delete it
if os.path.isfile(output_uri):
os.remove(output_uri)
elif os.path.isdir(output_uri):
shutil.rmtree(output_uri)
# Create the ogr driver for the new point shapefile
output_driver = ogr.GetDriverByName('ESRI Shapefile')
# Create the datasource for the new point shapefile
output_datasource = output_driver.CreateDataSource(output_uri)
# Set the spatial reference to WGS84 (lat/long)
source_sr = osr.SpatialReference()
source_sr.SetWellKnownGeogCS("WGS84")
# Create the new point shapefile layer
output_layer = output_datasource.CreateLayer(
layer_name, source_sr, ogr.wkbPoint)
# Get the keys of the dictionary which are the 'ID' values
outer_keys = dict_data.keys()
# Using the list of keys from above, get the first keys sub dictionary and
# get it's keys. These 'inner' keys are the column headers from the file
# and will be added to the point shapefile as fields
field_list = dict_data[outer_keys[0]].keys()
# Create a dictionary to store what variable types the fields are
type_dict = {}
for field in field_list:
# Get a value from the field
val = dict_data[outer_keys[0]][field]
# Check to see if the value is a String of characters or a number. This
# will determine the type of field created in the shapefile
if isinstance(val, str):
type_dict[field] = 'str'
else:
type_dict[field] = 'number'
for field in field_list:
field_type = None
# Distinguish if the field type is of type String or other. If Other, we
# are assuming it to be a float
if type_dict[field] == 'str':
field_type = ogr.OFTString
else:
field_type = ogr.OFTReal
# Create a new field in the point shapefile
output_field = ogr.FieldDefn(field, field_type)
output_layer.CreateField(output_field)
# For each inner dictionary (for each point) create a point and set its
# fields
for point_dict in dict_data.values():
# Get latitude / longitude values
latitude = float(point_dict['LATI'])
longitude = float(point_dict['LONG'])
# Make a new point geometry set the long / lat
geom = ogr.Geometry(ogr.wkbPoint)
geom.AddPoint_2D(longitude, latitude)
# Create a new point feature
output_feature = ogr.Feature(output_layer.GetLayerDefn())
for field_name in point_dict:
field_index = output_feature.GetFieldIndex(field_name)
# Set the value for each field for this particular point
output_feature.SetField(field_index, point_dict[field_name])
# Set geometry and create / set the feature
output_feature.SetGeometryDirectly(geom)
output_layer.CreateFeature(output_feature)
output_feature = None
output_layer.SyncToDisk()
if __name__ == '__main__':
# Argument 1 from the command line, the wave energy csv data
wave_data_csv_uri = sys.argv[1]
# Argument 2 from the command line, a string for the layer name
layer_name = sys.argv[2]
# Argument 3 from the command line, the output URI for the point shapefile
out_uri = sys.argv[3]
# Call the function to create our point shapefile from CSV
create_wave_point_ds(wave_data_csv_uri, layer_name, out_uri)