Skip to content

Commit

Permalink
Merge pull request #95 from GeoscienceAustralia/expand_test_coverage
Browse files Browse the repository at this point in the history
Expand test coverage
  • Loading branch information
BatchelorJ authored Apr 14, 2020
2 parents 67401fd + 8502201 commit a036b9b
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 298 deletions.
165 changes: 37 additions & 128 deletions geodepy/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,28 @@ def __repr__(self):
return '{DMSAngle: ' + signsymbol + str(self.degree) + 'd ' + str(self.minute) + 'm ' + str(self.second) + 's}'

def __add__(self, other):
return dec2dms(self.dec() + other.dec())
try:
return dec2dms(self.dec() + other.dec())
except AttributeError:
raise TypeError('Can only add DMSAngle and/or DDMAngle objects together')

def __radd__(self, other):
return dec2dms(other.dec() + self.dec())
try:
return dec2dms(other.dec() + self.dec())
except AttributeError:
raise TypeError('Can only add DMSAngle and/or DDMAngle objects together')

def __sub__(self, other):
return dec2dms(self.dec() - other.dec())
try:
return dec2dms(self.dec() - other.dec())
except AttributeError:
raise TypeError('Can only subtract DMSAngle and/or DDMAngle objects together')

def __rsub__(self, other):
return dec2dms(other.dec() - self.dec())
try:
return dec2dms(other.dec() - self.dec())
except AttributeError:
raise TypeError('Can only subtract DMSAngle and/or DDMAngle objects together')

def __mul__(self, other):
try:
Expand Down Expand Up @@ -142,10 +154,28 @@ def __repr__(self):
return '{DDMAngle: ' + signsymbol + str(self.degree) + 'd ' + str(self.minute) + 'm}'

def __add__(self, other):
return dec2ddm(self.dec() + other.dec())
try:
return dec2ddm(self.dec() + other.dec())
except AttributeError:
raise TypeError('Can only add DMSAngle and/or DDMAngle objects together')

def __radd__(self, other):
try:
return dec2ddm(other.dec() + self.dec())
except AttributeError:
raise TypeError('Can only add DMSAngle and/or DDMAngle objects together')

def __sub__(self, other):
return dec2ddm(self.dec() - other.dec())
try:
return dec2ddm(self.dec() - other.dec())
except AttributeError:
raise TypeError('Can only add DMSAngle and/or DDMAngle objects together')

def __rsub__(self, other):
try:
return dec2ddm(other.dec() - self.dec())
except AttributeError:
raise TypeError('Can only add DMSAngle and/or DDMAngle objects together')

def __mul__(self, other):
try:
Expand Down Expand Up @@ -265,127 +295,6 @@ def dms2dd(dms):
return dd if dms >= 0 else -dd


def dec2sex(lon, lat):
"""Convert decimal degrees to sexagesimal format
Longitudes go from -180 to 180
Latitudes go from -90 to 90
"""
def fmt_sex(coord):
"""Function to create a sexagesimal-formatted coordinate as a string
"""
coord = float(coord)
if coord < 0:
flag = -1
coord = abs(coord)
else:
flag = 1
min_sec, deg = modf(coord)
deg = int(deg)
deg *= flag # deal with negatives
sec, min = modf(min_sec * 60)
min = round(min)
sec *= 60
sex_coord = '{} {:02d} {:05.2f}'.format(deg, min, sec)

return sex_coord

# Convert the coordinates
sex_lon = fmt_sex(lon)
sex_lat = fmt_sex(lat)

return sex_lon, sex_lat


def sex2dec(lon, lat):
"""Convert a sexagesimal coordinate to decimal degrees
Longitudes go from -180 to 180
Latitudes go from -90 to 90
"""
def fmt_dec(coord):
"""Function to piece together a decimal coordinate
"""
coord = str(coord)
if coord[:1] == '-':
flag = -1
coord = coord[1:]
else:
flag = 1
deg, min, sec = coord.split()
dec_coord = int(deg) + float(min) / 60 + float(sec) / 3600
dec_coord = float('{:.6f}'.format(dec_coord))
dec_coord *= flag # deal with negatives

return dec_coord

# Convert the coordinates
dec_lon = fmt_dec(lon)
dec_lat = fmt_dec(lat)

return dec_lon, dec_lat


def sex2hp(lon, lat):
"""Convert a sexagesimal coordinate to HP notation
Longitudes go from -180 to 180
Latitudes go from -90 to 90
"""
def fmt_hp(coord):
"""Function to piece together a coordinate in HP notation
"""
coord = str(coord)
if coord[:1] == '-':
flag = -1
coord = coord[1:]
else:
flag = 1
deg, min, sec = coord.split()
sec = sec.replace('.', '')
hp_coord = '{}.{:02d}{:04d}'.format(deg, int(min), int(sec))
if flag == -1:
hp_coord = '-' + hp_coord # deal with negatives

return hp_coord

# Convert the coordinates
hp_lon = fmt_hp(lon)
hp_lat = fmt_hp(lat)

return hp_lon, hp_lat


def hp2sex(lon, lat):
"""Convert HP notation to a sexagesimal coordinate
Longitudes go from -180 to 180
Latitudes go from -90 to 90
"""
def fmt_sex(coord):
"""Function to piece together a coordinate in HP notation
"""
coord = str(coord)
if coord[:1] == '-':
flag = -1
coord = coord[1:]
else:
flag = 1
deg, min, sec = coord.split()
sec = sec.replace('.', '')
hp_coord = '{}.{:02d}{:04d}'.format(deg, int(min), int(sec))
if flag == -1:
hp_coord = '-' + hp_coord # deal with negatives

return hp_coord

# Convert the coordinates
hp_lon = fmt_sex(lon)
hp_lat = fmt_sex(lat)

return hp_lon, hp_lat


def dd2dms_v(dd):
minutes, seconds = divmod(abs(dd) * 3600, 60)
degrees, minutes = divmod(minutes, 60)
Expand Down Expand Up @@ -451,4 +360,4 @@ def read_dnacoord(fn):
record = DNACoord(pointid.strip(), const.strip(), easting, northing, zone, lat,
long, ortho_ht, ell_ht, x, y, z, x_sd, y_sd, z_sd, desc.strip())
coord_list.append(record)
return coord_list
return coord_list
72 changes: 0 additions & 72 deletions geodepy/geodesy.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,75 +282,3 @@ def vincinv_utm(zone1, east1, north1, zone2, east2, north2, hemisphere1='south',
pt2 = grid2geo(zone2, east2, north2, hemisphere2, ellipsoid)
# Use vincinv
return vincinv(pt1[0], pt1[1], pt2[0], pt2[1], ellipsoid)


def vincdirio():
"""
No Input:
Prompts the user for the name of a file in csv format. Data in the file
must be in the form Latitude, Longitude of Point 1 in Degrees Minutes
Seconds, Geodetic Azimuth from Point 1 to 2 in Degrees Minutes Seconds and
Distance in metres with no header line.
No Output:
Uses the function vincdir to calculate for each row in the csv file the
geographic coordinate (lat, long) of Point 2 and the Azimuth from Point 2
to Point 1, all in Degrees Minutes Seconds. This data is written to a new
file with the name <inputfile>_out.csv
"""
# Enter Filename
fn = input('Enter co-ordinate file:\n')
# Open Filename
csvfile = open(fn)
csvreader = csv.reader(csvfile)
# Create Output File
fn_part = (os.path.splitext(fn))
fn_out = fn_part[0] + '_out' + fn_part[1]
outfile = open(fn_out, 'w')
# Write Output
outfilewriter = csv.writer(outfile)
# outfilewriter.writerow(['Latitude2', 'Longitude2', 'azimuth2to1'])
for row in csvreader:
lat1 = hp2dec(float(row[0]))
long1 = hp2dec(float(row[1]))
azimuth1to2 = hp2dec(float(row[2]))
ell_dist = float(row[3])
lat2, long2, azimuth2to1 = vincdir(lat1, long1, azimuth1to2, ell_dist)
lat2 = dec2hp(lat2)
long2 = dec2hp(long2)
azimuth2to1 = dec2hp(azimuth2to1)
output = [lat2, long2, azimuth2to1]
outfilewriter.writerow(output)
# Close Files
outfile.close()
csvfile.close()


def vincinvio():
# Enter Filename
print('Enter co-ordinate file:')
fn = input()
# Open Filename
csvfile = open(fn)
csvreader = csv.reader(csvfile)
# Create Output File
fn_part = (os.path.splitext(fn))
fn_out = fn_part[0] + '_out' + fn_part[1]
outfile = open(fn_out, 'w')
# Write Output
outfilewriter = csv.writer(outfile)
outfilewriter.writerow(['Ell_Dist', 'Azimuth1to2', 'Azimuth2to1'])
for row in csvreader:
lat1 = hp2dec(float(row[0]))
long1 = hp2dec(float(row[1]))
lat2 = hp2dec(float(row[2]))
long2 = hp2dec(float(row[3]))
ell_dist, azimuth1to2, azimuth2to1 = vincinv(lat1, long1, lat2, long2)
azimuth1to2 = dec2hp(azimuth1to2)
azimuth2to1 = dec2hp(azimuth2to1)
output = (ell_dist, azimuth1to2, azimuth2to1)
outfilewriter.writerow(output)
# Close Files
outfile.close()
csvfile.close()

41 changes: 40 additions & 1 deletion geodepy/tests/test_convert.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import unittest
from geodepy.convert import dec2hp, hp2dec, DMSAngle, DDMAngle, dec2dms, dec2ddm, hp2dms, hp2ddm, dd2dms
from geodepy.convert import dec2hp, hp2dec, DMSAngle, DDMAngle, dec2dms, dec2ddm, hp2dms,\
hp2ddm, dd2dms, dms2dd

dec_ex = 123.74875
dec_ex2 = 12.575
Expand Down Expand Up @@ -42,6 +43,8 @@ def test_DMSAngle(self):
self.assertEqual(hp_ex, dms_ex.hp())
self.assertEqual(hp_ex3, dms_ex3.hp())
self.assertEqual(ddm_ex, dms_ex.ddm())
self.assertEqual(-ddm_ex, -dms_ex.ddm())
self.assertEqual(ddm_ex3, dms_ex3.ddm())

# Test DMSAngle Sign Conventions
self.assertEqual(-dec_ex, DMSAngle(-dms_ex.degree, dms_ex.minute, dms_ex.second).dec())
Expand All @@ -50,6 +53,7 @@ def test_DMSAngle(self):
self.assertAlmostEqual(dec_ex4, DMSAngle(0, dms_ex4.minute, dms_ex4.second).dec(), 9)
self.assertEqual(-dec_ex5, DMSAngle(0, 0, -dms_ex5.second).dec())
self.assertEqual(dec_ex5, DMSAngle(0, 0, dms_ex5.second).dec())
self.assertEqual(-dms_ex3, DMSAngle(12, 34, -30))
self.assertEqual(dms_ex.sign, 1)
self.assertEqual(-dms_ex.sign, -1)
self.assertEqual(dms_ex4.sign, 1)
Expand All @@ -63,10 +67,14 @@ def test_DMSAngle(self):
self.assertEqual(DMSAngle(0, 0, -3).sign, -1)
self.assertEqual(DMSAngle(-0, 1, 2).sign, 1)
self.assertEqual(DMSAngle(-0.0, 1, 2).sign, -1)
self.assertEqual(repr(dms_ex), '{DMSAngle: +123d 44m 55.5s}')
self.assertEqual(repr(dms_ex3), '{DMSAngle: -12d 34m 30s}')

# Test DMSAngle Overloads
self.assertEqual(dec_ex + dec_ex2, (dms_ex + dms_ex2).dec())
self.assertEqual(dec_ex2 + dec_ex, (dms_ex2 + dms_ex).dec())
self.assertEqual(dec_ex - dec_ex2, (dms_ex - dms_ex2).dec())
self.assertEqual(dec_ex2 - dec_ex, (dms_ex2 - dms_ex).dec())
self.assertEqual(dec_ex * 5, (dms_ex * 5).dec())
self.assertEqual(5 * dec_ex, (5 * dms_ex).dec())
self.assertEqual(dec_ex / 3, (dms_ex / 3).dec())
Expand All @@ -88,6 +96,20 @@ def test_DMSAngle(self):
'a' * dms_ex
with self.assertRaises(TypeError):
dms_ex / 'a'
with self.assertRaises(TypeError):
dms_ex + 'a'
with self.assertRaises(TypeError):
'a' + dms_ex
with self.assertRaises(TypeError):
dms_ex - 'a'
with self.assertRaises(TypeError):
'a' - dms_ex

# Test Class Interoperability
self.assertEqual(DMSAngle(1, 2, 3) + DDMAngle(2, 3), DMSAngle(3, 5, 3))
self.assertEqual(DMSAngle(3, 2, 0) - DDMAngle(2, 2.5), DMSAngle(0, 59, 30))
self.assertEqual(DDMAngle(2, 3) + DMSAngle(1, 2, 3), DDMAngle(3, 5.05))
self.assertEqual(DDMAngle(3, 2) - DMSAngle(2, 2, 30), DDMAngle(0, 59.5))

def test_DDMAngle(self):
# Test DDMAngle Methods
Expand All @@ -101,6 +123,7 @@ def test_DDMAngle(self):
self.assertEqual(dec_ex, DDMAngle(dms_ex.degree, -ddm_ex.minute).dec())
self.assertAlmostEqual(-dec_ex4, DDMAngle(0, -ddm_ex4.minute).dec(), 9)
self.assertAlmostEqual(dec_ex4, DDMAngle(0, ddm_ex4.minute).dec(), 9)
self.assertEqual(-ddm_ex3, DDMAngle(12, 34.5))
self.assertEqual(ddm_ex.sign, 1)
self.assertEqual(-ddm_ex.sign, -1)
self.assertEqual(ddm_ex4.sign, 1)
Expand All @@ -113,10 +136,14 @@ def test_DDMAngle(self):
self.assertEqual(DDMAngle(0, -1).sign, -1)
self.assertEqual(DDMAngle(-0, 1).sign, 1)
self.assertEqual(DDMAngle(-0.0, 1).sign, -1)
self.assertEqual(repr(ddm_ex), '{DDMAngle: +123d 44.925m}')
self.assertEqual(repr(ddm_ex3), '{DDMAngle: -12d 34.5m}')

# Test DDMAngle Overloads
self.assertEqual(dec_ex + dec_ex2, (ddm_ex + ddm_ex2).dec())
self.assertEqual(dec_ex2 + dec_ex, (ddm_ex2 + ddm_ex).dec())
self.assertEqual(dec_ex - dec_ex2, (ddm_ex - ddm_ex2).dec())
self.assertEqual(dec_ex2 - dec_ex, (ddm_ex2 - ddm_ex).dec())
self.assertEqual(dec_ex * 5, (ddm_ex * 5).dec())
self.assertEqual(5 * dec_ex, (5 * ddm_ex).dec())
self.assertEqual(dec_ex / 3, (ddm_ex / 3).dec())
Expand All @@ -138,6 +165,14 @@ def test_DDMAngle(self):
'a' * ddm_ex
with self.assertRaises(TypeError):
ddm_ex / 'a'
with self.assertRaises(TypeError):
ddm_ex + 'a'
with self.assertRaises(TypeError):
'a' + ddm_ex
with self.assertRaises(TypeError):
ddm_ex - 'a'
with self.assertRaises(TypeError):
'a' - ddm_ex

def test_dec2dms(self):
self.assertEqual(dms_ex, dec2dms(dec_ex))
Expand Down Expand Up @@ -165,6 +200,10 @@ def test_dd2dms(self):
self.assertEqual(hp_ex, dd2dms(dec_ex))
self.assertEqual(-hp_ex, dd2dms(-dec_ex))

def test_dms2dd(self):
self.assertAlmostEqual(dec_ex, dms2dd(hp_ex), 9)
self.assertAlmostEqual(-dec_ex, dms2dd(-hp_ex), 9)


if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit a036b9b

Please sign in to comment.