Skip to content

Commit

Permalink
Merge pull request #52 from JaimieDodd/feature/inputoutput
Browse files Browse the repository at this point in the history
Manage calls to GeodePy functions to transform large amounts of data in csv format
  • Loading branch information
harry093 authored Apr 3, 2020
2 parents dcace9b + 8433704 commit e95db0f
Showing 1 changed file with 192 additions and 0 deletions.
192 changes: 192 additions & 0 deletions geodepy/inputoutput.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@

__all__ = ["grid2geoio", "geo2gridio", "gdatrans7"]

import pandas as pd
import tkinter as ttk
import geodepy.transform as tf
import geodepy.convert as cv
import geodepy.constants as cs

'''
The inputoutput module acts as the backend for the GUI and manages the calls to the GeodePy functions. The functions
are rewritten from the transform module but use pandas to improve efficiency. Functions placed here to not overcrowd
the transform module.
'''


def grid2geoio(fn, fn_out, easting, northing, utmzone, geotypeout):
"""
Input:
The CSV data must have headers.
Inputs passed the the function:
:param fn: input file path
:param fn_out: file output path
:param easting: is the column name in the csv where the eastings are stored
:param northing: is the column name in the csv where the northings are stored
:param utmzone: is the column name in the csv where the UTM Zone is stored
:param geotypeout: format of latitude and longitude output e.g. DD or DMS
Output:
Data in the file is output to the fn_out location as a CSV.
"""

# Check whether geotypeout value is from GUI or if function called within other code, then check that a valid
# geotypeout value was provided
if isinstance(geotypeout, ttk.StringVar):
geotypeout = geotypeout.get()
geotypeout_options = ["DD", "DMS"]
if geotypeout not in geotypeout_options:
raise ValueError("Invalid geotypeout. Expected one of: %s" % geotypeout_options)

# Opens the CSV as a pandas dataframe
csvdf = pd.read_csv(fn, low_memory=False)
# Sends data to tf.grid2geo
returned = csvdf.apply(lambda x: tf.grid2geo(x[utmzone], x[easting], x[northing]), axis=1)
# Convert tuple returned to DafaFrame
resultdf = pd.DataFrame(list(returned), columns=['Latitude', 'Longitude', 'Point Scale Factor', 'Grid Convergence'])
if geotypeout == 'DMS':
resultdf['Latitude'] = resultdf['Latitude'].apply(cv.dd2dms)
resultdf['Longitude'] = resultdf['Longitude'].apply(cv.dd2dms)
# Adds the results to the original dataframe from the csv
csvdf = pd.concat([csvdf, resultdf], axis=1)
# Writes the dataframe to a csv
csvdf.to_csv(fn_out, index=False)


def geo2gridio(fn, fn_out, latitude, longitude, geotypein):
"""
Input:
The CSV data must have headers.
Inputs passed the the function:
:param fn: input file path
:param fn_out: file output path
:param latitude: is the column name in the csv where the latitudes are stored
:param longitude: is the column name in the csv where the longitudes are stored
:param geotypein: format of latitude and longitude e.g. DD or DMS
Output:
Data in the file is output to the fn_out location as a CSV.
"""

# Check whether geotypein value is from GUI or if function called within other code, then check that a valid
# geotypein value was provided
if isinstance(geotypein, ttk.StringVar):
geotypein = geotypein.get()
geotypein_options = ["DD", "DMS"]
if geotypein not in geotypein_options:
raise ValueError("Invalid geotypein. Expected one of: %s" % geotypein_options)

# Opens the CSV as a pandas dataframe
csvdf = pd.read_csv(fn, low_memory=False)

# Converts DMS lat and long to Decimal Degrees if required
if geotypein == 'DMS':
csvdf['LatitudeDD'] = csvdf[latitude].apply(cv.dms2dd)
csvdf['LongitudeDD'] = csvdf[longitude].apply(cv.dms2dd)
latitude = 'LatitudeDD'
longitude = 'LongitudeDD'

# Sends data to tf.geo2grid
returned = csvdf.apply(lambda x: tf.geo2grid(x[latitude], x[longitude]), axis=1)
# Convert tuple returned from tf.gepo2grid into DafaFrame
resultdf = pd.DataFrame(list(returned), columns=['Hemisphere', 'UTMZone', 'Easting', 'Northing',
'Point Scale Factor', 'Grid Convergence'])
# Adds the results to the original dataframe from the csv
csvdf = pd.concat([csvdf, resultdf], axis=1)
# Writes the dataframe to a csv
csvdf.to_csv(fn_out, index=False)


def gdatrans7(fn, fn_out, latitude, longitude, ellht, gdageotypein, direction):

"""
Input:
The CSV data must have headers.
Inputs passed the the function:
:param fn: input file path
:param fn_out: file output path
:param latitude: is the column name in the csv where the latitudes are stored
:param longitude: is the column name in the csv where the longitudes are stored
:param ellht: is the column name in the csv where the ellipsoidal heights are stored
:param gdageotypein: format of latitude and longitude e.g. DD or DMS
:param direction: either "94to2020" or "2020to94". Specifies the datum to transform from and to.
trans: Transformation parameter from the geodepy.constants module. The trans parameters are hard coded below.
Parameters were sourced from GDA2020 Technical Manual. Need to work on a way of entering and passing different
transformation parameters to the function.
Output:
Data in the file is output to the fn_out location as a CSV.
"""

# Check whether direction value is from GUI or if function called within other code, then check that a valid
# direction value was provided
if isinstance(direction, ttk.StringVar):
direction = direction.get()
direction_options = ["94to2020", "2020to94"]
if direction not in direction_options:
raise ValueError("Invalid direction. Expected one of: %s" % direction_options)

# Check whether gdageotypein value is from GUI or if function called within other code, then check that a valid
# gdageotypein value was provided
if isinstance(gdageotypein, ttk.StringVar):
gdageotypein = gdageotypein.get()
gdageotypein_options = ["DD", "DMS"]
if gdageotypein not in gdageotypein_options:
raise ValueError("Invalid gdageotypein. Expected one of: %s" % gdageotypein_options)

# Sets up the direction of the transformation and sets up the output column naming
if direction == "94to2020":
trans = cs.Transformation('MGA94', 'MGA2020', '1994', 0.06155, -0.01087, -0.04019, -0.009994, -0.0394924,
-0.0327221, -0.0328979)
translat = "GDA2020Latitude"
translong = "GDA2020Longitude"
transellht = "GDA2020EllHt"
else:
trans = cs.Transformation('MGA94', 'MGA2020', '1994', 0.06155, -0.01087, -0.04019, -0.009994, -0.0394924,
-0.0327221, -0.0328979).__neg__()
translat = "GDA1994Latitude"
translong = "GDA1994Longitude"
transellht = "GDA1994EllHt"

# Opens the CSV as a pandas dataframe
csvdf = pd.read_csv(fn, low_memory=False)

# Converts DMS lat and long to Decimal Degrees if required
if gdageotypein == 'DMS':
csvdf['LatitudeDMS'] = csvdf[latitude]
csvdf['LongitudeDMS'] = csvdf[longitude]
csvdf['Latitude'] = csvdf[latitude].apply(cv.dms2dd)
csvdf['Longitude'] = csvdf[longitude].apply(cv.dms2dd)

# Converts Lat, Long & ElipHt XYZ
returned = csvdf.apply(lambda x: tf.llh2xyz(x[latitude], x[longitude], x[ellht]), axis=1)
# Converts the results from llh2xyz into a dataframe
xyzresultdf = pd.DataFrame(list(returned), columns=['CartesianX', 'CartesianY', 'CartesianZ'])

# Combines the results with the original dataframe
csvdf = pd.concat([csvdf, xyzresultdf], axis=1)

# Transforms Lat, Long & ElipHt XYZ using a 7 parameter transformation
transformed = csvdf.apply(lambda x: tf.conform7(x.CartesianX, x.CartesianY, x.CartesianZ, trans), axis=1)
# Converts the results from conform7 into a dataframe
transresultdf = pd.DataFrame(list(transformed), columns=['TransCartesianX', 'TransCartesianY', 'TransCartesianZ'])

# Combines the results with the original dataframe
csvdf = pd.concat([csvdf, transresultdf], axis=1)

# Converts the the transformed XYZ coordinates back to Lats, Longs and Ellipsoidal Heights
returned = csvdf.apply(lambda x: tf.xyz2llh(x.TransCartesianX, x.TransCartesianY, x.TransCartesianZ), axis=1)
# Converts the results from llh2xyz into a dataframe
llhresultdf = pd.DataFrame(list(returned), columns=[translat, translong, transellht])

# Combines the results with the original dataframe
csvdf = pd.concat([csvdf, llhresultdf], axis=1)
csvdf = csvdf.drop(['CartesianX', 'CartesianY', 'CartesianZ', 'TransCartesianX', 'TransCartesianY',
'TransCartesianZ'], axis=1)

# Writes the csv dataframe to a csv file
csvdf.to_csv(fn_out, index=False)

0 comments on commit e95db0f

Please sign in to comment.