-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from JaimieDodd/feature/inputoutput
Manage calls to GeodePy functions to transform large amounts of data in csv format
- Loading branch information
Showing
1 changed file
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |